Commit 6ea41d25 authored by Thomas Gleixner's avatar Thomas Gleixner

clocksource: Call clocksource_change_rating() outside of watchdog_lock

The changes to the watchdog logic introduced a lock inversion between
watchdog_lock and clocksource_mutex. Change the rating outside of
watchdog_lock to avoid it.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 23970e38
...@@ -307,16 +307,23 @@ static void clocksource_watchdog_work(struct work_struct *work) ...@@ -307,16 +307,23 @@ static void clocksource_watchdog_work(struct work_struct *work)
{ {
struct clocksource *cs, *tmp; struct clocksource *cs, *tmp;
unsigned long flags; unsigned long flags;
LIST_HEAD(unstable);
spin_lock_irqsave(&watchdog_lock, flags); spin_lock_irqsave(&watchdog_lock, flags);
list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list)
if (cs->flags & CLOCK_SOURCE_UNSTABLE) { if (cs->flags & CLOCK_SOURCE_UNSTABLE) {
list_del_init(&cs->wd_list); list_del_init(&cs->wd_list);
clocksource_change_rating(cs, 0); list_add(&cs->wd_list, &unstable);
} }
/* Check if the watchdog timer needs to be stopped. */ /* Check if the watchdog timer needs to be stopped. */
clocksource_stop_watchdog(); clocksource_stop_watchdog();
spin_unlock(&watchdog_lock); spin_unlock_irqrestore(&watchdog_lock, flags);
/* Needs to be done outside of watchdog lock */
list_for_each_entry_safe(cs, tmp, &unstable, wd_list) {
list_del_init(&cs->wd_list);
clocksource_change_rating(cs, 0);
}
} }
#else /* CONFIG_CLOCKSOURCE_WATCHDOG */ #else /* CONFIG_CLOCKSOURCE_WATCHDOG */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment