* [PATCH net-next 0/5] net/mlx5e: improve RSS indirection table sizing and resizing
@ 2026-05-11 17:27 Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 1/5] net/mlx5e: remove channel count limit for XOR8 RSS hash Tariq Toukan
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Tariq Toukan @ 2026-05-11 17:27 UTC (permalink / raw)
To: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn,
David S. Miller
Cc: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Nimrod Oren, Yael Chemla, Carolina Jubran, Simon Horman,
Gal Pressman, Kees Cook, Dragos Tatulea, netdev, linux-rdma,
linux-kernel
Hi,
This series by Yael improves mlx5e RSS indirection table handling around
channel count changes and large RSS configurations.
The series:
* removes the XOR8-specific channel count limitation,
* advertises the maximum supported RSS indirection table size,
* fixes resizing of non-default RSS contexts,
* allows resizing configured default RSS contexts during channel
changes,
* and increases the default RSS spread factor from 2x to 4x to improve
traffic distribution for large channel counts.
Together, these changes make RSS table sizing more flexible and robust,
while improving load balancing behavior on large systems.
Thanks,
Tariq
Yael Chemla (5):
net/mlx5e: remove channel count limit for XOR8 RSS hash
net/mlx5e: advertise max RSS indirection table size to ethtool
net/mlx5e: resize non-default RSS indirection tables on channel change
net/mlx5e: resize configured default RSS context table on channel
change
net/mlx5e: increase RSS indirection table spread factor
.../net/ethernet/mellanox/mlx5/core/en/rqt.c | 9 --
.../net/ethernet/mellanox/mlx5/core/en/rqt.h | 2 +-
.../net/ethernet/mellanox/mlx5/core/en/rss.c | 29 ++++-
.../net/ethernet/mellanox/mlx5/core/en/rss.h | 6 +-
.../ethernet/mellanox/mlx5/core/en/rx_res.c | 40 +++++--
.../ethernet/mellanox/mlx5/core/en/rx_res.h | 4 +-
.../ethernet/mellanox/mlx5/core/en_ethtool.c | 106 ++++++++----------
.../net/ethernet/mellanox/mlx5/core/en_main.c | 9 +-
8 files changed, 112 insertions(+), 93 deletions(-)
base-commit: 63751099502d10f0aa6bb35273e56c5800cc4e3a
--
2.44.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net-next 1/5] net/mlx5e: remove channel count limit for XOR8 RSS hash
2026-05-11 17:27 [PATCH net-next 0/5] net/mlx5e: improve RSS indirection table sizing and resizing Tariq Toukan
@ 2026-05-11 17:27 ` Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 2/5] net/mlx5e: advertise max RSS indirection table size to ethtool Tariq Toukan
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Tariq Toukan @ 2026-05-11 17:27 UTC (permalink / raw)
To: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn,
David S. Miller
Cc: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Nimrod Oren, Yael Chemla, Carolina Jubran, Simon Horman,
Gal Pressman, Kees Cook, Dragos Tatulea, netdev, linux-rdma,
linux-kernel
From: Yael Chemla <ychemla@nvidia.com>
mlx5e_ethtool_set_channels() and mlx5e_rxfh_hfunc_check() rejected
channel counts that would produce an indirection table larger than 256
entries when the XOR8 hash function was active. This check was
introduced in commit 49e6c9387051 ("net/mlx5e: RSS, Block XOR hash
with over 128 channels").
XOR8 yields an 8-bit hash, so in practice only up to 256 entries in the
indirection table can be reached due to limited entropy. However, this
does not provide a strong justification for prohibiting larger
indirection tables. Remove the limitation.
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
.../net/ethernet/mellanox/mlx5/core/en/rqt.c | 7 ---
.../net/ethernet/mellanox/mlx5/core/en/rqt.h | 1 -
.../ethernet/mellanox/mlx5/core/en_ethtool.c | 48 -------------------
3 files changed, 56 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
index 8d9a3b5ec973..bcafb4bf9415 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
@@ -179,13 +179,6 @@ u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels)
return min_t(u32, rqt_size, max_cap_rqt_size);
}
-#define MLX5E_MAX_RQT_SIZE_ALLOWED_WITH_XOR8_HASH 256
-
-unsigned int mlx5e_rqt_max_num_channels_allowed_for_xor8(void)
-{
- return MLX5E_MAX_RQT_SIZE_ALLOWED_WITH_XOR8_HASH / MLX5E_UNIFORM_SPREAD_RQT_FACTOR;
-}
-
void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt)
{
mlx5_core_destroy_rqt(rqt->mdev, rqt->rqtn);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
index 2f9e04a8418f..e0bc30308c77 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
@@ -38,7 +38,6 @@ static inline u32 mlx5e_rqt_get_rqtn(struct mlx5e_rqt *rqt)
}
u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels);
-unsigned int mlx5e_rqt_max_num_channels_allowed_for_xor8(void);
int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn, u32 *vhca_id);
int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, u32 *vhca_ids,
unsigned int num_rqns,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index bb61e2179078..a6da0219723c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -511,17 +511,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
mutex_lock(&priv->state_lock);
- if (mlx5e_rx_res_get_current_hash(priv->rx_res).hfunc == ETH_RSS_HASH_XOR) {
- unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8();
-
- if (count > xor8_max_channels) {
- err = -EINVAL;
- netdev_err(priv->netdev, "%s: Requested number of channels (%d) exceeds the maximum allowed by the XOR8 RSS hfunc (%d)\n",
- __func__, count, xor8_max_channels);
- goto out;
- }
- }
-
/* If RXFH is configured, changing the channels number is allowed only if
* it does not require resizing the RSS table. This is because the previous
* configuration may no longer be compatible with the new RSS table.
@@ -1501,29 +1490,6 @@ static int mlx5e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *
return 0;
}
-static int mlx5e_rxfh_hfunc_check(struct mlx5e_priv *priv,
- const struct ethtool_rxfh_param *rxfh,
- struct netlink_ext_ack *extack)
-{
- unsigned int count;
-
- count = priv->channels.params.num_channels;
-
- if (rxfh->hfunc == ETH_RSS_HASH_XOR) {
- unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8();
-
- if (count > xor8_max_channels) {
- NL_SET_ERR_MSG_FMT_MOD(
- extack,
- "Number of channels (%u) exceeds the max for XOR8 RSS (%u)",
- count, xor8_max_channels);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
static int mlx5e_set_rxfh(struct net_device *dev,
struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
@@ -1535,16 +1501,11 @@ static int mlx5e_set_rxfh(struct net_device *dev,
mutex_lock(&priv->state_lock);
- err = mlx5e_rxfh_hfunc_check(priv, rxfh, extack);
- if (err)
- goto unlock;
-
err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
rxfh->indir, rxfh->key,
hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);
-unlock:
mutex_unlock(&priv->state_lock);
return err;
}
@@ -1561,10 +1522,6 @@ static int mlx5e_create_rxfh_context(struct net_device *dev,
mutex_lock(&priv->state_lock);
- err = mlx5e_rxfh_hfunc_check(priv, rxfh, extack);
- if (err)
- goto unlock;
-
err = mlx5e_rx_res_rss_init(priv->rx_res, rxfh->rss_context,
priv->channels.params.num_channels);
if (err)
@@ -1601,16 +1558,11 @@ static int mlx5e_modify_rxfh_context(struct net_device *dev,
mutex_lock(&priv->state_lock);
- err = mlx5e_rxfh_hfunc_check(priv, rxfh, extack);
- if (err)
- goto unlock;
-
err = mlx5e_rx_res_rss_set_rxfh(priv->rx_res, rxfh->rss_context,
rxfh->indir, rxfh->key,
hfunc == ETH_RSS_HASH_NO_CHANGE ? NULL : &hfunc,
rxfh->input_xfrm == RXH_XFRM_NO_CHANGE ? NULL : &symmetric);
-unlock:
mutex_unlock(&priv->state_lock);
return err;
}
--
2.44.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next 2/5] net/mlx5e: advertise max RSS indirection table size to ethtool
2026-05-11 17:27 [PATCH net-next 0/5] net/mlx5e: improve RSS indirection table sizing and resizing Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 1/5] net/mlx5e: remove channel count limit for XOR8 RSS hash Tariq Toukan
@ 2026-05-11 17:27 ` Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 3/5] net/mlx5e: resize non-default RSS indirection tables on channel change Tariq Toukan
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Tariq Toukan @ 2026-05-11 17:27 UTC (permalink / raw)
To: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn,
David S. Miller
Cc: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Nimrod Oren, Yael Chemla, Carolina Jubran, Simon Horman,
Gal Pressman, Kees Cook, Dragos Tatulea, netdev, linux-rdma,
linux-kernel
From: Yael Chemla <ychemla@nvidia.com>
Set rxfh_indir_space to the maximum indirection table size the driver
can support: the next power of two above MLX5E_MAX_NUM_CHANNELS times
MLX5E_UNIFORM_SPREAD_RQT_FACTOR.
Without this, ethtool_rxfh_ctxs_can_resize() returns -EINVAL, blocking
non-default RSS contexts from tracking indirection table size changes
when the channel count changes.
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c | 2 --
drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h | 1 +
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 5 +++++
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
index bcafb4bf9415..a3382f6a6b74 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c
@@ -168,8 +168,6 @@ int mlx5e_rqt_init_indir(struct mlx5e_rqt *rqt, struct mlx5_core_dev *mdev,
return err;
}
-#define MLX5E_UNIFORM_SPREAD_RQT_FACTOR 2
-
u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels)
{
u32 rqt_size = max_t(u32, MLX5E_INDIR_MIN_RQT_SIZE,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
index e0bc30308c77..680700e7437f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#define MLX5E_INDIR_MIN_RQT_SIZE (BIT(8))
+#define MLX5E_UNIFORM_SPREAD_RQT_FACTOR 2
struct mlx5_core_dev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index a6da0219723c..c483008e33e9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -45,6 +45,10 @@
#define LANES_UNKNOWN 0
+#define MLX5E_MAX_INDIR_RQT_SIZE \
+ roundup_pow_of_two(MLX5E_MAX_NUM_CHANNELS * \
+ MLX5E_UNIFORM_SPREAD_RQT_FACTOR)
+
void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
struct ethtool_drvinfo *drvinfo)
{
@@ -2692,6 +2696,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
.supported_input_xfrm = RXH_XFRM_SYM_OR_XOR,
.supported_ring_params = ETHTOOL_RING_USE_TCP_DATA_SPLIT |
ETHTOOL_RING_USE_HDS_THRS,
+ .rxfh_indir_space = MLX5E_MAX_INDIR_RQT_SIZE,
.get_drvinfo = mlx5e_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_link_ext_state = mlx5e_get_link_ext_state,
--
2.44.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next 3/5] net/mlx5e: resize non-default RSS indirection tables on channel change
2026-05-11 17:27 [PATCH net-next 0/5] net/mlx5e: improve RSS indirection table sizing and resizing Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 1/5] net/mlx5e: remove channel count limit for XOR8 RSS hash Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 2/5] net/mlx5e: advertise max RSS indirection table size to ethtool Tariq Toukan
@ 2026-05-11 17:27 ` Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 4/5] net/mlx5e: resize configured default RSS context table " Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 5/5] net/mlx5e: increase RSS indirection table spread factor Tariq Toukan
4 siblings, 0 replies; 6+ messages in thread
From: Tariq Toukan @ 2026-05-11 17:27 UTC (permalink / raw)
To: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn,
David S. Miller
Cc: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Nimrod Oren, Yael Chemla, Carolina Jubran, Simon Horman,
Gal Pressman, Kees Cook, Dragos Tatulea, netdev, linux-rdma,
linux-kernel
From: Yael Chemla <ychemla@nvidia.com>
When the channel count changes and the RQT size changes with it, a
problem arise for non-default RSS contexts. The driver-side indirection
table grows actual_table_size without filling the new entries; stale
entries from a prior larger configuration may be re-exposed, causing
mlx5e_calc_indir_rqns() to WARN on an out-of-range index.
Replace mlx5e_rss_params_indir_modify_actual_size() with
mlx5e_rss_ctx_resize(), which fills new entries by replicating
the existing pattern, matching what ethtool_rxfh_ctxs_resize() does
for the same case. And restrict the loop to non-default contexts.
Call ethtool_rxfh_ctxs_can_resize() before acquiring state_lock to
validate that all non-default contexts can be resized, and
ethtool_rxfh_ctxs_resize() after releasing it to fold or unfold their
indirection tables. Both functions acquire rss_lock internally and
cannot be called under state_lock. RTNL, held by all set_channels
callers, serialises context creation and deletion making the pre-lock
check safe.
Guard both ethtool calls on mlx5e_rx_res_rss_cnt() > 1: skip the
validation and resize when no non-default contexts exist. This
naturally covers representors and IPoIB, which share
mlx5e_ethtool_set_channels() but cannot have non-default RSS contexts.
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
| 16 +++++++--
| 3 +-
.../ethernet/mellanox/mlx5/core/en/rx_res.c | 15 ++++++--
.../ethernet/mellanox/mlx5/core/en_ethtool.c | 35 +++++++++++++++++--
4 files changed, 60 insertions(+), 9 deletions(-)
--git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
index a2ec67a122d9..992a78580a40 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
@@ -85,9 +85,21 @@ bool mlx5e_rss_get_inner_ft_support(struct mlx5e_rss *rss)
return rss->params.inner_ft_support;
}
-void mlx5e_rss_params_indir_modify_actual_size(struct mlx5e_rss *rss, u32 num_channels)
+void mlx5e_rss_set_indir_actual_size(struct mlx5e_rss *rss, u32 size)
{
- rss->indir.actual_table_size = mlx5e_rqt_size(rss->mdev, num_channels);
+ rss->indir.actual_table_size = size;
+}
+
+/* Handles non-default contexts, replicate existing pattern into new entries,
+ * matching what ethtool_rxfh_ctxs_resize() does.
+ */
+void mlx5e_rss_ctx_resize(struct mlx5e_rss *rss, u32 new_size)
+{
+ u32 old_size = rss->indir.actual_table_size;
+ u32 i;
+
+ for (i = old_size; i < new_size; i++)
+ rss->indir.table[i] = rss->indir.table[i % old_size];
}
int mlx5e_rss_params_indir_init(struct mlx5e_rss_params_indir *indir,
--git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
index 17664757a561..e48070e02979 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
@@ -34,7 +34,7 @@ struct mlx5e_rss;
int mlx5e_rss_params_indir_init(struct mlx5e_rss_params_indir *indir,
u32 actual_table_size, u32 max_table_size);
void mlx5e_rss_params_indir_cleanup(struct mlx5e_rss_params_indir *indir);
-void mlx5e_rss_params_indir_modify_actual_size(struct mlx5e_rss *rss, u32 num_channels);
+void mlx5e_rss_ctx_resize(struct mlx5e_rss *rss, u32 new_size);
struct mlx5e_rss *
mlx5e_rss_init(struct mlx5_core_dev *mdev,
const struct mlx5e_rss_params *params,
@@ -46,6 +46,7 @@ void mlx5e_rss_refcnt_dec(struct mlx5e_rss *rss);
unsigned int mlx5e_rss_refcnt_read(struct mlx5e_rss *rss);
bool mlx5e_rss_get_inner_ft_support(struct mlx5e_rss *rss);
+void mlx5e_rss_set_indir_actual_size(struct mlx5e_rss *rss, u32 size);
u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
bool inner);
bool mlx5e_rss_valid_tir(struct mlx5e_rss *rss, enum mlx5_traffic_types tt, bool inner);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
index 92974b11ec75..d81a91eb7664 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
@@ -42,11 +42,20 @@ static u32 *get_vhca_ids(struct mlx5e_rx_res *res, int offset)
void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch)
{
+ u32 new_size = mlx5e_rqt_size(res->mdev, nch);
int i;
- for (i = 0; i < MLX5E_MAX_NUM_RSS; i++) {
- if (res->rss[i])
- mlx5e_rss_params_indir_modify_actual_size(res->rss[i], nch);
+ WARN_ON_ONCE(res->rss_active);
+
+ /* Default context */
+ mlx5e_rss_set_indir_actual_size(res->rss[0], new_size);
+
+ /* Non-default contexts */
+ for (i = 1; i < MLX5E_MAX_NUM_RSS; i++) {
+ if (res->rss[i]) {
+ mlx5e_rss_ctx_resize(res->rss[i], new_size);
+ mlx5e_rss_set_indir_actual_size(res->rss[i], new_size);
+ }
}
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index c483008e33e9..4462cf29e977 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -499,11 +499,15 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
{
struct mlx5e_params *cur_params = &priv->channels.params;
unsigned int count = ch->combined_count;
+ int new_rqt_size, cur_rqt_size;
struct mlx5e_params new_params;
bool arfs_enabled;
+ bool has_rss_ctxs;
bool opened;
int err = 0;
+ ASSERT_RTNL();
+
if (!count) {
netdev_info(priv->netdev, "%s: combined_count=0 not supported\n",
__func__);
@@ -513,16 +517,33 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
if (cur_params->num_channels == count)
return 0;
+ new_rqt_size = mlx5e_rqt_size(priv->mdev, count);
+ /* Validate that all non-default RSS contexts can be resized before
+ * committing to the channel count change.
+ * ethtool_rxfh_ctxs_can_resize() acquires rss_lock internally and
+ * cannot be called under state_lock (rss_lock -> state_lock ordering).
+ */
+ has_rss_ctxs = priv->rx_res && mlx5e_rx_res_rss_cnt(priv->rx_res) > 1;
+ if (has_rss_ctxs) {
+ err = ethtool_rxfh_ctxs_can_resize(priv->netdev, new_rqt_size);
+ if (err)
+ return err;
+ }
+
mutex_lock(&priv->state_lock);
+ if (!priv->rx_res) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels);
+
/* If RXFH is configured, changing the channels number is allowed only if
* it does not require resizing the RSS table. This is because the previous
* configuration may no longer be compatible with the new RSS table.
*/
if (netif_is_rxfh_configured(priv->netdev)) {
- int cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels);
- int new_rqt_size = mlx5e_rqt_size(priv->mdev, count);
-
if (new_rqt_size != cur_rqt_size) {
err = -EINVAL;
netdev_err(priv->netdev,
@@ -577,6 +598,14 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
out:
mutex_unlock(&priv->state_lock);
+ /* After a successful channel count change that altered the RQT size,
+ * fold or unfold the indirection tables of all non-default RSS
+ * contexts. Must run after state_lock is released because
+ * ethtool_rxfh_ctxs_resize() acquires rss_lock internally.
+ */
+ if (!err && cur_rqt_size != new_rqt_size && has_rss_ctxs)
+ ethtool_rxfh_ctxs_resize(priv->netdev, new_rqt_size);
+
return err;
}
--
2.44.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next 4/5] net/mlx5e: resize configured default RSS context table on channel change
2026-05-11 17:27 [PATCH net-next 0/5] net/mlx5e: improve RSS indirection table sizing and resizing Tariq Toukan
` (2 preceding siblings ...)
2026-05-11 17:27 ` [PATCH net-next 3/5] net/mlx5e: resize non-default RSS indirection tables on channel change Tariq Toukan
@ 2026-05-11 17:27 ` Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 5/5] net/mlx5e: increase RSS indirection table spread factor Tariq Toukan
4 siblings, 0 replies; 6+ messages in thread
From: Tariq Toukan @ 2026-05-11 17:27 UTC (permalink / raw)
To: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn,
David S. Miller
Cc: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Nimrod Oren, Yael Chemla, Carolina Jubran, Simon Horman,
Gal Pressman, Kees Cook, Dragos Tatulea, netdev, linux-rdma,
linux-kernel
From: Yael Chemla <ychemla@nvidia.com>
mlx5e_ethtool_set_channels() rejected channel count changes that
required a different RQT size when the default context indirection
table was user-configured. This restriction was introduced by
commit ee3572409f74 ("net/mlx5e: RSS, Block changing channels number
when RXFH is configured").
Lift the restriction. Validate the resize upfront with
ethtool_rxfh_indir_can_resize(), then fold or unfold the table
in-place via ethtool_rxfh_indir_resize() inside state_lock, before
mlx5e_safe_switch_params(), so the preactivate callback sees the
correct table content when it programs the HW.
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
| 13 +++++++++
| 3 +++
.../ethernet/mellanox/mlx5/core/en/rx_res.c | 27 ++++++++++++-------
.../ethernet/mellanox/mlx5/core/en/rx_res.h | 4 +--
.../ethernet/mellanox/mlx5/core/en_ethtool.c | 22 +++++++--------
.../net/ethernet/mellanox/mlx5/core/en_main.c | 9 +++----
6 files changed, 49 insertions(+), 29 deletions(-)
--git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
index 992a78580a40..de435df7ca50 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
// Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES.
+#include <linux/ethtool.h>
#include "rss.h"
#define mlx5e_rss_warn(__dev, format, ...) \
@@ -85,6 +86,11 @@ bool mlx5e_rss_get_inner_ft_support(struct mlx5e_rss *rss)
return rss->params.inner_ft_support;
}
+u32 *mlx5e_rss_get_indir_table(struct mlx5e_rss *rss)
+{
+ return rss->indir.table;
+}
+
void mlx5e_rss_set_indir_actual_size(struct mlx5e_rss *rss, u32 size)
{
rss->indir.actual_table_size = size;
@@ -102,6 +108,13 @@ void mlx5e_rss_ctx_resize(struct mlx5e_rss *rss, u32 new_size)
rss->indir.table[i] = rss->indir.table[i % old_size];
}
+void mlx5e_rss_indir_resize(struct mlx5e_rss *rss, struct net_device *netdev,
+ u32 new_size)
+{
+ ethtool_rxfh_indir_resize(netdev, rss->indir.table,
+ rss->indir.actual_table_size, new_size);
+}
+
int mlx5e_rss_params_indir_init(struct mlx5e_rss_params_indir *indir,
u32 actual_table_size, u32 max_table_size)
{
--git a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
index e48070e02979..1bb0434612a4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rss.h
@@ -35,6 +35,8 @@ int mlx5e_rss_params_indir_init(struct mlx5e_rss_params_indir *indir,
u32 actual_table_size, u32 max_table_size);
void mlx5e_rss_params_indir_cleanup(struct mlx5e_rss_params_indir *indir);
void mlx5e_rss_ctx_resize(struct mlx5e_rss *rss, u32 new_size);
+void mlx5e_rss_indir_resize(struct mlx5e_rss *rss, struct net_device *netdev,
+ u32 new_size);
struct mlx5e_rss *
mlx5e_rss_init(struct mlx5_core_dev *mdev,
const struct mlx5e_rss_params *params,
@@ -46,6 +48,7 @@ void mlx5e_rss_refcnt_dec(struct mlx5e_rss *rss);
unsigned int mlx5e_rss_refcnt_read(struct mlx5e_rss *rss);
bool mlx5e_rss_get_inner_ft_support(struct mlx5e_rss *rss);
+u32 *mlx5e_rss_get_indir_table(struct mlx5e_rss *rss);
void mlx5e_rss_set_indir_actual_size(struct mlx5e_rss *rss, u32 size);
u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
bool inner);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
index d81a91eb7664..e940635f5dcb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.c
@@ -40,15 +40,31 @@ static u32 *get_vhca_ids(struct mlx5e_rx_res *res, int offset)
return multi_vhca ? res->rss_vhca_ids + offset : NULL;
}
-void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch)
+/* Updates the indirection table SW shadow, does not update the HW resources yet
+ */
+void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch,
+ struct net_device *netdev)
{
u32 new_size = mlx5e_rqt_size(res->mdev, nch);
int i;
WARN_ON_ONCE(res->rss_active);
- /* Default context */
+ /* Default context: fold/unfold user-configured table, then update size
+ * and reset to uniform when unconfigured.
+ */
+ mlx5e_rss_indir_resize(res->rss[0], netdev, new_size);
+
+ /* mlx5e_rss_indir_resize() is a no-op when the table is not
+ * user-configured. actual_table_size is updated after the resize
+ * because ethtool_rxfh_indir_resize() uses it as the old size to
+ * replicate the pattern; updating it first would make the grow a no-op.
+ * It must be updated before mlx5e_rss_set_indir_uniform() so that
+ * the uniform fill covers all new entries, not just the old ones.
+ */
mlx5e_rss_set_indir_actual_size(res->rss[0], new_size);
+ if (!netif_is_rxfh_configured(netdev))
+ mlx5e_rss_set_indir_uniform(res->rss[0], nch);
/* Non-default contexts */
for (i = 1; i < MLX5E_MAX_NUM_RSS; i++) {
@@ -218,13 +234,6 @@ static void mlx5e_rx_res_rss_disable(struct mlx5e_rx_res *res)
}
}
-/* Updates the indirection table SW shadow, does not update the HW resources yet */
-void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch)
-{
- WARN_ON_ONCE(res->rss_active);
- mlx5e_rss_set_indir_uniform(res->rss[0], nch);
-}
-
void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
u32 *indir, u8 *key, u8 *hfunc, bool *symmetric)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h
index 675780120a20..8fff18d64978 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rx_res.h
@@ -48,7 +48,6 @@ void mlx5e_rx_res_xsk_update(struct mlx5e_rx_res *res, struct mlx5e_channels *ch
unsigned int ix, bool xsk);
/* Configuration API */
-void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch);
void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 rss_idx,
u32 *indir, u8 *key, u8 *hfunc,
bool *symmetric);
@@ -68,7 +67,8 @@ int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx);
int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res);
int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss);
struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx);
-void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch);
+void mlx5e_rx_res_rss_update_num_channels(struct mlx5e_rx_res *res, u32 nch,
+ struct net_device *netdev);
/* Workaround for hairpin */
struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 4462cf29e977..300d1cb2e070 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -501,6 +501,7 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
unsigned int count = ch->combined_count;
int new_rqt_size, cur_rqt_size;
struct mlx5e_params new_params;
+ struct mlx5e_rss *rss0;
bool arfs_enabled;
bool has_rss_ctxs;
bool opened;
@@ -538,19 +539,16 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
}
cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels);
+ rss0 = mlx5e_rx_res_rss_get(priv->rx_res, 0);
- /* If RXFH is configured, changing the channels number is allowed only if
- * it does not require resizing the RSS table. This is because the previous
- * configuration may no longer be compatible with the new RSS table.
- */
- if (netif_is_rxfh_configured(priv->netdev)) {
- if (new_rqt_size != cur_rqt_size) {
- err = -EINVAL;
- netdev_err(priv->netdev,
- "%s: RXFH is configured, block changing channels number that affects RSS table size (new: %d, current: %d)\n",
- __func__, new_rqt_size, cur_rqt_size);
- goto out;
- }
+ if (!ethtool_rxfh_indir_can_resize(priv->netdev,
+ mlx5e_rss_get_indir_table(rss0),
+ cur_rqt_size, new_rqt_size)) {
+ netdev_err(priv->netdev,
+ "%s: cannot resize RSS table (%u -> %u); reset indirection table to allow this change\n",
+ __func__, cur_rqt_size, new_rqt_size);
+ err = -EINVAL;
+ goto out;
}
/* Don't allow changing the number of channels if HTB offload is active,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 85b1ccbd351f..a904e468c197 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3296,12 +3296,9 @@ static int mlx5e_num_channels_changed(struct mlx5e_priv *priv)
}
/* This function may be called on attach, before priv->rx_res is created. */
- if (priv->rx_res) {
- mlx5e_rx_res_rss_update_num_channels(priv->rx_res, count);
-
- if (!netif_is_rxfh_configured(priv->netdev))
- mlx5e_rx_res_rss_set_indir_uniform(priv->rx_res, count);
- }
+ if (priv->rx_res)
+ mlx5e_rx_res_rss_update_num_channels(priv->rx_res, count,
+ netdev);
return 0;
}
--
2.44.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net-next 5/5] net/mlx5e: increase RSS indirection table spread factor
2026-05-11 17:27 [PATCH net-next 0/5] net/mlx5e: improve RSS indirection table sizing and resizing Tariq Toukan
` (3 preceding siblings ...)
2026-05-11 17:27 ` [PATCH net-next 4/5] net/mlx5e: resize configured default RSS context table " Tariq Toukan
@ 2026-05-11 17:27 ` Tariq Toukan
4 siblings, 0 replies; 6+ messages in thread
From: Tariq Toukan @ 2026-05-11 17:27 UTC (permalink / raw)
To: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn,
David S. Miller
Cc: Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Mark Bloch,
Nimrod Oren, Yael Chemla, Carolina Jubran, Simon Horman,
Gal Pressman, Kees Cook, Dragos Tatulea, netdev, linux-rdma,
linux-kernel
From: Yael Chemla <ychemla@nvidia.com>
Increase the RQT uniform spread factor from 2 to 4 so that each channel
gets more indirection table entries and traffic is spread more evenly.
For num_channels > 64 imbalance drops from up to ~50% to up to ~25%.
For 64 or fewer channels the 256 entry minimum already provides at least
4x coverage and the table size is unchanged by this commit.
This satisfies the minimum 4x coverage requirement validated by the
generic RSS selftest commit 9e3d4dae9832 ("selftests: drv-net: rss:
validate min RSS table size").
The 4x spread factor is best-effort and the table size is always capped by
the device's log_max_rqt_size capability.
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Nimrod Oren <noren@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
index 680700e7437f..c6d0a92b132c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h
@@ -7,7 +7,7 @@
#include <linux/kernel.h>
#define MLX5E_INDIR_MIN_RQT_SIZE (BIT(8))
-#define MLX5E_UNIFORM_SPREAD_RQT_FACTOR 2
+#define MLX5E_UNIFORM_SPREAD_RQT_FACTOR 4
struct mlx5_core_dev;
--
2.44.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-05-11 17:28 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-11 17:27 [PATCH net-next 0/5] net/mlx5e: improve RSS indirection table sizing and resizing Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 1/5] net/mlx5e: remove channel count limit for XOR8 RSS hash Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 2/5] net/mlx5e: advertise max RSS indirection table size to ethtool Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 3/5] net/mlx5e: resize non-default RSS indirection tables on channel change Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 4/5] net/mlx5e: resize configured default RSS context table " Tariq Toukan
2026-05-11 17:27 ` [PATCH net-next 5/5] net/mlx5e: increase RSS indirection table spread factor Tariq Toukan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox