diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-14 19:47:05 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-14 19:47:05 -0400 |
| commit | 59d66ce238e573fe3369427e91a8291f2cf67891 (patch) | |
| tree | 2d6be8e29e7cceaaa2d1ce9a8957bda103467a7a | |
| parent | 5c0d6b34d6ee11ff979cbdac9a59b47a74cb9f43 (diff) | |
| parent | 89039b37be7c34194db0e72f956a5f02cfa30941 (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
| -rw-r--r-- | arch/x86/kernel/alternative.c | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/apic_64.c | 26 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot_64.c | 7 | ||||
| -rw-r--r-- | include/linux/clockchips.h | 1 | ||||
| -rw-r--r-- | kernel/time/tick-broadcast.c | 29 | ||||
| -rw-r--r-- | kernel/time/tick-common.c | 1 |
6 files changed, 54 insertions, 11 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index bd72d94e713e..11b03d3c6fda 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
| 11 | #include <asm/mce.h> | 11 | #include <asm/mce.h> |
| 12 | #include <asm/nmi.h> | 12 | #include <asm/nmi.h> |
| 13 | #include <asm/vsyscall.h> | ||
| 13 | 14 | ||
| 14 | #define MAX_PATCH_LEN (255-1) | 15 | #define MAX_PATCH_LEN (255-1) |
| 15 | 16 | ||
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 395928de28ea..09b82093bc75 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
| @@ -964,8 +964,34 @@ void __init setup_boot_APIC_clock (void) | |||
| 964 | setup_APIC_timer(); | 964 | setup_APIC_timer(); |
| 965 | } | 965 | } |
| 966 | 966 | ||
| 967 | /* | ||
| 968 | * AMD C1E enabled CPUs have a real nasty problem: Some BIOSes set the | ||
| 969 | * C1E flag only in the secondary CPU, so when we detect the wreckage | ||
| 970 | * we already have enabled the boot CPU local apic timer. Check, if | ||
| 971 | * disable_apic_timer is set and the DUMMY flag is cleared. If yes, | ||
| 972 | * set the DUMMY flag again and force the broadcast mode in the | ||
| 973 | * clockevents layer. | ||
| 974 | */ | ||
| 975 | void __cpuinit check_boot_apic_timer_broadcast(void) | ||
| 976 | { | ||
| 977 | struct clock_event_device *levt = &per_cpu(lapic_events, boot_cpu_id); | ||
| 978 | |||
| 979 | if (!disable_apic_timer || | ||
| 980 | (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY)) | ||
| 981 | return; | ||
| 982 | |||
| 983 | printk(KERN_INFO "AMD C1E detected late. Force timer broadcast.\n"); | ||
| 984 | lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY; | ||
| 985 | levt->features |= CLOCK_EVT_FEAT_DUMMY; | ||
| 986 | |||
| 987 | local_irq_enable(); | ||
| 988 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id); | ||
| 989 | local_irq_disable(); | ||
| 990 | } | ||
| 991 | |||
| 967 | void __cpuinit setup_secondary_APIC_clock(void) | 992 | void __cpuinit setup_secondary_APIC_clock(void) |
| 968 | { | 993 | { |
| 994 | check_boot_apic_timer_broadcast(); | ||
| 969 | setup_APIC_timer(); | 995 | setup_APIC_timer(); |
| 970 | } | 996 | } |
| 971 | 997 | ||
diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index 57ccf7cb6b91..720a7d1f8862 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c | |||
| @@ -335,11 +335,6 @@ void __cpuinit start_secondary(void) | |||
| 335 | */ | 335 | */ |
| 336 | check_tsc_sync_target(); | 336 | check_tsc_sync_target(); |
| 337 | 337 | ||
| 338 | Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); | ||
| 339 | setup_secondary_APIC_clock(); | ||
| 340 | |||
| 341 | Dprintk("cpu %d: enabling apic timer\n", smp_processor_id()); | ||
| 342 | |||
| 343 | if (nmi_watchdog == NMI_IO_APIC) { | 338 | if (nmi_watchdog == NMI_IO_APIC) { |
| 344 | disable_8259A_irq(0); | 339 | disable_8259A_irq(0); |
| 345 | enable_NMI_through_LVT0(NULL); | 340 | enable_NMI_through_LVT0(NULL); |
| @@ -374,6 +369,8 @@ void __cpuinit start_secondary(void) | |||
| 374 | 369 | ||
| 375 | unlock_ipi_call_lock(); | 370 | unlock_ipi_call_lock(); |
| 376 | 371 | ||
| 372 | setup_secondary_APIC_clock(); | ||
| 373 | |||
| 377 | cpu_idle(); | 374 | cpu_idle(); |
| 378 | } | 375 | } |
| 379 | 376 | ||
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index d2ddea926895..c33b0dc28e4d 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h | |||
| @@ -31,6 +31,7 @@ enum clock_event_nofitiers { | |||
| 31 | CLOCK_EVT_NOTIFY_ADD, | 31 | CLOCK_EVT_NOTIFY_ADD, |
| 32 | CLOCK_EVT_NOTIFY_BROADCAST_ON, | 32 | CLOCK_EVT_NOTIFY_BROADCAST_ON, |
| 33 | CLOCK_EVT_NOTIFY_BROADCAST_OFF, | 33 | CLOCK_EVT_NOTIFY_BROADCAST_OFF, |
| 34 | CLOCK_EVT_NOTIFY_BROADCAST_FORCE, | ||
| 34 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, | 35 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, |
| 35 | CLOCK_EVT_NOTIFY_BROADCAST_EXIT, | 36 | CLOCK_EVT_NOTIFY_BROADCAST_EXIT, |
| 36 | CLOCK_EVT_NOTIFY_SUSPEND, | 37 | CLOCK_EVT_NOTIFY_SUSPEND, |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 298bc7c6f09f..fc3fc79b3d59 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) | |||
| 217 | bc = tick_broadcast_device.evtdev; | 217 | bc = tick_broadcast_device.evtdev; |
| 218 | 218 | ||
| 219 | /* | 219 | /* |
| 220 | * Is the device in broadcast mode forever or is it not | 220 | * Is the device not affected by the powerstate ? |
| 221 | * affected by the powerstate ? | ||
| 222 | */ | 221 | */ |
| 223 | if (!dev || !tick_device_is_functional(dev) || | 222 | if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) |
| 224 | !(dev->features & CLOCK_EVT_FEAT_C3STOP)) | ||
| 225 | goto out; | 223 | goto out; |
| 226 | 224 | ||
| 227 | if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_ON) { | 225 | /* |
| 226 | * Defect device ? | ||
| 227 | */ | ||
| 228 | if (!tick_device_is_functional(dev)) { | ||
| 229 | /* | ||
| 230 | * AMD C1E wreckage fixup: | ||
| 231 | * | ||
| 232 | * Device was registered functional in the first | ||
| 233 | * place. Now the secondary CPU detected the C1E | ||
| 234 | * misfeature and notifies us to fix it up | ||
| 235 | */ | ||
| 236 | if (*reason != CLOCK_EVT_NOTIFY_BROADCAST_FORCE) | ||
| 237 | goto out; | ||
| 238 | } | ||
| 239 | |||
| 240 | switch (*reason) { | ||
| 241 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | ||
| 242 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | ||
| 228 | if (!cpu_isset(cpu, tick_broadcast_mask)) { | 243 | if (!cpu_isset(cpu, tick_broadcast_mask)) { |
| 229 | cpu_set(cpu, tick_broadcast_mask); | 244 | cpu_set(cpu, tick_broadcast_mask); |
| 230 | if (td->mode == TICKDEV_MODE_PERIODIC) | 245 | if (td->mode == TICKDEV_MODE_PERIODIC) |
| 231 | clockevents_set_mode(dev, | 246 | clockevents_set_mode(dev, |
| 232 | CLOCK_EVT_MODE_SHUTDOWN); | 247 | CLOCK_EVT_MODE_SHUTDOWN); |
| 233 | } | 248 | } |
| 234 | } else { | 249 | break; |
| 250 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | ||
| 235 | if (cpu_isset(cpu, tick_broadcast_mask)) { | 251 | if (cpu_isset(cpu, tick_broadcast_mask)) { |
| 236 | cpu_clear(cpu, tick_broadcast_mask); | 252 | cpu_clear(cpu, tick_broadcast_mask); |
| 237 | if (td->mode == TICKDEV_MODE_PERIODIC) | 253 | if (td->mode == TICKDEV_MODE_PERIODIC) |
| 238 | tick_setup_periodic(dev, 0); | 254 | tick_setup_periodic(dev, 0); |
| 239 | } | 255 | } |
| 256 | break; | ||
| 240 | } | 257 | } |
| 241 | 258 | ||
| 242 | if (cpus_empty(tick_broadcast_mask)) | 259 | if (cpus_empty(tick_broadcast_mask)) |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 3f3ae3907830..1bea399a9ef0 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, | |||
| 345 | 345 | ||
| 346 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | 346 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: |
| 347 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | 347 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: |
| 348 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | ||
| 348 | tick_broadcast_on_off(reason, dev); | 349 | tick_broadcast_on_off(reason, dev); |
| 349 | break; | 350 | break; |
| 350 | 351 | ||
