aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic_32.c
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel@gmail.com>2008-08-19 23:50:34 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-16 10:52:54 -0400
commit1d02519242c23450b043e5e8a9e3cb84a8666fe3 (patch)
tree4a9d55644edf712ba4a09607ffb2d51966527a7f /arch/x86/kernel/io_apic_32.c
parentd83e94acd95789829804fd9e442bd18975f4dc89 (diff)
x86: ordering functions in io_apic_32.c
prepare for unification: try to make functions be of the same order to io_apic_64.c. v2: add calling setup_msi_irq back to arch_setup_msi_irq Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/io_apic_32.c')
-rw-r--r--arch/x86/kernel/io_apic_32.c178
1 files changed, 94 insertions, 84 deletions
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c
index 353e586822af..9531ef33362b 100644
--- a/arch/x86/kernel/io_apic_32.c
+++ b/arch/x86/kernel/io_apic_32.c
@@ -1029,23 +1029,6 @@ static int pin_2_irq(int idx, int apic, int pin)
1029 return irq; 1029 return irq;
1030} 1030}
1031 1031
1032static inline int IO_APIC_irq_trigger(int irq)
1033{
1034 int apic, idx, pin;
1035
1036 for (apic = 0; apic < nr_ioapics; apic++) {
1037 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
1038 idx = find_irq_entry(apic, pin, mp_INT);
1039 if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
1040 return irq_trigger(idx);
1041 }
1042 }
1043 /*
1044 * nonexistent IRQs are edge default
1045 */
1046 return 0;
1047}
1048
1049void lock_vector_lock(void) 1032void lock_vector_lock(void)
1050{ 1033{
1051 /* Used to the online set of cpus does not change 1034 /* Used to the online set of cpus does not change
@@ -1190,6 +1173,23 @@ static struct irq_chip ioapic_chip;
1190#define IOAPIC_EDGE 0 1173#define IOAPIC_EDGE 0
1191#define IOAPIC_LEVEL 1 1174#define IOAPIC_LEVEL 1
1192 1175
1176static inline int IO_APIC_irq_trigger(int irq)
1177{
1178 int apic, idx, pin;
1179
1180 for (apic = 0; apic < nr_ioapics; apic++) {
1181 for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
1182 idx = find_irq_entry(apic, pin, mp_INT);
1183 if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin)))
1184 return irq_trigger(idx);
1185 }
1186 }
1187 /*
1188 * nonexistent IRQs are edge default
1189 */
1190 return 0;
1191}
1192
1193static void ioapic_register_intr(int irq, unsigned long trigger) 1193static void ioapic_register_intr(int irq, unsigned long trigger)
1194{ 1194{
1195 struct irq_desc *desc; 1195 struct irq_desc *desc;
@@ -1926,55 +1926,6 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
1926 return was_pending; 1926 return was_pending;
1927} 1927}
1928 1928
1929static void irq_complete_move(unsigned int irq);
1930static void ack_ioapic_irq(unsigned int irq)
1931{
1932 irq_complete_move(irq);
1933 move_native_irq(irq);
1934 ack_APIC_irq();
1935}
1936
1937static void ack_ioapic_quirk_irq(unsigned int irq)
1938{
1939 unsigned long v;
1940 int i;
1941
1942 irq_complete_move(irq);
1943 move_native_irq(irq);
1944/*
1945 * It appears there is an erratum which affects at least version 0x11
1946 * of I/O APIC (that's the 82093AA and cores integrated into various
1947 * chipsets). Under certain conditions a level-triggered interrupt is
1948 * erroneously delivered as edge-triggered one but the respective IRR
1949 * bit gets set nevertheless. As a result the I/O unit expects an EOI
1950 * message but it will never arrive and further interrupts are blocked
1951 * from the source. The exact reason is so far unknown, but the
1952 * phenomenon was observed when two consecutive interrupt requests
1953 * from a given source get delivered to the same CPU and the source is
1954 * temporarily disabled in between.
1955 *
1956 * A workaround is to simulate an EOI message manually. We achieve it
1957 * by setting the trigger mode to edge and then to level when the edge
1958 * trigger mode gets detected in the TMR of a local APIC for a
1959 * level-triggered interrupt. We mask the source for the time of the
1960 * operation to prevent an edge-triggered interrupt escaping meanwhile.
1961 * The idea is from Manfred Spraul. --macro
1962 */
1963 i = irq_cfg(irq)->vector;
1964
1965 v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
1966
1967 ack_APIC_irq();
1968
1969 if (!(v & (1 << (i & 0x1f)))) {
1970 atomic_inc(&irq_mis_count);
1971 spin_lock(&ioapic_lock);
1972 __mask_and_edge_IO_APIC_irq(irq);
1973 __unmask_and_level_IO_APIC_irq(irq);
1974 spin_unlock(&ioapic_lock);
1975 }
1976}
1977
1978static int ioapic_retrigger_irq(unsigned int irq) 1929static int ioapic_retrigger_irq(unsigned int irq)
1979{ 1930{
1980 send_IPI_self(irq_cfg(irq)->vector); 1931 send_IPI_self(irq_cfg(irq)->vector);
@@ -2040,13 +1991,61 @@ static void irq_complete_move(unsigned int irq)
2040static inline void irq_complete_move(unsigned int irq) {} 1991static inline void irq_complete_move(unsigned int irq) {}
2041#endif 1992#endif
2042 1993
1994static void ack_apic_edge(unsigned int irq)
1995{
1996 irq_complete_move(irq);
1997 move_native_irq(irq);
1998 ack_APIC_irq();
1999}
2000
2001static void ack_apic_level(unsigned int irq)
2002{
2003 unsigned long v;
2004 int i;
2005
2006 irq_complete_move(irq);
2007 move_native_irq(irq);
2008/*
2009 * It appears there is an erratum which affects at least version 0x11
2010 * of I/O APIC (that's the 82093AA and cores integrated into various
2011 * chipsets). Under certain conditions a level-triggered interrupt is
2012 * erroneously delivered as edge-triggered one but the respective IRR
2013 * bit gets set nevertheless. As a result the I/O unit expects an EOI
2014 * message but it will never arrive and further interrupts are blocked
2015 * from the source. The exact reason is so far unknown, but the
2016 * phenomenon was observed when two consecutive interrupt requests
2017 * from a given source get delivered to the same CPU and the source is
2018 * temporarily disabled in between.
2019 *
2020 * A workaround is to simulate an EOI message manually. We achieve it
2021 * by setting the trigger mode to edge and then to level when the edge
2022 * trigger mode gets detected in the TMR of a local APIC for a
2023 * level-triggered interrupt. We mask the source for the time of the
2024 * operation to prevent an edge-triggered interrupt escaping meanwhile.
2025 * The idea is from Manfred Spraul. --macro
2026 */
2027 i = irq_cfg(irq)->vector;
2028
2029 v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
2030
2031 ack_APIC_irq();
2032
2033 if (!(v & (1 << (i & 0x1f)))) {
2034 atomic_inc(&irq_mis_count);
2035 spin_lock(&ioapic_lock);
2036 __mask_and_edge_IO_APIC_irq(irq);
2037 __unmask_and_level_IO_APIC_irq(irq);
2038 spin_unlock(&ioapic_lock);
2039 }
2040}
2041
2043static struct irq_chip ioapic_chip __read_mostly = { 2042static struct irq_chip ioapic_chip __read_mostly = {
2044 .name = "IO-APIC", 2043 .name = "IO-APIC",
2045 .startup = startup_ioapic_irq, 2044 .startup = startup_ioapic_irq,
2046 .mask = mask_IO_APIC_irq, 2045 .mask = mask_IO_APIC_irq,
2047 .unmask = unmask_IO_APIC_irq, 2046 .unmask = unmask_IO_APIC_irq,
2048 .ack = ack_ioapic_irq, 2047 .ack = ack_apic_edge,
2049 .eoi = ack_ioapic_quirk_irq, 2048 .eoi = ack_apic_level,
2050#ifdef CONFIG_SMP 2049#ifdef CONFIG_SMP
2051 .set_affinity = set_ioapic_affinity_irq, 2050 .set_affinity = set_ioapic_affinity_irq,
2052#endif 2051#endif
@@ -2094,11 +2093,6 @@ static inline void init_IO_APIC_traps(void)
2094 * The local APIC irq-chip implementation: 2093 * The local APIC irq-chip implementation:
2095 */ 2094 */
2096 2095
2097static void ack_lapic_irq(unsigned int irq)
2098{
2099 ack_APIC_irq();
2100}
2101
2102static void mask_lapic_irq(unsigned int irq) 2096static void mask_lapic_irq(unsigned int irq)
2103{ 2097{
2104 unsigned long v; 2098 unsigned long v;
@@ -2115,6 +2109,11 @@ static void unmask_lapic_irq(unsigned int irq)
2115 apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); 2109 apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
2116} 2110}
2117 2111
2112static void ack_lapic_irq(unsigned int irq)
2113{
2114 ack_APIC_irq();
2115}
2116
2118static struct irq_chip lapic_chip __read_mostly = { 2117static struct irq_chip lapic_chip __read_mostly = {
2119 .name = "local-APIC", 2118 .name = "local-APIC",
2120 .mask = mask_lapic_irq, 2119 .mask = mask_lapic_irq,
@@ -2636,13 +2635,31 @@ static struct irq_chip msi_chip = {
2636 .name = "PCI-MSI", 2635 .name = "PCI-MSI",
2637 .unmask = unmask_msi_irq, 2636 .unmask = unmask_msi_irq,
2638 .mask = mask_msi_irq, 2637 .mask = mask_msi_irq,
2639 .ack = ack_ioapic_irq, 2638 .ack = ack_apic_edge,
2640#ifdef CONFIG_SMP 2639#ifdef CONFIG_SMP
2641 .set_affinity = set_msi_irq_affinity, 2640 .set_affinity = set_msi_irq_affinity,
2642#endif 2641#endif
2643 .retrigger = ioapic_retrigger_irq, 2642 .retrigger = ioapic_retrigger_irq,
2644}; 2643};
2645 2644
2645
2646static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
2647{
2648 int ret;
2649 struct msi_msg msg;
2650
2651 ret = msi_compose_msg(dev, irq, &msg);
2652 if (ret < 0)
2653 return ret;
2654
2655 set_irq_msi(irq, desc);
2656 write_msi_msg(irq, &msg);
2657
2658 set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
2659
2660 return 0;
2661}
2662
2646static unsigned int build_irq_for_pci_dev(struct pci_dev *dev) 2663static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
2647{ 2664{
2648 unsigned int irq; 2665 unsigned int irq;
@@ -2657,7 +2674,6 @@ static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
2657 2674
2658int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) 2675int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
2659{ 2676{
2660 struct msi_msg msg;
2661 int irq, ret; 2677 int irq, ret;
2662 2678
2663 unsigned int irq_want; 2679 unsigned int irq_want;
@@ -2669,17 +2685,11 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
2669 if (irq == 0) 2685 if (irq == 0)
2670 return -1; 2686 return -1;
2671 2687
2672 ret = msi_compose_msg(dev, irq, &msg); 2688 ret = setup_msi_irq(dev, desc, irq);
2673 if (ret < 0) { 2689 if (ret < 0) {
2674 destroy_irq(irq); 2690 destroy_irq(irq);
2675 return ret; 2691 return ret;
2676 } 2692 }
2677
2678 set_irq_msi(irq, desc);
2679 write_msi_msg(irq, &msg);
2680
2681 set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
2682 "edge");
2683 2693
2684 return 0; 2694 return 0;
2685} 2695}
@@ -2738,7 +2748,7 @@ static struct irq_chip ht_irq_chip = {
2738 .name = "PCI-HT", 2748 .name = "PCI-HT",
2739 .mask = mask_ht_irq, 2749 .mask = mask_ht_irq,
2740 .unmask = unmask_ht_irq, 2750 .unmask = unmask_ht_irq,
2741 .ack = ack_ioapic_irq, 2751 .ack = ack_apic_edge,
2742#ifdef CONFIG_SMP 2752#ifdef CONFIG_SMP
2743 .set_affinity = set_ht_irq_affinity, 2753 .set_affinity = set_ht_irq_affinity,
2744#endif 2754#endif