[PATCH 1/2] clocksource/drivers/timer-ti-dm: Unregister CPU PM notifier outside of the timer lock
From: Bradley Morgan
Date: Thu Aug 13 2026 - 03:44:26 EST
omap_dm_timer_remove() calls cpu_pm_unregister_notifier() with
dm_timer_lock held and interrupts disabled. Nothing sleeps in there
today, but it pins the helper into a context where it can never be
allowed to sleep, which is in the way of restoring the RCU grace
period on the cpu_pm notifier chain.
Do the list lookup under the lock and move the unregister after the
unlock. Nothing can race it at that point: remove() owns the device,
and once the timer is off the list nobody can reach it anymore.
Signed-off-by: Bradley Morgan <include@xxxxxxxxx>
---
drivers/clocksource/timer-ti-dm.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index bd06afb7d522..032e102bdd0a 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -1530,7 +1530,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
*/
static void omap_dm_timer_remove(struct platform_device *pdev)
{
- struct dmtimer *timer;
+ struct dmtimer *timer, *found = NULL;
unsigned long flags;
int ret = -EINVAL;
@@ -1538,14 +1538,17 @@ static void omap_dm_timer_remove(struct platform_device *pdev)
list_for_each_entry(timer, &omap_timer_list, node)
if (!strcmp(dev_name(&timer->pdev->dev),
dev_name(&pdev->dev))) {
- if (!(timer->capability & OMAP_TIMER_ALWON))
- cpu_pm_unregister_notifier(&timer->nb);
list_del(&timer->node);
+ found = timer;
ret = 0;
break;
}
spin_unlock_irqrestore(&dm_timer_lock, flags);
+ /* Unregister outside the lock: cpu_pm_unregister_notifier() may sleep. */
+ if (found && !(found->capability & OMAP_TIMER_ALWON))
+ cpu_pm_unregister_notifier(&found->nb);
+
pm_runtime_disable(&pdev->dev);
if (ret)
--
2.47.3