mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
pds_core: keep the health thread stopped during reset
Commitd9407ff118("pds_core: Prevent health thread from running during reset/remove") stops the health thread with cancel_work_sync() before a reset, but a devcmd timeout during pdsc_fw_down() re-queues health_work, so pdsc_health_thread() runs again mid-reset and double allocates the core DMA queues via pdsc_fw_up(). Only the reset path is affected: on remove PDSC_S_STOPPING_DRIVER gates the health thread and the workqueue is destroyed. Use disable_work_sync() to cancel health_work and block further queue_work() on it, and enable_work() in pdsc_restart_health_thread() to re-allow it after the reset. disable_work_sync() keeps a disable depth, so every disable must be matched by one enable. pdsc_reset_prepare() stops the health thread and pdsc_reset_done() restarts it. On the AER path pdsc_pci_error_detected() calls pdsc_reset_prepare(), then pdsc_pci_error_resume() re-inits via pci_reset_function_locked() (pds_core has no .slot_reset handler), which runs the pair again - stopping the thread twice but restarting it once. Gate the disable and enable on a health_stopped flag so each fires at most once per stopped/running transition. Fixes:d9407ff118("pds_core: Prevent health thread from running during reset/remove") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/20260727164548.359562-1-nikhil.rao@amd.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
6ddfba2ea9
commit
cd09971dcc
@@ -171,6 +171,7 @@ struct pdsc {
|
||||
struct timer_list wdtimer;
|
||||
unsigned int wdtimer_period;
|
||||
struct work_struct health_work;
|
||||
bool health_stopped;
|
||||
struct devlink_health_reporter *fw_reporter;
|
||||
u32 fw_recoveries;
|
||||
|
||||
|
||||
@@ -470,8 +470,10 @@ static void pdsc_stop_health_thread(struct pdsc *pdsc)
|
||||
return;
|
||||
|
||||
timer_shutdown_sync(&pdsc->wdtimer);
|
||||
if (pdsc->health_work.func)
|
||||
cancel_work_sync(&pdsc->health_work);
|
||||
if (pdsc->health_work.func && !pdsc->health_stopped) {
|
||||
disable_work_sync(&pdsc->health_work);
|
||||
pdsc->health_stopped = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void pdsc_restart_health_thread(struct pdsc *pdsc)
|
||||
@@ -479,6 +481,10 @@ static void pdsc_restart_health_thread(struct pdsc *pdsc)
|
||||
if (pdsc->pdev->is_virtfn)
|
||||
return;
|
||||
|
||||
if (pdsc->health_stopped) {
|
||||
enable_work(&pdsc->health_work);
|
||||
pdsc->health_stopped = false;
|
||||
}
|
||||
timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
|
||||
mod_timer(&pdsc->wdtimer, jiffies + 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user