-/*-
- * BSD LICENSE
- *
- * Copyright(c) Broadcom Limited.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Broadcom Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2014-2018 Broadcom
+ * All rights reserved.
*/
#include <inttypes.h>
#define BROADCOM_DEV_ID_57407_MF 0x16ea
#define BROADCOM_DEV_ID_57414_MF 0x16ec
#define BROADCOM_DEV_ID_57416_MF 0x16ee
+#define BROADCOM_DEV_ID_58802 0xd802
+#define BROADCOM_DEV_ID_58804 0xd804
+#define BROADCOM_DEV_ID_58808 0x16f0
static const struct rte_pci_id bnxt_pci_id_map[] = {
{ RTE_PCI_DEVICE(PCI_VENDOR_ID_BROADCOM,
{ RTE_PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BROADCOM_DEV_ID_57317_SFP) },
{ RTE_PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BROADCOM_DEV_ID_57414_MF) },
{ RTE_PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BROADCOM_DEV_ID_57416_MF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BROADCOM_DEV_ID_58802) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BROADCOM_DEV_ID_58804) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, BROADCOM_DEV_ID_58808) },
{ .vendor_id = 0, /* sentinel */ },
};
ETH_RSS_NONFRAG_IPV6_TCP | \
ETH_RSS_NONFRAG_IPV6_UDP)
+#define BNXT_DEV_TX_OFFLOAD_SUPPORT (DEV_TX_OFFLOAD_VLAN_INSERT | \
+ DEV_TX_OFFLOAD_IPV4_CKSUM | \
+ DEV_TX_OFFLOAD_TCP_CKSUM | \
+ DEV_TX_OFFLOAD_UDP_CKSUM | \
+ DEV_TX_OFFLOAD_TCP_TSO | \
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM | \
+ DEV_TX_OFFLOAD_VXLAN_TNL_TSO | \
+ DEV_TX_OFFLOAD_GRE_TNL_TSO | \
+ DEV_TX_OFFLOAD_IPIP_TNL_TSO | \
+ DEV_TX_OFFLOAD_GENEVE_TNL_TSO | \
+ DEV_TX_OFFLOAD_MULTI_SEGS)
+
+#define BNXT_DEV_RX_OFFLOAD_SUPPORT (DEV_RX_OFFLOAD_VLAN_FILTER | \
+ DEV_RX_OFFLOAD_VLAN_STRIP | \
+ DEV_RX_OFFLOAD_IPV4_CKSUM | \
+ DEV_RX_OFFLOAD_UDP_CKSUM | \
+ DEV_RX_OFFLOAD_TCP_CKSUM | \
+ DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | \
+ DEV_RX_OFFLOAD_JUMBO_FRAME | \
+ DEV_RX_OFFLOAD_CRC_STRIP | \
+ DEV_RX_OFFLOAD_TCP_LRO)
+
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_init_chip(struct bnxt *bp)
{
- unsigned int i, rss_idx, fw_idx;
+ unsigned int i;
struct rte_eth_link new;
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(bp->eth_dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
rte_intr_disable(intr_handle);
if (bp->eth_dev->data->mtu > ETHER_MTU) {
- bp->eth_dev->data->dev_conf.rxmode.jumbo_frame = 1;
+ bp->eth_dev->data->dev_conf.rxmode.offloads |=
+ DEV_RX_OFFLOAD_JUMBO_FRAME;
bp->flags |= BNXT_FLAG_JUMBO;
} else {
- bp->eth_dev->data->dev_conf.rxmode.jumbo_frame = 0;
+ bp->eth_dev->data->dev_conf.rxmode.offloads &=
+ ~DEV_RX_OFFLOAD_JUMBO_FRAME;
bp->flags &= ~BNXT_FLAG_JUMBO;
}
i, rc);
goto err_out;
}
- if (vnic->rss_table && vnic->hash_type) {
- /*
- * Fill the RSS hash & redirection table with
- * ring group ids for all VNICs
- */
- for (rss_idx = 0, fw_idx = 0;
- rss_idx < HW_HASH_INDEX_SIZE;
- rss_idx++, fw_idx++) {
- if (vnic->fw_grp_ids[fw_idx] ==
- INVALID_HW_RING_ID)
- fw_idx = 0;
- vnic->rss_table[rss_idx] =
- vnic->fw_grp_ids[fw_idx];
- }
- rc = bnxt_hwrm_vnic_rss_cfg(bp, vnic);
- if (rc) {
- PMD_DRV_LOG(ERR,
- "HWRM vnic %d set RSS failure rc: %x\n",
- i, rc);
- goto err_out;
- }
+
+ 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.enable_lro)
+ 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);
uint16_t max_vnics, i, j, vpool, vrxq;
unsigned int max_rx_rings;
- dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
-
/* MAC Specifics */
dev_info->max_mac_addrs = bp->max_l2_ctx;
dev_info->max_hash_mac_addrs = 0;
dev_info->min_rx_bufsize = 1;
dev_info->max_rx_pktlen = BNXT_MAX_MTU + ETHER_HDR_LEN + ETHER_CRC_LEN
+ VLAN_TAG_SIZE;
- dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
- DEV_RX_OFFLOAD_IPV4_CKSUM |
- DEV_RX_OFFLOAD_UDP_CKSUM |
- DEV_RX_OFFLOAD_TCP_CKSUM |
- DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM;
- dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
- DEV_TX_OFFLOAD_IPV4_CKSUM |
- DEV_TX_OFFLOAD_TCP_CKSUM |
- DEV_TX_OFFLOAD_UDP_CKSUM |
- DEV_TX_OFFLOAD_TCP_TSO |
- DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
- DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
- DEV_TX_OFFLOAD_GRE_TNL_TSO |
- DEV_TX_OFFLOAD_IPIP_TNL_TSO |
- DEV_TX_OFFLOAD_GENEVE_TNL_TSO;
+
+ dev_info->rx_offload_capa = BNXT_DEV_RX_OFFLOAD_SUPPORT;
+ if (bp->flags & BNXT_FLAG_PTP_SUPPORTED)
+ dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_TIMESTAMP;
+ dev_info->tx_offload_capa = BNXT_DEV_TX_OFFLOAD_SUPPORT;
+ dev_info->flow_type_rss_offloads = BNXT_ETH_RSS_SUPPORT;
/* *INDENT-OFF* */
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.wthresh = 0,
},
.rx_free_thresh = 32,
- .rx_drop_en = 0,
+ /* If no descriptors available, pkts are dropped by default */
+ .rx_drop_en = 1,
};
dev_info->default_txconf = (struct rte_eth_txconf) {
},
.tx_free_thresh = 32,
.tx_rs_thresh = 32,
- .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
- ETH_TXQ_FLAGS_NOOFFLOADS,
};
eth_dev->data->dev_conf.intr_conf.lsc = 1;
static int bnxt_dev_configure_op(struct rte_eth_dev *eth_dev)
{
struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private;
+ uint64_t tx_offloads = eth_dev->data->dev_conf.txmode.offloads;
+ uint64_t rx_offloads = eth_dev->data->dev_conf.rxmode.offloads;
+
+ if (tx_offloads != (tx_offloads & BNXT_DEV_TX_OFFLOAD_SUPPORT)) {
+ PMD_DRV_LOG
+ (ERR,
+ "Tx offloads requested 0x%" PRIx64 " supported 0x%x\n",
+ tx_offloads, BNXT_DEV_TX_OFFLOAD_SUPPORT);
+ return -ENOTSUP;
+ }
+
+ if (rx_offloads != (rx_offloads & BNXT_DEV_RX_OFFLOAD_SUPPORT)) {
+ PMD_DRV_LOG
+ (ERR,
+ "Rx offloads requested 0x%" PRIx64 " supported 0x%x\n",
+ rx_offloads, BNXT_DEV_RX_OFFLOAD_SUPPORT);
+ return -ENOTSUP;
+ }
bp->rx_queues = (void *)eth_dev->data->rx_queues;
bp->tx_queues = (void *)eth_dev->data->tx_queues;
bp->rx_cp_nr_rings = bp->rx_nr_rings;
bp->tx_cp_nr_rings = bp->tx_nr_rings;
- if (eth_dev->data->dev_conf.rxmode.jumbo_frame)
+ if (rx_offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
eth_dev->data->mtu =
eth_dev->data->dev_conf.rxmode.max_rx_pkt_len -
ETHER_HDR_LEN - ETHER_CRC_LEN - VLAN_TAG_SIZE;
static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
{
struct bnxt *bp = (struct bnxt *)eth_dev->data->dev_private;
+ uint64_t rx_offloads = eth_dev->data->dev_conf.rxmode.offloads;
int vlan_mask = 0;
int rc;
bnxt_link_update_op(eth_dev, 1);
- if (eth_dev->data->dev_conf.rxmode.hw_vlan_filter)
+ if (rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
vlan_mask |= ETH_VLAN_FILTER_MASK;
- if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
+ if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
vlan_mask |= ETH_VLAN_STRIP_MASK;
rc = bnxt_vlan_offload_set_op(eth_dev, vlan_mask);
if (rc)
if (filter->mac_index == index) {
PMD_DRV_LOG(ERR,
"MAC addr already existed for pool %d\n", pool);
- return -EINVAL;
+ return 0;
}
}
filter = bnxt_alloc_filter(bp);
bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
{
struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+ uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
unsigned int i;
if (mask & ETH_VLAN_FILTER_MASK) {
- if (!dev->data->dev_conf.rxmode.hw_vlan_filter) {
+ if (!(rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER)) {
/* Remove any VLAN filters programmed */
for (i = 0; i < 4095; i++)
bnxt_del_vlan_filter(bp, i);
}
PMD_DRV_LOG(DEBUG, "VLAN Filtering: %d\n",
- dev->data->dev_conf.rxmode.hw_vlan_filter);
+ !!(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 (dev->data->dev_conf.rxmode.hw_vlan_strip)
+ 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",
- dev->data->dev_conf.rxmode.hw_vlan_strip);
+ !!(rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP));
}
if (mask & ETH_VLAN_EXTEND_MASK)
return 0;
}
-static void
+static int
bnxt_set_default_mac_addr_op(struct rte_eth_dev *dev, struct ether_addr *addr)
{
struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
int rc;
if (BNXT_VF(bp))
- return;
+ return -EPERM;
memcpy(bp->mac_addr, addr, sizeof(bp->mac_addr));
continue;
rc = bnxt_hwrm_clear_l2_filter(bp, filter);
if (rc)
- break;
+ return rc;
memcpy(filter->l2_addr, bp->mac_addr, ETHER_ADDR_LEN);
memset(filter->l2_addr_mask, 0xff, ETHER_ADDR_LEN);
filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX;
HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK;
rc = bnxt_hwrm_set_l2_filter(bp, vnic->fw_vnic_id, filter);
if (rc)
- break;
+ return rc;
filter->mac_index = 0;
PMD_DRV_LOG(DEBUG, "Set MAC addr\n");
}
+
+ return 0;
}
static int
if (new_mtu > ETHER_MTU) {
bp->flags |= BNXT_FLAG_JUMBO;
- eth_dev->data->dev_conf.rxmode.jumbo_frame = 1;
+ bp->eth_dev->data->dev_conf.rxmode.offloads |=
+ DEV_RX_OFFLOAD_JUMBO_FRAME;
} else {
- eth_dev->data->dev_conf.rxmode.jumbo_frame = 0;
+ bp->eth_dev->data->dev_conf.rxmode.offloads &=
+ ~DEV_RX_OFFLOAD_JUMBO_FRAME;
bp->flags &= ~BNXT_FLAG_JUMBO;
}
}
static struct bnxt_filter_info *
-bnxt_match_fdir(struct bnxt *bp, struct bnxt_filter_info *nf)
+bnxt_match_fdir(struct bnxt *bp, struct bnxt_filter_info *nf,
+ struct bnxt_vnic_info **mvnic)
{
struct bnxt_filter_info *mf = NULL;
int i;
!memcmp(mf->dst_ipaddr, nf->dst_ipaddr,
sizeof(nf->dst_ipaddr)) &&
!memcmp(mf->dst_ipaddr_mask, nf->dst_ipaddr_mask,
- sizeof(nf->dst_ipaddr_mask)))
+ sizeof(nf->dst_ipaddr_mask))) {
+ if (mvnic)
+ *mvnic = vnic;
return mf;
+ }
}
}
return NULL;
struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
struct rte_eth_fdir_filter *fdir = (struct rte_eth_fdir_filter *)arg;
struct bnxt_filter_info *filter, *match;
- struct bnxt_vnic_info *vnic;
+ struct bnxt_vnic_info *vnic, *mvnic;
int ret = 0, i;
if (filter_op == RTE_ETH_FILTER_NOP)
switch (filter_op) {
case RTE_ETH_FILTER_ADD:
case RTE_ETH_FILTER_DELETE:
- /* FALLTHROUGH */
filter = bnxt_get_unused_filter(bp);
if (filter == NULL) {
PMD_DRV_LOG(ERR,
goto free_filter;
filter->filter_type = HWRM_CFA_NTUPLE_FILTER;
- match = bnxt_match_fdir(bp, filter);
+ if (fdir->action.behavior == RTE_ETH_FDIR_REJECT)
+ vnic = STAILQ_FIRST(&bp->ff_pool[0]);
+ else
+ vnic = STAILQ_FIRST(&bp->ff_pool[fdir->action.rx_queue]);
+
+ match = bnxt_match_fdir(bp, filter, &mvnic);
if (match != NULL && filter_op == RTE_ETH_FILTER_ADD) {
- PMD_DRV_LOG(ERR, "Flow already exists.\n");
- ret = -EEXIST;
- goto free_filter;
+ if (match->dst_id == vnic->fw_vnic_id) {
+ PMD_DRV_LOG(ERR, "Flow already exists.\n");
+ ret = -EEXIST;
+ goto free_filter;
+ } else {
+ match->dst_id = vnic->fw_vnic_id;
+ ret = bnxt_hwrm_set_ntuple_filter(bp,
+ match->dst_id,
+ match);
+ STAILQ_REMOVE(&mvnic->filter, match,
+ bnxt_filter_info, next);
+ STAILQ_INSERT_TAIL(&vnic->filter, match, next);
+ PMD_DRV_LOG(ERR,
+ "Filter with matching pattern exist\n");
+ PMD_DRV_LOG(ERR,
+ "Updated it to new destination q\n");
+ goto free_filter;
+ }
}
if (match == NULL && filter_op == RTE_ETH_FILTER_DELETE) {
PMD_DRV_LOG(ERR, "Flow does not exist.\n");
goto free_filter;
}
- if (fdir->action.behavior == RTE_ETH_FDIR_REJECT)
- vnic = STAILQ_FIRST(&bp->ff_pool[0]);
- else
- vnic =
- STAILQ_FIRST(&bp->ff_pool[fdir->action.rx_queue]);
-
if (filter_op == RTE_ETH_FILTER_ADD) {
ret = bnxt_hwrm_set_ntuple_filter(bp,
filter->dst_id,
case RTE_ETH_FILTER_UPDATE:
case RTE_ETH_FILTER_STATS:
case RTE_ETH_FILTER_INFO:
- /* FALLTHROUGH */
PMD_DRV_LOG(ERR, "operation %u not implemented", filter_op);
break;
default:
.rx_queue_count = bnxt_rx_queue_count_op,
.rx_descriptor_status = bnxt_rx_descriptor_status_op,
.tx_descriptor_status = bnxt_tx_descriptor_status_op,
+ .rx_queue_start = bnxt_rx_queue_start,
+ .rx_queue_stop = bnxt_rx_queue_stop,
+ .tx_queue_start = bnxt_tx_queue_start,
+ .tx_queue_stop = bnxt_tx_queue_stop,
.filter_ctrl = bnxt_filter_ctrl_op,
.dev_supported_ptypes_get = bnxt_dev_supported_ptypes_get_op,
.get_eeprom_length = bnxt_get_eeprom_length_op,
sizeof(struct rx_port_stats) + 512);
if (!mz) {
mz = rte_memzone_reserve(mz_name, total_alloc_len,
- SOCKET_ID_ANY,
- RTE_MEMZONE_2MB |
- RTE_MEMZONE_SIZE_HINT_ONLY);
+ SOCKET_ID_ANY,
+ RTE_MEMZONE_2MB |
+ RTE_MEMZONE_SIZE_HINT_ONLY |
+ RTE_MEMZONE_IOVA_CONTIG);
if (mz == NULL)
return -ENOMEM;
}
total_alloc_len = RTE_CACHE_LINE_ROUNDUP(
sizeof(struct tx_port_stats) + 512);
if (!mz) {
- mz = rte_memzone_reserve(mz_name, total_alloc_len,
- SOCKET_ID_ANY,
- RTE_MEMZONE_2MB |
- RTE_MEMZONE_SIZE_HINT_ONLY);
+ mz = rte_memzone_reserve(mz_name,
+ total_alloc_len,
+ SOCKET_ID_ANY,
+ RTE_MEMZONE_2MB |
+ RTE_MEMZONE_SIZE_HINT_ONLY |
+ RTE_MEMZONE_IOVA_CONTIG);
if (mz == NULL)
return -ENOMEM;
}
rc = -ENOMEM;
goto error_free;
}
+
+ if (check_zero_bytes(bp->dflt_mac_addr, ETHER_ADDR_LEN)) {
+ PMD_DRV_LOG(ERR,
+ "Invalid MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n",
+ bp->dflt_mac_addr[0], bp->dflt_mac_addr[1],
+ bp->dflt_mac_addr[2], bp->dflt_mac_addr[3],
+ bp->dflt_mac_addr[4], bp->dflt_mac_addr[5]);
+ rc = -EINVAL;
+ goto error_free;
+ }
/* Copy the permanent MAC from the qcap response address now. */
memcpy(bp->mac_addr, bp->dflt_mac_addr, sizeof(bp->mac_addr));
memcpy(ð_dev->data->mac_addrs[0], bp->mac_addr, ETHER_ADDR_LEN);