Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: Sanitize apb timer interrupt handling

Disable the interrupt in CPU_DEAD where it belongs. Remove the
open coded irq_desc manipulation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@elte.hu>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>

+24 -30
+24 -30
arch/x86/kernel/apb_timer.c
··· 231 231 apbt_start_counter(phy_cs_timer_id); 232 232 } 233 233 234 - /* Setup IRQ routing via IOAPIC */ 235 - #ifdef CONFIG_SMP 236 - static void apbt_setup_irq(struct apbt_dev *adev) 237 - { 238 - struct irq_chip *chip; 239 - struct irq_desc *desc; 240 - 241 - /* timer0 irq has been setup early */ 242 - if (adev->irq == 0) 243 - return; 244 - desc = irq_to_desc(adev->irq); 245 - chip = get_irq_chip(adev->irq); 246 - disable_irq(adev->irq); 247 - desc->status |= IRQ_MOVE_PCNTXT; 248 - irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); 249 - /* APB timer irqs are set up as mp_irqs, timer is edge triggerred */ 250 - set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge"); 251 - enable_irq(adev->irq); 252 - if (system_state == SYSTEM_BOOTING) 253 - if (request_irq(adev->irq, apbt_interrupt_handler, 254 - IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, 255 - adev->name, adev)) { 256 - printk(KERN_ERR "Failed request IRQ for APBT%d\n", 257 - adev->num); 258 - } 259 - } 260 - #endif 261 - 262 234 static void apbt_enable_int(int n) 263 235 { 264 236 unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); ··· 306 334 } 307 335 308 336 #ifdef CONFIG_SMP 337 + 338 + static void apbt_setup_irq(struct apbt_dev *adev) 339 + { 340 + /* timer0 irq has been setup early */ 341 + if (adev->irq == 0) 342 + return; 343 + 344 + if (system_state == SYSTEM_BOOTING) { 345 + irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); 346 + /* APB timer irqs are set up as mp_irqs, timer is edge type */ 347 + __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); 348 + if (request_irq(adev->irq, apbt_interrupt_handler, 349 + IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, 350 + adev->name, adev)) { 351 + printk(KERN_ERR "Failed request IRQ for APBT%d\n", 352 + adev->num); 353 + } 354 + } else 355 + enable_irq(adev->irq); 356 + } 357 + 309 358 /* Should be called with per cpu */ 310 359 void apbt_setup_secondary_clock(void) 311 360 { ··· 382 389 383 390 switch (action & 0xf) { 384 391 case CPU_DEAD: 392 + disable_irq(adev->irq); 385 393 apbt_disable_int(cpu); 386 - if (system_state == SYSTEM_RUNNING) 394 + if (system_state == SYSTEM_RUNNING) { 387 395 pr_debug("skipping APBT CPU %lu offline\n", cpu); 388 - else if (adev) { 396 + } else if (adev) { 389 397 pr_debug("APBT clockevent for cpu %lu offline\n", cpu); 390 398 free_irq(adev->irq, adev); 391 399 }