This document explains how to use DPDK with the Netronome Poll Mode
Driver (PMD) supporting Netronome's Network Flow Processor 6xxx
-(NFP-6xxx) and Netronome's Flow Processor 4xxx (NFP-4xxx).
+(NFP-6xxx), Netronome's Network Flow Processor 4xxx (NFP-4xxx) and
+Netronome's Network Flow Processor 38xx (NFP-38xx).
NFP is a SRIOV capable device and the PMD supports the physical
function (PF) and the virtual functions (VFs).
* Added support for MTU on Windows.
* Added matching and RSS on IPsec ESP.
+* **Updated Netronome nfp driver.**
+
+ * Added support for NFP3800 NIC.
+
* **Updated VMware vmxnet3 networking driver.**
* Added version 5 support.
#define NFP_NET_PMD_VERSION "0.1"
#define PCI_VENDOR_ID_NETRONOME 0x19ee
+#define PCI_DEVICE_ID_NFP3800_PF_NIC 0x3800
+#define PCI_DEVICE_ID_NFP3800_VF_NIC 0x3803
#define PCI_DEVICE_ID_NFP4000_PF_NIC 0x4000
#define PCI_DEVICE_ID_NFP6000_PF_NIC 0x6000
-#define PCI_DEVICE_ID_NFP6000_VF_NIC 0x6003
+#define PCI_DEVICE_ID_NFP6000_VF_NIC 0x6003 /* Include NFP4000VF */
/* Forward declaration */
struct nfp_net_adapter;
#define NFP_QCP_QUEUE_STS_HI 0x000c
#define NFP_QCP_QUEUE_STS_HI_WRITEPTR_mask (0x3ffff)
+#define NFP_PCIE_QCP_NFP3800_OFFSET 0x400000
+#define NFP_PCIE_QCP_NFP6000_OFFSET 0x80000
+#define NFP_PCIE_QUEUE_NFP3800_MASK 0x1ff
+#define NFP_PCIE_QUEUE_NFP6000_MASK 0xff
+#define NFP_PCIE_QCP_PF_OFFSET 0x0
+#define NFP_PCIE_QCP_VF_OFFSET 0x0
+
/* The offset of the queue controller queues in the PCIe Target */
-#define NFP_PCIE_QUEUE(_q) (0x80000 + (NFP_QCP_QUEUE_ADDR_SZ * ((_q) & 0xff)))
+#define NFP_PCIE_QUEUE(_offset, _q, _mask) \
+ ((_offset) + (NFP_QCP_QUEUE_ADDR_SZ * ((_q) & (_mask))))
/* Interrupt definitions */
#define NFP_NET_IRQ_LSC_IDX 0
return val & NFP_QCP_QUEUE_STS_HI_WRITEPTR_mask;
}
+static inline uint32_t
+nfp_pci_queue(struct rte_pci_device *pdev, uint16_t queue)
+{
+ switch (pdev->id.device_id) {
+ case PCI_DEVICE_ID_NFP4000_PF_NIC:
+ case PCI_DEVICE_ID_NFP6000_PF_NIC:
+ return NFP_PCIE_QUEUE(NFP_PCIE_QCP_PF_OFFSET, queue,
+ NFP_PCIE_QUEUE_NFP6000_MASK);
+ case PCI_DEVICE_ID_NFP3800_VF_NIC:
+ return NFP_PCIE_QUEUE(NFP_PCIE_QCP_VF_OFFSET, queue,
+ NFP_PCIE_QUEUE_NFP3800_MASK);
+ case PCI_DEVICE_ID_NFP6000_VF_NIC:
+ return NFP_PCIE_QUEUE(NFP_PCIE_QCP_VF_OFFSET, queue,
+ NFP_PCIE_QUEUE_NFP6000_MASK);
+ default:
+ return NFP_PCIE_QUEUE(NFP_PCIE_QCP_PF_OFFSET, queue,
+ NFP_PCIE_QUEUE_NFP3800_MASK);
+ }
+}
+
/* Prototypes for common NFP functions */
int nfp_net_reconfig(struct nfp_net_hw *hw, uint32_t ctrl, uint32_t update);
int nfp_net_configure(struct rte_eth_dev *dev);
/* Work out where in the BAR the queues start. */
switch (pci_dev->id.device_id) {
+ case PCI_DEVICE_ID_NFP3800_PF_NIC:
case PCI_DEVICE_ID_NFP4000_PF_NIC:
case PCI_DEVICE_ID_NFP6000_PF_NIC:
start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ);
- tx_bar_off = (uint64_t)start_q * NFP_QCP_QUEUE_ADDR_SZ;
+ tx_bar_off = nfp_pci_queue(pci_dev, start_q);
start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ);
- rx_bar_off = (uint64_t)start_q * NFP_QCP_QUEUE_ADDR_SZ;
+ rx_bar_off = nfp_pci_queue(pci_dev, start_q);
break;
default:
PMD_DRV_LOG(ERR, "nfp_net: no device ID matching");
{
int err;
int ret = 0;
+ uint64_t addr;
int total_ports;
struct nfp_cpp *cpp;
struct nfp_pf_dev *pf_dev;
PMD_INIT_LOG(DEBUG, "ctrl bar: %p", pf_dev->ctrl_bar);
/* configure access to tx/rx vNIC BARs */
+ switch (pci_dev->id.device_id) {
+ case PCI_DEVICE_ID_NFP3800_PF_NIC:
+ addr = NFP_PCIE_QUEUE(NFP_PCIE_QCP_NFP3800_OFFSET,
+ 0, NFP_PCIE_QUEUE_NFP3800_MASK);
+ break;
+ case PCI_DEVICE_ID_NFP4000_PF_NIC:
+ case PCI_DEVICE_ID_NFP6000_PF_NIC:
+ addr = NFP_PCIE_QUEUE(NFP_PCIE_QCP_NFP6000_OFFSET,
+ 0, NFP_PCIE_QUEUE_NFP6000_MASK);
+ break;
+ default:
+ PMD_INIT_LOG(ERR, "nfp_net: no device ID matching");
+ err = -ENODEV;
+ goto ctrl_area_cleanup;
+ }
+
pf_dev->hw_queues = nfp_cpp_map_area(pf_dev->cpp, 0, 0,
- NFP_PCIE_QUEUE(0), NFP_QCP_QUEUE_AREA_SZ,
+ addr, NFP_QCP_QUEUE_AREA_SZ,
&pf_dev->hwqueues_area);
if (pf_dev->hw_queues == NULL) {
PMD_INIT_LOG(ERR, "nfp_rtsym_map fails for net.qc");
}
static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
+ {
+ RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
+ PCI_DEVICE_ID_NFP3800_PF_NIC)
+ },
{
RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
PCI_DEVICE_ID_NFP4000_PF_NIC)
/* Work out where in the BAR the queues start. */
switch (pci_dev->id.device_id) {
+ case PCI_DEVICE_ID_NFP3800_VF_NIC:
case PCI_DEVICE_ID_NFP6000_VF_NIC:
start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_TXQ);
- tx_bar_off = (uint64_t)start_q * NFP_QCP_QUEUE_ADDR_SZ;
+ tx_bar_off = nfp_pci_queue(pci_dev, start_q);
start_q = nn_cfg_readl(hw, NFP_NET_CFG_START_RXQ);
- rx_bar_off = (uint64_t)start_q * NFP_QCP_QUEUE_ADDR_SZ;
+ rx_bar_off = nfp_pci_queue(pci_dev, start_q);
break;
default:
PMD_DRV_LOG(ERR, "nfp_net: no device ID matching");
}
static const struct rte_pci_id pci_id_nfp_vf_net_map[] = {
+ {
+ RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
+ PCI_DEVICE_ID_NFP3800_VF_NIC)
+ },
{
RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
PCI_DEVICE_ID_NFP6000_VF_NIC)
* @return true if model is in the NFP6000 family, false otherwise.
*/
#define NFP_CPP_MODEL_IS_6000(model) \
- ((NFP_CPP_MODEL_CHIP_of(model) >= 0x4000) && \
+ ((NFP_CPP_MODEL_CHIP_of(model) >= 0x3800) && \
(NFP_CPP_MODEL_CHIP_of(model) < 0x7000))
/*
struct nfp_eth_table *table;
uint32_t table_sz;
int i, j, ret, cnt = 0;
+ const struct rte_ether_addr *mac;
entries = malloc(NSP_ETH_TABLE_SIZE);
if (!entries)
goto err;
}
- for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
- if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
+ /* The NFP3800 NIC support 8 ports, but only 2 ports are valid,
+ * the rest 6 ports mac are all 0, ensure we don't use these port
+ */
+ for (i = 0; i < NSP_ETH_MAX_COUNT; i++) {
+ mac = (const struct rte_ether_addr *)entries[i].mac_addr;
+ if ((entries[i].port & NSP_ETH_PORT_LANES_MASK) &&
+ (!rte_is_zero_ether_addr(mac)))
cnt++;
+ }
/* Some versions of flash will give us 0 instead of port count. For
* those that give a port count, verify it against the value calculated
memset(table, 0, table_sz);
table->count = cnt;
- for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++)
- if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
+ for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++) {
+ mac = (const struct rte_ether_addr *)entries[i].mac_addr;
+ if ((entries[i].port & NSP_ETH_PORT_LANES_MASK) &&
+ (!rte_is_zero_ether_addr(mac)))
nfp_eth_port_translate(nsp, &entries[i], i,
- &table->ports[j++]);
+ &table->ports[j++]);
+ }
nfp_eth_calc_port_geometry(table);
for (i = 0; i < (int)table->count; i++)