ibmveth_open() allocates the filter list and every RX queue inline.
That's already ~160 lines and would get ugly once we loop over
num_rx_queues, especially on error unwind.

Pull the RX bits into helpers:

  ibmveth_alloc_filter_list() / ibmveth_free_filter_list()
    — shared multicast filter list (one per adapter, not per queue)

  ibmveth_alloc_rx_queues() / ibmveth_cleanup_rx_resources()
    — per-queue buffer lists and RX rings, looping [0, num_rx_queues)

alloc_rx_queues() rolls back on failure so open() does not need nested
goto chains for every queue index.

This is the first of several helper-only patches (pools, IRQ, TX, PHYP
registration, open/close wiring, buffer submit) that reshape bring-up
ahead of MQ datapath commit later in the series.

Signed-off-by: Mingming Cao <[email protected]>
Reviewed-by: Dave Marquardt <[email protected]>
---
 drivers/net/ethernet/ibm/ibmveth.c | 168 +++++++++++++++++++++++++++++
 1 file changed, 168 insertions(+)

diff --git a/drivers/net/ethernet/ibm/ibmveth.c 
b/drivers/net/ethernet/ibm/ibmveth.c
index 8f9f927bff23..b8adc9935471 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -147,6 +147,174 @@ static unsigned int ibmveth_real_max_tx_queues(void)
        return min(n_cpu, IBMVETH_MAX_QUEUES);
 }
 
+/**
+ * ibmveth_alloc_filter_list - Allocate and map filter list
+ * @adapter: ibmveth adapter structure
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int __maybe_unused ibmveth_alloc_filter_list(struct ibmveth_adapter 
*adapter)
+{
+       struct device *dev = &adapter->vdev->dev;
+       struct net_device *netdev = adapter->netdev;
+
+       adapter->filter_list_addr = (void *)get_zeroed_page(GFP_KERNEL);
+       if (!adapter->filter_list_addr) {
+               netdev_err(netdev, "unable to allocate filter pages\n");
+               return -ENOMEM;
+       }
+
+       adapter->filter_list_dma = dma_map_single(dev,
+                                                 adapter->filter_list_addr,
+                                                 4096, DMA_BIDIRECTIONAL);
+       if (dma_mapping_error(dev, adapter->filter_list_dma)) {
+               netdev_err(netdev, "unable to map filter list pages\n");
+               free_page((unsigned long)adapter->filter_list_addr);
+               adapter->filter_list_addr = NULL;
+               return -ENOMEM;
+       }
+
+       netdev_dbg(netdev, "filter list @ 0x%p (DMA: 0x%llx)\n",
+                  adapter->filter_list_addr,
+                  (unsigned long long)adapter->filter_list_dma);
+
+       return 0;
+}
+
+/**
+ * ibmveth_free_filter_list - Free filter list resources
+ * @adapter: ibmveth adapter structure
+ */
+static void __maybe_unused ibmveth_free_filter_list(struct ibmveth_adapter 
*adapter)
+{
+       struct device *dev = &adapter->vdev->dev;
+
+       if (adapter->filter_list_dma) {
+               dma_unmap_single(dev, adapter->filter_list_dma, 4096,
+                                DMA_BIDIRECTIONAL);
+               adapter->filter_list_dma = 0;
+       }
+
+       if (adapter->filter_list_addr) {
+               free_page((unsigned long)adapter->filter_list_addr);
+               adapter->filter_list_addr = NULL;
+       }
+}
+
+/**
+ * ibmveth_alloc_rx_queues - Allocate per-queue RX resources
+ * @adapter: ibmveth adapter structure
+ * @rxq_entries: Number of entries per RX queue
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int __maybe_unused
+ibmveth_alloc_rx_queues(struct ibmveth_adapter *adapter, int rxq_entries)
+{
+       struct device *dev = &adapter->vdev->dev;
+       struct net_device *netdev = adapter->netdev;
+       int i;
+
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               adapter->buffer_list_addr[i] = (void 
*)get_zeroed_page(GFP_KERNEL);
+               if (!adapter->buffer_list_addr[i]) {
+                       netdev_err(netdev, "unable to allocate buffer list for 
queue %d\n", i);
+                       goto err_cleanup;
+               }
+
+               adapter->rx_queue[i].queue_len =
+                       sizeof(struct ibmveth_rx_q_entry) * rxq_entries;
+               adapter->rx_queue[i].queue_addr =
+                       dma_alloc_coherent(dev, adapter->rx_queue[i].queue_len,
+                                          &adapter->rx_queue[i].queue_dma,
+                                          GFP_KERNEL);
+               if (!adapter->rx_queue[i].queue_addr) {
+                       netdev_err(netdev, "unable to allocate RX queue for 
queue %d\n", i);
+                       goto err_cleanup;
+               }
+
+               adapter->buffer_list_dma[i] = dma_map_single(dev,
+                                                            
adapter->buffer_list_addr[i],
+                                                            4096, 
DMA_BIDIRECTIONAL);
+               if (dma_mapping_error(dev, adapter->buffer_list_dma[i])) {
+                       netdev_err(netdev, "unable to map buffer list for queue 
%d\n", i);
+                       adapter->buffer_list_dma[i] = 0;
+                       goto err_cleanup;
+               }
+
+               adapter->rx_queue[i].index = 0;
+               adapter->rx_queue[i].num_slots = rxq_entries;
+               adapter->rx_queue[i].toggle = 1;
+
+               netdev_dbg(netdev, "queue %d: buffer_list @ 0x%p (DMA: 0x%llx), 
rx_queue @ 0x%p (DMA: 0x%llx), %llu entries\n",
+                          i, adapter->buffer_list_addr[i],
+                          (unsigned long long)adapter->buffer_list_dma[i],
+                          adapter->rx_queue[i].queue_addr,
+                          (unsigned long long)adapter->rx_queue[i].queue_dma,
+                          (unsigned long long)rxq_entries);
+       }
+
+       netdev_dbg(netdev, "allocated %d RX queue(s) with %d entries each\n",
+                  adapter->num_rx_queues, rxq_entries);
+
+       return 0;
+
+err_cleanup:
+       /* Clean up previously allocated queues */
+       for (; i >= 0; i--) {
+               if (adapter->buffer_list_dma[i]) {
+                       dma_unmap_single(dev, adapter->buffer_list_dma[i],
+                                        4096, DMA_BIDIRECTIONAL);
+                       adapter->buffer_list_dma[i] = 0;
+               }
+               if (adapter->rx_queue[i].queue_addr) {
+                       dma_free_coherent(dev, adapter->rx_queue[i].queue_len,
+                                         adapter->rx_queue[i].queue_addr,
+                                         adapter->rx_queue[i].queue_dma);
+                       adapter->rx_queue[i].queue_addr = NULL;
+               }
+               if (adapter->buffer_list_addr[i]) {
+                       free_page((unsigned long)adapter->buffer_list_addr[i]);
+                       adapter->buffer_list_addr[i] = NULL;
+               }
+       }
+
+       return -ENOMEM;
+}
+
+/**
+ * ibmveth_cleanup_rx_resources - Free all RX queue resources
+ * @adapter: ibmveth adapter structure
+ */
+static void __maybe_unused ibmveth_cleanup_rx_resources(struct ibmveth_adapter 
*adapter)
+{
+       struct device *dev = &adapter->vdev->dev;
+       int i;
+
+       netdev_dbg(adapter->netdev, "cleaning up %d RX queue(s)\n",
+                  adapter->num_rx_queues);
+
+       for (i = 0; i < adapter->num_rx_queues; i++) {
+               if (adapter->buffer_list_dma[i]) {
+                       dma_unmap_single(dev, adapter->buffer_list_dma[i],
+                                        4096, DMA_BIDIRECTIONAL);
+                       adapter->buffer_list_dma[i] = 0;
+               }
+
+               if (adapter->rx_queue[i].queue_addr) {
+                       dma_free_coherent(dev, adapter->rx_queue[i].queue_len,
+                                         adapter->rx_queue[i].queue_addr,
+                                         adapter->rx_queue[i].queue_dma);
+                       adapter->rx_queue[i].queue_addr = NULL;
+               }
+
+               if (adapter->buffer_list_addr[i]) {
+                       free_page((unsigned long)adapter->buffer_list_addr[i]);
+                       adapter->buffer_list_addr[i] = NULL;
+               }
+       }
+}
+
 /* setup the initial settings for a buffer pool */
 static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool,
                                     u32 pool_index, u32 pool_size,
-- 
2.39.3 (Apple Git-146)


Reply via email to