mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
genirq: Handle pending irqs in irq_startup()
An interrupt might be pending when irq_startup() is called, but the startup code does not invoke the resend logic. In some cases this prevents the device from issuing another interrupt which renders the device non functional. Call the resend function in irq_startup() to keep things going. Reported-and-tested-by: Russell King <rmk+kernel@arm.linux.org.uk> Cc: stable@vger.kernel.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
ac56376111
commit
b4bc724e82
@ -53,7 +53,7 @@ unsigned long probe_irq_on(void)
|
||||
if (desc->irq_data.chip->irq_set_type)
|
||||
desc->irq_data.chip->irq_set_type(&desc->irq_data,
|
||||
IRQ_TYPE_PROBE);
|
||||
irq_startup(desc);
|
||||
irq_startup(desc, false);
|
||||
}
|
||||
raw_spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
@ -70,7 +70,7 @@ unsigned long probe_irq_on(void)
|
||||
raw_spin_lock_irq(&desc->lock);
|
||||
if (!desc->action && irq_settings_can_probe(desc)) {
|
||||
desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
|
||||
if (irq_startup(desc))
|
||||
if (irq_startup(desc, false))
|
||||
desc->istate |= IRQS_PENDING;
|
||||
}
|
||||
raw_spin_unlock_irq(&desc->lock);
|
||||
|
@ -157,19 +157,22 @@ static void irq_state_set_masked(struct irq_desc *desc)
|
||||
irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
|
||||
}
|
||||
|
||||
int irq_startup(struct irq_desc *desc)
|
||||
int irq_startup(struct irq_desc *desc, bool resend)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
irq_state_clr_disabled(desc);
|
||||
desc->depth = 0;
|
||||
|
||||
if (desc->irq_data.chip->irq_startup) {
|
||||
int ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
|
||||
ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
|
||||
irq_state_clr_masked(desc);
|
||||
return ret;
|
||||
} else {
|
||||
irq_enable(desc);
|
||||
}
|
||||
|
||||
irq_enable(desc);
|
||||
return 0;
|
||||
if (resend)
|
||||
check_irq_resend(desc, desc->irq_data.irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void irq_shutdown(struct irq_desc *desc)
|
||||
@ -646,7 +649,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
|
||||
irq_settings_set_noprobe(desc);
|
||||
irq_settings_set_norequest(desc);
|
||||
irq_settings_set_nothread(desc);
|
||||
irq_startup(desc);
|
||||
irq_startup(desc, true);
|
||||
}
|
||||
out:
|
||||
irq_put_desc_busunlock(desc, flags);
|
||||
|
@ -67,7 +67,7 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
|
||||
extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
|
||||
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
|
||||
|
||||
extern int irq_startup(struct irq_desc *desc);
|
||||
extern int irq_startup(struct irq_desc *desc, bool resend);
|
||||
extern void irq_shutdown(struct irq_desc *desc);
|
||||
extern void irq_enable(struct irq_desc *desc);
|
||||
extern void irq_disable(struct irq_desc *desc);
|
||||
|
@ -1027,7 +1027,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
||||
desc->istate |= IRQS_ONESHOT;
|
||||
|
||||
if (irq_settings_can_autoenable(desc))
|
||||
irq_startup(desc);
|
||||
irq_startup(desc, true);
|
||||
else
|
||||
/* Undo nested disables: */
|
||||
desc->depth = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user