From a10d58b1feaebcd74c4c1c0d2247c742a8d704e7 Mon Sep 17 00:00:00 2001 From: Jonathan Toppins Date: Wed, 2 Oct 2019 18:23:39 -0400 Subject: [PATCH 84/96] [netdrv] bnxt_en: Add a new BNXT_FW_RESET_STATE_POLL_FW_DOWN state Message-id: Patchwork-id: 276502 O-Subject: [RHEL-8.2 PATCH 77/78] bnxt_en: Add a new BNXT_FW_RESET_STATE_POLL_FW_DOWN state. Bugzilla: 1724766 RH-Acked-by: John Linville RH-Acked-by: Jarod Wilson This new state is required when firmware indicates that the error recovery process requires polling for firmware state to be completely down before initiating reset. For example, firmware may take some time to collect the crash dump before it is down and ready to be reset. Signed-off-by: Vasundhara Volam Signed-off-by: Michael Chan Signed-off-by: David S. Miller (cherry picked from commit 4037eb715680caa3d80075fb54dbc35d79d5f9ff) Bugzilla: 1724766 Build Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23809532 Tested: build, boot, basic ping Signed-off-by: Jonathan Toppins Signed-off-by: Bruno Meneguele --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 48 +++++++++++++++++++++++++++---- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 3 ++ 2 files changed, 46 insertions(+), 5 deletions(-) Index: src/drivers/net/ethernet/broadcom/bnxt/bnxt.c =================================================================== --- src.orig/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2020-02-06 16:23:21.286461969 +0100 +++ src/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2020-02-06 16:23:21.672458426 +0100 @@ -6952,6 +6952,8 @@ bp->fw_cap |= BNXT_FW_CAP_EXT_STATS_SUPPORTED; if (flags & FUNC_QCAPS_RESP_FLAGS_ERROR_RECOVERY_CAPABLE) bp->fw_cap |= BNXT_FW_CAP_ERROR_RECOVERY; + if (flags & FUNC_QCAPS_RESP_FLAGS_ERR_RECOVER_RELOAD) + bp->fw_cap |= BNXT_FW_CAP_ERR_RECOVER_RELOAD; bp->tx_push_thresh = 0; if (flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) @@ -10102,6 +10104,8 @@ wait_dsecs = fw_health->normal_func_wait_dsecs; bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; } + + bp->fw_reset_min_dsecs = fw_health->post_reset_wait_dsecs; bp->fw_reset_max_dsecs = fw_health->post_reset_max_wait_dsecs; bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10); } @@ -10143,7 +10147,7 @@ bnxt_rtnl_lock_sp(bp); if (test_bit(BNXT_STATE_OPEN, &bp->state) && !test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) { - int n = 0; + int n = 0, tmo; set_bit(BNXT_STATE_IN_FW_RESET, &bp->state); if (bp->pf.active_vfs && @@ -10166,8 +10170,14 @@ goto fw_reset_exit; } bnxt_fw_reset_close(bp); - bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; - bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10); + if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) { + bp->fw_reset_state = BNXT_FW_RESET_STATE_POLL_FW_DOWN; + tmo = HZ / 10; + } else { + bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + tmo = bp->fw_reset_min_dsecs * HZ / 10; + } + bnxt_queue_fw_reset_work(bp, tmo); } fw_reset_exit: bnxt_rtnl_unlock_sp(bp); @@ -10610,6 +10620,7 @@ switch (bp->fw_reset_state) { case BNXT_FW_RESET_STATE_POLL_VF: { int n = bnxt_get_registered_vfs(bp); + int tmo; if (n < 0) { netdev_err(bp->dev, "Firmware reset aborted, subsequent func_qcfg cmd failed, rc = %d, %d msecs since reset timestamp\n", @@ -10631,11 +10642,38 @@ bp->fw_reset_timestamp = jiffies; rtnl_lock(); bnxt_fw_reset_close(bp); - bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) { + bp->fw_reset_state = BNXT_FW_RESET_STATE_POLL_FW_DOWN; + tmo = HZ / 10; + } else { + bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + tmo = bp->fw_reset_min_dsecs * HZ / 10; + } rtnl_unlock(); - bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10); + bnxt_queue_fw_reset_work(bp, tmo); return; } + case BNXT_FW_RESET_STATE_POLL_FW_DOWN: { + u32 val; + + val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG); + if (!(val & BNXT_FW_STATUS_SHUTDOWN) && + !time_after(jiffies, bp->fw_reset_timestamp + + (bp->fw_reset_max_dsecs * HZ / 10))) { + bnxt_queue_fw_reset_work(bp, HZ / 5); + return; + } + + if (!bp->fw_health->master) { + u32 wait_dsecs = bp->fw_health->normal_func_wait_dsecs; + + bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; + bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10); + return; + } + bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW; + } + /* fall through */ case BNXT_FW_RESET_STATE_RESET_FW: { u32 wait_dsecs = bp->fw_health->post_reset_wait_dsecs; Index: src/drivers/net/ethernet/broadcom/bnxt/bnxt.h =================================================================== --- src.orig/drivers/net/ethernet/broadcom/bnxt/bnxt.h 2020-02-06 16:23:21.412460813 +0100 +++ src/drivers/net/ethernet/broadcom/bnxt/bnxt.h 2020-02-06 16:23:21.672458426 +0100 @@ -1398,6 +1398,7 @@ #define BNXT_FW_HEALTH_WIN_MAP_OFF 8 #define BNXT_FW_STATUS_HEALTHY 0x8000 +#define BNXT_FW_STATUS_SHUTDOWN 0x100000 struct bnxt { void __iomem *bar0; @@ -1655,6 +1656,7 @@ #define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX 0x00010000 #define BNXT_FW_CAP_PCIE_STATS_SUPPORTED 0x00020000 #define BNXT_FW_CAP_EXT_STATS_SUPPORTED 0x00040000 + #define BNXT_FW_CAP_ERR_RECOVER_RELOAD 0x00100000 #define BNXT_NEW_RM(bp) ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM) u32 hwrm_spec_code; @@ -1744,6 +1746,7 @@ #define BNXT_FW_RESET_STATE_ENABLE_DEV 3 #define BNXT_FW_RESET_STATE_POLL_FW 4 #define BNXT_FW_RESET_STATE_OPENING 5 +#define BNXT_FW_RESET_STATE_POLL_FW_DOWN 6 u16 fw_reset_min_dsecs; #define BNXT_DFLT_FW_RST_MIN_DSECS 20