Re: [PATCH RFC 1/3] cpumask: Honor irq_default_affinity in cpumask_local_spread()

Yury Norov <[email protected]>
Newsgroups dev.linux.lists.linux-rt-devel,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <aoX4HuUxL4tNWvpq@yury>
On Wed, Aug 19, 2026 at 04:30:30PM +0200, Florian Bezdeka wrote:
> Many drivers call cpumask_local_spread() to spread IRQs to several
> CPUs, mainly to get best performance and balance CPU load. For
> realtime (PREEMPT_RT) and other cpu-isolating workloads the old
> implementation was triggering an IRQ placement problem. IRQs were
> targeting CPUs that were isolated for those sensitive workloads.
> 
> Userland will tell the kernel about the desired IRQ configuration
> for new interrupts by writing a proper cpumask to
> /proc/irq/default_smp_affinity. This cpu mask has to be honored to
> avoid IRQ noise on isolated cores.
> 
> The default for irq_default_affinity is "all CPUs". So all CPUs will
> be taken into account for spreading when userland did not configure
> something special.
> ---
>  lib/cpumask.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/lib/cpumask.c b/lib/cpumask.c
> index 5adb9874fbd0f5a42ea8cd9e6c3729a70599781f..73e7b60a9201174f83df6067effbe7d1889dcdb9 100644
> --- a/lib/cpumask.c
> +++ b/lib/cpumask.c
> @@ -6,6 +6,7 @@
>  #include <linux/export.h>
>  #include <linux/memblock.h>
>  #include <linux/numa.h>
> +#include <linux/interrupt.h>
>  
>  /* These are not inline because of header tangles. */
>  #ifdef CONFIG_CPUMASK_OFFSTACK
> @@ -81,8 +82,9 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask)
>   * @i: index number
>   * @node: local numa_node
>   *
> - * Return: online CPU according to a numa aware policy; local cpus are returned
> - * first, followed by non-local ones, then it wraps around.
> + * Return: online CPU according to the default IRQ affinity and a numa aware
> + * policy; local cpus are returned first, followed by non-local ones, then it
> + * wraps around.
>   *
>   * For those who wants to enumerate all CPUs based on their NUMA distances,
>   * i.e. call this function in a loop, like:
> @@ -110,9 +112,9 @@ unsigned int cpumask_local_spread(unsigned int i, int node)

Please don't touch this function. There's ~40 users, and we don't want
to inspect every caller for their intention.

Looking at ionic_get_preferred_cpu(), the cpumask_local_spread() is
used there as a fallback for the affinity IRQ search:

 static int ionic_get_preferred_cpu(struct ionic *ionic,
                                    struct ionic_intr_info *intr)
 {
         int cpu;
 
         cpu = cpumask_first_and(*intr->affinity_mask, cpu_online_mask);
         if (cpu >= nr_cpu_ids)
                 cpu = cpumask_local_spread(0, dev_to_node(ionic->dev));
 
         return cpu;
 }

Your change may affect the logic, seemingly.

Instead, please create something like:

        unsigned int cpumask_spread(struct cpumask cpus,
                                    unsigned int i, int node);

Thanks,
Yury

>  	unsigned int cpu;
>  
>  	/* Wrap: we always want a cpu. */
> -	i %= num_online_cpus();
> +	i %= cpumask_weight(irq_default_affinity);
>  
> -	cpu = sched_numa_find_nth_cpu(cpu_online_mask, i, node);
> +	cpu = sched_numa_find_nth_cpu(irq_default_affinity, i, node);
>  
>  	WARN_ON(cpu >= nr_cpu_ids);
>  	return cpu;
> 
> -- 
> 2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.