aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/chip.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r--kernel/irq/chip.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index f7c543a801d9..6080f6bc8c33 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -16,6 +16,8 @@
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/kernel_stat.h> 17#include <linux/kernel_stat.h>
18 18
19#include <trace/events/irq.h>
20
19#include "internals.h" 21#include "internals.h"
20 22
21/** 23/**
@@ -61,8 +63,7 @@ int irq_set_irq_type(unsigned int irq, unsigned int type)
61 return -EINVAL; 63 return -EINVAL;
62 64
63 type &= IRQ_TYPE_SENSE_MASK; 65 type &= IRQ_TYPE_SENSE_MASK;
64 if (type != IRQ_TYPE_NONE) 66 ret = __irq_set_trigger(desc, irq, type);
65 ret = __irq_set_trigger(desc, irq, type);
66 irq_put_desc_busunlock(desc, flags); 67 irq_put_desc_busunlock(desc, flags);
67 return ret; 68 return ret;
68} 69}
@@ -157,19 +158,22 @@ static void irq_state_set_masked(struct irq_desc *desc)
157 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); 158 irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
158} 159}
159 160
160int irq_startup(struct irq_desc *desc) 161int irq_startup(struct irq_desc *desc, bool resend)
161{ 162{
163 int ret = 0;
164
162 irq_state_clr_disabled(desc); 165 irq_state_clr_disabled(desc);
163 desc->depth = 0; 166 desc->depth = 0;
164 167
165 if (desc->irq_data.chip->irq_startup) { 168 if (desc->irq_data.chip->irq_startup) {
166 int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); 169 ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
167 irq_state_clr_masked(desc); 170 irq_state_clr_masked(desc);
168 return ret; 171 } else {
172 irq_enable(desc);
169 } 173 }
170 174 if (resend)
171 irq_enable(desc); 175 check_irq_resend(desc, desc->irq_data.irq);
172 return 0; 176 return ret;
173} 177}
174 178
175void irq_shutdown(struct irq_desc *desc) 179void irq_shutdown(struct irq_desc *desc)
@@ -330,6 +334,24 @@ out_unlock:
330} 334}
331EXPORT_SYMBOL_GPL(handle_simple_irq); 335EXPORT_SYMBOL_GPL(handle_simple_irq);
332 336
337/*
338 * Called unconditionally from handle_level_irq() and only for oneshot
339 * interrupts from handle_fasteoi_irq()
340 */
341static void cond_unmask_irq(struct irq_desc *desc)
342{
343 /*
344 * We need to unmask in the following cases:
345 * - Standard level irq (IRQF_ONESHOT is not set)
346 * - Oneshot irq which did not wake the thread (caused by a
347 * spurious interrupt or a primary handler handling it
348 * completely).
349 */
350 if (!irqd_irq_disabled(&desc->irq_data) &&
351 irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot)
352 unmask_irq(desc);
353}
354
333/** 355/**
334 * handle_level_irq - Level type irq handler 356 * handle_level_irq - Level type irq handler
335 * @irq: the interrupt number 357 * @irq: the interrupt number
@@ -362,8 +384,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
362 384
363 handle_irq_event(desc); 385 handle_irq_event(desc);
364 386
365 if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) 387 cond_unmask_irq(desc);
366 unmask_irq(desc); 388
367out_unlock: 389out_unlock:
368 raw_spin_unlock(&desc->lock); 390 raw_spin_unlock(&desc->lock);
369} 391}
@@ -417,6 +439,9 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
417 preflow_handler(desc); 439 preflow_handler(desc);
418 handle_irq_event(desc); 440 handle_irq_event(desc);
419 441
442 if (desc->istate & IRQS_ONESHOT)
443 cond_unmask_irq(desc);
444
420out_eoi: 445out_eoi:
421 desc->irq_data.chip->irq_eoi(&desc->irq_data); 446 desc->irq_data.chip->irq_eoi(&desc->irq_data);
422out_unlock: 447out_unlock:
@@ -625,7 +650,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
625 irq_settings_set_noprobe(desc); 650 irq_settings_set_noprobe(desc);
626 irq_settings_set_norequest(desc); 651 irq_settings_set_norequest(desc);
627 irq_settings_set_nothread(desc); 652 irq_settings_set_nothread(desc);
628 irq_startup(desc); 653 irq_startup(desc, true);
629 } 654 }
630out: 655out:
631 irq_put_desc_busunlock(desc, flags); 656 irq_put_desc_busunlock(desc, flags);