⬢ DragonFlyBSD Kernel Audit
DF-4163 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/radeon_pm.c	(with DF-4162/fix.diff applied first)
+++ b/sys/dev/drm/radeon/radeon_pm.c
@@ -1724,6 +1724,20 @@
 
 static void radeon_pm_fini_dpm(struct radeon_device *rdev)
 {
+	/*
+	 * The thermal IRQ is still installed here (asic fini order:
+	 * radeon_pm_fini() runs BEFORE the irq teardown, e.g. si_fini)
+	 * and schedules pm.dpm.thermal.work whenever dpm_enabled is set.
+	 * Flush any pending handler and clear the flag BEFORE freeing
+	 * the dpm state, or the handler walks rdev->pm.dpm.ps[] after
+	 * radeon_dpm_fini() freed it (ps is kfree'd without NULLing and
+	 * num_ps stays > 0). The handler's dpm_enabled checks (entry +
+	 * under pm.mutex in radeon_dpm_change_power_state_locked) make
+	 * any post-cancel stragglers return once the flag is clear.
+	 */
+	cancel_work_sync(&rdev->pm.dpm.thermal.work);
+	rdev->pm.dpm_enabled = false;
+
 	if (rdev->pm.num_power_states > 1 && rdev->pm.dpm.boot_ps) {
 		mutex_lock(&rdev->pm.mutex);
 		radeon_dpm_disable(rdev);