aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/irq/chip.c6
-rw-r--r--kernel/irq/manage.c127
-rw-r--r--kernel/irq/spurious.c14
3 files changed, 83 insertions, 64 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 7de11bd64df..55d526c0eef 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -290,7 +290,8 @@ static inline void mask_ack_irq(struct irq_desc *desc, int irq)
290 desc->chip->mask_ack(irq); 290 desc->chip->mask_ack(irq);
291 else { 291 else {
292 desc->chip->mask(irq); 292 desc->chip->mask(irq);
293 desc->chip->ack(irq); 293 if (desc->chip->ack)
294 desc->chip->ack(irq);
294 } 295 }
295} 296}
296 297
@@ -476,7 +477,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
476 kstat_incr_irqs_this_cpu(irq, desc); 477 kstat_incr_irqs_this_cpu(irq, desc);
477 478
478 /* Start handling the irq */ 479 /* Start handling the irq */
479 desc->chip->ack(irq); 480 if (desc->chip->ack)
481 desc->chip->ack(irq);
480 desc = irq_remap_to_desc(irq, desc); 482 desc = irq_remap_to_desc(irq, desc);
481 483
482 /* Mark the IRQ currently in progress.*/ 484 /* Mark the IRQ currently in progress.*/
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 291f0366455..52ee1713509 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -389,9 +389,9 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
389 * allocate special interrupts that are part of the architecture. 389 * allocate special interrupts that are part of the architecture.
390 */ 390 */
391static int 391static int
392__setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) 392__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
393{ 393{
394 struct irqaction *old, **p; 394 struct irqaction *old, **old_ptr;
395 const char *old_name = NULL; 395 const char *old_name = NULL;
396 unsigned long flags; 396 unsigned long flags;
397 int shared = 0; 397 int shared = 0;
@@ -423,8 +423,8 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
423 * The following block of code has to be executed atomically 423 * The following block of code has to be executed atomically
424 */ 424 */
425 spin_lock_irqsave(&desc->lock, flags); 425 spin_lock_irqsave(&desc->lock, flags);
426 p = &desc->action; 426 old_ptr = &desc->action;
427 old = *p; 427 old = *old_ptr;
428 if (old) { 428 if (old) {
429 /* 429 /*
430 * Can't share interrupts unless both agree to and are 430 * Can't share interrupts unless both agree to and are
@@ -447,8 +447,8 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
447 447
448 /* add new interrupt at end of irq queue */ 448 /* add new interrupt at end of irq queue */
449 do { 449 do {
450 p = &old->next; 450 old_ptr = &old->next;
451 old = *p; 451 old = *old_ptr;
452 } while (old); 452 } while (old);
453 shared = 1; 453 shared = 1;
454 } 454 }
@@ -499,7 +499,7 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new)
499 (int)(new->flags & IRQF_TRIGGER_MASK)); 499 (int)(new->flags & IRQF_TRIGGER_MASK));
500 } 500 }
501 501
502 *p = new; 502 *old_ptr = new;
503 503
504 /* Reset broken irq detection when installing new handler */ 504 /* Reset broken irq detection when installing new handler */
505 desc->irq_count = 0; 505 desc->irq_count = 0;
@@ -567,72 +567,76 @@ int setup_irq(unsigned int irq, struct irqaction *act)
567void free_irq(unsigned int irq, void *dev_id) 567void free_irq(unsigned int irq, void *dev_id)
568{ 568{
569 struct irq_desc *desc = irq_to_desc(irq); 569 struct irq_desc *desc = irq_to_desc(irq);
570 struct irqaction **p; 570 struct irqaction *action, **action_ptr;
571 unsigned long flags; 571 unsigned long flags;
572 572
573 WARN_ON(in_interrupt()); 573 WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
574 574
575 if (!desc) 575 if (!desc)
576 return; 576 return;
577 577
578 spin_lock_irqsave(&desc->lock, flags); 578 spin_lock_irqsave(&desc->lock, flags);
579 p = &desc->action; 579
580 /*
581 * There can be multiple actions per IRQ descriptor, find the right
582 * one based on the dev_id:
583 */
584 action_ptr = &desc->action;
580 for (;;) { 585 for (;;) {
581 struct irqaction *action = *p; 586 action = *action_ptr;
587
588 if (!action) {
589 WARN(1, "Trying to free already-free IRQ %d\n", irq);
590 spin_unlock_irqrestore(&desc->lock, flags);
582 591
583 if (action) { 592 return;
584 struct irqaction **pp = p; 593 }
585 594
586 p = &action->next; 595 if (action->dev_id == dev_id)
587 if (action->dev_id != dev_id) 596 break;
588 continue; 597 action_ptr = &action->next;
598 }
589 599
590 /* Found it - now remove it from the list of entries */ 600 /* Found it - now remove it from the list of entries: */
591 *pp = action->next; 601 *action_ptr = action->next;
592 602
593 /* Currently used only by UML, might disappear one day.*/ 603 /* Currently used only by UML, might disappear one day: */
594#ifdef CONFIG_IRQ_RELEASE_METHOD 604#ifdef CONFIG_IRQ_RELEASE_METHOD
595 if (desc->chip->release) 605 if (desc->chip->release)
596 desc->chip->release(irq, dev_id); 606 desc->chip->release(irq, dev_id);
597#endif 607#endif
598 608
599 if (!desc->action) { 609 /* If this was the last handler, shut down the IRQ line: */
600 desc->status |= IRQ_DISABLED; 610 if (!desc->action) {
601 if (desc->chip->shutdown) 611 desc->status |= IRQ_DISABLED;
602 desc->chip->shutdown(irq); 612 if (desc->chip->shutdown)
603 else 613 desc->chip->shutdown(irq);
604 desc->chip->disable(irq); 614 else
605 } 615 desc->chip->disable(irq);
606 spin_unlock_irqrestore(&desc->lock, flags); 616 }
607 unregister_handler_proc(irq, action); 617 spin_unlock_irqrestore(&desc->lock, flags);
618
619 unregister_handler_proc(irq, action);
620
621 /* Make sure it's not being used on another CPU: */
622 synchronize_irq(irq);
608 623
609 /* Make sure it's not being used on another CPU */
610 synchronize_irq(irq);
611#ifdef CONFIG_DEBUG_SHIRQ
612 /*
613 * It's a shared IRQ -- the driver ought to be
614 * prepared for it to happen even now it's
615 * being freed, so let's make sure.... We do
616 * this after actually deregistering it, to
617 * make sure that a 'real' IRQ doesn't run in
618 * parallel with our fake
619 */
620 if (action->flags & IRQF_SHARED) {
621 local_irq_save(flags);
622 action->handler(irq, dev_id);
623 local_irq_restore(flags);
624 }
625#endif
626 kfree(action);
627 return;
628 }
629 printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
630#ifdef CONFIG_DEBUG_SHIRQ 624#ifdef CONFIG_DEBUG_SHIRQ
631 dump_stack(); 625 /*
632#endif 626 * It's a shared IRQ -- the driver ought to be prepared for an IRQ
633 spin_unlock_irqrestore(&desc->lock, flags); 627 * event to happen even now it's being freed, so let's make sure that
634 return; 628 * is so by doing an extra call to the handler ....
629 *
630 * ( We do this after actually deregistering it, to make sure that a
631 * 'real' IRQ doesn't run in * parallel with our fake. )
632 */
633 if (action->flags & IRQF_SHARED) {
634 local_irq_save(flags);
635 action->handler(irq, dev_id);
636 local_irq_restore(flags);
635 } 637 }
638#endif
639 kfree(action);
636} 640}
637EXPORT_SYMBOL(free_irq); 641EXPORT_SYMBOL(free_irq);
638 642
@@ -679,11 +683,12 @@ int request_irq(unsigned int irq, irq_handler_t handler,
679 * the behavior is classified as "will not fix" so we need to 683 * the behavior is classified as "will not fix" so we need to
680 * start nudging drivers away from using that idiom. 684 * start nudging drivers away from using that idiom.
681 */ 685 */
682 if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) 686 if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) ==
683 == (IRQF_SHARED|IRQF_DISABLED)) 687 (IRQF_SHARED|IRQF_DISABLED)) {
684 pr_warning("IRQ %d/%s: IRQF_DISABLED is not " 688 pr_warning(
685 "guaranteed on shared IRQs\n", 689 "IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs\n",
686 irq, devname); 690 irq, devname);
691 }
687 692
688#ifdef CONFIG_LOCKDEP 693#ifdef CONFIG_LOCKDEP
689 /* 694 /*
@@ -709,7 +714,7 @@ int request_irq(unsigned int irq, irq_handler_t handler,
709 if (!handler) 714 if (!handler)
710 return -EINVAL; 715 return -EINVAL;
711 716
712 action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); 717 action = kmalloc(sizeof(struct irqaction), GFP_KERNEL);
713 if (!action) 718 if (!action)
714 return -ENOMEM; 719 return -ENOMEM;
715 720
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index dd364c11e56..4d568294de3 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -104,7 +104,7 @@ static int misrouted_irq(int irq)
104 return ok; 104 return ok;
105} 105}
106 106
107static void poll_spurious_irqs(unsigned long dummy) 107static void poll_all_shared_irqs(void)
108{ 108{
109 struct irq_desc *desc; 109 struct irq_desc *desc;
110 int i; 110 int i;
@@ -123,11 +123,23 @@ static void poll_spurious_irqs(unsigned long dummy)
123 123
124 try_one_irq(i, desc); 124 try_one_irq(i, desc);
125 } 125 }
126}
127
128static void poll_spurious_irqs(unsigned long dummy)
129{
130 poll_all_shared_irqs();
126 131
127 mod_timer(&poll_spurious_irq_timer, 132 mod_timer(&poll_spurious_irq_timer,
128 jiffies + POLL_SPURIOUS_IRQ_INTERVAL); 133 jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
129} 134}
130 135
136#ifdef CONFIG_DEBUG_SHIRQ
137void debug_poll_all_shared_irqs(void)
138{
139 poll_all_shared_irqs();
140}
141#endif
142
131/* 143/*
132 * If 99,900 of the previous 100,000 interrupts have not been handled 144 * If 99,900 of the previous 100,000 interrupts have not been handled
133 * then assume that the IRQ is stuck in some manner. Drop a diagnostic 145 * then assume that the IRQ is stuck in some manner. Drop a diagnostic