diff options
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/autoprobe.c | 43 | ||||
-rw-r--r-- | kernel/irq/chip.c | 101 | ||||
-rw-r--r-- | kernel/irq/handle.c | 27 | ||||
-rw-r--r-- | kernel/irq/internals.h | 7 | ||||
-rw-r--r-- | kernel/irq/manage.c | 123 | ||||
-rw-r--r-- | kernel/irq/migration.c | 14 | ||||
-rw-r--r-- | kernel/irq/proc.c | 45 | ||||
-rw-r--r-- | kernel/irq/resend.c | 6 | ||||
-rw-r--r-- | kernel/irq/spurious.c | 162 |
9 files changed, 298 insertions, 230 deletions
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c index 533068cfb607..cc0f7321b8ce 100644 --- a/kernel/irq/autoprobe.c +++ b/kernel/irq/autoprobe.c | |||
@@ -30,17 +30,16 @@ static DEFINE_MUTEX(probing_active); | |||
30 | unsigned long probe_irq_on(void) | 30 | unsigned long probe_irq_on(void) |
31 | { | 31 | { |
32 | struct irq_desc *desc; | 32 | struct irq_desc *desc; |
33 | unsigned long mask; | 33 | unsigned long mask = 0; |
34 | unsigned int i; | 34 | unsigned int status; |
35 | int i; | ||
35 | 36 | ||
36 | mutex_lock(&probing_active); | 37 | mutex_lock(&probing_active); |
37 | /* | 38 | /* |
38 | * something may have generated an irq long ago and we want to | 39 | * something may have generated an irq long ago and we want to |
39 | * flush such a longstanding irq before considering it as spurious. | 40 | * flush such a longstanding irq before considering it as spurious. |
40 | */ | 41 | */ |
41 | for (i = NR_IRQS-1; i > 0; i--) { | 42 | for_each_irq_desc_reverse(i, desc) { |
42 | desc = irq_desc + i; | ||
43 | |||
44 | spin_lock_irq(&desc->lock); | 43 | spin_lock_irq(&desc->lock); |
45 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { | 44 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
46 | /* | 45 | /* |
@@ -68,9 +67,7 @@ unsigned long probe_irq_on(void) | |||
68 | * (we must startup again here because if a longstanding irq | 67 | * (we must startup again here because if a longstanding irq |
69 | * happened in the previous stage, it may have masked itself) | 68 | * happened in the previous stage, it may have masked itself) |
70 | */ | 69 | */ |
71 | for (i = NR_IRQS-1; i > 0; i--) { | 70 | for_each_irq_desc_reverse(i, desc) { |
72 | desc = irq_desc + i; | ||
73 | |||
74 | spin_lock_irq(&desc->lock); | 71 | spin_lock_irq(&desc->lock); |
75 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { | 72 | if (!desc->action && !(desc->status & IRQ_NOPROBE)) { |
76 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; | 73 | desc->status |= IRQ_AUTODETECT | IRQ_WAITING; |
@@ -88,11 +85,7 @@ unsigned long probe_irq_on(void) | |||
88 | /* | 85 | /* |
89 | * Now filter out any obviously spurious interrupts | 86 | * Now filter out any obviously spurious interrupts |
90 | */ | 87 | */ |
91 | mask = 0; | 88 | for_each_irq_desc(i, desc) { |
92 | for (i = 0; i < NR_IRQS; i++) { | ||
93 | unsigned int status; | ||
94 | |||
95 | desc = irq_desc + i; | ||
96 | spin_lock_irq(&desc->lock); | 89 | spin_lock_irq(&desc->lock); |
97 | status = desc->status; | 90 | status = desc->status; |
98 | 91 | ||
@@ -126,14 +119,11 @@ EXPORT_SYMBOL(probe_irq_on); | |||
126 | */ | 119 | */ |
127 | unsigned int probe_irq_mask(unsigned long val) | 120 | unsigned int probe_irq_mask(unsigned long val) |
128 | { | 121 | { |
129 | unsigned int mask; | 122 | unsigned int status, mask = 0; |
123 | struct irq_desc *desc; | ||
130 | int i; | 124 | int i; |
131 | 125 | ||
132 | mask = 0; | 126 | for_each_irq_desc(i, desc) { |
133 | for (i = 0; i < NR_IRQS; i++) { | ||
134 | struct irq_desc *desc = irq_desc + i; | ||
135 | unsigned int status; | ||
136 | |||
137 | spin_lock_irq(&desc->lock); | 127 | spin_lock_irq(&desc->lock); |
138 | status = desc->status; | 128 | status = desc->status; |
139 | 129 | ||
@@ -171,20 +161,19 @@ EXPORT_SYMBOL(probe_irq_mask); | |||
171 | */ | 161 | */ |
172 | int probe_irq_off(unsigned long val) | 162 | int probe_irq_off(unsigned long val) |
173 | { | 163 | { |
174 | int i, irq_found = 0, nr_irqs = 0; | 164 | int i, irq_found = 0, nr_of_irqs = 0; |
175 | 165 | struct irq_desc *desc; | |
176 | for (i = 0; i < NR_IRQS; i++) { | 166 | unsigned int status; |
177 | struct irq_desc *desc = irq_desc + i; | ||
178 | unsigned int status; | ||
179 | 167 | ||
168 | for_each_irq_desc(i, desc) { | ||
180 | spin_lock_irq(&desc->lock); | 169 | spin_lock_irq(&desc->lock); |
181 | status = desc->status; | 170 | status = desc->status; |
182 | 171 | ||
183 | if (status & IRQ_AUTODETECT) { | 172 | if (status & IRQ_AUTODETECT) { |
184 | if (!(status & IRQ_WAITING)) { | 173 | if (!(status & IRQ_WAITING)) { |
185 | if (!nr_irqs) | 174 | if (!nr_of_irqs) |
186 | irq_found = i; | 175 | irq_found = i; |
187 | nr_irqs++; | 176 | nr_of_irqs++; |
188 | } | 177 | } |
189 | desc->status = status & ~IRQ_AUTODETECT; | 178 | desc->status = status & ~IRQ_AUTODETECT; |
190 | desc->chip->shutdown(i); | 179 | desc->chip->shutdown(i); |
@@ -193,7 +182,7 @@ int probe_irq_off(unsigned long val) | |||
193 | } | 182 | } |
194 | mutex_unlock(&probing_active); | 183 | mutex_unlock(&probing_active); |
195 | 184 | ||
196 | if (nr_irqs > 1) | 185 | if (nr_of_irqs > 1) |
197 | irq_found = -irq_found; | 186 | irq_found = -irq_found; |
198 | 187 | ||
199 | return irq_found; | 188 | return irq_found; |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 3cd441ebf5d2..4895fde4eb93 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -24,16 +24,15 @@ | |||
24 | */ | 24 | */ |
25 | void dynamic_irq_init(unsigned int irq) | 25 | void dynamic_irq_init(unsigned int irq) |
26 | { | 26 | { |
27 | struct irq_desc *desc; | 27 | struct irq_desc *desc = irq_to_desc(irq); |
28 | unsigned long flags; | 28 | unsigned long flags; |
29 | 29 | ||
30 | if (irq >= NR_IRQS) { | 30 | if (!desc) { |
31 | WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq); | 31 | WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq); |
32 | return; | 32 | return; |
33 | } | 33 | } |
34 | 34 | ||
35 | /* Ensure we don't have left over values from a previous use of this irq */ | 35 | /* Ensure we don't have left over values from a previous use of this irq */ |
36 | desc = irq_desc + irq; | ||
37 | spin_lock_irqsave(&desc->lock, flags); | 36 | spin_lock_irqsave(&desc->lock, flags); |
38 | desc->status = IRQ_DISABLED; | 37 | desc->status = IRQ_DISABLED; |
39 | desc->chip = &no_irq_chip; | 38 | desc->chip = &no_irq_chip; |
@@ -57,15 +56,14 @@ void dynamic_irq_init(unsigned int irq) | |||
57 | */ | 56 | */ |
58 | void dynamic_irq_cleanup(unsigned int irq) | 57 | void dynamic_irq_cleanup(unsigned int irq) |
59 | { | 58 | { |
60 | struct irq_desc *desc; | 59 | struct irq_desc *desc = irq_to_desc(irq); |
61 | unsigned long flags; | 60 | unsigned long flags; |
62 | 61 | ||
63 | if (irq >= NR_IRQS) { | 62 | if (!desc) { |
64 | WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq); | 63 | WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq); |
65 | return; | 64 | return; |
66 | } | 65 | } |
67 | 66 | ||
68 | desc = irq_desc + irq; | ||
69 | spin_lock_irqsave(&desc->lock, flags); | 67 | spin_lock_irqsave(&desc->lock, flags); |
70 | if (desc->action) { | 68 | if (desc->action) { |
71 | spin_unlock_irqrestore(&desc->lock, flags); | 69 | spin_unlock_irqrestore(&desc->lock, flags); |
@@ -89,10 +87,10 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
89 | */ | 87 | */ |
90 | int set_irq_chip(unsigned int irq, struct irq_chip *chip) | 88 | int set_irq_chip(unsigned int irq, struct irq_chip *chip) |
91 | { | 89 | { |
92 | struct irq_desc *desc; | 90 | struct irq_desc *desc = irq_to_desc(irq); |
93 | unsigned long flags; | 91 | unsigned long flags; |
94 | 92 | ||
95 | if (irq >= NR_IRQS) { | 93 | if (!desc) { |
96 | WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq); | 94 | WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq); |
97 | return -EINVAL; | 95 | return -EINVAL; |
98 | } | 96 | } |
@@ -100,7 +98,6 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip) | |||
100 | if (!chip) | 98 | if (!chip) |
101 | chip = &no_irq_chip; | 99 | chip = &no_irq_chip; |
102 | 100 | ||
103 | desc = irq_desc + irq; | ||
104 | spin_lock_irqsave(&desc->lock, flags); | 101 | spin_lock_irqsave(&desc->lock, flags); |
105 | irq_chip_set_defaults(chip); | 102 | irq_chip_set_defaults(chip); |
106 | desc->chip = chip; | 103 | desc->chip = chip; |
@@ -111,27 +108,27 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip) | |||
111 | EXPORT_SYMBOL(set_irq_chip); | 108 | EXPORT_SYMBOL(set_irq_chip); |
112 | 109 | ||
113 | /** | 110 | /** |
114 | * set_irq_type - set the irq type for an irq | 111 | * set_irq_type - set the irq trigger type for an irq |
115 | * @irq: irq number | 112 | * @irq: irq number |
116 | * @type: interrupt type - see include/linux/interrupt.h | 113 | * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h |
117 | */ | 114 | */ |
118 | int set_irq_type(unsigned int irq, unsigned int type) | 115 | int set_irq_type(unsigned int irq, unsigned int type) |
119 | { | 116 | { |
120 | struct irq_desc *desc; | 117 | struct irq_desc *desc = irq_to_desc(irq); |
121 | unsigned long flags; | 118 | unsigned long flags; |
122 | int ret = -ENXIO; | 119 | int ret = -ENXIO; |
123 | 120 | ||
124 | if (irq >= NR_IRQS) { | 121 | if (!desc) { |
125 | printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); | 122 | printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); |
126 | return -ENODEV; | 123 | return -ENODEV; |
127 | } | 124 | } |
128 | 125 | ||
129 | desc = irq_desc + irq; | 126 | if (type == IRQ_TYPE_NONE) |
130 | if (desc->chip->set_type) { | 127 | return 0; |
131 | spin_lock_irqsave(&desc->lock, flags); | 128 | |
132 | ret = desc->chip->set_type(irq, type); | 129 | spin_lock_irqsave(&desc->lock, flags); |
133 | spin_unlock_irqrestore(&desc->lock, flags); | 130 | ret = __irq_set_trigger(desc, irq, flags); |
134 | } | 131 | spin_unlock_irqrestore(&desc->lock, flags); |
135 | return ret; | 132 | return ret; |
136 | } | 133 | } |
137 | EXPORT_SYMBOL(set_irq_type); | 134 | EXPORT_SYMBOL(set_irq_type); |
@@ -145,16 +142,15 @@ EXPORT_SYMBOL(set_irq_type); | |||
145 | */ | 142 | */ |
146 | int set_irq_data(unsigned int irq, void *data) | 143 | int set_irq_data(unsigned int irq, void *data) |
147 | { | 144 | { |
148 | struct irq_desc *desc; | 145 | struct irq_desc *desc = irq_to_desc(irq); |
149 | unsigned long flags; | 146 | unsigned long flags; |
150 | 147 | ||
151 | if (irq >= NR_IRQS) { | 148 | if (!desc) { |
152 | printk(KERN_ERR | 149 | printk(KERN_ERR |
153 | "Trying to install controller data for IRQ%d\n", irq); | 150 | "Trying to install controller data for IRQ%d\n", irq); |
154 | return -EINVAL; | 151 | return -EINVAL; |
155 | } | 152 | } |
156 | 153 | ||
157 | desc = irq_desc + irq; | ||
158 | spin_lock_irqsave(&desc->lock, flags); | 154 | spin_lock_irqsave(&desc->lock, flags); |
159 | desc->handler_data = data; | 155 | desc->handler_data = data; |
160 | spin_unlock_irqrestore(&desc->lock, flags); | 156 | spin_unlock_irqrestore(&desc->lock, flags); |
@@ -171,15 +167,15 @@ EXPORT_SYMBOL(set_irq_data); | |||
171 | */ | 167 | */ |
172 | int set_irq_msi(unsigned int irq, struct msi_desc *entry) | 168 | int set_irq_msi(unsigned int irq, struct msi_desc *entry) |
173 | { | 169 | { |
174 | struct irq_desc *desc; | 170 | struct irq_desc *desc = irq_to_desc(irq); |
175 | unsigned long flags; | 171 | unsigned long flags; |
176 | 172 | ||
177 | if (irq >= NR_IRQS) { | 173 | if (!desc) { |
178 | printk(KERN_ERR | 174 | printk(KERN_ERR |
179 | "Trying to install msi data for IRQ%d\n", irq); | 175 | "Trying to install msi data for IRQ%d\n", irq); |
180 | return -EINVAL; | 176 | return -EINVAL; |
181 | } | 177 | } |
182 | desc = irq_desc + irq; | 178 | |
183 | spin_lock_irqsave(&desc->lock, flags); | 179 | spin_lock_irqsave(&desc->lock, flags); |
184 | desc->msi_desc = entry; | 180 | desc->msi_desc = entry; |
185 | if (entry) | 181 | if (entry) |
@@ -197,10 +193,16 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry) | |||
197 | */ | 193 | */ |
198 | int set_irq_chip_data(unsigned int irq, void *data) | 194 | int set_irq_chip_data(unsigned int irq, void *data) |
199 | { | 195 | { |
200 | struct irq_desc *desc = irq_desc + irq; | 196 | struct irq_desc *desc = irq_to_desc(irq); |
201 | unsigned long flags; | 197 | unsigned long flags; |
202 | 198 | ||
203 | if (irq >= NR_IRQS || !desc->chip) { | 199 | if (!desc) { |
200 | printk(KERN_ERR | ||
201 | "Trying to install chip data for IRQ%d\n", irq); | ||
202 | return -EINVAL; | ||
203 | } | ||
204 | |||
205 | if (!desc->chip) { | ||
204 | printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); | 206 | printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); |
205 | return -EINVAL; | 207 | return -EINVAL; |
206 | } | 208 | } |
@@ -218,7 +220,7 @@ EXPORT_SYMBOL(set_irq_chip_data); | |||
218 | */ | 220 | */ |
219 | static void default_enable(unsigned int irq) | 221 | static void default_enable(unsigned int irq) |
220 | { | 222 | { |
221 | struct irq_desc *desc = irq_desc + irq; | 223 | struct irq_desc *desc = irq_to_desc(irq); |
222 | 224 | ||
223 | desc->chip->unmask(irq); | 225 | desc->chip->unmask(irq); |
224 | desc->status &= ~IRQ_MASKED; | 226 | desc->status &= ~IRQ_MASKED; |
@@ -236,8 +238,9 @@ static void default_disable(unsigned int irq) | |||
236 | */ | 238 | */ |
237 | static unsigned int default_startup(unsigned int irq) | 239 | static unsigned int default_startup(unsigned int irq) |
238 | { | 240 | { |
239 | irq_desc[irq].chip->enable(irq); | 241 | struct irq_desc *desc = irq_to_desc(irq); |
240 | 242 | ||
243 | desc->chip->enable(irq); | ||
241 | return 0; | 244 | return 0; |
242 | } | 245 | } |
243 | 246 | ||
@@ -246,7 +249,7 @@ static unsigned int default_startup(unsigned int irq) | |||
246 | */ | 249 | */ |
247 | static void default_shutdown(unsigned int irq) | 250 | static void default_shutdown(unsigned int irq) |
248 | { | 251 | { |
249 | struct irq_desc *desc = irq_desc + irq; | 252 | struct irq_desc *desc = irq_to_desc(irq); |
250 | 253 | ||
251 | desc->chip->mask(irq); | 254 | desc->chip->mask(irq); |
252 | desc->status |= IRQ_MASKED; | 255 | desc->status |= IRQ_MASKED; |
@@ -305,14 +308,13 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
305 | { | 308 | { |
306 | struct irqaction *action; | 309 | struct irqaction *action; |
307 | irqreturn_t action_ret; | 310 | irqreturn_t action_ret; |
308 | const unsigned int cpu = smp_processor_id(); | ||
309 | 311 | ||
310 | spin_lock(&desc->lock); | 312 | spin_lock(&desc->lock); |
311 | 313 | ||
312 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 314 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
313 | goto out_unlock; | 315 | goto out_unlock; |
314 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 316 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
315 | kstat_cpu(cpu).irqs[irq]++; | 317 | kstat_incr_irqs_this_cpu(irq, desc); |
316 | 318 | ||
317 | action = desc->action; | 319 | action = desc->action; |
318 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | 320 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) |
@@ -344,7 +346,6 @@ out_unlock: | |||
344 | void | 346 | void |
345 | handle_level_irq(unsigned int irq, struct irq_desc *desc) | 347 | handle_level_irq(unsigned int irq, struct irq_desc *desc) |
346 | { | 348 | { |
347 | unsigned int cpu = smp_processor_id(); | ||
348 | struct irqaction *action; | 349 | struct irqaction *action; |
349 | irqreturn_t action_ret; | 350 | irqreturn_t action_ret; |
350 | 351 | ||
@@ -354,7 +355,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
354 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 355 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
355 | goto out_unlock; | 356 | goto out_unlock; |
356 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 357 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
357 | kstat_cpu(cpu).irqs[irq]++; | 358 | kstat_incr_irqs_this_cpu(irq, desc); |
358 | 359 | ||
359 | /* | 360 | /* |
360 | * If its disabled or no action available | 361 | * If its disabled or no action available |
@@ -392,7 +393,6 @@ out_unlock: | |||
392 | void | 393 | void |
393 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | 394 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) |
394 | { | 395 | { |
395 | unsigned int cpu = smp_processor_id(); | ||
396 | struct irqaction *action; | 396 | struct irqaction *action; |
397 | irqreturn_t action_ret; | 397 | irqreturn_t action_ret; |
398 | 398 | ||
@@ -402,7 +402,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
402 | goto out; | 402 | goto out; |
403 | 403 | ||
404 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 404 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
405 | kstat_cpu(cpu).irqs[irq]++; | 405 | kstat_incr_irqs_this_cpu(irq, desc); |
406 | 406 | ||
407 | /* | 407 | /* |
408 | * If its disabled or no action available | 408 | * If its disabled or no action available |
@@ -451,8 +451,6 @@ out: | |||
451 | void | 451 | void |
452 | handle_edge_irq(unsigned int irq, struct irq_desc *desc) | 452 | handle_edge_irq(unsigned int irq, struct irq_desc *desc) |
453 | { | 453 | { |
454 | const unsigned int cpu = smp_processor_id(); | ||
455 | |||
456 | spin_lock(&desc->lock); | 454 | spin_lock(&desc->lock); |
457 | 455 | ||
458 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 456 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
@@ -468,8 +466,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
468 | mask_ack_irq(desc, irq); | 466 | mask_ack_irq(desc, irq); |
469 | goto out_unlock; | 467 | goto out_unlock; |
470 | } | 468 | } |
471 | 469 | kstat_incr_irqs_this_cpu(irq, desc); | |
472 | kstat_cpu(cpu).irqs[irq]++; | ||
473 | 470 | ||
474 | /* Start handling the irq */ | 471 | /* Start handling the irq */ |
475 | desc->chip->ack(irq); | 472 | desc->chip->ack(irq); |
@@ -524,7 +521,7 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) | |||
524 | { | 521 | { |
525 | irqreturn_t action_ret; | 522 | irqreturn_t action_ret; |
526 | 523 | ||
527 | kstat_this_cpu.irqs[irq]++; | 524 | kstat_incr_irqs_this_cpu(irq, desc); |
528 | 525 | ||
529 | if (desc->chip->ack) | 526 | if (desc->chip->ack) |
530 | desc->chip->ack(irq); | 527 | desc->chip->ack(irq); |
@@ -541,17 +538,15 @@ void | |||
541 | __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | 538 | __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, |
542 | const char *name) | 539 | const char *name) |
543 | { | 540 | { |
544 | struct irq_desc *desc; | 541 | struct irq_desc *desc = irq_to_desc(irq); |
545 | unsigned long flags; | 542 | unsigned long flags; |
546 | 543 | ||
547 | if (irq >= NR_IRQS) { | 544 | if (!desc) { |
548 | printk(KERN_ERR | 545 | printk(KERN_ERR |
549 | "Trying to install type control for IRQ%d\n", irq); | 546 | "Trying to install type control for IRQ%d\n", irq); |
550 | return; | 547 | return; |
551 | } | 548 | } |
552 | 549 | ||
553 | desc = irq_desc + irq; | ||
554 | |||
555 | if (!handle) | 550 | if (!handle) |
556 | handle = handle_bad_irq; | 551 | handle = handle_bad_irq; |
557 | else if (desc->chip == &no_irq_chip) { | 552 | else if (desc->chip == &no_irq_chip) { |
@@ -583,7 +578,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
583 | desc->status &= ~IRQ_DISABLED; | 578 | desc->status &= ~IRQ_DISABLED; |
584 | desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; | 579 | desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; |
585 | desc->depth = 0; | 580 | desc->depth = 0; |
586 | desc->chip->unmask(irq); | 581 | desc->chip->startup(irq); |
587 | } | 582 | } |
588 | spin_unlock_irqrestore(&desc->lock, flags); | 583 | spin_unlock_irqrestore(&desc->lock, flags); |
589 | } | 584 | } |
@@ -606,17 +601,14 @@ set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, | |||
606 | 601 | ||
607 | void __init set_irq_noprobe(unsigned int irq) | 602 | void __init set_irq_noprobe(unsigned int irq) |
608 | { | 603 | { |
609 | struct irq_desc *desc; | 604 | struct irq_desc *desc = irq_to_desc(irq); |
610 | unsigned long flags; | 605 | unsigned long flags; |
611 | 606 | ||
612 | if (irq >= NR_IRQS) { | 607 | if (!desc) { |
613 | printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq); | 608 | printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq); |
614 | |||
615 | return; | 609 | return; |
616 | } | 610 | } |
617 | 611 | ||
618 | desc = irq_desc + irq; | ||
619 | |||
620 | spin_lock_irqsave(&desc->lock, flags); | 612 | spin_lock_irqsave(&desc->lock, flags); |
621 | desc->status |= IRQ_NOPROBE; | 613 | desc->status |= IRQ_NOPROBE; |
622 | spin_unlock_irqrestore(&desc->lock, flags); | 614 | spin_unlock_irqrestore(&desc->lock, flags); |
@@ -624,17 +616,14 @@ void __init set_irq_noprobe(unsigned int irq) | |||
624 | 616 | ||
625 | void __init set_irq_probe(unsigned int irq) | 617 | void __init set_irq_probe(unsigned int irq) |
626 | { | 618 | { |
627 | struct irq_desc *desc; | 619 | struct irq_desc *desc = irq_to_desc(irq); |
628 | unsigned long flags; | 620 | unsigned long flags; |
629 | 621 | ||
630 | if (irq >= NR_IRQS) { | 622 | if (!desc) { |
631 | printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq); | 623 | printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq); |
632 | |||
633 | return; | 624 | return; |
634 | } | 625 | } |
635 | 626 | ||
636 | desc = irq_desc + irq; | ||
637 | |||
638 | spin_lock_irqsave(&desc->lock, flags); | 627 | spin_lock_irqsave(&desc->lock, flags); |
639 | desc->status &= ~IRQ_NOPROBE; | 628 | desc->status &= ~IRQ_NOPROBE; |
640 | spin_unlock_irqrestore(&desc->lock, flags); | 629 | spin_unlock_irqrestore(&desc->lock, flags); |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 5fa6198e9139..c815b42d0f5b 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -25,11 +25,10 @@ | |||
25 | * | 25 | * |
26 | * Handles spurious and unhandled IRQ's. It also prints a debugmessage. | 26 | * Handles spurious and unhandled IRQ's. It also prints a debugmessage. |
27 | */ | 27 | */ |
28 | void | 28 | void handle_bad_irq(unsigned int irq, struct irq_desc *desc) |
29 | handle_bad_irq(unsigned int irq, struct irq_desc *desc) | ||
30 | { | 29 | { |
31 | print_irq_desc(irq, desc); | 30 | print_irq_desc(irq, desc); |
32 | kstat_this_cpu.irqs[irq]++; | 31 | kstat_incr_irqs_this_cpu(irq, desc); |
33 | ack_bad_irq(irq); | 32 | ack_bad_irq(irq); |
34 | } | 33 | } |
35 | 34 | ||
@@ -47,6 +46,9 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc) | |||
47 | * | 46 | * |
48 | * Controller mappings for all interrupt sources: | 47 | * Controller mappings for all interrupt sources: |
49 | */ | 48 | */ |
49 | int nr_irqs = NR_IRQS; | ||
50 | EXPORT_SYMBOL_GPL(nr_irqs); | ||
51 | |||
50 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | 52 | struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { |
51 | [0 ... NR_IRQS-1] = { | 53 | [0 ... NR_IRQS-1] = { |
52 | .status = IRQ_DISABLED, | 54 | .status = IRQ_DISABLED, |
@@ -66,7 +68,9 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { | |||
66 | */ | 68 | */ |
67 | static void ack_bad(unsigned int irq) | 69 | static void ack_bad(unsigned int irq) |
68 | { | 70 | { |
69 | print_irq_desc(irq, irq_desc + irq); | 71 | struct irq_desc *desc = irq_to_desc(irq); |
72 | |||
73 | print_irq_desc(irq, desc); | ||
70 | ack_bad_irq(irq); | 74 | ack_bad_irq(irq); |
71 | } | 75 | } |
72 | 76 | ||
@@ -131,8 +135,6 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
131 | irqreturn_t ret, retval = IRQ_NONE; | 135 | irqreturn_t ret, retval = IRQ_NONE; |
132 | unsigned int status = 0; | 136 | unsigned int status = 0; |
133 | 137 | ||
134 | handle_dynamic_tick(action); | ||
135 | |||
136 | if (!(action->flags & IRQF_DISABLED)) | 138 | if (!(action->flags & IRQF_DISABLED)) |
137 | local_irq_enable_in_hardirq(); | 139 | local_irq_enable_in_hardirq(); |
138 | 140 | ||
@@ -165,11 +167,12 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
165 | */ | 167 | */ |
166 | unsigned int __do_IRQ(unsigned int irq) | 168 | unsigned int __do_IRQ(unsigned int irq) |
167 | { | 169 | { |
168 | struct irq_desc *desc = irq_desc + irq; | 170 | struct irq_desc *desc = irq_to_desc(irq); |
169 | struct irqaction *action; | 171 | struct irqaction *action; |
170 | unsigned int status; | 172 | unsigned int status; |
171 | 173 | ||
172 | kstat_this_cpu.irqs[irq]++; | 174 | kstat_incr_irqs_this_cpu(irq, desc); |
175 | |||
173 | if (CHECK_IRQ_PER_CPU(desc->status)) { | 176 | if (CHECK_IRQ_PER_CPU(desc->status)) { |
174 | irqreturn_t action_ret; | 177 | irqreturn_t action_ret; |
175 | 178 | ||
@@ -256,8 +259,8 @@ out: | |||
256 | } | 259 | } |
257 | #endif | 260 | #endif |
258 | 261 | ||
259 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
260 | 262 | ||
263 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
261 | /* | 264 | /* |
262 | * lockdep: we want to handle all irq_desc locks as a single lock-class: | 265 | * lockdep: we want to handle all irq_desc locks as a single lock-class: |
263 | */ | 266 | */ |
@@ -265,10 +268,10 @@ static struct lock_class_key irq_desc_lock_class; | |||
265 | 268 | ||
266 | void early_init_irq_lock_class(void) | 269 | void early_init_irq_lock_class(void) |
267 | { | 270 | { |
271 | struct irq_desc *desc; | ||
268 | int i; | 272 | int i; |
269 | 273 | ||
270 | for (i = 0; i < NR_IRQS; i++) | 274 | for_each_irq_desc(i, desc) |
271 | lockdep_set_class(&irq_desc[i].lock, &irq_desc_lock_class); | 275 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); |
272 | } | 276 | } |
273 | |||
274 | #endif | 277 | #endif |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 08a849a22447..c9767e641980 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -10,12 +10,15 @@ extern void irq_chip_set_defaults(struct irq_chip *chip); | |||
10 | /* Set default handler: */ | 10 | /* Set default handler: */ |
11 | extern void compat_irq_chip_set_default_handler(struct irq_desc *desc); | 11 | extern void compat_irq_chip_set_default_handler(struct irq_desc *desc); |
12 | 12 | ||
13 | extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | ||
14 | unsigned long flags); | ||
15 | |||
13 | #ifdef CONFIG_PROC_FS | 16 | #ifdef CONFIG_PROC_FS |
14 | extern void register_irq_proc(unsigned int irq); | 17 | extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); |
15 | extern void register_handler_proc(unsigned int irq, struct irqaction *action); | 18 | extern void register_handler_proc(unsigned int irq, struct irqaction *action); |
16 | extern void unregister_handler_proc(unsigned int irq, struct irqaction *action); | 19 | extern void unregister_handler_proc(unsigned int irq, struct irqaction *action); |
17 | #else | 20 | #else |
18 | static inline void register_irq_proc(unsigned int irq) { } | 21 | static inline void register_irq_proc(unsigned int irq, struct irq_desc *desc) { } |
19 | static inline void register_handler_proc(unsigned int irq, | 22 | static inline void register_handler_proc(unsigned int irq, |
20 | struct irqaction *action) { } | 23 | struct irqaction *action) { } |
21 | static inline void unregister_handler_proc(unsigned int irq, | 24 | static inline void unregister_handler_proc(unsigned int irq, |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 60c49e324390..c498a1b8c621 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -31,10 +31,10 @@ cpumask_t irq_default_affinity = CPU_MASK_ALL; | |||
31 | */ | 31 | */ |
32 | void synchronize_irq(unsigned int irq) | 32 | void synchronize_irq(unsigned int irq) |
33 | { | 33 | { |
34 | struct irq_desc *desc = irq_desc + irq; | 34 | struct irq_desc *desc = irq_to_desc(irq); |
35 | unsigned int status; | 35 | unsigned int status; |
36 | 36 | ||
37 | if (irq >= NR_IRQS) | 37 | if (!desc) |
38 | return; | 38 | return; |
39 | 39 | ||
40 | do { | 40 | do { |
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(synchronize_irq); | |||
64 | */ | 64 | */ |
65 | int irq_can_set_affinity(unsigned int irq) | 65 | int irq_can_set_affinity(unsigned int irq) |
66 | { | 66 | { |
67 | struct irq_desc *desc = irq_desc + irq; | 67 | struct irq_desc *desc = irq_to_desc(irq); |
68 | 68 | ||
69 | if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip || | 69 | if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip || |
70 | !desc->chip->set_affinity) | 70 | !desc->chip->set_affinity) |
@@ -81,18 +81,17 @@ int irq_can_set_affinity(unsigned int irq) | |||
81 | */ | 81 | */ |
82 | int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | 82 | int irq_set_affinity(unsigned int irq, cpumask_t cpumask) |
83 | { | 83 | { |
84 | struct irq_desc *desc = irq_desc + irq; | 84 | struct irq_desc *desc = irq_to_desc(irq); |
85 | 85 | ||
86 | if (!desc->chip->set_affinity) | 86 | if (!desc->chip->set_affinity) |
87 | return -EINVAL; | 87 | return -EINVAL; |
88 | 88 | ||
89 | set_balance_irq_affinity(irq, cpumask); | ||
90 | |||
91 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 89 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
92 | if (desc->status & IRQ_MOVE_PCNTXT) { | 90 | if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) { |
93 | unsigned long flags; | 91 | unsigned long flags; |
94 | 92 | ||
95 | spin_lock_irqsave(&desc->lock, flags); | 93 | spin_lock_irqsave(&desc->lock, flags); |
94 | desc->affinity = cpumask; | ||
96 | desc->chip->set_affinity(irq, cpumask); | 95 | desc->chip->set_affinity(irq, cpumask); |
97 | spin_unlock_irqrestore(&desc->lock, flags); | 96 | spin_unlock_irqrestore(&desc->lock, flags); |
98 | } else | 97 | } else |
@@ -111,16 +110,17 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | |||
111 | int irq_select_affinity(unsigned int irq) | 110 | int irq_select_affinity(unsigned int irq) |
112 | { | 111 | { |
113 | cpumask_t mask; | 112 | cpumask_t mask; |
113 | struct irq_desc *desc; | ||
114 | 114 | ||
115 | if (!irq_can_set_affinity(irq)) | 115 | if (!irq_can_set_affinity(irq)) |
116 | return 0; | 116 | return 0; |
117 | 117 | ||
118 | cpus_and(mask, cpu_online_map, irq_default_affinity); | 118 | cpus_and(mask, cpu_online_map, irq_default_affinity); |
119 | 119 | ||
120 | irq_desc[irq].affinity = mask; | 120 | desc = irq_to_desc(irq); |
121 | irq_desc[irq].chip->set_affinity(irq, mask); | 121 | desc->affinity = mask; |
122 | desc->chip->set_affinity(irq, mask); | ||
122 | 123 | ||
123 | set_balance_irq_affinity(irq, mask); | ||
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | #endif | 126 | #endif |
@@ -140,10 +140,10 @@ int irq_select_affinity(unsigned int irq) | |||
140 | */ | 140 | */ |
141 | void disable_irq_nosync(unsigned int irq) | 141 | void disable_irq_nosync(unsigned int irq) |
142 | { | 142 | { |
143 | struct irq_desc *desc = irq_desc + irq; | 143 | struct irq_desc *desc = irq_to_desc(irq); |
144 | unsigned long flags; | 144 | unsigned long flags; |
145 | 145 | ||
146 | if (irq >= NR_IRQS) | 146 | if (!desc) |
147 | return; | 147 | return; |
148 | 148 | ||
149 | spin_lock_irqsave(&desc->lock, flags); | 149 | spin_lock_irqsave(&desc->lock, flags); |
@@ -169,9 +169,9 @@ EXPORT_SYMBOL(disable_irq_nosync); | |||
169 | */ | 169 | */ |
170 | void disable_irq(unsigned int irq) | 170 | void disable_irq(unsigned int irq) |
171 | { | 171 | { |
172 | struct irq_desc *desc = irq_desc + irq; | 172 | struct irq_desc *desc = irq_to_desc(irq); |
173 | 173 | ||
174 | if (irq >= NR_IRQS) | 174 | if (!desc) |
175 | return; | 175 | return; |
176 | 176 | ||
177 | disable_irq_nosync(irq); | 177 | disable_irq_nosync(irq); |
@@ -211,10 +211,10 @@ static void __enable_irq(struct irq_desc *desc, unsigned int irq) | |||
211 | */ | 211 | */ |
212 | void enable_irq(unsigned int irq) | 212 | void enable_irq(unsigned int irq) |
213 | { | 213 | { |
214 | struct irq_desc *desc = irq_desc + irq; | 214 | struct irq_desc *desc = irq_to_desc(irq); |
215 | unsigned long flags; | 215 | unsigned long flags; |
216 | 216 | ||
217 | if (irq >= NR_IRQS) | 217 | if (!desc) |
218 | return; | 218 | return; |
219 | 219 | ||
220 | spin_lock_irqsave(&desc->lock, flags); | 220 | spin_lock_irqsave(&desc->lock, flags); |
@@ -223,9 +223,9 @@ void enable_irq(unsigned int irq) | |||
223 | } | 223 | } |
224 | EXPORT_SYMBOL(enable_irq); | 224 | EXPORT_SYMBOL(enable_irq); |
225 | 225 | ||
226 | int set_irq_wake_real(unsigned int irq, unsigned int on) | 226 | static int set_irq_wake_real(unsigned int irq, unsigned int on) |
227 | { | 227 | { |
228 | struct irq_desc *desc = irq_desc + irq; | 228 | struct irq_desc *desc = irq_to_desc(irq); |
229 | int ret = -ENXIO; | 229 | int ret = -ENXIO; |
230 | 230 | ||
231 | if (desc->chip->set_wake) | 231 | if (desc->chip->set_wake) |
@@ -248,7 +248,7 @@ int set_irq_wake_real(unsigned int irq, unsigned int on) | |||
248 | */ | 248 | */ |
249 | int set_irq_wake(unsigned int irq, unsigned int on) | 249 | int set_irq_wake(unsigned int irq, unsigned int on) |
250 | { | 250 | { |
251 | struct irq_desc *desc = irq_desc + irq; | 251 | struct irq_desc *desc = irq_to_desc(irq); |
252 | unsigned long flags; | 252 | unsigned long flags; |
253 | int ret = 0; | 253 | int ret = 0; |
254 | 254 | ||
@@ -288,12 +288,16 @@ EXPORT_SYMBOL(set_irq_wake); | |||
288 | */ | 288 | */ |
289 | int can_request_irq(unsigned int irq, unsigned long irqflags) | 289 | int can_request_irq(unsigned int irq, unsigned long irqflags) |
290 | { | 290 | { |
291 | struct irq_desc *desc = irq_to_desc(irq); | ||
291 | struct irqaction *action; | 292 | struct irqaction *action; |
292 | 293 | ||
293 | if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST) | 294 | if (!desc) |
295 | return 0; | ||
296 | |||
297 | if (desc->status & IRQ_NOREQUEST) | ||
294 | return 0; | 298 | return 0; |
295 | 299 | ||
296 | action = irq_desc[irq].action; | 300 | action = desc->action; |
297 | if (action) | 301 | if (action) |
298 | if (irqflags & action->flags & IRQF_SHARED) | 302 | if (irqflags & action->flags & IRQF_SHARED) |
299 | action = NULL; | 303 | action = NULL; |
@@ -312,10 +316,11 @@ void compat_irq_chip_set_default_handler(struct irq_desc *desc) | |||
312 | desc->handle_irq = NULL; | 316 | desc->handle_irq = NULL; |
313 | } | 317 | } |
314 | 318 | ||
315 | static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq, | 319 | int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, |
316 | unsigned long flags) | 320 | unsigned long flags) |
317 | { | 321 | { |
318 | int ret; | 322 | int ret; |
323 | struct irq_chip *chip = desc->chip; | ||
319 | 324 | ||
320 | if (!chip || !chip->set_type) { | 325 | if (!chip || !chip->set_type) { |
321 | /* | 326 | /* |
@@ -333,6 +338,11 @@ static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq, | |||
333 | pr_err("setting trigger mode %d for irq %u failed (%pF)\n", | 338 | pr_err("setting trigger mode %d for irq %u failed (%pF)\n", |
334 | (int)(flags & IRQF_TRIGGER_MASK), | 339 | (int)(flags & IRQF_TRIGGER_MASK), |
335 | irq, chip->set_type); | 340 | irq, chip->set_type); |
341 | else { | ||
342 | /* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */ | ||
343 | desc->status &= ~IRQ_TYPE_SENSE_MASK; | ||
344 | desc->status |= flags & IRQ_TYPE_SENSE_MASK; | ||
345 | } | ||
336 | 346 | ||
337 | return ret; | 347 | return ret; |
338 | } | 348 | } |
@@ -341,16 +351,16 @@ static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq, | |||
341 | * Internal function to register an irqaction - typically used to | 351 | * Internal function to register an irqaction - typically used to |
342 | * allocate special interrupts that are part of the architecture. | 352 | * allocate special interrupts that are part of the architecture. |
343 | */ | 353 | */ |
344 | int setup_irq(unsigned int irq, struct irqaction *new) | 354 | static int |
355 | __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | ||
345 | { | 356 | { |
346 | struct irq_desc *desc = irq_desc + irq; | ||
347 | struct irqaction *old, **p; | 357 | struct irqaction *old, **p; |
348 | const char *old_name = NULL; | 358 | const char *old_name = NULL; |
349 | unsigned long flags; | 359 | unsigned long flags; |
350 | int shared = 0; | 360 | int shared = 0; |
351 | int ret; | 361 | int ret; |
352 | 362 | ||
353 | if (irq >= NR_IRQS) | 363 | if (!desc) |
354 | return -EINVAL; | 364 | return -EINVAL; |
355 | 365 | ||
356 | if (desc->chip == &no_irq_chip) | 366 | if (desc->chip == &no_irq_chip) |
@@ -411,7 +421,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
411 | 421 | ||
412 | /* Setup the type (level, edge polarity) if configured: */ | 422 | /* Setup the type (level, edge polarity) if configured: */ |
413 | if (new->flags & IRQF_TRIGGER_MASK) { | 423 | if (new->flags & IRQF_TRIGGER_MASK) { |
414 | ret = __irq_set_trigger(desc->chip, irq, new->flags); | 424 | ret = __irq_set_trigger(desc, irq, new->flags); |
415 | 425 | ||
416 | if (ret) { | 426 | if (ret) { |
417 | spin_unlock_irqrestore(&desc->lock, flags); | 427 | spin_unlock_irqrestore(&desc->lock, flags); |
@@ -430,16 +440,21 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
430 | if (!(desc->status & IRQ_NOAUTOEN)) { | 440 | if (!(desc->status & IRQ_NOAUTOEN)) { |
431 | desc->depth = 0; | 441 | desc->depth = 0; |
432 | desc->status &= ~IRQ_DISABLED; | 442 | desc->status &= ~IRQ_DISABLED; |
433 | if (desc->chip->startup) | 443 | desc->chip->startup(irq); |
434 | desc->chip->startup(irq); | ||
435 | else | ||
436 | desc->chip->enable(irq); | ||
437 | } else | 444 | } else |
438 | /* Undo nested disables: */ | 445 | /* Undo nested disables: */ |
439 | desc->depth = 1; | 446 | desc->depth = 1; |
440 | 447 | ||
441 | /* Set default affinity mask once everything is setup */ | 448 | /* Set default affinity mask once everything is setup */ |
442 | irq_select_affinity(irq); | 449 | irq_select_affinity(irq); |
450 | |||
451 | } else if ((new->flags & IRQF_TRIGGER_MASK) | ||
452 | && (new->flags & IRQF_TRIGGER_MASK) | ||
453 | != (desc->status & IRQ_TYPE_SENSE_MASK)) { | ||
454 | /* hope the handler works with the actual trigger mode... */ | ||
455 | pr_warning("IRQ %d uses trigger mode %d; requested %d\n", | ||
456 | irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK), | ||
457 | (int)(new->flags & IRQF_TRIGGER_MASK)); | ||
443 | } | 458 | } |
444 | 459 | ||
445 | *p = new; | 460 | *p = new; |
@@ -464,7 +479,7 @@ int setup_irq(unsigned int irq, struct irqaction *new) | |||
464 | spin_unlock_irqrestore(&desc->lock, flags); | 479 | spin_unlock_irqrestore(&desc->lock, flags); |
465 | 480 | ||
466 | new->irq = irq; | 481 | new->irq = irq; |
467 | register_irq_proc(irq); | 482 | register_irq_proc(irq, desc); |
468 | new->dir = NULL; | 483 | new->dir = NULL; |
469 | register_handler_proc(irq, new); | 484 | register_handler_proc(irq, new); |
470 | 485 | ||
@@ -484,6 +499,20 @@ mismatch: | |||
484 | } | 499 | } |
485 | 500 | ||
486 | /** | 501 | /** |
502 | * setup_irq - setup an interrupt | ||
503 | * @irq: Interrupt line to setup | ||
504 | * @act: irqaction for the interrupt | ||
505 | * | ||
506 | * Used to statically setup interrupts in the early boot process. | ||
507 | */ | ||
508 | int setup_irq(unsigned int irq, struct irqaction *act) | ||
509 | { | ||
510 | struct irq_desc *desc = irq_to_desc(irq); | ||
511 | |||
512 | return __setup_irq(irq, desc, act); | ||
513 | } | ||
514 | |||
515 | /** | ||
487 | * free_irq - free an interrupt | 516 | * free_irq - free an interrupt |
488 | * @irq: Interrupt line to free | 517 | * @irq: Interrupt line to free |
489 | * @dev_id: Device identity to free | 518 | * @dev_id: Device identity to free |
@@ -499,15 +528,15 @@ mismatch: | |||
499 | */ | 528 | */ |
500 | void free_irq(unsigned int irq, void *dev_id) | 529 | void free_irq(unsigned int irq, void *dev_id) |
501 | { | 530 | { |
502 | struct irq_desc *desc; | 531 | struct irq_desc *desc = irq_to_desc(irq); |
503 | struct irqaction **p; | 532 | struct irqaction **p; |
504 | unsigned long flags; | 533 | unsigned long flags; |
505 | 534 | ||
506 | WARN_ON(in_interrupt()); | 535 | WARN_ON(in_interrupt()); |
507 | if (irq >= NR_IRQS) | 536 | |
537 | if (!desc) | ||
508 | return; | 538 | return; |
509 | 539 | ||
510 | desc = irq_desc + irq; | ||
511 | spin_lock_irqsave(&desc->lock, flags); | 540 | spin_lock_irqsave(&desc->lock, flags); |
512 | p = &desc->action; | 541 | p = &desc->action; |
513 | for (;;) { | 542 | for (;;) { |
@@ -596,12 +625,14 @@ EXPORT_SYMBOL(free_irq); | |||
596 | * IRQF_SHARED Interrupt is shared | 625 | * IRQF_SHARED Interrupt is shared |
597 | * IRQF_DISABLED Disable local interrupts while processing | 626 | * IRQF_DISABLED Disable local interrupts while processing |
598 | * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy | 627 | * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy |
628 | * IRQF_TRIGGER_* Specify active edge(s) or level | ||
599 | * | 629 | * |
600 | */ | 630 | */ |
601 | int request_irq(unsigned int irq, irq_handler_t handler, | 631 | int request_irq(unsigned int irq, irq_handler_t handler, |
602 | unsigned long irqflags, const char *devname, void *dev_id) | 632 | unsigned long irqflags, const char *devname, void *dev_id) |
603 | { | 633 | { |
604 | struct irqaction *action; | 634 | struct irqaction *action; |
635 | struct irq_desc *desc; | ||
605 | int retval; | 636 | int retval; |
606 | 637 | ||
607 | #ifdef CONFIG_LOCKDEP | 638 | #ifdef CONFIG_LOCKDEP |
@@ -618,9 +649,12 @@ int request_irq(unsigned int irq, irq_handler_t handler, | |||
618 | */ | 649 | */ |
619 | if ((irqflags & IRQF_SHARED) && !dev_id) | 650 | if ((irqflags & IRQF_SHARED) && !dev_id) |
620 | return -EINVAL; | 651 | return -EINVAL; |
621 | if (irq >= NR_IRQS) | 652 | |
653 | desc = irq_to_desc(irq); | ||
654 | if (!desc) | ||
622 | return -EINVAL; | 655 | return -EINVAL; |
623 | if (irq_desc[irq].status & IRQ_NOREQUEST) | 656 | |
657 | if (desc->status & IRQ_NOREQUEST) | ||
624 | return -EINVAL; | 658 | return -EINVAL; |
625 | if (!handler) | 659 | if (!handler) |
626 | return -EINVAL; | 660 | return -EINVAL; |
@@ -636,26 +670,29 @@ int request_irq(unsigned int irq, irq_handler_t handler, | |||
636 | action->next = NULL; | 670 | action->next = NULL; |
637 | action->dev_id = dev_id; | 671 | action->dev_id = dev_id; |
638 | 672 | ||
673 | retval = __setup_irq(irq, desc, action); | ||
674 | if (retval) | ||
675 | kfree(action); | ||
676 | |||
639 | #ifdef CONFIG_DEBUG_SHIRQ | 677 | #ifdef CONFIG_DEBUG_SHIRQ |
640 | if (irqflags & IRQF_SHARED) { | 678 | if (irqflags & IRQF_SHARED) { |
641 | /* | 679 | /* |
642 | * It's a shared IRQ -- the driver ought to be prepared for it | 680 | * It's a shared IRQ -- the driver ought to be prepared for it |
643 | * to happen immediately, so let's make sure.... | 681 | * to happen immediately, so let's make sure.... |
644 | * We do this before actually registering it, to make sure that | 682 | * We disable the irq to make sure that a 'real' IRQ doesn't |
645 | * a 'real' IRQ doesn't run in parallel with our fake | 683 | * run in parallel with our fake. |
646 | */ | 684 | */ |
647 | unsigned long flags; | 685 | unsigned long flags; |
648 | 686 | ||
687 | disable_irq(irq); | ||
649 | local_irq_save(flags); | 688 | local_irq_save(flags); |
689 | |||
650 | handler(irq, dev_id); | 690 | handler(irq, dev_id); |
691 | |||
651 | local_irq_restore(flags); | 692 | local_irq_restore(flags); |
693 | enable_irq(irq); | ||
652 | } | 694 | } |
653 | #endif | 695 | #endif |
654 | |||
655 | retval = setup_irq(irq, action); | ||
656 | if (retval) | ||
657 | kfree(action); | ||
658 | |||
659 | return retval; | 696 | return retval; |
660 | } | 697 | } |
661 | EXPORT_SYMBOL(request_irq); | 698 | EXPORT_SYMBOL(request_irq); |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index 77b7acc875c5..90b920d3f52b 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -3,18 +3,18 @@ | |||
3 | 3 | ||
4 | void set_pending_irq(unsigned int irq, cpumask_t mask) | 4 | void set_pending_irq(unsigned int irq, cpumask_t mask) |
5 | { | 5 | { |
6 | struct irq_desc *desc = irq_desc + irq; | 6 | struct irq_desc *desc = irq_to_desc(irq); |
7 | unsigned long flags; | 7 | unsigned long flags; |
8 | 8 | ||
9 | spin_lock_irqsave(&desc->lock, flags); | 9 | spin_lock_irqsave(&desc->lock, flags); |
10 | desc->status |= IRQ_MOVE_PENDING; | 10 | desc->status |= IRQ_MOVE_PENDING; |
11 | irq_desc[irq].pending_mask = mask; | 11 | desc->pending_mask = mask; |
12 | spin_unlock_irqrestore(&desc->lock, flags); | 12 | spin_unlock_irqrestore(&desc->lock, flags); |
13 | } | 13 | } |
14 | 14 | ||
15 | void move_masked_irq(int irq) | 15 | void move_masked_irq(int irq) |
16 | { | 16 | { |
17 | struct irq_desc *desc = irq_desc + irq; | 17 | struct irq_desc *desc = irq_to_desc(irq); |
18 | cpumask_t tmp; | 18 | cpumask_t tmp; |
19 | 19 | ||
20 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) | 20 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) |
@@ -30,7 +30,7 @@ void move_masked_irq(int irq) | |||
30 | 30 | ||
31 | desc->status &= ~IRQ_MOVE_PENDING; | 31 | desc->status &= ~IRQ_MOVE_PENDING; |
32 | 32 | ||
33 | if (unlikely(cpus_empty(irq_desc[irq].pending_mask))) | 33 | if (unlikely(cpus_empty(desc->pending_mask))) |
34 | return; | 34 | return; |
35 | 35 | ||
36 | if (!desc->chip->set_affinity) | 36 | if (!desc->chip->set_affinity) |
@@ -38,7 +38,7 @@ void move_masked_irq(int irq) | |||
38 | 38 | ||
39 | assert_spin_locked(&desc->lock); | 39 | assert_spin_locked(&desc->lock); |
40 | 40 | ||
41 | cpus_and(tmp, irq_desc[irq].pending_mask, cpu_online_map); | 41 | cpus_and(tmp, desc->pending_mask, cpu_online_map); |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * If there was a valid mask to work with, please | 44 | * If there was a valid mask to work with, please |
@@ -55,12 +55,12 @@ void move_masked_irq(int irq) | |||
55 | if (likely(!cpus_empty(tmp))) { | 55 | if (likely(!cpus_empty(tmp))) { |
56 | desc->chip->set_affinity(irq,tmp); | 56 | desc->chip->set_affinity(irq,tmp); |
57 | } | 57 | } |
58 | cpus_clear(irq_desc[irq].pending_mask); | 58 | cpus_clear(desc->pending_mask); |
59 | } | 59 | } |
60 | 60 | ||
61 | void move_native_irq(int irq) | 61 | void move_native_irq(int irq) |
62 | { | 62 | { |
63 | struct irq_desc *desc = irq_desc + irq; | 63 | struct irq_desc *desc = irq_to_desc(irq); |
64 | 64 | ||
65 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) | 65 | if (likely(!(desc->status & IRQ_MOVE_PENDING))) |
66 | return; | 66 | return; |
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index a09dd29c2fd7..fac014a81b24 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
@@ -19,7 +19,7 @@ static struct proc_dir_entry *root_irq_dir; | |||
19 | 19 | ||
20 | static int irq_affinity_proc_show(struct seq_file *m, void *v) | 20 | static int irq_affinity_proc_show(struct seq_file *m, void *v) |
21 | { | 21 | { |
22 | struct irq_desc *desc = irq_desc + (long)m->private; | 22 | struct irq_desc *desc = irq_to_desc((long)m->private); |
23 | cpumask_t *mask = &desc->affinity; | 23 | cpumask_t *mask = &desc->affinity; |
24 | 24 | ||
25 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 25 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
@@ -43,7 +43,7 @@ static ssize_t irq_affinity_proc_write(struct file *file, | |||
43 | cpumask_t new_value; | 43 | cpumask_t new_value; |
44 | int err; | 44 | int err; |
45 | 45 | ||
46 | if (!irq_desc[irq].chip->set_affinity || no_irq_affinity || | 46 | if (!irq_to_desc(irq)->chip->set_affinity || no_irq_affinity || |
47 | irq_balancing_disabled(irq)) | 47 | irq_balancing_disabled(irq)) |
48 | return -EIO; | 48 | return -EIO; |
49 | 49 | ||
@@ -132,20 +132,20 @@ static const struct file_operations default_affinity_proc_fops = { | |||
132 | static int irq_spurious_read(char *page, char **start, off_t off, | 132 | static int irq_spurious_read(char *page, char **start, off_t off, |
133 | int count, int *eof, void *data) | 133 | int count, int *eof, void *data) |
134 | { | 134 | { |
135 | struct irq_desc *d = &irq_desc[(long) data]; | 135 | struct irq_desc *desc = irq_to_desc((long) data); |
136 | return sprintf(page, "count %u\n" | 136 | return sprintf(page, "count %u\n" |
137 | "unhandled %u\n" | 137 | "unhandled %u\n" |
138 | "last_unhandled %u ms\n", | 138 | "last_unhandled %u ms\n", |
139 | d->irq_count, | 139 | desc->irq_count, |
140 | d->irqs_unhandled, | 140 | desc->irqs_unhandled, |
141 | jiffies_to_msecs(d->last_unhandled)); | 141 | jiffies_to_msecs(desc->last_unhandled)); |
142 | } | 142 | } |
143 | 143 | ||
144 | #define MAX_NAMELEN 128 | 144 | #define MAX_NAMELEN 128 |
145 | 145 | ||
146 | static int name_unique(unsigned int irq, struct irqaction *new_action) | 146 | static int name_unique(unsigned int irq, struct irqaction *new_action) |
147 | { | 147 | { |
148 | struct irq_desc *desc = irq_desc + irq; | 148 | struct irq_desc *desc = irq_to_desc(irq); |
149 | struct irqaction *action; | 149 | struct irqaction *action; |
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | int ret = 1; | 151 | int ret = 1; |
@@ -165,8 +165,9 @@ static int name_unique(unsigned int irq, struct irqaction *new_action) | |||
165 | void register_handler_proc(unsigned int irq, struct irqaction *action) | 165 | void register_handler_proc(unsigned int irq, struct irqaction *action) |
166 | { | 166 | { |
167 | char name [MAX_NAMELEN]; | 167 | char name [MAX_NAMELEN]; |
168 | struct irq_desc *desc = irq_to_desc(irq); | ||
168 | 169 | ||
169 | if (!irq_desc[irq].dir || action->dir || !action->name || | 170 | if (!desc->dir || action->dir || !action->name || |
170 | !name_unique(irq, action)) | 171 | !name_unique(irq, action)) |
171 | return; | 172 | return; |
172 | 173 | ||
@@ -174,36 +175,34 @@ void register_handler_proc(unsigned int irq, struct irqaction *action) | |||
174 | snprintf(name, MAX_NAMELEN, "%s", action->name); | 175 | snprintf(name, MAX_NAMELEN, "%s", action->name); |
175 | 176 | ||
176 | /* create /proc/irq/1234/handler/ */ | 177 | /* create /proc/irq/1234/handler/ */ |
177 | action->dir = proc_mkdir(name, irq_desc[irq].dir); | 178 | action->dir = proc_mkdir(name, desc->dir); |
178 | } | 179 | } |
179 | 180 | ||
180 | #undef MAX_NAMELEN | 181 | #undef MAX_NAMELEN |
181 | 182 | ||
182 | #define MAX_NAMELEN 10 | 183 | #define MAX_NAMELEN 10 |
183 | 184 | ||
184 | void register_irq_proc(unsigned int irq) | 185 | void register_irq_proc(unsigned int irq, struct irq_desc *desc) |
185 | { | 186 | { |
186 | char name [MAX_NAMELEN]; | 187 | char name [MAX_NAMELEN]; |
187 | struct proc_dir_entry *entry; | 188 | struct proc_dir_entry *entry; |
188 | 189 | ||
189 | if (!root_irq_dir || | 190 | if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir) |
190 | (irq_desc[irq].chip == &no_irq_chip) || | ||
191 | irq_desc[irq].dir) | ||
192 | return; | 191 | return; |
193 | 192 | ||
194 | memset(name, 0, MAX_NAMELEN); | 193 | memset(name, 0, MAX_NAMELEN); |
195 | sprintf(name, "%d", irq); | 194 | sprintf(name, "%d", irq); |
196 | 195 | ||
197 | /* create /proc/irq/1234 */ | 196 | /* create /proc/irq/1234 */ |
198 | irq_desc[irq].dir = proc_mkdir(name, root_irq_dir); | 197 | desc->dir = proc_mkdir(name, root_irq_dir); |
199 | 198 | ||
200 | #ifdef CONFIG_SMP | 199 | #ifdef CONFIG_SMP |
201 | /* create /proc/irq/<irq>/smp_affinity */ | 200 | /* create /proc/irq/<irq>/smp_affinity */ |
202 | proc_create_data("smp_affinity", 0600, irq_desc[irq].dir, | 201 | proc_create_data("smp_affinity", 0600, desc->dir, |
203 | &irq_affinity_proc_fops, (void *)(long)irq); | 202 | &irq_affinity_proc_fops, (void *)(long)irq); |
204 | #endif | 203 | #endif |
205 | 204 | ||
206 | entry = create_proc_entry("spurious", 0444, irq_desc[irq].dir); | 205 | entry = create_proc_entry("spurious", 0444, desc->dir); |
207 | if (entry) { | 206 | if (entry) { |
208 | entry->data = (void *)(long)irq; | 207 | entry->data = (void *)(long)irq; |
209 | entry->read_proc = irq_spurious_read; | 208 | entry->read_proc = irq_spurious_read; |
@@ -214,8 +213,11 @@ void register_irq_proc(unsigned int irq) | |||
214 | 213 | ||
215 | void unregister_handler_proc(unsigned int irq, struct irqaction *action) | 214 | void unregister_handler_proc(unsigned int irq, struct irqaction *action) |
216 | { | 215 | { |
217 | if (action->dir) | 216 | if (action->dir) { |
218 | remove_proc_entry(action->dir->name, irq_desc[irq].dir); | 217 | struct irq_desc *desc = irq_to_desc(irq); |
218 | |||
219 | remove_proc_entry(action->dir->name, desc->dir); | ||
220 | } | ||
219 | } | 221 | } |
220 | 222 | ||
221 | void register_default_affinity_proc(void) | 223 | void register_default_affinity_proc(void) |
@@ -228,7 +230,8 @@ void register_default_affinity_proc(void) | |||
228 | 230 | ||
229 | void init_irq_proc(void) | 231 | void init_irq_proc(void) |
230 | { | 232 | { |
231 | int i; | 233 | unsigned int irq; |
234 | struct irq_desc *desc; | ||
232 | 235 | ||
233 | /* create /proc/irq */ | 236 | /* create /proc/irq */ |
234 | root_irq_dir = proc_mkdir("irq", NULL); | 237 | root_irq_dir = proc_mkdir("irq", NULL); |
@@ -240,7 +243,7 @@ void init_irq_proc(void) | |||
240 | /* | 243 | /* |
241 | * Create entries for all existing IRQs. | 244 | * Create entries for all existing IRQs. |
242 | */ | 245 | */ |
243 | for (i = 0; i < NR_IRQS; i++) | 246 | for_each_irq_desc(irq, desc) |
244 | register_irq_proc(i); | 247 | register_irq_proc(irq, desc); |
245 | } | 248 | } |
246 | 249 | ||
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c index a8046791ba2d..89c7117acf2b 100644 --- a/kernel/irq/resend.c +++ b/kernel/irq/resend.c | |||
@@ -33,10 +33,10 @@ static void resend_irqs(unsigned long arg) | |||
33 | struct irq_desc *desc; | 33 | struct irq_desc *desc; |
34 | int irq; | 34 | int irq; |
35 | 35 | ||
36 | while (!bitmap_empty(irqs_resend, NR_IRQS)) { | 36 | while (!bitmap_empty(irqs_resend, nr_irqs)) { |
37 | irq = find_first_bit(irqs_resend, NR_IRQS); | 37 | irq = find_first_bit(irqs_resend, nr_irqs); |
38 | clear_bit(irq, irqs_resend); | 38 | clear_bit(irq, irqs_resend); |
39 | desc = irq_desc + irq; | 39 | desc = irq_to_desc(irq); |
40 | local_irq_disable(); | 40 | local_irq_disable(); |
41 | desc->handle_irq(irq, desc); | 41 | desc->handle_irq(irq, desc); |
42 | local_irq_enable(); | 42 | local_irq_enable(); |
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index c66d3f10e853..dd364c11e56e 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
@@ -12,83 +12,122 @@ | |||
12 | #include <linux/kallsyms.h> | 12 | #include <linux/kallsyms.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/timer.h> | ||
15 | 16 | ||
16 | static int irqfixup __read_mostly; | 17 | static int irqfixup __read_mostly; |
17 | 18 | ||
19 | #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10) | ||
20 | static void poll_spurious_irqs(unsigned long dummy); | ||
21 | static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); | ||
22 | |||
18 | /* | 23 | /* |
19 | * Recovery handler for misrouted interrupts. | 24 | * Recovery handler for misrouted interrupts. |
20 | */ | 25 | */ |
21 | static int misrouted_irq(int irq) | 26 | static int try_one_irq(int irq, struct irq_desc *desc) |
22 | { | 27 | { |
23 | int i; | 28 | struct irqaction *action; |
24 | int ok = 0; | 29 | int ok = 0, work = 0; |
25 | int work = 0; /* Did we do work for a real IRQ */ | ||
26 | |||
27 | for (i = 1; i < NR_IRQS; i++) { | ||
28 | struct irq_desc *desc = irq_desc + i; | ||
29 | struct irqaction *action; | ||
30 | |||
31 | if (i == irq) /* Already tried */ | ||
32 | continue; | ||
33 | 30 | ||
34 | spin_lock(&desc->lock); | 31 | spin_lock(&desc->lock); |
35 | /* Already running on another processor */ | 32 | /* Already running on another processor */ |
36 | if (desc->status & IRQ_INPROGRESS) { | 33 | if (desc->status & IRQ_INPROGRESS) { |
37 | /* | 34 | /* |
38 | * Already running: If it is shared get the other | 35 | * Already running: If it is shared get the other |
39 | * CPU to go looking for our mystery interrupt too | 36 | * CPU to go looking for our mystery interrupt too |
40 | */ | 37 | */ |
41 | if (desc->action && (desc->action->flags & IRQF_SHARED)) | 38 | if (desc->action && (desc->action->flags & IRQF_SHARED)) |
42 | desc->status |= IRQ_PENDING; | 39 | desc->status |= IRQ_PENDING; |
43 | spin_unlock(&desc->lock); | ||
44 | continue; | ||
45 | } | ||
46 | /* Honour the normal IRQ locking */ | ||
47 | desc->status |= IRQ_INPROGRESS; | ||
48 | action = desc->action; | ||
49 | spin_unlock(&desc->lock); | 40 | spin_unlock(&desc->lock); |
41 | return ok; | ||
42 | } | ||
43 | /* Honour the normal IRQ locking */ | ||
44 | desc->status |= IRQ_INPROGRESS; | ||
45 | action = desc->action; | ||
46 | spin_unlock(&desc->lock); | ||
50 | 47 | ||
51 | while (action) { | 48 | while (action) { |
52 | /* Only shared IRQ handlers are safe to call */ | 49 | /* Only shared IRQ handlers are safe to call */ |
53 | if (action->flags & IRQF_SHARED) { | 50 | if (action->flags & IRQF_SHARED) { |
54 | if (action->handler(i, action->dev_id) == | 51 | if (action->handler(irq, action->dev_id) == |
55 | IRQ_HANDLED) | 52 | IRQ_HANDLED) |
56 | ok = 1; | 53 | ok = 1; |
57 | } | ||
58 | action = action->next; | ||
59 | } | 54 | } |
60 | local_irq_disable(); | 55 | action = action->next; |
61 | /* Now clean up the flags */ | 56 | } |
62 | spin_lock(&desc->lock); | 57 | local_irq_disable(); |
63 | action = desc->action; | 58 | /* Now clean up the flags */ |
59 | spin_lock(&desc->lock); | ||
60 | action = desc->action; | ||
64 | 61 | ||
62 | /* | ||
63 | * While we were looking for a fixup someone queued a real | ||
64 | * IRQ clashing with our walk: | ||
65 | */ | ||
66 | while ((desc->status & IRQ_PENDING) && action) { | ||
65 | /* | 67 | /* |
66 | * While we were looking for a fixup someone queued a real | 68 | * Perform real IRQ processing for the IRQ we deferred |
67 | * IRQ clashing with our walk: | ||
68 | */ | ||
69 | while ((desc->status & IRQ_PENDING) && action) { | ||
70 | /* | ||
71 | * Perform real IRQ processing for the IRQ we deferred | ||
72 | */ | ||
73 | work = 1; | ||
74 | spin_unlock(&desc->lock); | ||
75 | handle_IRQ_event(i, action); | ||
76 | spin_lock(&desc->lock); | ||
77 | desc->status &= ~IRQ_PENDING; | ||
78 | } | ||
79 | desc->status &= ~IRQ_INPROGRESS; | ||
80 | /* | ||
81 | * If we did actual work for the real IRQ line we must let the | ||
82 | * IRQ controller clean up too | ||
83 | */ | 69 | */ |
84 | if (work && desc->chip && desc->chip->end) | 70 | work = 1; |
85 | desc->chip->end(i); | ||
86 | spin_unlock(&desc->lock); | 71 | spin_unlock(&desc->lock); |
72 | handle_IRQ_event(irq, action); | ||
73 | spin_lock(&desc->lock); | ||
74 | desc->status &= ~IRQ_PENDING; | ||
75 | } | ||
76 | desc->status &= ~IRQ_INPROGRESS; | ||
77 | /* | ||
78 | * If we did actual work for the real IRQ line we must let the | ||
79 | * IRQ controller clean up too | ||
80 | */ | ||
81 | if (work && desc->chip && desc->chip->end) | ||
82 | desc->chip->end(irq); | ||
83 | spin_unlock(&desc->lock); | ||
84 | |||
85 | return ok; | ||
86 | } | ||
87 | |||
88 | static int misrouted_irq(int irq) | ||
89 | { | ||
90 | struct irq_desc *desc; | ||
91 | int i, ok = 0; | ||
92 | |||
93 | for_each_irq_desc(i, desc) { | ||
94 | if (!i) | ||
95 | continue; | ||
96 | |||
97 | if (i == irq) /* Already tried */ | ||
98 | continue; | ||
99 | |||
100 | if (try_one_irq(i, desc)) | ||
101 | ok = 1; | ||
87 | } | 102 | } |
88 | /* So the caller can adjust the irq error counts */ | 103 | /* So the caller can adjust the irq error counts */ |
89 | return ok; | 104 | return ok; |
90 | } | 105 | } |
91 | 106 | ||
107 | static void poll_spurious_irqs(unsigned long dummy) | ||
108 | { | ||
109 | struct irq_desc *desc; | ||
110 | int i; | ||
111 | |||
112 | for_each_irq_desc(i, desc) { | ||
113 | unsigned int status; | ||
114 | |||
115 | if (!i) | ||
116 | continue; | ||
117 | |||
118 | /* Racy but it doesn't matter */ | ||
119 | status = desc->status; | ||
120 | barrier(); | ||
121 | if (!(status & IRQ_SPURIOUS_DISABLED)) | ||
122 | continue; | ||
123 | |||
124 | try_one_irq(i, desc); | ||
125 | } | ||
126 | |||
127 | mod_timer(&poll_spurious_irq_timer, | ||
128 | jiffies + POLL_SPURIOUS_IRQ_INTERVAL); | ||
129 | } | ||
130 | |||
92 | /* | 131 | /* |
93 | * If 99,900 of the previous 100,000 interrupts have not been handled | 132 | * If 99,900 of the previous 100,000 interrupts have not been handled |
94 | * then assume that the IRQ is stuck in some manner. Drop a diagnostic | 133 | * then assume that the IRQ is stuck in some manner. Drop a diagnostic |
@@ -137,7 +176,9 @@ report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) | |||
137 | } | 176 | } |
138 | } | 177 | } |
139 | 178 | ||
140 | static inline int try_misrouted_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) | 179 | static inline int |
180 | try_misrouted_irq(unsigned int irq, struct irq_desc *desc, | ||
181 | irqreturn_t action_ret) | ||
141 | { | 182 | { |
142 | struct irqaction *action; | 183 | struct irqaction *action; |
143 | 184 | ||
@@ -212,6 +253,9 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, | |||
212 | desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED; | 253 | desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED; |
213 | desc->depth++; | 254 | desc->depth++; |
214 | desc->chip->disable(irq); | 255 | desc->chip->disable(irq); |
256 | |||
257 | mod_timer(&poll_spurious_irq_timer, | ||
258 | jiffies + POLL_SPURIOUS_IRQ_INTERVAL); | ||
215 | } | 259 | } |
216 | desc->irqs_unhandled = 0; | 260 | desc->irqs_unhandled = 0; |
217 | } | 261 | } |
@@ -241,7 +285,7 @@ static int __init irqfixup_setup(char *str) | |||
241 | 285 | ||
242 | __setup("irqfixup", irqfixup_setup); | 286 | __setup("irqfixup", irqfixup_setup); |
243 | module_param(irqfixup, int, 0644); | 287 | module_param(irqfixup, int, 0644); |
244 | MODULE_PARM_DESC("irqfixup", "0: No fixup, 1: irqfixup mode 2: irqpoll mode"); | 288 | MODULE_PARM_DESC("irqfixup", "0: No fixup, 1: irqfixup mode, 2: irqpoll mode"); |
245 | 289 | ||
246 | static int __init irqpoll_setup(char *str) | 290 | static int __init irqpoll_setup(char *str) |
247 | { | 291 | { |