Expose incremental RX resize through ethtool channel control.

get_channels() reports rx_count from adapter->num_rx_queues and max_rx
as IBMVETH_MAX_RX_QUEUES when MQ firmware is enabled, else 1.

set_channels() validates rx_count is within 1..IBMVETH_MAX_RX_QUEUES.
When rx_count changes and the interface is up, call
ibmveth_resize_rx_queues_incremental(). When the interface is down,
store the requested rx_count in adapter->num_rx_queues so the next open
registers that many queues. Non-MQ firmware returns -EOPNOTSUPP for
rx > 1.

TX queue changes keep existing stop/wake behavior when tx_count changes.

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

diff --git a/drivers/net/ethernet/ibm/ibmveth.c 
b/drivers/net/ethernet/ibm/ibmveth.c
index ac4d89a66a8d..50a332ab83fd 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -2534,19 +2534,69 @@ static int ibmveth_set_channels(struct net_device 
*netdev,
                                struct ethtool_channels *channels)
 {
        struct ibmveth_adapter *adapter = netdev_priv(netdev);
-       unsigned int old = netdev->real_num_tx_queues,
-                    goal = channels->tx_count;
+       unsigned int old_rx = adapter->num_rx_queues;
+       unsigned int goal_rx = channels->rx_count;
+       unsigned int old = netdev->real_num_tx_queues;
+       unsigned int goal = channels->tx_count;
+       int rxq_entries = adapter->rx_queue[0].num_slots;
        int rc, i;
 
        /* If ndo_open has not been called yet then don't allocate, just set
         * desired netdev_queue's and return
         */
-       if (!(netdev->flags & IFF_UP))
+       if (!(netdev->flags & IFF_UP)) {
+               if (goal_rx > 1 && !adapter->multi_queue) {
+                       netdev_err(netdev,
+                                  "Cannot resize to %u RX queues: multi-queue 
mode not supported by firmware\n",
+                                  goal_rx);
+                       return -EOPNOTSUPP;
+               }
+
+               if (goal_rx < 1 || goal_rx > IBMVETH_MAX_RX_QUEUES) {
+                       netdev_err(netdev,
+                                  "Invalid RX queue count %u (must be 1-%d)\n",
+                                  goal_rx, IBMVETH_MAX_RX_QUEUES);
+                       return -EINVAL;
+               }
+
+               /* Stash desired RX count; open() publishes it via
+                * netif_set_real_num_rx_queues() after queue registration.
+                */
+               if (goal_rx != adapter->num_rx_queues)
+                       adapter->num_rx_queues = goal_rx;
+
                return netif_set_real_num_tx_queues(netdev, goal);
+       }
+
+       if (goal_rx > 1 && !adapter->multi_queue) {
+               netdev_err(netdev,
+                          "Cannot resize to %u RX queues: multi-queue mode not 
supported by firmware\n",
+                          goal_rx);
+               return -EOPNOTSUPP;
+       }
+
+       if (goal_rx < 1 || goal_rx > IBMVETH_MAX_RX_QUEUES) {
+               netdev_err(netdev,
+                          "Invalid RX queue count %u (must be 1-%d)\n",
+                          goal_rx, IBMVETH_MAX_RX_QUEUES);
+               return -EINVAL;
+       }
+
+       if (goal_rx != old_rx) {
+               rc = ibmveth_resize_rx_queues_incremental(adapter, goal_rx,
+                                                         rxq_entries);
+               if (rc) {
+                       netdev_err(netdev, "Failed to resize RX queues: %d\n", 
rc);
+                       return rc;
+               }
+       }
 
        /* We have IBMVETH_MAX_QUEUES netdev_queue's allocated
         * but we may need to alloc/free the ltb's.
         */
+       if (goal == old)
+               return 0;
+
        netif_tx_stop_all_queues(netdev);
 
        /* Allocate any queue that we need */
@@ -2580,7 +2630,7 @@ static int ibmveth_set_channels(struct net_device *netdev,
 
        netif_tx_wake_all_queues(netdev);
 
-       return rc;
+       return 0;
 }
 
 static const struct ethtool_ops netdev_ethtool_ops = {
-- 
2.39.3 (Apple Git-146)


Reply via email to