A context flagged SCHED_STATE_DESTROYED has already dropped its final
reference, and __guc_context_destroy() frees it immediately (virtual
engine contexts are kfree'd outright). The pending_disable block is not
mutually exclusive with the destroyed state and kept using the context
after that destroy. Defer __guc_context_destroy() until after the
pending_disable handling.

Fixes: eb5e7da736f3 ("drm/i915/guc: Reset implementation for new GuC interface")
Cc: [email protected]
Signed-off-by: Wentao Liang <[email protected]>
---
 drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 7b88e081c76d..5eab2baa1f7f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -1122,7 +1122,6 @@ static void scrub_guc_desc_for_outstanding_g2h(struct 
intel_guc *guc)
                        if (destroyed) {
                                intel_gt_pm_put_async_untracked(guc_to_gt(guc));
                                release_guc_id(guc, ce);
-                               __guc_context_destroy(ce);
                        }
                        if (pending_enable || deregister)
                                intel_context_put(ce);
@@ -1145,6 +1144,13 @@ static void scrub_guc_desc_for_outstanding_g2h(struct 
intel_guc *guc)
                        intel_context_put(ce);
                }
 
+               /*
+                * Finish the destroy last, as it may free the context while
+                * the above states still need to access it.
+                */
+               if (destroyed)
+                       __guc_context_destroy(ce);
+
                if (do_put)
                        intel_context_put(ce);
                xa_lock(&guc->context_lookup);
-- 
2.34.1

Reply via email to