Same story as the RX refactor: pull TX LTB alloc/free out of open/close
into helpers and wire them in this patch.

  ibmveth_alloc_tx_resources()
  ibmveth_free_tx_resources()

They wrap the existing per-queue allocate_tx_ltb() / free_tx_ltb()
primitives. alloc_tx_resources() allocates every TX queue and unwinds
partial failure itself; free_tx_resources() walks real_num_tx_queues.
TX was already multi-queue capable via ethtool -L, so there is no MQ
RX behaviour change here.

Also tighten TX LTB lifetime: free_tx_ltb() is safe on an unallocated
slot and clears tx_ltb_dma[] after unmap; allocate_tx_ltb() clears
tx_ltb_dma[] after DMA-map failure.

Move TX LTB allocation to the end of open(), after LAN registration,
RX pools, RX interrupt setup, and the initial replenish kick. A late
alloc_tx_resources() failure jumps to out_cleanup_rx_interrupts and
must not call free_tx_resources() again: alloc already freed any
partial TX LTBs. That also retires a mid-open TX leak where the old
index-based while (--i) free could skip successfully allocated LTBs.

close() uses free_tx_resources() and cleanup_rx_interrupts().

Signed-off-by: Mingming Cao <[email protected]>
Reviewed-by: Dave Marquardt <[email protected]>
Tested-by: Shaik Abdulla <[email protected]>
---

Changes in v4:
- Introduce the TX resource helpers in the same patch that wires their
  first open/close callers.
- Do not free TX LTBs again after a failed alloc_tx_resources();
  harden free_tx_ltb() against unset slots.
- Move TX allocation after RX IRQ setup / replenish kick so open()
  failure unwind no longer depends on a shared loop index (also fixes
  a mid-open TX LTB leak).

 drivers/net/ethernet/ibm/ibmveth.c | 90 ++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ibmveth.c 
b/drivers/net/ethernet/ibm/ibmveth.c
index 664169c4d27a..131c1a61d9e7 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1077,8 +1077,14 @@ static int ibmveth_rxq_harvest_buffer(struct 
ibmveth_adapter *adapter,
 
 static void ibmveth_free_tx_ltb(struct ibmveth_adapter *adapter, int idx)
 {
-       dma_unmap_single(&adapter->vdev->dev, adapter->tx_ltb_dma[idx],
-                        adapter->tx_ltb_size, DMA_TO_DEVICE);
+       if (!adapter->tx_ltb_ptr[idx])
+               return;
+
+       if (adapter->tx_ltb_dma[idx]) {
+               dma_unmap_single(&adapter->vdev->dev, adapter->tx_ltb_dma[idx],
+                                adapter->tx_ltb_size, DMA_TO_DEVICE);
+               adapter->tx_ltb_dma[idx] = 0;
+       }
        kfree(adapter->tx_ltb_ptr[idx]);
        adapter->tx_ltb_ptr[idx] = NULL;
 }
@@ -1101,12 +1107,54 @@ static int ibmveth_allocate_tx_ltb(struct 
ibmveth_adapter *adapter, int idx)
                           "unable to DMA map tx long term buffer\n");
                kfree(adapter->tx_ltb_ptr[idx]);
                adapter->tx_ltb_ptr[idx] = NULL;
+               adapter->tx_ltb_dma[idx] = 0;
                return -ENOMEM;
        }
 
        return 0;
 }
 
+/**
+ * ibmveth_alloc_tx_resources - Allocate TX resources for all queues
+ * @adapter: ibmveth adapter structure
+ *
+ * Allocates TX Long Term Buffers (LTBs) for all TX queues.
+ *
+ * Return: 0 on success, -ENOMEM on failure
+ */
+static int ibmveth_alloc_tx_resources(struct ibmveth_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       int i;
+
+       for (i = 0; i < netdev->real_num_tx_queues; i++) {
+               if (ibmveth_allocate_tx_ltb(adapter, i))
+                       goto err_free_ltbs;
+       }
+
+       return 0;
+
+err_free_ltbs:
+       while (--i >= 0)
+               ibmveth_free_tx_ltb(adapter, i);
+       return -ENOMEM;
+}
+
+/**
+ * ibmveth_free_tx_resources - Free TX resources for all queues
+ * @adapter: ibmveth adapter structure
+ *
+ * Frees TX Long Term Buffers (LTBs) for all TX queues.
+ */
+static void ibmveth_free_tx_resources(struct ibmveth_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       int i;
+
+       for (i = 0; i < netdev->real_num_tx_queues; i++)
+               ibmveth_free_tx_ltb(adapter, i);
+}
+
 static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
         union ibmveth_buf_desc rxq_desc, u64 mac_address)
 {
@@ -1157,12 +1205,6 @@ static int ibmveth_open(struct net_device *netdev)
        if (rc)
                goto out_free_filter_list;
 
-       rc = -ENOMEM;
-       for (i = 0; i < netdev->real_num_tx_queues; i++) {
-               if (ibmveth_allocate_tx_ltb(adapter, i))
-                       goto out_free_tx_ltb;
-       }
-
        mac_address = ether_addr_to_u64(netdev->dev_addr);
 
        rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
@@ -1184,35 +1226,38 @@ static int ibmveth_open(struct net_device *netdev)
                                     rxq_desc.desc,
                                     mac_address);
                rc = -ENONET;
-               goto out_free_tx_ltb;
+               goto out_free_queue_mem;
        }
 
        rc = ibmveth_alloc_buffer_pools(adapter);
        if (rc)
-               goto out_free_tx_ltb;
+               goto out_unregister_lan;
 
        rc = ibmveth_setup_rx_interrupts(adapter);
-       if (rc) {
-               do {
-                       lpar_rc = 
h_free_logical_lan(adapter->vdev->unit_address);
-               } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
-               goto out_free_buffer_pools;
-       }
+       if (rc)
+               goto out_unregister_lan;
 
        netdev_dbg(netdev, "initial replenish cycle\n");
        ibmveth_schedule_rx_queue(adapter, 0);
 
+       rc = ibmveth_alloc_tx_resources(adapter);
+       if (rc)
+               goto out_cleanup_rx_interrupts;
+
        netif_tx_start_all_queues(netdev);
 
        netdev_dbg(netdev, "open complete\n");
 
        return 0;
 
-out_free_buffer_pools:
+out_cleanup_rx_interrupts:
+       ibmveth_cleanup_rx_interrupts(adapter);
+out_unregister_lan:
+       do {
+               lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
+       } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
        ibmveth_free_buffer_pools(adapter);
-out_free_tx_ltb:
-       while (--i >= 0)
-               ibmveth_free_tx_ltb(adapter, i);
+out_free_queue_mem:
        ibmveth_cleanup_rx_resources(adapter);
 out_free_filter_list:
        ibmveth_free_filter_list(adapter);
@@ -1224,13 +1269,13 @@ static int ibmveth_close(struct net_device *netdev)
 {
        struct ibmveth_adapter *adapter = netdev_priv(netdev);
        long lpar_rc;
-       int i;
 
        netdev_dbg(netdev, "close starting\n");
 
        netif_tx_stop_all_queues(netdev);
 
        /* PHYP mask + napi_disable + free_irq live in cleanup_rx_interrupts */
+       ibmveth_free_tx_resources(adapter);
        ibmveth_cleanup_rx_interrupts(adapter);
 
        do {
@@ -1248,9 +1293,6 @@ static int ibmveth_close(struct net_device *netdev)
        ibmveth_cleanup_rx_resources(adapter);
        ibmveth_free_filter_list(adapter);
 
-       for (i = 0; i < netdev->real_num_tx_queues; i++)
-               ibmveth_free_tx_ltb(adapter, i);
-
        netdev_dbg(netdev, "close complete\n");
 
        return 0;
-- 
2.50.1 (Apple Git-155)


Reply via email to