aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c209
1 files changed, 146 insertions, 63 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 1279e3499534..92be519eff26 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,53 @@ 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, which is
141 * disabled by default. Enables and disables must match,
142 * just as they match for non-wakeup mode support.
143 *
144 * Wakeup mode lets this IRQ wake the system from sleep
145 * states like "suspend to RAM".
146 */
147int set_irq_wake(unsigned int irq, unsigned int on)
148{
149 struct irq_desc *desc = irq_desc + irq;
150 unsigned long flags;
151 int ret = -ENXIO;
152 int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake;
153
154 /* wakeup-capable irqs can be shared between drivers that
155 * don't need to have the same sleep mode behaviors.
156 */
157 spin_lock_irqsave(&desc->lock, flags);
158 if (on) {
159 if (desc->wake_depth++ == 0)
160 desc->status |= IRQ_WAKEUP;
161 else
162 set_wake = NULL;
163 } else {
164 if (desc->wake_depth == 0) {
165 printk(KERN_WARNING "Unbalanced IRQ %d "
166 "wake disable\n", irq);
167 WARN_ON(1);
168 } else if (--desc->wake_depth == 0)
169 desc->status &= ~IRQ_WAKEUP;
170 else
171 set_wake = NULL;
172 }
173 if (set_wake)
174 ret = desc->chip->set_wake(irq, on);
175 spin_unlock_irqrestore(&desc->lock, flags);
176 return ret;
177}
178EXPORT_SYMBOL(set_irq_wake);
179
147/* 180/*
148 * Internal function that tells the architecture code whether a 181 * Internal function that tells the architecture code whether a
149 * particular irq has been exclusively allocated or is available 182 * particular irq has been exclusively allocated or is available
@@ -153,22 +186,33 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
153{ 186{
154 struct irqaction *action; 187 struct irqaction *action;
155 188
156 if (irq >= NR_IRQS) 189 if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)
157 return 0; 190 return 0;
158 191
159 action = irq_desc[irq].action; 192 action = irq_desc[irq].action;
160 if (action) 193 if (action)
161 if (irqflags & action->flags & SA_SHIRQ) 194 if (irqflags & action->flags & IRQF_SHARED)
162 action = NULL; 195 action = NULL;
163 196
164 return !action; 197 return !action;
165} 198}
166 199
200void compat_irq_chip_set_default_handler(struct irq_desc *desc)
201{
202 /*
203 * If the architecture still has not overriden
204 * the flow handler then zap the default. This
205 * should catch incorrect flow-type setting.
206 */
207 if (desc->handle_irq == &handle_bad_irq)
208 desc->handle_irq = NULL;
209}
210
167/* 211/*
168 * Internal function to register an irqaction - typically used to 212 * Internal function to register an irqaction - typically used to
169 * allocate special interrupts that are part of the architecture. 213 * allocate special interrupts that are part of the architecture.
170 */ 214 */
171int setup_irq(unsigned int irq, struct irqaction * new) 215int setup_irq(unsigned int irq, struct irqaction *new)
172{ 216{
173 struct irq_desc *desc = irq_desc + irq; 217 struct irq_desc *desc = irq_desc + irq;
174 struct irqaction *old, **p; 218 struct irqaction *old, **p;
@@ -178,14 +222,14 @@ int setup_irq(unsigned int irq, struct irqaction * new)
178 if (irq >= NR_IRQS) 222 if (irq >= NR_IRQS)
179 return -EINVAL; 223 return -EINVAL;
180 224
181 if (desc->handler == &no_irq_type) 225 if (desc->chip == &no_irq_chip)
182 return -ENOSYS; 226 return -ENOSYS;
183 /* 227 /*
184 * Some drivers like serial.c use request_irq() heavily, 228 * Some drivers like serial.c use request_irq() heavily,
185 * so we have to be careful not to interfere with a 229 * so we have to be careful not to interfere with a
186 * running system. 230 * running system.
187 */ 231 */
188 if (new->flags & SA_SAMPLE_RANDOM) { 232 if (new->flags & IRQF_SAMPLE_RANDOM) {
189 /* 233 /*
190 * This function might sleep, we want to call it first, 234 * This function might sleep, we want to call it first,
191 * outside of the atomic block. 235 * outside of the atomic block.
@@ -200,16 +244,24 @@ int setup_irq(unsigned int irq, struct irqaction * new)
200 /* 244 /*
201 * The following block of code has to be executed atomically 245 * The following block of code has to be executed atomically
202 */ 246 */
203 spin_lock_irqsave(&desc->lock,flags); 247 spin_lock_irqsave(&desc->lock, flags);
204 p = &desc->action; 248 p = &desc->action;
205 if ((old = *p) != NULL) { 249 old = *p;
206 /* Can't share interrupts unless both agree to */ 250 if (old) {
207 if (!(old->flags & new->flags & SA_SHIRQ)) 251 /*
252 * Can't share interrupts unless both agree to and are
253 * the same type (level, edge, polarity). So both flag
254 * fields must have IRQF_SHARED set and the bits which
255 * set the trigger type must match.
256 */
257 if (!((old->flags & new->flags) & IRQF_SHARED) ||
258 ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK))
208 goto mismatch; 259 goto mismatch;
209 260
210#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) 261#if defined(CONFIG_IRQ_PER_CPU)
211 /* All handlers must agree on per-cpuness */ 262 /* All handlers must agree on per-cpuness */
212 if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU)) 263 if ((old->flags & IRQF_PERCPU) !=
264 (new->flags & IRQF_PERCPU))
213 goto mismatch; 265 goto mismatch;
214#endif 266#endif
215 267
@@ -222,20 +274,45 @@ int setup_irq(unsigned int irq, struct irqaction * new)
222 } 274 }
223 275
224 *p = new; 276 *p = new;
225#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) 277#if defined(CONFIG_IRQ_PER_CPU)
226 if (new->flags & SA_PERCPU_IRQ) 278 if (new->flags & IRQF_PERCPU)
227 desc->status |= IRQ_PER_CPU; 279 desc->status |= IRQ_PER_CPU;
228#endif 280#endif
229 if (!shared) { 281 if (!shared) {
230 desc->depth = 0; 282 irq_chip_set_defaults(desc->chip);
231 desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | 283
232 IRQ_WAITING | IRQ_INPROGRESS); 284 /* Setup the type (level, edge polarity) if configured: */
233 if (desc->handler->startup) 285 if (new->flags & IRQF_TRIGGER_MASK) {
234 desc->handler->startup(irq); 286 if (desc->chip && desc->chip->set_type)
235 else 287 desc->chip->set_type(irq,
236 desc->handler->enable(irq); 288 new->flags & IRQF_TRIGGER_MASK);
289 else
290 /*
291 * IRQF_TRIGGER_* but the PIC does not support
292 * multiple flow-types?
293 */
294 printk(KERN_WARNING "No IRQF_TRIGGER set_type "
295 "function for IRQ %d (%s)\n", irq,
296 desc->chip ? desc->chip->name :
297 "unknown");
298 } else
299 compat_irq_chip_set_default_handler(desc);
300
301 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
302 IRQ_INPROGRESS);
303
304 if (!(desc->status & IRQ_NOAUTOEN)) {
305 desc->depth = 0;
306 desc->status &= ~IRQ_DISABLED;
307 if (desc->chip->startup)
308 desc->chip->startup(irq);
309 else
310 desc->chip->enable(irq);
311 } else
312 /* Undo nested disables: */
313 desc->depth = 1;
237 } 314 }
238 spin_unlock_irqrestore(&desc->lock,flags); 315 spin_unlock_irqrestore(&desc->lock, flags);
239 316
240 new->irq = irq; 317 new->irq = irq;
241 register_irq_proc(irq); 318 register_irq_proc(irq);
@@ -246,8 +323,8 @@ int setup_irq(unsigned int irq, struct irqaction * new)
246 323
247mismatch: 324mismatch:
248 spin_unlock_irqrestore(&desc->lock, flags); 325 spin_unlock_irqrestore(&desc->lock, flags);
249 if (!(new->flags & SA_PROBEIRQ)) { 326 if (!(new->flags & IRQF_PROBE_SHARED)) {
250 printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__); 327 printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
251 dump_stack(); 328 dump_stack();
252 } 329 }
253 return -EBUSY; 330 return -EBUSY;
@@ -278,10 +355,10 @@ void free_irq(unsigned int irq, void *dev_id)
278 return; 355 return;
279 356
280 desc = irq_desc + irq; 357 desc = irq_desc + irq;
281 spin_lock_irqsave(&desc->lock,flags); 358 spin_lock_irqsave(&desc->lock, flags);
282 p = &desc->action; 359 p = &desc->action;
283 for (;;) { 360 for (;;) {
284 struct irqaction * action = *p; 361 struct irqaction *action = *p;
285 362
286 if (action) { 363 if (action) {
287 struct irqaction **pp = p; 364 struct irqaction **pp = p;
@@ -295,18 +372,18 @@ void free_irq(unsigned int irq, void *dev_id)
295 372
296 /* Currently used only by UML, might disappear one day.*/ 373 /* Currently used only by UML, might disappear one day.*/
297#ifdef CONFIG_IRQ_RELEASE_METHOD 374#ifdef CONFIG_IRQ_RELEASE_METHOD
298 if (desc->handler->release) 375 if (desc->chip->release)
299 desc->handler->release(irq, dev_id); 376 desc->chip->release(irq, dev_id);
300#endif 377#endif
301 378
302 if (!desc->action) { 379 if (!desc->action) {
303 desc->status |= IRQ_DISABLED; 380 desc->status |= IRQ_DISABLED;
304 if (desc->handler->shutdown) 381 if (desc->chip->shutdown)
305 desc->handler->shutdown(irq); 382 desc->chip->shutdown(irq);
306 else 383 else
307 desc->handler->disable(irq); 384 desc->chip->disable(irq);
308 } 385 }
309 spin_unlock_irqrestore(&desc->lock,flags); 386 spin_unlock_irqrestore(&desc->lock, flags);
310 unregister_handler_proc(irq, action); 387 unregister_handler_proc(irq, action);
311 388
312 /* Make sure it's not being used on another CPU */ 389 /* Make sure it's not being used on another CPU */
@@ -314,12 +391,11 @@ void free_irq(unsigned int irq, void *dev_id)
314 kfree(action); 391 kfree(action);
315 return; 392 return;
316 } 393 }
317 printk(KERN_ERR "Trying to free free IRQ%d\n",irq); 394 printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
318 spin_unlock_irqrestore(&desc->lock,flags); 395 spin_unlock_irqrestore(&desc->lock, flags);
319 return; 396 return;
320 } 397 }
321} 398}
322
323EXPORT_SYMBOL(free_irq); 399EXPORT_SYMBOL(free_irq);
324 400
325/** 401/**
@@ -346,28 +422,36 @@ EXPORT_SYMBOL(free_irq);
346 * 422 *
347 * Flags: 423 * Flags:
348 * 424 *
349 * SA_SHIRQ Interrupt is shared 425 * IRQF_SHARED Interrupt is shared
350 * SA_INTERRUPT Disable local interrupts while processing 426 * IRQF_DISABLED Disable local interrupts while processing
351 * SA_SAMPLE_RANDOM The interrupt can be used for entropy 427 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
352 * 428 *
353 */ 429 */
354int request_irq(unsigned int irq, 430int request_irq(unsigned int irq,
355 irqreturn_t (*handler)(int, void *, struct pt_regs *), 431 irqreturn_t (*handler)(int, void *, struct pt_regs *),
356 unsigned long irqflags, const char * devname, void *dev_id) 432 unsigned long irqflags, const char *devname, void *dev_id)
357{ 433{
358 struct irqaction * action; 434 struct irqaction *action;
359 int retval; 435 int retval;
360 436
437#ifdef CONFIG_LOCKDEP
438 /*
439 * Lockdep wants atomic interrupt handlers:
440 */
441 irqflags |= SA_INTERRUPT;
442#endif
361 /* 443 /*
362 * Sanity-check: shared interrupts must pass in a real dev-ID, 444 * Sanity-check: shared interrupts must pass in a real dev-ID,
363 * otherwise we'll have trouble later trying to figure out 445 * otherwise we'll have trouble later trying to figure out
364 * which interrupt is which (messes up the interrupt freeing 446 * which interrupt is which (messes up the interrupt freeing
365 * logic etc). 447 * logic etc).
366 */ 448 */
367 if ((irqflags & SA_SHIRQ) && !dev_id) 449 if ((irqflags & IRQF_SHARED) && !dev_id)
368 return -EINVAL; 450 return -EINVAL;
369 if (irq >= NR_IRQS) 451 if (irq >= NR_IRQS)
370 return -EINVAL; 452 return -EINVAL;
453 if (irq_desc[irq].status & IRQ_NOREQUEST)
454 return -EINVAL;
371 if (!handler) 455 if (!handler)
372 return -EINVAL; 456 return -EINVAL;
373 457
@@ -390,6 +474,5 @@ int request_irq(unsigned int irq,
390 474
391 return retval; 475 return retval;
392} 476}
393
394EXPORT_SYMBOL(request_irq); 477EXPORT_SYMBOL(request_irq);
395 478