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//smp_affinity{_list} interface. Signed-off-by: Florian Bezdeka --- 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//smp_affinity + */ + if (irqd_affinity_was_set(irq_data)) + setaffinity = false; } if (!ret && m && setaffinity) -- 2.55.0