drm/i915: Retire an active batch pool object rather than allocate new
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 16 Mar 2017 13:19:53 +0000 (13:19 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 17 Mar 2017 17:57:20 +0000 (17:57 +0000)
Since obj->active_count is only updated upon retirement, if we see an
active object in the batch pool, double check that is still active
before deciding to allocate a new object.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: http://patchwork.freedesktop.org/patch/msgid/20170316132006.7976-3-chris@chris-wilson.co.uk
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
drivers/gpu/drm/i915/i915_gem_batch_pool.c

index 99ceae7855f842e67595a66ab50199119f3a4834..41aa598c4f3b6393e83d2fc5ea9a0d7a3484dccd 100644 (file)
@@ -96,8 +96,7 @@ struct drm_i915_gem_object *
 i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool,
                        size_t size)
 {
-       struct drm_i915_gem_object *obj = NULL;
-       struct drm_i915_gem_object *tmp;
+       struct drm_i915_gem_object *obj;
        struct list_head *list;
        int n, ret;
 
@@ -112,31 +111,29 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool,
                n = ARRAY_SIZE(pool->cache_list) - 1;
        list = &pool->cache_list[n];
 
-       list_for_each_entry(tmp, list, batch_pool_link) {
+       list_for_each_entry(obj, list, batch_pool_link) {
                /* The batches are strictly LRU ordered */
-               if (i915_gem_object_is_active(tmp))
-                       break;
+               if (i915_gem_object_is_active(obj)) {
+                       if (!reservation_object_test_signaled_rcu(obj->resv,
+                                                                 true))
+                               break;
 
-               GEM_BUG_ON(!reservation_object_test_signaled_rcu(tmp->resv,
-                                                                true));
+                       i915_gem_retire_requests(pool->engine->i915);
+                       GEM_BUG_ON(i915_gem_object_is_active(obj));
+               }
 
-               if (tmp->base.size >= size) {
-                       /* Clear the set of shared fences early */
-                       reservation_object_lock(tmp->resv, NULL);
-                       reservation_object_add_excl_fence(tmp->resv, NULL);
-                       reservation_object_unlock(tmp->resv);
+               GEM_BUG_ON(!reservation_object_test_signaled_rcu(obj->resv,
+                                                                true));
 
-                       obj = tmp;
-                       break;
-               }
+               if (obj->base.size >= size)
+                       goto found;
        }
 
-       if (obj == NULL) {
-               obj = i915_gem_object_create_internal(pool->engine->i915, size);
-               if (IS_ERR(obj))
-                       return obj;
-       }
+       obj = i915_gem_object_create_internal(pool->engine->i915, size);
+       if (IS_ERR(obj))
+               return obj;
 
+found:
        ret = i915_gem_object_pin_pages(obj);
        if (ret)
                return ERR_PTR(ret);