diff options
author | Dimitri Sivanich <sivanich@sgi.com> | 2009-03-04 13:56:05 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-04 14:25:37 -0500 |
commit | acaabe795a62bba089c185917af86b44654313dc (patch) | |
tree | bbdf5eb8a7eb2a1a8c40bfc332db6d328a64b043 | |
parent | f254f3909efaf59ca2d0f408de2d044dace60706 (diff) |
x86: UV, SGI RTC: add generic system vector
This patch allocates a system interrupt vector for various platform
specific uses.
Signed-off-by: Dimitri Sivanich <sivanich@sgi.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: john stultz <johnstul@us.ibm.com>
LKML-Reference: <20090304185605.GA24419@sgi.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/include/asm/entry_arch.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/hardirq.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/hw_irq.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/irq.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/irq_vectors.h | 5 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 2 | ||||
-rw-r--r-- | arch/x86/kernel/irq.c | 34 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit_32.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit_64.c | 3 |
9 files changed, 52 insertions, 0 deletions
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index 854d538ae857..c2e6bedaf258 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
@@ -33,6 +33,8 @@ BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7, | |||
33 | smp_invalidate_interrupt) | 33 | smp_invalidate_interrupt) |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | BUILD_INTERRUPT(generic_interrupt, GENERIC_INTERRUPT_VECTOR) | ||
37 | |||
36 | /* | 38 | /* |
37 | * every pentium local APIC has two 'local interrupts', with a | 39 | * every pentium local APIC has two 'local interrupts', with a |
38 | * soft-definable vector attached to both interrupts, one of | 40 | * soft-definable vector attached to both interrupts, one of |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 176f058e7159..039db6aa8e02 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
@@ -12,6 +12,7 @@ typedef struct { | |||
12 | unsigned int apic_timer_irqs; /* arch dependent */ | 12 | unsigned int apic_timer_irqs; /* arch dependent */ |
13 | unsigned int irq_spurious_count; | 13 | unsigned int irq_spurious_count; |
14 | #endif | 14 | #endif |
15 | unsigned int generic_irqs; /* arch dependent */ | ||
15 | #ifdef CONFIG_SMP | 16 | #ifdef CONFIG_SMP |
16 | unsigned int irq_resched_count; | 17 | unsigned int irq_resched_count; |
17 | unsigned int irq_call_count; | 18 | unsigned int irq_call_count; |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index 370e1c83bb49..b762ea49bd70 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | /* Interrupt handlers registered during init_IRQ */ | 28 | /* Interrupt handlers registered during init_IRQ */ |
29 | extern void apic_timer_interrupt(void); | 29 | extern void apic_timer_interrupt(void); |
30 | extern void generic_interrupt(void); | ||
30 | extern void error_interrupt(void); | 31 | extern void error_interrupt(void); |
31 | extern void spurious_interrupt(void); | 32 | extern void spurious_interrupt(void); |
32 | extern void thermal_interrupt(void); | 33 | extern void thermal_interrupt(void); |
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 107eb2196691..f38481bcd455 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
@@ -36,6 +36,7 @@ static inline int irq_canonicalize(int irq) | |||
36 | extern void fixup_irqs(void); | 36 | extern void fixup_irqs(void); |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | extern void (*generic_interrupt_extension)(void); | ||
39 | extern void init_IRQ(void); | 40 | extern void init_IRQ(void); |
40 | extern void native_init_IRQ(void); | 41 | extern void native_init_IRQ(void); |
41 | extern bool handle_irq(unsigned irq, struct pt_regs *regs); | 42 | extern bool handle_irq(unsigned irq, struct pt_regs *regs); |
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h index 8a285f356f8a..3cbd79bbb47c 100644 --- a/arch/x86/include/asm/irq_vectors.h +++ b/arch/x86/include/asm/irq_vectors.h | |||
@@ -112,6 +112,11 @@ | |||
112 | #define LOCAL_PERF_VECTOR 0xee | 112 | #define LOCAL_PERF_VECTOR 0xee |
113 | 113 | ||
114 | /* | 114 | /* |
115 | * Generic system vector for platform specific use | ||
116 | */ | ||
117 | #define GENERIC_INTERRUPT_VECTOR 0xed | ||
118 | |||
119 | /* | ||
115 | * First APIC vector available to drivers: (vectors 0x30-0xee) we | 120 | * First APIC vector available to drivers: (vectors 0x30-0xee) we |
116 | * start at 0x31(0x41) to spread out vectors evenly between priority | 121 | * start at 0x31(0x41) to spread out vectors evenly between priority |
117 | * levels. (0x80 is the syscall vector) | 122 | * levels. (0x80 is the syscall vector) |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 83d1836b9467..7ba4621c0dfa 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -984,6 +984,8 @@ apicinterrupt UV_BAU_MESSAGE \ | |||
984 | #endif | 984 | #endif |
985 | apicinterrupt LOCAL_TIMER_VECTOR \ | 985 | apicinterrupt LOCAL_TIMER_VECTOR \ |
986 | apic_timer_interrupt smp_apic_timer_interrupt | 986 | apic_timer_interrupt smp_apic_timer_interrupt |
987 | apicinterrupt GENERIC_INTERRUPT_VECTOR \ | ||
988 | generic_interrupt smp_generic_interrupt | ||
987 | 989 | ||
988 | #ifdef CONFIG_SMP | 990 | #ifdef CONFIG_SMP |
989 | apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \ | 991 | apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \ |
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index f13ca1650aaf..b864341dcc45 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -15,6 +15,9 @@ | |||
15 | 15 | ||
16 | atomic_t irq_err_count; | 16 | atomic_t irq_err_count; |
17 | 17 | ||
18 | /* Function pointer for generic interrupt vector handling */ | ||
19 | void (*generic_interrupt_extension)(void) = NULL; | ||
20 | |||
18 | /* | 21 | /* |
19 | * 'what should we do if we get a hw irq event on an illegal vector'. | 22 | * 'what should we do if we get a hw irq event on an illegal vector'. |
20 | * each architecture has to answer this themselves. | 23 | * each architecture has to answer this themselves. |
@@ -56,6 +59,12 @@ static int show_other_interrupts(struct seq_file *p) | |||
56 | seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); | 59 | seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); |
57 | seq_printf(p, " Local timer interrupts\n"); | 60 | seq_printf(p, " Local timer interrupts\n"); |
58 | #endif | 61 | #endif |
62 | if (generic_interrupt_extension) { | ||
63 | seq_printf(p, "PLT: "); | ||
64 | for_each_online_cpu(j) | ||
65 | seq_printf(p, "%10u ", irq_stats(j)->generic_irqs); | ||
66 | seq_printf(p, " Platform interrupts\n"); | ||
67 | } | ||
59 | #ifdef CONFIG_SMP | 68 | #ifdef CONFIG_SMP |
60 | seq_printf(p, "RES: "); | 69 | seq_printf(p, "RES: "); |
61 | for_each_online_cpu(j) | 70 | for_each_online_cpu(j) |
@@ -163,6 +172,8 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
163 | #ifdef CONFIG_X86_LOCAL_APIC | 172 | #ifdef CONFIG_X86_LOCAL_APIC |
164 | sum += irq_stats(cpu)->apic_timer_irqs; | 173 | sum += irq_stats(cpu)->apic_timer_irqs; |
165 | #endif | 174 | #endif |
175 | if (generic_interrupt_extension) | ||
176 | sum += irq_stats(cpu)->generic_irqs; | ||
166 | #ifdef CONFIG_SMP | 177 | #ifdef CONFIG_SMP |
167 | sum += irq_stats(cpu)->irq_resched_count; | 178 | sum += irq_stats(cpu)->irq_resched_count; |
168 | sum += irq_stats(cpu)->irq_call_count; | 179 | sum += irq_stats(cpu)->irq_call_count; |
@@ -226,4 +237,27 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | |||
226 | return 1; | 237 | return 1; |
227 | } | 238 | } |
228 | 239 | ||
240 | /* | ||
241 | * Handler for GENERIC_INTERRUPT_VECTOR. | ||
242 | */ | ||
243 | void smp_generic_interrupt(struct pt_regs *regs) | ||
244 | { | ||
245 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
246 | |||
247 | ack_APIC_irq(); | ||
248 | |||
249 | exit_idle(); | ||
250 | |||
251 | irq_enter(); | ||
252 | |||
253 | inc_irq_stat(generic_irqs); | ||
254 | |||
255 | if (generic_interrupt_extension) | ||
256 | generic_interrupt_extension(); | ||
257 | |||
258 | irq_exit(); | ||
259 | |||
260 | set_irq_regs(old_regs); | ||
261 | } | ||
262 | |||
229 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | 263 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); |
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index 50b8c3a3006c..bc1326105448 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c | |||
@@ -175,6 +175,9 @@ void __init native_init_IRQ(void) | |||
175 | /* self generated IPI for local APIC timer */ | 175 | /* self generated IPI for local APIC timer */ |
176 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); | 176 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); |
177 | 177 | ||
178 | /* generic IPI for platform specific use */ | ||
179 | alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt); | ||
180 | |||
178 | /* IPI vectors for APIC spurious and error interrupts */ | 181 | /* IPI vectors for APIC spurious and error interrupts */ |
179 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 182 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
180 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 183 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c index da481a1e3f30..c7a49e0ffbfb 100644 --- a/arch/x86/kernel/irqinit_64.c +++ b/arch/x86/kernel/irqinit_64.c | |||
@@ -147,6 +147,9 @@ static void __init apic_intr_init(void) | |||
147 | /* self generated IPI for local APIC timer */ | 147 | /* self generated IPI for local APIC timer */ |
148 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); | 148 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); |
149 | 149 | ||
150 | /* generic IPI for platform specific use */ | ||
151 | alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt); | ||
152 | |||
150 | /* IPI vectors for APIC spurious and error interrupts */ | 153 | /* IPI vectors for APIC spurious and error interrupts */ |
151 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 154 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
152 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 155 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |