]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/gpu/drm/i915/i915_gem.c
i915: add newline to i915_gem_object_pin failure msg
[linux-2.6-omap-h63xx.git] / drivers / gpu / drm / i915 / i915_gem.c
index 02ef50d512d6fa9ee0d470754b833a6c37da614b..c94069b28a471847867d0ae52ec5c608ccd05f3f 100644 (file)
@@ -1051,6 +1051,9 @@ 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)
+               return;
+
        seqno = i915_get_gem_seqno(dev);
 
        while (!list_empty(&dev_priv->mm.request_list)) {
@@ -2067,8 +2070,14 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
                i915_gem_clflush_object(obj);
        }
 
-       if ((obj->pending_write_domain | flush_domains) != 0)
-               obj->write_domain = obj->pending_write_domain;
+       /* The actual obj->write_domain will be updated with
+        * pending_write_domain after we emit the accumulated flush for all
+        * of our domain changes in execbuffers (which clears objects'
+        * write_domains).  So if we have a current write domain that we
+        * aren't changing, set pending_write_domain to that.
+        */
+       if (flush_domains == 0 && obj->pending_write_domain == 0)
+               obj->pending_write_domain = obj->write_domain;
        obj->read_domains = obj->pending_read_domains;
 
        dev->invalidate_domains |= invalidate_domains;
@@ -2460,6 +2469,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
        struct drm_i915_gem_exec_object *exec_list = NULL;
        struct drm_gem_object **object_list = NULL;
        struct drm_gem_object *batch_obj;
+       struct drm_i915_gem_object *obj_priv;
        int ret, i, pinned = 0;
        uint64_t exec_offset;
        uint32_t seqno, flush_domains;
@@ -2524,6 +2534,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                        ret = -EBADF;
                        goto err;
                }
+
+               obj_priv = object_list[i]->driver_private;
+               if (obj_priv->in_execbuffer) {
+                       DRM_ERROR("Object %p appears more than once in object list\n",
+                                  object_list[i]);
+                       ret = -EBADF;
+                       goto err;
+               }
+               obj_priv->in_execbuffer = true;
        }
 
        /* Pin and relocate */
@@ -2598,6 +2617,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                        (void)i915_add_request(dev, dev->flush_domains);
        }
 
+       for (i = 0; i < args->buffer_count; i++) {
+               struct drm_gem_object *obj = object_list[i];
+
+               obj->write_domain = obj->pending_write_domain;
+       }
+
        i915_verify_inactive(dev, __FILE__, __LINE__);
 
 #if WATCH_COHERENCY
@@ -2659,8 +2684,13 @@ err:
        for (i = 0; i < pinned; i++)
                i915_gem_object_unpin(object_list[i]);
 
-       for (i = 0; i < args->buffer_count; i++)
+       for (i = 0; i < args->buffer_count; i++) {
+               if (object_list[i]) {
+                       obj_priv = object_list[i]->driver_private;
+                       obj_priv->in_execbuffer = false;
+               }
                drm_gem_object_unreference(object_list[i]);
+       }
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -2697,7 +2727,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
                ret = i915_gem_object_bind_to_gtt(obj, alignment);
                if (ret != 0) {
                        if (ret != -EBUSY && ret != -ERESTARTSYS)
-                               DRM_ERROR("Failure to bind: %d", ret);
+                               DRM_ERROR("Failure to bind: %d\n", ret);
                        return ret;
                }
                /*
@@ -2860,6 +2890,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
                return -EBADF;
        }
 
+       /* Update the active list for the hardware's current position.
+        * Otherwise this only updates on a delayed timer or when irqs are
+        * actually unmasked, and our working set ends up being larger than
+        * required.
+        */
+       i915_gem_retire_requests(dev);
+
        obj_priv = obj->driver_private;
        /* Don't count being on the flushing list against the object being
         * done.  Otherwise, a buffer left on the flushing list but not getting
@@ -2961,7 +2998,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
        return 0;
 }
 
-static int
+int
 i915_gem_idle(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -3124,16 +3161,20 @@ static void
 i915_gem_cleanup_hws(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_gem_object *obj = dev_priv->hws_obj;
-       struct drm_i915_gem_object *obj_priv = obj->driver_private;
+       struct drm_gem_object *obj;
+       struct drm_i915_gem_object *obj_priv;
 
        if (dev_priv->hws_obj == NULL)
                return;
 
+       obj = dev_priv->hws_obj;
+       obj_priv = obj->driver_private;
+
        kunmap(obj_priv->page_list[0]);
        i915_gem_object_unpin(obj);
        drm_gem_object_unreference(obj);
        dev_priv->hws_obj = NULL;
+
        memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
        dev_priv->hw_status_page = NULL;
 
@@ -3522,7 +3563,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
        user_data = (char __user *) (uintptr_t) args->data_ptr;
        obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
 
-       DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size);
+       DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size);
        ret = copy_from_user(obj_addr, user_data, args->size);
        if (ret)
                return -EFAULT;