net/sfc: avoid unnecessary actions on dummy default MAC set
[dpdk.git] / drivers / net / nfp / nfpcore / nfp_cpp_pcie_ops.c
index 52b2948..0b9db97 100644 (file)
@@ -16,7 +16,9 @@
 
 #include <assert.h>
 #include <stdio.h>
+#if defined(RTE_BACKTRACE)
 #include <execinfo.h>
+#endif
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdint.h>
@@ -31,6 +33,7 @@
 #include <sys/file.h>
 #include <sys/stat.h>
 
+#include <rte_ethdev_pci.h>
 #include <rte_string_fns.h>
 
 #include "nfp_cpp.h"
@@ -111,6 +114,7 @@ struct nfp_pcie_user {
 
        int device;
        int lock;
+       int secondary_lock;
        char busdev[BUSDEV_SZ];
        int barsz;
        char *cfg;
@@ -289,14 +293,32 @@ nfp_reconfigure_bar(struct nfp_pcie_user *nfp, struct nfp_bar *bar, int tgt,
  * 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;
@@ -309,13 +331,8 @@ nfp_enable_bars(struct nfp_pcie_user *nfp)
                bar->csr = nfp->cfg +
                           NFP_PCIE_CFG_BAR_PCIETOCPPEXPBAR(bar->index >> 3,
                                                           bar->index & 7);
-               bar->iomem =
-                   (char *)mmap(0, 1 << bar->bitsize, PROT_READ | PROT_WRITE,
-                                MAP_SHARED, nfp->device,
-                                bar->index << bar->bitsize);
 
-               if (bar->iomem == MAP_FAILED)
-                       return (-ENOMEM);
+               bar->iomem = nfp->cfg + (bar->index << bar->bitsize);
        }
        return 0;
 }
@@ -324,9 +341,16 @@ static struct nfp_bar *
 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;
@@ -340,12 +364,19 @@ static void
 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) {
-                       munmap(bar->iomem, 1 << (nfp->barsz - 3));
                        bar->iomem = NULL;
                        bar->lock = 0;
                }
@@ -639,61 +670,78 @@ nfp_acquire_process_lock(struct nfp_pcie_user *desc)
 }
 
 static int
-nfp6000_set_model(struct nfp_pcie_user *desc, struct nfp_cpp *cpp)
+nfp_acquire_secondary_process_lock(struct nfp_pcie_user *desc)
 {
-       char tmp_str[80];
-       uint32_t tmp;
-       int fp;
+       int rc;
+       struct flock lock;
+       const char *lockname = "/.lock_nfp_secondary";
+       char *home_path;
+       char *lockfile;
 
-       snprintf(tmp_str, sizeof(tmp_str), "%s/%s/config", PCI_DEVICES,
-                desc->busdev);
+       memset(&lock, 0, sizeof(lock));
 
-       fp = open(tmp_str, O_RDONLY);
-       if (!fp)
-               return -1;
+       /*
+        * 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));
 
-       lseek(fp, 0x2e, SEEK_SET);
+       if (!lockfile)
+               return -ENOMEM;
 
-       if (read(fp, &tmp, sizeof(tmp)) != sizeof(tmp)) {
-               printf("Error reading config file for model\n");
-               return -1;
+       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);
        }
 
-       tmp = tmp << 16;
+       free(lockfile);
+       return rc;
+}
 
-       if (close(fp) == -1)
+static int
+nfp6000_set_model(struct rte_pci_device *dev, struct nfp_cpp *cpp)
+{
+       uint32_t model;
+
+       if (rte_pci_read_config(dev, &model, 4, 0x2e) < 0) {
+               printf("nfp set model failed\n");
                return -1;
+       }
 
-       nfp_cpp_model_set(cpp, tmp);
+       model  = model << 16;
+       nfp_cpp_model_set(cpp, model);
 
        return 0;
 }
 
 static int
-nfp6000_set_interface(struct nfp_pcie_user *desc, struct nfp_cpp *cpp)
+nfp6000_set_interface(struct rte_pci_device *dev, struct nfp_cpp *cpp)
 {
-       char tmp_str[80];
-       uint16_t tmp;
-       int fp;
-
-       snprintf(tmp_str, sizeof(tmp_str), "%s/%s/config", PCI_DEVICES,
-                desc->busdev);
+       uint16_t interface;
 
-       fp = open(tmp_str, O_RDONLY);
-       if (!fp)
-               return -1;
-
-       lseek(fp, 0x154, SEEK_SET);
-
-       if (read(fp, &tmp, sizeof(tmp)) != sizeof(tmp)) {
-               printf("error reading config file for interface\n");
+       if (rte_pci_read_config(dev, &interface, 2, 0x154) < 0) {
+               printf("nfp set interface failed\n");
                return -1;
        }
 
-       if (close(fp) == -1)
-               return -1;
-
-       nfp_cpp_interface_set(cpp, tmp);
+       nfp_cpp_interface_set(cpp, interface);
 
        return 0;
 }
@@ -704,7 +752,7 @@ nfp6000_set_interface(struct nfp_pcie_user *desc, struct nfp_cpp *cpp)
 #define PCI_EXT_CAP_NEXT(header)       ((header >> 20) & 0xffc)
 #define PCI_EXT_CAP_ID_DSN     0x03
 static int
-nfp_pci_find_next_ext_capability(int fp, int cap)
+nfp_pci_find_next_ext_capability(struct rte_pci_device *dev, int cap)
 {
        uint32_t header;
        int ttl;
@@ -713,9 +761,8 @@ nfp_pci_find_next_ext_capability(int fp, int cap)
        /* minimum 8 bytes per capability */
        ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
 
-       lseek(fp, pos, SEEK_SET);
-       if (read(fp, &header, sizeof(header)) != sizeof(header)) {
-               printf("error reading config file for serial\n");
+       if (rte_pci_read_config(dev, &header, 4, pos) < 0) {
+               printf("nfp error reading extended capabilities\n");
                return -1;
        }
 
@@ -734,9 +781,8 @@ nfp_pci_find_next_ext_capability(int fp, int cap)
                if (pos < PCI_CFG_SPACE_SIZE)
                        break;
 
-               lseek(fp, pos, SEEK_SET);
-               if (read(fp, &header, sizeof(header)) != sizeof(header)) {
-                       printf("error reading config file for serial\n");
+               if (rte_pci_read_config(dev, &header, 4, pos) < 0) {
+                       printf("nfp error reading extended capabilities\n");
                        return -1;
                }
        }
@@ -745,101 +791,71 @@ nfp_pci_find_next_ext_capability(int fp, int cap)
 }
 
 static int
-nfp6000_set_serial(struct nfp_pcie_user *desc, struct nfp_cpp *cpp)
+nfp6000_set_serial(struct rte_pci_device *dev, struct nfp_cpp *cpp)
 {
-       char tmp_str[80];
        uint16_t tmp;
        uint8_t serial[6];
        int serial_len = 6;
-       int fp, pos;
-
-       snprintf(tmp_str, sizeof(tmp_str), "%s/%s/config", PCI_DEVICES,
-                desc->busdev);
+       int pos;
 
-       fp = open(tmp_str, O_RDONLY);
-       if (!fp)
-               return -1;
-
-       pos = nfp_pci_find_next_ext_capability(fp, PCI_EXT_CAP_ID_DSN);
+       pos = nfp_pci_find_next_ext_capability(dev, PCI_EXT_CAP_ID_DSN);
        if (pos <= 0) {
-               printf("PCI_EXT_CAP_ID_DSN not found. Using default offset\n");
-               lseek(fp, 0x156, SEEK_SET);
+               printf("PCI_EXT_CAP_ID_DSN not found. nfp set serial failed\n");
+               return -1;
        } else {
-               lseek(fp, pos + 6, SEEK_SET);
+               pos += 6;
        }
 
-       if (read(fp, &tmp, sizeof(tmp)) != sizeof(tmp)) {
-               printf("error reading config file for serial\n");
+       if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
+               printf("nfp set serial failed\n");
                return -1;
        }
 
        serial[4] = (uint8_t)((tmp >> 8) & 0xff);
        serial[5] = (uint8_t)(tmp & 0xff);
 
-       if (read(fp, &tmp, sizeof(tmp)) != sizeof(tmp)) {
-               printf("error reading config file for serial\n");
+       pos += 2;
+       if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
+               printf("nfp set serial failed\n");
                return -1;
        }
 
        serial[2] = (uint8_t)((tmp >> 8) & 0xff);
        serial[3] = (uint8_t)(tmp & 0xff);
 
-       if (read(fp, &tmp, sizeof(tmp)) != sizeof(tmp)) {
-               printf("error reading config file for serial\n");
+       pos += 2;
+       if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
+               printf("nfp set serial failed\n");
                return -1;
        }
 
        serial[0] = (uint8_t)((tmp >> 8) & 0xff);
        serial[1] = (uint8_t)(tmp & 0xff);
 
-       if (close(fp) == -1)
-               return -1;
-
        nfp_cpp_serial_set(cpp, serial, serial_len);
 
        return 0;
 }
 
 static int
-nfp6000_set_barsz(struct nfp_pcie_user *desc)
+nfp6000_set_barsz(struct rte_pci_device *dev, struct nfp_pcie_user *desc)
 {
-       char tmp_str[80];
-       unsigned long start, end, flags, tmp;
-       int i;
-       FILE *fp;
-
-       snprintf(tmp_str, sizeof(tmp_str), "%s/%s/resource", PCI_DEVICES,
-                desc->busdev);
-
-       fp = fopen(tmp_str, "r");
-       if (!fp)
-               return -1;
-
-       if (fscanf(fp, "0x%lx 0x%lx 0x%lx", &start, &end, &flags) == 0) {
-               printf("error reading resource file for bar size\n");
-               fclose(fp);
-               return -1;
-       }
+       unsigned long tmp;
+       int i = 0;
 
-       if (fclose(fp) == -1)
-               return -1;
+       tmp = dev->mem_resource[0].len;
 
-       tmp = (end - start) + 1;
-       i = 0;
        while (tmp >>= 1)
                i++;
+
        desc->barsz = i;
        return 0;
 }
 
 static int
-nfp6000_init(struct nfp_cpp *cpp, const char *devname)
+nfp6000_init(struct nfp_cpp *cpp, struct rte_pci_device *dev)
 {
-       char link[120];
-       char tmp_str[80];
-       ssize_t size;
        int ret = 0;
-       uint32_t model;
        struct nfp_pcie_user *desc;
 
        desc = malloc(sizeof(*desc));
@@ -848,71 +864,54 @@ nfp6000_init(struct nfp_cpp *cpp, const char *devname)
 
 
        memset(desc->busdev, 0, BUSDEV_SZ);
-       strlcpy(desc->busdev, devname, sizeof(desc->busdev));
-
-       ret = nfp_acquire_process_lock(desc);
-       if (ret)
-               return -1;
-
-       snprintf(tmp_str, sizeof(tmp_str), "%s/%s/driver", PCI_DEVICES,
-                desc->busdev);
-
-       size = readlink(tmp_str, link, sizeof(link));
+       strlcpy(desc->busdev, dev->device.name, sizeof(desc->busdev));
 
-       if (size == -1)
-               tmp_str[0] = '\0';
-
-       if (size == sizeof(link))
-               tmp_str[0] = '\0';
-
-       snprintf(tmp_str, sizeof(tmp_str), "%s/%s/resource0", PCI_DEVICES,
-                desc->busdev);
-
-       desc->device = open(tmp_str, O_RDWR);
-       if (desc->device == -1)
-               return -1;
+       if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
+           cpp->driver_lock_needed) {
+               ret = nfp_acquire_process_lock(desc);
+               if (ret)
+                       goto error;
+       }
 
-       if (nfp6000_set_model(desc, cpp) < 0)
-               return -1;
-       if (nfp6000_set_interface(desc, cpp) < 0)
-               return -1;
-       if (nfp6000_set_serial(desc, cpp) < 0)
-               return -1;
-       if (nfp6000_set_barsz(desc) < 0)
-               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)
+                       goto error;
+       }
 
-       desc->cfg = (char *)mmap(0, 1 << (desc->barsz - 3),
-                                PROT_READ | PROT_WRITE,
-                                MAP_SHARED, desc->device, 0);
+       if (nfp6000_set_model(dev, cpp) < 0)
+               goto error;
+       if (nfp6000_set_interface(dev, cpp) < 0)
+               goto error;
+       if (nfp6000_set_serial(dev, cpp) < 0)
+               goto error;
+       if (nfp6000_set_barsz(dev, desc) < 0)
+               goto error;
 
-       if (desc->cfg == MAP_FAILED)
-               return -1;
+       desc->cfg = (char *)dev->mem_resource[0].addr;
 
        nfp_enable_bars(desc);
 
        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
 nfp6000_free(struct nfp_cpp *cpp)
 {
        struct nfp_pcie_user *desc = nfp_cpp_priv(cpp);
-       int x;
 
-       /* Unmap may cause if there are any pending transaxctions */
        nfp_disable_bars(desc);
-       munmap(desc->cfg, 1 << (desc->barsz - 3));
-
-       for (x = ARRAY_SIZE(desc->bar); x > 0; x--) {
-               if (desc->bar[x - 1].iomem)
-                       munmap(desc->bar[x - 1].iomem, 1 << (desc->barsz - 3));
-       }
-       close(desc->lock);
+       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);
 }