Commit 4037eb71 authored by Vasundhara Volam's avatar Vasundhara Volam Committed by David S. Miller

bnxt_en: Add a new BNXT_FW_RESET_STATE_POLL_FW_DOWN state.

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: default avatarVasundhara Volam <vasundhara-v.volam@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 72e0c9f9
...@@ -6947,6 +6947,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp) ...@@ -6947,6 +6947,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->fw_cap |= BNXT_FW_CAP_EXT_STATS_SUPPORTED; bp->fw_cap |= BNXT_FW_CAP_EXT_STATS_SUPPORTED;
if (flags & FUNC_QCAPS_RESP_FLAGS_ERROR_RECOVERY_CAPABLE) if (flags & FUNC_QCAPS_RESP_FLAGS_ERROR_RECOVERY_CAPABLE)
bp->fw_cap |= BNXT_FW_CAP_ERROR_RECOVERY; 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; bp->tx_push_thresh = 0;
if (flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) if (flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED)
...@@ -10097,6 +10099,8 @@ static void bnxt_force_fw_reset(struct bnxt *bp) ...@@ -10097,6 +10099,8 @@ static void bnxt_force_fw_reset(struct bnxt *bp)
wait_dsecs = fw_health->normal_func_wait_dsecs; wait_dsecs = fw_health->normal_func_wait_dsecs;
bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; 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; bp->fw_reset_max_dsecs = fw_health->post_reset_max_wait_dsecs;
bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10); bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10);
} }
...@@ -10138,7 +10142,7 @@ void bnxt_fw_reset(struct bnxt *bp) ...@@ -10138,7 +10142,7 @@ void bnxt_fw_reset(struct bnxt *bp)
bnxt_rtnl_lock_sp(bp); bnxt_rtnl_lock_sp(bp);
if (test_bit(BNXT_STATE_OPEN, &bp->state) && if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
!test_bit(BNXT_STATE_IN_FW_RESET, &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); set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
if (bp->pf.active_vfs && if (bp->pf.active_vfs &&
...@@ -10161,8 +10165,14 @@ void bnxt_fw_reset(struct bnxt *bp) ...@@ -10161,8 +10165,14 @@ void bnxt_fw_reset(struct bnxt *bp)
goto fw_reset_exit; goto fw_reset_exit;
} }
bnxt_fw_reset_close(bp); 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) {
bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10); 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: fw_reset_exit:
bnxt_rtnl_unlock_sp(bp); bnxt_rtnl_unlock_sp(bp);
...@@ -10605,6 +10615,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) ...@@ -10605,6 +10615,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
switch (bp->fw_reset_state) { switch (bp->fw_reset_state) {
case BNXT_FW_RESET_STATE_POLL_VF: { case BNXT_FW_RESET_STATE_POLL_VF: {
int n = bnxt_get_registered_vfs(bp); int n = bnxt_get_registered_vfs(bp);
int tmo;
if (n < 0) { if (n < 0) {
netdev_err(bp->dev, "Firmware reset aborted, subsequent func_qcfg cmd failed, rc = %d, %d msecs since reset timestamp\n", netdev_err(bp->dev, "Firmware reset aborted, subsequent func_qcfg cmd failed, rc = %d, %d msecs since reset timestamp\n",
...@@ -10626,11 +10637,38 @@ static void bnxt_fw_reset_task(struct work_struct *work) ...@@ -10626,11 +10637,38 @@ static void bnxt_fw_reset_task(struct work_struct *work)
bp->fw_reset_timestamp = jiffies; bp->fw_reset_timestamp = jiffies;
rtnl_lock(); rtnl_lock();
bnxt_fw_reset_close(bp); 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(); rtnl_unlock();
bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10); bnxt_queue_fw_reset_work(bp, tmo);
return; 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: { case BNXT_FW_RESET_STATE_RESET_FW: {
u32 wait_dsecs = bp->fw_health->post_reset_wait_dsecs; u32 wait_dsecs = bp->fw_health->post_reset_wait_dsecs;
......
...@@ -1398,6 +1398,7 @@ struct bnxt_fw_reporter_ctx { ...@@ -1398,6 +1398,7 @@ struct bnxt_fw_reporter_ctx {
#define BNXT_FW_HEALTH_WIN_MAP_OFF 8 #define BNXT_FW_HEALTH_WIN_MAP_OFF 8
#define BNXT_FW_STATUS_HEALTHY 0x8000 #define BNXT_FW_STATUS_HEALTHY 0x8000
#define BNXT_FW_STATUS_SHUTDOWN 0x100000
struct bnxt { struct bnxt {
void __iomem *bar0; void __iomem *bar0;
...@@ -1655,6 +1656,7 @@ struct bnxt { ...@@ -1655,6 +1656,7 @@ struct bnxt {
#define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX 0x00010000 #define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX 0x00010000
#define BNXT_FW_CAP_PCIE_STATS_SUPPORTED 0x00020000 #define BNXT_FW_CAP_PCIE_STATS_SUPPORTED 0x00020000
#define BNXT_FW_CAP_EXT_STATS_SUPPORTED 0x00040000 #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) #define BNXT_NEW_RM(bp) ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
u32 hwrm_spec_code; u32 hwrm_spec_code;
...@@ -1744,6 +1746,7 @@ struct bnxt { ...@@ -1744,6 +1746,7 @@ struct bnxt {
#define BNXT_FW_RESET_STATE_ENABLE_DEV 3 #define BNXT_FW_RESET_STATE_ENABLE_DEV 3
#define BNXT_FW_RESET_STATE_POLL_FW 4 #define BNXT_FW_RESET_STATE_POLL_FW 4
#define BNXT_FW_RESET_STATE_OPENING 5 #define BNXT_FW_RESET_STATE_OPENING 5
#define BNXT_FW_RESET_STATE_POLL_FW_DOWN 6
u16 fw_reset_min_dsecs; u16 fw_reset_min_dsecs;
#define BNXT_DFLT_FW_RST_MIN_DSECS 20 #define BNXT_DFLT_FW_RST_MIN_DSECS 20
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment