bnxt_en: Fix possible BUG() condition when calling pci_disable_msix(). [Linux 5.2]

bnxt_en: Fix possible BUG() condition when calling pci_disable_msix(). [Linux 5.2]

This Linux kernel change "bnxt_en: Fix possible BUG() condition when calling pci_disable_msix()" is included in the Linux 5.2 release. This change is authored by Michael Chan <michael.chan [at] broadcom.com> on Wed May 22 19:12:55 2019 -0400. The commit for this change in Linux stable tree is 1b3f0b7 (patch).

bnxt_en: Fix possible BUG() condition when calling pci_disable_msix().

When making configuration changes, the driver calls bnxt_close_nic()
and then bnxt_open_nic() for the changes to take effect.  A parameter
irq_re_init is passed to the call sequence to indicate if IRQ
should be re-initialized.  This irq_re_init parameter needs to
be included in the bnxt_reserve_rings() call.  bnxt_reserve_rings()
can only call pci_disable_msix() if the irq_re_init parameter is
true, otherwise it may hit BUG() because some IRQs may not have been
freed yet.

Fixes: 41e8d7983752 ("bnxt_en: Modify the ring reservation functions for 57500 series chips.")
Signed-off-by: Michael Chan <[email protected]>
Signed-off-by: David S. Miller <[email protected]>

There are 19 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/ethernet/broadcom/bnxt/bnxt.c         | 13 +++++++------
 drivers/net/ethernet/broadcom/bnxt/bnxt.h         |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c |  2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c     |  2 +-
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 21f6826..cfcc33c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -7618,22 +7618,23 @@ static void bnxt_clear_int_mode(struct bnxt *bp)
    bp->flags &= ~BNXT_FLAG_USING_MSIX;
 }

-int bnxt_reserve_rings(struct bnxt *bp)
+int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
 {
    int tcs = netdev_get_num_tc(bp->dev);
-   bool reinit_irq = false;
+   bool irq_cleared = false;
    int rc;

    if (!bnxt_need_reserve_rings(bp))
        return 0;

-   if (BNXT_NEW_RM(bp) && (bnxt_get_num_msix(bp) != bp->total_irqs)) {
+   if (irq_re_init && BNXT_NEW_RM(bp) &&
+       bnxt_get_num_msix(bp) != bp->total_irqs) {
        bnxt_ulp_irq_stop(bp);
        bnxt_clear_int_mode(bp);
-       reinit_irq = true;
+       irq_cleared = true;
    }
    rc = __bnxt_reserve_rings(bp);
-   if (reinit_irq) {
+   if (irq_cleared) {
        if (!rc)
            rc = bnxt_init_int_mode(bp);
        bnxt_ulp_irq_restart(bp, rc);
@@ -8532,7 +8533,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
            return rc;
        }
    }
-   rc = bnxt_reserve_rings(bp);
+   rc = bnxt_reserve_rings(bp, irq_re_init);
    if (rc)
        return rc;
    if ((bp->flags & BNXT_FLAG_RFS) &&
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index eca36dd..acc73f3 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1790,7 +1790,7 @@ int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
 unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp);
 unsigned int bnxt_get_avail_cp_rings_for_en(struct bnxt *bp);
 int bnxt_get_avail_msix(struct bnxt *bp, int num);
-int bnxt_reserve_rings(struct bnxt *bp);
+int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init);
 void bnxt_tx_disable(struct bnxt *bp);
 void bnxt_tx_enable(struct bnxt *bp);
 int bnxt_hwrm_set_pause(struct bnxt *);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index b126382..a6c7baf 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -831,7 +831,7 @@ static int bnxt_set_channels(struct net_device *dev,
             */
        }
    } else {
-       rc = bnxt_reserve_rings(bp);
+       rc = bnxt_reserve_rings(bp, true);
    }

    return rc;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
index cf47587..bfa342a 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
@@ -147,7 +147,7 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
            bnxt_close_nic(bp, true, false);
            rc = bnxt_open_nic(bp, true, false);
        } else {
-           rc = bnxt_reserve_rings(bp);
+           rc = bnxt_reserve_rings(bp, true);
        }
    }
    if (rc) {

Leave a Reply

Your email address will not be published. Required fields are marked *