When ibmveth_set_channels() cannot allocate a TX buffer for a new
queue, it falls back to the old queue count, and the successful
netif_set_real_num_tx_queues() call then overwrites rc. ethtool -L
reports success while the queue count is unchanged.

Return the allocation error when the fallback succeeds.

Found in review of the ibmveth multi-queue RX series and confirmed by
code inspection. Tested on a POWER10 LPAR with the TX buffer allocation
forced to fail by a test-only module parameter (not part of this patch):
ethtool -L tx 8 now fails with -ENOMEM and the device keeps its four
queues and passes traffic. No kernel selftests cover ibmveth.

Fixes: 10c2aba89cc0 ("ibmveth: Ethtool set queue support")
Signed-off-by: Mingming Cao <[email protected]>
---
 drivers/net/ethernet/ibm/ibmveth.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ibm/ibmveth.c 
b/drivers/net/ethernet/ibm/ibmveth.c
index 42aa9f7bd49d..48bc4406396b 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1177,7 +1177,7 @@ static int ibmveth_set_channels(struct net_device *netdev,
        struct ibmveth_adapter *adapter = netdev_priv(netdev);
        unsigned int old = netdev->real_num_tx_queues,
                     goal = channels->tx_count;
-       int rc, i;
+       int rc, i, alloc_rc = 0;
 
        /* If the device is not open (including a failed close/open with
         * IFF_UP still set) then don't allocate, just set desired
@@ -1203,6 +1203,7 @@ static int ibmveth_set_channels(struct net_device *netdev,
                /* if something goes wrong, free everything we just allocated */
                netdev_err(netdev, "Failed to allocate more tx queues, 
returning to %d queues\n",
                           old);
+               alloc_rc = rc;
                goal = old;
                old = i;
                break;
@@ -1213,6 +1214,8 @@ static int ibmveth_set_channels(struct net_device *netdev,
                           old);
                goal = old;
                old = i;
+       } else if (alloc_rc) {
+               rc = alloc_rc;
        }
        /* Free any that are no longer needed */
        for (i = old; i > goal; i--) {
-- 
2.50.1 (Apple Git-155)


Reply via email to