aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/chip.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2012-02-08 05:57:52 -0500
committerLuis Henriques <luis.henriques@canonical.com>2012-03-26 05:26:46 -0400
commit4013a9d5a559fac2775485e8d7d888c8a5c46dfa (patch)
tree2046f078cfb376763a4cc35111236581c552ea5e /kernel/irq/chip.c
parent107ae9b50a9160948a11f2e78072188e71886ebb (diff)
genirq: Handle pending irqs in irq_startup()
BugLink: http://bugs.launchpad.net/bugs/954576 commit b4bc724e82e80478cba5fe9825b62e71ddf78757 upstream. 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> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r--kernel/irq/chip.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 3322a34d9ee..ca14f5dcabd 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -157,19 +157,22 @@ static void irq_state_set_masked(struct irq_desc *desc)
157 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); 157 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
158} 158}
159 159
160int irq_startup(struct irq_desc *desc) 160int irq_startup(struct irq_desc *desc, bool resend)
161{ 161{
162 int ret = 0;
163
162 irq_state_clr_disabled(desc); 164 irq_state_clr_disabled(desc);
163 desc->depth = 0; 165 desc->depth = 0;
164 166
165 if (desc->irq_data.chip->irq_startup) { 167 if (desc->irq_data.chip->irq_startup) {
166 int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); 168 ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
167 irq_state_clr_masked(desc); 169 irq_state_clr_masked(desc);
168 return ret; 170 } else {
171 irq_enable(desc);
169 } 172 }
170 173 if (resend)
171 irq_enable(desc); 174 check_irq_resend(desc, desc->irq_data.irq);
172 return 0; 175 return ret;
173} 176}
174 177
175void irq_shutdown(struct irq_desc *desc) 178void irq_shutdown(struct irq_desc *desc)
@@ -596,7 +599,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
596 irq_settings_set_noprobe(desc); 599 irq_settings_set_noprobe(desc);
597 irq_settings_set_norequest(desc); 600 irq_settings_set_norequest(desc);
598 irq_settings_set_nothread(desc); 601 irq_settings_set_nothread(desc);
599 irq_startup(desc); 602 irq_startup(desc, true);
600 } 603 }
601out: 604out:
602 irq_put_desc_busunlock(desc, flags); 605 irq_put_desc_busunlock(desc, flags);