aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/tsc.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-08-28 14:25:24 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-08-28 14:25:24 -0400
commit7285dd7fd375763bfb8ab1ac9cf3f1206f503c16 (patch)
tree42f809ab3616cc3d93d655acccfc2d54e9f6d0e4 /arch/x86/kernel/tsc.c
parent90cba64a5f672a239f43ec5cb9a11b806887331e (diff)
clocksource: Resolve cpu hotplug dead lock with TSC unstable
Martin Schwidefsky analyzed it: To register a clocksource the clocksource_mutex is acquired and if necessary timekeeping_notify is called to install the clocksource as the timekeeper clock. timekeeping_notify uses stop_machine which needs to take cpu_add_remove_lock mutex. Starting a new cpu is done with the cpu_add_remove_lock mutex held. native_cpu_up checks the tsc of the new cpu and if the tsc is no good clocksource_change_rating is called. Which needs the clocksource_mutex and the deadlock is complete. The solution is to replace the TSC via the clocksource watchdog mechanism. Mark the TSC as unstable and schedule the watchdog work so it gets removed in the watchdog thread context. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> LKML-Reference: <new-submission> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: John Stultz <johnstul@us.ibm.com>
Diffstat (limited to 'arch/x86/kernel/tsc.c')
-rw-r--r--arch/x86/kernel/tsc.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 968425422c46..fc3672a303d6 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -767,12 +767,14 @@ void mark_tsc_unstable(char *reason)
767{ 767{
768 if (!tsc_unstable) { 768 if (!tsc_unstable) {
769 tsc_unstable = 1; 769 tsc_unstable = 1;
770 printk("Marking TSC unstable due to %s\n", reason); 770 printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
771 /* Change only the rating, when not registered */ 771 /* Change only the rating, when not registered */
772 if (clocksource_tsc.mult) 772 if (clocksource_tsc.mult)
773 clocksource_change_rating(&clocksource_tsc, 0); 773 clocksource_mark_unstable(&clocksource_tsc);
774 else 774 else {
775 clocksource_tsc.flags |= CLOCK_SOURCE_UNSTABLE;
775 clocksource_tsc.rating = 0; 776 clocksource_tsc.rating = 0;
777 }
776 } 778 }
777} 779}
778 780