From: Long Li <longli@microsoft.com>
To: Long Li <longli@microsoft.com>,
Konstantin Taranov <kotaranov@microsoft.com>,
Jakub Kicinski <kuba@kernel.org>,
"David S . Miller" <davem@davemloft.net>,
Paolo Abeni <pabeni@redhat.com>,
Eric Dumazet <edumazet@google.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
Jason Gunthorpe <jgg@ziepe.ca>, Leon Romanovsky <leon@kernel.org>,
Haiyang Zhang <haiyangz@microsoft.com>,
"K . Y . Srinivasan" <kys@microsoft.com>,
Wei Liu <wei.liu@kernel.org>, Dexuan Cui <decui@microsoft.com>,
shradhagupta@linux.microsoft.com, Simon Horman <horms@kernel.org>,
ernis@linux.microsoft.com, stephen@networkplumber.org
Cc: netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH net-next v2 11/13] net: mana: keep a user-configured RSS table across a queue rebuild
Date: Mon, 10 Aug 2026 23:35:28 -0700 [thread overview]
Message-ID: <20260811063530.2428424-3-longli@microsoft.com> (raw)
In-Reply-To: <20260811063530.2428424-1-longli@microsoft.com>
mana_rss_table_init() overwrites the indirection table with the driver
default every time the queues are rebuilt. Both rebuild paths do it:
mana_alloc_qset() for the ethtool/MTU/XDP queue-set swap, and
mana_alloc_queues() for ndo_open and for the TX-timeout reset.
A table the user installed with "ethtool -X" is therefore lost by
operations that have nothing to do with RSS. Resizing the rings, changing
the MTU, toggling a private flag, attaching an XDP program, or simply
taking the port down and up again all silently reset the steering:
# ethtool -X ens1 equal 1 # everything to queue 0
# ethtool -G ens1 rx 1024
# ethtool -x ens1 # back to 0..15, silently
The entries are queue indices, so they stay meaningful as long as the
queue count does not change, and mana_config_rss() already maps them onto
whichever RX objects the new set has. Carry the table over instead of
regenerating it.
Only a user-configured table is preserved, which netif_is_rxfh_configured()
reports: a driver-generated table must still be rebuilt so that it spreads
over all the queues of the new set. ethtool_check_max_channel() refuses a
channel-count reduction that would leave a user table pointing past the
last queue, so the entries are in range by construction; the bounds check
is a safety net for the rebuild paths that do not come from ethtool, and
reports the table as lost rather than steering to a queue that is gone.
Signed-off-by: Long Li <longli@microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 50 ++++++++++++++++++-
1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 0d87440fbfbee7ac5729945d101eaa0c37745fbe..4cab3f658f2487671d26243d4e91f834580b3c5c 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3545,6 +3545,38 @@ static void mana_rss_table_init(struct mana_port_context *apc)
ethtool_rxfh_indir_default(i, apc->num_queues);
}
+/* Decide whether @apc's indirection table can be carried over to a queue set
+ * with @num_queues queues, instead of being rebuilt from the driver default.
+ *
+ * Only a table the user installed with "ethtool -X" is worth preserving: a
+ * driver-generated one has to be rebuilt so that it spreads over all the
+ * queues the new set actually has.
+ *
+ * ethtool_check_max_channel() already refuses a channel-count reduction that
+ * would leave a user-configured table pointing past the last queue, so the
+ * bounds check below is only a safety net for the rebuild paths that do not
+ * originate from ethtool. If it ever trips, the table cannot be honoured for
+ * the new queue count, so tell the core the user's table is gone rather than
+ * silently steering to queues that no longer exist.
+ */
+static bool mana_rss_table_keep(struct mana_port_context *apc,
+ unsigned int num_queues)
+{
+ u32 i;
+
+ 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) {
+ ethtool_rxfh_indir_lost(apc->ndev);
+ 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,
@@ -3860,7 +3892,12 @@ int mana_alloc_queues(struct net_device *ndev)
goto destroy_rxq;
}
- mana_rss_table_init(apc);
+ /* Keep a user-configured RSS table across a rebuild; the entries are
+ * queue indices, so they stay meaningful as long as the queue count
+ * is unchanged. Only a driver-generated table is regenerated here.
+ */
+ if (!mana_rss_table_keep(apc, apc->num_queues))
+ mana_rss_table_init(apc);
err = mana_config_rss(apc, TRI_STATE_TRUE, true, true);
if (err) {
@@ -4317,7 +4354,16 @@ int mana_alloc_qset(struct mana_port_context *apc,
if (err)
goto cleanup_rxq;
- mana_rss_table_init(scratch);
+ /* Carry a user-configured RSS table over to the new set. The entries
+ * are queue indices, so mana_config_rss() in mana_publish_qset() maps
+ * them onto the new set's RX objects. A driver-generated table is
+ * rebuilt instead, so it covers every queue of the new set.
+ */
+ if (mana_rss_table_keep(apc, num_queues))
+ 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);
return 0;
--
2.43.0
next prev parent reply other threads:[~2026-08-11 6:35 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-11 6:35 [PATCH net-next v2 01/13] net: mana: add queue-set allocation and teardown helpers Long Li
2026-08-11 6:35 ` [PATCH net-next v2 10/13] net: mana: release EQs left idle by a channel-count reduction Long Li
2026-08-11 6:35 ` Long Li [this message]
2026-08-11 6:35 ` [PATCH net-next v2 12/13] net: mana: keep the surviving queues when the channel count is reduced Long Li
2026-08-11 6:35 ` [PATCH net-next v2 13/13] net: mana: keep the existing queues when the channel count is raised Long Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260811063530.2428424-3-longli@microsoft.com \
--to=longli@microsoft.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=decui@microsoft.com \
--cc=edumazet@google.com \
--cc=ernis@linux.microsoft.com \
--cc=haiyangz@microsoft.com \
--cc=horms@kernel.org \
--cc=jgg@ziepe.ca \
--cc=kotaranov@microsoft.com \
--cc=kuba@kernel.org \
--cc=kys@microsoft.com \
--cc=leon@kernel.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=shradhagupta@linux.microsoft.com \
--cc=stephen@networkplumber.org \
--cc=wei.liu@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.