#include <assert.h>
#include <stdio.h>
+#if defined(RTE_BACKTRACE)
#include <execinfo.h>
+#endif
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/file.h>
#include <sys/stat.h>
-#include <rte_ethdev_pci.h>
+#include <ethdev_pci.h>
#include <rte_string_fns.h>
#include "nfp_cpp.h"
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;
- 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->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));
+
+ if (!lockfile)
+ return -ENOMEM;
+
+ 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");
+ free(lockfile);
+ 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);
+ }
+
+ free(lockfile);
+ return rc;
+}
+
static int
nfp6000_set_model(struct rte_pci_device *dev, struct nfp_cpp *cpp)
{
return 0;
}
-#define PCI_CFG_SPACE_SIZE 256
-#define PCI_CFG_SPACE_EXP_SIZE 4096
-#define PCI_EXT_CAP_ID(header) (int)(header & 0x0000ffff)
-#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
-#define PCI_EXT_CAP_ID_DSN 0x03
-static int
-nfp_pci_find_next_ext_capability(struct rte_pci_device *dev, int cap)
-{
- uint32_t header;
- int ttl;
- int pos = PCI_CFG_SPACE_SIZE;
-
- /* minimum 8 bytes per capability */
- ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
-
- if (rte_pci_read_config(dev, &header, 4, pos) < 0) {
- printf("nfp error reading extended capabilities\n");
- return -1;
- }
-
- /*
- * If we have no capabilities, this is indicated by cap ID,
- * cap version and next pointer all being 0.
- */
- if (header == 0)
- return 0;
-
- while (ttl-- > 0) {
- if (PCI_EXT_CAP_ID(header) == cap)
- return pos;
-
- pos = PCI_EXT_CAP_NEXT(header);
- if (pos < PCI_CFG_SPACE_SIZE)
- break;
-
- if (rte_pci_read_config(dev, &header, 4, pos) < 0) {
- printf("nfp error reading extended capabilities\n");
- return -1;
- }
- }
-
- return 0;
-}
-
static int
nfp6000_set_serial(struct rte_pci_device *dev, struct nfp_cpp *cpp)
{
uint16_t tmp;
uint8_t serial[6];
int serial_len = 6;
- int pos;
+ off_t pos;
- pos = nfp_pci_find_next_ext_capability(dev, PCI_EXT_CAP_ID_DSN);
+ pos = rte_pci_find_ext_capability(dev, RTE_PCI_EXT_CAP_ID_DSN);
if (pos <= 0) {
printf("PCI_EXT_CAP_ID_DSN not found. nfp set serial failed\n");
return -1;
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;
+ goto error;
+ }
+
+ /* Just support for one secondary process */
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ ret = nfp_acquire_secondary_process_lock(desc);
+ if (ret)
+ goto error;
}
if (nfp6000_set_model(dev, cpp) < 0)
- return -1;
+ goto error;
if (nfp6000_set_interface(dev, cpp) < 0)
- return -1;
+ goto error;
if (nfp6000_set_serial(dev, cpp) < 0)
- return -1;
+ goto error;
if (nfp6000_set_barsz(dev, desc) < 0)
- return -1;
+ goto error;
desc->cfg = (char *)dev->mem_resource[0].addr;
nfp_cpp_priv_set(cpp, desc);
- model = __nfp_cpp_model_autodetect(cpp);
- nfp_cpp_model_set(cpp, model);
+ return 0;
- return ret;
+error:
+ free(desc);
+ return -1;
}
static void
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);
}