Merge git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-genirq
* git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-genirq: genirq: reenable a nobody cared disabled irq when a new driver arrives
This commit is contained in:
commit
3482a6f1d1
3 changed files with 35 additions and 19 deletions
|
@ -61,6 +61,7 @@ typedef void (*irq_flow_handler_t)(unsigned int irq,
|
|||
#define IRQ_WAKEUP 0x00100000 /* IRQ triggers system wakeup */
|
||||
#define IRQ_MOVE_PENDING 0x00200000 /* need to re-target IRQ destination */
|
||||
#define IRQ_NO_BALANCING 0x00400000 /* IRQ is excluded from balancing */
|
||||
#define IRQ_SPURIOUS_DISABLED 0x00800000 /* IRQ was disabled by the spurious trap */
|
||||
|
||||
#ifdef CONFIG_IRQ_PER_CPU
|
||||
# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -209,8 +209,8 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
|
|||
* Now kill the IRQ
|
||||
*/
|
||||
printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->depth = 1;
|
||||
desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED;
|
||||
desc->depth++;
|
||||
desc->chip->disable(irq);
|
||||
}
|
||||
desc->irqs_unhandled = 0;
|
||||
|
|
Loading…
Reference in a new issue