From: Kalesh AP <kalesh-anakkur.pura...@broadcom.com> Firmware reports any fatal error (either ASIC or Firmware related) via a new status register. This status register can provide more detailed information about the firmware errors, especially if error occurs before HWRM_VER_GET is issued. Attempt to map this register if it is present and check for firmware status when VER_GET command fails.
Refactored the code to allocate the "bp->recovery_info" structure in bnxt_init_fw() instead of doing in bnxt_hwrm_error_recovery_qcfg(). Signed-off-by: Kalesh AP <kalesh-anakkur.pura...@broadcom.com> Reviewed-by: Ajit Kumar Khaparde <ajit.khapa...@broadcom.com> --- drivers/net/bnxt/bnxt.h | 5 ++ drivers/net/bnxt/bnxt_ethdev.c | 107 ++++++++++++++++++++++++++++++++++++++--- drivers/net/bnxt/bnxt_hwrm.c | 10 ---- 3 files changed, 106 insertions(+), 16 deletions(-) diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h index d55a570..586d3f5 100644 --- a/drivers/net/bnxt/bnxt.h +++ b/drivers/net/bnxt/bnxt.h @@ -507,6 +507,10 @@ struct bnxt_mark_info { #define BNXT_GRCP_WINDOW_2_BASE 0x2000 #define BNXT_GRCP_WINDOW_3_BASE 0x3000 +#define BNXT_GRCP_BASE_MASK 0xfffff000 +#define BNXT_GRCP_OFFSET_MASK 0x00000ffc + +#define BNXT_FW_STATUS_HEALTHY 0x8000 #define BNXT_FW_STATUS_SHUTDOWN 0x100000 #define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input) @@ -564,6 +568,7 @@ struct bnxt { #define BNXT_FW_CAP_ERR_RECOVER_RELOAD BIT(3) #define BNXT_FW_CAP_ADV_FLOW_MGMT BIT(5) #define BNXT_FW_CAP_ADV_FLOW_COUNTERS BIT(6) +#define BNXT_FW_CAP_HCOMM_FW_STATUS BIT(7) uint32_t flow_flags; #define BNXT_FLOW_FLAG_L2_HDR_SRC_FILTER_EN BIT(0) diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c index 589190b..1a3c7e6 100644 --- a/drivers/net/bnxt/bnxt_ethdev.c +++ b/drivers/net/bnxt/bnxt_ethdev.c @@ -155,6 +155,7 @@ static int bnxt_uninit_resources(struct bnxt *bp, bool reconfig_dev); static void bnxt_cancel_fw_health_check(struct bnxt *bp); static int bnxt_restore_vlan_filters(struct bnxt *bp); static void bnxt_dev_recover(void *arg); +static void bnxt_free_error_recovery_info(struct bnxt *bp); int is_bnxt_in_error(struct bnxt *bp) { @@ -4967,6 +4968,89 @@ bnxt_get_fw_func_id(uint16_t port) return bp->fw_fid; } +static void bnxt_alloc_error_recovery_info(struct bnxt *bp) +{ + struct bnxt_error_recovery_info *info = bp->recovery_info; + + if (info) { + if (!(bp->fw_cap & BNXT_FW_CAP_HCOMM_FW_STATUS)) + memset(info, 0, sizeof(*info)); + return; + } + + if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) + return; + + info = rte_zmalloc("bnxt_hwrm_error_recovery_qcfg", + sizeof(*info), 0); + if (!info) + bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY; + + bp->recovery_info = info; +} + +static void bnxt_check_fw_status(struct bnxt *bp) +{ + uint32_t fw_status; + + if (!(bp->recovery_info && + (bp->fw_cap & BNXT_FW_CAP_HCOMM_FW_STATUS))) + return; + + fw_status = bnxt_read_fw_status_reg(bp, BNXT_FW_STATUS_REG); + if (fw_status != BNXT_FW_STATUS_HEALTHY) + PMD_DRV_LOG(ERR, "Firmware not responding, status: %#x\n", + fw_status); +} + +static int bnxt_map_hcomm_fw_status_reg(struct bnxt *bp) +{ + struct bnxt_error_recovery_info *info = bp->recovery_info; + uint32_t status_loc; + uint32_t sig_ver; + + rte_write32(HCOMM_STATUS_STRUCT_LOC, (uint8_t *)bp->bar0 + + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4); + sig_ver = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 + + BNXT_GRCP_WINDOW_2_BASE + + offsetof(struct hcomm_status, + sig_ver))); + /* If the signature is absent, then FW does not support this feature */ + if ((sig_ver & HCOMM_STATUS_SIGNATURE_MASK) != + HCOMM_STATUS_SIGNATURE_VAL) + return 0; + + if (!info) { + info = rte_zmalloc("bnxt_hwrm_error_recovery_qcfg", + sizeof(*info), 0); + if (!info) + return -ENOMEM; + bp->recovery_info = info; + } else { + memset(info, 0, sizeof(*info)); + } + + status_loc = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 + + BNXT_GRCP_WINDOW_2_BASE + + offsetof(struct hcomm_status, + fw_status_loc))); + + /* Only pre-map the FW health status GRC register */ + if (BNXT_FW_STATUS_REG_TYPE(status_loc) != BNXT_FW_STATUS_REG_TYPE_GRC) + return 0; + + info->status_regs[BNXT_FW_STATUS_REG] = status_loc; + info->mapped_status_regs[BNXT_FW_STATUS_REG] = + BNXT_GRCP_WINDOW_2_BASE + (status_loc & BNXT_GRCP_OFFSET_MASK); + + rte_write32((status_loc & BNXT_GRCP_BASE_MASK), (uint8_t *)bp->bar0 + + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4); + + bp->fw_cap |= BNXT_FW_CAP_HCOMM_FW_STATUS; + + return 0; +} + static int bnxt_init_fw(struct bnxt *bp) { uint16_t mtu; @@ -4974,10 +5058,16 @@ static int bnxt_init_fw(struct bnxt *bp) bp->fw_cap = 0; - rc = bnxt_hwrm_ver_get(bp, DFLT_HWRM_CMD_TIMEOUT); + rc = bnxt_map_hcomm_fw_status_reg(bp); if (rc) return rc; + rc = bnxt_hwrm_ver_get(bp, DFLT_HWRM_CMD_TIMEOUT); + if (rc) { + bnxt_check_fw_status(bp); + return rc; + } + rc = bnxt_hwrm_func_reset(bp); if (rc) return -EIO; @@ -5008,6 +5098,7 @@ static int bnxt_init_fw(struct bnxt *bp) if (rc) return rc; + bnxt_alloc_error_recovery_info(bp); /* Get the adapter error recovery support info */ rc = bnxt_hwrm_error_recovery_qcfg(bp); if (rc) @@ -5344,6 +5435,14 @@ static void bnxt_uninit_ctx_mem(struct bnxt *bp) } static void +bnxt_free_error_recovery_info(struct bnxt *bp) +{ + rte_free(bp->recovery_info); + bp->recovery_info = NULL; + bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY; +} + +static void bnxt_uninit_locks(struct bnxt *bp) { pthread_mutex_destroy(&bp->flow_lock); @@ -5363,11 +5462,7 @@ bnxt_uninit_resources(struct bnxt *bp, bool reconfig_dev) bnxt_free_ctx_mem(bp); if (!reconfig_dev) { bnxt_free_hwrm_resources(bp); - - if (bp->recovery_info != NULL) { - rte_free(bp->recovery_info); - bp->recovery_info = NULL; - } + bnxt_free_error_recovery_info(bp); } bnxt_uninit_ctx_mem(bp); diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c index dc0b405..666056a 100644 --- a/drivers/net/bnxt/bnxt_hwrm.c +++ b/drivers/net/bnxt/bnxt_hwrm.c @@ -5076,16 +5076,6 @@ int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp) if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) return 0; - if (!info) { - info = rte_zmalloc("bnxt_hwrm_error_recovery_qcfg", - sizeof(*info), 0); - bp->recovery_info = info; - if (info == NULL) - return -ENOMEM; - } else { - memset(info, 0, sizeof(*info)); - } - HWRM_PREP(&req, HWRM_ERROR_RECOVERY_QCFG, BNXT_USE_CHIMP_MB); rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB); -- 2.10.1