tree-wide: fix assorted typos all over the place
[safe/jmp/linux-2.6] / drivers / gpu / drm / i915 / i915_gem.c
index d49ac1c..a2a3fa5 100644 (file)
@@ -1200,26 +1200,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        mutex_lock(&dev->struct_mutex);
        if (!obj_priv->gtt_space) {
                ret = i915_gem_object_bind_to_gtt(obj, 0);
-               if (ret) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return VM_FAULT_SIGBUS;
-               }
+               if (ret)
+                       goto unlock;
+
                list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
 
                ret = i915_gem_object_set_to_gtt_domain(obj, write);
-               if (ret) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return VM_FAULT_SIGBUS;
-               }
+               if (ret)
+                       goto unlock;
        }
 
        /* Need a new fence register? */
        if (obj_priv->tiling_mode != I915_TILING_NONE) {
                ret = i915_gem_object_get_fence_reg(obj);
-               if (ret) {
-                       mutex_unlock(&dev->struct_mutex);
-                       return VM_FAULT_SIGBUS;
-               }
+               if (ret)
+                       goto unlock;
        }
 
        pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
@@ -1227,18 +1222,18 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        /* Finally, remap it using the new GTT offset */
        ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
+unlock:
        mutex_unlock(&dev->struct_mutex);
 
        switch (ret) {
+       case 0:
+       case -ERESTARTSYS:
+               return VM_FAULT_NOPAGE;
        case -ENOMEM:
        case -EAGAIN:
                return VM_FAULT_OOM;
-       case -EFAULT:
-       case -EINVAL:
-               return VM_FAULT_SIGBUS;
        default:
-               return VM_FAULT_NOPAGE;
+               return VM_FAULT_SIGBUS;
        }
 }
 
@@ -1314,7 +1309,7 @@ out_free_list:
  * i915_gem_release_mmap - remove physical page mappings
  * @obj: obj in question
  *
- * Preserve the reservation of the mmaping with the DRM core code, but
+ * Preserve the reservation of the mmapping with the DRM core code, but
  * relinquish ownership of the pages back to the system.
  *
  * It is vital that we remove the page mapping if we have mapped a tiled
@@ -1431,6 +1426,14 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
 
        obj_priv = obj->driver_private;
 
+       if (obj_priv->madv != I915_MADV_WILLNEED) {
+               DRM_ERROR("Attempting to mmap a purgeable buffer\n");
+               drm_gem_object_unreference(obj);
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+
        if (!obj_priv->mmap_offset) {
                ret = i915_gem_create_mmap_offset(obj);
                if (ret) {
@@ -1470,6 +1473,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
        int i;
 
        BUG_ON(obj_priv->pages_refcount == 0);
+       BUG_ON(obj_priv->madv == __I915_MADV_PURGED);
 
        if (--obj_priv->pages_refcount != 0)
                return;
@@ -1478,7 +1482,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
                i915_gem_object_save_bit_17_swizzle(obj);
 
        if (obj_priv->madv == I915_MADV_DONTNEED)
-           obj_priv->dirty = 0;
+               obj_priv->dirty = 0;
 
        for (i = 0; i < page_count; i++) {
                if (obj_priv->pages[i] == NULL)
@@ -1488,7 +1492,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
                        set_page_dirty(obj_priv->pages[i]);
 
                if (obj_priv->madv == I915_MADV_WILLNEED)
-                   mark_page_accessed(obj_priv->pages[i]);
+                       mark_page_accessed(obj_priv->pages[i]);
 
                page_cache_release(obj_priv->pages[i]);
        }
@@ -1530,6 +1534,26 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
        obj_priv->last_rendering_seqno = 0;
 }
 
+/* Immediately discard the backing storage */
+static void
+i915_gem_object_truncate(struct drm_gem_object *obj)
+{
+       struct drm_i915_gem_object *obj_priv = obj->driver_private;
+       struct inode *inode;
+
+       inode = obj->filp->f_path.dentry->d_inode;
+       if (inode->i_op->truncate)
+               inode->i_op->truncate (inode);
+
+       obj_priv->madv = __I915_MADV_PURGED;
+}
+
+static inline int
+i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv)
+{
+       return obj_priv->madv == I915_MADV_DONTNEED;
+}
+
 static void
 i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
 {
@@ -1746,7 +1770,7 @@ i915_gem_retire_requests(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        uint32_t seqno;
 
-       if (!dev_priv->hw_status_page)
+       if (!dev_priv->hw_status_page || list_empty(&dev_priv->mm.request_list))
                return;
 
        seqno = i915_get_gem_seqno(dev);
@@ -1770,6 +1794,12 @@ i915_gem_retire_requests(struct drm_device *dev)
                } else
                        break;
        }
+
+       if (unlikely (dev_priv->trace_irq_seqno &&
+                     i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
+               i915_user_irq_put(dev);
+               dev_priv->trace_irq_seqno = 0;
+       }
 }
 
 void
@@ -2004,6 +2034,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
        }
 
        i915_gem_object_put_pages(obj);
+       BUG_ON(obj_priv->pages_refcount);
 
        if (obj_priv->gtt_space) {
                atomic_dec(&dev->gtt_count);
@@ -2017,17 +2048,14 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
        if (!list_empty(&obj_priv->list))
                list_del_init(&obj_priv->list);
 
+       if (i915_gem_object_is_purgeable(obj_priv))
+               i915_gem_object_truncate(obj);
+
        trace_i915_gem_object_unbind(obj);
 
        return 0;
 }
 
-static inline int
-i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv)
-{
-       return !obj_priv->dirty || obj_priv->madv == I915_MADV_DONTNEED;
-}
-
 static struct drm_gem_object *
 i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
 {
@@ -2040,7 +2068,8 @@ i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
        list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, list) {
                struct drm_gem_object *obj = obj_priv->obj;
                if (obj->size >= min_size) {
-                       if (i915_gem_object_is_purgeable(obj_priv) &&
+                       if ((!obj_priv->dirty ||
+                            i915_gem_object_is_purgeable(obj_priv)) &&
                            (!best || obj->size < best->size)) {
                                best = obj;
                                if (best->size == min_size)
@@ -2062,27 +2091,14 @@ i915_gem_evict_everything(struct drm_device *dev)
        int ret;
        bool lists_empty;
 
-       DRM_INFO("GTT full, evicting everything: "
-                "%d objects [%d pinned], "
-                "%d object bytes [%d pinned], "
-                "%d/%d gtt bytes\n",
-                atomic_read(&dev->object_count),
-                atomic_read(&dev->pin_count),
-                atomic_read(&dev->object_memory),
-                atomic_read(&dev->pin_memory),
-                atomic_read(&dev->gtt_memory),
-                dev->gtt_total);
-
        spin_lock(&dev_priv->mm.active_list_lock);
        lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
                       list_empty(&dev_priv->mm.flushing_list) &&
                       list_empty(&dev_priv->mm.active_list));
        spin_unlock(&dev_priv->mm.active_list_lock);
 
-       if (lists_empty) {
-               DRM_ERROR("GTT full, but lists empty!\n");
+       if (lists_empty)
                return -ENOSPC;
-       }
 
        /* Flush everything (on to the inactive lists) and evict */
        i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
@@ -2113,7 +2129,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_gem_object *obj;
-       int have_waited = 0;
        int ret;
 
        for (;;) {
@@ -2137,9 +2152,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
                        return i915_gem_object_unbind(obj);
                }
 
-               if (have_waited)
-                       return 0;
-
                /* If we didn't get anything, but the ring is still processing
                 * things, wait for the next to finish and hopefully leave us
                 * a buffer to evict.
@@ -2155,7 +2167,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
                        if (ret)
                                return ret;
 
-                       have_waited = 1;
                        continue;
                }
 
@@ -2166,36 +2177,41 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
                 */
                if (!list_empty(&dev_priv->mm.flushing_list)) {
                        struct drm_i915_gem_object *obj_priv;
-                       uint32_t seqno;
 
-                       obj_priv = list_first_entry(&dev_priv->mm.flushing_list,
-                                                   struct drm_i915_gem_object,
-                                                   list);
-                       obj = obj_priv->obj;
+                       /* Find an object that we can immediately reuse */
+                       list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, list) {
+                               obj = obj_priv->obj;
+                               if (obj->size >= min_size)
+                                       break;
+
+                               obj = NULL;
+                       }
 
-                       i915_gem_flush(dev,
-                                      obj->write_domain,
-                                      obj->write_domain);
-                       seqno = i915_add_request(dev, NULL, obj->write_domain);
-                       if (seqno == 0)
-                               return -ENOMEM;
+                       if (obj != NULL) {
+                               uint32_t seqno;
 
-                       ret = i915_wait_request(dev, seqno);
-                       if (ret)
-                               return ret;
+                               i915_gem_flush(dev,
+                                              obj->write_domain,
+                                              obj->write_domain);
+                               seqno = i915_add_request(dev, NULL, obj->write_domain);
+                               if (seqno == 0)
+                                       return -ENOMEM;
 
-                       have_waited = 1;
-                       continue;
+                               ret = i915_wait_request(dev, seqno);
+                               if (ret)
+                                       return ret;
+
+                               continue;
+                       }
                }
 
                /* If we didn't do any of the above, there's no single buffer
                 * large enough to swap out for the new one, so just evict
                 * everything and start again. (This should be rare.)
                 */
-               if (!list_empty (&dev_priv->mm.inactive_list)) {
-                       DRM_INFO("GTT full, evicting inactive buffers\n");
+               if (!list_empty (&dev_priv->mm.inactive_list))
                        return i915_gem_evict_from_inactive_list(dev);
-               else
+               else
                        return i915_gem_evict_everything(dev);
        }
 }
@@ -2220,7 +2236,6 @@ i915_gem_object_get_pages(struct drm_gem_object *obj)
        BUG_ON(obj_priv->pages != NULL);
        obj_priv->pages = drm_calloc_large(page_count, sizeof(struct page *));
        if (obj_priv->pages == NULL) {
-               DRM_ERROR("Failed to allocate page list\n");
                obj_priv->pages_refcount--;
                return -ENOMEM;
        }
@@ -2557,7 +2572,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
        if (dev_priv->mm.suspended)
                return -EBUSY;
 
-       if (obj_priv->madv == I915_MADV_DONTNEED) {
+       if (obj_priv->madv != I915_MADV_WILLNEED) {
                DRM_ERROR("Attempting to bind a purgeable object\n");
                return -EINVAL;
        }
@@ -2588,11 +2603,9 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
                DRM_INFO("%s: GTT full, evicting something\n", __func__);
 #endif
                ret = i915_gem_evict_something(dev, obj->size);
-               if (ret != 0) {
-                       if (ret != -ERESTARTSYS)
-                               DRM_ERROR("Failed to evict a buffer %d\n", ret);
+               if (ret)
                        return ret;
-               }
+
                goto search_free;
        }
 
@@ -2617,9 +2630,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
                        /* first try to clear up some space from the GTT */
                        ret = i915_gem_evict_something(dev, obj->size);
                        if (ret) {
-                               if (ret != -ERESTARTSYS)
-                                       DRM_ERROR("Failed to allocate space for backing pages %d\n", ret);
-
                                /* now try to shrink everyone else */
                                if (! retry_alloc) {
                                    retry_alloc = true;
@@ -2649,11 +2659,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
                obj_priv->gtt_space = NULL;
 
                ret = i915_gem_evict_something(dev, obj->size);
-               if (ret) {
-                       if (ret != -ERESTARTSYS)
-                               DRM_ERROR("Failed to allocate space to bind AGP: %d\n", ret);
+               if (ret)
                        return ret;
-               }
 
                goto search_free;
        }
@@ -3351,7 +3358,7 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
        exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
        exec_len = (uint32_t) exec->batch_len;
 
-       trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno);
+       trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno + 1);
 
        count = nbox ? nbox : 1;
 
@@ -3853,11 +3860,8 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
        i915_verify_inactive(dev, __FILE__, __LINE__);
        if (obj_priv->gtt_space == NULL) {
                ret = i915_gem_object_bind_to_gtt(obj, alignment);
-               if (ret != 0) {
-                       if (ret != -EBUSY && ret != -ERESTARTSYS)
-                               DRM_ERROR("Failure to bind: %d\n", ret);
+               if (ret)
                        return ret;
-               }
        }
        /*
         * Pre-965 chips need a fence register set up in order to
@@ -3937,8 +3941,8 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
        }
        obj_priv = obj->driver_private;
 
-       if (obj_priv->madv == I915_MADV_DONTNEED) {
-               DRM_ERROR("Attempting to pin a I915_MADV_DONTNEED buffer\n");
+       if (obj_priv->madv != I915_MADV_WILLNEED) {
+               DRM_ERROR("Attempting to pin a purgeable buffer\n");
                drm_gem_object_unreference(obj);
                mutex_unlock(&dev->struct_mutex);
                return -EINVAL;
@@ -4090,8 +4094,15 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       obj_priv->madv = args->madv;
-       args->retained = obj_priv->gtt_space != NULL;
+       if (obj_priv->madv != __I915_MADV_PURGED)
+               obj_priv->madv = args->madv;
+
+       /* if the object is no longer bound, discard its backing storage */
+       if (i915_gem_object_is_purgeable(obj_priv) &&
+           obj_priv->gtt_space == NULL)
+               i915_gem_object_truncate(obj);
+
+       args->retained = obj_priv->madv != __I915_MADV_PURGED;
 
        drm_gem_object_unreference(obj);
        mutex_unlock(&dev->struct_mutex);
@@ -4544,15 +4555,11 @@ int
 i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv)
 {
-       int ret;
-
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return 0;
 
-       ret = i915_gem_idle(dev);
        drm_irq_uninstall(dev);
-
-       return ret;
+       return i915_gem_idle(dev);
 }
 
 void
@@ -4806,19 +4813,6 @@ void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv)
        mutex_unlock(&dev->struct_mutex);
 }
 
-/* Immediately discard the backing storage */
-static void
-i915_gem_object_truncate(struct drm_gem_object *obj)
-{
-    struct inode *inode;
-
-    inode = obj->filp->f_path.dentry->d_inode;
-
-    mutex_lock(&inode->i_mutex);
-    truncate_inode_pages(inode->i_mapping, 0);
-    mutex_unlock(&inode->i_mutex);
-}
-
 static int
 i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask)
 {
@@ -4864,10 +4858,7 @@ i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask)
                                         &dev_priv->mm.inactive_list,
                                         list) {
                        if (i915_gem_object_is_purgeable(obj_priv)) {
-                               struct drm_gem_object *obj = obj_priv->obj;
-                               i915_gem_object_unbind(obj);
-                               i915_gem_object_truncate(obj);
-
+                               i915_gem_object_unbind(obj_priv->obj);
                                if (--nr_to_scan <= 0)
                                        break;
                        }
@@ -4876,6 +4867,8 @@ i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask)
                spin_lock(&shrink_list_lock);
                mutex_unlock(&dev->struct_mutex);
 
+               would_deadlock = 0;
+
                if (nr_to_scan <= 0)
                        break;
        }
@@ -4894,11 +4887,7 @@ i915_gem_shrink(int nr_to_scan, gfp_t gfp_mask)
                                         &dev_priv->mm.inactive_list,
                                         list) {
                        if (nr_to_scan > 0) {
-                               struct drm_gem_object *obj = obj_priv->obj;
-                               i915_gem_object_unbind(obj);
-                               if (i915_gem_object_is_purgeable(obj_priv))
-                                       i915_gem_object_truncate(obj);
-
+                               i915_gem_object_unbind(obj_priv->obj);
                                nr_to_scan--;
                        } else
                                cnt++;