goto error;
}
- if (hw->is_pf)
+ if (hw->is_pf && rte_eal_process_type() == RTE_PROC_PRIMARY)
/* Configure the physical port up */
nfp_eth_set_configured(hw->cpp, hw->pf_port_idx, 1);
+ else
+ nfp_eth_set_configured(dev->process_private,
+ hw->pf_port_idx, 1);
hw->ctrl = new_ctrl;
(struct nfp_net_rxq *)dev->data->rx_queues[i]);
}
- if (hw->is_pf)
+ if (hw->is_pf && rte_eal_process_type() == RTE_PROC_PRIMARY)
/* Configure the physical port down */
nfp_eth_set_configured(hw->cpp, hw->pf_port_idx, 0);
+ else
+ nfp_eth_set_configured(dev->process_private,
+ hw->pf_port_idx, 0);
}
/* Reset and stop device. The device can not be restarted. */
hw->mac_addr[0], hw->mac_addr[1], hw->mac_addr[2],
hw->mac_addr[3], hw->mac_addr[4], hw->mac_addr[5]);
- /* Registering LSC interrupt handler */
- rte_intr_callback_register(&pci_dev->intr_handle,
- nfp_net_dev_interrupt_handler,
- (void *)eth_dev);
-
- /* Telling the firmware about the LSC interrupt entry */
- nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
-
- /* Recording current stats counters values */
- nfp_net_stats_reset(eth_dev);
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ /* Registering LSC interrupt handler */
+ rte_intr_callback_register(&pci_dev->intr_handle,
+ nfp_net_dev_interrupt_handler,
+ (void *)eth_dev);
+ /* Telling the firmware about the LSC interrupt entry */
+ nn_cfg_writeb(hw, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
+ /* Recording current stats counters values */
+ nfp_net_stats_reset(eth_dev);
+ }
return 0;
struct rte_eth_dev *eth_dev;
struct nfp_net_hw *hw;
char *port_name;
- int ret;
+ int retval;
port_name = rte_zmalloc("nfp_pf_port_name", 100, 0);
if (!port_name)
else
sprintf(port_name, "%s", dev->device.name);
- eth_dev = rte_eth_dev_allocate(port_name);
- if (!eth_dev)
- return -ENOMEM;
- if (port == 0) {
- *priv = rte_zmalloc(port_name,
- sizeof(struct nfp_net_adapter) * ports,
- RTE_CACHE_LINE_SIZE);
- if (!*priv) {
- rte_eth_dev_release_port(eth_dev);
- return -ENOMEM;
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ eth_dev = rte_eth_dev_allocate(port_name);
+ if (!eth_dev) {
+ rte_free(port_name);
+ return -ENODEV;
}
- }
-
- eth_dev->data->dev_private = *priv;
-
- /*
- * dev_private pointing to port0 dev_private because we need
- * to configure vNIC bars based on port0 at nfp_net_init.
- * Then dev_private is adjusted per port.
- */
- hw = (struct nfp_net_hw *)(eth_dev->data->dev_private) + port;
- hw->cpp = cpp;
- hw->hwinfo = hwinfo;
- hw->sym_tbl = sym_tbl;
- hw->pf_port_idx = phys_port;
- hw->is_pf = 1;
- if (ports > 1)
- hw->pf_multiport_enabled = 1;
+ if (port == 0) {
+ *priv = rte_zmalloc(port_name,
+ sizeof(struct nfp_net_adapter) *
+ ports, RTE_CACHE_LINE_SIZE);
+ if (!*priv) {
+ rte_free(port_name);
+ rte_eth_dev_release_port(eth_dev);
+ return -ENOMEM;
+ }
+ }
+ eth_dev->data->dev_private = *priv;
- hw->total_ports = ports;
+ /*
+ * dev_private pointing to port0 dev_private because we need
+ * to configure vNIC bars based on port0 at nfp_net_init.
+ * Then dev_private is adjusted per port.
+ */
+ hw = (struct nfp_net_hw *)(eth_dev->data->dev_private) + port;
+ hw->cpp = cpp;
+ hw->hwinfo = hwinfo;
+ hw->sym_tbl = sym_tbl;
+ hw->pf_port_idx = phys_port;
+ hw->is_pf = 1;
+ if (ports > 1)
+ hw->pf_multiport_enabled = 1;
+
+ hw->total_ports = ports;
+ } else {
+ eth_dev = rte_eth_dev_attach_secondary(port_name);
+ if (!eth_dev) {
+ RTE_LOG(ERR, EAL, "secondary process attach failed, "
+ "ethdev doesn't exist");
+ rte_free(port_name);
+ return -ENODEV;
+ }
+ eth_dev->process_private = cpp;
+ }
eth_dev->device = &dev->device;
rte_eth_copy_pci_info(eth_dev, dev);
- ret = nfp_net_init(eth_dev);
+ retval = nfp_net_init(eth_dev);
- if (ret)
- rte_eth_dev_release_port(eth_dev);
- else
+ if (retval) {
+ retval = -ENODEV;
+ goto probe_failed;
+ } else {
rte_eth_dev_probing_finish(eth_dev);
+ }
rte_free(port_name);
- return ret;
+ return retval;
+
+probe_failed:
+ rte_free(port_name);
+ /* free ports private data if primary process */
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ rte_free(eth_dev->data->dev_private);
+
+ rte_eth_dev_release_port(eth_dev);
+
+ return retval;
}
#define DEFAULT_FW_PATH "/lib/firmware/netronome"
return -EIO;
}
- if (nfp_fw_setup(dev, cpp, nfp_eth_table, hwinfo)) {
- PMD_DRV_LOG(INFO, "Error when uploading firmware");
- ret = -EIO;
- goto error;
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ if (nfp_fw_setup(dev, cpp, nfp_eth_table, hwinfo)) {
+ PMD_DRV_LOG(INFO, "Error when uploading firmware");
+ ret = -EIO;
+ goto error;
+ }
}
/* Now the symbol table should be there */
int device;
int lock;
+ int secondary_lock;
char busdev[BUSDEV_SZ];
int barsz;
char *cfg;
* already mapped.
*
* BAR0.0: Reserved for General Mapping (for MSI-X access to PCIe SRAM)
+ *
+ * Halving PCItoCPPBars for primary and secondary processes.
+ * NFP PMD just requires two fixed slots, one for configuration BAR,
+ * and another for accessing the hw queues. Another slot is needed
+ * for setting the link up or down. Secondary processes do not need
+ * to map the first two slots again, but it requires one slot for
+ * accessing the link, even if it is not likely the secondary process
+ * starting the port. This implies a limit of secondary processes
+ * supported. Due to this requirement and future extensions requiring
+ * new slots per process, only one secondary process is supported by
+ * now.
*/
static int
nfp_enable_bars(struct nfp_pcie_user *nfp)
{
struct nfp_bar *bar;
- int x;
+ int x, start, end;
- for (x = ARRAY_SIZE(nfp->bar); x > 0; x--) {
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ start = 4;
+ end = 1;
+ } else {
+ start = 7;
+ end = 4;
+ }
+ for (x = start; x > end; x--) {
bar = &nfp->bar[x - 1];
bar->barcfg = 0;
bar->nfp = nfp;
nfp_alloc_bar(struct nfp_pcie_user *nfp)
{
struct nfp_bar *bar;
- int x;
+ int x, start, end;
- for (x = ARRAY_SIZE(nfp->bar); x > 0; x--) {
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ start = 4;
+ end = 1;
+ } else {
+ start = 7;
+ end = 4;
+ }
+ for (x = start; x > end; x--) {
bar = &nfp->bar[x - 1];
if (!bar->lock) {
bar->lock = 1;
nfp_disable_bars(struct nfp_pcie_user *nfp)
{
struct nfp_bar *bar;
- int x;
+ int x, start, end;
+
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ start = 4;
+ end = 1;
+ } else {
+ start = 7;
+ end = 4;
+ }
- for (x = ARRAY_SIZE(nfp->bar); x > 0; x--) {
+ for (x = start; x > end; x--) {
bar = &nfp->bar[x - 1];
if (bar->iomem) {
bar->iomem = NULL;
return 0;
}
+static int
+nfp_acquire_secondary_process_lock(struct nfp_pcie_user *desc)
+{
+ int rc;
+ struct flock lock;
+ const char *lockname = "/.lock_nfp_secondary";
+ char *home_path;
+ char *lockfile;
+
+ memset(&lock, 0, sizeof(lock));
+
+ /*
+ * Using user's home directory. Note this can be called in a DPDK app
+ * being executed as non-root. This is not the case for the previous
+ * function nfp_acquire_process_lock which is invoked only when UIO
+ * driver is used because that implies root user.
+ */
+ home_path = getenv("HOME");
+ lockfile = calloc(strlen(home_path) + strlen(lockname) + 1,
+ sizeof(char));
+
+ strcat(lockfile, home_path);
+ strcat(lockfile, "/.lock_nfp_secondary");
+ desc->secondary_lock = open(lockfile, O_RDWR | O_CREAT | O_NONBLOCK,
+ 0666);
+ if (desc->secondary_lock < 0) {
+ RTE_LOG(ERR, PMD, "NFP lock for secondary process failed\n");
+ return desc->secondary_lock;
+ }
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ rc = fcntl(desc->secondary_lock, F_SETLK, &lock);
+ if (rc < 0) {
+ RTE_LOG(ERR, PMD, "NFP lock for secondary process failed\n");
+ close(desc->secondary_lock);
+ }
+
+ return rc;
+}
+
static int
nfp6000_set_model(struct rte_pci_device *dev, struct nfp_cpp *cpp)
{
nfp6000_init(struct nfp_cpp *cpp, struct rte_pci_device *dev)
{
int ret = 0;
- uint32_t model;
struct nfp_pcie_user *desc;
desc = malloc(sizeof(*desc));
memset(desc->busdev, 0, BUSDEV_SZ);
strlcpy(desc->busdev, dev->device.name, sizeof(desc->busdev));
- if (cpp->driver_lock_needed) {
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
+ cpp->driver_lock_needed) {
ret = nfp_acquire_process_lock(desc);
if (ret)
return -1;
}
+ /* Just support for one secondary process */
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ ret = nfp_acquire_secondary_process_lock(desc);
+ if (ret)
+ return -1;
+ }
+
if (nfp6000_set_model(dev, cpp) < 0)
return -1;
if (nfp6000_set_interface(dev, cpp) < 0)
nfp_cpp_priv_set(cpp, desc);
- model = __nfp_cpp_model_autodetect(cpp);
- nfp_cpp_model_set(cpp, model);
-
return ret;
}
nfp_disable_bars(desc);
if (cpp->driver_lock_needed)
close(desc->lock);
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ close(desc->secondary_lock);
close(desc->device);
free(desc);
}