octeontx2-pf: Fix interface down flag on error
authorGeetha sowjanya <gakula@marvell.com>
Sun, 25 Jul 2021 07:59:03 +0000 (13:29 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Aug 2021 10:46:43 +0000 (12:46 +0200)
[ Upstream commit 69f0aeb13bb548e2d5710a350116e03f0273302e ]

In the existing code while changing the number of TX/RX
queues using ethtool the PF/VF interface resources are
freed and reallocated (otx2_stop and otx2_open is called)
if the device is in running state. If any resource allocation
fails in otx2_open, driver free already allocated resources
and return. But again, when the number of queues changes
as the device state still running oxt2_stop is called.
In which we try to free already freed resources leading
to driver crash.
This patch fixes the issue by setting the INTF_DOWN flag on
error and free the resources in otx2_stop only if the flag is
not set.

Fixes: 50fe6c02e5ad ("octeontx2-pf: Register and handle link notifications")
Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <Sunil.Goutham@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c

index 662fb80dbb9d5c3b1ec1299da53cf1577bc435c4..c6d408de06050ea673809556b777d20beb463a97 100644 (file)
@@ -230,15 +230,14 @@ static int otx2_set_channels(struct net_device *dev,
        err = otx2_set_real_num_queues(dev, channel->tx_count,
                                       channel->rx_count);
        if (err)
-               goto fail;
+               return err;
 
        pfvf->hw.rx_queues = channel->rx_count;
        pfvf->hw.tx_queues = channel->tx_count;
        pfvf->qset.cq_cnt = pfvf->hw.tx_queues +  pfvf->hw.rx_queues;
 
-fail:
        if (if_up)
-               dev->netdev_ops->ndo_open(dev);
+               err = dev->netdev_ops->ndo_open(dev);
 
        netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
                    pfvf->hw.tx_queues, pfvf->hw.rx_queues);
@@ -342,7 +341,7 @@ static int otx2_set_ringparam(struct net_device *netdev,
        qs->rqe_cnt = rx_count;
 
        if (if_up)
-               netdev->netdev_ops->ndo_open(netdev);
+               return netdev->netdev_ops->ndo_open(netdev);
 
        return 0;
 }
index 9fef9be015e5e793e52965e1181eb5c68dd93ba7..044a5b1196acbc2515b788cedeb4d16dbee79879 100644 (file)
@@ -1592,6 +1592,7 @@ int otx2_open(struct net_device *netdev)
 err_tx_stop_queues:
        netif_tx_stop_all_queues(netdev);
        netif_carrier_off(netdev);
+       pf->flags |= OTX2_FLAG_INTF_DOWN;
 err_free_cints:
        otx2_free_cints(pf, qidx);
        vec = pci_irq_vector(pf->pdev,
@@ -1619,6 +1620,10 @@ int otx2_stop(struct net_device *netdev)
        struct otx2_rss_info *rss;
        int qidx, vec, wrk;
 
+       /* If the DOWN flag is set resources are already freed */
+       if (pf->flags & OTX2_FLAG_INTF_DOWN)
+               return 0;
+
        netif_carrier_off(netdev);
        netif_tx_stop_all_queues(netdev);