Skip to content

Commit de07894

Browse files
smaeulMarc Zyngier
authored andcommitted
irqchip/sifive-plic: Make better use of the effective affinity mask
The PLIC driver already updates the effective affinity mask in its .irq_set_affinity callback. Take advantage of that information to only touch bits (and take spinlocks) for the specific relevant hart contexts. First, make sure the effective affinity mask is set before IRQ startup. Then, since this mask already takes priv->lmask into account, checking that mask later is no longer needed (and handler->present is equivalent to the bit being set in priv->lmask). Finally, when (un)masking or changing affinity, only clear/set the enable bits in the specific old/new context(s). The cpumask operations in plic_irq_unmask() are not needed because they duplicate the code in plic_set_affinity(). Signed-off-by: Samuel Holland <samuel@sholland.org> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20220701202440.59059-2-samuel@sholland.org
1 parent 4f4b8f8 commit de07894

File tree

2 files changed

+10
-18
lines changed

2 files changed

+10
-18
lines changed

drivers/irqchip/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ config SIFIVE_PLIC
531531
bool "SiFive Platform-Level Interrupt Controller"
532532
depends on RISCV
533533
select IRQ_DOMAIN_HIERARCHY
534+
select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
534535
help
535536
This enables support for the PLIC chip found in SiFive (and
536537
potentially other) RISC-V systems. The PLIC controls devices

drivers/irqchip/irq-sifive-plic.c

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -114,31 +114,18 @@ static inline void plic_irq_toggle(const struct cpumask *mask,
114114
for_each_cpu(cpu, mask) {
115115
struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
116116

117-
if (handler->present &&
118-
cpumask_test_cpu(cpu, &handler->priv->lmask))
119-
plic_toggle(handler, d->hwirq, enable);
117+
plic_toggle(handler, d->hwirq, enable);
120118
}
121119
}
122120

123121
static void plic_irq_unmask(struct irq_data *d)
124122
{
125-
struct cpumask amask;
126-
unsigned int cpu;
127-
struct plic_priv *priv = irq_data_get_irq_chip_data(d);
128-
129-
cpumask_and(&amask, &priv->lmask, cpu_online_mask);
130-
cpu = cpumask_any_and(irq_data_get_affinity_mask(d),
131-
&amask);
132-
if (WARN_ON_ONCE(cpu >= nr_cpu_ids))
133-
return;
134-
plic_irq_toggle(cpumask_of(cpu), d, 1);
123+
plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 1);
135124
}
136125

137126
static void plic_irq_mask(struct irq_data *d)
138127
{
139-
struct plic_priv *priv = irq_data_get_irq_chip_data(d);
140-
141-
plic_irq_toggle(&priv->lmask, d, 0);
128+
plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 0);
142129
}
143130

144131
#ifdef CONFIG_SMP
@@ -159,11 +146,13 @@ static int plic_set_affinity(struct irq_data *d,
159146
if (cpu >= nr_cpu_ids)
160147
return -EINVAL;
161148

162-
plic_irq_toggle(&priv->lmask, d, 0);
163-
plic_irq_toggle(cpumask_of(cpu), d, !irqd_irq_masked(d));
149+
plic_irq_mask(d);
164150

165151
irq_data_update_effective_affinity(d, cpumask_of(cpu));
166152

153+
if (!irqd_irq_masked(d))
154+
plic_irq_unmask(d);
155+
167156
return IRQ_SET_MASK_OK_DONE;
168157
}
169158
#endif
@@ -190,6 +179,7 @@ static struct irq_chip plic_edge_chip = {
190179
.irq_set_affinity = plic_set_affinity,
191180
#endif
192181
.irq_set_type = plic_irq_set_type,
182+
.flags = IRQCHIP_AFFINITY_PRE_STARTUP,
193183
};
194184

195185
static struct irq_chip plic_chip = {
@@ -201,6 +191,7 @@ static struct irq_chip plic_chip = {
201191
.irq_set_affinity = plic_set_affinity,
202192
#endif
203193
.irq_set_type = plic_irq_set_type,
194+
.flags = IRQCHIP_AFFINITY_PRE_STARTUP,
204195
};
205196

206197
static int plic_irq_set_type(struct irq_data *d, unsigned int type)

0 commit comments

Comments
 (0)