perf_mi_noop() waits for the request it has just submitted, drops the
reference taken with i915_request_get() and only then reads
rq->hwsp_seqno[].
i915_request_wait() returns as soon as the fence is signaled, which
happens in i915_request_retire() before it puts the request's initial
reference. If retirement has already run, the put in this loop is the
last one and i915_request_put() frees the request, so the seqno is read
from an object that the SLAB_TYPESAFE_BY_RCU slab cache can already have
handed out to another user.
Sample the seqno while the reference is still held.
Fixes: 3c7a44bbbfa7 ("drm/i915/selftests: Perform some basic cycle counting of
MI ops")
Cc: [email protected]
Assisted-by: DeepSeek-V4.1-Flash and OpenAI Codex
Signed-off-by: Wentao Liang <[email protected]>
---
drivers/gpu/drm/i915/gt/selftest_engine_cs.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
index 1846f1c7e77e..f894902f5509 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
@@ -357,13 +357,19 @@ static int perf_mi_noop(void *arg)
if (i915_request_wait(rq, 0, HZ / 5) < 0)
err = -EIO;
+
+ /*
+ * The request can be freed as soon as its last
+ * reference is dropped, so read the seqno first.
+ */
+ if (!err)
+ cycles[i] =
+ (rq->hwsp_seqno[4] - rq->hwsp_seqno[3])
-
+ (rq->hwsp_seqno[3] - rq->hwsp_seqno[2]);
+
i915_request_put(rq);
if (err)
break;
-
- cycles[i] =
- (rq->hwsp_seqno[4] - rq->hwsp_seqno[3]) -
- (rq->hwsp_seqno[3] - rq->hwsp_seqno[2]);
}
i915_vma_put(nop);
i915_vma_put(base);
--
2.34.1