--- 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);