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 <[email protected]>
Reviewed-by: Dave Marquardt <[email protected]>
Tested-by: Shaik Abdulla <[email protected]>
---
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)