Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/pm: fix BUG: scheduling while atomic

atomic scheduling will be triggered in interrupt handler for
AC/DC mode switch as following backtrace.
Call Trace:
<IRQ>
dump_stack_lvl
__schedule_bug
__schedule
schedule
schedule_preempt_disabled
__mutex_lock
smu_cmn_send_smc_msg_with_param
smu_v13_0_irq_process
amdgpu_irq_dispatch
amdgpu_ih_process
amdgpu_irq_handler
__handle_irq_event_percpu
handle_irq_event
handle_edge_irq
__common_interrupt
common_interrupt
</IRQ>
<TASK>
asm_common_interrupt

Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Kun Liu <Kun.Liu2@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Kun Liu and committed by
Alex Deucher
03cc84b1 9095567b

+10 -6
+2
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
··· 303 303 int smu_v13_0_get_boot_freq_by_index(struct smu_context *smu, 304 304 enum smu_clk_type clk_type, 305 305 uint32_t *value); 306 + 307 + void smu_v13_0_interrupt_work(struct smu_context *smu); 306 308 #endif 307 309 #endif
+6 -6
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
··· 1321 1321 return 0; 1322 1322 } 1323 1323 1324 - static int smu_v13_0_ack_ac_dc_interrupt(struct smu_context *smu) 1324 + void smu_v13_0_interrupt_work(struct smu_context *smu) 1325 1325 { 1326 - return smu_cmn_send_smc_msg(smu, 1327 - SMU_MSG_ReenableAcDcInterrupt, 1328 - NULL); 1326 + smu_cmn_send_smc_msg(smu, 1327 + SMU_MSG_ReenableAcDcInterrupt, 1328 + NULL); 1329 1329 } 1330 1330 1331 1331 #define THM_11_0__SRCID__THM_DIG_THERM_L2H 0 /* ASIC_TEMP > CG_THERMAL_INT.DIG_THERM_INTH */ ··· 1378 1378 switch (ctxid) { 1379 1379 case SMU_IH_INTERRUPT_CONTEXT_ID_AC: 1380 1380 dev_dbg(adev->dev, "Switched to AC mode!\n"); 1381 - smu_v13_0_ack_ac_dc_interrupt(smu); 1381 + schedule_work(&smu->interrupt_work); 1382 1382 adev->pm.ac_power = true; 1383 1383 break; 1384 1384 case SMU_IH_INTERRUPT_CONTEXT_ID_DC: 1385 1385 dev_dbg(adev->dev, "Switched to DC mode!\n"); 1386 - smu_v13_0_ack_ac_dc_interrupt(smu); 1386 + schedule_work(&smu->interrupt_work); 1387 1387 adev->pm.ac_power = false; 1388 1388 break; 1389 1389 case SMU_IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING:
+1
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
··· 3219 3219 .is_asic_wbrf_supported = smu_v13_0_0_wbrf_support_check, 3220 3220 .enable_uclk_shadow = smu_v13_0_enable_uclk_shadow, 3221 3221 .set_wbrf_exclusion_ranges = smu_v13_0_set_wbrf_exclusion_ranges, 3222 + .interrupt_work = smu_v13_0_interrupt_work, 3222 3223 }; 3223 3224 3224 3225 void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu)
+1
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
··· 2797 2797 .is_asic_wbrf_supported = smu_v13_0_7_wbrf_support_check, 2798 2798 .enable_uclk_shadow = smu_v13_0_enable_uclk_shadow, 2799 2799 .set_wbrf_exclusion_ranges = smu_v13_0_set_wbrf_exclusion_ranges, 2800 + .interrupt_work = smu_v13_0_interrupt_work, 2800 2801 }; 2801 2802 2802 2803 void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)