diff options
| -rw-r--r-- | arch/x86/include/asm/irq.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/irq_32.c | 34 | ||||
| -rw-r--r-- | arch/x86/kernel/irq_64.c | 23 |
3 files changed, 38 insertions, 20 deletions
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 592688ed04d3..d0f6f7d1771c 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
| @@ -39,6 +39,7 @@ extern void fixup_irqs(void); | |||
| 39 | extern unsigned int do_IRQ(struct pt_regs *regs); | 39 | extern unsigned int do_IRQ(struct pt_regs *regs); |
| 40 | extern void init_IRQ(void); | 40 | extern void init_IRQ(void); |
| 41 | extern void native_init_IRQ(void); | 41 | extern void native_init_IRQ(void); |
| 42 | extern bool handle_irq(unsigned irq, struct pt_regs *regs); | ||
| 42 | 43 | ||
| 43 | /* Interrupt vector management */ | 44 | /* Interrupt vector management */ |
| 44 | extern DECLARE_BITMAP(used_vectors, NR_VECTORS); | 45 | extern DECLARE_BITMAP(used_vectors, NR_VECTORS); |
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index d802c844991e..61f09fb969ee 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c | |||
| @@ -191,6 +191,26 @@ static inline int | |||
| 191 | execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } | 191 | execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) { return 0; } |
| 192 | #endif | 192 | #endif |
| 193 | 193 | ||
| 194 | bool handle_irq(unsigned irq, struct pt_regs *regs) | ||
| 195 | { | ||
| 196 | struct irq_desc *desc; | ||
| 197 | int overflow; | ||
| 198 | |||
| 199 | overflow = check_stack_overflow(); | ||
| 200 | |||
| 201 | desc = irq_to_desc(irq); | ||
| 202 | if (unlikely(!desc)) | ||
| 203 | return false; | ||
| 204 | |||
| 205 | if (!execute_on_irq_stack(overflow, desc, irq)) { | ||
| 206 | if (unlikely(overflow)) | ||
| 207 | print_stack_overflow(); | ||
| 208 | desc->handle_irq(irq, desc); | ||
| 209 | } | ||
| 210 | |||
| 211 | return true; | ||
| 212 | } | ||
| 213 | |||
| 194 | /* | 214 | /* |
| 195 | * do_IRQ handles all normal device IRQ's (the special | 215 | * do_IRQ handles all normal device IRQ's (the special |
| 196 | * SMP cross-CPU interrupts have their own specific | 216 | * SMP cross-CPU interrupts have their own specific |
| @@ -200,31 +220,19 @@ unsigned int do_IRQ(struct pt_regs *regs) | |||
| 200 | { | 220 | { |
| 201 | struct pt_regs *old_regs; | 221 | struct pt_regs *old_regs; |
| 202 | /* high bit used in ret_from_ code */ | 222 | /* high bit used in ret_from_ code */ |
| 203 | int overflow; | ||
| 204 | unsigned vector = ~regs->orig_ax; | 223 | unsigned vector = ~regs->orig_ax; |
| 205 | struct irq_desc *desc; | ||
| 206 | unsigned irq; | 224 | unsigned irq; |
| 207 | 225 | ||
| 208 | |||
| 209 | old_regs = set_irq_regs(regs); | 226 | old_regs = set_irq_regs(regs); |
| 210 | irq_enter(); | 227 | irq_enter(); |
| 211 | irq = __get_cpu_var(vector_irq)[vector]; | 228 | irq = __get_cpu_var(vector_irq)[vector]; |
| 212 | 229 | ||
| 213 | overflow = check_stack_overflow(); | 230 | if (!handle_irq(irq, regs)) { |
| 214 | |||
| 215 | desc = irq_to_desc(irq); | ||
| 216 | if (unlikely(!desc)) { | ||
| 217 | printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", | 231 | printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n", |
| 218 | __func__, irq, vector, smp_processor_id()); | 232 | __func__, irq, vector, smp_processor_id()); |
| 219 | BUG(); | 233 | BUG(); |
| 220 | } | 234 | } |
| 221 | 235 | ||
| 222 | if (!execute_on_irq_stack(overflow, desc, irq)) { | ||
| 223 | if (unlikely(overflow)) | ||
| 224 | print_stack_overflow(); | ||
| 225 | desc->handle_irq(irq, desc); | ||
| 226 | } | ||
| 227 | |||
| 228 | irq_exit(); | 236 | irq_exit(); |
| 229 | set_irq_regs(old_regs); | 237 | set_irq_regs(old_regs); |
| 230 | return 1; | 238 | return 1; |
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 018963aa6ee3..a93f3b0dc7f2 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c | |||
| @@ -48,6 +48,20 @@ static inline void stack_overflow_check(struct pt_regs *regs) | |||
| 48 | #endif | 48 | #endif |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | bool handle_irq(unsigned irq, struct pt_regs *regs) | ||
| 52 | { | ||
| 53 | struct irq_desc *desc; | ||
| 54 | |||
| 55 | stack_overflow_check(regs); | ||
| 56 | |||
| 57 | desc = irq_to_desc(irq); | ||
| 58 | if (unlikely(!desc)) | ||
| 59 | return false; | ||
| 60 | |||
| 61 | generic_handle_irq_desc(irq, desc); | ||
| 62 | return true; | ||
| 63 | } | ||
| 64 | |||
| 51 | /* | 65 | /* |
| 52 | * do_IRQ handles all normal device IRQ's (the special | 66 | * do_IRQ handles all normal device IRQ's (the special |
| 53 | * SMP cross-CPU interrupts have their own specific | 67 | * SMP cross-CPU interrupts have their own specific |
| @@ -56,7 +70,6 @@ static inline void stack_overflow_check(struct pt_regs *regs) | |||
| 56 | asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | 70 | asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) |
| 57 | { | 71 | { |
| 58 | struct pt_regs *old_regs = set_irq_regs(regs); | 72 | struct pt_regs *old_regs = set_irq_regs(regs); |
| 59 | struct irq_desc *desc; | ||
| 60 | 73 | ||
| 61 | /* high bit used in ret_from_ code */ | 74 | /* high bit used in ret_from_ code */ |
| 62 | unsigned vector = ~regs->orig_ax; | 75 | unsigned vector = ~regs->orig_ax; |
| @@ -64,14 +77,10 @@ asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | |||
| 64 | 77 | ||
| 65 | exit_idle(); | 78 | exit_idle(); |
| 66 | irq_enter(); | 79 | irq_enter(); |
| 67 | irq = __get_cpu_var(vector_irq)[vector]; | ||
| 68 | 80 | ||
| 69 | stack_overflow_check(regs); | 81 | irq = __get_cpu_var(vector_irq)[vector]; |
| 70 | 82 | ||
| 71 | desc = irq_to_desc(irq); | 83 | if (!handle_irq(irq, regs)) { |
| 72 | if (likely(desc)) | ||
| 73 | generic_handle_irq_desc(irq, desc); | ||
| 74 | else { | ||
| 75 | if (!disable_apic) | 84 | if (!disable_apic) |
| 76 | ack_APIC_irq(); | 85 | ack_APIC_irq(); |
| 77 | 86 | ||
