[PATCH net-next v6 11/13] net: mana: keep a user-configured RSS table across a queue rebuild
flat view
HOTtoday
From: Wei Hu <hidden>
Date: 2026-10-09 14:41:56
Also in:
bpf, linux-hyperv, linux-rdma, lkml
Subsystem:
hyper-v/azure core and drivers, networking drivers, networking [general], the rest · Maintainers:
"K. Y. Srinivasan", Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Long Li <longli@microsoft.com> Preserve a user RSS table whenever all entries fit the requested queue count. Regenerate driver defaults. On growth, a retained user table does not steer RSS traffic to the added queues until the user updates it. Report table loss only after successful queue-set publication. The non-swap allocation path still replaces invalid tables silently because its callers do not consistently hold the notification's netdev lock. Require RTNL for RSS setters to serialize them with reset/resume rebuilds. Signed-off-by: Long Li <longli@microsoft.com> Signed-off-by: Wei Hu <redacted> --- drivers/net/ethernet/microsoft/mana/mana_en.c | 41 +++++++++++++++++-- .../ethernet/microsoft/mana/mana_ethtool.c | 3 +- include/net/mana/mana.h | 2 + 3 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 86a09828b5f4..5619c6a763c2 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c@@ -3595,6 +3595,27 @@ static void mana_rss_table_init(struct mana_port_context *apc) ethtool_rxfh_indir_default(i, apc->num_queues); } +/* Keep user tables with valid indices; defer loss notification. */ +static bool mana_rss_table_keep(struct mana_port_context *apc, + unsigned int num_queues, bool *lost) +{ + u32 i; + + *lost = false; + + if (!netif_is_rxfh_configured(apc->ndev)) + return false; + + for (i = 0; i < apc->indir_table_sz; i++) { + if (apc->indir_table[i] >= num_queues) { + *lost = true; + return false; + } + } + + return true; +} + int mana_disable_vport_rx(struct mana_port_context *apc) { return mana_cfg_vport_steering(apc, TRI_STATE_FALSE, false, false,
@@ -3865,6 +3886,7 @@ int mana_alloc_queues(struct net_device *ndev) { struct mana_port_context *apc = netdev_priv(ndev); struct gdma_dev *gd = apc->ac->gdma_dev; + bool indir_lost; int err; err = mana_create_vport(apc, ndev);
@@ -3910,7 +3932,9 @@ int mana_alloc_queues(struct net_device *ndev) goto destroy_rxq; } - mana_rss_table_init(apc); + /* Loss notification needs a netdev instance lock we may lack. */ + if (!mana_rss_table_keep(apc, apc->num_queues, &indir_lost)) + mana_rss_table_init(apc); err = mana_config_rss(apc, TRI_STATE_TRUE, true, true); if (err) {
@@ -4069,9 +4093,10 @@ static void mana_qset_snapshot(const struct mana_port_context *ctx, out->priv_flags = ctx->priv_flags; out->mtu = ctx->configured_mtu; out->bpf_prog = ctx->bpf_prog; + + out->rxfh_indir_lost = false; } -/* Vport identity and port debugfs outlive queue sets. */ static void mana_qset_install(struct mana_port_context *ctx, const struct mana_qset *qset) {
@@ -4131,6 +4156,7 @@ int mana_alloc_qset(struct mana_port_context *apc, struct mana_qset *out) { struct net_device *ndev = scratch->ndev; + bool indir_lost; int err; ASSERT_RTNL();
@@ -4166,9 +4192,14 @@ int mana_alloc_qset(struct mana_port_context *apc, if (err) goto cleanup_rxq; - mana_rss_table_init(scratch); + if (mana_rss_table_keep(apc, num_queues, &indir_lost)) + memcpy(scratch->indir_table, apc->indir_table, + apc->indir_table_sz * sizeof(*apc->indir_table)); + else + mana_rss_table_init(scratch); mana_qset_snapshot(scratch, out); + out->rxfh_indir_lost = indir_lost; return 0; cleanup_rxq:
@@ -4407,6 +4438,10 @@ int mana_publish_qset(struct mana_port_context *apc, struct mana_qset *newq, WRITE_ONCE(apc->port_is_up, true); mana_start_txqs(apc); + /* Report a lost user table only after successful publication. */ + if (newq->rxfh_indir_lost) + ethtool_rxfh_indir_lost(ndev); + return 0; rollback:
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 611521d2d6d1..a53e19b15bae 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c@@ -953,7 +953,8 @@ const struct ethtool_ops mana_ethtool_ops = { .op_needs_rtnl = ETHTOOL_OP_NEEDS_RTNL_SCHANNELS | ETHTOOL_OP_NEEDS_RTNL_SRINGPARAM | ETHTOOL_OP_NEEDS_RTNL_SPFLAGS | - ETHTOOL_OP_NEEDS_RTNL_GLINK, + ETHTOOL_OP_NEEDS_RTNL_GLINK | + ETHTOOL_OP_NEEDS_RTNL_RSS, .get_ethtool_stats = mana_get_ethtool_stats, .get_sset_count = mana_get_sset_count, .get_strings = mana_get_strings,
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 5f9461bc16e9..9dad03150d1b 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h@@ -709,6 +709,8 @@ struct mana_qset { int mtu; struct bpf_prog *bpf_prog; + /* Notify the core only after this set is published. */ + bool rxfh_indir_lost; }; netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev);