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.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index dc04c166c54d..6397df2d6945 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc)
281 } 281 }
282} 282}
283 283
284void unmask_threaded_irq(struct irq_desc *desc)
285{
286 struct irq_chip *chip = desc->irq_data.chip;
287
288 if (chip->flags & IRQCHIP_EOI_THREADED)
289 chip->irq_eoi(&desc->irq_data);
290
291 if (chip->irq_unmask) {
292 chip->irq_unmask(&desc->irq_data);
293 irq_state_clr_masked(desc);
294 }
295}
296
284/* 297/*
285 * handle_nested_irq - Handle a nested irq from a irq thread 298 * handle_nested_irq - Handle a nested irq from a irq thread
286 * @irq: the interrupt number 299 * @irq: the interrupt number
@@ -435,6 +448,27 @@ static inline void preflow_handler(struct irq_desc *desc)
435static inline void preflow_handler(struct irq_desc *desc) { } 448static inline void preflow_handler(struct irq_desc *desc) { }
436#endif 449#endif
437 450
451static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
452{
453 if (!(desc->istate & IRQS_ONESHOT)) {
454 chip->irq_eoi(&desc->irq_data);
455 return;
456 }
457 /*
458 * We need to unmask in the following cases:
459 * - Oneshot irq which did not wake the thread (caused by a
460 * spurious interrupt or a primary handler handling it
461 * completely).
462 */
463 if (!irqd_irq_disabled(&desc->irq_data) &&
464 irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
465 chip->irq_eoi(&desc->irq_data);
466 unmask_irq(desc);
467 } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
468 chip->irq_eoi(&desc->irq_data);
469 }
470}
471
438/** 472/**
439 * handle_fasteoi_irq - irq handler for transparent controllers 473 * handle_fasteoi_irq - irq handler for transparent controllers
440 * @irq: the interrupt number 474 * @irq: the interrupt number
@@ -448,6 +482,8 @@ static inline void preflow_handler(struct irq_desc *desc) { }
448void 482void
449handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) 483handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
450{ 484{
485 struct irq_chip *chip = desc->irq_data.chip;
486
451 raw_spin_lock(&desc->lock); 487 raw_spin_lock(&desc->lock);
452 488
453 if (unlikely(irqd_irq_inprogress(&desc->irq_data))) 489 if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
473 preflow_handler(desc); 509 preflow_handler(desc);
474 handle_irq_event(desc); 510 handle_irq_event(desc);
475 511
476 if (desc->istate & IRQS_ONESHOT) 512 cond_unmask_eoi_irq(desc, chip);
477 cond_unmask_irq(desc);
478 513
479out_eoi:
480 desc->irq_data.chip->irq_eoi(&desc->irq_data);
481out_unlock:
482 raw_spin_unlock(&desc->lock); 514 raw_spin_unlock(&desc->lock);
483 return; 515 return;
484out: 516out:
485 if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED)) 517 if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
486 goto out_eoi; 518 chip->irq_eoi(&desc->irq_data);
487 goto out_unlock; 519 raw_spin_unlock(&desc->lock);
488} 520}
489 521
490/** 522/**