Skip to content

Commit 312c4ba

Browse files
committed
drm/i915: Protect i915_active iterators from the shrinker
If we allocate while iterating the rbtree of active nodes, we may hit the shrinker and so retire the i915_active, reaping the rbtree. Modifying the rbtree as we iterate is not good behaviour, so acquire the i915_active first to keep the tree intact whenever we allocate. Fixes: a42375a ("drm/i915: Release the active tracker tree upon idling") 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> Link: https://patchwork.freedesktop.org/patch/msgid/20190208134704.23039-1-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
1 parent c10c78a commit 312c4ba

File tree

1 file changed

+25
-11
lines changed

1 file changed

+25
-11
lines changed

drivers/gpu/drm/i915/i915_active.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,25 @@ int i915_active_ref(struct i915_active *ref,
163163
struct i915_request *rq)
164164
{
165165
struct i915_active_request *active;
166+
int err = 0;
167+
168+
/* Prevent reaping in case we malloc/wait while building the tree */
169+
i915_active_acquire(ref);
166170

167171
active = active_instance(ref, timeline);
168-
if (IS_ERR(active))
169-
return PTR_ERR(active);
172+
if (IS_ERR(active)) {
173+
err = PTR_ERR(active);
174+
goto out;
175+
}
170176

171177
if (!i915_active_request_isset(active))
172178
ref->count++;
173179
__i915_active_request_set(active, rq);
174180

175181
GEM_BUG_ON(!ref->count);
176-
return 0;
182+
out:
183+
i915_active_release(ref);
184+
return err;
177185
}
178186

179187
bool i915_active_acquire(struct i915_active *ref)
@@ -223,19 +231,25 @@ int i915_request_await_active_request(struct i915_request *rq,
223231
int i915_request_await_active(struct i915_request *rq, struct i915_active *ref)
224232
{
225233
struct active_node *it, *n;
226-
int ret;
234+
int err = 0;
227235

228-
ret = i915_request_await_active_request(rq, &ref->last);
229-
if (ret)
230-
return ret;
236+
/* await allocates and so we need to avoid hitting the shrinker */
237+
if (i915_active_acquire(ref))
238+
goto out; /* was idle */
239+
240+
err = i915_request_await_active_request(rq, &ref->last);
241+
if (err)
242+
goto out;
231243

232244
rbtree_postorder_for_each_entry_safe(it, n, &ref->tree, node) {
233-
ret = i915_request_await_active_request(rq, &it->base);
234-
if (ret)
235-
return ret;
245+
err = i915_request_await_active_request(rq, &it->base);
246+
if (err)
247+
goto out;
236248
}
237249

238-
return 0;
250+
out:
251+
i915_active_release(ref);
252+
return err;
239253
}
240254

241255
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)

0 commit comments

Comments
 (0)