pci: remove virtio-uio workaround
authorDavid Marchand <david.marchand@6wind.com>
Fri, 9 May 2014 13:15:55 +0000 (15:15 +0200)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Tue, 13 May 2014 11:20:35 +0000 (13:20 +0200)
virtio-uio does not need eal to map bars from uio device, so remove flag
RTE_PCI_DRV_NEED_IGB_UIO.
Then, move virtio-uio workaround out of generic eal_pci.c for linux
implementation.

Signed-off-by: David Marchand <david.marchand@6wind.com>
Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
lib/librte_eal/bsdapp/eal/eal_pci.c
lib/librte_eal/linuxapp/eal/eal_pci.c
lib/librte_pmd_virtio/virtio_ethdev.c

index 5d8bcbd..a8945e4 100644 (file)
@@ -221,8 +221,7 @@ pci_uio_map_resource(struct rte_pci_device *dev)
        dev->intr_handle.fd = -1;
 
        /* secondary processes - use already recorded details */
-       if ((rte_eal_process_type() != RTE_PROC_PRIMARY) &&
-               (dev->id.vendor_id != PCI_VENDOR_ID_QUMRANET))
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return (pci_uio_map_secondary(dev));
 
        rte_snprintf(devname, sizeof(devname), "/dev/uio@pci:%u:%u:%u",
@@ -234,12 +233,6 @@ pci_uio_map_resource(struct rte_pci_device *dev)
                return -1;
        }
 
-       if(dev->id.vendor_id == PCI_VENDOR_ID_QUMRANET) {
-               /* I/O port address already assigned */
-               /* rte_virtio_pmd does not need any other bar even if available */
-               return (0);
-       }
-       
        /* allocate the mapping details for secondary processes*/
        if ((uio_res = rte_zmalloc("UIO_RES", sizeof (*uio_res), 0)) == NULL) {
                RTE_LOG(ERR, EAL,
index 99e07d2..c006cf5 100644 (file)
@@ -584,11 +584,9 @@ pci_uio_map_resource(struct rte_pci_device *dev)
 {
        int i, j;
        char dirname[PATH_MAX];
-       char filename[PATH_MAX];
        char devname[PATH_MAX]; /* contains the /dev/uioX */
        void *mapaddr;
        int uio_num;
-       unsigned long start,size;
        uint64_t phaddr;
        uint64_t offset;
        uint64_t pagesz;
@@ -600,8 +598,7 @@ pci_uio_map_resource(struct rte_pci_device *dev)
        dev->intr_handle.fd = -1;
 
        /* secondary processes - use already recorded details */
-       if ((rte_eal_process_type() != RTE_PROC_PRIMARY) &&
-           (dev->id.vendor_id != PCI_VENDOR_ID_QUMRANET))
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return (pci_uio_map_secondary(dev));
 
        /* find uio resource */
@@ -612,31 +609,6 @@ pci_uio_map_resource(struct rte_pci_device *dev)
                return -1;
        }
 
-       if(dev->id.vendor_id == PCI_VENDOR_ID_QUMRANET) {
-               /* get portio size */
-               rte_snprintf(filename, sizeof(filename),
-                        "%s/portio/port0/size", dirname);
-               if (eal_parse_sysfs_value(filename, &size) < 0) {
-                       RTE_LOG(ERR, EAL, "%s(): cannot parse size\n",
-                               __func__);
-                       return -1;
-               }
-
-               /* get portio start */
-               rte_snprintf(filename, sizeof(filename),
-                        "%s/portio/port0/start", dirname);
-               if (eal_parse_sysfs_value(filename, &start) < 0) {
-                       RTE_LOG(ERR, EAL, "%s(): cannot parse portio start\n",
-                               __func__);
-                       return -1;
-               }
-               dev->mem_resource[0].addr = (void *)(uintptr_t)start;
-               dev->mem_resource[0].len =  (uint64_t)size;
-               RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%lx with size=0x%lx\n", start, size);
-               /* rte_virtio_pmd does not need any other bar even if available */
-               return (0);
-       }
-       
        /* allocate the mapping details for secondary processes*/
        if ((uio_res = rte_zmalloc("UIO_RES", sizeof (*uio_res), 0)) == NULL) {
                RTE_LOG(ERR, EAL,
index f107161..c6a1df5 100644 (file)
@@ -36,6 +36,9 @@
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
+#ifdef RTE_EXEC_ENV_LINUXAPP
+#include <dirent.h>
+#endif
 
 #include <rte_ethdev.h>
 #include <rte_memcpy.h>
@@ -392,6 +395,103 @@ virtio_negotiate_features(struct virtio_hw *hw)
        hw->guest_features = vtpci_negotiate_features(hw, guest_features);
 }
 
+#ifdef RTE_EXEC_ENV_LINUXAPP
+static int
+parse_sysfs_value(const char *filename, unsigned long *val)
+{
+       FILE *f;
+       char buf[BUFSIZ];
+       char *end = NULL;
+
+       if ((f = fopen(filename, "r")) == NULL) {
+               PMD_INIT_LOG(ERR, "%s(): cannot open sysfs value %s\n",
+                            __func__, filename);
+               return -1;
+       }
+
+       if (fgets(buf, sizeof(buf), f) == NULL) {
+               PMD_INIT_LOG(ERR, "%s(): cannot read sysfs value %s\n",
+                            __func__, filename);
+               fclose(f);
+               return -1;
+       }
+       *val = strtoul(buf, &end, 0);
+       if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
+               PMD_INIT_LOG(ERR, "%s(): cannot parse sysfs value %s\n",
+                            __func__, filename);
+               fclose(f);
+               return -1;
+       }
+       fclose(f);
+       return 0;
+}
+
+static int get_uio_dev(struct rte_pci_addr *loc, char *buf, unsigned int buflen)
+{
+       unsigned int uio_num;
+       struct dirent *e;
+       DIR *dir;
+       char dirname[PATH_MAX];
+
+       /* depending on kernel version, uio can be located in uio/uioX
+        * or uio:uioX */
+       rte_snprintf(dirname, sizeof(dirname),
+                SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/uio",
+                loc->domain, loc->bus, loc->devid, loc->function);
+       dir = opendir(dirname);
+       if (dir == NULL) {
+               /* retry with the parent directory */
+               rte_snprintf(dirname, sizeof(dirname),
+                        SYSFS_PCI_DEVICES "/" PCI_PRI_FMT,
+                        loc->domain, loc->bus, loc->devid, loc->function);
+               dir = opendir(dirname);
+
+               if (dir == NULL) {
+                       PMD_INIT_LOG(ERR, "Cannot opendir %s\n", dirname);
+                       return -1;
+               }
+       }
+
+       /* take the first file starting with "uio" */
+       while ((e = readdir(dir)) != NULL) {
+               /* format could be uio%d ...*/
+               int shortprefix_len = sizeof("uio") - 1;
+               /* ... or uio:uio%d */
+               int longprefix_len = sizeof("uio:uio") - 1;
+               char *endptr;
+
+               if (strncmp(e->d_name, "uio", 3) != 0)
+                       continue;
+
+               /* first try uio%d */
+               errno = 0;
+               uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
+               if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
+                       rte_snprintf(buf, buflen, "%s/uio%u", dirname, uio_num);
+                       break;
+               }
+
+               /* then try uio:uio%d */
+               errno = 0;
+               uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
+               if (errno == 0 && endptr != (e->d_name + longprefix_len)) {
+                       rte_snprintf(buf, buflen, "%s/uio:uio%u", dirname,
+                                    uio_num);
+                       break;
+               }
+       }
+       closedir(dir);
+
+       /* No uio resource found */
+       if (e == NULL) {
+               PMD_INIT_LOG(ERR, "Could not find uio resource\n");
+               return -1;
+       }
+
+       return 0;
+}
+#endif
+
 /*
  * This function is based on probe() function in virtio_pci.c
  * It returns 0 on success.
@@ -426,6 +526,38 @@ eth_virtio_dev_init(__rte_unused struct eth_driver *eth_drv,
 
        hw->device_id = pci_dev->id.device_id;
        hw->vendor_id = pci_dev->id.vendor_id;
+#ifdef RTE_EXEC_ENV_LINUXAPP
+       {
+               char dirname[PATH_MAX];
+               char filename[PATH_MAX];
+               unsigned long start,size;
+
+               if (get_uio_dev(&pci_dev->addr, dirname, sizeof(dirname)) < 0)
+                       return -1;
+
+               /* get portio size */
+               rte_snprintf(filename, sizeof(filename),
+                            "%s/portio/port0/size", dirname);
+               if (parse_sysfs_value(filename, &size) < 0) {
+                       PMD_INIT_LOG(ERR, "%s(): cannot parse size\n",
+                                    __func__);
+                       return -1;
+               }
+
+               /* get portio start */
+               rte_snprintf(filename, sizeof(filename),
+                            "%s/portio/port0/start", dirname);
+               if (parse_sysfs_value(filename, &start) < 0) {
+                       PMD_INIT_LOG(ERR, "%s(): cannot parse portio start\n",
+                                    __func__);
+                       return -1;
+               }
+               pci_dev->mem_resource[0].addr = (void *)(uintptr_t)start;
+               pci_dev->mem_resource[0].len =  (uint64_t)size;
+               PMD_INIT_LOG(DEBUG, "PCI Port IO found start=0x%lx with "
+                            "size=0x%lx\n", start, size);
+       }
+#endif
        hw->io_base = (uint32_t)(uintptr_t)pci_dev->mem_resource[0].addr;
 
        hw->max_rx_queues = VIRTIO_MAX_RX_QUEUES;
@@ -474,7 +606,6 @@ static struct eth_driver rte_virtio_pmd = {
        {
                .name = "rte_virtio_pmd",
                .id_table = pci_id_virtio_map,
-               .drv_flags = RTE_PCI_DRV_NEED_IGB_UIO,
        },
        .eth_dev_init = eth_virtio_dev_init,
        .dev_private_size = sizeof(struct virtio_adapter),