All of lore.kernel.org
 help / color / mirror / Atom feed
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 09/13] net: mana: share the EQ pool across a queue-set swap
Date: Wed, 12 Aug 2026 22:04:14 -0700	[thread overview]
Message-ID: <20260813050418.2906468-10-longli@microsoft.com> (raw)
In-Reply-To: <20260813050418.2906468-1-longli@microsoft.com>

Raising the channel count fails with -ENOSPC once the queue-set swap is
in use:

  # ethtool -L ens1 combined 32
  netlink error: No space left on device
  mana 7870:00:00.0: No free MSI vectors available

Building a second set of EQs while the running set still held its own
meant peak demand of old + new MSI-X vectors. With 32 usable vectors and
a driver that comes up at 16 queues, 16 -> 17 already needs 33, so the
advertised maximum is unreachable.

Make the EQ pool belong to the port rather than to a queue set, so both
sets share it and peak usage is max(old, new) rather than the sum. The
pool only ever grows, up to the maximum channel count ethtool reports,
and is released on detach as before.

Signed-off-by: Long Li <longli@microsoft.com>
---
 .../net/ethernet/microsoft/mana/mana_bpf.c    |   2 +-
 drivers/net/ethernet/microsoft/mana/mana_en.c | 173 +++++++++++-------
 .../ethernet/microsoft/mana/mana_ethtool.c    |   6 +-
 include/net/mana/mana.h                       |  34 ++--
 4 files changed, 120 insertions(+), 95 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
index ed9ec6b8af480a303bfa9c0dd9894f5049d8b6d6..05936453fbbfa59c563fdea50e0b40096c2b46ac 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
@@ -213,7 +213,7 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog,
 			return -ENOMEM;
 		}
 
-		err = mana_alloc_qset(scratch, apc->num_queues,
+		err = mana_alloc_qset(apc, scratch, apc->num_queues,
 				      apc->rx_queue_size, apc->tx_queue_size,
 				      apc->priv_flags, apc->configured_mtu,
 				      prog, &newq);
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 27484e5cf71a2216e7dc89c21ee0e9d95786cf30..be7f9f6626e42c33fc0e749e6897ecc8117222cf 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -913,7 +913,7 @@ static int mana_change_mtu(struct net_device *ndev, int new_mtu)
 	if (!scratch)
 		return -ENOMEM;
 
-	err = mana_alloc_qset(scratch, mpc->num_queues, mpc->rx_queue_size,
+	err = mana_alloc_qset(mpc, scratch, mpc->num_queues, mpc->rx_queue_size,
 			      mpc->tx_queue_size, mpc->priv_flags, new_mtu,
 			      mpc->bpf_prog, &newq);
 	if (err)
@@ -1809,7 +1809,7 @@ void mana_destroy_eq(struct mana_port_context *apc)
 	debugfs_remove_recursive(apc->mana_eqs_debugfs);
 	apc->mana_eqs_debugfs = NULL;
 
-	for (i = 0; i < apc->num_queues; i++) {
+	for (i = 0; i < apc->num_eqs; i++) {
 		eq = apc->eqs[i].eq;
 		if (!eq)
 			continue;
@@ -1821,6 +1821,7 @@ void mana_destroy_eq(struct mana_port_context *apc)
 
 	kfree(apc->eqs);
 	apc->eqs = NULL;
+	apc->num_eqs = 0;
 }
 EXPORT_SYMBOL_NS(mana_destroy_eq, "NET_MANA");
 
@@ -1849,9 +1850,14 @@ int mana_create_eq(struct mana_port_context *apc)
 
 	if (WARN_ON(apc->eqs))
 		return -EEXIST;
-	apc->eqs = kzalloc_objs(struct mana_eq, apc->num_queues);
+	/* Size the array to the largest queue count this port can ever use,
+	 * so growing it later never has to reallocate (the CQs of a live
+	 * queue set hold pointers taken from these slots).
+	 */
+	apc->eqs = kzalloc_objs(struct mana_eq, apc->max_queues);
 	if (!apc->eqs)
 		return -ENOMEM;
+	apc->num_eqs = 0;
 
 	spec.type = GDMA_EQ;
 	spec.monitor_avl_buf = false;
@@ -1881,6 +1887,7 @@ int mana_create_eq(struct mana_port_context *apc)
 		}
 		apc->eqs[i].eq->eq.irq = gic->irq;
 		mana_create_eq_debugfs(apc, i);
+		apc->num_eqs = i + 1;
 	}
 
 	return 0;
@@ -1890,6 +1897,70 @@ int mana_create_eq(struct mana_port_context *apc)
 }
 EXPORT_SYMBOL_NS(mana_create_eq, "NET_MANA");
 
+/**
+ * mana_grow_eqs - make sure the port has at least @need EQs
+ * @apc:  port context
+ * @need: number of EQs the new queue set requires
+ *
+ * EQs are bound to MSI-X vectors, so the pool is port-owned and shared across
+ * a swap: peak usage is max(old, new), not the sum. Grow-only, up to
+ * apc->max_queues.
+ */
+static int mana_grow_eqs(struct mana_port_context *apc, unsigned int need)
+{
+	struct gdma_dev *gd = apc->ac->gdma_dev;
+	struct gdma_context *gc = gd->gdma_context;
+	struct gdma_queue_spec spec = {};
+	struct gdma_irq_context *gic;
+	unsigned int i;
+	int err;
+	int msi;
+
+	if (WARN_ON(!apc->eqs))
+		return -EINVAL;
+
+	if (need > apc->max_queues)
+		return -EINVAL;
+
+	if (need <= apc->num_eqs)
+		return 0;
+
+	spec.type = GDMA_EQ;
+	spec.monitor_avl_buf = false;
+	spec.queue_size = EQ_SIZE;
+	spec.eq.callback = NULL;
+	spec.eq.context = apc->eqs;
+	spec.eq.log2_throttle_limit = LOG2_EQ_THROTTLE;
+
+	for (i = apc->num_eqs; i < need; i++) {
+		msi = (i + 1) % gc->num_msix_usable;
+
+		gic = mana_gd_get_gic(gc, !gc->msi_sharing, &msi);
+		if (IS_ERR(gic)) {
+			err = PTR_ERR(gic);
+			goto out;
+		}
+		spec.eq.msix_index = msi;
+
+		err = mana_gd_create_mana_eq(gd, &spec, &apc->eqs[i].eq);
+		if (err) {
+			dev_err(gc->dev, "Failed to grow EQ %u : %d\n", i, err);
+			mana_gd_put_gic(gc, !gc->msi_sharing, msi);
+			goto out;
+		}
+		apc->eqs[i].eq->eq.irq = gic->irq;
+		mana_create_eq_debugfs(apc, i);
+		apc->num_eqs = i + 1;
+	}
+
+	return 0;
+out:
+	/* Keep whatever was created: the running queue set still needs its
+	 * own EQs, and the extras are reused by the next attempt.
+	 */
+	return err;
+}
+
 static int mana_fence_rq(struct mana_port_context *apc, struct mana_rxq *rxq)
 {
 	struct mana_fence_rq_resp resp = {};
@@ -3936,52 +4007,23 @@ static int mana_dealloc_queues(struct net_device *ndev)
 }
 
 /*
- * ---------------------------------------------------------------------------
- * Pre-allocate + swap reconfiguration path.
- *
- * The detach/attach reconfigure path tears the vport down and rebuilds it,
- * which lets RDMA grab the vport mid-flight and, if attach fails, leaves the
- * port permanently broken.
- *
- * The swap path builds a *new* set of EQs/TXQs/RXQs while the current set
- * keeps serving traffic. If allocation fails the current qset is untouched
- * and we return the error; the user's requested value is never silently
- * replaced by a fallback. Once the new qset is ready we publish it onto apc
- * and destroy the old one. The vport is never torn down: vport_use_count
- * stays at 1 throughout, so RDMA cannot hijack it.
+ * Pre-allocate and swap reconfiguration.
  *
- * The cost of never dropping the working queues is that a rebuild needs room
- * for both sets at once, so one at the vport's maximum queue count can be
- * refused by the firmware where a teardown-first sequence would have fit.
- * That surfaces as a failed ethtool operation with the port still running on
- * its previous queues, which is the trade this path exists to make.
+ * Build a new queue set while the current one serves traffic, publish it, then
+ * destroy the old one. A failed allocation leaves the running config untouched,
+ * and the vport is never torn down, so RDMA cannot take it mid-swap. The cost
+ * is room for both sets at once, so a rebuild at the vport's maximum queue
+ * count can be refused; EQs are shared from a port-owned pool, not doubled.
  *
- * Allocation and teardown run against a *scratch* mana_port_context rather
- * than the live one. This is essential, not cosmetic: an earlier revision
- * temporarily NULLed apc->tx_qp so the allocators could
- * build into the live context, which reliably panicked in mana_start_xmit()
- * under traffic (it dereferences apc->tx_qp[] guarded only by port_is_up).
- * The live apc is now mutated only inside mana_publish_qset(), with TX
- * disabled.
- *
- * Note that both sets are live between publish and free, so this peaks at
- * old+new queues, and therefore at old+new MSI-X vectors. A later patch
- * gives the port a shared EQ pool so only the queues, not the interrupts,
- * are doubled up.
- *
- * Per-queue debugfs is suppressed for a set while it is being built or torn
- * down (see mana_qset_scratch_alloc()): the directory names are derived from
- * the queue index, so the incoming set would collide with the outgoing one
- * under vport%d. Restoring it needs per-set subdirectories or a
- * debugfs_rename() once the swap has completed.
- * ---------------------------------------------------------------------------
+ * Everything builds in a scratch mana_port_context, since mana_start_xmit()
+ * dereferences apc->tx_qp[] guarded only by port_is_up. Per-queue debugfs is
+ * suppressed meanwhile, as the names would collide.
  */
 
 /* Snapshot the queue-set fields of @ctx into @out. */
 static void mana_qset_snapshot(const struct mana_port_context *ctx,
 			       struct mana_qset *out)
 {
-	out->eqs		= ctx->eqs;
 	out->tx_qp		= ctx->tx_qp;
 	out->rxqs		= ctx->rxqs;
 	out->indir_table	= ctx->indir_table;
@@ -3994,7 +4036,6 @@ 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->mana_eqs_debugfs	= ctx->mana_eqs_debugfs;
 }
 
 /* Install @qset's fields onto @ctx. The vport (port_handle,
@@ -4004,7 +4045,6 @@ static void mana_qset_snapshot(const struct mana_port_context *ctx,
 static void mana_qset_install(struct mana_port_context *ctx,
 			      const struct mana_qset *qset)
 {
-	ctx->eqs		= qset->eqs;
 	ctx->tx_qp		= qset->tx_qp;
 	ctx->rxqs		= qset->rxqs;
 	ctx->indir_table	= qset->indir_table;
@@ -4017,7 +4057,6 @@ static void mana_qset_install(struct mana_port_context *ctx,
 	ctx->priv_flags		= qset->priv_flags;
 	ctx->configured_mtu	= qset->mtu;
 	ctx->bpf_prog		= qset->bpf_prog;
-	ctx->mana_eqs_debugfs	= qset->mana_eqs_debugfs;
 }
 
 /**
@@ -4038,29 +4077,24 @@ struct mana_port_context *mana_qset_scratch_alloc(struct mana_port_context *apc)
 
 	*scratch = *apc;
 
-	/* Owns no queues yet. */
-	scratch->eqs		= NULL;
+	/* EQs stay shared with the live port: they are a vector-backed
+	 * resource and must not be duplicated for the new set.
+	 */
 	scratch->tx_qp		= NULL;
 	scratch->rxqs		= NULL;
 	scratch->indir_table	= NULL;
 	scratch->rxobj_table	= NULL;
 	scratch->default_rxobj	= INVALID_MANA_HANDLE;
-	scratch->mana_eqs_debugfs = NULL;
 
-	/* Never consume the live set's pre-allocated RX buffers;
-	 * mana_get_rxbuf() falls back to normal allocation when these
-	 * are NULL, which is what we want since the swap path no longer
-	 * needs to de-risk post-teardown allocation.
+	/* Never consume the live set's pre-allocated RX buffers; the swap path
+	 * has no post-teardown allocation to de-risk.
 	 */
 	scratch->rxbufs_pre	= NULL;
 	scratch->das_pre	= NULL;
 	scratch->rxbpre_total	= 0;
 
-	/* Suppress debugfs for queues built through the scratch context:
-	 * two sets are alive at once and would collide on the same names
-	 * under vport%d. debugfs_start_creating() returns early on an
-	 * IS_ERR() parent, and debugfs_remove() ignores IS_ERR_OR_NULL,
-	 * so this makes every create/remove a clean no-op.
+	/* Two sets are alive at once and would collide on the same names under
+	 * vport%d. An IS_ERR() parent makes every create and remove a no-op.
 	 */
 	scratch->mana_port_debugfs = ERR_PTR(-ENODEV);
 
@@ -4077,7 +4111,8 @@ void mana_qset_scratch_free(struct mana_port_context *scratch)
  * mana_grow_qset(), so this never has to add an EQ. The installed set keeps
  * serving traffic meanwhile. On error nothing is left allocated.
  */
-int mana_alloc_qset(struct mana_port_context *scratch, unsigned int num_queues,
+int mana_alloc_qset(struct mana_port_context *apc,
+		    struct mana_port_context *scratch, unsigned int num_queues,
 		    unsigned int rx_queue_size, unsigned int tx_queue_size,
 		    u32 priv_flags, int mtu, struct bpf_prog *bpf_prog,
 		    struct mana_qset *out)
@@ -4107,13 +4142,20 @@ int mana_alloc_qset(struct mana_port_context *scratch, unsigned int num_queues,
 	if (err)
 		goto cleanup_rxq_array;
 
-	err = mana_create_eq(scratch);
+	/* Grow the port's shared EQ pool if this set needs more. The pool
+	 * belongs to @apc, not to either queue set, so both sets can be
+	 * live at once without double-booking MSI-X vectors.
+	 */
+	err = mana_grow_eqs(apc, num_queues);
 	if (err)
 		goto cleanup_rss;
 
+	scratch->eqs = apc->eqs;
+	scratch->num_eqs = apc->num_eqs;
+
 	err = mana_create_txq(scratch, ndev);
 	if (err)
-		goto cleanup_eq;
+		goto cleanup_rss;
 
 	err = mana_add_rx_queues(scratch, ndev);
 	if (err)
@@ -4131,8 +4173,6 @@ int mana_alloc_qset(struct mana_port_context *scratch, unsigned int num_queues,
 	 */
 	mana_destroy_rxqs(scratch);
 	mana_destroy_txq(scratch);
-cleanup_eq:
-	mana_destroy_eq(scratch);
 cleanup_rss:
 	mana_cleanup_indir_table(scratch);
 cleanup_rxq_array:
@@ -4423,16 +4463,10 @@ void mana_free_qset(struct mana_port_context *scratch, struct mana_qset *qset)
 
 	ASSERT_RTNL();
 
-	if (!qset->rxqs && !qset->tx_qp && !qset->eqs)
+	if (!qset->rxqs && !qset->tx_qp)
 		return;
 
-	/* These queues are leaving. Stop their completions from touching the
-	 * shared netdev queues: net_txq is shared with whatever replaced them
-	 * at the same index, and a queue that is only draining always looks
-	 * like it has room, so it would wake a live queue that stopped itself
-	 * because its ring was full. The synchronize_net() below then retires
-	 * any poll that has not seen the flag yet.
-	 */
+	/* Keep their completions off the netdev queues they now share. */
 	if (qset->tx_qp) {
 		unsigned int q;
 
@@ -4511,7 +4545,6 @@ void mana_free_qset(struct mana_port_context *scratch, struct mana_qset *qset)
 	mana_chn_xdp_release(retiring_prog, retiring_queues);
 
 	mana_destroy_txq(scratch);
-	mana_destroy_eq(scratch);
 	mana_cleanup_indir_table(scratch);
 	kfree(scratch->rxqs);
 	scratch->rxqs = NULL;
diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
index 26f5ea1f5091a7fab729ecf3468bdc13886fcccb..08e6fb7785cd3be72f8737083e6424783c5e0d21 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
@@ -722,7 +722,7 @@ static int mana_set_channels(struct net_device *ndev,
 		goto clear_flag;
 	}
 
-	err = mana_alloc_qset(scratch, new_count, apc->rx_queue_size,
+	err = mana_alloc_qset(apc, scratch, new_count, apc->rx_queue_size,
 			      apc->tx_queue_size, apc->priv_flags,
 			      apc->configured_mtu, apc->bpf_prog, &newq);
 	if (err)
@@ -818,7 +818,7 @@ static int mana_set_ringparam(struct net_device *ndev,
 		goto clear_flag;
 	}
 
-	err = mana_alloc_qset(scratch, apc->num_queues, new_rx, new_tx,
+	err = mana_alloc_qset(apc, scratch, apc->num_queues, new_rx, new_tx,
 			      apc->priv_flags, apc->configured_mtu,
 			      apc->bpf_prog, &newq);
 	if (err) {
@@ -917,7 +917,7 @@ static int mana_set_priv_flags(struct net_device *ndev, u32 priv_flags)
 		goto clear_flag;
 	}
 
-	err = mana_alloc_qset(scratch, apc->num_queues, apc->rx_queue_size,
+	err = mana_alloc_qset(apc, scratch, apc->num_queues, apc->rx_queue_size,
 			      apc->tx_queue_size, priv_flags,
 			      apc->configured_mtu, apc->bpf_prog, &newq);
 	if (err)
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 77cec5b44049202e21f919d4336fdf8ebc248a18..dfb6ba0012fda629192e4fe9cf8aba57fd5bb451 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -581,7 +581,12 @@ struct mana_port_context {
 
 	u8 mac_addr[ETH_ALEN];
 
+	/* EQ pool, owned by the port rather than a queue set: EQs are bound to
+	 * MSI-X vectors, which a swap must not double-book. Sized to
+	 * max_queues; num_eqs is how many exist.
+	 */
 	struct mana_eq *eqs;
+	unsigned int num_eqs;
 	struct dentry *mana_eqs_debugfs;
 
 	enum TRI_STATE rss_state;
@@ -702,18 +707,11 @@ struct mana_port_context {
 	u32 steer_cqe_coalescing;
 };
 
-/* struct mana_qset - a self-contained snapshot of the queue-related
- * fields inside mana_port_context that can be swapped atomically.
- *
- * Prototype for the "pre-allocate + swap" reconfiguration path (as
- * suggested by netdev maintainers): a new qset is allocated while the
- * current one keeps serving traffic, then apc's queue fields are
- * atomically switched to the new set and the old set is torn down.
- * The vport (port_handle / vport_use_count) is *not* touched, so RDMA
- * can never race in during reconfiguration.
+/* The queue-related fields of mana_port_context that can be swapped as a
+ * unit. The vport (port_handle, vport_use_count) is not part of it and is
+ * never touched by a swap.
  */
 struct mana_qset {
-	struct mana_eq		*eqs;
 	struct mana_tx_qp	**tx_qp;
 	struct mana_rxq		**rxqs;
 
@@ -733,13 +731,6 @@ struct mana_qset {
 	 */
 	int			mtu;
 	struct bpf_prog		*bpf_prog;
-
-	/* Per-queue-set debugfs root ("EQs"). Owned by the qset: it is
-	 * recreated by mana_create_eq() for each new set and torn down
-	 * with that set, so it must travel with the qset rather than
-	 * staying on apc.
-	 */
-	struct dentry		*mana_eqs_debugfs;
 };
 
 netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev);
@@ -751,13 +742,14 @@ int mana_alloc_queues(struct net_device *ndev);
 int mana_attach(struct net_device *ndev);
 int mana_detach(struct net_device *ndev, bool from_close);
 
-/* Pre-allocate + swap reconfiguration path (prototype). Allocation and
- * teardown run against a scratch context so the live port context is only
- * mutated inside mana_publish_qset(), with TX disabled.
+/* Pre-allocate + swap reconfiguration. Allocation and teardown run against a
+ * scratch context, so the live port context is mutated only inside
+ * mana_publish_qset() with TX disabled. Both sets share a port-owned EQ pool.
  */
 struct mana_port_context *mana_qset_scratch_alloc(struct mana_port_context *apc);
 void mana_qset_scratch_free(struct mana_port_context *scratch);
-int mana_alloc_qset(struct mana_port_context *scratch, unsigned int num_queues,
+int mana_alloc_qset(struct mana_port_context *apc,
+		    struct mana_port_context *scratch, unsigned int num_queues,
 		    unsigned int rx_queue_size, unsigned int tx_queue_size,
 		    u32 priv_flags, int mtu, struct bpf_prog *bpf_prog,
 		    struct mana_qset *out);
-- 
2.43.0


  parent reply	other threads:[~2026-08-13  5:05 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-13  5:04 [PATCH net-next v2 00/13] net: mana: reconfigure by replacing the queue set Long Li
2026-08-13  5:04 ` [PATCH net-next v2 01/13] net: mana: add queue-set allocation and teardown helpers Long Li
2026-08-13  5:04 ` [PATCH net-next v2 02/13] net: mana: swap queue sets in mana_set_channels Long Li
2026-08-13  5:04 ` [PATCH net-next v2 03/13] net: mana: swap queue sets in mana_set_ringparam Long Li
2026-08-13  5:04 ` [PATCH net-next v2 04/13] net: mana: swap queue sets in mana_set_priv_flags Long Li
2026-08-13  5:04 ` [PATCH net-next v2 05/13] net: mana: swap queue sets in mana_change_mtu Long Li
2026-08-13  5:04 ` [PATCH net-next v2 06/13] net: mana: swap queue sets in mana_xdp_set Long Li
2026-08-13  5:04 ` [PATCH net-next v2 07/13] net: mana: do not bail out of mana_detach on dealloc failure Long Li
2026-08-13  5:04 ` [PATCH net-next v2 08/13] net: mana: keep per-queue statistics in the port context Long Li
2026-08-13  5:04 ` Long Li [this message]
2026-08-13  5:04 ` [PATCH net-next v2 10/13] net: mana: release EQs left idle by a channel-count reduction Long Li
2026-08-13  5:04 ` [PATCH net-next v2 11/13] net: mana: keep a user-configured RSS table across a queue rebuild Long Li
2026-08-13  5:04 ` [PATCH net-next v2 12/13] net: mana: keep the surviving queues when the channel count is reduced Long Li
2026-08-13  5:04 ` [PATCH net-next v2 13/13] net: mana: keep the existing queues when the channel count is raised Long Li
  -- strict thread matches above, loose matches on Subject: below --
2026-08-11  6:34 [PATCH net-next v2 00/13] net: mana: reconfigure by replacing the queue set Long Li
2026-08-11  6:35 ` [PATCH net-next v2 09/13] net: mana: share the EQ pool across a queue-set swap 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=20260813050418.2906468-10-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.