Merge commit 'v2.6.34-rc1' into for-linus
[pandora-kernel.git] / drivers / gpu / drm / i915 / i915_gem.c
index ce1c026..fba37e9 100644 (file)
@@ -1558,6 +1558,38 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
        i915_verify_inactive(dev, __FILE__, __LINE__);
 }
 
+static void
+i915_gem_process_flushing_list(struct drm_device *dev,
+                              uint32_t flush_domains, uint32_t seqno)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_gem_object *obj_priv, *next;
+
+       list_for_each_entry_safe(obj_priv, next,
+                                &dev_priv->mm.gpu_write_list,
+                                gpu_write_list) {
+               struct drm_gem_object *obj = obj_priv->obj;
+
+               if ((obj->write_domain & flush_domains) ==
+                   obj->write_domain) {
+                       uint32_t old_write_domain = obj->write_domain;
+
+                       obj->write_domain = 0;
+                       list_del_init(&obj_priv->gpu_write_list);
+                       i915_gem_object_move_to_active(obj, seqno);
+
+                       /* update the fence lru list */
+                       if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
+                               list_move_tail(&obj_priv->fence_list,
+                                               &dev_priv->mm.fence_list);
+
+                       trace_i915_gem_object_change_domain(obj,
+                                                           obj->read_domains,
+                                                           old_write_domain);
+               }
+       }
+}
+
 /**
  * Creates a new sequence number, emitting a write of it to the status page
  * plus an interrupt, which will trigger i915_user_interrupt_handler.
@@ -1616,29 +1648,8 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
        /* Associate any objects on the flushing list matching the write
         * domain we're flushing with our flush.
         */
-       if (flush_domains != 0) {
-               struct drm_i915_gem_object *obj_priv, *next;
-
-               list_for_each_entry_safe(obj_priv, next,
-                                        &dev_priv->mm.gpu_write_list,
-                                        gpu_write_list) {
-                       struct drm_gem_object *obj = obj_priv->obj;
-
-                       if ((obj->write_domain & flush_domains) ==
-                           obj->write_domain) {
-                               uint32_t old_write_domain = obj->write_domain;
-
-                               obj->write_domain = 0;
-                               list_del_init(&obj_priv->gpu_write_list);
-                               i915_gem_object_move_to_active(obj, seqno);
-
-                               trace_i915_gem_object_change_domain(obj,
-                                                                   obj->read_domains,
-                                                                   old_write_domain);
-                       }
-               }
-
-       }
+       if (flush_domains != 0) 
+               i915_gem_process_flushing_list(dev, flush_domains, seqno);
 
        if (!dev_priv->mm.suspended) {
                mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
@@ -2083,12 +2094,35 @@ i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
        return best ? best : first;
 }
 
+static int
+i915_gpu_idle(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       bool lists_empty;
+       uint32_t seqno;
+
+       spin_lock(&dev_priv->mm.active_list_lock);
+       lists_empty = 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)
+               return 0;
+
+       /* Flush everything onto the inactive list. */
+       i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+       seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
+       if (seqno == 0)
+               return -ENOMEM;
+
+       return i915_wait_request(dev, seqno);
+}
+
 static int
 i915_gem_evict_everything(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
-       uint32_t seqno;
        bool lists_empty;
 
        spin_lock(&dev_priv->mm.active_list_lock);
@@ -2101,12 +2135,7 @@ i915_gem_evict_everything(struct drm_device *dev)
                return -ENOSPC;
 
        /* Flush everything (on to the inactive lists) and evict */
-       i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
-       seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
-       if (seqno == 0)
-               return -ENOMEM;
-
-       ret = i915_wait_request(dev, seqno);
+       ret = i915_gpu_idle(dev);
        if (ret)
                return ret;
 
@@ -2719,7 +2748,6 @@ static void
 i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
-       uint32_t seqno;
        uint32_t old_write_domain;
 
        if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
@@ -2728,9 +2756,8 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
        /* Queue the GPU write cache flushing we need. */
        old_write_domain = obj->write_domain;
        i915_gem_flush(dev, 0, obj->write_domain);
-       seqno = i915_add_request(dev, NULL, obj->write_domain);
+       (void) i915_add_request(dev, NULL, obj->write_domain);
        BUG_ON(obj->write_domain);
-       i915_gem_object_move_to_active(obj, seqno);
 
        trace_i915_gem_object_change_domain(obj,
                                            obj->read_domains,
@@ -3340,6 +3367,16 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                }
 
                /* Validate that the target is in a valid r/w GPU domain */
+               if (reloc->write_domain & (reloc->write_domain - 1)) {
+                       DRM_ERROR("reloc with multiple write domains: "
+                                 "obj %p target %d offset %d "
+                                 "read %08x write %08x",
+                                 obj, reloc->target_handle,
+                                 (int) reloc->offset,
+                                 reloc->read_domains,
+                                 reloc->write_domain);
+                       return -EINVAL;
+               }
                if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
                    reloc->read_domains & I915_GEM_DOMAIN_CPU) {
                        DRM_ERROR("reloc with read/write CPU domains: "
@@ -4464,30 +4501,6 @@ i915_gem_evict_from_inactive_list(struct drm_device *dev)
        return 0;
 }
 
-static int
-i915_gpu_idle(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       bool lists_empty;
-       uint32_t seqno;
-
-       spin_lock(&dev_priv->mm.active_list_lock);
-       lists_empty = 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)
-               return 0;
-
-       /* Flush everything onto the inactive list. */
-       i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
-       seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
-       if (seqno == 0)
-               return -ENOMEM;
-
-       return i915_wait_request(dev, seqno);
-}
-
 int
 i915_gem_idle(struct drm_device *dev)
 {