bnxt_en: Add bnxt_fw_exception() to handle fatal firmware errors.
This call will handle fatal firmware errors by forcing a reset on the firmware. The master function driver will carry out the forced reset. The sequence will go through the same bnxt_fw_reset_task() workqueue. This fatal reset differs from the non-fatal reset at the beginning stages. From the BNXT_FW_RESET_STATE_ENABLE_DEV state onwards where the firmware is coming out of reset, it is practically identical to the non-fatal reset. The next patch will add the periodic heartbeat check and the devlink reporter to report the fatal event and to initiate the bnxt_fw_exception() call. Signed-off-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com> Signed-off-by: Michael Chan <michael.chan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
cbb51067a5
Коммит
d1db9e166b
|
@ -10003,6 +10003,40 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
|
|||
bp->ctx = NULL;
|
||||
}
|
||||
|
||||
/* rtnl_lock is acquired before calling this function */
|
||||
static void bnxt_force_fw_reset(struct bnxt *bp)
|
||||
{
|
||||
struct bnxt_fw_health *fw_health = bp->fw_health;
|
||||
u32 wait_dsecs;
|
||||
|
||||
if (!test_bit(BNXT_STATE_OPEN, &bp->state) ||
|
||||
test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
|
||||
return;
|
||||
|
||||
set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
|
||||
bnxt_fw_reset_close(bp);
|
||||
wait_dsecs = fw_health->master_func_wait_dsecs;
|
||||
if (fw_health->master) {
|
||||
if (fw_health->flags & ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU)
|
||||
wait_dsecs = 0;
|
||||
bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW;
|
||||
} else {
|
||||
bp->fw_reset_timestamp = jiffies + wait_dsecs * HZ / 10;
|
||||
wait_dsecs = fw_health->normal_func_wait_dsecs;
|
||||
bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
|
||||
}
|
||||
bp->fw_reset_max_dsecs = fw_health->post_reset_max_wait_dsecs;
|
||||
bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10);
|
||||
}
|
||||
|
||||
void bnxt_fw_exception(struct bnxt *bp)
|
||||
{
|
||||
set_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
|
||||
bnxt_rtnl_lock_sp(bp);
|
||||
bnxt_force_fw_reset(bp);
|
||||
bnxt_rtnl_unlock_sp(bp);
|
||||
}
|
||||
|
||||
void bnxt_fw_reset(struct bnxt *bp)
|
||||
{
|
||||
int rc;
|
||||
|
@ -10506,6 +10540,16 @@ static void bnxt_fw_reset_task(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
case BNXT_FW_RESET_STATE_ENABLE_DEV:
|
||||
if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) &&
|
||||
bp->fw_health) {
|
||||
u32 val;
|
||||
|
||||
val = bnxt_fw_health_readl(bp,
|
||||
BNXT_FW_RESET_INPROG_REG);
|
||||
if (val)
|
||||
netdev_warn(bp->dev, "FW reset inprog %x after min wait time.\n",
|
||||
val);
|
||||
}
|
||||
clear_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
|
||||
if (pci_enable_device(bp->pdev)) {
|
||||
netdev_err(bp->dev, "Cannot re-enable PCI device\n");
|
||||
|
|
|
@ -1982,6 +1982,7 @@ int bnxt_open_nic(struct bnxt *, bool, bool);
|
|||
int bnxt_half_open_nic(struct bnxt *bp);
|
||||
void bnxt_half_close_nic(struct bnxt *bp);
|
||||
int bnxt_close_nic(struct bnxt *, bool, bool);
|
||||
void bnxt_fw_exception(struct bnxt *bp);
|
||||
void bnxt_fw_reset(struct bnxt *bp);
|
||||
int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
|
||||
int tx_xdp);
|
||||
|
|
Загрузка…
Ссылка в новой задаче