#include <rte_malloc.h>
#include <rte_cycles.h>
#include <rte_alarm.h>
+#include <rte_kvargs.h>
#include "bnxt.h"
#include "bnxt_filter.h"
DEV_RX_OFFLOAD_SCATTER | \
DEV_RX_OFFLOAD_RSS_HASH)
+#define BNXT_DEVARG_TRUFLOW "host-based-truflow"
+#define BNXT_DEVARG_FLOW_XSTAT "flow-xstat"
+static const char *const bnxt_dev_args[] = {
+ BNXT_DEVARG_TRUFLOW,
+ BNXT_DEVARG_FLOW_XSTAT,
+ NULL
+};
+
+/*
+ * truflow == false to disable the feature
+ * truflow == true to enable the feature
+ */
+#define BNXT_DEVARG_TRUFLOW_INVALID(truflow) ((truflow) > 1)
+
+/*
+ * flow_xstat == false to disable the feature
+ * flow_xstat == true to enable the feature
+ */
+#define BNXT_DEVARG_FLOW_XSTAT_INVALID(flow_xstat) ((flow_xstat) > 1)
+
static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
static void bnxt_print_link_info(struct rte_eth_dev *eth_dev);
static int bnxt_dev_uninit(struct rte_eth_dev *eth_dev);
static int bnxt_init_resources(struct bnxt *bp, bool reconfig_dev);
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)
{
* High level utility functions
*/
-uint16_t bnxt_rss_ctxts(const struct bnxt *bp)
+static uint16_t bnxt_rss_ctxts(const struct bnxt *bp)
{
if (!BNXT_CHIP_THOR(bp))
return 1;
return bnxt_rss_ctxts(bp) * BNXT_RSS_ENTRIES_PER_CTX_THOR;
}
+static void bnxt_free_pf_info(struct bnxt *bp)
+{
+ rte_free(bp->pf);
+}
+
+static void bnxt_free_link_info(struct bnxt *bp)
+{
+ rte_free(bp->link_info);
+}
+
+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);
bp->grp_info = NULL;
}
+static int bnxt_alloc_pf_info(struct bnxt *bp)
+{
+ bp->pf = rte_zmalloc("bnxt_pf_info", sizeof(struct bnxt_pf_info), 0);
+ if (bp->pf == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bnxt_alloc_link_info(struct bnxt *bp)
+{
+ bp->link_info =
+ rte_zmalloc("bnxt_link_info", sizeof(struct bnxt_link_info), 0);
+ if (bp->link_info == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+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;
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:
return rc;
}
-static int bnxt_init_chip(struct bnxt *bp)
+static int bnxt_setup_one_vnic(struct bnxt *bp, uint16_t vnic_id)
{
+ struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+ uint64_t rx_offloads = dev_conf->rxmode.offloads;
struct bnxt_rx_queue *rxq;
+ unsigned int j;
+ int rc;
+
+ rc = bnxt_vnic_grp_alloc(bp, vnic);
+ if (rc)
+ goto err_out;
+
+ PMD_DRV_LOG(DEBUG, "vnic[%d] = %p vnic->fw_grp_ids = %p\n",
+ vnic_id, vnic, vnic->fw_grp_ids);
+
+ rc = bnxt_hwrm_vnic_alloc(bp, vnic);
+ if (rc)
+ goto err_out;
+
+ /* Alloc RSS context only if RSS mode is enabled */
+ if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS) {
+ int j, nr_ctxs = bnxt_rss_ctxts(bp);
+
+ rc = 0;
+ for (j = 0; j < nr_ctxs; j++) {
+ rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic, j);
+ if (rc)
+ break;
+ }
+ if (rc) {
+ PMD_DRV_LOG(ERR,
+ "HWRM vnic %d ctx %d alloc failure rc: %x\n",
+ vnic_id, j, rc);
+ goto err_out;
+ }
+ vnic->num_lb_ctxts = nr_ctxs;
+ }
+
+ /*
+ * Firmware sets pf pair in default vnic cfg. If the VLAN strip
+ * setting is not available at this time, it will not be
+ * configured correctly in the CFA.
+ */
+ if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
+ vnic->vlan_strip = true;
+ else
+ vnic->vlan_strip = false;
+
+ rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+ if (rc)
+ goto err_out;
+
+ rc = bnxt_set_hwrm_vnic_filters(bp, vnic);
+ if (rc)
+ goto err_out;
+
+ for (j = 0; j < bp->rx_num_qs_per_vnic; j++) {
+ rxq = bp->eth_dev->data->rx_queues[j];
+
+ PMD_DRV_LOG(DEBUG,
+ "rxq[%d]->vnic=%p vnic->fw_grp_ids=%p\n",
+ j, rxq->vnic, rxq->vnic->fw_grp_ids);
+
+ if (BNXT_HAS_RING_GRPS(bp) && rxq->rx_deferred_start)
+ rxq->vnic->fw_grp_ids[j] = INVALID_HW_RING_ID;
+ else
+ vnic->rx_queue_cnt++;
+ }
+
+ PMD_DRV_LOG(DEBUG, "vnic->rx_queue_cnt = %d\n", vnic->rx_queue_cnt);
+
+ rc = bnxt_vnic_rss_configure(bp, vnic);
+ if (rc)
+ goto err_out;
+
+ bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
+
+ if (rx_offloads & DEV_RX_OFFLOAD_TCP_LRO)
+ bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 1);
+ else
+ bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 0);
+
+ return 0;
+err_out:
+ PMD_DRV_LOG(ERR, "HWRM vnic %d cfg failure rc: %x\n",
+ vnic_id, rc);
+ return rc;
+}
+
+static int bnxt_register_fc_ctx_mem(struct bnxt *bp)
+{
+ int rc = 0;
+
+ 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->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->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->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->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->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->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->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->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->flow_stat->rx_fc_out_tbl.ctx_id,
+ bp->flow_stat->max_fc,
+ true);
+ if (rc)
+ return rc;
+
+ 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->flow_stat->tx_fc_out_tbl.ctx_id,
+ bp->flow_stat->max_fc,
+ true);
+
+ return rc;
+}
+
+static int bnxt_alloc_ctx_mem_buf(char *type, size_t size,
+ struct bnxt_ctx_mem_buf_info *ctx)
+{
+ if (!ctx)
+ return -EINVAL;
+
+ ctx->va = rte_zmalloc(type, size, 0);
+ if (ctx->va == NULL)
+ return -ENOMEM;
+ rte_mem_lock_page(ctx->va);
+ ctx->size = size;
+ ctx->dma = rte_mem_virt2iova(ctx->va);
+ if (ctx->dma == RTE_BAD_IOVA)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int bnxt_init_fc_ctx_mem(struct bnxt *bp)
+{
+ struct rte_pci_device *pdev = bp->pdev;
+ char type[RTE_MEMZONE_NAMESIZE];
+ uint16_t max_fc;
+ int rc = 0;
+
+ 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->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->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->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->flow_stat->tx_fc_out_tbl);
+ if (rc)
+ return rc;
+
+ rc = bnxt_register_fc_ctx_mem(bp);
+
+ return rc;
+}
+
+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_FLOW_XSTATS_EN(bp))
+ return 0;
+
+ rc = bnxt_hwrm_cfa_counter_qcaps(bp, &bp->flow_stat->max_fc);
+ if (rc)
+ return rc;
+
+ rc = bnxt_init_fc_ctx_mem(bp);
+
+ return rc;
+}
+
+static int bnxt_init_chip(struct bnxt *bp)
+{
struct rte_eth_link new;
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(bp->eth_dev);
- struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
- uint64_t rx_offloads = dev_conf->rxmode.offloads;
uint32_t intr_vector = 0;
uint32_t queue_id, base = BNXT_MISC_VEC_ID;
uint32_t vec = BNXT_MISC_VEC_ID;
/* VNIC configuration */
for (i = 0; i < bp->nr_vnics; i++) {
- struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
- struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
-
- rc = bnxt_vnic_grp_alloc(bp, vnic);
+ rc = bnxt_setup_one_vnic(bp, i);
if (rc)
goto err_out;
-
- PMD_DRV_LOG(DEBUG, "vnic[%d] = %p vnic->fw_grp_ids = %p\n",
- i, vnic, vnic->fw_grp_ids);
-
- rc = bnxt_hwrm_vnic_alloc(bp, vnic);
- if (rc) {
- PMD_DRV_LOG(ERR, "HWRM vnic %d alloc failure rc: %x\n",
- i, rc);
- goto err_out;
- }
-
- /* Alloc RSS context only if RSS mode is enabled */
- if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS) {
- int j, nr_ctxs = bnxt_rss_ctxts(bp);
-
- rc = 0;
- for (j = 0; j < nr_ctxs; j++) {
- rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic, j);
- if (rc)
- break;
- }
- if (rc) {
- PMD_DRV_LOG(ERR,
- "HWRM vnic %d ctx %d alloc failure rc: %x\n",
- i, j, rc);
- goto err_out;
- }
- vnic->num_lb_ctxts = nr_ctxs;
- }
-
- /*
- * Firmware sets pf pair in default vnic cfg. If the VLAN strip
- * setting is not available at this time, it will not be
- * configured correctly in the CFA.
- */
- if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
- vnic->vlan_strip = true;
- else
- vnic->vlan_strip = false;
-
- rc = bnxt_hwrm_vnic_cfg(bp, vnic);
- if (rc) {
- PMD_DRV_LOG(ERR, "HWRM vnic %d cfg failure rc: %x\n",
- i, rc);
- goto err_out;
- }
-
- rc = bnxt_set_hwrm_vnic_filters(bp, vnic);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "HWRM vnic %d filter failure rc: %x\n",
- i, rc);
- goto err_out;
- }
-
- for (j = 0; j < bp->rx_num_qs_per_vnic; j++) {
- rxq = bp->eth_dev->data->rx_queues[j];
-
- PMD_DRV_LOG(DEBUG,
- "rxq[%d]->vnic=%p vnic->fw_grp_ids=%p\n",
- j, rxq->vnic, rxq->vnic->fw_grp_ids);
-
- if (BNXT_HAS_RING_GRPS(bp) && rxq->rx_deferred_start)
- rxq->vnic->fw_grp_ids[j] = INVALID_HW_RING_ID;
- }
-
- rc = bnxt_vnic_rss_configure(bp, vnic);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "HWRM vnic set RSS failure rc: %x\n", rc);
- goto err_out;
- }
-
- bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
-
- if (bp->eth_dev->data->dev_conf.rxmode.offloads &
- DEV_RX_OFFLOAD_TCP_LRO)
- bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 1);
- else
- bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 0);
}
+
rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, &bp->vnic_info[0], 0, NULL);
if (rc) {
PMD_DRV_LOG(ERR,
/* enable uio/vfio intr/eventfd mapping */
rc = rte_intr_enable(intr_handle);
+#ifndef RTE_EXEC_ENV_FREEBSD
+ /* In FreeBSD OS, nic_uio driver does not support interrupts */
if (rc)
goto err_free;
+#endif
rc = bnxt_get_hwrm_link_config(bp, &new);
if (rc) {
goto err_free;
}
- if (!bp->link_info.link_up) {
+ if (!bp->link_info->link_up) {
rc = bnxt_set_hwrm_link_config(bp, true);
if (rc) {
PMD_DRV_LOG(ERR,
}
bnxt_print_link_info(bp->eth_dev);
+ bp->mark_table = rte_zmalloc("bnxt_mark_table", BNXT_MARK_TABLE_SZ, 0);
+ if (!bp->mark_table)
+ PMD_DRV_LOG(ERR, "Allocation of mark table failed\n");
+
return 0;
err_free:
* Device configuration and status function
*/
+static uint32_t bnxt_get_speed_capabilities(struct bnxt *bp)
+{
+ uint32_t link_speed = bp->link_info->support_speeds;
+ uint32_t speed_capa = 0;
+
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB)
+ speed_capa |= ETH_LINK_SPEED_100M;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MBHD)
+ speed_capa |= ETH_LINK_SPEED_100M_HD;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
+ speed_capa |= ETH_LINK_SPEED_1G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
+ speed_capa |= ETH_LINK_SPEED_2_5G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
+ speed_capa |= ETH_LINK_SPEED_10G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB)
+ speed_capa |= ETH_LINK_SPEED_20G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
+ speed_capa |= ETH_LINK_SPEED_25G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
+ speed_capa |= ETH_LINK_SPEED_40G;
+ if (link_speed & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB)
+ 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;
+ else
+ speed_capa |= ETH_LINK_SPEED_AUTONEG;
+
+ return speed_capa;
+}
+
static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
struct rte_eth_dev_info *dev_info)
{
dev_info->tx_offload_capa = BNXT_DEV_TX_OFFLOAD_SUPPORT;
dev_info->flow_type_rss_offloads = BNXT_ETH_RSS_SUPPORT;
+ dev_info->speed_capa = bnxt_get_speed_capabilities(bp);
+
/* *INDENT-OFF* */
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.rx_thresh = {
}
static eth_rx_burst_t
-bnxt_receive_function(__rte_unused struct rte_eth_dev *eth_dev)
+bnxt_receive_function(struct rte_eth_dev *eth_dev)
{
+ struct bnxt *bp = eth_dev->data->dev_private;
+
#ifdef RTE_ARCH_X86
#ifndef RTE_LIBRTE_IEEE1588
/*
DEV_RX_OFFLOAD_TCP_CKSUM |
DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM |
DEV_RX_OFFLOAD_RSS_HASH |
- DEV_RX_OFFLOAD_VLAN_FILTER))) {
+ DEV_RX_OFFLOAD_VLAN_FILTER)) &&
+ !bp->truflow) {
PMD_DRV_LOG(INFO, "Using vector mode receive for port %d\n",
eth_dev->data->port_id);
+ bp->flags |= BNXT_FLAG_RX_VECTOR_PKT_MODE;
return bnxt_recv_pkts_vec;
}
PMD_DRV_LOG(INFO, "Vector mode receive disabled for port %d\n",
eth_dev->data->dev_conf.rxmode.offloads);
#endif
#endif
+ bp->flags &= ~BNXT_FLAG_RX_VECTOR_PKT_MODE;
return bnxt_recv_pkts;
}
struct bnxt *bp = eth_dev->data->dev_private;
uint64_t rx_offloads = eth_dev->data->dev_conf.rxmode.offloads;
int vlan_mask = 0;
- int rc;
+ int rc, retry_cnt = BNXT_IF_CHANGE_RETRY_COUNT;
if (!eth_dev->data->nb_tx_queues || !eth_dev->data->nb_rx_queues) {
PMD_DRV_LOG(ERR, "Queues are not configured yet!\n");
bp->rx_cp_nr_rings, RTE_ETHDEV_QUEUE_STAT_CNTRS);
}
- rc = bnxt_hwrm_if_change(bp, 1);
- if (!rc) {
- if (bp->flags & BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE) {
- rc = bnxt_handle_if_change_status(bp);
- if (rc)
- return rc;
- }
+ do {
+ rc = bnxt_hwrm_if_change(bp, true);
+ if (rc == 0 || rc != -EAGAIN)
+ break;
+
+ rte_delay_ms(BNXT_IF_CHANGE_RETRY_INTERVAL);
+ } while (retry_cnt--);
+
+ if (rc)
+ return rc;
+
+ if (bp->flags & BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE) {
+ rc = bnxt_handle_if_change_status(bp);
+ if (rc)
+ return rc;
}
+
bnxt_enable_int(bp);
rc = bnxt_init_chip(bp);
goto error;
eth_dev->data->scattered_rx = bnxt_scattered_rx(eth_dev);
+ eth_dev->data->dev_started = 1;
- bnxt_link_update_op(eth_dev, 1);
+ bnxt_link_update(eth_dev, 1, ETH_LINK_UP);
if (rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
vlan_mask |= ETH_VLAN_FILTER_MASK;
eth_dev->rx_pkt_burst = bnxt_receive_function(eth_dev);
eth_dev->tx_pkt_burst = bnxt_transmit_function(eth_dev);
- bp->flags |= BNXT_FLAG_INIT_DONE;
- eth_dev->data->dev_started = 1;
- bp->dev_stopped = 0;
pthread_mutex_lock(&bp->def_cp_lock);
bnxt_schedule_fw_health_check(bp);
pthread_mutex_unlock(&bp->def_cp_lock);
+
+ if (bp->truflow)
+ bnxt_ulp_init(bp);
+
return 0;
error:
- bnxt_hwrm_if_change(bp, 0);
bnxt_shutdown_nic(bp);
bnxt_free_tx_mbufs(bp);
bnxt_free_rx_mbufs(bp);
+ bnxt_hwrm_if_change(bp, false);
+ eth_dev->data->dev_started = 0;
return rc;
}
struct bnxt *bp = eth_dev->data->dev_private;
int rc = 0;
- if (!bp->link_info.link_up)
+ if (!bp->link_info->link_up)
rc = bnxt_set_hwrm_link_config(bp, true);
if (!rc)
eth_dev->data->dev_link.link_status = 1;
eth_dev->data->dev_link.link_status = 0;
bnxt_set_hwrm_link_config(bp, false);
- bp->link_info.link_up = 0;
+ bp->link_info->link_up = 0;
return 0;
}
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+ if (bp->truflow)
+ bnxt_ulp_deinit(bp);
+
eth_dev->data->dev_started = 0;
/* Prevent crashes when queues are still in use */
eth_dev->rx_pkt_burst = &bnxt_dummy_recv_pkts;
bnxt_cancel_fw_health_check(bp);
- bp->flags &= ~BNXT_FLAG_INIT_DONE;
- if (bp->eth_dev->data->dev_started) {
- /* TBD: STOP HW queues DMA */
- eth_dev->data->dev_link.link_status = 0;
- }
bnxt_dev_set_link_down_op(eth_dev);
/* Wait for link to be reset and the async notification to process.
- * During reset recovery, there is no need to wait
+ * During reset recovery, there is no need to wait and
+ * VF/NPAR functions do not have privilege to change PHY config.
*/
- if (!is_bnxt_in_error(bp))
- rte_delay_ms(BNXT_LINK_WAIT_INTERVAL * 2);
+ if (!is_bnxt_in_error(bp) && BNXT_SINGLE_PF(bp))
+ bnxt_link_update(eth_dev, 1, ETH_LINK_DOWN);
/* Clean queue intr-vector mapping */
rte_intr_efd_disable(intr_handle);
/* Process any remaining notifications in default completion queue */
bnxt_int_handler(eth_dev);
bnxt_shutdown_nic(bp);
- bnxt_hwrm_if_change(bp, 0);
- bp->dev_stopped = 1;
+ bnxt_hwrm_if_change(bp, false);
+
+ rte_free(bp->mark_table);
+ bp->mark_table = NULL;
+
+ 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)
{
struct bnxt *bp = eth_dev->data->dev_private;
- if (bp->dev_stopped == 0)
+ /* cancel the recovery handler before remove dev */
+ rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
+ rte_eal_alarm_cancel(bnxt_dev_recover, (void *)bp);
+ bnxt_cancel_fc_thread(bp);
+
+ if (eth_dev->data->dev_started)
bnxt_dev_stop_op(eth_dev);
- if (eth_dev->data->mac_addrs != NULL) {
- rte_free(eth_dev->data->mac_addrs);
- eth_dev->data->mac_addrs = NULL;
- }
- if (bp->grp_info != NULL) {
- rte_free(bp->grp_info);
- bp->grp_info = NULL;
- }
+ bnxt_uninit_resources(bp, false);
- bnxt_dev_uninit(eth_dev);
+ bnxt_free_leds_info(bp);
+ bnxt_free_cos_queues(bp);
+ bnxt_free_link_info(bp);
+ bnxt_free_pf_info(bp);
+
+ eth_dev->dev_ops = NULL;
+ eth_dev->rx_pkt_burst = NULL;
+ eth_dev->tx_pkt_burst = NULL;
+
+ rte_memzone_free((const struct rte_memzone *)bp->tx_mem_zone);
+ bp->tx_mem_zone = NULL;
+ rte_memzone_free((const struct rte_memzone *)bp->rx_mem_zone);
+ bp->rx_mem_zone = NULL;
+
+ rte_free(bp->pf->vf_info);
+ bp->pf->vf_info = NULL;
+
+ rte_free(bp->grp_info);
+ bp->grp_info = NULL;
}
static void bnxt_mac_addr_remove_op(struct rte_eth_dev *eth_dev,
STAILQ_REMOVE(&vnic->filter, filter,
bnxt_filter_info, next);
bnxt_hwrm_clear_l2_filter(bp, filter);
- filter->mac_index = INVALID_MAC_INDEX;
- memset(&filter->l2_addr, 0, RTE_ETHER_ADDR_LEN);
bnxt_free_filter(bp, filter);
}
filter = temp_filter;
else
STAILQ_INSERT_TAIL(&vnic->filter, filter, next);
} else {
- memset(&filter->l2_addr, 0, RTE_ETHER_ADDR_LEN);
bnxt_free_filter(bp, filter);
}
return -EINVAL;
}
+ /* Filter settings will get applied when port is started */
+ if (!eth_dev->data->dev_started)
+ return 0;
+
rc = bnxt_add_mac_filter(bp, vnic, mac_addr, index, pool);
return rc;
}
-int bnxt_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_complete)
+int bnxt_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete,
+ bool exp_link_status)
{
int rc = 0;
struct bnxt *bp = eth_dev->data->dev_private;
struct rte_eth_link new;
- unsigned int cnt = BNXT_LINK_WAIT_CNT;
+ int cnt = exp_link_status ? BNXT_LINK_UP_WAIT_CNT :
+ BNXT_LINK_DOWN_WAIT_CNT;
rc = is_bnxt_in_error(bp);
if (rc)
goto out;
}
- if (!wait_to_complete || new.link_status)
+ if (!wait_to_complete || new.link_status == exp_link_status)
break;
rte_delay_ms(BNXT_LINK_WAIT_INTERVAL);
return rc;
}
+static int bnxt_link_update_op(struct rte_eth_dev *eth_dev,
+ int wait_to_complete)
+{
+ return bnxt_link_update(eth_dev, wait_to_complete, ETH_LINK_UP);
+}
+
static int bnxt_promiscuous_enable_op(struct rte_eth_dev *eth_dev)
{
struct bnxt *bp = eth_dev->data->dev_private;
if (rc)
return rc;
+ /* Filter settings will get applied when port is started */
+ if (!eth_dev->data->dev_started)
+ return 0;
+
if (bp->vnic_info == NULL)
return 0;
if (rc)
return rc;
+ /* Filter settings will get applied when port is started */
+ if (!eth_dev->data->dev_started)
+ return 0;
+
if (bp->vnic_info == NULL)
return 0;
if (rc)
return rc;
+ /* Filter settings will get applied when port is started */
+ if (!eth_dev->data->dev_started)
+ return 0;
+
if (bp->vnic_info == NULL)
return 0;
if (rc)
return rc;
+ /* Filter settings will get applied when port is started */
+ if (!eth_dev->data->dev_started)
+ return 0;
+
if (bp->vnic_info == NULL)
return 0;
}
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;
}
return rc;
memset(fc_conf, 0, sizeof(*fc_conf));
- if (bp->link_info.auto_pause)
+ if (bp->link_info->auto_pause)
fc_conf->autoneg = 1;
- switch (bp->link_info.pause) {
+ switch (bp->link_info->pause) {
case 0:
fc_conf->mode = RTE_FC_NONE;
break;
switch (fc_conf->mode) {
case RTE_FC_NONE:
- bp->link_info.auto_pause = 0;
- bp->link_info.force_pause = 0;
+ bp->link_info->auto_pause = 0;
+ bp->link_info->force_pause = 0;
break;
case RTE_FC_RX_PAUSE:
if (fc_conf->autoneg) {
- bp->link_info.auto_pause =
+ bp->link_info->auto_pause =
HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
- bp->link_info.force_pause = 0;
+ bp->link_info->force_pause = 0;
} else {
- bp->link_info.auto_pause = 0;
- bp->link_info.force_pause =
+ bp->link_info->auto_pause = 0;
+ bp->link_info->force_pause =
HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
}
break;
case RTE_FC_TX_PAUSE:
if (fc_conf->autoneg) {
- bp->link_info.auto_pause =
+ bp->link_info->auto_pause =
HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
- bp->link_info.force_pause = 0;
+ bp->link_info->force_pause = 0;
} else {
- bp->link_info.auto_pause = 0;
- bp->link_info.force_pause =
+ bp->link_info->auto_pause = 0;
+ bp->link_info->force_pause =
HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
}
break;
case RTE_FC_FULL:
if (fc_conf->autoneg) {
- bp->link_info.auto_pause =
+ bp->link_info->auto_pause =
HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX |
HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
- bp->link_info.force_pause = 0;
+ bp->link_info->force_pause = 0;
} else {
- bp->link_info.auto_pause = 0;
- bp->link_info.force_pause =
+ bp->link_info->auto_pause = 0;
+ bp->link_info->force_pause =
HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX |
HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
}
/* Free the newly allocated filter as we were
* not able to create the filter in hardware.
*/
- filter->fw_l2_filter_id = UINT64_MAX;
bnxt_free_filter(bp, filter);
return rc;
}
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);
STAILQ_REMOVE(&vnic->filter, filter,
bnxt_filter_info, next);
bnxt_free_filter(bp, filter);
- filter->fw_l2_filter_id = UINT64_MAX;
}
return rc;
}
return 0;
}
+static int
+bnxt_config_vlan_hw_filter(struct bnxt *bp, uint64_t rx_offloads)
+{
+ struct bnxt_vnic_info *vnic;
+ unsigned int i;
+ int rc;
+
+ vnic = BNXT_GET_DEFAULT_VNIC(bp);
+ if (!(rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER)) {
+ /* Remove any VLAN filters programmed */
+ for (i = 0; i < RTE_ETHER_MAX_VLAN_ID; i++)
+ bnxt_del_vlan_filter(bp, i);
+
+ rc = bnxt_add_mac_filter(bp, vnic, NULL, 0, 0);
+ if (rc)
+ return rc;
+ } else {
+ /* Default filter will allow packets that match the
+ * dest mac. So, it has to be deleted, otherwise, we
+ * will endup receiving vlan packets for which the
+ * filter is not programmed, when hw-vlan-filter
+ * configuration is ON
+ */
+ bnxt_del_dflt_mac_filter(bp, vnic);
+ /* This filter will allow only untagged packets */
+ bnxt_add_vlan_filter(bp, 0);
+ }
+ PMD_DRV_LOG(DEBUG, "VLAN Filtering: %d\n",
+ !!(rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER));
+
+ return 0;
+}
+
+static int bnxt_free_one_vnic(struct bnxt *bp, uint16_t vnic_id)
+{
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+ unsigned int i;
+ int rc;
+
+ /* Destroy vnic filters and vnic */
+ if (bp->eth_dev->data->dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_VLAN_FILTER) {
+ for (i = 0; i < RTE_ETHER_MAX_VLAN_ID; i++)
+ bnxt_del_vlan_filter(bp, i);
+ }
+ bnxt_del_dflt_mac_filter(bp, vnic);
+
+ rc = bnxt_hwrm_vnic_free(bp, vnic);
+ if (rc)
+ return rc;
+
+ rte_free(vnic->fw_grp_ids);
+ vnic->fw_grp_ids = NULL;
+
+ vnic->rx_queue_cnt = 0;
+
+ return 0;
+}
+
+static int
+bnxt_config_vlan_hw_stripping(struct bnxt *bp, uint64_t rx_offloads)
+{
+ struct bnxt_vnic_info *vnic = BNXT_GET_DEFAULT_VNIC(bp);
+ int rc;
+
+ /* Destroy, recreate and reconfigure the default vnic */
+ rc = bnxt_free_one_vnic(bp, 0);
+ if (rc)
+ return rc;
+
+ /* default vnic 0 */
+ rc = bnxt_setup_one_vnic(bp, 0);
+ if (rc)
+ return rc;
+
+ if (bp->eth_dev->data->dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_VLAN_FILTER) {
+ rc = bnxt_add_vlan_filter(bp, 0);
+ if (rc)
+ return rc;
+ rc = bnxt_restore_vlan_filters(bp);
+ if (rc)
+ return rc;
+ } else {
+ rc = bnxt_add_mac_filter(bp, vnic, NULL, 0, 0);
+ if (rc)
+ return rc;
+ }
+
+ rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, vnic, 0, NULL);
+ if (rc)
+ return rc;
+
+ PMD_DRV_LOG(DEBUG, "VLAN Strip Offload: %d\n",
+ !!(rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP));
+
+ return rc;
+}
+
static int
bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
{
- struct bnxt *bp = dev->data->dev_private;
uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
- struct bnxt_vnic_info *vnic;
- unsigned int i;
+ struct bnxt *bp = dev->data->dev_private;
int rc;
rc = is_bnxt_in_error(bp);
if (rc)
return rc;
- vnic = BNXT_GET_DEFAULT_VNIC(bp);
- if (!(rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER)) {
- /* Remove any VLAN filters programmed */
- for (i = 0; i < RTE_ETHER_MAX_VLAN_ID; i++)
- bnxt_del_vlan_filter(bp, i);
+ /* Filter settings will get applied when port is started */
+ if (!dev->data->dev_started)
+ return 0;
- rc = bnxt_add_mac_filter(bp, vnic, NULL, 0, 0);
+ if (mask & ETH_VLAN_FILTER_MASK) {
+ /* Enable or disable VLAN filtering */
+ rc = bnxt_config_vlan_hw_filter(bp, rx_offloads);
if (rc)
return rc;
- } else {
- /* Default filter will allow packets that match the
- * dest mac. So, it has to be deleted, otherwise, we
- * will endup receiving vlan packets for which the
- * filter is not programmed, when hw-vlan-filter
- * configuration is ON
- */
- bnxt_del_dflt_mac_filter(bp, vnic);
- /* This filter will allow only untagged packets */
- bnxt_add_vlan_filter(bp, 0);
}
- PMD_DRV_LOG(DEBUG, "VLAN Filtering: %d\n",
- !!(rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER));
if (mask & ETH_VLAN_STRIP_MASK) {
/* Enable or disable VLAN stripping */
- for (i = 0; i < bp->nr_vnics; i++) {
- struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
- if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
- vnic->vlan_strip = true;
- else
- vnic->vlan_strip = false;
- bnxt_hwrm_vnic_cfg(bp, vnic);
- }
- PMD_DRV_LOG(DEBUG, "VLAN Strip Offload: %d\n",
- !!(rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP));
+ rc = bnxt_config_vlan_hw_stripping(bp, rx_offloads);
+ if (rc)
+ return rc;
}
if (mask & ETH_VLAN_EXTEND_MASK) {
struct bnxt *bp = dev->data->dev_private;
/* Default Filter is tied to VNIC 0 */
struct bnxt_vnic_info *vnic = BNXT_GET_DEFAULT_VNIC(bp);
- struct bnxt_filter_info *filter;
int rc;
rc = is_bnxt_in_error(bp);
if (rte_is_zero_ether_addr(addr))
return -EINVAL;
- STAILQ_FOREACH(filter, &vnic->filter, next) {
- /* Default Filter is at Index 0 */
- if (filter->mac_index != 0)
- continue;
+ /* Filter settings will get applied when port is started */
+ if (!dev->data->dev_started)
+ return 0;
- memcpy(filter->l2_addr, addr, RTE_ETHER_ADDR_LEN);
- memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN);
- filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX |
- HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST;
- filter->enables |=
- HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR |
- HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK;
+ /* Check if the requested MAC is already added */
+ if (memcmp(addr, bp->mac_addr, RTE_ETHER_ADDR_LEN) == 0)
+ return 0;
- rc = bnxt_hwrm_set_l2_filter(bp, vnic->fw_vnic_id, filter);
- if (rc) {
- memcpy(filter->l2_addr, bp->mac_addr,
- RTE_ETHER_ADDR_LEN);
- return rc;
- }
+ /* Destroy filter and re-create it */
+ bnxt_del_dflt_mac_filter(bp, vnic);
- memcpy(bp->mac_addr, addr, RTE_ETHER_ADDR_LEN);
- PMD_DRV_LOG(DEBUG, "Set MAC addr\n");
- return 0;
+ memcpy(bp->mac_addr, addr, RTE_ETHER_ADDR_LEN);
+ if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
+ /* This filter will allow only untagged packets */
+ rc = bnxt_add_vlan_filter(bp, 0);
+ } else {
+ rc = bnxt_add_mac_filter(bp, vnic, addr, 0, 0);
}
- return 0;
+ PMD_DRV_LOG(DEBUG, "Set MAC addr\n");
+ return rc;
}
static int
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)
STAILQ_REMOVE(&vnic->filter, mfilter, bnxt_filter_info, next);
bnxt_free_filter(bp, mfilter);
- mfilter->fw_l2_filter_id = -1;
bnxt_free_filter(bp, bfilter);
- bfilter->fw_l2_filter_id = -1;
}
return 0;
free_filter:
- bfilter->fw_l2_filter_id = -1;
bnxt_free_filter(bp, bfilter);
return ret;
}
STAILQ_REMOVE(&vnic->filter, match,
bnxt_filter_info, next);
bnxt_free_filter(bp, match);
- filter->fw_l2_filter_id = -1;
bnxt_free_filter(bp, filter);
}
break;
return ret;
free_filter:
- filter->fw_l2_filter_id = -1;
bnxt_free_filter(bp, filter);
return ret;
}
static int
-bnxt_filter_ctrl_op(struct rte_eth_dev *dev __rte_unused,
+bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
enum rte_filter_type filter_type,
enum rte_filter_op filter_op, void *arg)
{
+ struct bnxt *bp = dev->data->dev_private;
int ret = 0;
ret = is_bnxt_in_error(dev->data->dev_private);
case RTE_ETH_FILTER_GENERIC:
if (filter_op != RTE_ETH_FILTER_GET)
return -EINVAL;
- *(const void **)arg = &bnxt_flow_ops;
+ if (bp->truflow)
+ *(const void **)arg = &bnxt_ulp_rte_flow_ops;
+ else
+ *(const void **)arg = &bnxt_flow_ops;
break;
default:
PMD_DRV_LOG(ERR,
static int bnxt_get_rx_ts(struct bnxt *bp, uint64_t *ts)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
- struct bnxt_pf_info *pf = &bp->pf;
+ struct bnxt_pf_info *pf = bp->pf;
uint16_t port_id;
uint32_t fifo;
if (rc)
return rc;
- PMD_DRV_LOG(INFO, "%04x:%02x:%02x:%02x\n",
- bp->pdev->addr.domain, bp->pdev->addr.bus,
- bp->pdev->addr.devid, bp->pdev->addr.function);
+ PMD_DRV_LOG(INFO, PCI_PRI_FMT "\n",
+ bp->pdev->addr.domain, bp->pdev->addr.bus,
+ bp->pdev->addr.devid, bp->pdev->addr.function);
rc = bnxt_hwrm_nvm_get_dir_info(bp, &dir_entries, &entry_length);
if (rc != 0)
if (rc)
return rc;
- PMD_DRV_LOG(INFO, "%04x:%02x:%02x:%02x in_eeprom->offset = %d "
- "len = %d\n", bp->pdev->addr.domain,
- bp->pdev->addr.bus, bp->pdev->addr.devid,
- bp->pdev->addr.function, in_eeprom->offset, in_eeprom->length);
+ PMD_DRV_LOG(INFO, PCI_PRI_FMT " in_eeprom->offset = %d len = %d\n",
+ bp->pdev->addr.domain, bp->pdev->addr.bus,
+ bp->pdev->addr.devid, bp->pdev->addr.function,
+ in_eeprom->offset, in_eeprom->length);
if (in_eeprom->offset == 0) /* special offset value to get directory */
return bnxt_get_nvram_directory(bp, in_eeprom->length,
if (rc)
return rc;
- PMD_DRV_LOG(INFO, "%04x:%02x:%02x:%02x in_eeprom->offset = %d "
- "len = %d\n", bp->pdev->addr.domain,
- bp->pdev->addr.bus, bp->pdev->addr.devid,
- bp->pdev->addr.function, in_eeprom->offset, in_eeprom->length);
+ PMD_DRV_LOG(INFO, PCI_PRI_FMT " in_eeprom->offset = %d len = %d\n",
+ bp->pdev->addr.domain, bp->pdev->addr.bus,
+ bp->pdev->addr.devid, bp->pdev->addr.function,
+ in_eeprom->offset, in_eeprom->length);
if (!BNXT_PF(bp)) {
PMD_DRV_LOG(ERR, "NVM write not supported from a VF\n");
static void bnxt_dev_cleanup(struct bnxt *bp)
{
bnxt_set_hwrm_link_config(bp, false);
- bp->link_info.link_up = 0;
- if (bp->dev_stopped == 0)
+ bp->link_info->link_up = 0;
+ if (bp->eth_dev->data->dev_started)
bnxt_dev_stop_op(bp->eth_dev);
bnxt_uninit_resources(bp, true);
struct rte_eth_dev *dev = bp->eth_dev;
int ret = 0;
- if (dev->data->all_multicast)
+ if (dev->data->all_multicast) {
ret = bnxt_allmulticast_enable_op(dev);
- if (dev->data->promiscuous)
+ if (ret)
+ return ret;
+ }
+ if (dev->data->promiscuous) {
ret = bnxt_promiscuous_enable_op(dev);
+ if (ret)
+ return ret;
+ }
ret = bnxt_restore_mac_filters(bp);
if (ret)
bp->flags &= ~BNXT_FLAG_FATAL_ERROR;
do {
- rc = bnxt_hwrm_ver_get(bp);
+ rc = bnxt_hwrm_ver_get(bp, SHORT_HWRM_CMD_TIMEOUT);
if (rc == 0)
break;
rte_delay_ms(BNXT_FW_READY_WAIT_INTERVAL);
rc = bnxt_dev_start_op(bp->eth_dev);
if (rc) {
PMD_DRV_LOG(ERR, "Failed to start port after reset\n");
- goto err;
+ goto err_start;
}
rc = bnxt_restore_filters(bp);
if (rc)
- goto err;
+ goto err_start;
PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
return;
+err_start:
+ bnxt_dev_stop_op(bp->eth_dev);
err:
bp->flags |= BNXT_FLAG_FATAL_ERROR;
bnxt_uninit_resources(bp, false);
return 0;
}
-static int bnxt_alloc_ctx_mem_blk(__rte_unused struct bnxt *bp,
+static int bnxt_alloc_ctx_mem_blk(struct bnxt *bp,
struct bnxt_ctx_pg_info *ctx_pg,
uint32_t mem_size,
const char *suffix,
memset(mz->addr, 0, mz->len);
mz_phys_addr = mz->iova;
- if ((unsigned long)mz->addr == mz_phys_addr) {
- PMD_DRV_LOG(DEBUG,
- "physical address same as virtual\n");
- PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
- mz_phys_addr = rte_mem_virt2iova(mz->addr);
- if (mz_phys_addr == RTE_BAD_IOVA) {
- PMD_DRV_LOG(ERR,
- "unable to map addr to phys memory\n");
- return -ENOMEM;
- }
- }
- rte_mem_lock_page(((char *)mz->addr));
rmem->pg_tbl = mz->addr;
rmem->pg_tbl_map = mz_phys_addr;
memset(mz->addr, 0, mz->len);
mz_phys_addr = mz->iova;
- if ((unsigned long)mz->addr == mz_phys_addr) {
- PMD_DRV_LOG(DEBUG,
- "Memzone physical address same as virtual.\n");
- PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
- for (sz = 0; sz < mem_size; sz += BNXT_PAGE_SIZE)
- rte_mem_lock_page(((char *)mz->addr) + sz);
- mz_phys_addr = rte_mem_virt2iova(mz->addr);
- if (mz_phys_addr == RTE_BAD_IOVA) {
- PMD_DRV_LOG(ERR,
- "unable to map addr to phys memory\n");
- return -ENOMEM;
- }
- }
for (sz = 0, i = 0; sz < mem_size; sz += BNXT_PAGE_SIZE, i++) {
- rte_mem_lock_page(((char *)mz->addr) + sz);
rmem->pg_arr[i] = ((char *)mz->addr) + sz;
rmem->dma_arr[i] = mz_phys_addr + sz;
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);
}
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);
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)
}
memset(mz->addr, 0, mz->len);
mz_phys_addr = mz->iova;
- if ((unsigned long)mz->addr == mz_phys_addr) {
- PMD_DRV_LOG(DEBUG,
- "Memzone physical address same as virtual.\n");
- PMD_DRV_LOG(DEBUG,
- "Using rte_mem_virt2iova()\n");
- mz_phys_addr = rte_mem_virt2iova(mz->addr);
- if (mz_phys_addr == RTE_BAD_IOVA) {
- PMD_DRV_LOG(ERR,
- "Can't map address to physical memory\n");
- return -ENOMEM;
- }
- }
bp->rx_mem_zone = (const void *)mz;
bp->hw_rx_port_stats = mz->addr;
}
memset(mz->addr, 0, mz->len);
mz_phys_addr = mz->iova;
- if ((unsigned long)mz->addr == mz_phys_addr) {
- PMD_DRV_LOG(DEBUG,
- "Memzone physical address same as virtual\n");
- PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
- mz_phys_addr = rte_mem_virt2iova(mz->addr);
- if (mz_phys_addr == RTE_BAD_IOVA) {
- PMD_DRV_LOG(ERR,
- "Can't map address to physical memory\n");
- return -ENOMEM;
- }
- }
bp->tx_mem_zone = (const void *)mz;
bp->hw_tx_port_stats = mz->addr;
#define ALLOW_FUNC(x) \
{ \
uint32_t arg = (x); \
- bp->pf.vf_req_fwd[((arg) >> 5)] &= \
+ bp->pf->vf_req_fwd[((arg) >> 5)] &= \
~rte_cpu_to_le_32(1 << ((arg) & 0x1f)); \
}
if (((bp->fw_ver >= ((20 << 24) | (6 << 16) | (100 << 8))) &&
(bp->fw_ver < ((20 << 24) | (7 << 16)))) ||
((bp->fw_ver >= ((20 << 24) | (8 << 16))))) {
- memset(bp->pf.vf_req_fwd, 0xff, sizeof(bp->pf.vf_req_fwd));
+ memset(bp->pf->vf_req_fwd, 0xff, sizeof(bp->pf->vf_req_fwd));
} else {
PMD_DRV_LOG(WARNING,
"Firmware too old for VF mailbox functionality\n");
- memset(bp->pf.vf_req_fwd, 0, sizeof(bp->pf.vf_req_fwd));
+ memset(bp->pf->vf_req_fwd, 0, sizeof(bp->pf->vf_req_fwd));
}
/*
ALLOW_FUNC(HWRM_VNIC_TPA_CFG);
}
+uint16_t
+bnxt_get_svif(uint16_t port_id, bool func_svif)
+{
+ struct rte_eth_dev *eth_dev;
+ struct bnxt *bp;
+
+ eth_dev = &rte_eth_devices[port_id];
+ bp = eth_dev->data->dev_private;
+
+ return func_svif ? bp->func_svif : bp->port_svif;
+}
+
+uint16_t
+bnxt_get_vnic_id(uint16_t port)
+{
+ struct rte_eth_dev *eth_dev;
+ struct bnxt_vnic_info *vnic;
+ struct bnxt *bp;
+
+ eth_dev = &rte_eth_devices[port];
+ bp = eth_dev->data->dev_private;
+
+ vnic = BNXT_GET_DEFAULT_VNIC(bp);
+
+ return vnic->fw_vnic_id;
+}
+
+uint16_t
+bnxt_get_fw_func_id(uint16_t port)
+{
+ struct rte_eth_dev *eth_dev;
+ struct bnxt *bp;
+
+ eth_dev = &rte_eth_devices[port];
+ bp = eth_dev->data->dev_private;
+
+ 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;
int rc = 0;
- rc = bnxt_hwrm_ver_get(bp);
+ bp->fw_cap = 0;
+
+ 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;
if (rc)
return rc;
+ bnxt_hwrm_port_mac_qcfg(bp);
+
rc = bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(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)
- bp->flags &= ~BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+ bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
bnxt_hwrm_port_led_qcaps(bp);
if (rc)
return rc;
+ rc = bnxt_init_ctx_mem(bp);
+ if (rc) {
+ PMD_DRV_LOG(ERR, "Failed to init adv_flow_counters\n");
+ return rc;
+ }
+
rc = bnxt_init_locks(bp);
if (rc)
return rc;
return 0;
}
+static int
+bnxt_parse_devarg_truflow(__rte_unused const char *key,
+ const char *value, void *opaque_arg)
+{
+ struct bnxt *bp = opaque_arg;
+ unsigned long truflow;
+ char *end = NULL;
+
+ if (!value || !opaque_arg) {
+ PMD_DRV_LOG(ERR,
+ "Invalid parameter passed to truflow devargs.\n");
+ return -EINVAL;
+ }
+
+ truflow = strtoul(value, &end, 10);
+ if (end == NULL || *end != '\0' ||
+ (truflow == ULONG_MAX && errno == ERANGE)) {
+ PMD_DRV_LOG(ERR,
+ "Invalid parameter passed to truflow devargs.\n");
+ return -EINVAL;
+ }
+
+ if (BNXT_DEVARG_TRUFLOW_INVALID(truflow)) {
+ PMD_DRV_LOG(ERR,
+ "Invalid value passed to truflow devargs.\n");
+ return -EINVAL;
+ }
+
+ bp->truflow = truflow;
+ if (bp->truflow)
+ PMD_DRV_LOG(INFO, "Host-based truflow feature enabled.\n");
+
+ return 0;
+}
+
+static int
+bnxt_parse_devarg_flow_xstat(__rte_unused const char *key,
+ const char *value, void *opaque_arg)
+{
+ struct bnxt *bp = opaque_arg;
+ unsigned long flow_xstat;
+ char *end = NULL;
+
+ if (!value || !opaque_arg) {
+ PMD_DRV_LOG(ERR,
+ "Invalid parameter passed to flow_xstat devarg.\n");
+ return -EINVAL;
+ }
+
+ flow_xstat = strtoul(value, &end, 10);
+ if (end == NULL || *end != '\0' ||
+ (flow_xstat == ULONG_MAX && errno == ERANGE)) {
+ PMD_DRV_LOG(ERR,
+ "Invalid parameter passed to flow_xstat devarg.\n");
+ return -EINVAL;
+ }
+
+ if (BNXT_DEVARG_FLOW_XSTAT_INVALID(flow_xstat)) {
+ PMD_DRV_LOG(ERR,
+ "Invalid value passed to flow_xstat devarg.\n");
+ return -EINVAL;
+ }
+
+ bp->flags |= BNXT_FLAG_FLOW_XSTATS_EN;
+ if (BNXT_FLOW_XSTATS_EN(bp))
+ PMD_DRV_LOG(INFO, "flow_xstat feature enabled.\n");
+
+ return 0;
+}
+
+static void
+bnxt_parse_dev_args(struct bnxt *bp, struct rte_devargs *devargs)
+{
+ struct rte_kvargs *kvlist;
+
+ if (devargs == NULL)
+ return;
+
+ kvlist = rte_kvargs_parse(devargs->args, bnxt_dev_args);
+ if (kvlist == NULL)
+ return;
+
+ /*
+ * Handler for "truflow" devarg.
+ * Invoked as for ex: "-w 0000:00:0d.0,host-based-truflow=1”
+ */
+ rte_kvargs_process(kvlist, BNXT_DEVARG_TRUFLOW,
+ bnxt_parse_devarg_truflow, bp);
+
+ /*
+ * Handler for "flow_xstat" devarg.
+ * Invoked as for ex: "-w 0000:00:0d.0,flow_xstat=1”
+ */
+ rte_kvargs_process(kvlist, BNXT_DEVARG_FLOW_XSTAT,
+ bnxt_parse_devarg_flow_xstat, bp);
+
+ rte_kvargs_free(kvlist);
+}
+
static int
bnxt_dev_init(struct rte_eth_dev *eth_dev)
{
bp = eth_dev->data->dev_private;
- bp->dev_stopped = 1;
+ /* Parse dev arguments passed on when starting the DPDK application. */
+ bnxt_parse_dev_args(bp, pci_dev->device.devargs);
+
+ bp->flags &= ~BNXT_FLAG_RX_VECTOR_PKT_MODE;
if (bnxt_vf_pciid(pci_dev->id.device_id))
bp->flags |= BNXT_FLAG_VF;
return rc;
}
+ rc = bnxt_alloc_pf_info(bp);
+ if (rc)
+ goto error_free;
+
+ rc = bnxt_alloc_link_info(bp);
+ if (rc)
+ goto error_free;
+
rc = bnxt_alloc_hwrm_resources(bp);
if (rc) {
PMD_DRV_LOG(ERR,
"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;
if (rc)
goto error_free;
+ /* Pass the information to the rte_eth_dev_close() that it should also
+ * release the private port resources.
+ */
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
+
PMD_DRV_LOG(INFO,
DRV_MODULE_NAME "found at mem %" PRIX64 ", node addr %pM\n",
pci_dev->mem_resource[0].phys_addr,
return rc;
}
+
+static void bnxt_free_ctx_mem_buf(struct bnxt_ctx_mem_buf_info *ctx)
+{
+ if (!ctx)
+ return;
+
+ if (ctx->va)
+ rte_free(ctx->va);
+
+ ctx->va = NULL;
+ ctx->dma = RTE_BAD_IOVA;
+ ctx->ctx_id = BNXT_CTX_VAL_INVAL;
+}
+
+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->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->flow_stat->tx_fc_out_tbl.ctx_id,
+ bp->flow_stat->max_fc,
+ false);
+
+ 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->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->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->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->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)
+{
+ 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
bnxt_uninit_locks(struct bnxt *bp)
{
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);
+
bnxt_uninit_locks(bp);
rte_free(bp->ptp_cfg);
bp->ptp_cfg = NULL;
static int
bnxt_dev_uninit(struct rte_eth_dev *eth_dev)
{
- struct bnxt *bp = eth_dev->data->dev_private;
- int rc;
-
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return -EPERM;
PMD_DRV_LOG(DEBUG, "Calling Device uninit\n");
- rc = bnxt_uninit_resources(bp, false);
-
- if (bp->tx_mem_zone) {
- rte_memzone_free((const struct rte_memzone *)bp->tx_mem_zone);
- bp->tx_mem_zone = NULL;
- }
-
- if (bp->rx_mem_zone) {
- rte_memzone_free((const struct rte_memzone *)bp->rx_mem_zone);
- bp->rx_mem_zone = NULL;
- }
-
- if (bp->dev_stopped == 0)
+ if (eth_dev->state != RTE_ETH_DEV_UNUSED)
bnxt_dev_close_op(eth_dev);
- if (bp->pf.vf_info)
- rte_free(bp->pf.vf_info);
- eth_dev->dev_ops = NULL;
- eth_dev->rx_pkt_burst = NULL;
- eth_dev->tx_pkt_burst = NULL;
- return rc;
+ return 0;
}
static int bnxt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,