drm/i915: Trim struct_mutex hold duration for i915_gem_free_objects
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 13 Oct 2017 20:26:21 +0000 (21:26 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 16 Oct 2017 19:44:19 +0000 (20:44 +0100)
We free objects in bulk after they wait for their RCU grace period.
Currently, we take struct_mutex and unbind all the objects. This can lead
to a long lock duration during which time those objects have their pages
unfreeable (i.e. the shrinker is prevented from reaping those pages). If
we only process a single object under the struct_mutex and then free the
pages, the number of objects locked away from the shrinker is minimal
and we allow regular clients better access to struct_mutex if they need
it.

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

index f4b5921a9e9b20ec3f28f1f794e3e28f9e326954..1304152bd28b88499a152cc2961eb04a383a6a8b 100644 (file)
@@ -4490,13 +4490,14 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 {
        struct drm_i915_gem_object *obj, *on;
 
-       mutex_lock(&i915->drm.struct_mutex);
        intel_runtime_pm_get(i915);
-       llist_for_each_entry(obj, freed, freed) {
+       llist_for_each_entry_safe(obj, on, freed, freed) {
                struct i915_vma *vma, *vn;
 
                trace_i915_gem_object_destroy(obj);
 
+               mutex_lock(&i915->drm.struct_mutex);
+
                GEM_BUG_ON(i915_gem_object_is_active(obj));
                list_for_each_entry_safe(vma, vn,
                                         &obj->vma_list, obj_link) {
@@ -4519,13 +4520,8 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
                        spin_unlock(&i915->mm.obj_lock);
                }
 
-       }
-       intel_runtime_pm_put(i915);
-       mutex_unlock(&i915->drm.struct_mutex);
-
-       cond_resched();
+               mutex_unlock(&i915->drm.struct_mutex);
 
-       llist_for_each_entry_safe(obj, on, freed, freed) {
                GEM_BUG_ON(obj->bind_count);
                GEM_BUG_ON(obj->userfault_count);
                GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));
@@ -4548,7 +4544,11 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 
                kfree(obj->bit_17);
                i915_gem_object_free(obj);
+
+               if (on)
+                       cond_resched();
        }
+       intel_runtime_pm_put(i915);
 }
 
 static void i915_gem_flush_free_objects(struct drm_i915_private *i915)