Thread (7 messages) flat view 7 messages, 1 author, 3h ago
HOTtoday REVIEWED: 2 (0M)

2 review trailers.

[PATCH net-next v1 4/6] ibmvnic: allocate new buffer pools before releasing the old ones

From: Mingming Cao <hidden>
Date: 2026-08-05 22:44:53
Also in: netdev
Subsystem: ibm power sriov virtual nic device driver, linux for powerpc (32-bit and 64-bit), networking drivers, the rest · Maintainers: Haren Myneni, Rick Lindsley, Madhavan Srinivasan, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

An mtu change goes through wait_for_reset() and then init_rx_pools() /
init_tx_pools(). Those helpers release the existing pools before
allocating their replacements:

  release_rx_pools(adapter);

  adapter->rx_pool = kzalloc_objs(struct ibmvnic_rx_pool, num_pools);
  if (!adapter->rx_pool) {
          dev_err(dev, "Failed to allocate rx pools\n");
          return -ENOMEM;
  }

If that allocation fails mid-reset the interface is left with no pools
and stays down after what should have been a refused mtu change, when
it could have kept running with the pools it still had.

Allocate first and only release once the allocation has succeeded. The
tx side has to swap ->tx_pool and ->tso_pool in together, so that
release_tx_pools() never sees one set without the other.

These are small allocations and failing them is unlikely, so this is
about the ordering rather than about any failure seen in the field.
alloc_long_term_buff() has the same shape for a much larger allocation
on the mtu-grow path and is dealt with next.

Fixes: 489de956e7a2 ("ibmvnic: Reuse rx pools when possible")
Fixes: bbd809305bc7 ("ibmvnic: Reuse tx pools when possible")
Reviewed-by: Dave Marquardt <redacted>
Tested-by: Vaishnavi Bhat <redacted>
Signed-off-by: Mingming Cao <redacted>
---
 drivers/net/ethernet/ibm/ibmvnic.c | 37 ++++++++++++++++--------------
 1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index e875f43a1ea1..24c8acc42a93 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1098,6 +1098,7 @@ static int init_rx_pools(struct net_device *netdev)
 {
 	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
 	struct device *dev = &adapter->vdev->dev;
+	struct ibmvnic_rx_pool *new_rx_pool;
 	struct ibmvnic_rx_pool *rx_pool;
 	u64 num_pools;
 	u64 pool_size;		/* # of buffers in one pool */
@@ -1113,15 +1114,16 @@ static int init_rx_pools(struct net_device *netdev)
 		goto update_ltb;
 	}
 
-	/* Allocate/populate the pools. */
-	release_rx_pools(adapter);
-
-	adapter->rx_pool = kzalloc_objs(struct ibmvnic_rx_pool, num_pools);
-	if (!adapter->rx_pool) {
+	/* Allocate before release so a failure keeps the old pools. */
+	new_rx_pool = kzalloc_objs(struct ibmvnic_rx_pool, num_pools);
+	if (!new_rx_pool) {
 		dev_err(dev, "Failed to allocate rx pools\n");
 		return -ENOMEM;
 	}
 
+	release_rx_pools(adapter);
+	adapter->rx_pool = new_rx_pool;
+
 	/* Set num_active_rx_pools early. If we fail below after partial
 	 * allocation, release_rx_pools() will know how many to look for.
 	 */
@@ -1333,6 +1335,8 @@ static int init_tx_pools(struct net_device *netdev)
 {
 	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
 	struct device *dev = &adapter->vdev->dev;
+	struct ibmvnic_tx_pool *new_tso_pool;
+	struct ibmvnic_tx_pool *new_tx_pool;
 	int num_pools;
 	u64 pool_size;		/* # of buffers in pool */
 	u64 buff_size;
@@ -1349,26 +1353,25 @@ static int init_tx_pools(struct net_device *netdev)
 		goto update_ltb;
 	}
 
-	/* Allocate/populate the pools. */
-	release_tx_pools(adapter);
-
+	/* Allocate before release so a failure keeps the old pools. */
 	pool_size = adapter->req_tx_entries_per_subcrq;
 	num_pools = adapter->num_active_tx_scrqs;
 
-	adapter->tx_pool = kzalloc_objs(struct ibmvnic_tx_pool, num_pools);
-	if (!adapter->tx_pool)
+	new_tx_pool = kzalloc_objs(struct ibmvnic_tx_pool, num_pools);
+	if (!new_tx_pool)
 		return -ENOMEM;
 
-	adapter->tso_pool = kzalloc_objs(struct ibmvnic_tx_pool, num_pools);
-	/* To simplify release_tx_pools() ensure that ->tx_pool and
-	 * ->tso_pool are either both NULL or both non-NULL.
-	 */
-	if (!adapter->tso_pool) {
-		kfree(adapter->tx_pool);
-		adapter->tx_pool = NULL;
+	new_tso_pool = kzalloc_objs(struct ibmvnic_tx_pool, num_pools);
+	if (!new_tso_pool) {
+		kfree(new_tx_pool);
 		return -ENOMEM;
 	}
 
+	/* Swap both in together for release_tx_pools(). */
+	release_tx_pools(adapter);
+	adapter->tx_pool = new_tx_pool;
+	adapter->tso_pool = new_tso_pool;
+
 	/* Set num_active_tx_pools early. If we fail below after partial
 	 * allocation, release_tx_pools() will know how many to look for.
 	 */
-- 
2.50.1 (Apple Git-155)

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help