mask_ack_irq(desc, irq);
if (unlikely(desc->status & IRQ_INPROGRESS))
- goto out;
+ goto out_unlock;
desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
kstat_cpu(cpu).irqs[irq]++;
* keep it masked and get out of here
*/
action = desc->action;
- if (unlikely(!action || (desc->status & IRQ_DISABLED)))
- goto out;
+ if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+ desc->status |= IRQ_PENDING;
+ goto out_unlock;
+ }
desc->status |= IRQ_INPROGRESS;
+ desc->status &= ~IRQ_PENDING;
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, regs, action);
spin_lock(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
-out:
if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
desc->chip->unmask(irq);
+out_unlock:
spin_unlock(&desc->lock);
}
if (!handle)
handle = handle_bad_irq;
- if (is_chained && desc->chip == &no_irq_chip)
- printk(KERN_WARNING "Trying to install "
- "chained interrupt type for IRQ%d\n", irq);
+ if (desc->chip == &no_irq_chip) {
+ printk(KERN_WARNING "Trying to install %sinterrupt handler "
+ "for IRQ%d\n", is_chained ? "chained " : " ", irq);
+ /*
+ * Some ARM implementations install a handler for really dumb
+ * interrupt hardware without setting an irq_chip. This worked
+ * with the ARM no_irq_chip but the check in setup_irq would
+ * prevent us to setup the interrupt at all. Switch it to
+ * dummy_irq_chip for easy transition.
+ */
+ desc->chip = &dummy_irq_chip;
+ }
spin_lock_irqsave(&desc->lock, flags);