⬢ DragonFlyBSD Kernel Audit
DF-4568 / fix.diff
← back to finding ↓ download raw
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)