From: Mingming Cao <mmc@linux.ibm.com>
To: netdev@vger.kernel.org
Cc: horms@kernel.org, bjking1@linux.ibm.com, haren@linux.ibm.com,
ricklind@linux.ibm.com, mmc@linux.ibm.com, kuba@kernel.org,
edumazet@google.com, pabeni@redhat.com, davem@davemloft.net,
linuxppc-dev@lists.ozlabs.org, maddy@linux.ibm.com,
mpe@ellerman.id.au, simon.horman@corigine.com,
shaik.abdulla1@ibm.com, Dave Marquardt <davemarq@linux.ibm.com>
Subject: [PATCH net-next v4 04/14] ibmveth: Refactor buffer pool management for per-queue MQ RX
Date: Thu, 30 Jul 2026 17:47:07 -0700 [thread overview]
Message-ID: <e22471625e6a04bee87f099f467d575bcfd0c2c6.1785457143.git.mmc@linux.ibm.com> (raw)
In-Reply-To: <cover.1785457143.git.mmc@linux.ibm.com>
Legacy ibmveth uses five adapter-level RX buffer pools (512 B through
64 KiB). pool_active[] enables the standard-MTU pools by default;
larger pools activate when MTU requires them. With single-queue RX
that set is shared on one completion path.
MQ requires the same pool model per queue: buffers post with
H_ADD_LOGICAL_LAN_BUFFERS_QUEUE against a queue handle and completions
return on that queue. Sharing pools across queues would mix ownership
and break queue-local replenish/drain/teardown.
Refactor around queue-local pools:
rx_buff_pool[queue][pool]
ibmveth_alloc_queue_buffer_pools()
ibmveth_free_queue_buffer_pools()
ibmveth_alloc_buffer_pools() / ibmveth_free_buffer_pools()
Queue 0 remains the template for pool geometry (size, buff_size,
threshold, index, active). For queues 1..N we copy metadata from
queue 0, then allocate backing arrays/skbs per queue.
Wire the helpers into open()/close() in the same patch. Runtime
remains single-queue (num_rx_queues is still 1).
Error handling is queue-safe:
- allocation failure unwinds only what that queue allocated, then
prior queues in the caller
- free paths release by real allocations (free_map/dma_addr/skbuff),
not only pool->active
That allocation-based free check is intentional: later resize and
failure paths can leave memory allocated after active was cleared.
Also disable the 64 KiB pool by default at standard MTU. MTU changes
activate it when required; leaving it enabled would pin about 16 MiB
per RX queue in MQ mode.
Signed-off-by: Mingming Cao <mmc@linux.ibm.com>
Reviewed-by: Dave Marquardt <davemarq@linux.ibm.com>
Tested-by: Shaik Abdulla <shaik.abdulla1@ibm.com>
---
Changes in v4:
- Introduce the pool helpers in the same patch that wires their first
open/close callers, instead of leaving unused statics.
- Copy pool->index when cloning queue-0 geometry to later queues
(needed for correlators; also required by incremental resize).
drivers/net/ethernet/ibm/ibmveth.c | 164 +++++++++++++++++++++++++----
drivers/net/ethernet/ibm/ibmveth.h | 2 +-
2 files changed, 145 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 1007dd95cde0..7a2ed49cad4f 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -625,6 +625,145 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter,
}
}
+/**
+ * ibmveth_alloc_queue_buffer_pools - Allocate buffer pools for a single queue
+ * @adapter: ibmveth adapter structure
+ * @queue: queue index
+ *
+ * Allocates all active buffer pools for the specified queue.
+ * Pool metadata must be initialized before calling this function.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int ibmveth_alloc_queue_buffer_pools(struct ibmveth_adapter *adapter,
+ int queue)
+{
+ struct net_device *netdev = adapter->netdev;
+ int i;
+
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
+ struct ibmveth_buff_pool *bpool =
+ &adapter->rx_buff_pool[queue][i];
+
+ if (!bpool->active)
+ continue;
+
+ if (ibmveth_alloc_buffer_pool(bpool)) {
+ netdev_err(netdev,
+ "pool %d/%d alloc failed (size=%u count=%u)\n",
+ i, queue,
+ bpool->buff_size,
+ bpool->size);
+ bpool->active = 0;
+
+ /* Free pools allocated so far for this queue */
+ while (--i >= 0) {
+ struct ibmveth_buff_pool *fpool =
+ &adapter->rx_buff_pool[queue][i];
+
+ if (fpool->active)
+ ibmveth_free_buffer_pool(adapter,
+ fpool);
+ }
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ibmveth_free_queue_buffer_pools - Free buffer pools for a single queue
+ * @adapter: ibmveth adapter structure
+ * @queue: queue index
+ *
+ * Frees all active buffer pools for the specified queue.
+ */
+static void ibmveth_free_queue_buffer_pools(struct ibmveth_adapter *adapter,
+ int queue)
+{
+ int i;
+
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
+ struct ibmveth_buff_pool *pool =
+ &adapter->rx_buff_pool[queue][i];
+
+ /* Free pool if it has allocated memory, regardless of
+ * active flag. Pools may have memory allocated but not
+ * marked active during queue scale-up, so we must check
+ * for actual allocations.
+ */
+ if (pool->free_map || pool->dma_addr || pool->skbuff)
+ ibmveth_free_buffer_pool(adapter, pool);
+ }
+}
+
+/**
+ * ibmveth_alloc_buffer_pools - Allocate buffer pools for all queues
+ * @adapter: ibmveth adapter structure
+ *
+ * Initializes pool metadata for queues 1-N from queue 0 settings,
+ * then allocates buffer pools for all queues using the helper function.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int
+ibmveth_alloc_buffer_pools(struct ibmveth_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ int i, q, rc;
+
+ /* Initialize pool metadata for queues 1-15 from queue 0 settings */
+ for (q = 1; q < adapter->num_rx_queues; q++) {
+ for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
+ struct ibmveth_buff_pool *src =
+ &adapter->rx_buff_pool[0][i];
+ struct ibmveth_buff_pool *dst =
+ &adapter->rx_buff_pool[q][i];
+
+ dst->size = src->size;
+ dst->index = src->index;
+ dst->buff_size = src->buff_size;
+ dst->threshold = src->threshold;
+ dst->active = src->active;
+ }
+ }
+
+ /* Allocate actual buffers for all queues */
+ for (q = 0; q < adapter->num_rx_queues; q++) {
+ rc = ibmveth_alloc_queue_buffer_pools(adapter, q);
+ if (rc) {
+ /* Free pools for all previous queues */
+ while (--q >= 0)
+ ibmveth_free_queue_buffer_pools(adapter, q);
+ return rc;
+ }
+ }
+
+ netdev_dbg(netdev, "allocated buffer pools for %d queue(s)\n",
+ adapter->num_rx_queues);
+ return 0;
+}
+
+/**
+ * ibmveth_free_buffer_pools - Free buffer pools for all queues
+ * @adapter: ibmveth adapter structure
+ *
+ * Frees buffer pools for all queues using the helper function.
+ */
+static void
+ibmveth_free_buffer_pools(struct ibmveth_adapter *adapter)
+{
+ int q;
+
+ /* Free buffer pools for all queues */
+ for (q = 0; q < adapter->num_rx_queues; q++)
+ ibmveth_free_queue_buffer_pools(adapter, q);
+
+ netdev_dbg(adapter->netdev, "freed buffer pools for %d queue(s)\n",
+ adapter->num_rx_queues);
+}
+
/**
* ibmveth_remove_buffer_from_pool - remove a buffer from a pool
* @adapter: adapter instance
@@ -850,16 +989,9 @@ static int ibmveth_open(struct net_device *netdev)
goto out_free_tx_ltb;
}
- for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
- if (!adapter->rx_buff_pool[0][i].active)
- continue;
- if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0][i])) {
- netdev_err(netdev, "unable to alloc pool\n");
- adapter->rx_buff_pool[0][i].active = 0;
- rc = -ENOMEM;
- goto out_free_buffer_pools;
- }
- }
+ rc = ibmveth_alloc_buffer_pools(adapter);
+ if (rc)
+ goto out_free_tx_ltb;
netdev_dbg(netdev, "registering irq 0x%x\n", netdev->irq);
rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name,
@@ -884,11 +1016,7 @@ static int ibmveth_open(struct net_device *netdev)
return 0;
out_free_buffer_pools:
- while (--i >= 0) {
- if (adapter->rx_buff_pool[0][i].active)
- ibmveth_free_buffer_pool(adapter,
- &adapter->rx_buff_pool[0][i]);
- }
+ ibmveth_free_buffer_pools(adapter);
out_free_tx_ltb:
while (--i >= 0)
ibmveth_free_tx_ltb(adapter, i);
@@ -927,14 +1055,10 @@ static int ibmveth_close(struct net_device *netdev)
ibmveth_update_rx_no_buffer(adapter);
+ ibmveth_free_buffer_pools(adapter);
ibmveth_cleanup_rx_resources(adapter);
ibmveth_free_filter_list(adapter);
- for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
- if (adapter->rx_buff_pool[0][i].active)
- ibmveth_free_buffer_pool(adapter,
- &adapter->rx_buff_pool[0][i]);
-
for (i = 0; i < netdev->real_num_tx_queues; i++)
ibmveth_free_tx_ltb(adapter, i);
diff --git a/drivers/net/ethernet/ibm/ibmveth.h b/drivers/net/ethernet/ibm/ibmveth.h
index 8eaa3942fc40..abcd4054c67e 100644
--- a/drivers/net/ethernet/ibm/ibmveth.h
+++ b/drivers/net/ethernet/ibm/ibmveth.h
@@ -265,7 +265,7 @@ static inline long h_illan_attributes(unsigned long unit_address,
static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
static int pool_count[] = { 256, 512, 256, 256, 256 };
static int pool_count_cmo[] = { 256, 512, 256, 256, 64 };
-static int pool_active[] = { 1, 1, 0, 0, 1};
+static int pool_active[] = { 1, 1, 0, 0, 0};
#define IBM_VETH_INVALID_MAP ((u16)0xffff)
--
2.50.1 (Apple Git-155)
next prev parent reply other threads:[~2026-07-31 0:48 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 0:47 [PATCH net-next v4 00/14] ibmveth: Add multi-queue RX support Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 01/14] ibmveth: Add MQ RX hypercall wrappers and call definitions Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 02/14] ibmveth: Prepare MQ RX adapter data structures Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 03/14] ibmveth: Refactor RX resource allocation for MQ RX bring-up Mingming Cao
2026-07-31 0:47 ` Mingming Cao [this message]
2026-07-31 0:47 ` [PATCH net-next v4 05/14] ibmveth: Refactor RX interrupt control for MQ RX queues Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 06/14] ibmveth: Refactor TX resource allocation in open/close paths Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 07/14] ibmveth: Add RX queue register/deregister helpers for MQ Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 08/14] ibmveth: Add queue-aware RX buffer submit helper " Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 09/14] ibmveth: Enable multi-queue RX receive path Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 10/14] ibmveth: Add per-queue RX and TX statistics collection Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 11/14] ibmveth: Expose per-queue buffer pool details via debugfs Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 12/14] ibmveth: Implement incremental MQ RX queue resize Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 13/14] ibmveth: Wire ethtool set_channels to " Mingming Cao
2026-07-31 0:47 ` [PATCH net-next v4 14/14] ibmveth: Fix MQ RX poll and shutdown hangs after " Mingming Cao
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=e22471625e6a04bee87f099f467d575bcfd0c2c6.1785457143.git.mmc@linux.ibm.com \
--to=mmc@linux.ibm.com \
--cc=bjking1@linux.ibm.com \
--cc=davem@davemloft.net \
--cc=davemarq@linux.ibm.com \
--cc=edumazet@google.com \
--cc=haren@linux.ibm.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=maddy@linux.ibm.com \
--cc=mpe@ellerman.id.au \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=ricklind@linux.ibm.com \
--cc=shaik.abdulla1@ibm.com \
--cc=simon.horman@corigine.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox