|
@@ -150,6 +150,26 @@ void disable_irq(unsigned int irq)
|
|
|
}
|
|
|
EXPORT_SYMBOL(disable_irq);
|
|
|
|
|
|
+static void __enable_irq(struct irq_desc *desc, unsigned int irq)
|
|
|
+{
|
|
|
+ switch (desc->depth) {
|
|
|
+ case 0:
|
|
|
+ printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
|
|
|
+ WARN_ON(1);
|
|
|
+ break;
|
|
|
+ case 1: {
|
|
|
+ unsigned int status = desc->status & ~IRQ_DISABLED;
|
|
|
+
|
|
|
+ /* Prevent probing on this irq: */
|
|
|
+ desc->status = status | IRQ_NOPROBE;
|
|
|
+ check_irq_resend(desc, irq);
|
|
|
+ /* fall-through */
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ desc->depth--;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* enable_irq - enable handling of an irq
|
|
|
* @irq: Interrupt to enable
|
|
@@ -169,22 +189,7 @@ void enable_irq(unsigned int irq)
|
|
|
return;
|
|
|
|
|
|
spin_lock_irqsave(&desc->lock, flags);
|
|
|
- switch (desc->depth) {
|
|
|
- case 0:
|
|
|
- printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
|
|
|
- WARN_ON(1);
|
|
|
- break;
|
|
|
- case 1: {
|
|
|
- unsigned int status = desc->status & ~IRQ_DISABLED;
|
|
|
-
|
|
|
- /* Prevent probing on this irq: */
|
|
|
- desc->status = status | IRQ_NOPROBE;
|
|
|
- check_irq_resend(desc, irq);
|
|
|
- /* fall-through */
|
|
|
- }
|
|
|
- default:
|
|
|
- desc->depth--;
|
|
|
- }
|
|
|
+ __enable_irq(desc, irq);
|
|
|
spin_unlock_irqrestore(&desc->lock, flags);
|
|
|
}
|
|
|
EXPORT_SYMBOL(enable_irq);
|
|
@@ -365,7 +370,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
|
|
|
compat_irq_chip_set_default_handler(desc);
|
|
|
|
|
|
desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING |
|
|
|
- IRQ_INPROGRESS);
|
|
|
+ IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
|
|
|
|
|
|
if (!(desc->status & IRQ_NOAUTOEN)) {
|
|
|
desc->depth = 0;
|
|
@@ -381,6 +386,16 @@ int setup_irq(unsigned int irq, struct irqaction *new)
|
|
|
/* Reset broken irq detection when installing new handler */
|
|
|
desc->irq_count = 0;
|
|
|
desc->irqs_unhandled = 0;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check whether we disabled the irq via the spurious handler
|
|
|
+ * before. Reenable it and give it another chance.
|
|
|
+ */
|
|
|
+ if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
|
|
|
+ desc->status &= ~IRQ_SPURIOUS_DISABLED;
|
|
|
+ __enable_irq(desc, irq);
|
|
|
+ }
|
|
|
+
|
|
|
spin_unlock_irqrestore(&desc->lock, flags);
|
|
|
|
|
|
new->irq = irq;
|