#include <rte_io.h>
#define HWRM_CMD_TIMEOUT 6000000
+#define HWRM_SHORT_CMD_TIMEOUT 50000
#define HWRM_SPEC_CODE_1_8_3 0x10803
#define HWRM_VERSION_1_9_1 0x10901
#define HWRM_VERSION_1_9_2 0x10903
GRCPF_REG_KONG_CHANNEL_OFFSET : GRCPF_REG_CHIMP_CHANNEL_OFFSET;
uint16_t mb_trigger_offset = use_kong_mb ?
GRCPF_REG_KONG_COMM_TRIGGER : GRCPF_REG_CHIMP_COMM_TRIGGER;
+ uint32_t timeout;
+
+ /* Do not send HWRM commands to firmware in error state */
+ if (bp->flags & BNXT_FLAG_FATAL_ERROR)
+ return 0;
+
+ /* For VER_GET command, set timeout as 50ms */
+ if (rte_cpu_to_le_16(req->req_type) == HWRM_VER_GET)
+ timeout = HWRM_SHORT_CMD_TIMEOUT;
+ else
+ timeout = HWRM_CMD_TIMEOUT;
if (bp->flags & BNXT_FLAG_SHORT_CMD ||
msg_len > bp->max_req_len) {
rte_write32(1, bar);
/* Poll for the valid bit */
- for (i = 0; i < HWRM_CMD_TIMEOUT; i++) {
+ for (i = 0; i < timeout; i++) {
/* Sanity check on the resp->resp_len */
rte_rmb();
if (resp->resp_len && resp->resp_len <= bp->max_resp_len) {
rte_delay_us(1);
}
- if (i >= HWRM_CMD_TIMEOUT) {
- PMD_DRV_LOG(ERR, "Error sending msg 0x%04x\n",
- req->req_type);
- goto err_ret;
+ if (i >= timeout) {
+ /* Suppress VER_GET timeout messages during reset recovery */
+ if (bp->flags & BNXT_FLAG_FW_RESET &&
+ rte_cpu_to_le_16(req->req_type) == HWRM_VER_GET)
+ return -ETIMEDOUT;
+
+ PMD_DRV_LOG(ERR, "Error(timeout) sending msg 0x%04x\n",
+ req->req_type);
+ return -ETIMEDOUT;
}
return 0;
-
-err_ret:
- return -1;
}
/*
if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_STATS_SUPPORTED)
bp->flags |= BNXT_FLAG_EXT_STATS_SUPPORTED;
+ if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERROR_RECOVERY_CAPABLE) {
+ bp->flags |= BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+ PMD_DRV_LOG(DEBUG, "Adapter Error recovery SUPPORTED\n");
+ } else {
+ bp->flags &= ~BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+ }
+
HWRM_UNLOCK();
return rc;
int bnxt_hwrm_func_driver_register(struct bnxt *bp)
{
int rc;
+ uint32_t flags = 0;
struct hwrm_func_drv_rgtr_input req = {.req_type = 0 };
struct hwrm_func_drv_rgtr_output *resp = bp->hwrm_cmd_resp_addr;
if (bp->flags & BNXT_FLAG_REGISTERED)
return 0;
+ flags = HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_HOT_RESET_SUPPORT;
+ if (bp->flags & BNXT_FLAG_FW_CAP_ERROR_RECOVERY)
+ flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ERROR_RECOVERY_SUPPORT;
+
+ /* PFs and trusted VFs should indicate the support of the
+ * Master capability on non Stingray platform
+ */
+ if ((BNXT_PF(bp) || BNXT_VF_IS_TRUSTED(bp)) && !BNXT_STINGRAY(bp))
+ flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_MASTER_SUPPORT;
+
HWRM_PREP(req, FUNC_DRV_RGTR, BNXT_USE_CHIMP_MB);
req.enables = rte_cpu_to_le_32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
* this HWRM sniffer list in FW because DPDK PF driver does
* not support this.
*/
- req.flags =
- rte_cpu_to_le_32(HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_NONE_MODE);
+ flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_FWD_NONE_MODE;
}
+ req.flags = rte_cpu_to_le_32(flags);
+
req.async_event_fwd[0] |=
rte_cpu_to_le_32(ASYNC_CMPL_EVENT_ID_LINK_STATUS_CHANGE |
ASYNC_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED |
- ASYNC_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
+ ASYNC_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE |
+ ASYNC_CMPL_EVENT_ID_RESET_NOTIFY);
+ if (bp->flags & BNXT_FLAG_FW_CAP_ERROR_RECOVERY)
+ req.async_event_fwd[0] |=
+ rte_cpu_to_le_32(ASYNC_CMPL_EVENT_ID_ERROR_RECOVERY);
req.async_event_fwd[1] |=
rte_cpu_to_le_32(ASYNC_CMPL_EVENT_ID_PF_DRVR_UNLOAD |
ASYNC_CMPL_EVENT_ID_VF_CFG_CHANGE);
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
+
+ flags = rte_le_to_cpu_32(resp->flags);
+ if (flags & HWRM_FUNC_DRV_RGTR_OUTPUT_FLAGS_IF_CHANGE_SUPPORTED)
+ bp->flags |= BNXT_FLAG_FW_CAP_IF_CHANGE;
+
HWRM_UNLOCK();
bp->flags |= BNXT_FLAG_REGISTERED;
req.num_tx_rings = rte_cpu_to_le_16(bp->tx_nr_rings);
req.num_rx_rings = rte_cpu_to_le_16(bp->rx_nr_rings *
AGG_RING_MULTIPLIER);
- req.num_stat_ctxs = rte_cpu_to_le_16(bp->rx_nr_rings + bp->tx_nr_rings);
+ req.num_stat_ctxs = rte_cpu_to_le_16(bp->rx_nr_rings +
+ bp->tx_nr_rings +
+ BNXT_NUM_ASYNC_CPR(bp));
req.num_cmpl_rings = rte_cpu_to_le_16(bp->rx_nr_rings +
- bp->tx_nr_rings);
+ bp->tx_nr_rings +
+ BNXT_NUM_ASYNC_CPR(bp));
req.num_vnics = rte_cpu_to_le_16(bp->rx_nr_rings);
if (bp->vf_resv_strategy ==
HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESV_STRATEGY_MINIMAL_STATIC) {
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
- HWRM_CHECK_RESULT();
+ if (bp->flags & BNXT_FLAG_FW_RESET)
+ HWRM_CHECK_RESULT_SILENT();
+ else
+ HWRM_CHECK_RESULT();
PMD_DRV_LOG(INFO, "%d.%d.%d:%d.%d.%d\n",
resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
HWRM_CHECK_RESULT();
HWRM_UNLOCK();
- bp->flags &= ~BNXT_FLAG_REGISTERED;
-
return rc;
}
PMD_DRV_LOG(ERR, "hwrm alloc invalid ring type %d\n",
ring_type);
HWRM_UNLOCK();
- return -1;
+ return -EINVAL;
}
req.enables = rte_cpu_to_le_32(enables);
{
int i;
int rc = 0;
- int nr_ctxs = bp->max_ring_grps;
+ int nr_ctxs = vnic->num_lb_ctxts;
struct hwrm_vnic_rss_cfg_input req = {.req_type = 0 };
struct hwrm_vnic_rss_cfg_output *resp = bp->hwrm_cmd_resp_addr;
- if (!(vnic->rss_table && vnic->hash_type))
- return 0;
-
- HWRM_PREP(req, VNIC_RSS_CFG, BNXT_USE_CHIMP_MB);
+ for (i = 0; i < nr_ctxs; i++) {
+ HWRM_PREP(req, VNIC_RSS_CFG, BNXT_USE_CHIMP_MB);
- req.vnic_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
- req.hash_type = rte_cpu_to_le_32(vnic->hash_type);
- req.hash_mode_flags = vnic->hash_mode;
+ req.vnic_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
+ req.hash_type = rte_cpu_to_le_32(vnic->hash_type);
+ req.hash_mode_flags = vnic->hash_mode;
- req.hash_key_tbl_addr =
- rte_cpu_to_le_64(vnic->rss_hash_key_dma_addr);
+ req.hash_key_tbl_addr =
+ rte_cpu_to_le_64(vnic->rss_hash_key_dma_addr);
- for (i = 0; i < nr_ctxs; i++) {
req.ring_grp_tbl_addr =
rte_cpu_to_le_64(vnic->rss_table_dma_addr +
i * HW_HASH_INDEX_SIZE);
BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
+ HWRM_UNLOCK();
}
- HWRM_UNLOCK();
-
return rc;
}
struct hwrm_vnic_rss_cfg_input req = {.req_type = 0 };
struct hwrm_vnic_rss_cfg_output *resp = bp->hwrm_cmd_resp_addr;
+ if (!vnic->rss_table)
+ return 0;
+
if (BNXT_CHIP_THOR(bp))
return bnxt_hwrm_vnic_rss_cfg_thor(bp, vnic);
return rc;
}
-static void bnxt_free_nq_ring(struct bnxt *bp, struct bnxt_cp_ring_info *cpr)
+void bnxt_free_nq_ring(struct bnxt *bp, struct bnxt_cp_ring_info *cpr)
{
struct bnxt_ring *cp_ring = cpr->cp_ring_struct;
memset(cpr->cp_desc_ring, 0, cpr->cp_ring_struct->ring_size *
sizeof(*cpr->cp_desc_ring));
cpr->cp_raw_cons = 0;
+ cpr->valid = 0;
}
-static void bnxt_free_cp_ring(struct bnxt *bp, struct bnxt_cp_ring_info *cpr)
+void bnxt_free_cp_ring(struct bnxt *bp, struct bnxt_cp_ring_info *cpr)
{
struct bnxt_ring *cp_ring = cpr->cp_ring_struct;
STAILQ_FOREACH(flow, &vnic->flow_list, next) {
filter = flow->filter;
- PMD_DRV_LOG(ERR, "filter type %d\n", filter->filter_type);
+ PMD_DRV_LOG(DEBUG, "filter type %d\n", filter->filter_type);
if (filter->filter_type == HWRM_CFA_EM_FILTER)
rc = bnxt_hwrm_clear_em_filter(bp, filter);
else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
if (BNXT_VF(bp) && (flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_TRUSTED_VF)) {
bp->flags |= BNXT_FLAG_TRUSTED_VF_EN;
PMD_DRV_LOG(INFO, "Trusted VF cap enabled\n");
+ } else if (BNXT_VF(bp) &&
+ !(flags & HWRM_FUNC_QCFG_OUTPUT_FLAGS_TRUSTED_VF)) {
+ bp->flags &= ~BNXT_FLAG_TRUSTED_VF_EN;
+ PMD_DRV_LOG(INFO, "Trusted VF cap disabled\n");
}
if (mtu)
HWRM_PREP(req, FUNC_QCFG, BNXT_USE_CHIMP_MB);
req.fid = rte_cpu_to_le_16(bp->pf.vf_info[vf].fid);
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
- if (rc) {
- PMD_DRV_LOG(ERR, "hwrm_func_qcfg failed rc:%d\n", rc);
- return -1;
- } else if (resp->error_code) {
- rc = rte_le_to_cpu_16(resp->error_code);
- PMD_DRV_LOG(ERR, "hwrm_func_qcfg error %d\n", rc);
- return -1;
- }
+ HWRM_CHECK_RESULT();
rc = rte_le_to_cpu_16(resp->vlan);
HWRM_UNLOCK();
if (!BNXT_PF(bp)) {
PMD_DRV_LOG(ERR, "Attempt to allcoate VFs on a VF!\n");
- return -1;
+ return -EINVAL;
}
rc = bnxt_hwrm_func_qcaps(bp);
if (!BNXT_PF(bp)) {
PMD_DRV_LOG(ERR, "Attempt to allcoate VFs on a VF!\n");
- return -1;
+ return -EINVAL;
}
rc = bnxt_hwrm_func_qcaps(bp);
req.enables = rte_cpu_to_le_32(
HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
req.async_event_cr = rte_cpu_to_le_16(
- bp->def_cp_ring->cp_ring_struct->fw_ring_id);
+ bp->async_cp_ring->cp_ring_struct->fw_ring_id);
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
req.enables = rte_cpu_to_le_32(
HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
req.async_event_cr = rte_cpu_to_le_16(
- bp->def_cp_ring->cp_ring_struct->fw_ring_id);
+ bp->async_cp_ring->cp_ring_struct->fw_ring_id);
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
- HWRM_UNLOCK();
- if (!rc) {
- *entries = rte_le_to_cpu_32(resp->entries);
- *length = rte_le_to_cpu_32(resp->entry_length);
- }
+ *entries = rte_le_to_cpu_32(resp->entries);
+ *length = rte_le_to_cpu_32(resp->entry_length);
+
+ HWRM_UNLOCK();
return rc;
}
vnic_id_sz = bp->pf.total_vnics * sizeof(*vnic_ids);
vnic_ids = rte_malloc("bnxt_hwrm_vf_vnic_ids_query", vnic_id_sz,
RTE_CACHE_LINE_SIZE);
- if (vnic_ids == NULL) {
- rc = -ENOMEM;
- return rc;
- }
+ if (vnic_ids == NULL)
+ return -ENOMEM;
+
for (sz = 0; sz < vnic_id_sz; sz += getpagesize())
rte_mem_lock_page(((char *)vnic_ids) + sz);
vnic_id_sz = bp->pf.total_vnics * sizeof(*vnic_ids);
vnic_ids = rte_malloc("bnxt_hwrm_vf_vnic_ids_query", vnic_id_sz,
RTE_CACHE_LINE_SIZE);
- if (vnic_ids == NULL) {
- rc = -ENOMEM;
- return rc;
- }
+ if (vnic_ids == NULL)
+ return -ENOMEM;
for (sz = 0; sz < vnic_id_sz; sz += getpagesize())
rte_mem_lock_page(((char *)vnic_ids) + sz);
PMD_DRV_LOG(ERR, "No default VNIC\n");
exit:
rte_free(vnic_ids);
- return -1;
+ return rc;
}
int bnxt_hwrm_set_em_filter(struct bnxt *bp,
struct hwrm_vnic_rss_cfg_output *resp = bp->hwrm_cmd_resp_addr;
uint8_t *rx_queue_state = bp->eth_dev->data->rx_queue_state;
struct hwrm_vnic_rss_cfg_input req = {.req_type = 0 };
- int nr_ctxs = bp->max_ring_grps;
struct bnxt_rx_queue **rxqs = bp->rx_queues;
uint16_t *ring_tbl = vnic->rss_table;
+ int nr_ctxs = vnic->num_lb_ctxts;
int max_rings = bp->rx_nr_rings;
int i, j, k, cnt;
int rc = 0;
- HWRM_PREP(req, VNIC_RSS_CFG, BNXT_USE_CHIMP_MB);
-
- req.vnic_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
- req.hash_type = rte_cpu_to_le_32(vnic->hash_type);
- req.hash_mode_flags = vnic->hash_mode;
-
- req.ring_grp_tbl_addr =
- rte_cpu_to_le_64(vnic->rss_table_dma_addr);
- req.hash_key_tbl_addr =
- rte_cpu_to_le_64(vnic->rss_hash_key_dma_addr);
-
for (i = 0, k = 0; i < nr_ctxs; i++) {
struct bnxt_rx_ring_info *rxr;
struct bnxt_cp_ring_info *cpr;
+ HWRM_PREP(req, VNIC_RSS_CFG, BNXT_USE_CHIMP_MB);
+
+ req.vnic_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
+ req.hash_type = rte_cpu_to_le_32(vnic->hash_type);
+ req.hash_mode_flags = vnic->hash_mode;
+
+ req.ring_grp_tbl_addr =
+ rte_cpu_to_le_64(vnic->rss_table_dma_addr +
+ i * BNXT_RSS_ENTRIES_PER_CTX_THOR *
+ 2 * sizeof(*ring_tbl));
+ req.hash_key_tbl_addr =
+ rte_cpu_to_le_64(vnic->rss_hash_key_dma_addr);
+
req.ring_table_pair_index = i;
req.rss_ctx_idx = rte_cpu_to_le_16(vnic->fw_grp_ids[i]);
BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
+ HWRM_UNLOCK();
}
- HWRM_UNLOCK();
-
return rc;
}
bp->hwrm_cmd_resp_addr;
int rc = 0;
- HWRM_PREP(req, CFA_REDIRECT_TUNNEL_TYPE_ALLOC, BNXT_USE_KONG(bp));
+ HWRM_PREP(req, CFA_REDIRECT_TUNNEL_TYPE_ALLOC, BNXT_USE_CHIMP_MB);
req.tunnel_type = type;
req.dest_fid = bp->fw_fid;
- rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_KONG(bp));
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
HWRM_UNLOCK();
bp->hwrm_cmd_resp_addr;
int rc = 0;
- HWRM_PREP(req, CFA_REDIRECT_TUNNEL_TYPE_FREE, BNXT_USE_KONG(bp));
+ HWRM_PREP(req, CFA_REDIRECT_TUNNEL_TYPE_FREE, BNXT_USE_CHIMP_MB);
req.tunnel_type = type;
req.dest_fid = bp->fw_fid;
- rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_KONG(bp));
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
HWRM_UNLOCK();
bp->hwrm_cmd_resp_addr;
int rc = 0;
- HWRM_PREP(req, CFA_REDIRECT_QUERY_TUNNEL_TYPE, BNXT_USE_KONG(bp));
+ HWRM_PREP(req, CFA_REDIRECT_QUERY_TUNNEL_TYPE, BNXT_USE_CHIMP_MB);
req.src_fid = bp->fw_fid;
- rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_KONG(bp));
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
if (type)
- *type = resp->tunnel_mask;
+ *type = rte_le_to_cpu_32(resp->tunnel_mask);
HWRM_UNLOCK();
bp->hwrm_cmd_resp_addr;
int rc = 0;
- HWRM_PREP(req, CFA_REDIRECT_TUNNEL_TYPE_INFO, BNXT_USE_KONG(bp));
+ HWRM_PREP(req, CFA_REDIRECT_TUNNEL_TYPE_INFO, BNXT_USE_CHIMP_MB);
req.src_fid = bp->fw_fid;
req.tunnel_type = tun_type;
- rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_KONG(bp));
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
HWRM_CHECK_RESULT();
if (dst_fid)
- *dst_fid = resp->dest_fid;
+ *dst_fid = rte_le_to_cpu_16(resp->dest_fid);
PMD_DRV_LOG(DEBUG, "dst_fid: %x\n", resp->dest_fid);
return rc;
}
+
+int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
+{
+ struct hwrm_func_drv_if_change_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_func_drv_if_change_input req = {0};
+ uint32_t flags;
+ int rc;
+
+ if (!(bp->flags & BNXT_FLAG_FW_CAP_IF_CHANGE))
+ return 0;
+
+ /* Do not issue FUNC_DRV_IF_CHANGE during reset recovery.
+ * If we issue FUNC_DRV_IF_CHANGE with flags down before
+ * FUNC_DRV_UNRGTR, FW resets before FUNC_DRV_UNRGTR
+ */
+ if (!up && (bp->flags & BNXT_FLAG_FW_RESET))
+ return 0;
+
+ HWRM_PREP(req, FUNC_DRV_IF_CHANGE, BNXT_USE_CHIMP_MB);
+
+ if (up)
+ req.flags =
+ rte_cpu_to_le_32(HWRM_FUNC_DRV_IF_CHANGE_INPUT_FLAGS_UP);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
+
+ HWRM_CHECK_RESULT();
+ flags = rte_le_to_cpu_32(resp->flags);
+ HWRM_UNLOCK();
+
+ if (flags & HWRM_FUNC_DRV_IF_CHANGE_OUTPUT_FLAGS_HOT_FW_RESET_DONE) {
+ PMD_DRV_LOG(INFO, "FW reset happened while port was down\n");
+ bp->flags |= BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE;
+ }
+
+ return 0;
+}
+
+int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp)
+{
+ struct hwrm_error_recovery_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+ struct bnxt_error_recovery_info *info = bp->recovery_info;
+ struct hwrm_error_recovery_qcfg_input req = {0};
+ uint32_t flags = 0;
+ unsigned int i;
+ int rc;
+
+ /* Older FW does not have error recovery support */
+ if (!(bp->flags & BNXT_FLAG_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, ERROR_RECOVERY_QCFG, BNXT_USE_CHIMP_MB);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
+
+ HWRM_CHECK_RESULT();
+
+ flags = rte_le_to_cpu_32(resp->flags);
+ if (flags & HWRM_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_HOST)
+ info->flags |= BNXT_FLAG_ERROR_RECOVERY_HOST;
+ else if (flags & HWRM_ERROR_RECOVERY_QCFG_OUTPUT_FLAGS_CO_CPU)
+ info->flags |= BNXT_FLAG_ERROR_RECOVERY_CO_CPU;
+
+ if ((info->flags & BNXT_FLAG_ERROR_RECOVERY_CO_CPU) &&
+ !(bp->flags & BNXT_FLAG_KONG_MB_EN)) {
+ rc = -EINVAL;
+ goto err;
+ }
+
+ /* FW returned values are in units of 100msec */
+ info->driver_polling_freq =
+ rte_le_to_cpu_32(resp->driver_polling_freq) * 100;
+ info->master_func_wait_period =
+ rte_le_to_cpu_32(resp->master_func_wait_period) * 100;
+ info->normal_func_wait_period =
+ rte_le_to_cpu_32(resp->normal_func_wait_period) * 100;
+ info->master_func_wait_period_after_reset =
+ rte_le_to_cpu_32(resp->master_func_wait_period_after_reset) * 100;
+ info->max_bailout_time_after_reset =
+ rte_le_to_cpu_32(resp->max_bailout_time_after_reset) * 100;
+ info->status_regs[BNXT_FW_STATUS_REG] =
+ rte_le_to_cpu_32(resp->fw_health_status_reg);
+ info->status_regs[BNXT_FW_HEARTBEAT_CNT_REG] =
+ rte_le_to_cpu_32(resp->fw_heartbeat_reg);
+ info->status_regs[BNXT_FW_RECOVERY_CNT_REG] =
+ rte_le_to_cpu_32(resp->fw_reset_cnt_reg);
+ info->status_regs[BNXT_FW_RESET_INPROG_REG] =
+ rte_le_to_cpu_32(resp->reset_inprogress_reg);
+ info->reg_array_cnt =
+ rte_le_to_cpu_32(resp->reg_array_cnt);
+
+ if (info->reg_array_cnt >= BNXT_NUM_RESET_REG) {
+ rc = -EINVAL;
+ goto err;
+ }
+
+ for (i = 0; i < info->reg_array_cnt; i++) {
+ info->reset_reg[i] =
+ rte_le_to_cpu_32(resp->reset_reg[i]);
+ info->reset_reg_val[i] =
+ rte_le_to_cpu_32(resp->reset_reg_val[i]);
+ info->delay_after_reset[i] =
+ resp->delay_after_reset[i];
+ }
+err:
+ HWRM_UNLOCK();
+
+ /* Map the FW status registers */
+ if (!rc)
+ rc = bnxt_map_fw_health_status_regs(bp);
+
+ if (rc) {
+ rte_free(bp->recovery_info);
+ bp->recovery_info = NULL;
+ }
+ return rc;
+}
+
+int bnxt_hwrm_fw_reset(struct bnxt *bp)
+{
+ struct hwrm_fw_reset_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_fw_reset_input req = {0};
+ int rc;
+
+ if (!BNXT_PF(bp))
+ return -EOPNOTSUPP;
+
+ HWRM_PREP(req, FW_RESET, BNXT_USE_KONG(bp));
+
+ req.embedded_proc_type =
+ HWRM_FW_RESET_INPUT_EMBEDDED_PROC_TYPE_CHIP;
+ req.selfrst_status =
+ HWRM_FW_RESET_INPUT_SELFRST_STATUS_SELFRSTASAP;
+ req.flags = HWRM_FW_RESET_INPUT_FLAGS_RESET_GRACEFUL;
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req),
+ BNXT_USE_KONG(bp));
+
+ HWRM_CHECK_RESULT();
+ HWRM_UNLOCK();
+
+ return rc;
+}