Complete set_channels() RX handling around ibmveth_resize_rx_channels(): - When the interface is down: set TX queues first, then stash the desired RX count in adapter->num_rx_queues for the next open() (open publishes via netif_set_real_num_rx_queues). While down there are no RX queue mappings, buffers, or IRQs to grow or shrink, so do not allocate immediately. - When up: resize RX via ibmveth_resize_rx_channels(), then adjust TX LTBs with the existing stop/alloc/set_real_num_tx/free/wake path. - Non-MQ firmware returns -EOPNOTSUPP for rx > 1. - Validate rx_count within 1..IBMVETH_MAX_RX_QUEUES. TX path hardening: - Initialize i = old_tx so a scale-down path that never enters the alloc loop still has defined bounds if set_real_num_tx_queues() fails. - Always return rc from set_channels(). Signed-off-by: Mingming Cao Reviewed-by: Dave Marquardt Tested-by: Shaik Abdulla --- Changes in v4: - On !IFF_UP, stash num_rx_queues only after TX set succeeds; do not allocate live subordinate IRQs/buffers while down. - Initialize i = old_tx on the TX adjust path. - Always return rc from set_channels(). - Split from the resize-helper patch (same split as v3) while keeping a live caller of resize_rx_channels() in the previous patch. drivers/net/ethernet/ibm/ibmveth.c | 51 ++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index b57c7df92853..c99d8e8be7b3 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -2723,20 +2723,28 @@ 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 goal_rx = channels->rx_count; + unsigned int old_tx = netdev->real_num_tx_queues; + unsigned int goal_tx = channels->tx_count; 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)) - return netif_set_real_num_tx_queues(netdev, goal); + if (!(netdev->flags & IFF_UP)) { + if (goal_tx != old_tx) { + rc = netif_set_real_num_tx_queues(netdev, goal_tx); + if (rc) + return rc; + } + + /* Stash desired RX count only after TX succeeds (or was + * already correct); open() publishes it via + * netif_set_real_num_rx_queues(). + */ + return ibmveth_resize_rx_channels(adapter, goal_rx); + } - /* Resize RX first while UP so ibmveth_resize_rx_channels() is used - * in this patch. !IFF_UP RX stash ordering lands next. - */ rc = ibmveth_resize_rx_channels(adapter, goal_rx); if (rc) return rc; @@ -2744,10 +2752,17 @@ static int ibmveth_set_channels(struct net_device *netdev, /* We have IBMVETH_MAX_QUEUES netdev_queue's allocated * but we may need to alloc/free the ltb's. */ + if (goal_tx == old_tx) + return 0; + netif_tx_stop_all_queues(netdev); - /* Allocate any queue that we need */ - for (i = old; i < goal; i++) { + /* Allocate any queue that we need. Initialize i to old_tx so a + * scale-down path that never enters the loop still has defined + * bounds if set_real_num_tx_queues() fails. + */ + i = old_tx; + for (; i < goal_tx; i++) { if (adapter->tx_ltb_ptr[i]) continue; @@ -2755,20 +2770,22 @@ static int ibmveth_set_channels(struct net_device *netdev, if (!rc) continue; + /* if something goes wrong, free everything we just allocated */ netdev_err(netdev, "Failed to allocate more tx queues, returning to %d queues\n", - old); - goal = old; - old = i; + old_tx); + goal_tx = old_tx; + old_tx = i; break; } - rc = netif_set_real_num_tx_queues(netdev, goal); + rc = netif_set_real_num_tx_queues(netdev, goal_tx); if (rc) { netdev_err(netdev, "Failed to set real tx queues, returning to %d queues\n", - old); - goal = old; - old = i; + old_tx); + goal_tx = old_tx; + old_tx = i; } - for (i = old; i > goal; i--) { + /* Free any that are no longer needed */ + for (i = old_tx; i > goal_tx; i--) { if (adapter->tx_ltb_ptr[i - 1]) ibmveth_free_tx_ltb(adapter, i - 1); } -- 2.50.1 (Apple Git-155)