Skip to content

Commit c10e4a7

Browse files
ickledanvet
authored andcommitted
drm/i915: Protect against request freeing during cancellation on wedging
As soon as we mark a request as completed, it may be retired. So when cancelling a request and marking it complete, make sure we first keep a reference to the request. Signed-off-by: Chris Wilson <[email protected]> Reviewed-by: Mika Kuoppala <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Daniel Vetter <[email protected]>
1 parent d712f4c commit c10e4a7

File tree

6 files changed

+31
-24
lines changed

6 files changed

+31
-24
lines changed

drivers/gpu/drm/i915/gt/intel_execlists_submission.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2954,16 +2954,18 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
29542954

29552955
/* Mark all executing requests as skipped. */
29562956
list_for_each_entry(rq, &engine->active.requests, sched.link)
2957-
i915_request_mark_eio(rq);
2957+
i915_request_put(i915_request_mark_eio(rq));
29582958
intel_engine_signal_breadcrumbs(engine);
29592959

29602960
/* Flush the queued requests to the timeline list (for retiring). */
29612961
while ((rb = rb_first_cached(&execlists->queue))) {
29622962
struct i915_priolist *p = to_priolist(rb);
29632963

29642964
priolist_for_each_request_consume(rq, rn, p) {
2965-
i915_request_mark_eio(rq);
2966-
__i915_request_submit(rq);
2965+
if (i915_request_mark_eio(rq)) {
2966+
__i915_request_submit(rq);
2967+
i915_request_put(rq);
2968+
}
29672969
}
29682970

29692971
rb_erase_cached(&p->node, &execlists->queue);
@@ -2972,7 +2974,7 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
29722974

29732975
/* On-hold requests will be flushed to timeline upon their release */
29742976
list_for_each_entry(rq, &engine->active.hold, sched.link)
2975-
i915_request_mark_eio(rq);
2977+
i915_request_put(i915_request_mark_eio(rq));
29762978

29772979
/* Cancel all attached virtual engines */
29782980
while ((rb = rb_first_cached(&execlists->virtual))) {
@@ -2985,10 +2987,11 @@ static void execlists_reset_cancel(struct intel_engine_cs *engine)
29852987
spin_lock(&ve->base.active.lock);
29862988
rq = fetch_and_zero(&ve->request);
29872989
if (rq) {
2988-
i915_request_mark_eio(rq);
2989-
2990-
rq->engine = engine;
2991-
__i915_request_submit(rq);
2990+
if (i915_request_mark_eio(rq)) {
2991+
rq->engine = engine;
2992+
__i915_request_submit(rq);
2993+
i915_request_put(rq);
2994+
}
29922995
i915_request_put(rq);
29932996

29942997
ve->base.execlists.queue_priority_hint = INT_MIN;

drivers/gpu/drm/i915/gt/intel_reset.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -786,18 +786,15 @@ static void reset_finish(struct intel_gt *gt, intel_engine_mask_t awake)
786786

787787
static void nop_submit_request(struct i915_request *request)
788788
{
789-
struct intel_engine_cs *engine = request->engine;
790-
unsigned long flags;
791-
792789
RQ_TRACE(request, "-EIO\n");
793-
i915_request_set_error_once(request, -EIO);
794790

795-
spin_lock_irqsave(&engine->active.lock, flags);
796-
__i915_request_submit(request);
797-
i915_request_mark_complete(request);
798-
spin_unlock_irqrestore(&engine->active.lock, flags);
791+
request = i915_request_mark_eio(request);
792+
if (request) {
793+
i915_request_submit(request);
794+
intel_engine_signal_breadcrumbs(request->engine);
799795

800-
intel_engine_signal_breadcrumbs(engine);
796+
i915_request_put(request);
797+
}
801798
}
802799

803800
static void __intel_gt_set_wedged(struct intel_gt *gt)

drivers/gpu/drm/i915/gt/intel_ring_submission.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ static void reset_cancel(struct intel_engine_cs *engine)
411411

412412
/* Mark all submitted requests as skipped. */
413413
list_for_each_entry(request, &engine->active.requests, sched.link)
414-
i915_request_mark_eio(request);
414+
i915_request_put(i915_request_mark_eio(request));
415415
intel_engine_signal_breadcrumbs(engine);
416416

417417
/* Remaining _unready_ requests will be nop'ed when submitted */

drivers/gpu/drm/i915/gt/mock_engine.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,15 @@ static void mock_reset_cancel(struct intel_engine_cs *engine)
239239

240240
/* Mark all submitted requests as skipped. */
241241
list_for_each_entry(rq, &engine->active.requests, sched.link)
242-
i915_request_mark_eio(rq);
242+
i915_request_put(i915_request_mark_eio(rq));
243243
intel_engine_signal_breadcrumbs(engine);
244244

245245
/* Cancel and submit all pending requests. */
246246
list_for_each_entry(rq, &mock->hw_queue, mock.link) {
247-
i915_request_mark_eio(rq);
248-
__i915_request_submit(rq);
247+
if (i915_request_mark_eio(rq)) {
248+
__i915_request_submit(rq);
249+
i915_request_put(rq);
250+
}
249251
}
250252
INIT_LIST_HEAD(&mock->hw_queue);
251253

drivers/gpu/drm/i915/i915_request.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,15 +514,20 @@ void i915_request_set_error_once(struct i915_request *rq, int error)
514514
} while (!try_cmpxchg(&rq->fence.error, &old, error));
515515
}
516516

517-
void i915_request_mark_eio(struct i915_request *rq)
517+
struct i915_request *i915_request_mark_eio(struct i915_request *rq)
518518
{
519519
if (__i915_request_is_complete(rq))
520-
return;
520+
return NULL;
521521

522522
GEM_BUG_ON(i915_request_signaled(rq));
523523

524+
/* As soon as the request is completed, it may be retired */
525+
rq = i915_request_get(rq);
526+
524527
i915_request_set_error_once(rq, -EIO);
525528
i915_request_mark_complete(rq);
529+
530+
return rq;
526531
}
527532

528533
bool __i915_request_submit(struct i915_request *request)

drivers/gpu/drm/i915/i915_request.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ i915_request_create(struct intel_context *ce);
311311

312312
void __i915_request_skip(struct i915_request *rq);
313313
void i915_request_set_error_once(struct i915_request *rq, int error);
314-
void i915_request_mark_eio(struct i915_request *rq);
314+
struct i915_request *i915_request_mark_eio(struct i915_request *rq);
315315

316316
struct i915_request *__i915_request_commit(struct i915_request *request);
317317
void __i915_request_queue(struct i915_request *rq,

0 commit comments

Comments
 (0)