mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
thermal/drivers/ti-soc-thermal: Cancel pending alert work on remove
On a threshold crossing, the talert IRQ handler calls
ti_thermal_report_sensor_temperature(), which queues the work embedded
in the sensor's ti_thermal_data on the system workqueue. Nothing ever
cancels or flushes that work.
ti_bandgap_remove() frees the talert IRQ last. free_irq() waits for a
running handler, but not for the work the handler has queued. When
remove returns, devres unregisters and frees the thermal zones and then
frees the devm-allocated ti_thermal_data, so a work item that is still
pending runs ti_thermal_work() on freed memory:
ti_thermal_work()
data = container_of(work, struct ti_thermal_data, thermal_wq);
thermal_zone_device_update(data->ti_thermal, ...);
Free the talert IRQ before removing the sensors, so that no new work
can be queued, and cancel the work in ti_thermal_remove_sensor().
This needs an OMAP4460/4470 or OMAP5 SoC (DRA7 has TALERT but no
->report_temperature, so it never queues the work), a threshold crossing
just before the driver is unbound or unloaded, and the work still
pending when devres frees the data.
Found by static analysis tool CodeQL.
Fixes: 445eaf871b ("staging: omap-thermal: common code to expose driver to thermal framework")
Assisted-by: LLM codeql
Signed-off-by: Weigang He <geoffreyhe2@gmail.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@kernel.org>
Acked-by: Keerthy <j-keerthy@ti.com>
Link: https://patch.msgid.link/20260926124931.3599746-1-geoffreyhe2@gmail.com
This commit is contained in:
parent
51c262cf2a
commit
aaa6c8dec4
|
|
@ -1077,6 +1077,10 @@ void ti_bandgap_remove(struct platform_device *pdev)
|
|||
if (!soc_device_match(soc_no_cpu_notifier))
|
||||
cpu_pm_unregister_notifier(&bgp->nb);
|
||||
|
||||
/* Stop the alerts first: they queue work on the sensors' data */
|
||||
if (TI_BANDGAP_HAS(bgp, TALERT))
|
||||
free_irq(bgp->irq, bgp);
|
||||
|
||||
/* Remove sensor interfaces */
|
||||
for (i = 0; i < bgp->conf->sensor_count; i++) {
|
||||
if (bgp->conf->sensors[i].unregister_cooling)
|
||||
|
|
@ -1093,9 +1097,6 @@ void ti_bandgap_remove(struct platform_device *pdev)
|
|||
clk_put(bgp->fclock);
|
||||
clk_put(bgp->div_clk);
|
||||
|
||||
if (TI_BANDGAP_HAS(bgp, TALERT))
|
||||
free_irq(bgp->irq, bgp);
|
||||
|
||||
if (TI_BANDGAP_HAS(bgp, TSHUT))
|
||||
free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,10 @@ int ti_thermal_remove_sensor(struct ti_bandgap *bgp, int id)
|
|||
|
||||
data = ti_bandgap_get_sensor_data(bgp, id);
|
||||
|
||||
/* Work queued by the talert IRQ must not outlive the data */
|
||||
if (!IS_ERR_OR_NULL(data))
|
||||
cancel_work_sync(&data->thermal_wq);
|
||||
|
||||
if (!IS_ERR_OR_NULL(data) && data->ti_thermal) {
|
||||
if (data->our_zone)
|
||||
thermal_zone_device_unregister(data->ti_thermal);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user