[dpdk-dev] [PATCH 3/7] pci: remove virtio-uio workaround

David Marchand david.marchand at 6wind.com
Mon Apr 28 15:19:43 CEST 2014


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 at 6wind.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c   |    9 +--
 lib/librte_eal/linuxapp/eal/eal_pci.c |   30 +-------
 lib/librte_pmd_virtio/virtio_ethdev.c |  133 ++++++++++++++++++++++++++++++++-
 3 files changed, 134 insertions(+), 38 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index b25c0a1..fbb281f 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -220,8 +220,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 at pci:%u:%u:%u",
@@ -233,12 +232,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,
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 313bab7..64c2130 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -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,
diff --git a/lib/librte_pmd_virtio/virtio_ethdev.c b/lib/librte_pmd_virtio/virtio_ethdev.c
index f107161..c6a1df5 100644
--- a/lib/librte_pmd_virtio/virtio_ethdev.c
+++ b/lib/librte_pmd_virtio/virtio_ethdev.c
@@ -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),
-- 
1.7.10.4



More information about the dev mailing list