aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-03 13:49:45 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-07-03 13:49:45 -0400
commit026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (patch)
tree2624a44924c625c367f3cebf937853b9da2de282 /kernel/irq/manage.c
parent9f2fa466383ce100b90fe52cb4489d7a26bf72a9 (diff)
parent29454dde27d8e340bb1987bad9aa504af7081eba (diff)
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c179
1 files changed, 116 insertions, 63 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 1279e3499534..c911c6ec4dd6 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * linux/kernel/irq/manage.c 2 * linux/kernel/irq/manage.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
5 * 6 *
6 * This file contains driver APIs to the irq subsystem. 7 * This file contains driver APIs to the irq subsystem.
7 */ 8 */
8 9
9#include <linux/config.h>
10#include <linux/irq.h> 10#include <linux/irq.h>
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/random.h> 12#include <linux/random.h>
@@ -16,12 +16,6 @@
16 16
17#ifdef CONFIG_SMP 17#ifdef CONFIG_SMP
18 18
19cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
20
21#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
22cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
23#endif
24
25/** 19/**
26 * synchronize_irq - wait for pending IRQ handlers (on other CPUs) 20 * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
27 * @irq: interrupt number to wait for 21 * @irq: interrupt number to wait for
@@ -42,7 +36,6 @@ void synchronize_irq(unsigned int irq)
42 while (desc->status & IRQ_INPROGRESS) 36 while (desc->status & IRQ_INPROGRESS)
43 cpu_relax(); 37 cpu_relax();
44} 38}
45
46EXPORT_SYMBOL(synchronize_irq); 39EXPORT_SYMBOL(synchronize_irq);
47 40
48#endif 41#endif
@@ -60,7 +53,7 @@ EXPORT_SYMBOL(synchronize_irq);
60 */ 53 */
61void disable_irq_nosync(unsigned int irq) 54void disable_irq_nosync(unsigned int irq)
62{ 55{
63 irq_desc_t *desc = irq_desc + irq; 56 struct irq_desc *desc = irq_desc + irq;
64 unsigned long flags; 57 unsigned long flags;
65 58
66 if (irq >= NR_IRQS) 59 if (irq >= NR_IRQS)
@@ -69,11 +62,10 @@ void disable_irq_nosync(unsigned int irq)
69 spin_lock_irqsave(&desc->lock, flags); 62 spin_lock_irqsave(&desc->lock, flags);
70 if (!desc->depth++) { 63 if (!desc->depth++) {
71 desc->status |= IRQ_DISABLED; 64 desc->status |= IRQ_DISABLED;
72 desc->handler->disable(irq); 65 desc->chip->disable(irq);
73 } 66 }
74 spin_unlock_irqrestore(&desc->lock, flags); 67 spin_unlock_irqrestore(&desc->lock, flags);
75} 68}
76
77EXPORT_SYMBOL(disable_irq_nosync); 69EXPORT_SYMBOL(disable_irq_nosync);
78 70
79/** 71/**
@@ -90,7 +82,7 @@ EXPORT_SYMBOL(disable_irq_nosync);
90 */ 82 */
91void disable_irq(unsigned int irq) 83void disable_irq(unsigned int irq)
92{ 84{
93 irq_desc_t *desc = irq_desc + irq; 85 struct irq_desc *desc = irq_desc + irq;
94 86
95 if (irq >= NR_IRQS) 87 if (irq >= NR_IRQS)
96 return; 88 return;
@@ -99,7 +91,6 @@ void disable_irq(unsigned int irq)
99 if (desc->action) 91 if (desc->action)
100 synchronize_irq(irq); 92 synchronize_irq(irq);
101} 93}
102
103EXPORT_SYMBOL(disable_irq); 94EXPORT_SYMBOL(disable_irq);
104 95
105/** 96/**
@@ -114,7 +105,7 @@ EXPORT_SYMBOL(disable_irq);
114 */ 105 */
115void enable_irq(unsigned int irq) 106void enable_irq(unsigned int irq)
116{ 107{
117 irq_desc_t *desc = irq_desc + irq; 108 struct irq_desc *desc = irq_desc + irq;
118 unsigned long flags; 109 unsigned long flags;
119 110
120 if (irq >= NR_IRQS) 111 if (irq >= NR_IRQS)
@@ -123,17 +114,15 @@ void enable_irq(unsigned int irq)
123 spin_lock_irqsave(&desc->lock, flags); 114 spin_lock_irqsave(&desc->lock, flags);
124 switch (desc->depth) { 115 switch (desc->depth) {
125 case 0: 116 case 0:
117 printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
126 WARN_ON(1); 118 WARN_ON(1);
127 break; 119 break;
128 case 1: { 120 case 1: {
129 unsigned int status = desc->status & ~IRQ_DISABLED; 121 unsigned int status = desc->status & ~IRQ_DISABLED;
130 122
131 desc->status = status; 123 /* Prevent probing on this irq: */
132 if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { 124 desc->status = status | IRQ_NOPROBE;
133 desc->status = status | IRQ_REPLAY; 125 check_irq_resend(desc, irq);
134 hw_resend_irq(desc->handler,irq);
135 }
136 desc->handler->enable(irq);
137 /* fall-through */ 126 /* fall-through */
138 } 127 }
139 default: 128 default:
@@ -141,9 +130,29 @@ void enable_irq(unsigned int irq)
141 } 130 }
142 spin_unlock_irqrestore(&desc->lock, flags); 131 spin_unlock_irqrestore(&desc->lock, flags);
143} 132}
144
145EXPORT_SYMBOL(enable_irq); 133EXPORT_SYMBOL(enable_irq);
146 134
135/**
136 * set_irq_wake - control irq power management wakeup
137 * @irq: interrupt to control
138 * @on: enable/disable power management wakeup
139 *
140 * Enable/disable power management wakeup mode
141 */
142int set_irq_wake(unsigned int irq, unsigned int on)
143{
144 struct irq_desc *desc = irq_desc + irq;
145 unsigned long flags;
146 int ret = -ENXIO;
147
148 spin_lock_irqsave(&desc->lock, flags);
149 if (desc->chip->set_wake)
150 ret = desc->chip->set_wake(irq, on);
151 spin_unlock_irqrestore(&desc->lock, flags);
152 return ret;
153}
154EXPORT_SYMBOL(set_irq_wake);
155
147/* 156/*
148 * Internal function that tells the architecture code whether a 157 * Internal function that tells the architecture code whether a
149 * particular irq has been exclusively allocated or is available 158 * particular irq has been exclusively allocated or is available
@@ -153,22 +162,33 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
153{ 162{
154 struct irqaction *action; 163 struct irqaction *action;
155 164
156 if (irq >= NR_IRQS) 165 if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)
157 return 0; 166 return 0;
158 167
159 action = irq_desc[irq].action; 168 action = irq_desc[irq].action;
160 if (action) 169 if (action)
161 if (irqflags & action->flags & SA_SHIRQ) 170 if (irqflags & action->flags & IRQF_SHARED)
162 action = NULL; 171 action = NULL;
163 172
164 return !action; 173 return !action;
165} 174}
166 175
176void compat_irq_chip_set_default_handler(struct irq_desc *desc)
177{
178 /*
179 * If the architecture still has not overriden
180 * the flow handler then zap the default. This
181 * should catch incorrect flow-type setting.
182 */
183 if (desc->handle_irq == &handle_bad_irq)
184 desc->handle_irq = NULL;
185}
186
167/* 187/*
168 * Internal function to register an irqaction - typically used to 188 * Internal function to register an irqaction - typically used to
169 * allocate special interrupts that are part of the architecture. 189 * allocate special interrupts that are part of the architecture.
170 */ 190 */
171int setup_irq(unsigned int irq, struct irqaction * new) 191int setup_irq(unsigned int irq, struct irqaction *new)
172{ 192{
173 struct irq_desc *desc = irq_desc + irq; 193 struct irq_desc *desc = irq_desc + irq;
174 struct irqaction *old, **p; 194 struct irqaction *old, **p;
@@ -178,14 +198,14 @@ int setup_irq(unsigned int irq, struct irqaction * new)
178 if (irq >= NR_IRQS) 198 if (irq >= NR_IRQS)
179 return -EINVAL; 199 return -EINVAL;
180 200
181 if (desc->handler == &no_irq_type) 201 if (desc->chip == &no_irq_chip)
182 return -ENOSYS; 202 return -ENOSYS;
183 /* 203 /*
184 * Some drivers like serial.c use request_irq() heavily, 204 * Some drivers like serial.c use request_irq() heavily,
185 * so we have to be careful not to interfere with a 205 * so we have to be careful not to interfere with a
186 * running system. 206 * running system.
187 */ 207 */
188 if (new->flags & SA_SAMPLE_RANDOM) { 208 if (new->flags & IRQF_SAMPLE_RANDOM) {
189 /* 209 /*
190 * This function might sleep, we want to call it first, 210 * This function might sleep, we want to call it first,
191 * outside of the atomic block. 211 * outside of the atomic block.
@@ -200,16 +220,24 @@ int setup_irq(unsigned int irq, struct irqaction * new)
200 /* 220 /*
201 * The following block of code has to be executed atomically 221 * The following block of code has to be executed atomically
202 */ 222 */
203 spin_lock_irqsave(&desc->lock,flags); 223 spin_lock_irqsave(&desc->lock, flags);
204 p = &desc->action; 224 p = &desc->action;
205 if ((old = *p) != NULL) { 225 old = *p;
206 /* Can't share interrupts unless both agree to */ 226 if (old) {
207 if (!(old->flags & new->flags & SA_SHIRQ)) 227 /*
228 * Can't share interrupts unless both agree to and are
229 * the same type (level, edge, polarity). So both flag
230 * fields must have IRQF_SHARED set and the bits which
231 * set the trigger type must match.
232 */
233 if (!((old->flags & new->flags) & IRQF_SHARED) ||
234 ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK))
208 goto mismatch; 235 goto mismatch;
209 236
210#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) 237#if defined(CONFIG_IRQ_PER_CPU)
211 /* All handlers must agree on per-cpuness */ 238 /* All handlers must agree on per-cpuness */
212 if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU)) 239 if ((old->flags & IRQF_PERCPU) !=
240 (new->flags & IRQF_PERCPU))
213 goto mismatch; 241 goto mismatch;
214#endif 242#endif
215 243
@@ -222,20 +250,45 @@ int setup_irq(unsigned int irq, struct irqaction * new)
222 } 250 }
223 251
224 *p = new; 252 *p = new;
225#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) 253#if defined(CONFIG_IRQ_PER_CPU)
226 if (new->flags & SA_PERCPU_IRQ) 254 if (new->flags & IRQF_PERCPU)
227 desc->status |= IRQ_PER_CPU; 255 desc->status |= IRQ_PER_CPU;
228#endif 256#endif
229 if (!shared) { 257 if (!shared) {
230 desc->depth = 0; 258 irq_chip_set_defaults(desc->chip);
231 desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | 259
232 IRQ_WAITING | IRQ_INPROGRESS); 260 /* Setup the type (level, edge polarity) if configured: */
233 if (desc->handler->startup) 261 if (new->flags & IRQF_TRIGGER_MASK) {
234 desc->handler->startup(irq); 262 if (desc->chip && desc->chip->set_type)
235 else 263 desc->chip->set_type(irq,
236 desc->handler->enable(irq); 264 new->flags & IRQF_TRIGGER_MASK);
265 else
266 /*
267 * IRQF_TRIGGER_* but the PIC does not support
268 * multiple flow-types?
269 */
270 printk(KERN_WARNING "No IRQF_TRIGGER set_type "
271 "function for IRQ %d (%s)\n", irq,
272 desc->chip ? desc->chip->name :
273 "unknown");
274 } else
275 compat_irq_chip_set_default_handler(desc);
276
277 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
278 IRQ_INPROGRESS);
279
280 if (!(desc->status & IRQ_NOAUTOEN)) {
281 desc->depth = 0;
282 desc->status &= ~IRQ_DISABLED;
283 if (desc->chip->startup)
284 desc->chip->startup(irq);
285 else
286 desc->chip->enable(irq);
287 } else
288 /* Undo nested disables: */
289 desc->depth = 1;
237 } 290 }
238 spin_unlock_irqrestore(&desc->lock,flags); 291 spin_unlock_irqrestore(&desc->lock, flags);
239 292
240 new->irq = irq; 293 new->irq = irq;
241 register_irq_proc(irq); 294 register_irq_proc(irq);
@@ -246,8 +299,8 @@ int setup_irq(unsigned int irq, struct irqaction * new)
246 299
247mismatch: 300mismatch:
248 spin_unlock_irqrestore(&desc->lock, flags); 301 spin_unlock_irqrestore(&desc->lock, flags);
249 if (!(new->flags & SA_PROBEIRQ)) { 302 if (!(new->flags & IRQF_PROBE_SHARED)) {
250 printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__); 303 printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
251 dump_stack(); 304 dump_stack();
252 } 305 }
253 return -EBUSY; 306 return -EBUSY;
@@ -278,10 +331,10 @@ void free_irq(unsigned int irq, void *dev_id)
278 return; 331 return;
279 332
280 desc = irq_desc + irq; 333 desc = irq_desc + irq;
281 spin_lock_irqsave(&desc->lock,flags); 334 spin_lock_irqsave(&desc->lock, flags);
282 p = &desc->action; 335 p = &desc->action;
283 for (;;) { 336 for (;;) {
284 struct irqaction * action = *p; 337 struct irqaction *action = *p;
285 338
286 if (action) { 339 if (action) {
287 struct irqaction **pp = p; 340 struct irqaction **pp = p;
@@ -295,18 +348,18 @@ void free_irq(unsigned int irq, void *dev_id)
295 348
296 /* Currently used only by UML, might disappear one day.*/ 349 /* Currently used only by UML, might disappear one day.*/
297#ifdef CONFIG_IRQ_RELEASE_METHOD 350#ifdef CONFIG_IRQ_RELEASE_METHOD
298 if (desc->handler->release) 351 if (desc->chip->release)
299 desc->handler->release(irq, dev_id); 352 desc->chip->release(irq, dev_id);
300#endif 353#endif
301 354
302 if (!desc->action) { 355 if (!desc->action) {
303 desc->status |= IRQ_DISABLED; 356 desc->status |= IRQ_DISABLED;
304 if (desc->handler->shutdown) 357 if (desc->chip->shutdown)
305 desc->handler->shutdown(irq); 358 desc->chip->shutdown(irq);
306 else 359 else
307 desc->handler->disable(irq); 360 desc->chip->disable(irq);
308 } 361 }
309 spin_unlock_irqrestore(&desc->lock,flags); 362 spin_unlock_irqrestore(&desc->lock, flags);
310 unregister_handler_proc(irq, action); 363 unregister_handler_proc(irq, action);
311 364
312 /* Make sure it's not being used on another CPU */ 365 /* Make sure it's not being used on another CPU */
@@ -314,12 +367,11 @@ void free_irq(unsigned int irq, void *dev_id)
314 kfree(action); 367 kfree(action);
315 return; 368 return;
316 } 369 }
317 printk(KERN_ERR "Trying to free free IRQ%d\n",irq); 370 printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
318 spin_unlock_irqrestore(&desc->lock,flags); 371 spin_unlock_irqrestore(&desc->lock, flags);
319 return; 372 return;
320 } 373 }
321} 374}
322
323EXPORT_SYMBOL(free_irq); 375EXPORT_SYMBOL(free_irq);
324 376
325/** 377/**
@@ -346,16 +398,16 @@ EXPORT_SYMBOL(free_irq);
346 * 398 *
347 * Flags: 399 * Flags:
348 * 400 *
349 * SA_SHIRQ Interrupt is shared 401 * IRQF_SHARED Interrupt is shared
350 * SA_INTERRUPT Disable local interrupts while processing 402 * IRQF_DISABLED Disable local interrupts while processing
351 * SA_SAMPLE_RANDOM The interrupt can be used for entropy 403 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
352 * 404 *
353 */ 405 */
354int request_irq(unsigned int irq, 406int request_irq(unsigned int irq,
355 irqreturn_t (*handler)(int, void *, struct pt_regs *), 407 irqreturn_t (*handler)(int, void *, struct pt_regs *),
356 unsigned long irqflags, const char * devname, void *dev_id) 408 unsigned long irqflags, const char *devname, void *dev_id)
357{ 409{
358 struct irqaction * action; 410 struct irqaction *action;
359 int retval; 411 int retval;
360 412
361 /* 413 /*
@@ -364,10 +416,12 @@ int request_irq(unsigned int irq,
364 * which interrupt is which (messes up the interrupt freeing 416 * which interrupt is which (messes up the interrupt freeing
365 * logic etc). 417 * logic etc).
366 */ 418 */
367 if ((irqflags & SA_SHIRQ) && !dev_id) 419 if ((irqflags & IRQF_SHARED) && !dev_id)
368 return -EINVAL; 420 return -EINVAL;
369 if (irq >= NR_IRQS) 421 if (irq >= NR_IRQS)
370 return -EINVAL; 422 return -EINVAL;
423 if (irq_desc[irq].status & IRQ_NOREQUEST)
424 return -EINVAL;
371 if (!handler) 425 if (!handler)
372 return -EINVAL; 426 return -EINVAL;
373 427
@@ -390,6 +444,5 @@ int request_irq(unsigned int irq,
390 444
391 return retval; 445 return retval;
392} 446}
393
394EXPORT_SYMBOL(request_irq); 447EXPORT_SYMBOL(request_irq);
395 448