Skip to content

Commit 33de0aa

Browse files
Marc ZyngierKAGA-KOKO
authored andcommitted
genirq: Always limit the affinity to online CPUs
When booting with maxcpus=<small number> (or even loading a driver while most CPUs are offline), it is pretty easy to observe managed affinities containing a mix of online and offline CPUs being passed to the irqchip driver. This means that the irqchip cannot trust the affinity passed down from the core code, which is a bit annoying and requires (at least in theory) all drivers to implement some sort of affinity narrowing. In order to address this, always limit the cpumask to the set of online CPUs. Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d802057 commit 33de0aa

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

kernel/irq/manage.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,16 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
222222
{
223223
struct irq_desc *desc = irq_data_to_desc(data);
224224
struct irq_chip *chip = irq_data_get_irq_chip(data);
225+
const struct cpumask *prog_mask;
225226
int ret;
226227

228+
static DEFINE_RAW_SPINLOCK(tmp_mask_lock);
229+
static struct cpumask tmp_mask;
230+
227231
if (!chip || !chip->irq_set_affinity)
228232
return -EINVAL;
229233

234+
raw_spin_lock(&tmp_mask_lock);
230235
/*
231236
* If this is a managed interrupt and housekeeping is enabled on
232237
* it check whether the requested affinity mask intersects with
@@ -248,24 +253,28 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
248253
*/
249254
if (irqd_affinity_is_managed(data) &&
250255
housekeeping_enabled(HK_TYPE_MANAGED_IRQ)) {
251-
const struct cpumask *hk_mask, *prog_mask;
252-
253-
static DEFINE_RAW_SPINLOCK(tmp_mask_lock);
254-
static struct cpumask tmp_mask;
256+
const struct cpumask *hk_mask;
255257

256258
hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ);
257259

258-
raw_spin_lock(&tmp_mask_lock);
259260
cpumask_and(&tmp_mask, mask, hk_mask);
260261
if (!cpumask_intersects(&tmp_mask, cpu_online_mask))
261262
prog_mask = mask;
262263
else
263264
prog_mask = &tmp_mask;
264-
ret = chip->irq_set_affinity(data, prog_mask, force);
265-
raw_spin_unlock(&tmp_mask_lock);
266265
} else {
267-
ret = chip->irq_set_affinity(data, mask, force);
266+
prog_mask = mask;
268267
}
268+
269+
/* Make sure we only provide online CPUs to the irqchip */
270+
cpumask_and(&tmp_mask, prog_mask, cpu_online_mask);
271+
if (!cpumask_empty(&tmp_mask))
272+
ret = chip->irq_set_affinity(data, &tmp_mask, force);
273+
else
274+
ret = -EINVAL;
275+
276+
raw_spin_unlock(&tmp_mask_lock);
277+
269278
switch (ret) {
270279
case IRQ_SET_MASK_OK:
271280
case IRQ_SET_MASK_OK_DONE:

0 commit comments

Comments
 (0)