bnxt_en: Retry sending the first message to firmware if it is under reset.
The first HWRM_VER_GET message to firmware during probe may timeout if firmware is under reset. This can happen during hot-plug for example. On P5 and newer chips, we can check if firmware is in the boot stage by reading a status register. Retry 5 times if the status register shows that firmware is not ready and not in error state. Reviewed-by: Edwin Peer <edwin.peer@broadcom.com> Signed-off-by: Michael Chan <michael.chan@broadcom.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
b187e4bae0
commit
d1cbd1659c
@ -7441,9 +7441,22 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
|
||||
|
||||
sig = readl(hs + offsetof(struct hcomm_status, sig_ver));
|
||||
if ((sig & HCOMM_STATUS_SIGNATURE_MASK) != HCOMM_STATUS_SIGNATURE_VAL) {
|
||||
if (bp->fw_health)
|
||||
bp->fw_health->status_reliable = false;
|
||||
return;
|
||||
if (!bp->chip_num) {
|
||||
__bnxt_map_fw_health_reg(bp, BNXT_GRC_REG_BASE);
|
||||
bp->chip_num = readl(bp->bar0 +
|
||||
BNXT_FW_HEALTH_WIN_BASE +
|
||||
BNXT_GRC_REG_CHIP_NUM);
|
||||
}
|
||||
if (!BNXT_CHIP_P5(bp)) {
|
||||
if (bp->fw_health)
|
||||
bp->fw_health->status_reliable = false;
|
||||
return;
|
||||
}
|
||||
status_loc = BNXT_GRC_REG_STATUS_P5 |
|
||||
BNXT_FW_HEALTH_REG_TYPE_BAR0;
|
||||
} else {
|
||||
status_loc = readl(hs + offsetof(struct hcomm_status,
|
||||
fw_status_loc));
|
||||
}
|
||||
|
||||
if (__bnxt_alloc_fw_health(bp)) {
|
||||
@ -7451,7 +7464,6 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
|
||||
return;
|
||||
}
|
||||
|
||||
status_loc = readl(hs + offsetof(struct hcomm_status, fw_status_loc));
|
||||
bp->fw_health->regs[BNXT_FW_HEALTH_REG] = status_loc;
|
||||
reg_type = BNXT_FW_HEALTH_REG_TYPE(status_loc);
|
||||
if (reg_type == BNXT_FW_HEALTH_REG_TYPE_GRC) {
|
||||
@ -9355,14 +9367,30 @@ static int bnxt_fw_reset_via_optee(struct bnxt *bp)
|
||||
static int bnxt_try_recover_fw(struct bnxt *bp)
|
||||
{
|
||||
if (bp->fw_health && bp->fw_health->status_reliable) {
|
||||
u32 sts = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
|
||||
int retry = 0, rc;
|
||||
u32 sts;
|
||||
|
||||
netdev_err(bp->dev, "Firmware not responding, status: 0x%x\n",
|
||||
sts);
|
||||
mutex_lock(&bp->hwrm_cmd_lock);
|
||||
do {
|
||||
rc = __bnxt_hwrm_ver_get(bp, true);
|
||||
sts = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
|
||||
if (!sts || !BNXT_FW_IS_BOOTING(sts))
|
||||
break;
|
||||
retry++;
|
||||
} while (rc == -EBUSY && retry < BNXT_FW_RETRY);
|
||||
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||
|
||||
if (!BNXT_FW_IS_HEALTHY(sts)) {
|
||||
netdev_err(bp->dev,
|
||||
"Firmware not responding, status: 0x%x\n",
|
||||
sts);
|
||||
rc = -ENODEV;
|
||||
}
|
||||
if (sts & FW_STATUS_REG_CRASHED_NO_MASTER) {
|
||||
netdev_warn(bp->dev, "Firmware recover via OP-TEE requested\n");
|
||||
return bnxt_fw_reset_via_optee(bp);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
|
@ -1345,9 +1345,14 @@ struct bnxt_test_info {
|
||||
#define BNXT_CAG_REG_LEGACY_INT_STATUS 0x4014
|
||||
#define BNXT_CAG_REG_BASE 0x300000
|
||||
|
||||
#define BNXT_GRC_REG_STATUS_P5 0x520
|
||||
|
||||
#define BNXT_GRCPF_REG_KONG_COMM 0xA00
|
||||
#define BNXT_GRCPF_REG_KONG_COMM_TRIGGER 0xB00
|
||||
|
||||
#define BNXT_GRC_REG_CHIP_NUM 0x48
|
||||
#define BNXT_GRC_REG_BASE 0x260000
|
||||
|
||||
#define BNXT_GRC_BASE_MASK 0xfffff000
|
||||
#define BNXT_GRC_OFFSET_MASK 0x00000ffc
|
||||
|
||||
@ -1547,6 +1552,8 @@ struct bnxt_fw_reporter_ctx {
|
||||
#define BNXT_FW_IS_ERR(sts) (((sts) & BNXT_FW_STATUS_HEALTH_MSK) > \
|
||||
BNXT_FW_STATUS_HEALTHY)
|
||||
|
||||
#define BNXT_FW_RETRY 5
|
||||
|
||||
struct bnxt {
|
||||
void __iomem *bar0;
|
||||
void __iomem *bar1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user