ACPICA: avoid "Info: mapping multiple BARs. Your kernel is fine."
[safe/jmp/linux-2.6] / drivers / gpu / drm / i915 / i915_gem.c
index 8beec97..abfc27b 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;
        }
 }
 
@@ -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;
@@ -1534,11 +1538,14 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
 static void
 i915_gem_object_truncate(struct drm_gem_object *obj)
 {
-    struct inode *inode;
+       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);
 
-    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
@@ -1763,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);
@@ -1787,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
@@ -2559,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;
        }
@@ -3345,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;
 
@@ -3928,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;
@@ -4081,14 +4094,16 @@ 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);
 
@@ -4540,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