DF-4568 / fix.diff
diff --git a/sys/dev/drm/i915/intel_guc_ct.c b/sys/dev/drm/i915/intel_guc_ct.c index 1278f33..254959b 100644 --- a/sys/dev/drm/i915/intel_guc_ct.c +++ b/sys/dev/drm/i915/intel_guc_ct.c @@ -895,10 +895,11 @@ void intel_guc_ct_disable(struct intel_guc_ct *ct) if (!ctch_is_open(ctch)) return; - ctch_close(guc, ctch); - - /* Disable send */ + /* Stop send and event handling before freeing the shared buffers */ guc->send = intel_guc_send_nop; guc->handler = intel_guc_to_host_event_handler_nop; + + ctch_close(guc, ctch); + DRM_INFO("CT: %s\n", enableddisabled(false)); } diff --git a/sys/dev/drm/i915/intel_uc.c b/sys/dev/drm/i915/intel_uc.c index b1b3e81..e2745a9 100644 --- a/sys/dev/drm/i915/intel_uc.c +++ b/sys/dev/drm/i915/intel_uc.c @@ -227,13 +227,19 @@ static void guc_disable_communication(struct intel_guc *guc) { struct drm_i915_private *i915 = guc_to_i915(guc); - if (HAS_GUC_CT(i915)) - intel_guc_ct_disable(&guc->ct); - + /* + * Quiesce first: gen9_disable_guc_interrupts() masks the GuC events + * and synchronize_irq()s them, so no in-flight handler can touch the + * CT buffers we are about to free. + */ gen9_disable_guc_interrupts(i915); + /* Disable send and event handling before freeing the shared buffers */ guc->send = intel_guc_send_nop; guc->handler = intel_guc_to_host_event_handler_nop; + + if (HAS_GUC_CT(i915)) + intel_guc_ct_disable(&guc->ct); } int intel_uc_init_misc(struct drm_i915_private *i915) |