Skip to content

Commit

Permalink
bnxt_en: log firmware status on firmware init failure
Browse files Browse the repository at this point in the history
Firmware now supports device independent discovery of the status
register location. This status register can provide more detailed
information about firmware errors, especially if problems occur
before the HWRM interface is functioning. Attempt to map this
register if it is present and report the firmware status on firmware
init failures.

Signed-off-by: Edwin Peer <[email protected]>
Signed-off-by: Michael Chan <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Edwin Peer authored and davem330 committed Oct 4, 2020
1 parent 3e9ec2b commit ba02629
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
56 changes: 51 additions & 5 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -7366,6 +7366,47 @@ static int bnxt_alloc_fw_health(struct bnxt *bp)
return 0;
}

static void __bnxt_map_fw_health_reg(struct bnxt *bp, u32 reg)
{
writel(reg & BNXT_GRC_BASE_MASK, bp->bar0 +
BNXT_GRCPF_REG_WINDOW_BASE_OUT +
BNXT_FW_HEALTH_WIN_MAP_OFF);
}

static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
{
void __iomem *hs;
u32 status_loc;
u32 reg_type;
u32 sig;

__bnxt_map_fw_health_reg(bp, HCOMM_STATUS_STRUCT_LOC);
hs = bp->bar0 + BNXT_FW_HEALTH_WIN_OFF(HCOMM_STATUS_STRUCT_LOC);

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 (__bnxt_alloc_fw_health(bp)) {
netdev_warn(bp->dev, "no memory for firmware status checks\n");
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) {
__bnxt_map_fw_health_reg(bp, status_loc);
bp->fw_health->mapped_regs[BNXT_FW_HEALTH_REG] =
BNXT_FW_HEALTH_WIN_OFF(status_loc);
}

bp->fw_health->status_reliable = true;
}

static int bnxt_map_fw_health_regs(struct bnxt *bp)
{
struct bnxt_fw_health *fw_health = bp->fw_health;
Expand All @@ -7382,14 +7423,12 @@ static int bnxt_map_fw_health_regs(struct bnxt *bp)
reg_base = reg & BNXT_GRC_BASE_MASK;
if ((reg & BNXT_GRC_BASE_MASK) != reg_base)
return -ERANGE;
fw_health->mapped_regs[i] = BNXT_FW_HEALTH_WIN_BASE +
(reg & BNXT_GRC_OFFSET_MASK);
fw_health->mapped_regs[i] = BNXT_FW_HEALTH_WIN_OFF(reg);
}
if (reg_base == 0xffffffff)
return 0;

writel(reg_base, bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT +
BNXT_FW_HEALTH_WIN_MAP_OFF);
__bnxt_map_fw_health_reg(bp, reg_base);
return 0;
}

Expand Down Expand Up @@ -11002,8 +11041,15 @@ static int bnxt_fw_init_one_p1(struct bnxt *bp)

bp->fw_cap = 0;
rc = bnxt_hwrm_ver_get(bp);
if (rc)
bnxt_try_map_fw_health_reg(bp);
if (rc) {
if (bp->fw_health && bp->fw_health->status_reliable)
netdev_err(bp->dev,
"Firmware not responding, status: 0x%x\n",
bnxt_fw_health_readl(bp,
BNXT_FW_HEALTH_REG));
return rc;
}

if (bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL) {
rc = bnxt_alloc_kong_hwrm_resources(bp);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,7 @@ struct bnxt_fw_health {
u8 enabled:1;
u8 master:1;
u8 fatal:1;
u8 status_reliable:1;
u8 tmr_multiplier;
u8 tmr_counter;
u8 fw_reset_seq_cnt;
Expand Down Expand Up @@ -1521,6 +1522,9 @@ struct bnxt_fw_reporter_ctx {
#define BNXT_FW_HEALTH_WIN_BASE 0x3000
#define BNXT_FW_HEALTH_WIN_MAP_OFF 8

#define BNXT_FW_HEALTH_WIN_OFF(reg) (BNXT_FW_HEALTH_WIN_BASE + \
((reg) & BNXT_GRC_OFFSET_MASK))

#define BNXT_FW_STATUS_HEALTHY 0x8000
#define BNXT_FW_STATUS_SHUTDOWN 0x100000

Expand Down

0 comments on commit ba02629

Please sign in to comment.