aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/handle.c')
-rw-r--r--kernel/irq/handle.c118
1 files changed, 78 insertions, 40 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 0f6530117105..5a360dd4331b 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -1,9 +1,13 @@
1/* 1/*
2 * linux/kernel/irq/handle.c 2 * linux/kernel/irq/handle.c
3 * 3 *
4 * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar 4 * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
5 * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
5 * 6 *
6 * This file contains the core interrupt handling code. 7 * This file contains the core interrupt handling code.
8 *
9 * Detailed information is available in Documentation/DocBook/genericirq
10 *
7 */ 11 */
8 12
9#include <linux/irq.h> 13#include <linux/irq.h>
@@ -14,11 +18,22 @@
14 18
15#include "internals.h" 19#include "internals.h"
16 20
21/**
22 * handle_bad_irq - handle spurious and unhandled irqs
23 */
24void fastcall
25handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
26{
27 print_irq_desc(irq, desc);
28 kstat_this_cpu.irqs[irq]++;
29 ack_bad_irq(irq);
30}
31
17/* 32/*
18 * Linux has a controller-independent interrupt architecture. 33 * Linux has a controller-independent interrupt architecture.
19 * Every controller has a 'controller-template', that is used 34 * Every controller has a 'controller-template', that is used
20 * by the main code to do the right thing. Each driver-visible 35 * by the main code to do the right thing. Each driver-visible
21 * interrupt source is transparently wired to the apropriate 36 * interrupt source is transparently wired to the appropriate
22 * controller. Thus drivers need not be aware of the 37 * controller. Thus drivers need not be aware of the
23 * interrupt-controller. 38 * interrupt-controller.
24 * 39 *
@@ -28,41 +43,52 @@
28 * 43 *
29 * Controller mappings for all interrupt sources: 44 * Controller mappings for all interrupt sources:
30 */ 45 */
31irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { 46struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = {
32 [0 ... NR_IRQS-1] = { 47 [0 ... NR_IRQS-1] = {
33 .status = IRQ_DISABLED, 48 .status = IRQ_DISABLED,
34 .handler = &no_irq_type, 49 .chip = &no_irq_chip,
35 .lock = SPIN_LOCK_UNLOCKED 50 .handle_irq = handle_bad_irq,
51 .depth = 1,
52 .lock = SPIN_LOCK_UNLOCKED,
53#ifdef CONFIG_SMP
54 .affinity = CPU_MASK_ALL
55#endif
36 } 56 }
37}; 57};
38 58
39/* 59/*
40 * Generic 'no controller' code 60 * What should we do if we get a hw irq event on an illegal vector?
61 * Each architecture has to answer this themself.
41 */ 62 */
42static void end_none(unsigned int irq) { } 63static void ack_bad(unsigned int irq)
43static void enable_none(unsigned int irq) { }
44static void disable_none(unsigned int irq) { }
45static void shutdown_none(unsigned int irq) { }
46static unsigned int startup_none(unsigned int irq) { return 0; }
47
48static void ack_none(unsigned int irq)
49{ 64{
50 /* 65 print_irq_desc(irq, irq_desc + irq);
51 * 'what should we do if we get a hw irq event on an illegal vector'.
52 * each architecture has to answer this themself.
53 */
54 ack_bad_irq(irq); 66 ack_bad_irq(irq);
55} 67}
56 68
57struct hw_interrupt_type no_irq_type = { 69/*
58 .typename = "none", 70 * NOP functions
59 .startup = startup_none, 71 */
60 .shutdown = shutdown_none, 72static void noop(unsigned int irq)
61 .enable = enable_none, 73{
62 .disable = disable_none, 74}
63 .ack = ack_none, 75
64 .end = end_none, 76static unsigned int noop_ret(unsigned int irq)
65 .set_affinity = NULL 77{
78 return 0;
79}
80
81/*
82 * Generic no controller implementation
83 */
84struct irq_chip no_irq_chip = {
85 .name = "none",
86 .startup = noop_ret,
87 .shutdown = noop,
88 .enable = noop,
89 .disable = noop,
90 .ack = ack_bad,
91 .end = noop,
66}; 92};
67 93
68/* 94/*
@@ -73,11 +99,16 @@ irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
73 return IRQ_NONE; 99 return IRQ_NONE;
74} 100}
75 101
76/* 102/**
77 * Have got an event to handle: 103 * handle_IRQ_event - irq action chain handler
104 * @irq: the interrupt number
105 * @regs: pointer to a register structure
106 * @action: the interrupt action chain for this irq
107 *
108 * Handles the action chain of an irq event
78 */ 109 */
79fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, 110irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
80 struct irqaction *action) 111 struct irqaction *action)
81{ 112{
82 irqreturn_t ret, retval = IRQ_NONE; 113 irqreturn_t ret, retval = IRQ_NONE;
83 unsigned int status = 0; 114 unsigned int status = 0;
@@ -100,15 +131,22 @@ fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
100 return retval; 131 return retval;
101} 132}
102 133
103/* 134/**
104 * do_IRQ handles all normal device IRQ's (the special 135 * __do_IRQ - original all in one highlevel IRQ handler
136 * @irq: the interrupt number
137 * @regs: pointer to a register structure
138 *
139 * __do_IRQ handles all normal device IRQ's (the special
105 * SMP cross-CPU interrupts have their own specific 140 * SMP cross-CPU interrupts have their own specific
106 * handlers). 141 * handlers).
142 *
143 * This is the original x86 implementation which is used for every
144 * interrupt type.
107 */ 145 */
108fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) 146fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
109{ 147{
110 irq_desc_t *desc = irq_desc + irq; 148 struct irq_desc *desc = irq_desc + irq;
111 struct irqaction * action; 149 struct irqaction *action;
112 unsigned int status; 150 unsigned int status;
113 151
114 kstat_this_cpu.irqs[irq]++; 152 kstat_this_cpu.irqs[irq]++;
@@ -118,16 +156,16 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
118 /* 156 /*
119 * No locking required for CPU-local interrupts: 157 * No locking required for CPU-local interrupts:
120 */ 158 */
121 if (desc->handler->ack) 159 if (desc->chip->ack)
122 desc->handler->ack(irq); 160 desc->chip->ack(irq);
123 action_ret = handle_IRQ_event(irq, regs, desc->action); 161 action_ret = handle_IRQ_event(irq, regs, desc->action);
124 desc->handler->end(irq); 162 desc->chip->end(irq);
125 return 1; 163 return 1;
126 } 164 }
127 165
128 spin_lock(&desc->lock); 166 spin_lock(&desc->lock);
129 if (desc->handler->ack) 167 if (desc->chip->ack)
130 desc->handler->ack(irq); 168 desc->chip->ack(irq);
131 /* 169 /*
132 * REPLAY is when Linux resends an IRQ that was dropped earlier 170 * REPLAY is when Linux resends an IRQ that was dropped earlier
133 * WAITING is used by probe to mark irqs that are being tested 171 * WAITING is used by probe to mark irqs that are being tested
@@ -187,7 +225,7 @@ out:
187 * The ->end() handler has to deal with interrupts which got 225 * The ->end() handler has to deal with interrupts which got
188 * disabled while the handler was running. 226 * disabled while the handler was running.
189 */ 227 */
190 desc->handler->end(irq); 228 desc->chip->end(irq);
191 spin_unlock(&desc->lock); 229 spin_unlock(&desc->lock);
192 230
193 return 1; 231 return 1;