aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-11-09 03:55:40 -0500
committerJani Nikula <jani.nikula@intel.com>2017-11-09 09:18:37 -0500
commite8c49fa96838101435b9e4884d49b30da7a4e0c6 (patch)
tree4245d55b3fc04709d3aa5144b8957498fc23aa6b /drivers/gpu/drm
parent6ac43272768ca901daac4076a66c2c4e3c7b9321 (diff)
drm/i915: Reorder context-close to avoid calling i915_vma_close() under RCU
When we close the VMA, we unbind it from the ppgtt and tear down the page directory pointing at it. That may trigger us to return WC pages back to the system, requiring conversion back to WB which itself may sleep. That makes i915_vma_close() unsuitable for use inside the RCU read lock, which we need to hold to iterate the radixtree. The fix is quite simple, we can close all the VMA as we close the ppgtt, we only need to do that instead of closing them during destruction of the LUT. v2: Order between closing the LUT and the ppgtt is important; we use the vma inside the LUT as a means of retrieving the object, and so we must clear the LUT before freeing the VMA when closing the ppgtt. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103638 Fixes: 547da76b5777 ("drm/i915: Hold rcu_read_lock when iterating over the radixtree (vma idr)") Fixes: d1b48c1e7184 ("drm/i915: Replace execbuf vma ht with an idr") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Matthew Auld <matthew.william.auld@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171109085540.32264-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> (cherry picked from commit 94dec87159af6f3dcc0b78d3f909aefa9e29c01a) Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 5bf96a258509..e304dcbc6042 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -106,14 +106,9 @@ static void lut_close(struct i915_gem_context *ctx)
106 106
107 radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) { 107 radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) {
108 struct i915_vma *vma = rcu_dereference_raw(*slot); 108 struct i915_vma *vma = rcu_dereference_raw(*slot);
109 struct drm_i915_gem_object *obj = vma->obj;
110 109
111 radix_tree_iter_delete(&ctx->handles_vma, &iter, slot); 110 radix_tree_iter_delete(&ctx->handles_vma, &iter, slot);
112 111 __i915_gem_object_release_unless_active(vma->obj);
113 if (!i915_vma_is_ggtt(vma))
114 i915_vma_close(vma);
115
116 __i915_gem_object_release_unless_active(obj);
117 } 112 }
118} 113}
119 114
@@ -198,6 +193,11 @@ static void context_close(struct i915_gem_context *ctx)
198{ 193{
199 i915_gem_context_set_closed(ctx); 194 i915_gem_context_set_closed(ctx);
200 195
196 /*
197 * The LUT uses the VMA as a backpointer to unref the object,
198 * so we need to clear the LUT before we close all the VMA (inside
199 * the ppgtt).
200 */
201 lut_close(ctx); 201 lut_close(ctx);
202 if (ctx->ppgtt) 202 if (ctx->ppgtt)
203 i915_ppgtt_close(&ctx->ppgtt->base); 203 i915_ppgtt_close(&ctx->ppgtt->base);