[PATCH RFC 2/3] genirq: Honor existing IRQ affinities when setting affinity hints

From: Florian Bezdeka

Date: Wed Aug 19 2026 - 10:32:17 EST


Some device drivers implement an IRQ balancing / spreading mechanism
based on cpumask_local_spread() and irq_set_affinity_hint() (deprecated)
or irq_set_affinity_and_hint().

__irq_apply_affinity_hint() was overwriting already configured
affinities and with that violating user defined affinities.

This was especially a problem on systems with isolated CPUs, a common
pattern on PREEMPT_RT enabled systems. Device IRQs were balanced over
CPUs that were isolated for RT workloads.

Note that only the first call of irq_set_affinity_hint() and
irq_set_affinity_and_hint() - for each IRQ - will have any effect.
Afterward affinities might be controlled from userspace using the
/proc/irq/<n>/smp_affinity{_list} interface.

Signed-off-by: Florian Bezdeka <florian.bezdeka@xxxxxxxxxxx>
---
kernel/irq/manage.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 7eb07e3bdb4c2419e0a58a75c29d88b4b00b8287..3937ba24df6d63375dda88164cf92fd49e70a3eb 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -503,11 +503,21 @@ EXPORT_SYMBOL_GPL(irq_force_affinity);

int __irq_apply_affinity_hint(unsigned int irq, const struct cpumask *m, bool setaffinity)
{
+ struct irq_data *irq_data;
int ret = -EINVAL;

scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
scoped_irqdesc->affinity_hint = m;
+ irq_data = irq_desc_get_irq_data(scoped_irqdesc);
ret = 0;
+
+ /*
+ * Do not overwrite the affinity in case an affinity for this
+ * IRQ has already been requested, e.g. by writing to
+ * /proc/irq/<n>/smp_affinity
+ */
+ if (irqd_affinity_was_set(irq_data))
+ setaffinity = false;
}

if (!ret && m && setaffinity)

--
2.55.0