Blame view
kernel/irq/manage.c
13.9 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * linux/kernel/irq/manage.c * |
a34db9b28 [PATCH] genirq: u... |
4 5 |
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar * Copyright (C) 2005-2006 Thomas Gleixner |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 12 13 14 15 16 17 |
* * This file contains driver APIs to the irq subsystem. */ #include <linux/irq.h> #include <linux/module.h> #include <linux/random.h> #include <linux/interrupt.h> #include "internals.h" #ifdef CONFIG_SMP |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
/** * synchronize_irq - wait for pending IRQ handlers (on other CPUs) |
1e5d53314 [PATCH] more kern... |
20 |
* @irq: interrupt number to wait for |
1da177e4c Linux-2.6.12-rc2 |
21 22 23 24 25 26 27 28 29 30 |
* * This function waits for any pending IRQ handlers for this interrupt * to complete before returning. If you use this function while * holding a resource the IRQ handler may need you will deadlock. * * This function may be called - with care - from IRQ context. */ void synchronize_irq(unsigned int irq) { struct irq_desc *desc = irq_desc + irq; |
c2b5a251b [PATCH] Check the... |
31 32 |
if (irq >= NR_IRQS) return; |
1da177e4c Linux-2.6.12-rc2 |
33 34 35 |
while (desc->status & IRQ_INPROGRESS) cpu_relax(); } |
1da177e4c Linux-2.6.12-rc2 |
36 |
EXPORT_SYMBOL(synchronize_irq); |
771ee3b04 [PATCH] Add a fun... |
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
/** * irq_can_set_affinity - Check if the affinity of a given irq can be set * @irq: Interrupt to check * */ int irq_can_set_affinity(unsigned int irq) { struct irq_desc *desc = irq_desc + irq; if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip || !desc->chip->set_affinity) return 0; return 1; } /** * irq_set_affinity - Set the irq affinity of a given irq * @irq: Interrupt to set affinity * @cpumask: cpumask * */ int irq_set_affinity(unsigned int irq, cpumask_t cpumask) { struct irq_desc *desc = irq_desc + irq; if (!desc->chip->set_affinity) return -EINVAL; set_balance_irq_affinity(irq, cpumask); #ifdef CONFIG_GENERIC_PENDING_IRQ set_pending_irq(irq, cpumask); #else desc->affinity = cpumask; desc->chip->set_affinity(irq, cpumask); #endif return 0; } |
1da177e4c Linux-2.6.12-rc2 |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
#endif /** * disable_irq_nosync - disable an irq without waiting * @irq: Interrupt to disable * * Disable the selected interrupt line. Disables and Enables are * nested. * Unlike disable_irq(), this function does not ensure existing * instances of the IRQ handler have completed before returning. * * This function may be called from IRQ context. */ void disable_irq_nosync(unsigned int irq) { |
34ffdb723 [PATCH] genirq: c... |
91 |
struct irq_desc *desc = irq_desc + irq; |
1da177e4c Linux-2.6.12-rc2 |
92 |
unsigned long flags; |
c2b5a251b [PATCH] Check the... |
93 94 |
if (irq >= NR_IRQS) return; |
1da177e4c Linux-2.6.12-rc2 |
95 96 97 |
spin_lock_irqsave(&desc->lock, flags); if (!desc->depth++) { desc->status |= IRQ_DISABLED; |
d1bef4ed5 [PATCH] genirq: r... |
98 |
desc->chip->disable(irq); |
1da177e4c Linux-2.6.12-rc2 |
99 100 101 |
} spin_unlock_irqrestore(&desc->lock, flags); } |
1da177e4c Linux-2.6.12-rc2 |
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
EXPORT_SYMBOL(disable_irq_nosync); /** * disable_irq - disable an irq and wait for completion * @irq: Interrupt to disable * * Disable the selected interrupt line. Enables and Disables are * nested. * This function waits for any pending IRQ handlers for this interrupt * to complete before returning. If you use this function while * holding a resource the IRQ handler may need you will deadlock. * * This function may be called - with care - from IRQ context. */ void disable_irq(unsigned int irq) { |
34ffdb723 [PATCH] genirq: c... |
118 |
struct irq_desc *desc = irq_desc + irq; |
1da177e4c Linux-2.6.12-rc2 |
119 |
|
c2b5a251b [PATCH] Check the... |
120 121 |
if (irq >= NR_IRQS) return; |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 |
disable_irq_nosync(irq); if (desc->action) synchronize_irq(irq); } |
1da177e4c Linux-2.6.12-rc2 |
126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
EXPORT_SYMBOL(disable_irq); /** * enable_irq - enable handling of an irq * @irq: Interrupt to enable * * Undoes the effect of one call to disable_irq(). If this * matches the last disable, processing of interrupts on this * IRQ line is re-enabled. * * This function may be called from IRQ context. */ void enable_irq(unsigned int irq) { |
34ffdb723 [PATCH] genirq: c... |
140 |
struct irq_desc *desc = irq_desc + irq; |
1da177e4c Linux-2.6.12-rc2 |
141 |
unsigned long flags; |
c2b5a251b [PATCH] Check the... |
142 143 |
if (irq >= NR_IRQS) return; |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 |
spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 0: |
e8c4b9d00 [PATCH] IRQ: warn... |
147 148 |
printk(KERN_WARNING "Unbalanced enable for IRQ %d ", irq); |
1da177e4c Linux-2.6.12-rc2 |
149 150 151 |
WARN_ON(1); break; case 1: { |
3418d7240 [PATCH] genirq: a... |
152 153 154 155 |
unsigned int status = desc->status & ~IRQ_DISABLED; /* Prevent probing on this irq: */ desc->status = status | IRQ_NOPROBE; |
a4633adcd [PATCH] genirq: a... |
156 |
check_irq_resend(desc, irq); |
1da177e4c Linux-2.6.12-rc2 |
157 158 159 160 161 162 163 |
/* fall-through */ } default: desc->depth--; } spin_unlock_irqrestore(&desc->lock, flags); } |
1da177e4c Linux-2.6.12-rc2 |
164 |
EXPORT_SYMBOL(enable_irq); |
ba9a2331b [PATCH] genirq: a... |
165 166 167 168 169 |
/** * set_irq_wake - control irq power management wakeup * @irq: interrupt to control * @on: enable/disable power management wakeup * |
15a647eba [PATCH] genirq: {... |
170 171 172 173 174 175 |
* Enable/disable power management wakeup mode, which is * disabled by default. Enables and disables must match, * just as they match for non-wakeup mode support. * * Wakeup mode lets this IRQ wake the system from sleep * states like "suspend to RAM". |
ba9a2331b [PATCH] genirq: a... |
176 177 178 179 180 181 |
*/ int set_irq_wake(unsigned int irq, unsigned int on) { struct irq_desc *desc = irq_desc + irq; unsigned long flags; int ret = -ENXIO; |
15a647eba [PATCH] genirq: {... |
182 |
int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake; |
ba9a2331b [PATCH] genirq: a... |
183 |
|
15a647eba [PATCH] genirq: {... |
184 185 186 |
/* wakeup-capable irqs can be shared between drivers that * don't need to have the same sleep mode behaviors. */ |
ba9a2331b [PATCH] genirq: a... |
187 |
spin_lock_irqsave(&desc->lock, flags); |
15a647eba [PATCH] genirq: {... |
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
if (on) { if (desc->wake_depth++ == 0) desc->status |= IRQ_WAKEUP; else set_wake = NULL; } else { if (desc->wake_depth == 0) { printk(KERN_WARNING "Unbalanced IRQ %d " "wake disable ", irq); WARN_ON(1); } else if (--desc->wake_depth == 0) desc->status &= ~IRQ_WAKEUP; else set_wake = NULL; } if (set_wake) |
ba9a2331b [PATCH] genirq: a... |
205 206 207 208 209 |
ret = desc->chip->set_wake(irq, on); spin_unlock_irqrestore(&desc->lock, flags); return ret; } EXPORT_SYMBOL(set_irq_wake); |
1da177e4c Linux-2.6.12-rc2 |
210 211 212 213 214 215 216 217 |
/* * Internal function that tells the architecture code whether a * particular irq has been exclusively allocated or is available * for driver use. */ int can_request_irq(unsigned int irq, unsigned long irqflags) { struct irqaction *action; |
6550c775c [PATCH] genirq: a... |
218 |
if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST) |
1da177e4c Linux-2.6.12-rc2 |
219 220 221 222 |
return 0; action = irq_desc[irq].action; if (action) |
3cca53b02 [PATCH] irq-flags... |
223 |
if (irqflags & action->flags & IRQF_SHARED) |
1da177e4c Linux-2.6.12-rc2 |
224 225 226 227 |
action = NULL; return !action; } |
6a6de9ef5 [PATCH] genirq: core |
228 229 230 231 232 233 234 235 236 237 |
void compat_irq_chip_set_default_handler(struct irq_desc *desc) { /* * If the architecture still has not overriden * the flow handler then zap the default. This * should catch incorrect flow-type setting. */ if (desc->handle_irq == &handle_bad_irq) desc->handle_irq = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
238 239 240 241 |
/* * Internal function to register an irqaction - typically used to * allocate special interrupts that are part of the architecture. */ |
06fcb0c6f [PATCH] genirq: c... |
242 |
int setup_irq(unsigned int irq, struct irqaction *new) |
1da177e4c Linux-2.6.12-rc2 |
243 244 245 |
{ struct irq_desc *desc = irq_desc + irq; struct irqaction *old, **p; |
8b126b775 [PATCH] setup_irq... |
246 |
const char *old_name = NULL; |
1da177e4c Linux-2.6.12-rc2 |
247 248 |
unsigned long flags; int shared = 0; |
c2b5a251b [PATCH] Check the... |
249 250 |
if (irq >= NR_IRQS) return -EINVAL; |
f1c2662cb [PATCH] genirq: c... |
251 |
if (desc->chip == &no_irq_chip) |
1da177e4c Linux-2.6.12-rc2 |
252 253 254 255 256 257 |
return -ENOSYS; /* * Some drivers like serial.c use request_irq() heavily, * so we have to be careful not to interfere with a * running system. */ |
3cca53b02 [PATCH] irq-flags... |
258 |
if (new->flags & IRQF_SAMPLE_RANDOM) { |
1da177e4c Linux-2.6.12-rc2 |
259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
/* * This function might sleep, we want to call it first, * outside of the atomic block. * Yes, this might clear the entropy pool if the wrong * driver is attempted to be loaded, without actually * installing a new handler, but is this really a problem, * only the sysadmin is able to do this. */ rand_initialize_irq(irq); } /* * The following block of code has to be executed atomically */ |
06fcb0c6f [PATCH] genirq: c... |
273 |
spin_lock_irqsave(&desc->lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
274 |
p = &desc->action; |
06fcb0c6f [PATCH] genirq: c... |
275 276 |
old = *p; if (old) { |
e76de9f8e [PATCH] genirq: a... |
277 278 279 |
/* * Can't share interrupts unless both agree to and are * the same type (level, edge, polarity). So both flag |
3cca53b02 [PATCH] irq-flags... |
280 |
* fields must have IRQF_SHARED set and the bits which |
e76de9f8e [PATCH] genirq: a... |
281 282 |
* set the trigger type must match. */ |
3cca53b02 [PATCH] irq-flags... |
283 |
if (!((old->flags & new->flags) & IRQF_SHARED) || |
8b126b775 [PATCH] setup_irq... |
284 285 |
((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) { old_name = old->name; |
f51634274 [PATCH] Add SA_PE... |
286 |
goto mismatch; |
8b126b775 [PATCH] setup_irq... |
287 |
} |
f51634274 [PATCH] Add SA_PE... |
288 |
|
284c66806 [PATCH] genirq:fi... |
289 |
#if defined(CONFIG_IRQ_PER_CPU) |
f51634274 [PATCH] Add SA_PE... |
290 |
/* All handlers must agree on per-cpuness */ |
3cca53b02 [PATCH] irq-flags... |
291 292 |
if ((old->flags & IRQF_PERCPU) != (new->flags & IRQF_PERCPU)) |
f51634274 [PATCH] Add SA_PE... |
293 294 |
goto mismatch; #endif |
1da177e4c Linux-2.6.12-rc2 |
295 296 297 298 299 300 301 302 303 304 |
/* add new interrupt at end of irq queue */ do { p = &old->next; old = *p; } while (old); shared = 1; } *p = new; |
f75d222b8 IRQ: check for PE... |
305 |
|
950f4427c [PATCH] Add irq f... |
306 307 308 |
/* Exclude IRQ from balancing */ if (new->flags & IRQF_NOBALANCING) desc->status |= IRQ_NO_BALANCING; |
1da177e4c Linux-2.6.12-rc2 |
309 |
if (!shared) { |
6a6de9ef5 [PATCH] genirq: core |
310 |
irq_chip_set_defaults(desc->chip); |
e76de9f8e [PATCH] genirq: a... |
311 |
|
f75d222b8 IRQ: check for PE... |
312 313 314 315 |
#if defined(CONFIG_IRQ_PER_CPU) if (new->flags & IRQF_PERCPU) desc->status |= IRQ_PER_CPU; #endif |
e76de9f8e [PATCH] genirq: a... |
316 |
/* Setup the type (level, edge polarity) if configured: */ |
3cca53b02 [PATCH] irq-flags... |
317 |
if (new->flags & IRQF_TRIGGER_MASK) { |
e76de9f8e [PATCH] genirq: a... |
318 319 |
if (desc->chip && desc->chip->set_type) desc->chip->set_type(irq, |
3cca53b02 [PATCH] irq-flags... |
320 |
new->flags & IRQF_TRIGGER_MASK); |
e76de9f8e [PATCH] genirq: a... |
321 322 |
else /* |
3cca53b02 [PATCH] irq-flags... |
323 |
* IRQF_TRIGGER_* but the PIC does not support |
e76de9f8e [PATCH] genirq: a... |
324 325 |
* multiple flow-types? */ |
3cca53b02 [PATCH] irq-flags... |
326 |
printk(KERN_WARNING "No IRQF_TRIGGER set_type " |
e8c4b9d00 [PATCH] IRQ: warn... |
327 328 329 330 |
"function for IRQ %d (%s) ", irq, desc->chip ? desc->chip->name : "unknown"); |
e76de9f8e [PATCH] genirq: a... |
331 332 |
} else compat_irq_chip_set_default_handler(desc); |
6a6de9ef5 [PATCH] genirq: core |
333 |
|
94d39e1f6 [PATCH] genirq: a... |
334 335 336 337 338 339 340 341 342 343 |
desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); if (!(desc->status & IRQ_NOAUTOEN)) { desc->depth = 0; desc->status &= ~IRQ_DISABLED; if (desc->chip->startup) desc->chip->startup(irq); else desc->chip->enable(irq); |
e76de9f8e [PATCH] genirq: a... |
344 345 346 |
} else /* Undo nested disables: */ desc->depth = 1; |
1da177e4c Linux-2.6.12-rc2 |
347 |
} |
8528b0f1d Clear spurious ir... |
348 349 350 |
/* Reset broken irq detection when installing new handler */ desc->irq_count = 0; desc->irqs_unhandled = 0; |
06fcb0c6f [PATCH] genirq: c... |
351 |
spin_unlock_irqrestore(&desc->lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
352 353 354 355 356 357 358 |
new->irq = irq; register_irq_proc(irq); new->dir = NULL; register_handler_proc(irq, new); return 0; |
f51634274 [PATCH] Add SA_PE... |
359 360 |
mismatch: |
3f0504471 [PATCH] kernel: s... |
361 |
#ifdef CONFIG_DEBUG_SHIRQ |
3cca53b02 [PATCH] irq-flags... |
362 |
if (!(new->flags & IRQF_PROBE_SHARED)) { |
e8c4b9d00 [PATCH] IRQ: warn... |
363 364 |
printk(KERN_ERR "IRQ handler type mismatch for IRQ %d ", irq); |
8b126b775 [PATCH] setup_irq... |
365 366 367 |
if (old_name) printk(KERN_ERR "current handler: %s ", old_name); |
13e87ec68 [PATCH] request_i... |
368 369 |
dump_stack(); } |
3f0504471 [PATCH] kernel: s... |
370 |
#endif |
8b126b775 [PATCH] setup_irq... |
371 |
spin_unlock_irqrestore(&desc->lock, flags); |
f51634274 [PATCH] Add SA_PE... |
372 |
return -EBUSY; |
1da177e4c Linux-2.6.12-rc2 |
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 |
} /** * free_irq - free an interrupt * @irq: Interrupt line to free * @dev_id: Device identity to free * * Remove an interrupt handler. The handler is removed and if the * interrupt line is no longer in use by any driver it is disabled. * On a shared IRQ the caller must ensure the interrupt is disabled * on the card it drives before calling this function. The function * does not return until any executing interrupts for this IRQ * have completed. * * This function must not be called from interrupt context. */ void free_irq(unsigned int irq, void *dev_id) { struct irq_desc *desc; struct irqaction **p; unsigned long flags; |
a304e1b82 [PATCH] Debug sha... |
394 |
irqreturn_t (*handler)(int, void *) = NULL; |
1da177e4c Linux-2.6.12-rc2 |
395 |
|
cd7b24bb1 [PATCH] warn if f... |
396 |
WARN_ON(in_interrupt()); |
1da177e4c Linux-2.6.12-rc2 |
397 398 399 400 |
if (irq >= NR_IRQS) return; desc = irq_desc + irq; |
06fcb0c6f [PATCH] genirq: c... |
401 |
spin_lock_irqsave(&desc->lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
402 403 |
p = &desc->action; for (;;) { |
06fcb0c6f [PATCH] genirq: c... |
404 |
struct irqaction *action = *p; |
1da177e4c Linux-2.6.12-rc2 |
405 406 407 408 409 410 411 412 413 414 |
if (action) { struct irqaction **pp = p; p = &action->next; if (action->dev_id != dev_id) continue; /* Found it - now remove it from the list of entries */ *pp = action->next; |
dbce706e2 [PATCH] uml: add ... |
415 |
|
b77d6adc9 [PATCH] uml: make... |
416 417 |
/* Currently used only by UML, might disappear one day.*/ #ifdef CONFIG_IRQ_RELEASE_METHOD |
d1bef4ed5 [PATCH] genirq: r... |
418 419 |
if (desc->chip->release) desc->chip->release(irq, dev_id); |
b77d6adc9 [PATCH] uml: make... |
420 |
#endif |
dbce706e2 [PATCH] uml: add ... |
421 |
|
1da177e4c Linux-2.6.12-rc2 |
422 423 |
if (!desc->action) { desc->status |= IRQ_DISABLED; |
d1bef4ed5 [PATCH] genirq: r... |
424 425 |
if (desc->chip->shutdown) desc->chip->shutdown(irq); |
1da177e4c Linux-2.6.12-rc2 |
426 |
else |
d1bef4ed5 [PATCH] genirq: r... |
427 |
desc->chip->disable(irq); |
1da177e4c Linux-2.6.12-rc2 |
428 |
} |
06fcb0c6f [PATCH] genirq: c... |
429 |
spin_unlock_irqrestore(&desc->lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
430 431 432 433 |
unregister_handler_proc(irq, action); /* Make sure it's not being used on another CPU */ synchronize_irq(irq); |
a304e1b82 [PATCH] Debug sha... |
434 435 |
if (action->flags & IRQF_SHARED) handler = action->handler; |
1da177e4c Linux-2.6.12-rc2 |
436 437 438 |
kfree(action); return; } |
e8c4b9d00 [PATCH] IRQ: warn... |
439 440 |
printk(KERN_ERR "Trying to free already-free IRQ %d ", irq); |
06fcb0c6f [PATCH] genirq: c... |
441 |
spin_unlock_irqrestore(&desc->lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
442 443 |
return; } |
a304e1b82 [PATCH] Debug sha... |
444 445 446 447 448 449 450 451 452 453 454 |
#ifdef CONFIG_DEBUG_SHIRQ if (handler) { /* * It's a shared IRQ -- the driver ought to be prepared for it * to happen even now it's being freed, so let's make sure.... * We do this after actually deregistering it, to make sure that * a 'real' IRQ doesn't run in parallel with our fake */ handler(irq, dev_id); } #endif |
1da177e4c Linux-2.6.12-rc2 |
455 |
} |
1da177e4c Linux-2.6.12-rc2 |
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 |
EXPORT_SYMBOL(free_irq); /** * request_irq - allocate an interrupt line * @irq: Interrupt line to allocate * @handler: Function to be called when the IRQ occurs * @irqflags: Interrupt type flags * @devname: An ascii name for the claiming device * @dev_id: A cookie passed back to the handler function * * This call allocates interrupt resources and enables the * interrupt line and IRQ handling. From the point this * call is made your handler function may be invoked. Since * your handler function must clear any interrupt the board * raises, you must take care both to initialise your hardware * and to set up the interrupt handler in the right order. * * Dev_id must be globally unique. Normally the address of the * device data structure is used as the cookie. Since the handler * receives this value it makes sense to use it. * * If your interrupt is shared you must pass a non NULL dev_id * as this is required when freeing the interrupt. * * Flags: * |
3cca53b02 [PATCH] irq-flags... |
482 483 484 |
* IRQF_SHARED Interrupt is shared * IRQF_DISABLED Disable local interrupts while processing * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy |
1da177e4c Linux-2.6.12-rc2 |
485 486 |
* */ |
da482792a IRQ: Typedef the ... |
487 |
int request_irq(unsigned int irq, irq_handler_t handler, |
06fcb0c6f [PATCH] genirq: c... |
488 |
unsigned long irqflags, const char *devname, void *dev_id) |
1da177e4c Linux-2.6.12-rc2 |
489 |
{ |
06fcb0c6f [PATCH] genirq: c... |
490 |
struct irqaction *action; |
1da177e4c Linux-2.6.12-rc2 |
491 |
int retval; |
fbb9ce953 [PATCH] lockdep: ... |
492 493 494 495 |
#ifdef CONFIG_LOCKDEP /* * Lockdep wants atomic interrupt handlers: */ |
38515e908 [PATCH] Scheduled... |
496 |
irqflags |= IRQF_DISABLED; |
fbb9ce953 [PATCH] lockdep: ... |
497 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
498 499 500 501 502 503 |
/* * Sanity-check: shared interrupts must pass in a real dev-ID, * otherwise we'll have trouble later trying to figure out * which interrupt is which (messes up the interrupt freeing * logic etc). */ |
3cca53b02 [PATCH] irq-flags... |
504 |
if ((irqflags & IRQF_SHARED) && !dev_id) |
1da177e4c Linux-2.6.12-rc2 |
505 506 507 |
return -EINVAL; if (irq >= NR_IRQS) return -EINVAL; |
6550c775c [PATCH] genirq: a... |
508 509 |
if (irq_desc[irq].status & IRQ_NOREQUEST) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
510 511 512 513 514 515 516 517 518 519 520 521 522 |
if (!handler) return -EINVAL; action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) return -ENOMEM; action->handler = handler; action->flags = irqflags; cpus_clear(action->mask); action->name = devname; action->next = NULL; action->dev_id = dev_id; |
eee45269b [PATCH] Alpha: co... |
523 |
select_smp_affinity(irq); |
a304e1b82 [PATCH] Debug sha... |
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 |
#ifdef CONFIG_DEBUG_SHIRQ if (irqflags & IRQF_SHARED) { /* * It's a shared IRQ -- the driver ought to be prepared for it * to happen immediately, so let's make sure.... * We do this before actually registering it, to make sure that * a 'real' IRQ doesn't run in parallel with our fake */ if (irqflags & IRQF_DISABLED) { unsigned long flags; local_irq_save(flags); handler(irq, dev_id); local_irq_restore(flags); } else handler(irq, dev_id); } #endif |
1da177e4c Linux-2.6.12-rc2 |
542 543 544 545 546 547 |
retval = setup_irq(irq, action); if (retval) kfree(action); return retval; } |
1da177e4c Linux-2.6.12-rc2 |
548 |
EXPORT_SYMBOL(request_irq); |