cf4f6e1e21e898d198b334c8b126b399191223ef
[openwrt/openwrt.git] / target / linux / generic / backport-5.4 / 041-genirq-affinity-Make-affinity-setting-if-activated-o.patch
1 From: Thomas Gleixner <tglx@linutronix.de>
2 Date: Fri, 24 Jul 2020 22:44:41 +0200
3 Subject: [PATCH] genirq/affinity: Make affinity setting if activated opt-in
4
5 commit f0c7baca180046824e07fc5f1326e83a8fd150c7 upstream.
6
7 John reported that on a RK3288 system the perf per CPU interrupts are all
8 affine to CPU0 and provided the analysis:
9
10 "It looks like what happens is that because the interrupts are not per-CPU
11 in the hardware, armpmu_request_irq() calls irq_force_affinity() while
12 the interrupt is deactivated and then request_irq() with IRQF_PERCPU |
13 IRQF_NOBALANCING.
14
15 Now when irq_startup() runs with IRQ_STARTUP_NORMAL, it calls
16 irq_setup_affinity() which returns early because IRQF_PERCPU and
17 IRQF_NOBALANCING are set, leaving the interrupt on its original CPU."
18
19 This was broken by the recent commit which blocked interrupt affinity
20 setting in hardware before activation of the interrupt. While this works in
21 general, it does not work for this particular case. As contrary to the
22 initial analysis not all interrupt chip drivers implement an activate
23 callback, the safe cure is to make the deferred interrupt affinity setting
24 at activation time opt-in.
25
26 Implement the necessary core logic and make the two irqchip implementations
27 for which this is required opt-in. In hindsight this would have been the
28 right thing to do, but ...
29
30 Fixes: baedb87d1b53 ("genirq/affinity: Handle affinity setting on inactive interrupts correctly")
31 Reported-by: John Keeping <john@metanate.com>
32 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
33 Tested-by: Marc Zyngier <maz@kernel.org>
34 Acked-by: Marc Zyngier <maz@kernel.org>
35 Cc: stable@vger.kernel.org
36 Link: https://lkml.kernel.org/r/87blk4tzgm.fsf@nanos.tec.linutronix.de
37 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
38 ---
39
40 --- a/arch/x86/kernel/apic/vector.c
41 +++ b/arch/x86/kernel/apic/vector.c
42 @@ -554,6 +554,10 @@ static int x86_vector_alloc_irqs(struct
43 irqd->chip_data = apicd;
44 irqd->hwirq = virq + i;
45 irqd_set_single_target(irqd);
46 +
47 + /* Don't invoke affinity setter on deactivated interrupts */
48 + irqd_set_affinity_on_activate(irqd);
49 +
50 /*
51 * Legacy vectors are already assigned when the IOAPIC
52 * takes them over. They stay on the same vector. This is
53 --- a/drivers/irqchip/irq-gic-v3-its.c
54 +++ b/drivers/irqchip/irq-gic-v3-its.c
55 @@ -2581,6 +2581,7 @@ static int its_irq_domain_alloc(struct i
56 msi_alloc_info_t *info = args;
57 struct its_device *its_dev = info->scratchpad[0].ptr;
58 struct its_node *its = its_dev->its;
59 + struct irq_data *irqd;
60 irq_hw_number_t hwirq;
61 int err;
62 int i;
63 @@ -2600,7 +2601,9 @@ static int its_irq_domain_alloc(struct i
64
65 irq_domain_set_hwirq_and_chip(domain, virq + i,
66 hwirq + i, &its_irq_chip, its_dev);
67 - irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
68 + irqd = irq_get_irq_data(virq + i);
69 + irqd_set_single_target(irqd);
70 + irqd_set_affinity_on_activate(irqd);
71 pr_debug("ID:%d pID:%d vID:%d\n",
72 (int)(hwirq + i - its_dev->event_map.lpi_base),
73 (int)(hwirq + i), virq + i);
74 --- a/include/linux/irq.h
75 +++ b/include/linux/irq.h
76 @@ -211,6 +211,8 @@ struct irq_data {
77 * IRQD_CAN_RESERVE - Can use reservation mode
78 * IRQD_MSI_NOMASK_QUIRK - Non-maskable MSI quirk for affinity change
79 * required
80 + * IRQD_AFFINITY_ON_ACTIVATE - Affinity is set on activation. Don't call
81 + * irq_chip::irq_set_affinity() when deactivated.
82 */
83 enum {
84 IRQD_TRIGGER_MASK = 0xf,
85 @@ -234,6 +236,7 @@ enum {
86 IRQD_DEFAULT_TRIGGER_SET = (1 << 25),
87 IRQD_CAN_RESERVE = (1 << 26),
88 IRQD_MSI_NOMASK_QUIRK = (1 << 27),
89 + IRQD_AFFINITY_ON_ACTIVATE = (1 << 29),
90 };
91
92 #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
93 @@ -408,6 +411,16 @@ static inline bool irqd_msi_nomask_quirk
94 return __irqd_to_state(d) & IRQD_MSI_NOMASK_QUIRK;
95 }
96
97 +static inline void irqd_set_affinity_on_activate(struct irq_data *d)
98 +{
99 + __irqd_to_state(d) |= IRQD_AFFINITY_ON_ACTIVATE;
100 +}
101 +
102 +static inline bool irqd_affinity_on_activate(struct irq_data *d)
103 +{
104 + return __irqd_to_state(d) & IRQD_AFFINITY_ON_ACTIVATE;
105 +}
106 +
107 #undef __irqd_to_state
108
109 static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
110 --- a/kernel/irq/manage.c
111 +++ b/kernel/irq/manage.c
112 @@ -281,12 +281,16 @@ static bool irq_set_affinity_deactivated
113 struct irq_desc *desc = irq_data_to_desc(data);
114
115 /*
116 + * Handle irq chips which can handle affinity only in activated
117 + * state correctly
118 + *
119 * If the interrupt is not yet activated, just store the affinity
120 * mask and do not call the chip driver at all. On activation the
121 * driver has to make sure anyway that the interrupt is in a
122 * useable state so startup works.
123 */
124 - if (!IS_ENABLED(CONFIG_IRQ_DOMAIN_HIERARCHY) || irqd_is_activated(data))
125 + if (!IS_ENABLED(CONFIG_IRQ_DOMAIN_HIERARCHY) ||
126 + irqd_is_activated(data) || !irqd_affinity_on_activate(data))
127 return false;
128
129 cpumask_copy(desc->irq_common_data.affinity, mask);