struct rte_eth_dev_info *dev_info);
static int nfp_net_init(struct rte_eth_dev *eth_dev);
static int nfp_pf_init(struct rte_eth_dev *eth_dev);
+static int nfp_pci_uninit(struct rte_eth_dev *eth_dev);
static int nfp_init_phyports(struct nfp_pf_dev *pf_dev);
static int nfp_net_link_update(struct rte_eth_dev *dev, int wait_to_complete);
static int nfp_net_promisc_enable(struct rte_eth_dev *dev);
if (hw->is_phyport) {
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
/* Configure the physical port up */
- nfp_eth_set_configured(hw->cpp, hw->idx, 1);
+ nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 1);
else
nfp_eth_set_configured(dev->process_private,
- hw->idx, 1);
+ hw->nfp_idx, 1);
}
hw->ctrl = new_ctrl;
if (hw->is_phyport) {
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
/* Configure the physical port down */
- nfp_eth_set_configured(hw->cpp, hw->idx, 0);
+ nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 0);
else
nfp_eth_set_configured(dev->process_private,
- hw->idx, 0);
+ hw->nfp_idx, 0);
}
return 0;
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
/* Configure the physical port down */
- return nfp_eth_set_configured(hw->cpp, hw->idx, 1);
+ return nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 1);
else
return nfp_eth_set_configured(dev->process_private,
- hw->idx, 1);
+ hw->nfp_idx, 1);
}
/* Set the link down. */
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
/* Configure the physical port down */
- return nfp_eth_set_configured(hw->cpp, hw->idx, 0);
+ return nfp_eth_set_configured(hw->cpp, hw->nfp_idx, 0);
else
return nfp_eth_set_configured(dev->process_private,
- hw->idx, 0);
+ hw->nfp_idx, 0);
}
/* Reset and stop device. The device can not be restarted. */
(struct nfp_net_rxq *)dev->data->rx_queues[i]);
}
+ /* Only free PF resources after all physical ports have been closed */
+ if (pci_dev->id.device_id == PCI_DEVICE_ID_NFP4000_PF_NIC ||
+ pci_dev->id.device_id == PCI_DEVICE_ID_NFP6000_PF_NIC) {
+ struct nfp_pf_dev *pf_dev;
+ pf_dev = NFP_NET_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+ /* Mark this port as unused and free device priv resources*/
+ nn_cfg_writeb(hw, NFP_NET_CFG_LSC, 0xff);
+ pf_dev->ports[hw->idx] = NULL;
+ rte_eth_dev_release_port(dev);
+
+ for (i = 0; i < pf_dev->total_phyports; i++) {
+ /* Check to see if ports are still in use */
+ if (pf_dev->ports[i])
+ return 0;
+ }
+
+ /* Now it is safe to free all PF resources */
+ PMD_INIT_LOG(INFO, "Freeing PF resources");
+ nfp_cpp_area_free(pf_dev->ctrl_area);
+ nfp_cpp_area_free(pf_dev->hwqueues_area);
+ free(pf_dev->hwinfo);
+ free(pf_dev->sym_tbl);
+ nfp_cpp_free(pf_dev->cpp);
+ rte_free(pf_dev);
+ }
+
rte_intr_disable(&pci_dev->intr_handle);
- nn_cfg_writeb(hw, NFP_NET_CFG_LSC, 0xff);
/* unregister callback func from eal lib */
rte_intr_callback_unregister(&pci_dev->intr_handle,
DEV_RX_OFFLOAD_UDP_CKSUM |
DEV_RX_OFFLOAD_TCP_CKSUM;
- dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_JUMBO_FRAME |
- DEV_RX_OFFLOAD_RSS_HASH;
-
if (hw->cap & NFP_NET_CFG_CTRL_TXVLAN)
dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT;
.nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG,
};
- dev_info->flow_type_rss_offloads = ETH_RSS_IPV4 |
- ETH_RSS_NONFRAG_IPV4_TCP |
- ETH_RSS_NONFRAG_IPV4_UDP |
- ETH_RSS_IPV6 |
- ETH_RSS_NONFRAG_IPV6_TCP |
- ETH_RSS_NONFRAG_IPV6_UDP;
+ /* All NFP devices support jumbo frames */
+ dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_JUMBO_FRAME;
+
+ if (hw->cap & NFP_NET_CFG_CTRL_RSS) {
+ dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_RSS_HASH;
- dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
- dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;
+ dev_info->flow_type_rss_offloads = ETH_RSS_IPV4 |
+ ETH_RSS_NONFRAG_IPV4_TCP |
+ ETH_RSS_NONFRAG_IPV4_UDP |
+ ETH_RSS_IPV6 |
+ ETH_RSS_NONFRAG_IPV6_TCP |
+ ETH_RSS_NONFRAG_IPV6_UDP;
+
+ dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
+ dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;
+ }
dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
ETH_LINK_SPEED_25G | ETH_LINK_SPEED_40G |
return -ENODEV;
}
- /* This points to the specific port private data */
- PMD_INIT_LOG(DEBUG, "Working with physical port number %d",
- port);
-
/* Use PF array of physical ports to get pointer to
* this specific port
*/
hw = pf_dev->ports[port];
+ PMD_INIT_LOG(DEBUG, "Working with physical port number: %d, "
+ "NFP internal port number: %d",
+ port, hw->nfp_idx);
+
} else {
hw = NFP_NET_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
}
{
struct nfp_net_hw *hw;
struct rte_eth_dev *eth_dev;
+ struct nfp_eth_table *nfp_eth_table = NULL;
int ret = 0;
int i;
+ nfp_eth_table = nfp_eth_read_ports(pf_dev->cpp);
+ if (!nfp_eth_table) {
+ PMD_INIT_LOG(ERR, "Error reading NFP ethernet table");
+ ret = -EIO;
+ goto error;
+ }
+
/* Loop through all physical ports on PF */
for (i = 0; i < pf_dev->total_phyports; i++) {
const unsigned int numa_node = rte_socket_id();
hw->cpp = pf_dev->cpp;
hw->eth_dev = eth_dev;
hw->idx = i;
+ hw->nfp_idx = nfp_eth_table->ports[i].index;
hw->is_phyport = true;
nfp_net_init:
rte_eth_dev_probing_finish(eth_dev);
} /* End loop, all ports on this PF */
- return 0;
+ ret = 0;
+ goto eth_table_cleanup;
port_cleanup:
for (i = 0; i < pf_dev->total_phyports; i++) {
pf_dev->ports[i] = NULL;
}
}
+eth_table_cleanup:
+ free(nfp_eth_table);
error:
return ret;
}
},
};
+static int nfp_pci_uninit(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev;
+ uint16_t port_id;
+
+ pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+
+ if (pci_dev->id.device_id == PCI_DEVICE_ID_NFP4000_PF_NIC ||
+ pci_dev->id.device_id == PCI_DEVICE_ID_NFP6000_PF_NIC) {
+ /* Free up all physical ports under PF */
+ RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device)
+ rte_eth_dev_close(port_id);
+ /*
+ * Ports can be closed and freed but hotplugging is not
+ * currently supported
+ */
+ return -ENOTSUP;
+ }
+
+ /* VF cleanup, just free private port data */
+ return nfp_net_close(eth_dev);
+}
+
static int eth_nfp_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
struct rte_pci_device *pci_dev)
{
static int eth_nfp_pci_remove(struct rte_pci_device *pci_dev)
{
- struct rte_eth_dev *eth_dev;
-
- eth_dev = rte_eth_dev_allocated(pci_dev->device.name);
- if (eth_dev == NULL)
- return 0; /* port already released */
- if ((pci_dev->id.device_id == PCI_DEVICE_ID_NFP4000_PF_NIC) ||
- (pci_dev->id.device_id == PCI_DEVICE_ID_NFP6000_PF_NIC))
- return -ENOTSUP;
-
- return rte_eth_dev_pci_generic_remove(pci_dev, NULL);
+ return rte_eth_dev_pci_generic_remove(pci_dev, nfp_pci_uninit);
}
static struct rte_pci_driver rte_nfp_net_pf_pmd = {
RTE_PMD_REGISTER_PCI_TABLE(net_nfp_vf, pci_id_nfp_vf_net_map);
RTE_PMD_REGISTER_KMOD_DEP(net_nfp_pf, "* igb_uio | uio_pci_generic | vfio");
RTE_PMD_REGISTER_KMOD_DEP(net_nfp_vf, "* igb_uio | uio_pci_generic | vfio");
-RTE_LOG_REGISTER(nfp_logtype_init, pmd.net.nfp.init, NOTICE);
-RTE_LOG_REGISTER(nfp_logtype_driver, pmd.net.nfp.driver, NOTICE);
+RTE_LOG_REGISTER_SUFFIX(nfp_logtype_init, init, NOTICE);
+RTE_LOG_REGISTER_SUFFIX(nfp_logtype_driver, driver, NOTICE);
/*
* Local variables:
* c-file-style: "Linux"