Each thermal zone carries a work_struct that the BPMP thermal message handler queues on the system workqueue whenever the firmware reports a trip point crossing. The work handler tz_device_update_work_fn() recovers the zone with container_of() and calls thermal_zone_device_update() on its thermal zone device. tegra_bpmp_thermal_remove() only unregisters the mrq handler with tegra_bpmp_free_mrq(). That stops new trip messages from being dispatched, but it does not drain work that was already queued. After the remove callback returns, devm releases the zones, and a pending trip update work can then run and dereference the freed zone. Cancel the per-zone works after tegra_bpmp_free_mrq(), which guarantees no new instance can be queued: mrq handlers are dispatched under the same bpmp->lock that tegra_bpmp_free_mrq() holds. This issue was found by an in-house static analysis tool. Fixes: 7afebede62be ("thermal: Add Tegra BPMP thermal sensor driver") Cc: stable@vger.kernel.org Assisted-by: Codex:gpt-5.6 Co-developed-by: Song Li Signed-off-by: Song Li Signed-off-by: Fan Wu --- drivers/thermal/tegra/tegra-bpmp-thermal.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/tegra/tegra-bpmp-thermal.c b/drivers/thermal/tegra/tegra-bpmp-thermal.c index 997d77ce30d..7ad46b34e17 100644 --- a/drivers/thermal/tegra/tegra-bpmp-thermal.c +++ b/drivers/thermal/tegra/tegra-bpmp-thermal.c @@ -303,8 +303,12 @@ static int tegra_bpmp_thermal_probe(struct platform_device *pdev) static void tegra_bpmp_thermal_remove(struct platform_device *pdev) { struct tegra_bpmp_thermal *tegra = platform_get_drvdata(pdev); + unsigned int i; tegra_bpmp_free_mrq(tegra->bpmp, MRQ_THERMAL, tegra); + + for (i = 0; i < tegra->num_zones; ++i) + cancel_work_sync(&tegra->zones[i]->tz_device_update_work); } static const struct of_device_id tegra_bpmp_thermal_of_match[] = {