Thomas Bogendoerfer 27f47f
From: Vikas Gupta <vikas.gupta@broadcom.com>
Thomas Bogendoerfer 27f47f
Date: Thu, 3 Nov 2022 19:33:25 -0400
Thomas Bogendoerfer 27f47f
Subject: bnxt_en: fix the handling of PCIE-AER
Thomas Bogendoerfer 27f47f
Patch-mainline: v6.1-rc5
Thomas Bogendoerfer 27f47f
Git-commit: 0cf736a18a1e804037839bd8df9e36f0efdb8745
Thomas Bogendoerfer 27f47f
References: git-fixes
Thomas Bogendoerfer 27f47f
Thomas Bogendoerfer 27f47f
Fix the sequence required for PCIE-AER. While slot reset occurs, firmware
Thomas Bogendoerfer 27f47f
might not be ready and the driver needs to check for its recovery.  We
Thomas Bogendoerfer 27f47f
also need to remap the health registers for some chips and clear the
Thomas Bogendoerfer 27f47f
resource reservations.  The resources will be allocated again during
Thomas Bogendoerfer 27f47f
bnxt_io_resume().
Thomas Bogendoerfer 27f47f
Thomas Bogendoerfer 27f47f
Fixes: fb1e6e562b37 ("bnxt_en: Fix AER recovery.")
Thomas Bogendoerfer 27f47f
Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com>
Thomas Bogendoerfer 27f47f
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Thomas Bogendoerfer 27f47f
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Thomas Bogendoerfer 27f47f
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Thomas Bogendoerfer 27f47f
---
Thomas Bogendoerfer 27f47f
 drivers/net/ethernet/broadcom/bnxt/bnxt.c      |   29 ++++++++++++++++++++++++-
Thomas Bogendoerfer 27f47f
 drivers/net/ethernet/broadcom/bnxt/bnxt.h      |    1 
Thomas Bogendoerfer 27f47f
 drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c |    3 +-
Thomas Bogendoerfer 27f47f
 3 files changed, 31 insertions(+), 2 deletions(-)
Thomas Bogendoerfer 27f47f
Thomas Bogendoerfer 27f47f
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
Thomas Bogendoerfer 27f47f
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
Thomas Bogendoerfer 27f47f
@@ -13687,7 +13687,9 @@ static pci_ers_result_t bnxt_io_slot_res
Thomas Bogendoerfer 27f47f
 	pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
Thomas Bogendoerfer 27f47f
 	struct net_device *netdev = pci_get_drvdata(pdev);
Thomas Bogendoerfer 27f47f
 	struct bnxt *bp = netdev_priv(netdev);
Thomas Bogendoerfer 27f47f
-	int err = 0, off;
Thomas Bogendoerfer 27f47f
+	int retry = 0;
Thomas Bogendoerfer 27f47f
+	int err = 0;
Thomas Bogendoerfer 27f47f
+	int off;
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
 	netdev_info(bp->dev, "PCI Slot Reset\n");
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
@@ -13715,11 +13717,36 @@ static pci_ers_result_t bnxt_io_slot_res
Thomas Bogendoerfer 27f47f
 		pci_restore_state(pdev);
Thomas Bogendoerfer 27f47f
 		pci_save_state(pdev);
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
+		bnxt_inv_fw_health_reg(bp);
Thomas Bogendoerfer 27f47f
+		bnxt_try_map_fw_health_reg(bp);
Thomas Bogendoerfer 27f47f
+
Thomas Bogendoerfer 27f47f
+		/* In some PCIe AER scenarios, firmware may take up to
Thomas Bogendoerfer 27f47f
+		 * 10 seconds to become ready in the worst case.
Thomas Bogendoerfer 27f47f
+		 */
Thomas Bogendoerfer 27f47f
+		do {
Thomas Bogendoerfer 27f47f
+			err = bnxt_try_recover_fw(bp);
Thomas Bogendoerfer 27f47f
+			if (!err)
Thomas Bogendoerfer 27f47f
+				break;
Thomas Bogendoerfer 27f47f
+			retry++;
Thomas Bogendoerfer 27f47f
+		} while (retry < BNXT_FW_SLOT_RESET_RETRY);
Thomas Bogendoerfer 27f47f
+
Thomas Bogendoerfer 27f47f
+		if (err) {
Thomas Bogendoerfer 27f47f
+			dev_err(&pdev->dev, "Firmware not ready\n");
Thomas Bogendoerfer 27f47f
+			goto reset_exit;
Thomas Bogendoerfer 27f47f
+		}
Thomas Bogendoerfer 27f47f
+
Thomas Bogendoerfer 27f47f
 		err = bnxt_hwrm_func_reset(bp);
Thomas Bogendoerfer 27f47f
 		if (!err)
Thomas Bogendoerfer 27f47f
 			result = PCI_ERS_RESULT_RECOVERED;
Thomas Bogendoerfer 27f47f
+
Thomas Bogendoerfer 27f47f
+		bnxt_ulp_irq_stop(bp);
Thomas Bogendoerfer 27f47f
+		bnxt_clear_int_mode(bp);
Thomas Bogendoerfer 27f47f
+		err = bnxt_init_int_mode(bp);
Thomas Bogendoerfer 27f47f
+		bnxt_ulp_irq_restart(bp, err);
Thomas Bogendoerfer 27f47f
 	}
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
+reset_exit:
Thomas Bogendoerfer 27f47f
+	bnxt_clear_reservations(bp, true);
Thomas Bogendoerfer 27f47f
 	rtnl_unlock();
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
 	return result;
Thomas Bogendoerfer 27f47f
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
Thomas Bogendoerfer 27f47f
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
Thomas Bogendoerfer 27f47f
@@ -1615,6 +1615,7 @@ struct bnxt_fw_health {
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
 #define BNXT_FW_RETRY			5
Thomas Bogendoerfer 27f47f
 #define BNXT_FW_IF_RETRY		10
Thomas Bogendoerfer 27f47f
+#define BNXT_FW_SLOT_RESET_RETRY	4
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
 enum board_idx {
Thomas Bogendoerfer 27f47f
 	BCM57301,
Thomas Bogendoerfer 27f47f
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
Thomas Bogendoerfer 27f47f
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
Thomas Bogendoerfer 27f47f
@@ -462,7 +462,8 @@ static int __hwrm_send(struct bnxt *bp,
Thomas Bogendoerfer 27f47f
 		memset(ctx->resp, 0, PAGE_SIZE);
Thomas Bogendoerfer 27f47f
 
Thomas Bogendoerfer 27f47f
 	req_type = le16_to_cpu(ctx->req->req_type);
Thomas Bogendoerfer 27f47f
-	if (BNXT_NO_FW_ACCESS(bp) && req_type != HWRM_FUNC_RESET) {
Thomas Bogendoerfer 27f47f
+	if (BNXT_NO_FW_ACCESS(bp) &&
Thomas Bogendoerfer 27f47f
+	    (req_type != HWRM_FUNC_RESET && req_type != HWRM_VER_GET)) {
Thomas Bogendoerfer 27f47f
 		netdev_dbg(bp->dev, "hwrm req_type 0x%x skipped, FW channel down\n",
Thomas Bogendoerfer 27f47f
 			   req_type);
Thomas Bogendoerfer 27f47f
 		goto exit;