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; |