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 Reviewed-by: Dave Marquardt --- 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)