Commit 43a440c4 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Improve the status_reliable flag in bp->fw_health.

In order to read the firmware health status, we first need to determine
the register location and then the register may need to be mapped.
There are 2 code paths to do this.  The first one is done early as a
best effort attempt by the function bnxt_try_map_fw_health_reg().  The
second one is done later in the function bnxt_map_fw_health_regs()
after establishing communications with the firmware.  We currently
only set fw_health->status_reliable if we can successfully set up the
health register in the first code path.

Improve the scheme by setting the fw_health->status_reliable flag if
either (or both) code paths can successfully set up the health
register.  This flag is relied upon during run-time when we need to
check the health status.  So this will make it work better.

During ifdown, if the health register is mapped, we need to invalidate
the health register mapping because a potential fw reset will reset
the mapping.  Similarly, we need to do the same after firmware reset
during recovery.  We'll remap it during ifup.
Reviewed-by: default avatarEdwin Peer <edwin.peer@broadcom.com>
Reviewed-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 3e0144ad
...@@ -7540,6 +7540,19 @@ static void __bnxt_map_fw_health_reg(struct bnxt *bp, u32 reg) ...@@ -7540,6 +7540,19 @@ static void __bnxt_map_fw_health_reg(struct bnxt *bp, u32 reg)
BNXT_FW_HEALTH_WIN_MAP_OFF); BNXT_FW_HEALTH_WIN_MAP_OFF);
} }
static void bnxt_inv_fw_health_reg(struct bnxt *bp)
{
struct bnxt_fw_health *fw_health = bp->fw_health;
u32 reg_type;
if (!fw_health || !fw_health->status_reliable)
return;
reg_type = BNXT_FW_HEALTH_REG_TYPE(fw_health->regs[BNXT_FW_HEALTH_REG]);
if (reg_type == BNXT_FW_HEALTH_REG_TYPE_GRC)
fw_health->status_reliable = false;
}
static void bnxt_try_map_fw_health_reg(struct bnxt *bp) static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
{ {
void __iomem *hs; void __iomem *hs;
...@@ -7547,6 +7560,9 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp) ...@@ -7547,6 +7560,9 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
u32 reg_type; u32 reg_type;
u32 sig; u32 sig;
if (bp->fw_health)
bp->fw_health->status_reliable = false;
__bnxt_map_fw_health_reg(bp, HCOMM_STATUS_STRUCT_LOC); __bnxt_map_fw_health_reg(bp, HCOMM_STATUS_STRUCT_LOC);
hs = bp->bar0 + BNXT_FW_HEALTH_WIN_OFF(HCOMM_STATUS_STRUCT_LOC); hs = bp->bar0 + BNXT_FW_HEALTH_WIN_OFF(HCOMM_STATUS_STRUCT_LOC);
...@@ -7558,11 +7574,9 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp) ...@@ -7558,11 +7574,9 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
BNXT_FW_HEALTH_WIN_BASE + BNXT_FW_HEALTH_WIN_BASE +
BNXT_GRC_REG_CHIP_NUM); BNXT_GRC_REG_CHIP_NUM);
} }
if (!BNXT_CHIP_P5(bp)) { if (!BNXT_CHIP_P5(bp))
if (bp->fw_health)
bp->fw_health->status_reliable = false;
return; return;
}
status_loc = BNXT_GRC_REG_STATUS_P5 | status_loc = BNXT_GRC_REG_STATUS_P5 |
BNXT_FW_HEALTH_REG_TYPE_BAR0; BNXT_FW_HEALTH_REG_TYPE_BAR0;
} else { } else {
...@@ -7592,6 +7606,7 @@ static int bnxt_map_fw_health_regs(struct bnxt *bp) ...@@ -7592,6 +7606,7 @@ static int bnxt_map_fw_health_regs(struct bnxt *bp)
u32 reg_base = 0xffffffff; u32 reg_base = 0xffffffff;
int i; int i;
bp->fw_health->status_reliable = false;
/* Only pre-map the monitoring GRC registers using window 3 */ /* Only pre-map the monitoring GRC registers using window 3 */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
u32 reg = fw_health->regs[i]; u32 reg = fw_health->regs[i];
...@@ -7604,6 +7619,7 @@ static int bnxt_map_fw_health_regs(struct bnxt *bp) ...@@ -7604,6 +7619,7 @@ static int bnxt_map_fw_health_regs(struct bnxt *bp)
return -ERANGE; return -ERANGE;
fw_health->mapped_regs[i] = BNXT_FW_HEALTH_WIN_OFF(reg); fw_health->mapped_regs[i] = BNXT_FW_HEALTH_WIN_OFF(reg);
} }
bp->fw_health->status_reliable = true;
if (reg_base == 0xffffffff) if (reg_base == 0xffffffff)
return 0; return 0;
...@@ -9556,13 +9572,17 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) ...@@ -9556,13 +9572,17 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
if (rc) if (rc)
return rc; return rc;
if (!up) if (!up) {
bnxt_inv_fw_health_reg(bp);
return 0; return 0;
}
if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_RESC_CHANGE) if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_RESC_CHANGE)
resc_reinit = true; resc_reinit = true;
if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_HOT_FW_RESET_DONE) if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_HOT_FW_RESET_DONE)
fw_reset = true; fw_reset = true;
else if (bp->fw_health && !bp->fw_health->status_reliable)
bnxt_try_map_fw_health_reg(bp);
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) { if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) {
netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n"); netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n");
...@@ -11723,6 +11743,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) ...@@ -11723,6 +11743,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10); bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10);
return; return;
case BNXT_FW_RESET_STATE_ENABLE_DEV: case BNXT_FW_RESET_STATE_ENABLE_DEV:
bnxt_inv_fw_health_reg(bp);
if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) { if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) {
u32 val; u32 val;
......
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