d1: add new target
[openwrt/staging/pepe2k.git] / target / linux / d1 / patches-6.1 / 0011-genirq-Add-support-for-oneshot-safe-threaded-EOIs.patch
1 From ee6459d60f24d91052f0288155f44e6a7f991050 Mon Sep 17 00:00:00 2001
2 From: Samuel Holland <samuel@sholland.org>
3 Date: Sat, 7 May 2022 18:34:25 -0500
4 Subject: [PATCH 011/117] genirq: Add support for oneshot-safe threaded EOIs
5
6 irqchips can use the combination of flags IRQCHIP_ONESHOT_SAFE |
7 IRQCHIP_EOI_THREADED to elide mask operations.
8
9 Signed-off-by: Samuel Holland <samuel@sholland.org>
10 ---
11 kernel/irq/chip.c | 36 +++++++++++++++++-------------------
12 kernel/irq/internals.h | 2 +-
13 kernel/irq/manage.c | 12 ++++++------
14 3 files changed, 24 insertions(+), 26 deletions(-)
15
16 --- a/kernel/irq/chip.c
17 +++ b/kernel/irq/chip.c
18 @@ -439,16 +439,6 @@ void unmask_irq(struct irq_desc *desc)
19 }
20 }
21
22 -void unmask_threaded_irq(struct irq_desc *desc)
23 -{
24 - struct irq_chip *chip = desc->irq_data.chip;
25 -
26 - if (chip->flags & IRQCHIP_EOI_THREADED)
27 - chip->irq_eoi(&desc->irq_data);
28 -
29 - unmask_irq(desc);
30 -}
31 -
32 /*
33 * handle_nested_irq - Handle a nested irq from a irq thread
34 * @irq: the interrupt number
35 @@ -656,25 +646,33 @@ out_unlock:
36 }
37 EXPORT_SYMBOL_GPL(handle_level_irq);
38
39 -static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
40 +void unmask_eoi_threaded_irq(struct irq_desc *desc)
41 {
42 - if (!(desc->istate & IRQS_ONESHOT)) {
43 + struct irq_chip *chip = desc->irq_data.chip;
44 +
45 + if (desc->istate & IRQS_ONESHOT)
46 + unmask_irq(desc);
47 +
48 + if (chip->flags & IRQCHIP_EOI_THREADED)
49 chip->irq_eoi(&desc->irq_data);
50 +}
51 +
52 +static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
53 +{
54 + /* Do not send EOI if the thread will do it for us. */
55 + if ((chip->flags & IRQCHIP_EOI_THREADED) && desc->threads_oneshot)
56 return;
57 - }
58 +
59 /*
60 * We need to unmask in the following cases:
61 * - Oneshot irq which did not wake the thread (caused by a
62 * spurious interrupt or a primary handler handling it
63 * completely).
64 */
65 - if (!irqd_irq_disabled(&desc->irq_data) &&
66 - irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
67 - chip->irq_eoi(&desc->irq_data);
68 + if ((desc->istate & IRQS_ONESHOT) && !desc->threads_oneshot)
69 unmask_irq(desc);
70 - } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
71 - chip->irq_eoi(&desc->irq_data);
72 - }
73 +
74 + chip->irq_eoi(&desc->irq_data);
75 }
76
77 /**
78 --- a/kernel/irq/internals.h
79 +++ b/kernel/irq/internals.h
80 @@ -93,7 +93,7 @@ extern void irq_percpu_enable(struct irq
81 extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
82 extern void mask_irq(struct irq_desc *desc);
83 extern void unmask_irq(struct irq_desc *desc);
84 -extern void unmask_threaded_irq(struct irq_desc *desc);
85 +extern void unmask_eoi_threaded_irq(struct irq_desc *desc);
86
87 #ifdef CONFIG_SPARSE_IRQ
88 static inline void irq_mark_irq(unsigned int irq) { }
89 --- a/kernel/irq/manage.c
90 +++ b/kernel/irq/manage.c
91 @@ -1074,9 +1074,9 @@ static int irq_wait_for_interrupt(struct
92 static void irq_finalize_oneshot(struct irq_desc *desc,
93 struct irqaction *action)
94 {
95 - if (!(desc->istate & IRQS_ONESHOT) ||
96 - action->handler == irq_forced_secondary_handler)
97 + if (action->handler == irq_forced_secondary_handler)
98 return;
99 +
100 again:
101 chip_bus_lock(desc);
102 raw_spin_lock_irq(&desc->lock);
103 @@ -1112,9 +1112,8 @@ again:
104
105 desc->threads_oneshot &= ~action->thread_mask;
106
107 - if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
108 - irqd_irq_masked(&desc->irq_data))
109 - unmask_threaded_irq(desc);
110 + if (!desc->threads_oneshot)
111 + unmask_eoi_threaded_irq(desc);
112
113 out_unlock:
114 raw_spin_unlock_irq(&desc->lock);
115 @@ -1662,7 +1661,8 @@ __setup_irq(unsigned int irq, struct irq
116 * !ONESHOT irqs the thread mask is 0 so we can avoid a
117 * conditional in irq_wake_thread().
118 */
119 - if (new->flags & IRQF_ONESHOT) {
120 + if ((new->flags & IRQF_ONESHOT) ||
121 + (desc->irq_data.chip->flags & (IRQCHIP_ONESHOT_SAFE | IRQCHIP_EOI_THREADED)) == (IRQCHIP_ONESHOT_SAFE | IRQCHIP_EOI_THREADED)) {
122 /*
123 * Unlikely to have 32 resp 64 irqs sharing one line,
124 * but who knows.