diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2008-07-11 14:35:17 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-11 14:54:02 -0400 |
commit | c88ac1df4885ce0d762cfeff0e7d5b83725c1e5c (patch) | |
tree | 4e26beb237403efcc9af3353a6bba58c1110be19 /arch/x86 | |
parent | 1baea6e2fea6f235b21f32a322cb6cb43ffdb704 (diff) |
x86: L-APIC: Always fully configure IRQ0
Unlike the 32-bit one, the 64-bit variation of the LVT0 setup code for
the "8259A Virtual Wire" through the local APIC timer configuration does
not fully configure the relevant irq_chip structure. Instead it relies on
the preceding I/O APIC code to have set it up, which does not happen if
the I/O APIC variants have not been tried.
The patch includes corresponding changes to the 32-bit variation too
which make them both the same, barring a small syntactic difference
involving sequence of functions in the source. That should work as an aid
with the upcoming merge.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Matthew Garrett <mjg59@srcf.ucam.org>
Cc: Andreas Herrmann <andreas.herrmann3@amd.com>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/io_apic_32.c | 15 | ||||
-rw-r--r-- | arch/x86/kernel/io_apic_64.c | 29 |
2 files changed, 26 insertions, 18 deletions
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 50e1131a6ec6..74d49e04de58 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c | |||
@@ -2027,7 +2027,7 @@ static inline void init_IO_APIC_traps(void) | |||
2027 | * The local APIC irq-chip implementation: | 2027 | * The local APIC irq-chip implementation: |
2028 | */ | 2028 | */ |
2029 | 2029 | ||
2030 | static void ack_apic(unsigned int irq) | 2030 | static void ack_lapic_irq(unsigned int irq) |
2031 | { | 2031 | { |
2032 | ack_APIC_irq(); | 2032 | ack_APIC_irq(); |
2033 | } | 2033 | } |
@@ -2052,9 +2052,17 @@ static struct irq_chip lapic_chip __read_mostly = { | |||
2052 | .name = "local-APIC", | 2052 | .name = "local-APIC", |
2053 | .mask = mask_lapic_irq, | 2053 | .mask = mask_lapic_irq, |
2054 | .unmask = unmask_lapic_irq, | 2054 | .unmask = unmask_lapic_irq, |
2055 | .ack = ack_apic, | 2055 | .ack = ack_lapic_irq, |
2056 | }; | 2056 | }; |
2057 | 2057 | ||
2058 | static void lapic_register_intr(int irq, int vector) | ||
2059 | { | ||
2060 | irq_desc[irq].status &= ~IRQ_LEVEL; | ||
2061 | set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, | ||
2062 | "edge"); | ||
2063 | set_intr_gate(vector, interrupt[irq]); | ||
2064 | } | ||
2065 | |||
2058 | static void __init setup_nmi(void) | 2066 | static void __init setup_nmi(void) |
2059 | { | 2067 | { |
2060 | /* | 2068 | /* |
@@ -2257,8 +2265,7 @@ static inline void __init check_timer(void) | |||
2257 | 2265 | ||
2258 | printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); | 2266 | printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); |
2259 | 2267 | ||
2260 | set_irq_chip_and_handler_name(0, &lapic_chip, handle_edge_irq, | 2268 | lapic_register_intr(0, vector); |
2261 | "edge"); | ||
2262 | apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ | 2269 | apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ |
2263 | enable_8259A_irq(0); | 2270 | enable_8259A_irq(0); |
2264 | 2271 | ||
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 848411753c7c..07ebcd305fb7 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c | |||
@@ -1561,7 +1561,7 @@ static inline void init_IO_APIC_traps(void) | |||
1561 | } | 1561 | } |
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | static void enable_lapic_irq (unsigned int irq) | 1564 | static void unmask_lapic_irq(unsigned int irq) |
1565 | { | 1565 | { |
1566 | unsigned long v; | 1566 | unsigned long v; |
1567 | 1567 | ||
@@ -1569,7 +1569,7 @@ static void enable_lapic_irq (unsigned int irq) | |||
1569 | apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); | 1569 | apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED); |
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | static void disable_lapic_irq (unsigned int irq) | 1572 | static void mask_lapic_irq(unsigned int irq) |
1573 | { | 1573 | { |
1574 | unsigned long v; | 1574 | unsigned long v; |
1575 | 1575 | ||
@@ -1582,19 +1582,20 @@ static void ack_lapic_irq (unsigned int irq) | |||
1582 | ack_APIC_irq(); | 1582 | ack_APIC_irq(); |
1583 | } | 1583 | } |
1584 | 1584 | ||
1585 | static void end_lapic_irq (unsigned int i) { /* nothing */ } | 1585 | static struct irq_chip lapic_chip __read_mostly = { |
1586 | 1586 | .name = "local-APIC", | |
1587 | static struct hw_interrupt_type lapic_irq_type __read_mostly = { | 1587 | .mask = mask_lapic_irq, |
1588 | .name = "local-APIC", | 1588 | .unmask = unmask_lapic_irq, |
1589 | .typename = "local-APIC-edge", | 1589 | .ack = ack_lapic_irq, |
1590 | .startup = NULL, /* startup_irq() not used for IRQ0 */ | ||
1591 | .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */ | ||
1592 | .enable = enable_lapic_irq, | ||
1593 | .disable = disable_lapic_irq, | ||
1594 | .ack = ack_lapic_irq, | ||
1595 | .end = end_lapic_irq, | ||
1596 | }; | 1590 | }; |
1597 | 1591 | ||
1592 | static void lapic_register_intr(int irq) | ||
1593 | { | ||
1594 | irq_desc[irq].status &= ~IRQ_LEVEL; | ||
1595 | set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, | ||
1596 | "edge"); | ||
1597 | } | ||
1598 | |||
1598 | static void __init setup_nmi(void) | 1599 | static void __init setup_nmi(void) |
1599 | { | 1600 | { |
1600 | /* | 1601 | /* |
@@ -1784,7 +1785,7 @@ static inline void __init check_timer(void) | |||
1784 | 1785 | ||
1785 | apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); | 1786 | apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); |
1786 | 1787 | ||
1787 | irq_desc[0].chip = &lapic_irq_type; | 1788 | lapic_register_intr(0); |
1788 | apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ | 1789 | apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ |
1789 | enable_8259A_irq(0); | 1790 | enable_8259A_irq(0); |
1790 | 1791 | ||