x86, mrst: Fix APB timer per cpu clockevent

The current APB timer code incorrectly registers a static copy of the
clockevent device for the boot CPU. The per cpu clockevent should be
used instead.

This bug was hidden by zero-initialized data; as such it did not get
exposed in testing, but was discovered by code review.

Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
LKML-Reference: <1267592494-7723-1-git-send-email-jacob.jun.pan@linux.intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>

authored by Jacob Pan and committed by H. Peter Anvin 3010673e d8111cd9

+8 -4
+8 -4
arch/x86/kernel/apb_timer.c
··· 84 84 85 85 int disable_apbt_percpu __cpuinitdata; 86 86 87 + static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); 88 + 87 89 #ifdef CONFIG_SMP 88 90 static unsigned int apbt_num_timers_used; 89 - static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); 90 91 static struct apbt_dev *apbt_devs; 91 92 #endif 92 93 ··· 303 302 static int __init apbt_clockevent_register(void) 304 303 { 305 304 struct sfi_timer_table_entry *mtmr; 305 + struct apbt_dev *adev = &__get_cpu_var(cpu_apbt_dev); 306 306 307 307 mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM); 308 308 if (mtmr == NULL) { ··· 331 329 * global if not used for per cpu timer. 332 330 */ 333 331 apbt_clockevent.cpumask = cpumask_of(smp_processor_id()); 332 + adev->num = smp_processor_id(); 333 + memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device)); 334 334 335 335 if (disable_apbt_percpu) { 336 336 apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100; 337 - global_clock_event = &apbt_clockevent; 337 + global_clock_event = &adev->evt; 338 338 printk(KERN_DEBUG "%s clockevent registered as global\n", 339 339 global_clock_event->name); 340 340 } 341 341 342 342 if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler, 343 343 IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, 344 - apbt_clockevent.name, &apbt_clockevent)) { 344 + apbt_clockevent.name, adev)) { 345 345 printk(KERN_ERR "Failed request IRQ for APBT%d\n", 346 346 apbt_clockevent.irq); 347 347 } 348 348 349 - clockevents_register_device(&apbt_clockevent); 349 + clockevents_register_device(&adev->evt); 350 350 /* Start APBT 0 interrupts */ 351 351 apbt_enable_int(APBT_CLOCKEVENT0_NUM); 352 352