aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-09-22 13:04:02 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-09-23 05:38:53 -0400
commit27ce4cb4a0c7cf59b9a9952266883862f2e4c99f (patch)
tree066245d42877d8535853e3199b33cdf1110eb8e4
parent302745699c1b675b5d2a1af87271de10e4d96b6a (diff)
clockevents: prevent mode mismatch on cpu online
Impact: timer hang on CPU online observed on AMD C1E systems When a CPU is brought online then the broadcast machinery can be in the one shot state already. Check this and setup the timer device of the new CPU in one shot mode so the broadcast code can pick up the next_event value correctly. Another AMD C1E oddity, as we switch to broadcast immediately and not after the full bring up via the ACPI cpu idle code. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--kernel/time/tick-broadcast.c8
-rw-r--r--kernel/time/tick-common.c3
-rw-r--r--kernel/time/tick-internal.h2
3 files changed, 12 insertions, 1 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index e2b66d1c8ca5..bd7034542399 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -575,4 +575,12 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
575 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 575 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
576} 576}
577 577
578/*
579 * Check, whether the broadcast device is in one shot mode
580 */
581int tick_broadcast_oneshot_active(void)
582{
583 return tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT;
584}
585
578#endif 586#endif
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index b523d095decf..df12434b43ca 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -109,7 +109,8 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
109 if (!tick_device_is_functional(dev)) 109 if (!tick_device_is_functional(dev))
110 return; 110 return;
111 111
112 if (dev->features & CLOCK_EVT_FEAT_PERIODIC) { 112 if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) &&
113 !tick_broadcast_oneshot_active()) {
113 clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC); 114 clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC);
114 } else { 115 } else {
115 unsigned long seq; 116 unsigned long seq;
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index e18014fadf95..55c3f4be6077 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -35,6 +35,7 @@ extern void tick_broadcast_oneshot_control(unsigned long reason);
35extern void tick_broadcast_switch_to_oneshot(void); 35extern void tick_broadcast_switch_to_oneshot(void);
36extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup); 36extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
37extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc); 37extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
38extern int tick_broadcast_oneshot_active(void);
38# else /* BROADCAST */ 39# else /* BROADCAST */
39static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) 40static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
40{ 41{
@@ -43,6 +44,7 @@ static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
43static inline void tick_broadcast_oneshot_control(unsigned long reason) { } 44static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
44static inline void tick_broadcast_switch_to_oneshot(void) { } 45static inline void tick_broadcast_switch_to_oneshot(void) { }
45static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { } 46static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
47static inline int tick_broadcast_oneshot_active(void) { return 0; }
46# endif /* !BROADCAST */ 48# endif /* !BROADCAST */
47 49
48#else /* !ONESHOT */ 50#else /* !ONESHOT */