#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);
return rc;
}
+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);
+ 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);
+
+ rc = bnxt_hwrm_ctx_rgtr(bp, bp->rx_fc_out_tbl.dma,
+ &bp->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);
+
+ rc = bnxt_hwrm_ctx_rgtr(bp, bp->tx_fc_in_tbl.dma,
+ &bp->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);
+
+ rc = bnxt_hwrm_ctx_rgtr(bp, bp->tx_fc_out_tbl.dma,
+ &bp->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);
+
+ memset(bp->rx_fc_out_tbl.va, 0, bp->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,
+ true);
+ if (rc)
+ return rc;
+
+ memset(bp->tx_fc_out_tbl.va, 0, bp->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,
+ 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->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);
+ 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);
+ 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);
+ 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);
+ 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)))
+ return 0;
+
+ rc = bnxt_hwrm_cfa_counter_qcaps(bp, &bp->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;
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;
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:
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;
/* 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);
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,
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;
+}
+
static int bnxt_init_fw(struct bnxt *bp)
{
uint16_t mtu;
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->flow_xstat = flow_xstat;
+ if (bp->flow_xstat)
+ 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;
+ /* 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))
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->rx_fc_out_tbl.ctx_id,
+ bp->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,
+ 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->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->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->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;
+}
+
+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);
+}
+
+static void bnxt_uninit_ctx_mem(struct bnxt *bp)
+{
+ bnxt_uninit_fc_ctx_mem(bp);
+}
+
static void
bnxt_uninit_locks(struct bnxt *bp)
{
}
}
+ bnxt_uninit_ctx_mem(bp);
+
bnxt_uninit_locks(bp);
rte_free(bp->ptp_cfg);
bp->ptp_cfg = NULL;