123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- From ee6459d60f24d91052f0288155f44e6a7f991050 Mon Sep 17 00:00:00 2001
- From: Samuel Holland <[email protected]>
- Date: Sat, 7 May 2022 18:34:25 -0500
- Subject: [PATCH 011/117] genirq: Add support for oneshot-safe threaded EOIs
- irqchips can use the combination of flags IRQCHIP_ONESHOT_SAFE |
- IRQCHIP_EOI_THREADED to elide mask operations.
- Signed-off-by: Samuel Holland <[email protected]>
- ---
- kernel/irq/chip.c | 36 +++++++++++++++++-------------------
- kernel/irq/internals.h | 2 +-
- kernel/irq/manage.c | 12 ++++++------
- 3 files changed, 24 insertions(+), 26 deletions(-)
- --- a/kernel/irq/chip.c
- +++ b/kernel/irq/chip.c
- @@ -439,16 +439,6 @@ void unmask_irq(struct irq_desc *desc)
- }
- }
-
- -void unmask_threaded_irq(struct irq_desc *desc)
- -{
- - struct irq_chip *chip = desc->irq_data.chip;
- -
- - if (chip->flags & IRQCHIP_EOI_THREADED)
- - chip->irq_eoi(&desc->irq_data);
- -
- - unmask_irq(desc);
- -}
- -
- /*
- * handle_nested_irq - Handle a nested irq from a irq thread
- * @irq: the interrupt number
- @@ -656,25 +646,33 @@ out_unlock:
- }
- EXPORT_SYMBOL_GPL(handle_level_irq);
-
- -static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
- +void unmask_eoi_threaded_irq(struct irq_desc *desc)
- {
- - if (!(desc->istate & IRQS_ONESHOT)) {
- + struct irq_chip *chip = desc->irq_data.chip;
- +
- + if (desc->istate & IRQS_ONESHOT)
- + unmask_irq(desc);
- +
- + if (chip->flags & IRQCHIP_EOI_THREADED)
- chip->irq_eoi(&desc->irq_data);
- +}
- +
- +static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
- +{
- + /* Do not send EOI if the thread will do it for us. */
- + if ((chip->flags & IRQCHIP_EOI_THREADED) && desc->threads_oneshot)
- return;
- - }
- +
- /*
- * We need to unmask in the following cases:
- * - Oneshot irq which did not wake the thread (caused by a
- * spurious interrupt or a primary handler handling it
- * completely).
- */
- - if (!irqd_irq_disabled(&desc->irq_data) &&
- - irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
- - chip->irq_eoi(&desc->irq_data);
- + if ((desc->istate & IRQS_ONESHOT) && !desc->threads_oneshot)
- unmask_irq(desc);
- - } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
- - chip->irq_eoi(&desc->irq_data);
- - }
- +
- + chip->irq_eoi(&desc->irq_data);
- }
-
- /**
- --- a/kernel/irq/internals.h
- +++ b/kernel/irq/internals.h
- @@ -93,7 +93,7 @@ extern void irq_percpu_enable(struct irq
- extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
- extern void mask_irq(struct irq_desc *desc);
- extern void unmask_irq(struct irq_desc *desc);
- -extern void unmask_threaded_irq(struct irq_desc *desc);
- +extern void unmask_eoi_threaded_irq(struct irq_desc *desc);
-
- #ifdef CONFIG_SPARSE_IRQ
- static inline void irq_mark_irq(unsigned int irq) { }
- --- a/kernel/irq/manage.c
- +++ b/kernel/irq/manage.c
- @@ -1074,9 +1074,9 @@ static int irq_wait_for_interrupt(struct
- static void irq_finalize_oneshot(struct irq_desc *desc,
- struct irqaction *action)
- {
- - if (!(desc->istate & IRQS_ONESHOT) ||
- - action->handler == irq_forced_secondary_handler)
- + if (action->handler == irq_forced_secondary_handler)
- return;
- +
- again:
- chip_bus_lock(desc);
- raw_spin_lock_irq(&desc->lock);
- @@ -1112,9 +1112,8 @@ again:
-
- desc->threads_oneshot &= ~action->thread_mask;
-
- - if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
- - irqd_irq_masked(&desc->irq_data))
- - unmask_threaded_irq(desc);
- + if (!desc->threads_oneshot)
- + unmask_eoi_threaded_irq(desc);
-
- out_unlock:
- raw_spin_unlock_irq(&desc->lock);
- @@ -1662,7 +1661,8 @@ __setup_irq(unsigned int irq, struct irq
- * !ONESHOT irqs the thread mask is 0 so we can avoid a
- * conditional in irq_wake_thread().
- */
- - if (new->flags & IRQF_ONESHOT) {
- + if ((new->flags & IRQF_ONESHOT) ||
- + (desc->irq_data.chip->flags & (IRQCHIP_ONESHOT_SAFE | IRQCHIP_EOI_THREADED)) == (IRQCHIP_ONESHOT_SAFE | IRQCHIP_EOI_THREADED)) {
- /*
- * Unlikely to have 32 resp 64 irqs sharing one line,
- * but who knows.
|