aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-14 16:47:05 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-14 16:47:05 -0700
commit59d66ce238e573fe3369427e91a8291f2cf67891 (patch)
tree2d6be8e29e7cceaaa2d1ce9a8957bda103467a7a /kernel
parent5c0d6b34d6ee11ff979cbdac9a59b47a74cb9f43 (diff)
parent89039b37be7c34194db0e72f956a5f02cfa30941 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-x86
* git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-x86: x86: force timer broadcast on late AMD C1E detection x86: move local APIC timer init to the end of start_secondary() clockevents: introduce force broadcast notifier x86: fix missing include for vsyscall
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/tick-broadcast.c29
-rw-r--r--kernel/time/tick-common.c1
2 files changed, 24 insertions, 6 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 298bc7c6f09..fc3fc79b3d5 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -217,26 +217,43 @@ static void tick_do_broadcast_on_off(void *why)
bc = tick_broadcast_device.evtdev;
/*
- * Is the device in broadcast mode forever or is it not
- * affected by the powerstate ?
+ * Is the device not affected by the powerstate ?
*/
- if (!dev || !tick_device_is_functional(dev) ||
- !(dev->features & CLOCK_EVT_FEAT_C3STOP))
+ if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP))
goto out;
- if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_ON) {
+ /*
+ * Defect device ?
+ */
+ if (!tick_device_is_functional(dev)) {
+ /*
+ * AMD C1E wreckage fixup:
+ *
+ * Device was registered functional in the first
+ * place. Now the secondary CPU detected the C1E
+ * misfeature and notifies us to fix it up
+ */
+ if (*reason != CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
+ goto out;
+ }
+
+ switch (*reason) {
+ case CLOCK_EVT_NOTIFY_BROADCAST_ON:
+ case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
if (!cpu_isset(cpu, tick_broadcast_mask)) {
cpu_set(cpu, tick_broadcast_mask);
if (td->mode == TICKDEV_MODE_PERIODIC)
clockevents_set_mode(dev,
CLOCK_EVT_MODE_SHUTDOWN);
}
- } else {
+ break;
+ case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
if (cpu_isset(cpu, tick_broadcast_mask)) {
cpu_clear(cpu, tick_broadcast_mask);
if (td->mode == TICKDEV_MODE_PERIODIC)
tick_setup_periodic(dev, 0);
}
+ break;
}
if (cpus_empty(tick_broadcast_mask))
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index 3f3ae390783..1bea399a9ef 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -345,6 +345,7 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason,
case CLOCK_EVT_NOTIFY_BROADCAST_ON:
case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
+ case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
tick_broadcast_on_off(reason, dev);
break;