bnxt_en: fix the handling of PCIE-AER
Fix the sequence required for PCIE-AER. While slot reset occurs, firmware
might not be ready and the driver needs to check for its recovery. We
also need to remap the health registers for some chips and clear the
resource reservations. The resources will be allocated again during
bnxt_io_resume().
Fixes: fb1e6e562b
("bnxt_en: Fix AER recovery.")
Signed-off-by: Vikas Gupta <vikas.gupta@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
b4c6642577
commit
0cf736a18a
@@ -13922,7 +13922,9 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
|
|||||||
pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
|
pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
|
||||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||||
struct bnxt *bp = netdev_priv(netdev);
|
struct bnxt *bp = netdev_priv(netdev);
|
||||||
int err = 0, off;
|
int retry = 0;
|
||||||
|
int err = 0;
|
||||||
|
int off;
|
||||||
|
|
||||||
netdev_info(bp->dev, "PCI Slot Reset\n");
|
netdev_info(bp->dev, "PCI Slot Reset\n");
|
||||||
|
|
||||||
@@ -13950,11 +13952,36 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
|
|||||||
pci_restore_state(pdev);
|
pci_restore_state(pdev);
|
||||||
pci_save_state(pdev);
|
pci_save_state(pdev);
|
||||||
|
|
||||||
|
bnxt_inv_fw_health_reg(bp);
|
||||||
|
bnxt_try_map_fw_health_reg(bp);
|
||||||
|
|
||||||
|
/* In some PCIe AER scenarios, firmware may take up to
|
||||||
|
* 10 seconds to become ready in the worst case.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
err = bnxt_try_recover_fw(bp);
|
||||||
|
if (!err)
|
||||||
|
break;
|
||||||
|
retry++;
|
||||||
|
} while (retry < BNXT_FW_SLOT_RESET_RETRY);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
dev_err(&pdev->dev, "Firmware not ready\n");
|
||||||
|
goto reset_exit;
|
||||||
|
}
|
||||||
|
|
||||||
err = bnxt_hwrm_func_reset(bp);
|
err = bnxt_hwrm_func_reset(bp);
|
||||||
if (!err)
|
if (!err)
|
||||||
result = PCI_ERS_RESULT_RECOVERED;
|
result = PCI_ERS_RESULT_RECOVERED;
|
||||||
|
|
||||||
|
bnxt_ulp_irq_stop(bp);
|
||||||
|
bnxt_clear_int_mode(bp);
|
||||||
|
err = bnxt_init_int_mode(bp);
|
||||||
|
bnxt_ulp_irq_restart(bp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_exit:
|
||||||
|
bnxt_clear_reservations(bp, true);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@@ -1621,6 +1621,7 @@ struct bnxt_fw_health {
|
|||||||
|
|
||||||
#define BNXT_FW_RETRY 5
|
#define BNXT_FW_RETRY 5
|
||||||
#define BNXT_FW_IF_RETRY 10
|
#define BNXT_FW_IF_RETRY 10
|
||||||
|
#define BNXT_FW_SLOT_RESET_RETRY 4
|
||||||
|
|
||||||
enum board_idx {
|
enum board_idx {
|
||||||
BCM57301,
|
BCM57301,
|
||||||
|
@@ -476,7 +476,8 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx)
|
|||||||
memset(ctx->resp, 0, PAGE_SIZE);
|
memset(ctx->resp, 0, PAGE_SIZE);
|
||||||
|
|
||||||
req_type = le16_to_cpu(ctx->req->req_type);
|
req_type = le16_to_cpu(ctx->req->req_type);
|
||||||
if (BNXT_NO_FW_ACCESS(bp) && req_type != HWRM_FUNC_RESET) {
|
if (BNXT_NO_FW_ACCESS(bp) &&
|
||||||
|
(req_type != HWRM_FUNC_RESET && req_type != HWRM_VER_GET)) {
|
||||||
netdev_dbg(bp->dev, "hwrm req_type 0x%x skipped, FW channel down\n",
|
netdev_dbg(bp->dev, "hwrm req_type 0x%x skipped, FW channel down\n",
|
||||||
req_type);
|
req_type);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
Reference in New Issue
Block a user