diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-08-19 23:50:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:52:54 -0400 |
commit | 1d02519242c23450b043e5e8a9e3cb84a8666fe3 (patch) | |
tree | 4a9d55644edf712ba4a09607ffb2d51966527a7f /arch/x86/kernel/io_apic_32.c | |
parent | d83e94acd95789829804fd9e442bd18975f4dc89 (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.c | 178 |
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 | ||
1032 | static 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 | |||
1049 | void lock_vector_lock(void) | 1032 | void 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 | ||
1176 | static 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 | |||
1193 | static void ioapic_register_intr(int irq, unsigned long trigger) | 1193 | static 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 | ||
1929 | static void irq_complete_move(unsigned int irq); | ||
1930 | static void ack_ioapic_irq(unsigned int irq) | ||
1931 | { | ||
1932 | irq_complete_move(irq); | ||
1933 | move_native_irq(irq); | ||
1934 | ack_APIC_irq(); | ||
1935 | } | ||
1936 | |||
1937 | static 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 | |||
1978 | static int ioapic_retrigger_irq(unsigned int irq) | 1929 | static 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) | |||
2040 | static inline void irq_complete_move(unsigned int irq) {} | 1991 | static inline void irq_complete_move(unsigned int irq) {} |
2041 | #endif | 1992 | #endif |
2042 | 1993 | ||
1994 | static void ack_apic_edge(unsigned int irq) | ||
1995 | { | ||
1996 | irq_complete_move(irq); | ||
1997 | move_native_irq(irq); | ||
1998 | ack_APIC_irq(); | ||
1999 | } | ||
2000 | |||
2001 | static 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 | |||
2043 | static struct irq_chip ioapic_chip __read_mostly = { | 2042 | static 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 | ||
2097 | static void ack_lapic_irq(unsigned int irq) | ||
2098 | { | ||
2099 | ack_APIC_irq(); | ||
2100 | } | ||
2101 | |||
2102 | static void mask_lapic_irq(unsigned int irq) | 2096 | static 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 | ||
2112 | static void ack_lapic_irq(unsigned int irq) | ||
2113 | { | ||
2114 | ack_APIC_irq(); | ||
2115 | } | ||
2116 | |||
2118 | static struct irq_chip lapic_chip __read_mostly = { | 2117 | static 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 | |||
2646 | static 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 | |||
2646 | static unsigned int build_irq_for_pci_dev(struct pci_dev *dev) | 2663 | static 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 | ||
2658 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) | 2675 | int 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 |