aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/io_apic.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-05-01 13:02:50 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-01 13:02:50 -0400
commit4420471f14b79f2a42e4603be7794ea49b68bca4 (patch)
treed391d25458bc0aa86dcf2823fd6c1464883b0533 /arch/x86/kernel/apic/io_apic.c
parent15e957d08dd4a841359cfec59ecb74041e0097aa (diff)
parente0e42142bab96404de535cceb85d6533d5ad7942 (diff)
Merge branch 'x86/apic' into irq/numa
Conflicts: arch/x86/kernel/apic/io_apic.c Merge reason: non-trivial interaction between ongoing work in io_apic.c and the NUMA migration feature in the irq tree. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-rw-r--r--arch/x86/kernel/apic/io_apic.c341
1 files changed, 150 insertions, 191 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e583291fe6c3..21c30e1121ee 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -489,121 +489,6 @@ static void ioapic_mask_entry(int apic, int pin)
489 spin_unlock_irqrestore(&ioapic_lock, flags); 489 spin_unlock_irqrestore(&ioapic_lock, flags);
490} 490}
491 491
492#ifdef CONFIG_SMP
493static void send_cleanup_vector(struct irq_cfg *cfg)
494{
495 cpumask_var_t cleanup_mask;
496
497 if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
498 unsigned int i;
499 cfg->move_cleanup_count = 0;
500 for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
501 cfg->move_cleanup_count++;
502 for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
503 apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
504 } else {
505 cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
506 cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
507 apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
508 free_cpumask_var(cleanup_mask);
509 }
510 cfg->move_in_progress = 0;
511}
512
513static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
514{
515 int apic, pin;
516 struct irq_pin_list *entry;
517 u8 vector = cfg->vector;
518
519 entry = cfg->irq_2_pin;
520 for (;;) {
521 unsigned int reg;
522
523 if (!entry)
524 break;
525
526 apic = entry->apic;
527 pin = entry->pin;
528 /*
529 * With interrupt-remapping, destination information comes
530 * from interrupt-remapping table entry.
531 */
532 if (!irq_remapped(irq))
533 io_apic_write(apic, 0x11 + pin*2, dest);
534 reg = io_apic_read(apic, 0x10 + pin*2);
535 reg &= ~IO_APIC_REDIR_VECTOR_MASK;
536 reg |= vector;
537 io_apic_modify(apic, 0x10 + pin*2, reg);
538 if (!entry->next)
539 break;
540 entry = entry->next;
541 }
542}
543
544static int
545assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
546
547/*
548 * Either sets desc->affinity to a valid value, and returns
549 * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
550 * leaves desc->affinity untouched.
551 */
552static unsigned int
553set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
554{
555 struct irq_cfg *cfg;
556 unsigned int irq;
557
558 if (!cpumask_intersects(mask, cpu_online_mask))
559 return BAD_APICID;
560
561 irq = desc->irq;
562 cfg = desc->chip_data;
563 if (assign_irq_vector(irq, cfg, mask))
564 return BAD_APICID;
565
566 cpumask_copy(desc->affinity, mask);
567
568 return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
569}
570
571static int
572set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
573{
574 struct irq_cfg *cfg;
575 unsigned long flags;
576 unsigned int dest;
577 unsigned int irq;
578 int ret = -1;
579
580 irq = desc->irq;
581 cfg = desc->chip_data;
582
583 spin_lock_irqsave(&ioapic_lock, flags);
584 dest = set_desc_affinity(desc, mask);
585 if (dest != BAD_APICID) {
586 /* Only the high 8 bits are valid. */
587 dest = SET_APIC_LOGICAL_ID(dest);
588 __target_IO_APIC_irq(irq, dest, cfg);
589 ret = 0;
590 }
591 spin_unlock_irqrestore(&ioapic_lock, flags);
592
593 return ret;
594}
595
596static int
597set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
598{
599 struct irq_desc *desc;
600
601 desc = irq_to_desc(irq);
602
603 return set_ioapic_affinity_irq_desc(desc, mask);
604}
605#endif /* CONFIG_SMP */
606
607/* 492/*
608 * The common case is 1:1 IRQ<->pin mappings. Sometimes there are 493 * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
609 * shared ISA-space IRQs, so we have to support them. We are super 494 * shared ISA-space IRQs, so we have to support them. We are super
@@ -822,7 +707,6 @@ static int __init ioapic_pirq_setup(char *str)
822__setup("pirq=", ioapic_pirq_setup); 707__setup("pirq=", ioapic_pirq_setup);
823#endif /* CONFIG_X86_32 */ 708#endif /* CONFIG_X86_32 */
824 709
825#ifdef CONFIG_INTR_REMAP
826struct IO_APIC_route_entry **alloc_ioapic_entries(void) 710struct IO_APIC_route_entry **alloc_ioapic_entries(void)
827{ 711{
828 int apic; 712 int apic;
@@ -920,20 +804,6 @@ int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
920 return 0; 804 return 0;
921} 805}
922 806
923void reinit_intr_remapped_IO_APIC(int intr_remapping,
924 struct IO_APIC_route_entry **ioapic_entries)
925
926{
927 /*
928 * for now plain restore of previous settings.
929 * TBD: In the case of OS enabling interrupt-remapping,
930 * IO-APIC RTE's need to be setup to point to interrupt-remapping
931 * table entries. for now, do a plain restore, and wait for
932 * the setup_IO_APIC_irqs() to do proper initialization.
933 */
934 restore_IO_APIC_setup(ioapic_entries);
935}
936
937void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries) 807void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
938{ 808{
939 int apic; 809 int apic;
@@ -943,7 +813,6 @@ void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries)
943 813
944 kfree(ioapic_entries); 814 kfree(ioapic_entries);
945} 815}
946#endif
947 816
948/* 817/*
949 * Find the IRQ entry number of a certain pin. 818 * Find the IRQ entry number of a certain pin.
@@ -2332,6 +2201,118 @@ static int ioapic_retrigger_irq(unsigned int irq)
2332 */ 2201 */
2333 2202
2334#ifdef CONFIG_SMP 2203#ifdef CONFIG_SMP
2204static void send_cleanup_vector(struct irq_cfg *cfg)
2205{
2206 cpumask_var_t cleanup_mask;
2207
2208 if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
2209 unsigned int i;
2210 cfg->move_cleanup_count = 0;
2211 for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
2212 cfg->move_cleanup_count++;
2213 for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
2214 apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
2215 } else {
2216 cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
2217 cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
2218 apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
2219 free_cpumask_var(cleanup_mask);
2220 }
2221 cfg->move_in_progress = 0;
2222}
2223
2224static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
2225{
2226 int apic, pin;
2227 struct irq_pin_list *entry;
2228 u8 vector = cfg->vector;
2229
2230 entry = cfg->irq_2_pin;
2231 for (;;) {
2232 unsigned int reg;
2233
2234 if (!entry)
2235 break;
2236
2237 apic = entry->apic;
2238 pin = entry->pin;
2239 /*
2240 * With interrupt-remapping, destination information comes
2241 * from interrupt-remapping table entry.
2242 */
2243 if (!irq_remapped(irq))
2244 io_apic_write(apic, 0x11 + pin*2, dest);
2245 reg = io_apic_read(apic, 0x10 + pin*2);
2246 reg &= ~IO_APIC_REDIR_VECTOR_MASK;
2247 reg |= vector;
2248 io_apic_modify(apic, 0x10 + pin*2, reg);
2249 if (!entry->next)
2250 break;
2251 entry = entry->next;
2252 }
2253}
2254
2255static int
2256assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
2257
2258/*
2259 * Either sets desc->affinity to a valid value, and returns
2260 * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
2261 * leaves desc->affinity untouched.
2262 */
2263static unsigned int
2264set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
2265{
2266 struct irq_cfg *cfg;
2267 unsigned int irq;
2268
2269 if (!cpumask_intersects(mask, cpu_online_mask))
2270 return BAD_APICID;
2271
2272 irq = desc->irq;
2273 cfg = desc->chip_data;
2274 if (assign_irq_vector(irq, cfg, mask))
2275 return BAD_APICID;
2276
2277 cpumask_copy(desc->affinity, mask);
2278
2279 return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
2280}
2281
2282static int
2283set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
2284{
2285 struct irq_cfg *cfg;
2286 unsigned long flags;
2287 unsigned int dest;
2288 unsigned int irq;
2289 int ret = -1;
2290
2291 irq = desc->irq;
2292 cfg = desc->chip_data;
2293
2294 spin_lock_irqsave(&ioapic_lock, flags);
2295 dest = set_desc_affinity(desc, mask);
2296 if (dest != BAD_APICID) {
2297 /* Only the high 8 bits are valid. */
2298 dest = SET_APIC_LOGICAL_ID(dest);
2299 __target_IO_APIC_irq(irq, dest, cfg);
2300 ret = 0;
2301 }
2302 spin_unlock_irqrestore(&ioapic_lock, flags);
2303
2304 return ret;
2305}
2306
2307static int
2308set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
2309{
2310 struct irq_desc *desc;
2311
2312 desc = irq_to_desc(irq);
2313
2314 return set_ioapic_affinity_irq_desc(desc, mask);
2315}
2335 2316
2336#ifdef CONFIG_INTR_REMAP 2317#ifdef CONFIG_INTR_REMAP
2337 2318
@@ -2478,53 +2459,6 @@ static void irq_complete_move(struct irq_desc **descp)
2478static inline void irq_complete_move(struct irq_desc **descp) {} 2459static inline void irq_complete_move(struct irq_desc **descp) {}
2479#endif 2460#endif
2480 2461
2481static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
2482{
2483 int apic, pin;
2484 struct irq_pin_list *entry;
2485
2486 entry = cfg->irq_2_pin;
2487 for (;;) {
2488
2489 if (!entry)
2490 break;
2491
2492 apic = entry->apic;
2493 pin = entry->pin;
2494 io_apic_eoi(apic, pin);
2495 entry = entry->next;
2496 }
2497}
2498
2499static void
2500eoi_ioapic_irq(struct irq_desc *desc)
2501{
2502 struct irq_cfg *cfg;
2503 unsigned long flags;
2504 unsigned int irq;
2505
2506 irq = desc->irq;
2507 cfg = desc->chip_data;
2508
2509 spin_lock_irqsave(&ioapic_lock, flags);
2510 __eoi_ioapic_irq(irq, cfg);
2511 spin_unlock_irqrestore(&ioapic_lock, flags);
2512}
2513
2514#ifdef CONFIG_X86_X2APIC
2515static void ack_x2apic_level(unsigned int irq)
2516{
2517 struct irq_desc *desc = irq_to_desc(irq);
2518 ack_x2APIC_irq();
2519 eoi_ioapic_irq(desc);
2520}
2521
2522static void ack_x2apic_edge(unsigned int irq)
2523{
2524 ack_x2APIC_irq();
2525}
2526#endif
2527
2528static void ack_apic_edge(unsigned int irq) 2462static void ack_apic_edge(unsigned int irq)
2529{ 2463{
2530 struct irq_desc *desc = irq_to_desc(irq); 2464 struct irq_desc *desc = irq_to_desc(irq);
@@ -2588,9 +2522,6 @@ static void ack_apic_level(unsigned int irq)
2588 */ 2522 */
2589 ack_APIC_irq(); 2523 ack_APIC_irq();
2590 2524
2591 if (irq_remapped(irq))
2592 eoi_ioapic_irq(desc);
2593
2594 /* Now we can move and renable the irq */ 2525 /* Now we can move and renable the irq */
2595 if (unlikely(do_unmask_irq)) { 2526 if (unlikely(do_unmask_irq)) {
2596 /* Only migrate the irq if the ack has been received. 2527 /* Only migrate the irq if the ack has been received.
@@ -2637,22 +2568,50 @@ static void ack_apic_level(unsigned int irq)
2637} 2568}
2638 2569
2639#ifdef CONFIG_INTR_REMAP 2570#ifdef CONFIG_INTR_REMAP
2571static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
2572{
2573 int apic, pin;
2574 struct irq_pin_list *entry;
2575
2576 entry = cfg->irq_2_pin;
2577 for (;;) {
2578
2579 if (!entry)
2580 break;
2581
2582 apic = entry->apic;
2583 pin = entry->pin;
2584 io_apic_eoi(apic, pin);
2585 entry = entry->next;
2586 }
2587}
2588
2589static void
2590eoi_ioapic_irq(struct irq_desc *desc)
2591{
2592 struct irq_cfg *cfg;
2593 unsigned long flags;
2594 unsigned int irq;
2595
2596 irq = desc->irq;
2597 cfg = desc->chip_data;
2598
2599 spin_lock_irqsave(&ioapic_lock, flags);
2600 __eoi_ioapic_irq(irq, cfg);
2601 spin_unlock_irqrestore(&ioapic_lock, flags);
2602}
2603
2640static void ir_ack_apic_edge(unsigned int irq) 2604static void ir_ack_apic_edge(unsigned int irq)
2641{ 2605{
2642#ifdef CONFIG_X86_X2APIC 2606 ack_APIC_irq();
2643 if (x2apic_enabled())
2644 return ack_x2apic_edge(irq);
2645#endif
2646 return ack_apic_edge(irq);
2647} 2607}
2648 2608
2649static void ir_ack_apic_level(unsigned int irq) 2609static void ir_ack_apic_level(unsigned int irq)
2650{ 2610{
2651#ifdef CONFIG_X86_X2APIC 2611 struct irq_desc *desc = irq_to_desc(irq);
2652 if (x2apic_enabled()) 2612
2653 return ack_x2apic_level(irq); 2613 ack_APIC_irq();
2654#endif 2614 eoi_ioapic_irq(desc);
2655 return ack_apic_level(irq);
2656} 2615}
2657#endif /* CONFIG_INTR_REMAP */ 2616#endif /* CONFIG_INTR_REMAP */
2658 2617