aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2007-02-17 15:09:59 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-17 15:09:59 -0500
commit48c871c1f6a7c7044dd76774fb469e65c7e2e4e8 (patch)
treeda3aa535c98cc0957851354ceb0fbff7482d7a9d /kernel/irq/manage.c
parent1a1689344add3333d28d1b5495d8043a3877d01c (diff)
parent4409d28140d9a6e6e3f4f1fdaf7234c4b965d954 (diff)
Merge branch 'gfar' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc into upstream
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 8b961adc3bd2..7c85d69188ef 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -328,12 +328,14 @@ int setup_irq(unsigned int irq, struct irqaction *new)
328 return 0; 328 return 0;
329 329
330mismatch: 330mismatch:
331#ifdef CONFIG_DEBUG_SHIRQ
331 if (!(new->flags & IRQF_PROBE_SHARED)) { 332 if (!(new->flags & IRQF_PROBE_SHARED)) {
332 printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq); 333 printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
333 if (old_name) 334 if (old_name)
334 printk(KERN_ERR "current handler: %s\n", old_name); 335 printk(KERN_ERR "current handler: %s\n", old_name);
335 dump_stack(); 336 dump_stack();
336 } 337 }
338#endif
337 spin_unlock_irqrestore(&desc->lock, flags); 339 spin_unlock_irqrestore(&desc->lock, flags);
338 return -EBUSY; 340 return -EBUSY;
339} 341}
@@ -357,6 +359,7 @@ void free_irq(unsigned int irq, void *dev_id)
357 struct irq_desc *desc; 359 struct irq_desc *desc;
358 struct irqaction **p; 360 struct irqaction **p;
359 unsigned long flags; 361 unsigned long flags;
362 irqreturn_t (*handler)(int, void *) = NULL;
360 363
361 WARN_ON(in_interrupt()); 364 WARN_ON(in_interrupt());
362 if (irq >= NR_IRQS) 365 if (irq >= NR_IRQS)
@@ -396,6 +399,8 @@ void free_irq(unsigned int irq, void *dev_id)
396 399
397 /* Make sure it's not being used on another CPU */ 400 /* Make sure it's not being used on another CPU */
398 synchronize_irq(irq); 401 synchronize_irq(irq);
402 if (action->flags & IRQF_SHARED)
403 handler = action->handler;
399 kfree(action); 404 kfree(action);
400 return; 405 return;
401 } 406 }
@@ -403,6 +408,17 @@ void free_irq(unsigned int irq, void *dev_id)
403 spin_unlock_irqrestore(&desc->lock, flags); 408 spin_unlock_irqrestore(&desc->lock, flags);
404 return; 409 return;
405 } 410 }
411#ifdef CONFIG_DEBUG_SHIRQ
412 if (handler) {
413 /*
414 * It's a shared IRQ -- the driver ought to be prepared for it
415 * to happen even now it's being freed, so let's make sure....
416 * We do this after actually deregistering it, to make sure that
417 * a 'real' IRQ doesn't run in parallel with our fake
418 */
419 handler(irq, dev_id);
420 }
421#endif
406} 422}
407EXPORT_SYMBOL(free_irq); 423EXPORT_SYMBOL(free_irq);
408 424
@@ -475,6 +491,25 @@ int request_irq(unsigned int irq, irq_handler_t handler,
475 491
476 select_smp_affinity(irq); 492 select_smp_affinity(irq);
477 493
494#ifdef CONFIG_DEBUG_SHIRQ
495 if (irqflags & IRQF_SHARED) {
496 /*
497 * It's a shared IRQ -- the driver ought to be prepared for it
498 * to happen immediately, so let's make sure....
499 * We do this before actually registering it, to make sure that
500 * a 'real' IRQ doesn't run in parallel with our fake
501 */
502 if (irqflags & IRQF_DISABLED) {
503 unsigned long flags;
504
505 local_irq_save(flags);
506 handler(irq, dev_id);
507 local_irq_restore(flags);
508 } else
509 handler(irq, dev_id);
510 }
511#endif
512
478 retval = setup_irq(irq, action); 513 retval = setup_irq(irq, action);
479 if (retval) 514 if (retval)
480 kfree(action); 515 kfree(action);