Re: [PATCH RFC 3/3] net: stmmac: Migrate IRQ balancing to 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 <aoX5wglLYYtLcE5J@yury>
On Wed, Aug 19, 2026 at 04:30:32PM +0200, Florian Bezdeka wrote:
> The previous balancing mechanism was based on num_online_cpus(), which
> is a problem for systems cpu-isolating workloads. IRQs were targeting
> CPUs that were isolated for those sensitive workloads.
> 
> With a migration to cpumask_local_spread() we
>     - get NUMA locality
>     - honor the default SMP affinity mask, which avoids targeting
>       isolated CPUs.
> 
> This also aligns with the pattern used by most network drivers dealing
> with IRQ affinities / affinity hints.
> 
> Signed-off-by: Florian Bezdeka <[email protected]>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index a71f0df263785dd8badc45292ca3067ab33bda05..949ced7e46d2814b57c6bd86b4886ac3bf33996c 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -3826,11 +3826,16 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
>  	struct stmmac_priv *priv = netdev_priv(dev);
>  	struct stmmac_msi *msi = priv->msi;
>  	enum request_irq_err irq_err;
> +	cpumask_var_t affinity;
>  	int irq_idx = 0;
>  	char *int_name;
> +	int node;
>  	int ret;
>  	int i;
>  
> +	if (!zalloc_cpumask_var(&affinity, GFP_KERNEL))
> +		return -ENOMEM;
> +
>  	/* For common interrupt */
>  	int_name = msi->int_name_mac;
>  	sprintf(int_name, "%s:%s", dev->name, "mac");
> @@ -3916,6 +3921,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
>  	}
>  
>  	/* Request Rx MSI irq */
> +	node = dev_to_node(&priv->dev->dev);
>  	for (i = 0; i < priv->plat->rx_queues_to_use; i++) {
>  		if (i >= MTL_MAX_RX_QUEUES)
>  			break;
> @@ -3935,8 +3941,10 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
>  			irq_idx = i;
>  			goto irq_error;
>  		}
> -		irq_set_affinity_hint(msi->rx_irq[i],
> -				      cpumask_of(i % num_online_cpus()));
> +
> +		cpumask_clear(affinity);
> +		cpumask_set_cpu(cpumask_local_spread(i, node), affinity);
> +		irq_set_affinity_and_hint(msi->rx_irq[i], affinity);

If you want to spread more than one IRQ, you'd better convert your
loop into for_each_numa_hop_mask(). That way you don't need to
introduce new function. See the comment on top of
cpumask_local_spread():

 * For those who wants to enumerate all CPUs based on their NUMA distances,
 * i.e. call this function in a loop, like:
 *
 * for (i = 0; i < num_online_cpus(); i++) {
 *      cpu = cpumask_local_spread(i, node);
 *      do_something(cpu);
 * }
 *
 * There's a better alternative based on for_each()-like iterators:
 *
 *      for_each_numa_hop_mask(mask, node) {
 *              for_each_cpu_andnot(cpu, mask, prev)
 *                      do_something(cpu);
 *              prev = mask;
 *      }

Thanks,
Yury

>  	}
>  
>  	/* Request Tx MSI irq */
> @@ -3959,13 +3967,18 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)
>  			irq_idx = i;
>  			goto irq_error;
>  		}
> -		irq_set_affinity_hint(msi->tx_irq[i],
> -				      cpumask_of(i % num_online_cpus()));
> +
> +		cpumask_clear(affinity);
> +		cpumask_set_cpu(cpumask_local_spread(i, node), affinity);
> +		irq_set_affinity_and_hint(msi->tx_irq[i], affinity);
>  	}
>  
> +	free_cpumask_var(affinity);
> +
>  	return 0;
>  
>  irq_error:
> +	free_cpumask_var(affinity);
>  	stmmac_free_irq(dev, irq_err, irq_idx);
>  	return ret;
>  }
> 
> -- 
> 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.