aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2011-08-25 15:01:13 -0400
committerIngo Molnar <mingo@elte.hu>2011-09-21 04:26:28 -0400
commitc020570138f5d9cb1fc0a853f9cf9e641178b5c5 (patch)
treeff696be9affd2e192878c6842452b772e8746d24
parente57253a81d9cc7049e9e43bd806ce6cdd297ec1c (diff)
x86, ioapic: Consolidate the explicit EOI code
Consolidate the io-apic EOI code in clear_IO_APIC_pin() and eoi_ioapic_irq(). Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: Thomas Renninger <trenn@suse.de> Cc: Rafael Wysocki <rjw@novell.com> Cc: Maciej W. Rozycki <macro@linux-mips.org> Cc: lchiquitto@novell.com Cc: jbeulich@novell.com Cc: yinghai@kernel.org Link: http://lkml.kernel.org/r/20110825190657.259696697@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/apic/io_apic.c139
1 files changed, 65 insertions, 74 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 85050c9ab755..229e19f3eb57 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -581,6 +581,66 @@ static void unmask_ioapic_irq(struct irq_data *data)
581 unmask_ioapic(data->chip_data); 581 unmask_ioapic(data->chip_data);
582} 582}
583 583
584/*
585 * IO-APIC versions below 0x20 don't support EOI register.
586 * For the record, here is the information about various versions:
587 * 0Xh 82489DX
588 * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
589 * 2Xh I/O(x)APIC which is PCI 2.2 Compliant
590 * 30h-FFh Reserved
591 *
592 * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
593 * version as 0x2. This is an error with documentation and these ICH chips
594 * use io-apic's of version 0x20.
595 *
596 * For IO-APIC's with EOI register, we use that to do an explicit EOI.
597 * Otherwise, we simulate the EOI message manually by changing the trigger
598 * mode to edge and then back to level, with RTE being masked during this.
599 */
600static void __eoi_ioapic_pin(int apic, int pin, int vector, struct irq_cfg *cfg)
601{
602 if (mpc_ioapic_ver(apic) >= 0x20) {
603 /*
604 * Intr-remapping uses pin number as the virtual vector
605 * in the RTE. Actual vector is programmed in
606 * intr-remapping table entry. Hence for the io-apic
607 * EOI we use the pin number.
608 */
609 if (cfg && irq_remapped(cfg))
610 io_apic_eoi(apic, pin);
611 else
612 io_apic_eoi(apic, vector);
613 } else {
614 struct IO_APIC_route_entry entry, entry1;
615
616 entry = entry1 = __ioapic_read_entry(apic, pin);
617
618 /*
619 * Mask the entry and change the trigger mode to edge.
620 */
621 entry1.mask = 1;
622 entry1.trigger = IOAPIC_EDGE;
623
624 __ioapic_write_entry(apic, pin, entry1);
625
626 /*
627 * Restore the previous level triggered entry.
628 */
629 __ioapic_write_entry(apic, pin, entry);
630 }
631}
632
633static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
634{
635 struct irq_pin_list *entry;
636 unsigned long flags;
637
638 raw_spin_lock_irqsave(&ioapic_lock, flags);
639 for_each_irq_pin(entry, cfg->irq_2_pin)
640 __eoi_ioapic_pin(entry->apic, entry->pin, cfg->vector, cfg);
641 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
642}
643
584static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) 644static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
585{ 645{
586 struct IO_APIC_route_entry entry; 646 struct IO_APIC_route_entry entry;
@@ -601,6 +661,8 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
601 } 661 }
602 662
603 if (entry.irr) { 663 if (entry.irr) {
664 unsigned long flags;
665
604 /* 666 /*
605 * Make sure the trigger mode is set to level. Explicit EOI 667 * Make sure the trigger mode is set to level. Explicit EOI
606 * doesn't clear the remote-IRR if the trigger mode is not 668 * doesn't clear the remote-IRR if the trigger mode is not
@@ -611,23 +673,9 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
611 ioapic_write_entry(apic, pin, entry); 673 ioapic_write_entry(apic, pin, entry);
612 } 674 }
613 675
614 if (mpc_ioapic_ver(apic) >= 0x20) { 676 raw_spin_lock_irqsave(&ioapic_lock, flags);
615 unsigned long flags; 677 __eoi_ioapic_pin(apic, pin, entry.vector, NULL);
616 678 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
617 raw_spin_lock_irqsave(&ioapic_lock, flags);
618 io_apic_eoi(apic, entry.vector);
619 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
620 } else {
621 /*
622 * Mechanism by which we clear remote-IRR in this
623 * case is by changing the trigger mode to edge and
624 * back to level.
625 */
626 entry.trigger = IOAPIC_EDGE;
627 ioapic_write_entry(apic, pin, entry);
628 entry.trigger = IOAPIC_LEVEL;
629 ioapic_write_entry(apic, pin, entry);
630 }
631 } 679 }
632 680
633 /* 681 /*
@@ -2457,63 +2505,6 @@ static void ack_apic_edge(struct irq_data *data)
2457 2505
2458atomic_t irq_mis_count; 2506atomic_t irq_mis_count;
2459 2507
2460/*
2461 * IO-APIC versions below 0x20 don't support EOI register.
2462 * For the record, here is the information about various versions:
2463 * 0Xh 82489DX
2464 * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
2465 * 2Xh I/O(x)APIC which is PCI 2.2 Compliant
2466 * 30h-FFh Reserved
2467 *
2468 * Some of the Intel ICH Specs (ICH2 to ICH5) documents the io-apic
2469 * version as 0x2. This is an error with documentation and these ICH chips
2470 * use io-apic's of version 0x20.
2471 *
2472 * For IO-APIC's with EOI register, we use that to do an explicit EOI.
2473 * Otherwise, we simulate the EOI message manually by changing the trigger
2474 * mode to edge and then back to level, with RTE being masked during this.
2475*/
2476static void eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
2477{
2478 struct irq_pin_list *entry;
2479 unsigned long flags;
2480
2481 raw_spin_lock_irqsave(&ioapic_lock, flags);
2482 for_each_irq_pin(entry, cfg->irq_2_pin) {
2483 if (mpc_ioapic_ver(entry->apic) >= 0x20) {
2484 /*
2485 * Intr-remapping uses pin number as the virtual vector
2486 * in the RTE. Actual vector is programmed in
2487 * intr-remapping table entry. Hence for the io-apic
2488 * EOI we use the pin number.
2489 */
2490 if (irq_remapped(cfg))
2491 io_apic_eoi(entry->apic, entry->pin);
2492 else
2493 io_apic_eoi(entry->apic, cfg->vector);
2494 } else {
2495 struct IO_APIC_route_entry rte, rte1;
2496
2497 rte = rte1 =
2498 __ioapic_read_entry(entry->apic, entry->pin);
2499
2500 /*
2501 * Mask the entry and change the trigger mode to edge.
2502 */
2503 rte1.mask = 1;
2504 rte1.trigger = IOAPIC_EDGE;
2505
2506 __ioapic_write_entry(apic, pin, rte1);
2507
2508 /*
2509 * Restore the previous level triggered entry.
2510 */
2511 __ioapic_write_entry(apic, pin, rte);
2512 }
2513 }
2514 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
2515}
2516
2517static void ack_apic_level(struct irq_data *data) 2508static void ack_apic_level(struct irq_data *data)
2518{ 2509{
2519 struct irq_cfg *cfg = data->chip_data; 2510 struct irq_cfg *cfg = data->chip_data;