net/bnxt: fix allocation of flow stat related structs
[dpdk.git] / drivers / net / bnxt / bnxt_ethdev.c
index 206111d..90fb7f6 100644 (file)
@@ -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)
 {
@@ -190,8 +191,28 @@ static uint16_t  bnxt_rss_hash_tbl_size(const struct bnxt *bp)
        return bnxt_rss_ctxts(bp) * BNXT_RSS_ENTRIES_PER_CTX_THOR;
 }
 
+static void bnxt_free_leds_info(struct bnxt *bp)
+{
+       rte_free(bp->leds);
+       bp->leds = NULL;
+}
+
+static void bnxt_free_flow_stats_info(struct bnxt *bp)
+{
+       rte_free(bp->flow_stat);
+       bp->flow_stat = NULL;
+}
+
+static void bnxt_free_cos_queues(struct bnxt *bp)
+{
+       rte_free(bp->rx_cos_queue);
+       rte_free(bp->tx_cos_queue);
+}
+
 static void bnxt_free_mem(struct bnxt *bp, bool reconfig)
 {
+       bnxt_free_flow_stats_info(bp);
+
        bnxt_free_filter_mem(bp);
        bnxt_free_vnic_attributes(bp);
        bnxt_free_vnic_mem(bp);
@@ -212,6 +233,48 @@ static void bnxt_free_mem(struct bnxt *bp, bool reconfig)
        bp->grp_info = NULL;
 }
 
+static int bnxt_alloc_leds_info(struct bnxt *bp)
+{
+       bp->leds = rte_zmalloc("bnxt_leds",
+                              BNXT_MAX_LED * sizeof(struct bnxt_led_info),
+                              0);
+       if (bp->leds == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int bnxt_alloc_cos_queues(struct bnxt *bp)
+{
+       bp->rx_cos_queue =
+               rte_zmalloc("bnxt_rx_cosq",
+                           BNXT_COS_QUEUE_COUNT *
+                           sizeof(struct bnxt_cos_queue_info),
+                           0);
+       if (bp->rx_cos_queue == NULL)
+               return -ENOMEM;
+
+       bp->tx_cos_queue =
+               rte_zmalloc("bnxt_tx_cosq",
+                           BNXT_COS_QUEUE_COUNT *
+                           sizeof(struct bnxt_cos_queue_info),
+                           0);
+       if (bp->tx_cos_queue == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int bnxt_alloc_flow_stats_info(struct bnxt *bp)
+{
+       bp->flow_stat = rte_zmalloc("bnxt_flow_xstat",
+                                   sizeof(struct bnxt_flow_stat_info), 0);
+       if (bp->flow_stat == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int bnxt_alloc_mem(struct bnxt *bp, bool reconfig)
 {
        int rc;
@@ -244,6 +307,12 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool reconfig)
        if (rc)
                goto alloc_mem_err;
 
+       if (BNXT_FLOW_XSTATS_EN(bp)) {
+               rc = bnxt_alloc_flow_stats_info(bp);
+               if (rc)
+                       goto alloc_mem_err;
+       }
+
        return 0;
 
 alloc_mem_err:
@@ -345,68 +414,72 @@ static int bnxt_register_fc_ctx_mem(struct bnxt *bp)
 {
        int rc = 0;
 
-       rc = bnxt_hwrm_ctx_rgtr(bp, bp->rx_fc_in_tbl.dma,
-                               &bp->rx_fc_in_tbl.ctx_id);
+       rc = bnxt_hwrm_ctx_rgtr(bp, bp->flow_stat->rx_fc_in_tbl.dma,
+                               &bp->flow_stat->rx_fc_in_tbl.ctx_id);
        if (rc)
                return rc;
 
        PMD_DRV_LOG(DEBUG,
                    "rx_fc_in_tbl.va = %p rx_fc_in_tbl.dma = %p"
                    " rx_fc_in_tbl.ctx_id = %d\n",
-                   bp->rx_fc_in_tbl.va,
-                   (void *)((uintptr_t)bp->rx_fc_in_tbl.dma),
-                   bp->rx_fc_in_tbl.ctx_id);
+                   bp->flow_stat->rx_fc_in_tbl.va,
+                   (void *)((uintptr_t)bp->flow_stat->rx_fc_in_tbl.dma),
+                   bp->flow_stat->rx_fc_in_tbl.ctx_id);
 
-       rc = bnxt_hwrm_ctx_rgtr(bp, bp->rx_fc_out_tbl.dma,
-                               &bp->rx_fc_out_tbl.ctx_id);
+       rc = bnxt_hwrm_ctx_rgtr(bp, bp->flow_stat->rx_fc_out_tbl.dma,
+                               &bp->flow_stat->rx_fc_out_tbl.ctx_id);
        if (rc)
                return rc;
 
        PMD_DRV_LOG(DEBUG,
                    "rx_fc_out_tbl.va = %p rx_fc_out_tbl.dma = %p"
                    " rx_fc_out_tbl.ctx_id = %d\n",
-                   bp->rx_fc_out_tbl.va,
-                   (void *)((uintptr_t)bp->rx_fc_out_tbl.dma),
-                   bp->rx_fc_out_tbl.ctx_id);
+                   bp->flow_stat->rx_fc_out_tbl.va,
+                   (void *)((uintptr_t)bp->flow_stat->rx_fc_out_tbl.dma),
+                   bp->flow_stat->rx_fc_out_tbl.ctx_id);
 
-       rc = bnxt_hwrm_ctx_rgtr(bp, bp->tx_fc_in_tbl.dma,
-                               &bp->tx_fc_in_tbl.ctx_id);
+       rc = bnxt_hwrm_ctx_rgtr(bp, bp->flow_stat->tx_fc_in_tbl.dma,
+                               &bp->flow_stat->tx_fc_in_tbl.ctx_id);
        if (rc)
                return rc;
 
        PMD_DRV_LOG(DEBUG,
                    "tx_fc_in_tbl.va = %p tx_fc_in_tbl.dma = %p"
                    " tx_fc_in_tbl.ctx_id = %d\n",
-                   bp->tx_fc_in_tbl.va,
-                   (void *)((uintptr_t)bp->tx_fc_in_tbl.dma),
-                   bp->tx_fc_in_tbl.ctx_id);
+                   bp->flow_stat->tx_fc_in_tbl.va,
+                   (void *)((uintptr_t)bp->flow_stat->tx_fc_in_tbl.dma),
+                   bp->flow_stat->tx_fc_in_tbl.ctx_id);
 
-       rc = bnxt_hwrm_ctx_rgtr(bp, bp->tx_fc_out_tbl.dma,
-                               &bp->tx_fc_out_tbl.ctx_id);
+       rc = bnxt_hwrm_ctx_rgtr(bp, bp->flow_stat->tx_fc_out_tbl.dma,
+                               &bp->flow_stat->tx_fc_out_tbl.ctx_id);
        if (rc)
                return rc;
 
        PMD_DRV_LOG(DEBUG,
                    "tx_fc_out_tbl.va = %p tx_fc_out_tbl.dma = %p"
                    " tx_fc_out_tbl.ctx_id = %d\n",
-                   bp->tx_fc_out_tbl.va,
-                   (void *)((uintptr_t)bp->tx_fc_out_tbl.dma),
-                   bp->tx_fc_out_tbl.ctx_id);
+                   bp->flow_stat->tx_fc_out_tbl.va,
+                   (void *)((uintptr_t)bp->flow_stat->tx_fc_out_tbl.dma),
+                   bp->flow_stat->tx_fc_out_tbl.ctx_id);
 
-       memset(bp->rx_fc_out_tbl.va, 0, bp->rx_fc_out_tbl.size);
+       memset(bp->flow_stat->rx_fc_out_tbl.va,
+              0,
+              bp->flow_stat->rx_fc_out_tbl.size);
        rc = bnxt_hwrm_cfa_counter_cfg(bp, BNXT_DIR_RX,
                                       CFA_COUNTER_CFG_IN_COUNTER_TYPE_FC,
-                                      bp->rx_fc_out_tbl.ctx_id,
-                                      bp->max_fc,
+                                      bp->flow_stat->rx_fc_out_tbl.ctx_id,
+                                      bp->flow_stat->max_fc,
                                       true);
        if (rc)
                return rc;
 
-       memset(bp->tx_fc_out_tbl.va, 0, bp->tx_fc_out_tbl.size);
+       memset(bp->flow_stat->tx_fc_out_tbl.va,
+              0,
+              bp->flow_stat->tx_fc_out_tbl.size);
        rc = bnxt_hwrm_cfa_counter_cfg(bp, BNXT_DIR_TX,
                                       CFA_COUNTER_CFG_IN_COUNTER_TYPE_FC,
-                                      bp->tx_fc_out_tbl.ctx_id,
-                                      bp->max_fc,
+                                      bp->flow_stat->tx_fc_out_tbl.ctx_id,
+                                      bp->flow_stat->max_fc,
                                       true);
 
        return rc;
@@ -437,33 +510,41 @@ static int bnxt_init_fc_ctx_mem(struct bnxt *bp)
        uint16_t max_fc;
        int rc = 0;
 
-       max_fc = bp->max_fc;
+       max_fc = bp->flow_stat->max_fc;
 
        sprintf(type, "bnxt_rx_fc_in_" PCI_PRI_FMT, pdev->addr.domain,
                pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
        /* 4 bytes for each counter-id */
-       rc = bnxt_alloc_ctx_mem_buf(type, max_fc * 4, &bp->rx_fc_in_tbl);
+       rc = bnxt_alloc_ctx_mem_buf(type,
+                                   max_fc * 4,
+                                   &bp->flow_stat->rx_fc_in_tbl);
        if (rc)
                return rc;
 
        sprintf(type, "bnxt_rx_fc_out_" PCI_PRI_FMT, pdev->addr.domain,
                pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
        /* 16 bytes for each counter - 8 bytes pkt_count, 8 bytes byte_count */
-       rc = bnxt_alloc_ctx_mem_buf(type, max_fc * 16, &bp->rx_fc_out_tbl);
+       rc = bnxt_alloc_ctx_mem_buf(type,
+                                   max_fc * 16,
+                                   &bp->flow_stat->rx_fc_out_tbl);
        if (rc)
                return rc;
 
        sprintf(type, "bnxt_tx_fc_in_" PCI_PRI_FMT, pdev->addr.domain,
                pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
        /* 4 bytes for each counter-id */
-       rc = bnxt_alloc_ctx_mem_buf(type, max_fc * 4, &bp->tx_fc_in_tbl);
+       rc = bnxt_alloc_ctx_mem_buf(type,
+                                   max_fc * 4,
+                                   &bp->flow_stat->tx_fc_in_tbl);
        if (rc)
                return rc;
 
        sprintf(type, "bnxt_tx_fc_out_" PCI_PRI_FMT, pdev->addr.domain,
                pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
        /* 16 bytes for each counter - 8 bytes pkt_count, 8 bytes byte_count */
-       rc = bnxt_alloc_ctx_mem_buf(type, max_fc * 16, &bp->tx_fc_out_tbl);
+       rc = bnxt_alloc_ctx_mem_buf(type,
+                                   max_fc * 16,
+                                   &bp->flow_stat->tx_fc_out_tbl);
        if (rc)
                return rc;
 
@@ -477,10 +558,11 @@ static int bnxt_init_ctx_mem(struct bnxt *bp)
        int rc = 0;
 
        if (!(bp->fw_cap & BNXT_FW_CAP_ADV_FLOW_COUNTERS) ||
-           !(BNXT_PF(bp) || BNXT_VF_IS_TRUSTED(bp)))
+           !(BNXT_PF(bp) || BNXT_VF_IS_TRUSTED(bp)) ||
+           !BNXT_FLOW_XSTATS_EN(bp))
                return 0;
 
-       rc = bnxt_hwrm_cfa_counter_qcaps(bp, &bp->max_fc);
+       rc = bnxt_hwrm_cfa_counter_qcaps(bp, &bp->flow_stat->max_fc);
        if (rc)
                return rc;
 
@@ -692,6 +774,8 @@ static uint32_t bnxt_get_speed_capabilities(struct bnxt *bp)
                speed_capa |= ETH_LINK_SPEED_50G;
        if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
                speed_capa |= ETH_LINK_SPEED_100G;
+       if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_200GB)
+               speed_capa |= ETH_LINK_SPEED_200G;
 
        if (bp->link_info.auto_mode == HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE)
                speed_capa |= ETH_LINK_SPEED_FIXED;
@@ -1197,6 +1281,9 @@ static void bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 
        bp->flags &= ~BNXT_FLAG_RX_VECTOR_PKT_MODE;
        bp->rx_cosq_cnt = 0;
+       /* All filters are deleted on a port stop. */
+       if (BNXT_FLOW_XSTATS_EN(bp))
+               bp->flow_stat->flow_count = 0;
 }
 
 static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
@@ -1213,6 +1300,9 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 
        bnxt_uninit_resources(bp, false);
 
+       bnxt_free_leds_info(bp);
+       bnxt_free_cos_queues(bp);
+
        eth_dev->dev_ops = NULL;
        eth_dev->rx_pkt_burst = NULL;
        eth_dev->tx_pkt_burst = NULL;
@@ -1751,7 +1841,7 @@ static int bnxt_rss_hash_conf_get_op(struct rte_eth_dev *eth_dev,
                }
                if (hash_types) {
                        PMD_DRV_LOG(ERR,
-                               "Unknwon RSS config from firmware (%08x), RSS disabled",
+                               "Unknown RSS config from firmware (%08x), RSS disabled",
                                vnic->hash_type);
                        return -ENOTSUP;
                }
@@ -2082,6 +2172,11 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
        if (rc)
                return rc;
 
+       if (!eth_dev->data->dev_started) {
+               PMD_DRV_LOG(ERR, "port must be started before setting vlan\n");
+               return -EINVAL;
+       }
+
        /* These operations apply to ALL existing MAC/VLAN filters */
        if (on)
                return bnxt_add_vlan_filter(bp, vlan_id);
@@ -2167,6 +2262,8 @@ static int bnxt_free_one_vnic(struct bnxt *bp, uint16_t vnic_id)
        rte_free(vnic->fw_grp_ids);
        vnic->fw_grp_ids = NULL;
 
+       vnic->rx_queue_cnt = 0;
+
        return 0;
 }
 
@@ -2396,10 +2493,11 @@ bnxt_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
        uint8_t fw_major = (bp->fw_ver >> 24) & 0xff;
        uint8_t fw_minor = (bp->fw_ver >> 16) & 0xff;
        uint8_t fw_updt = (bp->fw_ver >> 8) & 0xff;
+       uint8_t fw_rsvd = bp->fw_ver & 0xff;
        int ret;
 
-       ret = snprintf(fw_version, fw_size, "%d.%d.%d",
-                       fw_major, fw_minor, fw_updt);
+       ret = snprintf(fw_version, fw_size, "%d.%d.%d.%d",
+                       fw_major, fw_minor, fw_updt, fw_rsvd);
 
        ret += 1; /* add the size of '\0' */
        if (fw_size < (uint32_t)ret)
@@ -4636,7 +4734,7 @@ static void bnxt_free_ctx_mem(struct bnxt *bp)
        rte_memzone_free(bp->ctx->vnic_mem.ring_mem.pg_tbl_mz);
        rte_memzone_free(bp->ctx->stat_mem.ring_mem.pg_tbl_mz);
 
-       for (i = 0; i < BNXT_MAX_Q; i++) {
+       for (i = 0; i < bp->ctx->tqm_fp_rings_count + 1; i++) {
                if (bp->ctx->tqm_mem[i])
                        rte_memzone_free(bp->ctx->tqm_mem[i]->ring_mem.mz);
        }
@@ -4664,6 +4762,7 @@ int bnxt_alloc_ctx_mem(struct bnxt *bp)
        struct bnxt_ctx_pg_info *ctx_pg;
        struct bnxt_ctx_mem_info *ctx;
        uint32_t mem_size, ena, entries;
+       uint32_t entries_sp, min;
        int i, rc;
 
        rc = bnxt_hwrm_func_backing_store_qcaps(bp);
@@ -4711,16 +4810,20 @@ int bnxt_alloc_ctx_mem(struct bnxt *bp)
        if (rc)
                return rc;
 
-       entries = ctx->qp_max_l2_entries +
-                 ctx->vnic_max_vnic_entries +
-                 ctx->tqm_min_entries_per_ring;
+       min = ctx->tqm_min_entries_per_ring;
+
+       entries_sp = ctx->qp_max_l2_entries +
+                    ctx->vnic_max_vnic_entries +
+                    2 * ctx->qp_min_qp1_entries + min;
+       entries_sp = bnxt_roundup(entries_sp, ctx->tqm_entries_multiple);
+
+       entries = ctx->qp_max_l2_entries + ctx->qp_min_qp1_entries;
        entries = bnxt_roundup(entries, ctx->tqm_entries_multiple);
-       entries = clamp_t(uint32_t, entries, ctx->tqm_min_entries_per_ring,
+       entries = clamp_t(uint32_t, entries, min,
                          ctx->tqm_max_entries_per_ring);
-       for (i = 0, ena = 0; i < BNXT_MAX_Q; i++) {
+       for (i = 0, ena = 0; i < ctx->tqm_fp_rings_count + 1; i++) {
                ctx_pg = ctx->tqm_mem[i];
-               /* use min tqm entries for now. */
-               ctx_pg->entries = entries;
+               ctx_pg->entries = i ? entries : entries_sp;
                mem_size = ctx->tqm_entry_size * ctx_pg->entries;
                rc = bnxt_alloc_ctx_mem_blk(bp, ctx_pg, mem_size, "tqm_mem", i);
                if (rc)
@@ -4962,6 +5065,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;
@@ -4969,10 +5155,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;
@@ -5003,6 +5195,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)
@@ -5161,8 +5354,8 @@ bnxt_parse_devarg_flow_xstat(__rte_unused const char *key,
                return -EINVAL;
        }
 
-       bp->flow_xstat = flow_xstat;
-       if (bp->flow_xstat)
+       bp->flags |= BNXT_FLAG_FLOW_XSTATS_EN;
+       if (BNXT_FLOW_XSTATS_EN(bp))
                PMD_DRV_LOG(INFO, "flow_xstat feature enabled.\n");
 
        return 0;
@@ -5253,6 +5446,14 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev)
                            "Failed to allocate hwrm resource rc: %x\n", rc);
                goto error_free;
        }
+       rc = bnxt_alloc_leds_info(bp);
+       if (rc)
+               goto error_free;
+
+       rc = bnxt_alloc_cos_queues(bp);
+       if (rc)
+               goto error_free;
+
        rc = bnxt_init_resources(bp, false);
        if (rc)
                goto error_free;
@@ -5296,46 +5497,55 @@ static void bnxt_unregister_fc_ctx_mem(struct bnxt *bp)
 {
        bnxt_hwrm_cfa_counter_cfg(bp, BNXT_DIR_RX,
                                  CFA_COUNTER_CFG_IN_COUNTER_TYPE_FC,
-                                 bp->rx_fc_out_tbl.ctx_id,
-                                 bp->max_fc,
+                                 bp->flow_stat->rx_fc_out_tbl.ctx_id,
+                                 bp->flow_stat->max_fc,
                                  false);
 
        bnxt_hwrm_cfa_counter_cfg(bp, BNXT_DIR_TX,
                                  CFA_COUNTER_CFG_IN_COUNTER_TYPE_FC,
-                                 bp->tx_fc_out_tbl.ctx_id,
-                                 bp->max_fc,
+                                 bp->flow_stat->tx_fc_out_tbl.ctx_id,
+                                 bp->flow_stat->max_fc,
                                  false);
 
-       if (bp->rx_fc_in_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
-               bnxt_hwrm_ctx_unrgtr(bp, bp->rx_fc_in_tbl.ctx_id);
-       bp->rx_fc_in_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
+       if (bp->flow_stat->rx_fc_in_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
+               bnxt_hwrm_ctx_unrgtr(bp, bp->flow_stat->rx_fc_in_tbl.ctx_id);
+       bp->flow_stat->rx_fc_in_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
 
-       if (bp->rx_fc_out_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
-               bnxt_hwrm_ctx_unrgtr(bp, bp->rx_fc_out_tbl.ctx_id);
-       bp->rx_fc_out_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
+       if (bp->flow_stat->rx_fc_out_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
+               bnxt_hwrm_ctx_unrgtr(bp, bp->flow_stat->rx_fc_out_tbl.ctx_id);
+       bp->flow_stat->rx_fc_out_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
 
-       if (bp->tx_fc_in_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
-               bnxt_hwrm_ctx_unrgtr(bp, bp->tx_fc_in_tbl.ctx_id);
-       bp->tx_fc_in_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
+       if (bp->flow_stat->tx_fc_in_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
+               bnxt_hwrm_ctx_unrgtr(bp, bp->flow_stat->tx_fc_in_tbl.ctx_id);
+       bp->flow_stat->tx_fc_in_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
 
-       if (bp->tx_fc_out_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
-               bnxt_hwrm_ctx_unrgtr(bp, bp->tx_fc_out_tbl.ctx_id);
-       bp->tx_fc_out_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
+       if (bp->flow_stat->tx_fc_out_tbl.ctx_id != BNXT_CTX_VAL_INVAL)
+               bnxt_hwrm_ctx_unrgtr(bp, bp->flow_stat->tx_fc_out_tbl.ctx_id);
+       bp->flow_stat->tx_fc_out_tbl.ctx_id = BNXT_CTX_VAL_INVAL;
 }
 
 static void bnxt_uninit_fc_ctx_mem(struct bnxt *bp)
 {
        bnxt_unregister_fc_ctx_mem(bp);
 
-       bnxt_free_ctx_mem_buf(&bp->rx_fc_in_tbl);
-       bnxt_free_ctx_mem_buf(&bp->rx_fc_out_tbl);
-       bnxt_free_ctx_mem_buf(&bp->tx_fc_in_tbl);
-       bnxt_free_ctx_mem_buf(&bp->tx_fc_out_tbl);
+       bnxt_free_ctx_mem_buf(&bp->flow_stat->rx_fc_in_tbl);
+       bnxt_free_ctx_mem_buf(&bp->flow_stat->rx_fc_out_tbl);
+       bnxt_free_ctx_mem_buf(&bp->flow_stat->tx_fc_in_tbl);
+       bnxt_free_ctx_mem_buf(&bp->flow_stat->tx_fc_out_tbl);
 }
 
 static void bnxt_uninit_ctx_mem(struct bnxt *bp)
 {
-       bnxt_uninit_fc_ctx_mem(bp);
+       if (BNXT_FLOW_XSTATS_EN(bp))
+               bnxt_uninit_fc_ctx_mem(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
@@ -5358,11 +5568,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);