From 31f67c2ee0551f0fd0dd134f4a73c456c53ea015 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 14 Feb 2021 18:04:55 -0500 Subject: [PATCH 1/7] bnxt_en: Update firmware interface spec to 1.10.2.16. The main changes are the echo request/response from firmware for error detection and the NO_FCS feature to transmit frames without FCS. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 103 ++++++++++++++++-- 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 4ef6888acdc6..36007b0d1177 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -18,7 +18,7 @@ */ #define DRV_VER_MAJ 1 #define DRV_VER_MIN 10 -#define DRV_VER_UPD 1 +#define DRV_VER_UPD 2 #include #include diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h index d5c6e6a3d22d..6199f125bc13 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -103,6 +103,7 @@ struct hwrm_short_input { struct cmd_nums { __le16 req_type; #define HWRM_VER_GET 0x0UL + #define HWRM_FUNC_ECHO_RESPONSE 0xbUL #define HWRM_ERROR_RECOVERY_QCFG 0xcUL #define HWRM_FUNC_DRV_IF_CHANGE 0xdUL #define HWRM_FUNC_BUF_UNRGTR 0xeUL @@ -501,8 +502,8 @@ struct hwrm_err_output { #define HWRM_VERSION_MAJOR 1 #define HWRM_VERSION_MINOR 10 #define HWRM_VERSION_UPDATE 2 -#define HWRM_VERSION_RSVD 11 -#define HWRM_VERSION_STR "1.10.2.11" +#define HWRM_VERSION_RSVD 16 +#define HWRM_VERSION_STR "1.10.2.16" /* hwrm_ver_get_input (size:192b/24B) */ struct hwrm_ver_get_input { @@ -723,7 +724,8 @@ struct hwrm_async_event_cmpl { #define ASYNC_EVENT_CMPL_EVENT_ID_QUIESCE_DONE 0x3fUL #define ASYNC_EVENT_CMPL_EVENT_ID_DEFERRED_RESPONSE 0x40UL #define ASYNC_EVENT_CMPL_EVENT_ID_PFC_WATCHDOG_CFG_CHANGE 0x41UL - #define ASYNC_EVENT_CMPL_EVENT_ID_MAX_RGTR_EVENT_ID 0x42UL + #define ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST 0x42UL + #define ASYNC_EVENT_CMPL_EVENT_ID_MAX_RGTR_EVENT_ID 0x43UL #define ASYNC_EVENT_CMPL_EVENT_ID_FW_TRACE_MSG 0xfeUL #define ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR 0xffUL #define ASYNC_EVENT_CMPL_EVENT_ID_LAST ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR @@ -1052,6 +1054,26 @@ struct hwrm_async_event_cmpl_deferred_response { __le32 event_data1; }; +/* hwrm_async_event_cmpl_echo_request (size:128b/16B) */ +struct hwrm_async_event_cmpl_echo_request { + __le16 type; + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_TYPE_MASK 0x3fUL + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_TYPE_SFT 0 + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_TYPE_HWRM_ASYNC_EVENT 0x2eUL + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_TYPE_LAST ASYNC_EVENT_CMPL_ECHO_REQUEST_TYPE_HWRM_ASYNC_EVENT + __le16 event_id; + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_EVENT_ID_ECHO_REQUEST 0x42UL + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_EVENT_ID_LAST ASYNC_EVENT_CMPL_ECHO_REQUEST_EVENT_ID_ECHO_REQUEST + __le32 event_data2; + u8 opaque_v; + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_V 0x1UL + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_OPAQUE_MASK 0xfeUL + #define ASYNC_EVENT_CMPL_ECHO_REQUEST_OPAQUE_SFT 1 + u8 timestamp_lo; + __le16 timestamp_hi; + __le32 event_data1; +}; + /* hwrm_func_reset_input (size:192b/24B) */ struct hwrm_func_reset_input { __le16 req_type; @@ -1294,6 +1316,10 @@ struct hwrm_func_qcaps_output { #define FUNC_QCAPS_RESP_FLAGS_EXT_SOC_SPD_SUPPORTED 0x200UL #define FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED 0x400UL #define FUNC_QCAPS_RESP_FLAGS_EXT_FAST_RESET_CAPABLE 0x800UL + #define FUNC_QCAPS_RESP_FLAGS_EXT_TX_METADATA_CFG_CAPABLE 0x1000UL + #define FUNC_QCAPS_RESP_FLAGS_EXT_NVM_OPTION_ACTION_SUPPORTED 0x2000UL + #define FUNC_QCAPS_RESP_FLAGS_EXT_BD_METADATA_SUPPORTED 0x4000UL + #define FUNC_QCAPS_RESP_FLAGS_EXT_ECHO_REQUEST_SUPPORTED 0x8000UL u8 max_schqs; u8 mpc_chnls_cap; #define FUNC_QCAPS_RESP_MPC_CHNLS_CAP_TCE 0x1UL @@ -1339,6 +1365,7 @@ struct hwrm_func_qcfg_output { #define FUNC_QCFG_RESP_FLAGS_PPP_PUSH_MODE_ENABLED 0x400UL #define FUNC_QCFG_RESP_FLAGS_RING_MONITOR_ENABLED 0x800UL #define FUNC_QCFG_RESP_FLAGS_FAST_RESET_ALLOWED 0x1000UL + #define FUNC_QCFG_RESP_FLAGS_MULTI_ROOT 0x2000UL u8 mac_address[6]; __le16 pci_id; __le16 alloc_rsscos_ctx; @@ -1474,6 +1501,8 @@ struct hwrm_func_cfg_input { #define FUNC_CFG_REQ_FLAGS_HOT_RESET_IF_EN_DIS 0x4000000UL #define FUNC_CFG_REQ_FLAGS_PPP_PUSH_MODE_ENABLE 0x8000000UL #define FUNC_CFG_REQ_FLAGS_PPP_PUSH_MODE_DISABLE 0x10000000UL + #define FUNC_CFG_REQ_FLAGS_BD_METADATA_ENABLE 0x20000000UL + #define FUNC_CFG_REQ_FLAGS_BD_METADATA_DISABLE 0x40000000UL __le32 enables; #define FUNC_CFG_REQ_ENABLES_MTU 0x1UL #define FUNC_CFG_REQ_ENABLES_MRU 0x2UL @@ -2063,10 +2092,34 @@ struct hwrm_func_backing_store_qcaps_output { u8 tqm_fp_rings_count; u8 stat_init_offset; u8 mrav_init_offset; - u8 rsvd[6]; + u8 tqm_fp_rings_count_ext; + u8 rsvd[5]; u8 valid; }; +/* tqm_fp_ring_cfg (size:128b/16B) */ +struct tqm_fp_ring_cfg { + u8 tqm_ring_pg_size_tqm_ring_lvl; + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_LVL_MASK 0xfUL + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_LVL_SFT 0 + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_LVL_LVL_0 0x0UL + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_LVL_LVL_1 0x1UL + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_LVL_LVL_2 0x2UL + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_LVL_LAST TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_LVL_LVL_2 + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_MASK 0xf0UL + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_SFT 4 + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_PG_4K (0x0UL << 4) + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_PG_8K (0x1UL << 4) + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_PG_64K (0x2UL << 4) + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_PG_2M (0x3UL << 4) + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_PG_8M (0x4UL << 4) + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_PG_1G (0x5UL << 4) + #define TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_LAST TQM_FP_RING_CFG_TQM_RING_CFG_TQM_RING_PG_SIZE_PG_1G + u8 unused[3]; + __le32 tqm_ring_num_entries; + __le64 tqm_ring_page_dir; +}; + /* hwrm_func_backing_store_cfg_input (size:2432b/304B) */ struct hwrm_func_backing_store_cfg_input { __le16 req_type; @@ -2560,6 +2613,27 @@ struct hwrm_error_recovery_qcfg_output { u8 valid; }; +/* hwrm_func_echo_response_input (size:192b/24B) */ +struct hwrm_func_echo_response_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 event_data1; + __le32 event_data2; +}; + +/* hwrm_func_echo_response_output (size:128b/16B) */ +struct hwrm_func_echo_response_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 unused_0[7]; + u8 valid; +}; + /* hwrm_func_drv_if_change_input (size:192b/24B) */ struct hwrm_func_drv_if_change_input { __le16 req_type; @@ -3627,7 +3701,7 @@ struct hwrm_port_phy_qcaps_output { #define PORT_PHY_QCAPS_RESP_FLAGS_CUMULATIVE_COUNTERS_ON_RESET 0x10UL #define PORT_PHY_QCAPS_RESP_FLAGS_LOCAL_LPBK_NOT_SUPPORTED 0x20UL #define PORT_PHY_QCAPS_RESP_FLAGS_FW_MANAGED_LINK_DOWN 0x40UL - #define PORT_PHY_QCAPS_RESP_FLAGS_RSVD1 0x80UL + #define PORT_PHY_QCAPS_RESP_FLAGS_NO_FCS 0x80UL u8 port_cnt; #define PORT_PHY_QCAPS_RESP_PORT_CNT_UNKNOWN 0x0UL #define PORT_PHY_QCAPS_RESP_PORT_CNT_1 0x1UL @@ -5392,6 +5466,7 @@ struct hwrm_vnic_qcaps_output { #define VNIC_QCAPS_RESP_FLAGS_RX_CMPL_V2_CAP 0x200UL #define VNIC_QCAPS_RESP_FLAGS_VNIC_STATE_CAP 0x400UL #define VNIC_QCAPS_RESP_FLAGS_VIRTIO_NET_VNIC_ALLOC_CAP 0x800UL + #define VNIC_QCAPS_RESP_FLAGS_METADATA_FORMAT_CAP 0x1000UL __le16 max_aggs_supported; u8 unused_1[5]; u8 valid; @@ -5725,7 +5800,7 @@ struct hwrm_ring_alloc_output { u8 valid; }; -/* hwrm_ring_free_input (size:192b/24B) */ +/* hwrm_ring_free_input (size:256b/32B) */ struct hwrm_ring_free_input { __le16 req_type; __le16 cmpl_ring; @@ -5740,9 +5815,13 @@ struct hwrm_ring_free_input { #define RING_FREE_REQ_RING_TYPE_RX_AGG 0x4UL #define RING_FREE_REQ_RING_TYPE_NQ 0x5UL #define RING_FREE_REQ_RING_TYPE_LAST RING_FREE_REQ_RING_TYPE_NQ - u8 unused_0; + u8 flags; + #define RING_FREE_REQ_FLAGS_VIRTIO_RING_VALID 0x1UL + #define RING_FREE_REQ_FLAGS_LAST RING_FREE_REQ_FLAGS_VIRTIO_RING_VALID __le16 ring_id; - u8 unused_1[4]; + __le32 prod_idx; + __le32 opaque; + __le32 unused_1; }; /* hwrm_ring_free_output (size:128b/16B) */ @@ -7562,7 +7641,13 @@ struct hwrm_fw_qstatus_output { #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTPCIERST 0x2UL #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTPOWER 0x3UL #define FW_QSTATUS_RESP_SELFRST_STATUS_LAST FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTPOWER - u8 unused_0[6]; + u8 nvm_option_action_status; + #define FW_QSTATUS_RESP_NVM_OPTION_ACTION_STATUS_NVMOPT_ACTION_NONE 0x0UL + #define FW_QSTATUS_RESP_NVM_OPTION_ACTION_STATUS_NVMOPT_ACTION_HOTRESET 0x1UL + #define FW_QSTATUS_RESP_NVM_OPTION_ACTION_STATUS_NVMOPT_ACTION_WARMBOOT 0x2UL + #define FW_QSTATUS_RESP_NVM_OPTION_ACTION_STATUS_NVMOPT_ACTION_COLDBOOT 0x3UL + #define FW_QSTATUS_RESP_NVM_OPTION_ACTION_STATUS_LAST FW_QSTATUS_RESP_NVM_OPTION_ACTION_STATUS_NVMOPT_ACTION_COLDBOOT + u8 unused_0[5]; u8 valid; }; From be6d755f3d0c7c76d07f980bca6dd7e70dcec452 Mon Sep 17 00:00:00 2001 From: Edwin Peer Date: Sun, 14 Feb 2021 18:04:56 -0500 Subject: [PATCH 2/7] bnxt_en: selectively allocate context memories Newer devices may have local context memory instead of relying on the host for backing store. In these cases, HWRM_FUNC_BACKING_STORE_QCAPS will return a zero entry size to indicate contexts for which the host should not allocate backing store. Selectively allocate context memory based on device capabilities and only enable backing store for the appropriate contexts. Signed-off-by: Edwin Peer Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 84 ++++++++++++++--------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f508c5c61a30..7512879a551a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6834,6 +6834,9 @@ static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, u8 *pg_attr, { u8 pg_size = 0; + if (!rmem->nr_pages) + return; + if (BNXT_PAGE_SHIFT == 13) pg_size = 1 << 4; else if (BNXT_PAGE_SIZE == 16) @@ -7124,39 +7127,49 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx_pg = &ctx->qp_mem; ctx_pg->entries = ctx->qp_min_qp1_entries + ctx->qp_max_l2_entries + extra_qps; - mem_size = ctx->qp_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); - if (rc) - return rc; + if (ctx->qp_entry_size) { + mem_size = ctx->qp_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); + if (rc) + return rc; + } ctx_pg = &ctx->srq_mem; ctx_pg->entries = ctx->srq_max_l2_entries + extra_srqs; - mem_size = ctx->srq_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); - if (rc) - return rc; + if (ctx->srq_entry_size) { + mem_size = ctx->srq_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); + if (rc) + return rc; + } ctx_pg = &ctx->cq_mem; ctx_pg->entries = ctx->cq_max_l2_entries + extra_qps * 2; - mem_size = ctx->cq_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); - if (rc) - return rc; + if (ctx->cq_entry_size) { + mem_size = ctx->cq_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); + if (rc) + return rc; + } ctx_pg = &ctx->vnic_mem; ctx_pg->entries = ctx->vnic_max_vnic_entries + ctx->vnic_max_ring_table_entries; - mem_size = ctx->vnic_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, true); - if (rc) - return rc; + if (ctx->vnic_entry_size) { + mem_size = ctx->vnic_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, true); + if (rc) + return rc; + } ctx_pg = &ctx->stat_mem; ctx_pg->entries = ctx->stat_max_entries; - mem_size = ctx->stat_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, true); - if (rc) - return rc; + if (ctx->stat_entry_size) { + mem_size = ctx->stat_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, true); + if (rc) + return rc; + } ena = 0; if (!(bp->flags & BNXT_FLAG_ROCE_CAP)) @@ -7169,10 +7182,12 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) num_mr = 1024 * 256; num_ah = 1024 * 128; ctx_pg->entries = num_mr + num_ah; - mem_size = ctx->mrav_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 2, true); - if (rc) - return rc; + if (ctx->mrav_entry_size) { + mem_size = ctx->mrav_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 2, true); + if (rc) + return rc; + } ena = FUNC_BACKING_STORE_CFG_REQ_ENABLES_MRAV; if (ctx->mrav_num_entries_units) ctx_pg->entries = @@ -7181,10 +7196,12 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx_pg = &ctx->tim_mem; ctx_pg->entries = ctx->qp_mem.entries; - mem_size = ctx->tim_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, false); - if (rc) - return rc; + if (ctx->tim_entry_size) { + mem_size = ctx->tim_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, false); + if (rc) + return rc; + } ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_TIM; skip_rdma: @@ -7198,10 +7215,13 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) for (i = 0; i < ctx->tqm_fp_rings_count + 1; i++) { ctx_pg = ctx->tqm_mem[i]; ctx_pg->entries = i ? entries : entries_sp; - mem_size = ctx->tqm_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, false); - if (rc) - return rc; + if (ctx->tqm_entry_size) { + mem_size = ctx->tqm_entry_size * ctx_pg->entries; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, + false); + if (rc) + return rc; + } ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_TQM_SP << i; } ena |= FUNC_BACKING_STORE_CFG_REQ_DFLT_ENABLES; From dab62e7c2de7b035c928a8babee27a6127891fdf Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 14 Feb 2021 18:04:57 -0500 Subject: [PATCH 3/7] bnxt_en: Implement faster recovery for firmware fatal error. During some fatal firmware error conditions, the PCI config space register 0x2e which normally contains the subsystem ID will become 0xffff. This register will revert back to the normal value after the chip has completed core reset. If we detect this condition, we can poll this config register immediately for the value to revert. Because we use config read cycles to poll this register, there is no possibility of Master Abort if we happen to read it during core reset. This speeds up recovery significantly as we don't have to wait for the conservative min_time before polling MMIO to see if the firmware has come out of reset. As soon as this register changes value we can proceed to re-initialize the device. Reviewed-by: Edwin Peer Reviewed-by: Vasundhara Volam Reviewed-by: Andy Gospodarek Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 7512879a551a..f2cf89d61eb2 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -10935,6 +10935,11 @@ static void bnxt_fw_reset_close(struct bnxt *bp) * kernel memory. */ if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) { + u16 val = 0; + + pci_read_config_word(bp->pdev, PCI_SUBSYSTEM_ID, &val); + if (val == 0xffff) + bp->fw_reset_min_dsecs = 0; bnxt_tx_disable(bp); bnxt_disable_napi(bp); bnxt_disable_int_sync(bp); @@ -11620,6 +11625,20 @@ static void bnxt_fw_reset_task(struct work_struct *work) if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) { u32 val; + if (!bp->fw_reset_min_dsecs) { + u16 val; + + pci_read_config_word(bp->pdev, PCI_SUBSYSTEM_ID, + &val); + if (val == 0xffff) { + if (bnxt_fw_reset_timeout(bp)) { + netdev_err(bp->dev, "Firmware reset aborted, PCI config space invalid\n"); + goto fw_reset_abort; + } + bnxt_queue_fw_reset_work(bp, HZ / 1000); + return; + } + } val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_INPROG_REG); if (val) From e9696ff33c79aed73ff76edb4961042a9b87d27b Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 14 Feb 2021 18:04:58 -0500 Subject: [PATCH 4/7] bnxt_en: Add context memory initialization infrastructure. Currently, the driver calls memset() to set all relevant context memory used by the chip to the initial value. This can take many milliseconds with the potentially large number of context pages allocated for the chip. To make this faster, we only need to initialize the "context kind" field of each block of context memory. This patch sets up the infrastructure to do that with the bnxt_mem_init structure. In the next patch, we'll add the logic to obtain the offset of the "context kind" from the firmware. This patch is not changing the current behavior of calling memset() to initialize all relevant context memory. Reviewed-by: Pavan Chebbi Reviewed-by: Edwin Peer Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 52 ++++++++++++++++------- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 19 ++++++++- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f2cf89d61eb2..888466c3ed78 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2747,8 +2747,8 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem) if (!rmem->pg_arr[i]) return -ENOMEM; - if (rmem->init_val) - memset(rmem->pg_arr[i], rmem->init_val, + if (rmem->mem_init && rmem->mem_init->init_val) + memset(rmem->pg_arr[i], rmem->mem_init->init_val, rmem->page_size); if (rmem->nr_pages > 1 || rmem->depth > 0) { if (i == rmem->nr_pages - 2 && @@ -6750,6 +6750,19 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp) return rc; } +static void bnxt_init_ctx_initializer(struct bnxt_ctx_mem_info *ctx, + struct hwrm_func_backing_store_qcaps_output *resp) +{ + struct bnxt_mem_init *mem_init; + u8 init_val; + int i; + + init_val = resp->ctx_kind_initializer; + mem_init = &ctx->mem_init[0]; + for (i = 0; i < BNXT_CTX_MEM_INIT_MAX; i++, mem_init++) + mem_init->init_val = init_val; +} + static int bnxt_hwrm_func_backing_store_qcaps(struct bnxt *bp) { struct hwrm_func_backing_store_qcaps_input req = {0}; @@ -6804,7 +6817,9 @@ static int bnxt_hwrm_func_backing_store_qcaps(struct bnxt *bp) le16_to_cpu(resp->mrav_num_entries_units); ctx->tim_entry_size = le16_to_cpu(resp->tim_entry_size); ctx->tim_max_entries = le32_to_cpu(resp->tim_max_entries); - ctx->ctx_kind_initializer = resp->ctx_kind_initializer; + + bnxt_init_ctx_initializer(ctx, resp); + ctx->tqm_fp_rings_count = resp->tqm_fp_rings_count; if (!ctx->tqm_fp_rings_count) ctx->tqm_fp_rings_count = bp->max_q; @@ -6981,7 +6996,7 @@ static int bnxt_alloc_ctx_mem_blk(struct bnxt *bp, static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp, struct bnxt_ctx_pg_info *ctx_pg, u32 mem_size, - u8 depth, bool use_init_val) + u8 depth, struct bnxt_mem_init *mem_init) { struct bnxt_ring_mem_info *rmem = &ctx_pg->ring_mem; int rc; @@ -7019,8 +7034,7 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp, rmem->pg_tbl_map = ctx_pg->ctx_dma_arr[i]; rmem->depth = 1; rmem->nr_pages = MAX_CTX_PAGES; - if (use_init_val) - rmem->init_val = bp->ctx->ctx_kind_initializer; + rmem->mem_init = mem_init; if (i == (nr_tbls - 1)) { int rem = ctx_pg->nr_pages % MAX_CTX_PAGES; @@ -7035,8 +7049,7 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp, rmem->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE); if (rmem->nr_pages > 1 || depth) rmem->depth = 1; - if (use_init_val) - rmem->init_val = bp->ctx->ctx_kind_initializer; + rmem->mem_init = mem_init; rc = bnxt_alloc_ctx_mem_blk(bp, ctx_pg); } return rc; @@ -7100,6 +7113,7 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) { struct bnxt_ctx_pg_info *ctx_pg; struct bnxt_ctx_mem_info *ctx; + struct bnxt_mem_init *init; u32 mem_size, ena, entries; u32 entries_sp, min; u32 num_mr, num_ah; @@ -7129,7 +7143,8 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) extra_qps; if (ctx->qp_entry_size) { mem_size = ctx->qp_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); + init = &ctx->mem_init[BNXT_CTX_MEM_INIT_QP]; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, init); if (rc) return rc; } @@ -7138,7 +7153,8 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx_pg->entries = ctx->srq_max_l2_entries + extra_srqs; if (ctx->srq_entry_size) { mem_size = ctx->srq_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); + init = &ctx->mem_init[BNXT_CTX_MEM_INIT_SRQ]; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, init); if (rc) return rc; } @@ -7147,7 +7163,8 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx_pg->entries = ctx->cq_max_l2_entries + extra_qps * 2; if (ctx->cq_entry_size) { mem_size = ctx->cq_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, true); + init = &ctx->mem_init[BNXT_CTX_MEM_INIT_CQ]; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, pg_lvl, init); if (rc) return rc; } @@ -7157,7 +7174,8 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx->vnic_max_ring_table_entries; if (ctx->vnic_entry_size) { mem_size = ctx->vnic_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, true); + init = &ctx->mem_init[BNXT_CTX_MEM_INIT_VNIC]; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, init); if (rc) return rc; } @@ -7166,7 +7184,8 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx_pg->entries = ctx->stat_max_entries; if (ctx->stat_entry_size) { mem_size = ctx->stat_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, true); + init = &ctx->mem_init[BNXT_CTX_MEM_INIT_STAT]; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, init); if (rc) return rc; } @@ -7184,7 +7203,8 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx_pg->entries = num_mr + num_ah; if (ctx->mrav_entry_size) { mem_size = ctx->mrav_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 2, true); + init = &ctx->mem_init[BNXT_CTX_MEM_INIT_MRAV]; + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 2, init); if (rc) return rc; } @@ -7198,7 +7218,7 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) ctx_pg->entries = ctx->qp_mem.entries; if (ctx->tim_entry_size) { mem_size = ctx->tim_entry_size * ctx_pg->entries; - rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, false); + rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, NULL); if (rc) return rc; } @@ -7218,7 +7238,7 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp) if (ctx->tqm_entry_size) { mem_size = ctx->tqm_entry_size * ctx_pg->entries; rc = bnxt_alloc_ctx_pg_tbls(bp, ctx_pg, mem_size, 1, - false); + NULL); if (rc) return rc; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 36007b0d1177..f5c45ea52b44 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -714,6 +714,13 @@ struct bnxt_sw_rx_agg_bd { dma_addr_t mapping; }; +struct bnxt_mem_init { + u8 init_val; + u16 offset; +#define BNXT_MEM_INVALID_OFFSET 0xffff + u16 size; +}; + struct bnxt_ring_mem_info { int nr_pages; int page_size; @@ -723,7 +730,7 @@ struct bnxt_ring_mem_info { #define BNXT_RMEM_USE_FULL_PAGE_FLAG 4 u16 depth; - u8 init_val; + struct bnxt_mem_init *mem_init; void **pg_arr; dma_addr_t *dma_arr; @@ -1474,7 +1481,6 @@ struct bnxt_ctx_mem_info { u32 tim_max_entries; u16 mrav_num_entries_units; u8 tqm_entries_multiple; - u8 ctx_kind_initializer; u8 tqm_fp_rings_count; u32 flags; @@ -1488,6 +1494,15 @@ struct bnxt_ctx_mem_info { struct bnxt_ctx_pg_info mrav_mem; struct bnxt_ctx_pg_info tim_mem; struct bnxt_ctx_pg_info *tqm_mem[BNXT_MAX_TQM_RINGS]; + +#define BNXT_CTX_MEM_INIT_QP 0 +#define BNXT_CTX_MEM_INIT_SRQ 1 +#define BNXT_CTX_MEM_INIT_CQ 2 +#define BNXT_CTX_MEM_INIT_VNIC 3 +#define BNXT_CTX_MEM_INIT_STAT 4 +#define BNXT_CTX_MEM_INIT_MRAV 5 +#define BNXT_CTX_MEM_INIT_MAX 6 + struct bnxt_mem_init mem_init[BNXT_CTX_MEM_INIT_MAX]; }; struct bnxt_fw_health { From 41435c39400071904a9b569d7bfc053c7c644bc5 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 14 Feb 2021 18:04:59 -0500 Subject: [PATCH 5/7] bnxt_en: Initialize "context kind" field for context memory blocks. If firmware provides the offset to the "context kind" field of the relevant context memory blocks, we'll initialize just that field for each block instead of initializing all of context memory. Populate the bnxt_mem_init structure with the proper offset returned by firmware. If it is older firmware and the information is not available, we set the offset to an invalid value and fall back to the old behavior of initializing every byte. Otherwise, we initialize only the "context kind" byte at the offset. Reviewed-by: Edwin Peer Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 47 ++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 888466c3ed78..2bd9358c11e0 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2688,6 +2688,23 @@ static void bnxt_free_skbs(struct bnxt *bp) bnxt_free_rx_skbs(bp); } +static void bnxt_init_ctx_mem(struct bnxt_mem_init *mem_init, void *p, int len) +{ + u8 init_val = mem_init->init_val; + u16 offset = mem_init->offset; + u8 *p2 = p; + int i; + + if (!init_val) + return; + if (offset == BNXT_MEM_INVALID_OFFSET) { + memset(p, init_val, len); + return; + } + for (i = 0; i < len; i += mem_init->size) + *(p2 + i + offset) = init_val; +} + static void bnxt_free_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem) { struct pci_dev *pdev = bp->pdev; @@ -2747,9 +2764,9 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem) if (!rmem->pg_arr[i]) return -ENOMEM; - if (rmem->mem_init && rmem->mem_init->init_val) - memset(rmem->pg_arr[i], rmem->mem_init->init_val, - rmem->page_size); + if (rmem->mem_init) + bnxt_init_ctx_mem(rmem->mem_init, rmem->pg_arr[i], + rmem->page_size); if (rmem->nr_pages > 1 || rmem->depth > 0) { if (i == rmem->nr_pages - 2 && (rmem->flags & BNXT_RMEM_RING_PTE_FLAG)) @@ -6754,13 +6771,33 @@ static void bnxt_init_ctx_initializer(struct bnxt_ctx_mem_info *ctx, struct hwrm_func_backing_store_qcaps_output *resp) { struct bnxt_mem_init *mem_init; + u16 init_mask; u8 init_val; + u8 *offset; int i; init_val = resp->ctx_kind_initializer; - mem_init = &ctx->mem_init[0]; - for (i = 0; i < BNXT_CTX_MEM_INIT_MAX; i++, mem_init++) + init_mask = le16_to_cpu(resp->ctx_init_mask); + offset = &resp->qp_init_offset; + mem_init = &ctx->mem_init[BNXT_CTX_MEM_INIT_QP]; + for (i = 0; i < BNXT_CTX_MEM_INIT_MAX; i++, mem_init++, offset++) { mem_init->init_val = init_val; + mem_init->offset = BNXT_MEM_INVALID_OFFSET; + if (!init_mask) + continue; + if (i == BNXT_CTX_MEM_INIT_STAT) + offset = &resp->stat_init_offset; + if (init_mask & (1 << i)) + mem_init->offset = *offset * 4; + else + mem_init->init_val = 0; + } + ctx->mem_init[BNXT_CTX_MEM_INIT_QP].size = ctx->qp_entry_size; + ctx->mem_init[BNXT_CTX_MEM_INIT_SRQ].size = ctx->srq_entry_size; + ctx->mem_init[BNXT_CTX_MEM_INIT_CQ].size = ctx->cq_entry_size; + ctx->mem_init[BNXT_CTX_MEM_INIT_VNIC].size = ctx->vnic_entry_size; + ctx->mem_init[BNXT_CTX_MEM_INIT_STAT].size = ctx->stat_entry_size; + ctx->mem_init[BNXT_CTX_MEM_INIT_MRAV].size = ctx->mrav_entry_size; } static int bnxt_hwrm_func_backing_store_qcaps(struct bnxt *bp) From df97b34d3ace777f90df368efe5508ddd32c16d4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 14 Feb 2021 18:05:00 -0500 Subject: [PATCH 6/7] bnxt_en: Reply to firmware's echo request async message. This is a new async message that the firmware can send to check if it can communicate with the driver. This is an added error detection scheme that firmware can use if it suspects errors in the PCIe interface. When the driver receives this async message, it will reply back echoing some data in the async message. If the firmware is not getting the reply with the proper data after some retries, error recovery will kick in. Reviewed-by: Andy Gospodarek Reviewed-by: Edwin Peer Reviewed-by: Vasundhara Volam Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 29 +++++++++++++++++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 3 +++ 2 files changed, 32 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 2bd9358c11e0..65771be802af 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -257,6 +257,7 @@ static const u16 bnxt_async_events_arr[] = { ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY, ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION, ASYNC_EVENT_CMPL_EVENT_ID_RING_MONITOR_MSG, + ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST, }; static struct workqueue_struct *bnxt_pf_wq; @@ -2099,6 +2100,20 @@ static int bnxt_async_event_process(struct bnxt *bp, bnxt_sched_reset(bp, rxr); goto async_event_process_exit; } + case ASYNC_EVENT_CMPL_EVENT_ID_ECHO_REQUEST: { + struct bnxt_fw_health *fw_health = bp->fw_health; + + netif_notice(bp, hw, bp->dev, + "Received firmware echo request, data1: 0x%x, data2: 0x%x\n", + data1, data2); + if (fw_health) { + fw_health->echo_req_data1 = data1; + fw_health->echo_req_data2 = data2; + set_bit(BNXT_FW_ECHO_REQUEST_SP_EVENT, &bp->sp_event); + break; + } + goto async_event_process_exit; + } default: goto async_event_process_exit; } @@ -11208,6 +11223,17 @@ static void bnxt_init_ethtool_link_settings(struct bnxt *bp) link_info->req_flow_ctrl = link_info->force_pause_setting; } +static void bnxt_fw_echo_reply(struct bnxt *bp) +{ + struct bnxt_fw_health *fw_health = bp->fw_health; + struct hwrm_func_echo_response_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_ECHO_RESPONSE, -1, -1); + req.event_data1 = cpu_to_le32(fw_health->echo_req_data1); + req.event_data2 = cpu_to_le32(fw_health->echo_req_data2); + hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + static void bnxt_sp_task(struct work_struct *work) { struct bnxt *bp = container_of(work, struct bnxt, sp_task); @@ -11275,6 +11301,9 @@ static void bnxt_sp_task(struct work_struct *work) if (test_and_clear_bit(BNXT_RING_COAL_NOW_SP_EVENT, &bp->sp_event)) bnxt_chk_missed_irq(bp); + if (test_and_clear_bit(BNXT_FW_ECHO_REQUEST_SP_EVENT, &bp->sp_event)) + bnxt_fw_echo_reply(bp); + /* These functions below will clear BNXT_STATE_IN_SP_TASK. They * must be the last functions to be called before exiting. */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index f5c45ea52b44..1259e68cba2a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1531,6 +1531,8 @@ struct bnxt_fw_health { u32 fw_reset_seq_regs[16]; u32 fw_reset_seq_vals[16]; u32 fw_reset_seq_delay_msec[16]; + u32 echo_req_data1; + u32 echo_req_data2; struct devlink_health_reporter *fw_reporter; struct devlink_health_reporter *fw_reset_reporter; struct devlink_health_reporter *fw_fatal_reporter; @@ -1940,6 +1942,7 @@ struct bnxt { #define BNXT_FW_RESET_NOTIFY_SP_EVENT 18 #define BNXT_FW_EXCEPTION_SP_EVENT 19 #define BNXT_LINK_CFG_CHANGE_SP_EVENT 21 +#define BNXT_FW_ECHO_REQUEST_SP_EVENT 23 struct delayed_work fw_reset_task; int fw_reset_state; From f4d95c3c194de04ae7b44f850131321c7ceb9312 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 14 Feb 2021 18:05:01 -0500 Subject: [PATCH 7/7] bnxt_en: Improve logging of error recovery settings information. We currently only log the error recovery settings if it is enabled. In some cases, firmware disables error recovery after it was initially enabled. Without logging anything, the user will not be aware of this change in setting. Log it when error recovery is disabled. Also, change the reset count value from hexadecimal to decimal. Reviewed-by: Edwin Peer Reviewed-by: Pavan Chebbi Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 65771be802af..d0f3f68faa91 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2055,14 +2055,11 @@ static int bnxt_async_event_process(struct bnxt *bp, fw_health->enabled = EVENT_DATA1_RECOVERY_ENABLED(data1); fw_health->master = EVENT_DATA1_RECOVERY_MASTER_FUNC(data1); - if (!fw_health->enabled) + if (!fw_health->enabled) { + netif_info(bp, drv, bp->dev, + "Error recovery info: error recovery[0]\n"); break; - - netif_info(bp, drv, bp->dev, - "Error recovery info: error recovery[%d], master[%d], reset count[0x%x], health status: 0x%x\n", - fw_health->enabled, fw_health->master, - bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG), - bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG)); + } fw_health->tmr_multiplier = DIV_ROUND_UP(fw_health->polling_dsecs * HZ, bp->current_interval * 10); @@ -2071,6 +2068,10 @@ static int bnxt_async_event_process(struct bnxt *bp, bnxt_fw_health_readl(bp, BNXT_FW_HEARTBEAT_REG); fw_health->last_fw_reset_cnt = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG); + netif_info(bp, drv, bp->dev, + "Error recovery info: error recovery[1], master[%d], reset count[%u], health status: 0x%x\n", + fw_health->master, fw_health->last_fw_reset_cnt, + bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG)); goto async_event_process_exit; } case ASYNC_EVENT_CMPL_EVENT_ID_DEBUG_NOTIFICATION: