diff options
| -rw-r--r-- | arch/x86/include/asm/irq.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 18 | ||||
| -rw-r--r-- | arch/x86/kernel/irq.c | 7 |
3 files changed, 23 insertions, 3 deletions
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index ddda6cbed6f4..ffd700ff5dcb 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
| @@ -34,6 +34,7 @@ static inline int irq_canonicalize(int irq) | |||
| 34 | #ifdef CONFIG_HOTPLUG_CPU | 34 | #ifdef CONFIG_HOTPLUG_CPU |
| 35 | #include <linux/cpumask.h> | 35 | #include <linux/cpumask.h> |
| 36 | extern void fixup_irqs(void); | 36 | extern void fixup_irqs(void); |
| 37 | extern void irq_force_complete_move(int); | ||
| 37 | #endif | 38 | #endif |
| 38 | 39 | ||
| 39 | extern void (*generic_interrupt_extension)(void); | 40 | extern void (*generic_interrupt_extension)(void); |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e9e5b02c3af2..4e886efd9a15 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -2450,21 +2450,33 @@ unlock: | |||
| 2450 | irq_exit(); | 2450 | irq_exit(); |
| 2451 | } | 2451 | } |
| 2452 | 2452 | ||
| 2453 | static void irq_complete_move(struct irq_desc **descp) | 2453 | static void __irq_complete_move(struct irq_desc **descp, unsigned vector) |
| 2454 | { | 2454 | { |
| 2455 | struct irq_desc *desc = *descp; | 2455 | struct irq_desc *desc = *descp; |
| 2456 | struct irq_cfg *cfg = desc->chip_data; | 2456 | struct irq_cfg *cfg = desc->chip_data; |
| 2457 | unsigned vector, me; | 2457 | unsigned me; |
| 2458 | 2458 | ||
| 2459 | if (likely(!cfg->move_in_progress)) | 2459 | if (likely(!cfg->move_in_progress)) |
| 2460 | return; | 2460 | return; |
| 2461 | 2461 | ||
| 2462 | vector = ~get_irq_regs()->orig_ax; | ||
| 2463 | me = smp_processor_id(); | 2462 | me = smp_processor_id(); |
| 2464 | 2463 | ||
| 2465 | if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) | 2464 | if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) |
| 2466 | send_cleanup_vector(cfg); | 2465 | send_cleanup_vector(cfg); |
| 2467 | } | 2466 | } |
| 2467 | |||
| 2468 | static void irq_complete_move(struct irq_desc **descp) | ||
| 2469 | { | ||
| 2470 | __irq_complete_move(descp, ~get_irq_regs()->orig_ax); | ||
| 2471 | } | ||
| 2472 | |||
| 2473 | void irq_force_complete_move(int irq) | ||
| 2474 | { | ||
| 2475 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 2476 | struct irq_cfg *cfg = desc->chip_data; | ||
| 2477 | |||
| 2478 | __irq_complete_move(&desc, cfg->vector); | ||
| 2479 | } | ||
| 2468 | #else | 2480 | #else |
| 2469 | static inline void irq_complete_move(struct irq_desc **descp) {} | 2481 | static inline void irq_complete_move(struct irq_desc **descp) {} |
| 2470 | #endif | 2482 | #endif |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 342bcbca19b4..b10a5e1da06c 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
| @@ -305,6 +305,13 @@ void fixup_irqs(void) | |||
| 305 | continue; | 305 | continue; |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | /* | ||
| 309 | * Complete the irq move. This cpu is going down and for | ||
| 310 | * non intr-remapping case, we can't wait till this interrupt | ||
| 311 | * arrives at this cpu before completing the irq move. | ||
| 312 | */ | ||
| 313 | irq_force_complete_move(irq); | ||
| 314 | |||
| 308 | if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { | 315 | if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { |
| 309 | break_affinity = 1; | 316 | break_affinity = 1; |
| 310 | affinity = cpu_all_mask; | 317 | affinity = cpu_all_mask; |
