DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 13/13] eal/pci: remove PCI probe and init calls
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

Now that PCI bus handles the scan/probe methods, independent calls to
PCI scan and probe can be removed from the code.
PCI device and driver list are also removed.

rte_device and rte_driver list continue to exist. As does the VDEV lists.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c             | 15 ---------
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  3 --
 lib/librte_eal/common/eal_common_pci.c          | 43 -------------------------
 lib/librte_eal/common/eal_private.h             | 10 ------
 lib/librte_eal/common/include/rte_pci.h         | 19 -----------
 lib/librte_eal/linuxapp/eal/eal_pci.c           | 16 ---------
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  3 --
 7 files changed, 109 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index ab04408..5344f9a 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -680,21 +680,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-	return 0;
-}
-
 struct rte_bus pci_bus = {
 	.scan = rte_eal_pci_scan,
 	.match = rte_eal_pci_match_default,
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 23fc1c1..0d2c8ec 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4093746..6d7b53e 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -83,11 +83,6 @@
 
 #include "eal_private.h"
 
-struct pci_driver_list pci_driver_list =
-	TAILQ_HEAD_INITIALIZER(pci_driver_list);
-struct pci_device_list pci_device_list =
-	TAILQ_HEAD_INITIALIZER(pci_device_list);
-
 #define SYSFS_PCI_DEVICES "/sys/bus/pci/devices"
 
 const char *pci_get_sysfs_path(void)
@@ -464,44 +459,6 @@ rte_eal_pci_detach(const struct rte_pci_addr *addr)
 	return -1;
 }
 
-/*
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
- */
-int
-rte_eal_pci_probe(void)
-{
-	struct rte_pci_device *dev = NULL;
-	struct rte_devargs *devargs;
-	int probe_all = 0;
-	int ret = 0;
-
-	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) == 0)
-		probe_all = 1;
-
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
-
-		/* set devargs in PCI structure */
-		devargs = pci_devargs_lookup(dev);
-		if (devargs != NULL)
-			dev->device.devargs = devargs;
-
-		/* probe all or only whitelisted devices */
-		if (probe_all)
-			ret = pci_probe_all_drivers(NULL, dev);
-		else if (devargs != NULL &&
-			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(NULL, dev);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
-				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
-				 dev->addr.devid, dev->addr.function);
-	}
-
-	return 0;
-}
-
 int
 rte_eal_pci_probe_default(struct rte_driver *driver, struct rte_device *device)
 {
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index e006d95..06ec172 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -108,16 +108,6 @@ int rte_eal_timer_init(void);
  */
 int rte_eal_log_init(const char *id, int facility);
 
-/**
- * Init the PCI infrastructure
- *
- * This function is private to EAL.
- *
- * @return
- *   0 on success, negative on error
- */
-int rte_eal_pci_init(void);
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index c0a0c6a..95e6656 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -86,12 +86,6 @@ extern "C" {
 #include <rte_interrupts.h>
 #include <rte_dev.h>
 
-TAILQ_HEAD(pci_device_list, rte_pci_device); /**< PCI devices in D-linked Q. */
-TAILQ_HEAD(pci_driver_list, rte_pci_driver); /**< PCI drivers in D-linked Q. */
-
-extern struct pci_driver_list pci_driver_list; /**< Global list of PCI drivers. */
-extern struct pci_device_list pci_device_list; /**< Global list of PCI devices. */
-
 /** Pathname of PCI devices directory. */
 const char *pci_get_sysfs_path(void);
 
@@ -390,19 +384,6 @@ rte_eal_pci_match_default(struct rte_driver *drv,
 			  struct rte_device *dev);
 
 /**
- * Probe the PCI bus for registered drivers.
- *
- * Scan the content of the PCI bus, and call the probe() function for
- * all registered drivers that have a matching entry in its id_table
- * for discovered devices.
- *
- * @return
- *   - 0 on success.
- *   - Negative on error.
- */
-int rte_eal_pci_probe(void);
-
-/**
  * Map the PCI device resources in user space virtual memory address
  *
  * Note that driver should not call this function when flag
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index de4ed86..a79b47c 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -765,22 +765,6 @@ rte_eal_pci_ioport_unmap(struct rte_pci_ioport *p)
 	return ret;
 }
 
-/* Init the PCI EAL subsystem */
-int
-rte_eal_pci_init(void)
-{
-	/* for debug purposes, PCI can be disabled */
-	if (internal_config.no_pci)
-		return 0;
-
-	if (rte_eal_pci_scan(NULL) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
-		return -1;
-	}
-
-	return 0;
-}
-
 struct rte_bus pci_bus = {
 	.scan = rte_eal_pci_scan,
 	.match = rte_eal_pci_match_default,
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index c873a7f..48e847c 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -6,8 +6,6 @@ DPDK_2.0 {
 	eal_parse_sysfs_value;
 	eal_timer_source;
 	lcore_config;
-	pci_device_list;
-	pci_driver_list;
 	per_lcore__lcore_id;
 	per_lcore__rte_errno;
 	rte_calloc;
@@ -41,7 +39,6 @@ DPDK_2.0 {
 	rte_eal_mp_wait_lcore;
 	rte_eal_parse_devargs_str;
 	rte_eal_pci_dump;
-	rte_eal_pci_probe;
 	rte_eal_pci_probe_one;
 	rte_eal_pci_register;
 	rte_eal_pci_scan;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 12/13] eal: enable PCI bus
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

Register a PCI bus with Scan/match and probe callbacks. Necessary changes
in EAL layer for enabling bus interfaces. PCI devices and drivers now
reside within the Bus object.

Removing PCI init and probe from rte_eal_init now that bus performs these
functions.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |   7 --
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  42 +++++++---
 lib/librte_eal/common/eal_common_bus.c  |   5 +-
 lib/librte_eal/common/eal_common_pci.c  | 137 ++++++++++++++++++++++++++------
 lib/librte_eal/common/eal_private.h     |   4 +-
 lib/librte_eal/common/include/rte_bus.h |   5 ++
 lib/librte_eal/common/include/rte_pci.h |   3 +
 lib/librte_eal/linuxapp/eal/eal.c       |   7 --
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  43 +++++++---
 9 files changed, 189 insertions(+), 64 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 30afc6b..79d82d4 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -562,9 +562,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_timer_init() < 0)
 		rte_panic("Cannot init HPET or TSC timers\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 	eal_check_mem_on_local_socket();
 
 	if (eal_plugins_init() < 0)
@@ -616,10 +613,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	if (rte_eal_bus_probe())
 		rte_panic("Cannot probe devices\n");
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 10b234e..ab04408 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -58,6 +58,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_common.h>
 #include <rte_launch.h>
@@ -249,7 +250,7 @@ pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
 }
 
 static int
-pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
+pci_scan_one(struct rte_bus *bus, int dev_pci_fd, struct pci_conf *conf)
 {
 	struct rte_pci_device *dev;
 	struct pci_bar_io bar;
@@ -322,19 +323,23 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 	}
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+	if (TAILQ_EMPTY(&bus->device_list)) {
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 	else {
 		struct rte_pci_device *dev2 = NULL;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+					    device);
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 			else if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
+				rte_eal_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				return 0;
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -346,7 +351,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
 				return 0;
 			}
 		}
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
@@ -361,7 +366,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -374,6 +379,10 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 			.matches = &matches[0],
 	};
 
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -389,7 +398,7 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 		}
 
 		for (i = 0; i < conf_io.num_matches; i++)
-			if (pci_scan_one(fd, &matches[i]) < 0)
+			if (pci_scan_one(bus, fd, &matches[i]) < 0)
 				goto error;
 
 		dev_count += conf_io.num_matches;
@@ -407,9 +416,9 @@ rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
-	int fd;
+	int fd = -1;
 	struct pci_conf matches[2];
 	struct pci_match_conf match = {
 		.pc_sel = {
@@ -427,6 +436,9 @@ pci_update_device(const struct rte_pci_addr *addr)
 		.matches = &matches[0],
 	};
 
+	if (!bus)
+		goto error;
+
 	fd = open("/dev/pci", O_RDONLY);
 	if (fd < 0) {
 		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
@@ -442,7 +454,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 	if (conf_io.num_matches != 1)
 		goto error;
 
-	if (pci_scan_one(fd, &matches[0]) < 0)
+	if (pci_scan_one(bus, fd, &matches[0]) < 0)
 		goto error;
 
 	close(fd);
@@ -682,3 +694,11 @@ rte_eal_pci_init(void)
 	}
 	return 0;
 }
+
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match_default,
+	.probe = rte_eal_pci_probe_default,
+};
+
+RTE_REGISTER_BUS(pci, pci_bus);
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 469abac..52bf051 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -196,7 +196,7 @@ rte_eal_bus_scan(void)
 }
 
 static int
-perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+perform_probe(struct rte_bus *bus, struct rte_driver *driver,
 	      struct rte_device *device)
 {
 	int ret;
@@ -208,7 +208,7 @@ perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
 		return 0;
 	}
 
-	ret = driver->probe(driver, device);
+	ret = bus->probe(driver, device);
 	if (ret < 0)
 		/* One of the probes failed */
 		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
@@ -234,6 +234,7 @@ rte_eal_bus_probe(void)
 			TAILQ_FOREACH(driver, &bus->driver_list, next) {
 				ret = bus->match(driver, device);
 				if (!ret) {
+					device->driver = driver;
 					ret = perform_probe(bus, driver,
 							    device);
 					if (ret < 0)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index ba84ccb..4093746 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -71,6 +71,7 @@
 
 #include <rte_interrupts.h>
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_per_lcore.h>
 #include <rte_memory.h>
@@ -230,15 +231,6 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 		return 1;
 	}
 
-	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match_default(driver, device);
-	if (ret) {
-		/* Match of device and driver failed */
-		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
-			driver->name);
-		return 1;
-	}
-
 	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
 			dev->id.device_id, dr->driver.name);
 
@@ -322,19 +314,24 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_probe_all_drivers(struct rte_pci_device *dev)
+pci_probe_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
+	if (!bus)
+		return -1;
+
 	/* Check if a driver is already loaded */
 	if (dev->driver != NULL)
 		return 0;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_probe_one_driver(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -353,15 +350,20 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * failed, return 1 if no driver is found for this device.
  */
 static int
-pci_detach_all_drivers(struct rte_pci_device *dev)
+pci_detach_all_drivers(struct rte_bus *bus, struct rte_pci_device *dev)
 {
 	struct rte_pci_driver *dr = NULL;
+	struct rte_driver *r_dr = NULL;
 	int rc = 0;
 
 	if (dev == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dr, &pci_driver_list, next) {
+	if (!bus)
+		return -1;
+
+	TAILQ_FOREACH(r_dr, &bus->driver_list, next) {
+		dr = container_of(r_dr, struct rte_pci_driver, driver);
 		rc = rte_eal_pci_detach_dev(dr, dev);
 		if (rc < 0)
 			/* negative value is an error */
@@ -382,22 +384,31 @@ int
 rte_eal_pci_probe_one(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return -1;
+	}
+
 	/* update current pci device in global list, kernel bindings might have
 	 * changed since last time we looked at it.
 	 */
-	if (pci_update_device(addr) < 0)
+	if (pci_update_device(bus, addr) < 0)
 		goto err_return;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_probe_all_drivers(dev);
+		ret = pci_probe_all_drivers(bus, dev);
 		if (ret)
 			goto err_return;
 		return 0;
@@ -418,20 +429,29 @@ int
 rte_eal_pci_detach(const struct rte_pci_addr *addr)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 	int ret = 0;
 
 	if (addr == NULL)
 		return -1;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		if (rte_eal_compare_pci_addr(&dev->addr, addr))
 			continue;
 
-		ret = pci_detach_all_drivers(dev);
+		ret = pci_detach_all_drivers(bus, dev);
 		if (ret < 0)
 			goto err_return;
 
-		TAILQ_REMOVE(&pci_device_list, dev, next);
+		rte_eal_bus_remove_device(r_dev);
 		free(dev);
 		return 0;
 	}
@@ -469,10 +489,10 @@ rte_eal_pci_probe(void)
 
 		/* probe all or only whitelisted devices */
 		if (probe_all)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(NULL, dev);
 		else if (devargs != NULL &&
 			devargs->type == RTE_DEVTYPE_WHITELISTED_PCI)
-			ret = pci_probe_all_drivers(dev);
+			ret = pci_probe_all_drivers(NULL, dev);
 		if (ret < 0)
 			rte_exit(EXIT_FAILURE, "Requested device " PCI_PRI_FMT
 				 " cannot be used\n", dev->addr.domain, dev->addr.bus,
@@ -482,6 +502,44 @@ rte_eal_pci_probe(void)
 	return 0;
 }
 
+int
+rte_eal_pci_probe_default(struct rte_driver *driver, struct rte_device *device)
+{
+	int ret = 0;
+	struct rte_devargs *devargs;
+	struct rte_pci_device *pci_dev;
+	struct rte_pci_driver *pci_drv;
+
+	if (!driver || !device)
+		return -1;
+
+	pci_dev = container_of(device, struct rte_pci_device, device);
+	pci_drv = container_of(driver, struct rte_pci_driver, driver);
+
+	ret = rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI);
+	if (ret != 0) {
+		/* set devargs in PCI structure */
+		devargs = pci_devargs_lookup(pci_dev);
+		if (devargs != NULL &&
+		    devargs->type == RTE_DEVTYPE_WHITELISTED_PCI) {
+			pci_dev->device.devargs = devargs;
+		} else {
+			/* Ignore the device */
+			return 0;
+		}
+	}
+
+	ret = rte_eal_pci_probe_one_driver(pci_drv, pci_dev);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL, "Requested device " PCI_PRI_FMT
+			" cannot be used\n", pci_dev->addr.domain,
+			pci_dev->addr.bus, pci_dev->addr.devid,
+			pci_dev->addr.function);
+		return ret;
+	}
+	return 0;
+}
+
 /* dump one device */
 static int
 pci_dump_one_device(FILE *f, struct rte_pci_device *dev)
@@ -507,8 +565,17 @@ void
 rte_eal_pci_dump(FILE *f)
 {
 	struct rte_pci_device *dev = NULL;
+	struct rte_device *r_dev = NULL;
+	struct rte_bus *bus;
 
-	TAILQ_FOREACH(dev, &pci_device_list, next) {
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	TAILQ_FOREACH(r_dev, &bus->device_list, next) {
+		dev = container_of(r_dev, struct rte_pci_device, device);
 		pci_dump_one_device(f, dev);
 	}
 }
@@ -517,14 +584,32 @@ rte_eal_pci_dump(FILE *f)
 void
 rte_eal_pci_register(struct rte_pci_driver *driver)
 {
-	TAILQ_INSERT_TAIL(&pci_driver_list, driver, next);
-	rte_eal_driver_register(&driver->driver);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = rte_eal_get_bus("pci");
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_add_driver(bus, &driver->driver);
 }
 
 /* unregister a driver */
 void
 rte_eal_pci_unregister(struct rte_pci_driver *driver)
 {
-	rte_eal_driver_unregister(&driver->driver);
-	TAILQ_REMOVE(&pci_driver_list, driver, next);
+	struct rte_bus *bus;
+
+	RTE_VERIFY(driver);
+
+	bus = driver->driver.bus;
+	if (!bus) {
+		RTE_LOG(ERR, EAL, "PCI Bus not registered\n");
+		return;
+	}
+
+	rte_eal_bus_remove_driver(&driver->driver);
 }
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 9e7d8f6..e006d95 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -126,13 +126,15 @@ struct rte_pci_device;
  *
  * This function is private to EAL.
  *
+ * @param bus
+ *	The PCI bus on which device is connected
  * @param addr
  *	The PCI Bus-Device-Function address to look for
  * @return
  *   - 0 on success.
  *   - negative on error.
  */
-int pci_update_device(const struct rte_pci_addr *addr);
+int pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr);
 
 /**
  * Unbind kernel driver for this device
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 9bd8650..e8db5b4 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -102,6 +102,10 @@ typedef int (*bus_scan_t)(struct rte_bus *bus);
  */
 typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
 
+/** TODO
+ */
+typedef int (*bus_probe_t)(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	struct rte_driver_list driver_list;
@@ -112,6 +116,7 @@ struct rte_bus {
 	bus_scan_t scan;            /**< Scan for devices attached to bus */
 	bus_match_t match;
 	/**< Match device with drivers associated with the bus */
+	bus_probe_t probe;           /**< TODO */
 };
 
 /** @internal
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 2a5f766..c0a0c6a 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -371,6 +371,9 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  */
 int rte_eal_pci_scan(struct rte_bus *bus);
 
+int
+rte_eal_pci_probe_default(struct rte_driver *driver, struct rte_device *device);
+
 /**
  * Match the PCI Driver and Device using the ID Table
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 01d0cee..ff92de2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -803,9 +803,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
-	if (rte_eal_pci_init() < 0)
-		rte_panic("Cannot init PCI\n");
-
 #ifdef VFIO_PRESENT
 	if (rte_eal_vfio_setup() < 0)
 		rte_panic("Cannot init VFIO\n");
@@ -887,10 +884,6 @@ rte_eal_init(int argc, char **argv)
 	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
 	rte_eal_mp_wait_lcore();
 
-	/* Probe & Initialize PCI devices */
-	if (rte_eal_pci_probe())
-		rte_panic("Cannot probe PCI\n");
-
 	if (rte_eal_bus_probe())
 		rte_panic("Cannot probe devices\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index cbd25df..de4ed86 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -35,6 +35,7 @@
 #include <dirent.h>
 
 #include <rte_log.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_eal_memconfig.h>
 #include <rte_malloc.h>
@@ -267,7 +268,8 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
+pci_scan_one(struct rte_bus *bus, const char *dirname,
+	     const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -385,20 +387,24 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 		dev->kdrv = RTE_KDRV_NONE;
 
 	/* device is valid, add in list (sorted) */
-	if (TAILQ_EMPTY(&pci_device_list)) {
+	if (TAILQ_EMPTY(&bus->device_list)) {
 		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	} else {
 		struct rte_pci_device *dev2;
+		struct rte_device *r_dev2;
 		int ret;
 
-		TAILQ_FOREACH(dev2, &pci_device_list, next) {
+		TAILQ_FOREACH(r_dev2, &bus->device_list, next) {
+			dev2 = container_of(r_dev2, struct rte_pci_device,
+						device);
 			ret = rte_eal_compare_pci_addr(&dev->addr, &dev2->addr);
 			if (ret > 0)
 				continue;
 
 			if (ret < 0) {
-				TAILQ_INSERT_BEFORE(dev2, dev, next);
+				rte_eal_bus_insert_device(bus, &dev2->device,
+							  &dev->device);
 				rte_eal_device_insert(&dev->device);
 			} else { /* already registered */
 				dev2->kdrv = dev->kdrv;
@@ -410,14 +416,14 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 			return 0;
 		}
 		rte_eal_device_insert(&dev->device);
-		TAILQ_INSERT_TAIL(&pci_device_list, dev, next);
+		rte_eal_bus_add_device(bus, &dev->device);
 	}
 
 	return 0;
 }
 
 int
-pci_update_device(const struct rte_pci_addr *addr)
+pci_update_device(struct rte_bus *bus, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 
@@ -425,7 +431,7 @@ pci_update_device(const struct rte_pci_addr *addr)
 		 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
 		 addr->function);
 
-	return pci_scan_one(filename, addr);
+	return pci_scan_one(bus, filename, addr);
 }
 
 /*
@@ -479,13 +485,22 @@ parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
  * list
  */
 int
-rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
+rte_eal_pci_scan(struct rte_bus *bus_p)
 {
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
 	struct rte_pci_addr addr;
 
+	if (!bus_p) {
+		RTE_LOG(ERR, EAL, "PCI Bus is not registered\n");
+		return -1;
+	}
+
+	/* for debug purposes, PCI can be disabled */
+	if (internal_config.no_pci)
+		return 0;
+
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
 		RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n",
@@ -504,7 +519,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, &addr) < 0)
+		if (pci_scan_one(bus_p, dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
@@ -765,3 +780,11 @@ rte_eal_pci_init(void)
 
 	return 0;
 }
+
+struct rte_bus pci_bus = {
+	.scan = rte_eal_pci_scan,
+	.match = rte_eal_pci_match_default,
+	.probe = rte_eal_pci_probe_default,
+};
+
+RTE_REGISTER_BUS(pci, pci_bus);
-- 
2.7.4

^ permalink raw reply related

* [PATCH 11/13] pci: Pass rte_pci_addr to functions instead of separate args
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Ben Walker, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

From: Ben Walker <benjamin.walker@intel.com>

Instead of passing domain, bus, devid, func, just pass
an rte_pci_addr.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
[Shreyansh: Checkpatch error fix]
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/linuxapp/eal/eal_pci.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index bafb7fb..cbd25df 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -267,8 +267,7 @@ pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 
 /* Scan one pci sysfs entry, and fill the devices list from it. */
 static int
-pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
-	     uint8_t devid, uint8_t function)
+pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 {
 	char filename[PATH_MAX];
 	unsigned long tmp;
@@ -281,10 +280,7 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus,
 		return -1;
 
 	memset(dev, 0, sizeof(*dev));
-	dev->addr.domain = domain;
-	dev->addr.bus = bus;
-	dev->addr.devid = devid;
-	dev->addr.function = function;
+	dev->addr = *addr;
 
 	/* get vendor id */
 	snprintf(filename, sizeof(filename), "%s/vendor", dirname);
@@ -429,16 +425,14 @@ pci_update_device(const struct rte_pci_addr *addr)
 		 pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
 		 addr->function);
 
-	return pci_scan_one(filename, addr->domain, addr->bus, addr->devid,
-				addr->function);
+	return pci_scan_one(filename, addr);
 }
 
 /*
  * split up a pci address into its constituent parts.
  */
 static int
-parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
-		uint8_t *bus, uint8_t *devid, uint8_t *function)
+parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr)
 {
 	/* first split on ':' */
 	union splitaddr {
@@ -466,10 +460,10 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
 
 	/* now convert to int values */
 	errno = 0;
-	*domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
-	*bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
-	*devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
-	*function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
+	addr->domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
+	addr->bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
+	addr->devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
+	addr->function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
 	if (errno != 0)
 		goto error;
 
@@ -490,8 +484,7 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 	struct dirent *e;
 	DIR *dir;
 	char dirname[PATH_MAX];
-	uint16_t domain;
-	uint8_t bus, devid, function;
+	struct rte_pci_addr addr;
 
 	dir = opendir(pci_get_sysfs_path());
 	if (dir == NULL) {
@@ -500,20 +493,22 @@ rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 		return -1;
 	}
 
+
 	while ((e = readdir(dir)) != NULL) {
 		if (e->d_name[0] == '.')
 			continue;
 
-		if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
-				&bus, &devid, &function) != 0)
+		if (parse_pci_addr_format(e->d_name,
+					  sizeof(e->d_name), &addr) != 0)
 			continue;
 
 		snprintf(dirname, sizeof(dirname), "%s/%s",
 				pci_get_sysfs_path(), e->d_name);
-		if (pci_scan_one(dirname, domain, bus, devid, function) < 0)
+		if (pci_scan_one(dirname, &addr) < 0)
 			goto error;
 	}
 	closedir(dir);
+
 	return 0;
 
 error:
-- 
2.7.4

^ permalink raw reply related

* [PATCH 10/13] eal/pci: generalize args of PCI scan/match towards RTE device/driver
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

PCI scan and match now work on rte_device/rte_driver rather than PCI
specific objects. These functions can now be plugged to the generic
bus callbacks for scanning and matching devices/drivers.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_pci.c                     |  2 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c     |  4 ++--
 lib/librte_eal/common/eal_common_pci.c  | 17 +++++++++++------
 lib/librte_eal/common/include/rte_pci.h | 17 ++++++++++-------
 lib/librte_eal/linuxapp/eal/eal_pci.c   |  4 ++--
 5 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/app/test/test_pci.c b/app/test/test_pci.c
index cda186d..f9b84db 100644
--- a/app/test/test_pci.c
+++ b/app/test/test_pci.c
@@ -180,7 +180,7 @@ test_pci_setup(void)
 		TAILQ_INSERT_TAIL(&real_pci_device_list, dev, next);
 	}
 
-	ret = rte_eal_pci_scan();
+	ret = rte_eal_pci_scan(NULL);
 	TEST_ASSERT_SUCCESS(ret, "failed to scan PCI bus");
 	rte_eal_pci_dump(stdout);
 
diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index 8b3ed88..10b234e 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -361,7 +361,7 @@ pci_scan_one(int dev_pci_fd, struct pci_conf *conf)
  * list. Call pci_scan_one() for each pci entry found.
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus __rte_unused)
 {
 	int fd;
 	unsigned dev_count = 0;
@@ -676,7 +676,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 793ac59..ba84ccb 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -153,17 +153,22 @@ pci_unmap_resource(void *requested_addr, size_t size)
 }
 
 int
-rte_eal_pci_match_default(struct rte_pci_driver *pci_drv,
-			  struct rte_pci_device *pci_dev)
+rte_eal_pci_match_default(struct rte_driver *drv,
+			  struct rte_device *dev)
 {
 	int match = 0;
 	const struct rte_pci_id *id_table;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 
-	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
-		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+	if (!drv || !dev) {
+		RTE_LOG(DEBUG, EAL, "Invalid Device/Driver\n");
 		return -1;
 	}
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
 	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
@@ -226,7 +231,7 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
 	}
 
 	/* The device is not blacklisted; Check if driver supports it */
-	ret = rte_eal_pci_match_default(dr, dev);
+	ret = rte_eal_pci_match_default(driver, device);
 	if (ret) {
 		/* Match of device and driver failed */
 		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
@@ -282,7 +287,7 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 	driver = &(dr->driver);
 	device = &(dev->device);
 
-	ret = rte_eal_pci_match_default(dr, dev);
+	ret = rte_eal_pci_match_default(driver, device);
 	if (ret) {
 		/* Device and driver don't match */
 		return 1;
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index eb9ef7d..2a5f766 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -363,25 +363,28 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
  * Scan the content of the PCI bus, and the devices in the devices
  * list
  *
+ * @param bus
+ *	Reference to the PCI bus
+ *
  * @return
  *  0 on success, negative on error
  */
-int rte_eal_pci_scan(void);
+int rte_eal_pci_scan(struct rte_bus *bus);
 
 /**
  * Match the PCI Driver and Device using the ID Table
  *
- * @param pci_drv
- *	PCI driver from which ID table would be extracted
- * @param pci_dev
- *	PCI device to match against the driver
+ * @param drv
+ *	driver from which ID table would be extracted
+ * @param dev
+ *	device to match against the driver
  * @return
  *	0 for successful match
  *	!0 for unsuccessful match
  */
 int
-rte_eal_pci_match_default(struct rte_pci_driver *pci_drv,
-			  struct rte_pci_device *pci_dev);
+rte_eal_pci_match_default(struct rte_driver *drv,
+			  struct rte_device *dev);
 
 /**
  * Probe the PCI bus for registered drivers.
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index 876ba38..bafb7fb 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -485,7 +485,7 @@ parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
  * list
  */
 int
-rte_eal_pci_scan(void)
+rte_eal_pci_scan(struct rte_bus *bus_p __rte_unused)
 {
 	struct dirent *e;
 	DIR *dir;
@@ -763,7 +763,7 @@ rte_eal_pci_init(void)
 	if (internal_config.no_pci)
 		return 0;
 
-	if (rte_eal_pci_scan() < 0) {
+	if (rte_eal_pci_scan(NULL) < 0) {
 		RTE_LOG(ERR, EAL, "%s(): Cannot scan PCI bus\n", __func__);
 		return -1;
 	}
-- 
2.7.4

^ permalink raw reply related

* [PATCH 08/13] eal: enable probe and remove from bus infrastructure
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

The model is:
 rte_eal_init
 `--> calls rte_eal_bus_probe()
      This iterates over all the drivers and devices and matches them. For
      matched bus specific device-driver:
      `--> bus->probe()
           This would be responsible for generic work, equivalent to
           rte_eal_pci_probe - specific to the bus. Handles over control
           to,
           `--> rte_driver->probe()
                which works equivalent to rte_eth_dev_pci_probe for alloc-
                -ating a ethernet device. This would hand over the control
                to,
                `--> rte_xxx_driver->probe()
                     Calls driver specific initialization of the eth_dev
                     Similar to what eth_dev_init of eth_driver does.
                     In further changes, eth_driver would be removed.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c | 50 +++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 67b808b..469abac 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -195,11 +195,59 @@ rte_eal_bus_scan(void)
 	return 0;
 }
 
+static int
+perform_probe(struct rte_bus *bus __rte_unused, struct rte_driver *driver,
+	      struct rte_device *device)
+{
+	int ret;
+
+	if (!driver->probe) {
+		RTE_LOG(ERR, EAL, "Driver (%s) doesn't support probe.\n",
+			driver->name);
+		/* This is not an error - just a badly implemented PMD */
+		return 0;
+	}
+
+	ret = driver->probe(driver, device);
+	if (ret < 0)
+		/* One of the probes failed */
+		RTE_LOG(ERR, EAL, "Probe failed for (%s).\n", driver->name);
+
+	/* In either case, ret <0 (error), ret > 0 (not supported) and ret = 0
+	 * success, return ret
+	 */
+	return ret;
+}
+
 /* Match driver<->device and call driver->probe() */
 int
 rte_eal_bus_probe(void)
 {
-	/* Until driver->probe is available, this is dummy implementation */
+	int ret;
+	struct rte_bus *bus;
+	struct rte_device *device;
+	struct rte_driver *driver;
+
+	/* For each bus registered with EAL */
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		TAILQ_FOREACH(device, &bus->device_list, next) {
+			TAILQ_FOREACH(driver, &bus->driver_list, next) {
+				ret = bus->match(driver, device);
+				if (!ret) {
+					ret = perform_probe(bus, driver,
+							    device);
+					if (ret < 0)
+						return ret;
+
+					/* ret == 0 is success; ret >0 implies
+					 * driver doesn't support the device.
+					 * in either case, continue
+					 */
+				}
+			}
+		}
+	}
+
 	return 0;
 }
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 09/13] pci: split match and probe function
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

Matching of PCI device address and driver ID table is being done at two
discreet locations duplicating the code. (rte_eal_pci_probe_one_driver
and rte_eal_pci_detach_dev).

Splitting the matching function into rte_eal_pci_match_default.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_pci.c  | 210 ++++++++++++++++++--------------
 lib/librte_eal/common/include/rte_pci.h |  15 +++
 2 files changed, 133 insertions(+), 92 deletions(-)

diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 3082b1a..793ac59 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -152,80 +152,115 @@ pci_unmap_resource(void *requested_addr, size_t size)
 				requested_addr);
 }
 
-/*
- * If vendor/device ID match, call the probe() function of the
- * driver.
- */
-static int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+int
+rte_eal_pci_match_default(struct rte_pci_driver *pci_drv,
+			  struct rte_pci_device *pci_dev)
 {
-	int ret;
+	int match = 0;
 	const struct rte_pci_id *id_table;
-	struct rte_driver *driver;
-	struct rte_device *device;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	if (!pci_drv || !pci_dev || !pci_drv->id_table) {
+		RTE_LOG(DEBUG, EAL, "Invalid PCI Driver object\n");
+		return -1;
+	}
 
+	for (id_table = pci_drv->id_table; id_table->vendor_id != 0;
+	     id_table++) {
 		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
+		if (id_table->vendor_id != pci_dev->id.vendor_id &&
 				id_table->vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->device_id != dev->id.device_id &&
+		if (id_table->device_id != pci_dev->id.device_id &&
 				id_table->device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
+		if (id_table->subsystem_vendor_id !=
+		    pci_dev->id.subsystem_vendor_id &&
+		    id_table->subsystem_vendor_id != PCI_ANY_ID)
 			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
+		if (id_table->subsystem_device_id !=
+		    pci_dev->id.subsystem_device_id &&
+		    id_table->subsystem_device_id != PCI_ANY_ID)
 			continue;
-		if (id_table->class_id != dev->id.class_id &&
+		if (id_table->class_id != pci_dev->id.class_id &&
 				id_table->class_id != RTE_CLASS_ANY_ID)
 			continue;
 
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->device.numa_node);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->device.devargs != NULL &&
-			dev->device.devargs->type ==
-				RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(INFO, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = rte_eal_pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-				rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-		driver = &dr->driver;
-		device = &dev->device;
-
-		/* call the driver probe() function */
-		ret = driver->probe(driver, device);
-		if (ret)
-			dev->driver = NULL;
+		match = 1;
+		break;
+	}
+
+	return !match;
+}
+
+/*
+ * If vendor/device ID match, call the probe() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
+			     struct rte_pci_device *dev)
+{
+	int ret;
+	struct rte_driver *driver;
+	struct rte_device *device;
+	struct rte_pci_addr *loc;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
 
-		return ret;
+	driver = &dr->driver;
+	device = &dev->device;
+	loc = &dev->addr;
+
+	RTE_LOG(INFO, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid, loc->function,
+			dev->device.numa_node);
+
+	/* no initialization when blacklisted, return without error */
+	if (dev->device.devargs != NULL &&
+		dev->device.devargs->type ==
+			RTE_DEVTYPE_BLACKLISTED_PCI) {
+		RTE_LOG(INFO, EAL, "  Device is blacklisted, not"
+			" initializing\n");
+		return 1;
 	}
-	/* return positive value if driver doesn't support this device */
-	return 1;
+
+	/* The device is not blacklisted; Check if driver supports it */
+	ret = rte_eal_pci_match_default(dr, dev);
+	if (ret) {
+		/* Match of device and driver failed */
+		RTE_LOG(DEBUG, EAL, "Driver (%s) doesn't match the device\n",
+			driver->name);
+		return 1;
+	}
+
+	RTE_LOG(INFO, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
+
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+		/* map resources for devices that use igb_uio */
+		ret = rte_eal_pci_map_device(dev);
+		if (ret != 0)
+			return ret;
+	} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
+			rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* unbind current driver */
+		if (pci_unbind_kernel_driver(dev) < 0)
+			return -1;
+	}
+
+	/* reference driver structure */
+	dev->driver = dr;
+
+	/* call the driver probe() function */
+	ret = driver->probe(driver, device);
+	if (ret) {
+		RTE_LOG(DEBUG, EAL, "Driver (%s) probe failed.\n",
+			driver->name);
+		dev->driver = NULL;
+	}
+
+	return ret;
 }
 
 /*
@@ -236,53 +271,44 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
+	int ret;
 	struct rte_driver *driver = NULL;
-	const struct rte_pci_id *id_table;
+	struct rte_device *device;
+	struct rte_pci_addr *loc;
 
 	if ((dr == NULL) || (dev == NULL))
 		return -EINVAL;
 
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+	driver = &(dr->driver);
+	device = &(dev->device);
 
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
+	ret = rte_eal_pci_match_default(dr, dev);
+	if (ret) {
+		/* Device and driver don't match */
+		return 1;
+	}
 
-		struct rte_pci_addr *loc = &dev->addr;
+	loc = &dev->addr;
 
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->device.numa_node);
+	RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+			loc->domain, loc->bus, loc->devid,
+			loc->function, dev->device.numa_node);
 
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->driver.name);
+	RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+			dev->id.device_id, dr->driver.name);
 
-		driver = &(dr->driver);
-		if (driver->remove && (driver->remove(&(dev->device)) < 0))
-			return -1;	/* negative value is an error */
+	driver = &(dr->driver);
+	if (driver->remove && (driver->remove(device) < 0))
+		return -1;	/* negative value is an error */
 
-		/* clear driver structure */
-		dev->driver = NULL;
+	/* clear driver structure */
+	dev->driver = NULL;
 
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
-			rte_eal_pci_unmap_device(dev);
+	if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+		/* unmap resources for devices that use igb_uio */
+		rte_eal_pci_unmap_device(dev);
 
-		return 0;
-	}
-
-	/* return positive value if driver doesn't support this device */
-	return 1;
+	return 0;
 }
 
 /*
diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h
index 9ce8847..eb9ef7d 100644
--- a/lib/librte_eal/common/include/rte_pci.h
+++ b/lib/librte_eal/common/include/rte_pci.h
@@ -369,6 +369,21 @@ rte_eal_compare_pci_addr(const struct rte_pci_addr *addr,
 int rte_eal_pci_scan(void);
 
 /**
+ * Match the PCI Driver and Device using the ID Table
+ *
+ * @param pci_drv
+ *	PCI driver from which ID table would be extracted
+ * @param pci_dev
+ *	PCI device to match against the driver
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+int
+rte_eal_pci_match_default(struct rte_pci_driver *pci_drv,
+			  struct rte_pci_device *pci_dev);
+
+/**
  * Probe the PCI bus for registered drivers.
  *
  * Scan the content of the PCI bus, and call the probe() function for
-- 
2.7.4

^ permalink raw reply related

* [PATCH 07/13] pci: replace probe and remove handlers with rte_driver
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

rte_pci_driver probe/remove callback are replaced with the rte_driver
based probe/remove. This patch changes all the PCI drivers which reference
rte_pci_driver->probe/remove.

rte_pci_driver continues to have probe/remove callback which would be used
once eth_driver is removed in later patches.

Only changes to PCI are done. VDEV changes require a different
model because of arguments being passed to vdev->probe/remove.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 drivers/net/bnx2x/bnx2x_ethdev.c        | 12 ++++++++----
 drivers/net/bnxt/bnxt_ethdev.c          |  6 ++++--
 drivers/net/cxgbe/cxgbe_ethdev.c        |  6 ++++--
 drivers/net/e1000/em_ethdev.c           |  6 ++++--
 drivers/net/e1000/igb_ethdev.c          | 12 ++++++++----
 drivers/net/ena/ena_ethdev.c            |  6 ++++--
 drivers/net/enic/enic_ethdev.c          |  6 ++++--
 drivers/net/fm10k/fm10k_ethdev.c        |  6 ++++--
 drivers/net/i40e/i40e_ethdev.c          |  6 ++++--
 drivers/net/i40e/i40e_ethdev_vf.c       |  6 ++++--
 drivers/net/ixgbe/ixgbe_ethdev.c        | 12 ++++++++----
 drivers/net/mlx4/mlx4.c                 |  6 ++++--
 drivers/net/mlx5/mlx5.c                 |  4 +++-
 drivers/net/nfp/nfp_net.c               |  6 ++++--
 drivers/net/qede/qede_ethdev.c          | 16 ++++++++++------
 drivers/net/szedata2/rte_eth_szedata2.c |  6 ++++--
 drivers/net/virtio/virtio_ethdev.c      |  4 ++--
 drivers/net/vmxnet3/vmxnet3_ethdev.c    |  6 ++++--
 lib/librte_eal/common/eal_common_pci.c  | 10 ++++++++--
 lib/librte_eal/common/include/rte_dev.h | 12 ++++++++++++
 lib/librte_ether/rte_ethdev.c           | 16 ++++++++++++----
 lib/librte_ether/rte_ethdev.h           |  6 +++---
 22 files changed, 122 insertions(+), 54 deletions(-)

diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index 0eae433..6b5f906 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -620,8 +620,10 @@ static struct eth_driver rte_bnx2x_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_bnx2x_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_bnx2x_dev_init,
 	.dev_private_size = sizeof(struct bnx2x_softc),
@@ -634,8 +636,10 @@ static struct eth_driver rte_bnx2xvf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_bnx2xvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_bnx2xvf_dev_init,
 	.dev_private_size = sizeof(struct bnx2x_softc),
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 035fe07..70dccf6 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1163,8 +1163,10 @@ static struct eth_driver bnxt_rte_pmd = {
 		    .id_table = bnxt_pci_id_map,
 		    .drv_flags = RTE_PCI_DRV_NEED_MAPPING |
 			    RTE_PCI_DRV_DETACHABLE | RTE_PCI_DRV_INTR_LSC,
-		    .probe = rte_eth_dev_pci_probe,
-		    .remove = rte_eth_dev_pci_remove
+			.driver = {
+			    .probe = rte_eth_dev_pci_probe,
+			    .remove = rte_eth_dev_pci_remove
+			},
 		    },
 	.eth_dev_init = bnxt_dev_init,
 	.eth_dev_uninit = bnxt_dev_uninit,
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index b7f28eb..334e462 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -1041,8 +1041,10 @@ static struct eth_driver rte_cxgbe_pmd = {
 	.pci_drv = {
 		.id_table = cxgb4_pci_tbl,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_cxgbe_dev_init,
 	.dev_private_size = sizeof(struct port_info),
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index aee3d34..34c4b31 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -394,8 +394,10 @@ static struct eth_driver rte_em_pmd = {
 		.id_table = pci_id_em_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_em_dev_init,
 	.eth_dev_uninit = eth_em_dev_uninit,
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 2fddf0c..ae75b7e 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1081,8 +1081,10 @@ static struct eth_driver rte_igb_pmd = {
 		.id_table = pci_id_igb_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_igb_dev_init,
 	.eth_dev_uninit = eth_igb_dev_uninit,
@@ -1096,8 +1098,10 @@ static struct eth_driver rte_igbvf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_igbvf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_igbvf_dev_init,
 	.eth_dev_uninit = eth_igbvf_dev_uninit,
diff --git a/drivers/net/ena/ena_ethdev.c b/drivers/net/ena/ena_ethdev.c
index ab9a178..8825585 100644
--- a/drivers/net/ena/ena_ethdev.c
+++ b/drivers/net/ena/ena_ethdev.c
@@ -1707,8 +1707,10 @@ static struct eth_driver rte_ena_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_ena_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_ena_dev_init,
 	.dev_private_size = sizeof(struct ena_adapter),
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index 2b154ec..1ed951f 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -636,8 +636,10 @@ static struct eth_driver rte_enic_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_enic_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_enicpmd_dev_init,
 	.dev_private_size = sizeof(struct enic),
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 923690c..53a8e33 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -3064,8 +3064,10 @@ static struct eth_driver rte_pmd_fm10k = {
 		.id_table = pci_id_fm10k_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_fm10k_dev_init,
 	.eth_dev_uninit = eth_fm10k_dev_uninit,
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..7c08095 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -673,8 +673,10 @@ static struct eth_driver rte_i40e_pmd = {
 		.id_table = pci_id_i40e_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_i40e_dev_init,
 	.eth_dev_uninit = eth_i40e_dev_uninit,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index aa306d6..cbff0da 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1529,8 +1529,10 @@ static struct eth_driver rte_i40evf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_i40evf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = i40evf_dev_init,
 	.eth_dev_uninit = i40evf_dev_uninit,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index edc9b22..4b99ca1 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1567,8 +1567,10 @@ static struct eth_driver rte_ixgbe_pmd = {
 		.id_table = pci_id_ixgbe_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_ixgbe_dev_init,
 	.eth_dev_uninit = eth_ixgbe_dev_uninit,
@@ -1582,8 +1584,10 @@ static struct eth_driver rte_ixgbevf_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_ixgbevf_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_ixgbevf_dev_init,
 	.eth_dev_uninit = eth_ixgbevf_dev_uninit,
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index da61a85..b3f72d9 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -5910,8 +5910,10 @@ static struct eth_driver mlx4_driver = {
 			.name = MLX4_DRIVER_NAME
 		},
 		.id_table = mlx4_pci_id_map,
-		.probe = mlx4_pci_probe,
-		.drv_flags = RTE_PCI_DRV_INTR_LSC,
+		.driver = {
+			.probe = mlx4_pci_probe,
+			.drv_flags = RTE_PCI_DRV_INTR_LSC,
+		},
 	},
 	.dev_private_size = sizeof(struct priv)
 };
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 90cc35e..fa34724 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -733,7 +733,9 @@ static struct eth_driver mlx5_driver = {
 			.name = MLX5_DRIVER_NAME
 		},
 		.id_table = mlx5_pci_id_map,
-		.probe = mlx5_pci_probe,
+		.driver = {
+			.probe = mlx5_pci_probe,
+		},
 		.drv_flags = RTE_PCI_DRV_INTR_LSC,
 	},
 	.dev_private_size = sizeof(struct priv)
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index c6b1587..ffcc1b5 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2472,8 +2472,10 @@ static struct eth_driver rte_nfp_net_pmd = {
 		.id_table = pci_id_nfp_net_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
 			     RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = nfp_net_init,
 	.dev_private_size = sizeof(struct nfp_net_adapter),
diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c
index d106dd0..b8ad392 100644
--- a/drivers/net/qede/qede_ethdev.c
+++ b/drivers/net/qede/qede_ethdev.c
@@ -1645,9 +1645,11 @@ static struct eth_driver rte_qedevf_pmd = {
 		    .id_table = pci_id_qedevf_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		    .probe = rte_eth_dev_pci_probe,
-		    .remove = rte_eth_dev_pci_remove,
-		   },
+		    .driver = {
+				.probe = rte_eth_dev_pci_probe,
+				.remove = rte_eth_dev_pci_remove,
+			},
+		},
 	.eth_dev_init = qedevf_eth_dev_init,
 	.eth_dev_uninit = qedevf_eth_dev_uninit,
 	.dev_private_size = sizeof(struct qede_dev),
@@ -1658,9 +1660,11 @@ static struct eth_driver rte_qede_pmd = {
 		    .id_table = pci_id_qede_map,
 		    .drv_flags =
 		    RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
-		    .probe = rte_eth_dev_pci_probe,
-		    .remove = rte_eth_dev_pci_remove,
-		   },
+		    .driver = {
+			    .probe = rte_eth_dev_pci_probe,
+			    .remove = rte_eth_dev_pci_remove,
+			},
+		},
 	.eth_dev_init = qede_eth_dev_init,
 	.eth_dev_uninit = qede_eth_dev_uninit,
 	.dev_private_size = sizeof(struct qede_dev),
diff --git a/drivers/net/szedata2/rte_eth_szedata2.c b/drivers/net/szedata2/rte_eth_szedata2.c
index f3cd52d..d08da9d 100644
--- a/drivers/net/szedata2/rte_eth_szedata2.c
+++ b/drivers/net/szedata2/rte_eth_szedata2.c
@@ -1573,8 +1573,10 @@ static const struct rte_pci_id rte_szedata2_pci_id_table[] = {
 static struct eth_driver szedata2_eth_driver = {
 	.pci_drv = {
 		.id_table = rte_szedata2_pci_id_table,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init     = rte_szedata2_eth_dev_init,
 	.eth_dev_uninit   = rte_szedata2_eth_dev_uninit,
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 079fd6c..b7bec8f 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1377,11 +1377,11 @@ static struct eth_driver rte_virtio_pmd = {
 	.pci_drv = {
 		.driver = {
 			.name = "net_virtio",
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
 		},
 		.id_table = pci_id_virtio_map,
 		.drv_flags = RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
 	},
 	.eth_dev_init = eth_virtio_dev_init,
 	.eth_dev_uninit = eth_virtio_dev_uninit,
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 8bb13e5..52993de 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -337,8 +337,10 @@ static struct eth_driver rte_vmxnet3_pmd = {
 	.pci_drv = {
 		.id_table = pci_id_vmxnet3_map,
 		.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
-		.probe = rte_eth_dev_pci_probe,
-		.remove = rte_eth_dev_pci_remove,
+		.driver = {
+			.probe = rte_eth_dev_pci_probe,
+			.remove = rte_eth_dev_pci_remove,
+		},
 	},
 	.eth_dev_init = eth_vmxnet3_dev_init,
 	.eth_dev_uninit = eth_vmxnet3_dev_uninit,
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 6bff675..3082b1a 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -161,6 +161,8 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d
 {
 	int ret;
 	const struct rte_pci_id *id_table;
+	struct rte_driver *driver;
+	struct rte_device *device;
 
 	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
 
@@ -212,9 +214,11 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d
 
 		/* reference driver structure */
 		dev->driver = dr;
+		driver = &dr->driver;
+		device = &dev->device;
 
 		/* call the driver probe() function */
-		ret = dr->probe(dr, dev);
+		ret = driver->probe(driver, device);
 		if (ret)
 			dev->driver = NULL;
 
@@ -232,6 +236,7 @@ static int
 rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		struct rte_pci_device *dev)
 {
+	struct rte_driver *driver = NULL;
 	const struct rte_pci_id *id_table;
 
 	if ((dr == NULL) || (dev == NULL))
@@ -262,7 +267,8 @@ rte_eal_pci_detach_dev(struct rte_pci_driver *dr,
 		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
 				dev->id.device_id, dr->driver.name);
 
-		if (dr->remove && (dr->remove(dev) < 0))
+		driver = &(dr->driver);
+		if (driver->remove && (driver->remove(&(dev->device)) < 0))
 			return -1;	/* negative value is an error */
 
 		/* clear driver structure */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 4004f9a..7d2ab16 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -145,6 +145,16 @@ void rte_eal_device_insert(struct rte_device *dev);
 void rte_eal_device_remove(struct rte_device *dev);
 
 /**
+ * Initialisation function for the driver called during probing.
+ */
+typedef int (driver_probe_t)(struct rte_driver *, struct rte_device *);
+
+/**
+ * Uninitialisation function for the driver called during hotplugging.
+ */
+typedef int (driver_remove_t)(struct rte_device *);
+
+/**
  * A structure describing a device driver.
  */
 struct rte_driver {
@@ -152,6 +162,8 @@ struct rte_driver {
 	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
+	driver_probe_t *probe;         /**< Probe the device */
+	driver_remove_t *remove;       /**< Remove/hotplugging the device */
 };
 
 /**
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index fde8112..164d348 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -232,15 +232,20 @@ rte_eth_dev_release_port(struct rte_eth_dev *eth_dev)
 }
 
 int
-rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
-		      struct rte_pci_device *pci_dev)
+rte_eth_dev_pci_probe(struct rte_driver *drv,
+		      struct rte_device *dev)
 {
 	struct eth_driver    *eth_drv;
 	struct rte_eth_dev *eth_dev;
+	struct rte_pci_driver *pci_drv;
+	struct rte_pci_device *pci_dev;
 	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
 
 	int diag;
 
+	pci_drv = container_of(drv, struct rte_pci_driver, driver);
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	eth_drv = (struct eth_driver *)pci_drv;
 
 	rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
@@ -285,16 +290,19 @@ rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
 }
 
 int
-rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
+rte_eth_dev_pci_remove(struct rte_device *dev)
 {
 	const struct eth_driver *eth_drv;
 	struct rte_eth_dev *eth_dev;
+	struct rte_pci_device *pci_dev;
 	char ethdev_name[RTE_ETH_NAME_MAX_LEN];
 	int ret;
 
-	if (pci_dev == NULL)
+	if (dev == NULL)
 		return -EINVAL;
 
+	pci_dev = container_of(dev, struct rte_pci_device, device);
+
 	rte_eal_pci_device_name(&pci_dev->addr, ethdev_name,
 			sizeof(ethdev_name));
 
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 9678179..3c45a1f 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -4369,15 +4369,15 @@ rte_eth_dev_get_name_by_port(uint8_t port_id, char *name);
  * Wrapper for use by pci drivers as a .probe function to attach to a ethdev
  * interface.
  */
-int rte_eth_dev_pci_probe(struct rte_pci_driver *pci_drv,
-			  struct rte_pci_device *pci_dev);
+int rte_eth_dev_pci_probe(struct rte_driver *drv,
+			  struct rte_device *dev);
 
 /**
  * @internal
  * Wrapper for use by pci drivers as a .remove function to detach a ethdev
  * interface.
  */
-int rte_eth_dev_pci_remove(struct rte_pci_device *pci_dev);
+int rte_eth_dev_pci_remove(struct rte_device *dev);
 
 #ifdef __cplusplus
 }
-- 
2.7.4

^ permalink raw reply related

* [PATCH 06/13] eal: integrate bus scan and probe with EAL
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

Still a dummy implementation as no real bus driver exists. This adds calls
from EAL to bus specific scan, match functions.
Once driver->probe is in place, and a bus handler has been installed,
the code would become effective.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/eal.c         |  7 +++++++
 lib/librte_eal/common/eal_common_bus.c  | 30 ++++++++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h | 19 +++++++++++++++++++
 lib/librte_eal/linuxapp/eal/eal.c       |  7 +++++++
 4 files changed, 63 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 35e3117..30afc6b 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -64,6 +64,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -580,6 +581,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_dev_init() < 0)
 		rte_panic("Cannot init pmd devices\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -616,6 +620,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 3be9c77..67b808b 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -173,6 +173,36 @@ rte_eal_bus_unregister(struct rte_bus *bus)
 	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
 }
 
+/* Scan all the buses for registering devices */
+int
+rte_eal_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus->scan(bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
+				bus->name);
+			/* TODO: Should error on a particular bus block scan
+			 * for all others?
+			 */
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Match driver<->device and call driver->probe() */
+int
+rte_eal_bus_probe(void)
+{
+	/* Until driver->probe is available, this is dummy implementation */
+	return 0;
+}
+
 /* dump one bus info */
 static int
 bus_dump_one(FILE *f, struct rte_bus *bus)
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index d1bd2e8..9bd8650 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -209,6 +209,25 @@ void rte_eal_bus_unregister(struct rte_bus *bus);
  */
 struct rte_bus *rte_eal_get_bus(const char *bus_name);
 
+/** @internal
+ * Scan all the buses attached to the framework.
+ *
+ * @param void
+ * @return void
+ */
+int rte_eal_bus_scan(void);
+
+/** @internal
+ * For each device on the bus, perform a driver 'match' and call the
+ * driver's probe for device initialization.
+ *
+ * @param void
+ * @return
+ *	0 for successful match/probe
+ *	!0 otherwise
+ */
+int rte_eal_bus_probe(void);
+
 /**
  * Dump information of all the buses registered with EAL.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 2075282..01d0cee 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -69,6 +69,7 @@
 #include <rte_string_fns.h>
 #include <rte_cpuflags.h>
 #include <rte_interrupts.h>
+#include <rte_bus.h>
 #include <rte_pci.h>
 #include <rte_dev.h>
 #include <rte_devargs.h>
@@ -847,6 +848,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_intr_init() < 0)
 		rte_panic("Cannot init interrupt-handling thread\n");
 
+	if (rte_eal_bus_scan())
+		rte_panic("Cannot scan the buses for devices\n");
+
 	RTE_LCORE_FOREACH_SLAVE(i) {
 
 		/*
@@ -887,6 +891,9 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	if (rte_eal_bus_probe())
+		rte_panic("Cannot probe devices\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 04/13] eal/bus: add scan and match support
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

When a PMD is registred, it will associate itself with a bus.

A bus is responsible for 'scan' of all the devices attached to it.
All the scanned devices are attached to bus specific device_list.

During the probe operation, 'match' of the drivers and devices would
be done.

This patch also adds necessary test framework to test the scan and
match callbacks.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/test_bus.c                     | 265 ++++++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_common_bus.c  |   3 +
 lib/librte_eal/common/include/rte_bus.h |  46 ++++++
 3 files changed, 314 insertions(+)

diff --git a/app/test/test_bus.c b/app/test/test_bus.c
index 760d40a..ed95479 100644
--- a/app/test/test_bus.c
+++ b/app/test/test_bus.c
@@ -80,12 +80,32 @@ struct dummy_bus {
 struct rte_bus_list orig_bus_list =
 	TAILQ_HEAD_INITIALIZER(orig_bus_list);
 
+/* Forward declarations for callbacks from bus */
+
+/* Bus A
+ * Scan would register devA1 and devA2 to bus
+ */
+int scan_fn_for_busA(struct rte_bus *bus);
+
+/* Bus B
+ * Scan would register devB1 and devB2 to bus
+ */
+int scan_fn_for_busB(struct rte_bus *bus);
+
+/* generic implementations wrapped around by above declarations */
+static int generic_scan_fn(struct rte_bus *bus);
+static int generic_match_fn(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus busA = {
 	.name = "busA", /* "busA" */
+	.scan = scan_fn_for_busA,
+	.match = generic_match_fn,
 };
 
 struct rte_bus busB = {
 	.name = "busB", /* "busB */
+	.scan = scan_fn_for_busB,
+	.match = generic_match_fn,
 };
 
 struct rte_driver driverA = {
@@ -184,6 +204,92 @@ dump_device_tree(void)
 	printf("------>8-------\n");
 }
 
+/* @internal
+ * Move over the dummy_buses and find the entry matching the bus object
+ * passed as argument.
+ * For each device in that dummy_buses list, register.
+ *
+ * @param bus
+ *	bus to scan againt test entry
+ * @return
+ *	0 for successful scan, even if no devices are found
+ *	!0 for any error in scanning (like, invalid bus)
+ */
+static int
+generic_scan_fn(struct rte_bus *bus)
+{
+	int i = 0;
+	struct rte_device *dev = NULL;
+	struct dummy_bus *db = NULL;
+
+	if (!bus)
+		return -1;
+
+	/* Extract the device tree node using the bus passed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		if (!strcmp(dummy_buses[i].name, bus->name)) {
+			db = &dummy_buses[i];
+			break;
+		}
+	}
+
+	if (!db)
+		return -1;
+
+	/* For all the devices in the device tree (dummy_buses), add device */
+	for (i = 0; db->devices[i]; i++) {
+		dev = &(db->devices[i]->dev);
+		rte_eal_bus_add_device(bus, dev);
+	}
+
+	return 0;
+}
+
+/* @internal
+ * Obtain bus from driver object. Match the address of rte_device object
+ * with all the devices associated with that bus.
+ *
+ * Being a test function, all this does is validate that device object
+ * provided is available on the same bus to which driver is registered.
+ *
+ * @param drv
+ *	driver to which matching is to be performed
+ * @param dev
+ *	device object to match with driver
+ * @return
+ *	0 for successful match
+ *	!0 for failed match
+ */
+static int
+generic_match_fn(struct rte_driver *drv, struct rte_device *dev)
+{
+	struct rte_bus *bus;
+	struct rte_device *dev_p = NULL;
+
+	/* Match is based entirely on address of 'dev' and 'dev_p' extracted
+	 * from bus->device_list.
+	 */
+
+	/* a driver is registered with the bus *before* the scan. */
+	bus = drv->bus;
+	TAILQ_FOREACH(dev_p, &bus->device_list, next) {
+		if (dev == dev_p)
+			return 0;
+	}
+
+	return 1;
+}
+
+int
+scan_fn_for_busA(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
+int
+scan_fn_for_busB(struct rte_bus *bus) {
+	return generic_scan_fn(bus);
+}
+
 static int
 test_bus_setup(void)
 {
@@ -391,6 +497,155 @@ test_driver_unregistration_on_bus(void)
 
 }
 
+static int
+test_device_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all devices */
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			rte_eal_bus_remove_device(dev);
+		}
+	}
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->device_list)) {
+			printf("Unable to remove all devices on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	/* All devices from all buses have been removed */
+	printf("All devices on all buses unregistered.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * For each bus registered, call the scan function to identify devices
+ * on the bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful scan
+ *	!0 for unsuccessful scan
+ *
+ */
+static int
+test_bus_scan(void)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Call the scan function for each bus */
+		ret = bus->scan(bus);
+		if (ret) {
+			printf("Scan of buses failed.\n");
+			return -1;
+		}
+	}
+
+	printf("Scan of all buses completed.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+/* @internal
+ * Function to perform 'probe' and link devices and drivers on a bus.
+ * This would work over all the buses registered, and all devices and drivers
+ * registered with it - call match on each pair.
+ * Aim is to test the match_fn for each bus.
+ *
+ * @param void
+ * @return
+ *	0 for successful probe
+ *	!0 for failure in probe
+ *
+ */
+static int
+test_probe_on_bus(void)
+{
+	int ret = 0;
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_device *dev = NULL;
+	struct rte_driver *drv = NULL;
+
+	/* In case of this test:
+	* 1. for each bus in rte_bus_list
+	* 2.  for each device in bus->device_list
+	* 3.   for each driver in bus->driver_list
+	* 4.    call match
+	* 5.    link driver and device
+	* 6. Verify the linkage.
+	*/
+	for (i = 0; dummy_buses[i].name; i++) {
+		/* get bus pointer from dummy_buses itself rather than
+		 * rte_eal_get_bus
+		 */
+		bus = dummy_buses[i].bus;
+
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			TAILQ_FOREACH(drv, &bus->driver_list, next) {
+				if (!bus->match) {
+					printf("Incorrect bus without match "
+					       "fn: (%s).\n", bus->name);
+					return -1;
+				}
+
+				ret = bus->match(drv, dev);
+				if (ret) {
+					printf("Device and driver don't "
+					       "belong to same bus.\n");
+					return -1;
+				}
+				dev->driver = drv;
+
+				/* As match is generic, it always results in
+				 * dev->drv pointing to first driver entry in
+				 * dummy_buses[i]
+				 */
+			}
+		}
+	}
+
+	/* Verify the linkage. All devices belonging to a dummy_buses[i]
+	 * should have same driver (first driver entry of dummy_buses[i])
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		drv = dummy_buses[i].drivers[0];
+
+		for (j = 0; dummy_buses[i].devices[j]; j++) {
+			dev = &(dummy_buses[i].devices[j]->dev);
+			if (dev->driver != drv) {
+				printf("Incorrect driver<->device linkage.\n");
+				return -1;
+			}
+		}
+	}
+
+	printf("Probe on all buses successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
 int
 test_bus(void)
 {
@@ -407,6 +662,16 @@ test_bus(void)
 	if (test_driver_registration_on_bus())
 		return -1;
 
+	if (test_bus_scan())
+		return -1;
+
+	/* Now that the devices and drivers are registered, perform probe */
+	if (test_probe_on_bus())
+		return -1;
+
+	if (test_device_unregistration_on_bus())
+		return -1;
+
 	if (test_driver_unregistration_on_bus())
 		return -1;
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 612f64e..2473fe4 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -132,6 +132,9 @@ rte_eal_bus_register(struct rte_bus *bus)
 {
 	RTE_VERIFY(bus);
 	RTE_VERIFY(bus->name && strlen(bus->name));
+	/* A bus should mandatorily have the scan and match implemented */
+	RTE_VERIFY(bus->scan);
+	RTE_VERIFY(bus->match);
 
 	/* Initialize the driver and device list associated with the bus */
 	TAILQ_INIT(&(bus->driver_list));
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index f0297a9..b41105c 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -59,6 +59,49 @@ TAILQ_HEAD(rte_bus_list, rte_bus);
 /* Global Bus list */
 extern struct rte_bus_list rte_bus_list;
 
+/**
+ * Bus specific scan for devices attached on the bus.
+ * For each bus object, the scan would be reponsible for finding devices and
+ * adding them to its private device list.
+ *
+ * Successful detection of a device results in rte_device object which is
+ * embedded within the respective device type (rte_pci_device, for example).
+ * Thereafter, PCI specific bus would need to perform
+ * container_of(rte_pci_device) to obtain PCI device object.
+ *
+ * Scan failure of a bus is not treated as exit criteria for application. Scan
+ * for all other buses would still continue.
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param bus
+ *	Reference to the bus on which device is added
+ * @return
+ *	0 for successful scan
+ *	!0 (<0) for unsuccessful scan with error value
+ */
+typedef int (*bus_scan_t)(struct rte_bus *bus);
+
+/**
+ * Bus specific match for devices and drivers which can service them.
+ * For each scanned device, rte_driver->probe would be called for driver
+ * specific initialization of the device.
+ *
+ * It is the work of each bus handler to obtain the specific device object
+ * using container_of (or typecasting, as a less preferred way).
+ *
+ * A bus should mandatorily implement this method.
+ *
+ * @param drv
+ *	Driver object attached to the bus
+ * @param dev
+ *	Device object which is being probed.
+ * @return
+ *	0 for successful match
+ *	!0 for unsuccessful match
+ */
+typedef int (*bus_match_t)(struct rte_driver *drv, struct rte_device *dev);
+
 struct rte_bus {
 	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
 	struct rte_driver_list driver_list;
@@ -66,6 +109,9 @@ struct rte_bus {
 	struct rte_device_list device_list;
 				     /**< List of all devices on bus */
 	const char *name;            /**< Name of the bus */
+	bus_scan_t scan;            /**< Scan for devices attached to bus */
+	bus_match_t match;
+	/**< Match device with drivers associated with the bus */
 };
 
 /** @internal
-- 
2.7.4

^ permalink raw reply related

* [PATCH 05/13] eal/bus: add support for inserting a device on a bus
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

Rather than adding a device to tail, a new device might be added to the
list (pivoted on bus) at a predefined position, for example, adding it
order of addressing.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/common/eal_common_bus.c  | 11 +++++++++++
 lib/librte_eal/common/include/rte_bus.h | 18 ++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index 2473fe4..3be9c77 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -58,6 +58,17 @@ rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
 	dev->bus = bus;
 }
 
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_dev,
+			  struct rte_device *new_dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(old_dev);
+	RTE_VERIFY(new_dev);
+
+	TAILQ_INSERT_BEFORE(old_dev, new_dev, next);
+}
+
 /** @internal
  * Remove a device from its bus.
  */
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index b41105c..d1bd2e8 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -128,6 +128,24 @@ void
 rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
 
 /** @internal
+ * Rather than adding a device to tail, insert at a predefined location.
+ * This is specifically useful for update device cases, or where addition
+ * of devices in the list needs to be ordered (addressing, for example).
+ *
+ * @param bus
+ *	Handle for bus on which device is to be added
+ * @param old_dev
+ *	Existing rte_device object before which new device needs to be added
+ * @param new_dev
+ *	Object for device to be added before old_dev
+ * @return
+ *	void
+ */
+void
+rte_eal_bus_insert_device(struct rte_bus *bus, struct rte_device *old_device,
+			  struct rte_device *new_device);
+
+/** @internal
  * Remove a device from its bus.
  *
  * @param dev
-- 
2.7.4

^ permalink raw reply related

* [PATCH 03/13] test: add basic bus infrastructure tests
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

Verification of bus registration, driver registration on a bus.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 app/test/Makefile   |   2 +-
 app/test/test.h     |   2 +
 app/test/test_bus.c | 423 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 426 insertions(+), 1 deletion(-)
 create mode 100644 app/test/test_bus.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 5be023a..ca0f106 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..c8ec43f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -236,6 +236,8 @@ int commands_init(void);
 int test_pci(void);
 int test_pci_run;
 
+int test_bus(void);
+
 int test_mp_secondary(void);
 
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..760d40a
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,423 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	const char *name;
+	struct rte_device dev;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus {
+	const char *name;
+	struct rte_bus *bus;
+	struct rte_driver *drivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *devices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct rte_bus busA = {
+	.name = "busA", /* "busA" */
+};
+
+struct rte_bus busB = {
+	.name = "busB", /* "busB */
+};
+
+struct rte_driver driverA = {
+	.name = "driverA",
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct rte_driver driverB = {
+	.name = "driverB",
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.bus = NULL,
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus dummy_buses[] = {
+	{
+		.name = "busA",
+		.bus = &busA,
+		.drivers = {&driverA, NULL},
+		.devices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.bus = &busB,
+		.drivers = {&driverB, NULL},
+		.devices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus *db;
+	struct rte_bus *bus;
+	struct rte_driver *drv;
+	struct rte_device *dev;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; dummy_buses[i].name; i++) {
+		db = &dummy_buses[i];
+
+		bus = rte_eal_get_bus(db->name);
+		if (!bus)
+			return;
+
+		printf(" Bus: %s\n", bus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			printf("    %s\n", drv->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(dev, &bus->device_list, next) {
+			printf("    Addr: %p\n", dev);
+			if (dev->driver)
+				printf("    Driver = %s\n", dev->driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_eal_bus_unregister(bus_p);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_eal_bus_unregister(bus_p);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		rte_eal_bus_register(bus_p);
+	}
+
+	dump_device_tree();
+	return 0;
+}
+
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = dummy_buses[i].bus;
+		rte_eal_bus_register(bus);
+		printf("Registered Bus %s\n", dummy_buses[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of dummy_buses */
+		ret = strcmp(bus->name, dummy_buses[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of dummy_buses[i] should be the NULL entry */
+	if (dummy_buses[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       dummy_buses[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_eal_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; dummy_buses[i].name != NULL; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_eal_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+/* Positive case: For each driver in dummy_buses, perform
+ * registration
+ */
+static int
+test_driver_registration_on_bus(void)
+{
+	int i, j;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv, *drv2;
+
+	/* For each bus on the dummy_buses list:
+	 * 1. get the bus reference
+	 * 2. register all drivers from dummy_buses
+	 */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', register all drivers */
+		for (j = 0; dummy_buses[i].drivers[j]; j++) {
+			drv = dummy_buses[i].drivers[j];
+			rte_eal_bus_add_driver(bus, drv);
+		}
+	}
+
+	/* Drivers have been registered. Verify by parsing the list */
+	drv = NULL;
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		j = 0;
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			drv2 = dummy_buses[i].drivers[j++];
+			if (strcmp(drv2->name, drv->name)) {
+				printf("Incorrectly registered drivers."
+				       " Expected: %s; Available: %s\n",
+				       drv2->name, drv->name);
+				return -1;
+			}
+		}
+	}
+
+	printf("Driver registration test successful.\n");
+	dump_device_tree();
+
+	return 0;
+}
+
+static int
+test_driver_unregistration_on_bus(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+	struct rte_driver *drv;
+
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+		if (!bus) {
+			printf("Unable to find bus (%s)\n",
+			       dummy_buses[i].name);
+			return -1;
+		}
+
+		/* For bus 'bus', unregister all drivers */
+		TAILQ_FOREACH(drv, &bus->driver_list, next) {
+			rte_eal_bus_remove_driver(drv);
+		}
+	}
+
+	/* Verifying that all drivers have been removed */
+	for (i = 0; dummy_buses[i].name; i++) {
+		bus = rte_eal_get_bus(dummy_buses[i].name);
+
+		if (!TAILQ_EMPTY(&bus->driver_list)) {
+			printf("Unable to remove all drivers on bus (%s)\n",
+			       bus->name);
+			return -1;
+		}
+	}
+
+	printf("Unregistration of drivers on all buses is successful.\n");
+	/* All devices from all buses have been removed */
+	dump_device_tree();
+	return 0;
+
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	/* Assuming that buses are already registered, register drivers
+	 * with them.
+	 */
+	if (test_driver_registration_on_bus())
+		return -1;
+
+	if (test_driver_unregistration_on_bus())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
-- 
2.7.4

^ permalink raw reply related

* [PATCH 02/13] eal/bus: introduce bus abstraction
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

This patch introduces the rte_bus abstraction for devices and drivers in
EAL framework. The model is:
 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

This patch adds a 'rte_bus' class which rte_driver and rte_device refer.
This way, each device (rte_xxx_device) would have reference to the bus
it is based on. As well as, each driver (rte_xxx_driver) would have link
to the bus and devices on it for servicing.

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> List of rte_bus specific
                     | device_list----    devices
                     |              | `-> List of rte_bus associated
                     |              |     drivers
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | rte_bus     |                     | rte_bus         |
    | rte_driver  |                     | ...             |
    | ...         |                     +---------...-----+
    |             |                               |||
    +---||--------+                               |||
        ||                                        |||
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | ....           | | ....          |               |||
 +----------------+ +---------------+              / | \
                                                  /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | ....           |    | ....           |    | ....          |
            +----------------+    +----------------+    +---------------+

This patch only enables the bus references on rte_driver and rte_driver.
EAL wide global device and driver list continue to exist until an instance
of bus is added in subsequent patches.

This patch also introduces RTE_REGISTER_BUS macro on the lines of
RTE_PMD_REGISTER_XXX. Key difference is that the constructor priority has
been explicitly set to 101 so as to execute bus registration before PMD.

Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  15 ++
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 192 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_bus.h         | 174 +++++++++++++++++++++
 lib/librte_eal/common/include/rte_dev.h         |   2 +
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  15 ++
 7 files changed, 400 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2f81f7c..23fc1c1 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -174,3 +174,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index dfd64aa..79f958d 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -38,7 +38,7 @@ INC += rte_per_lcore.h rte_random.h
 INC += rte_tailq.h rte_interrupts.h rte_alarm.h
 INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
-INC += rte_hexdump.h rte_devargs.h rte_dev.h rte_vdev.h
+INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_vdev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
 INC += rte_malloc.h rte_keepalive.h rte_time.h
 
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
new file mode 100644
index 0000000..612f64e
--- /dev/null
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -0,0 +1,192 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_devargs.h>
+#include <rte_debug.h>
+
+#include "eal_private.h"
+
+struct rte_bus_list rte_bus_list =
+	TAILQ_HEAD_INITIALIZER(rte_bus_list);
+
+/** @internal
+ * Add a device to a bus.
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(dev);
+
+	TAILQ_INSERT_TAIL(&bus->device_list, dev, next);
+	dev->bus = bus;
+}
+
+/** @internal
+ * Remove a device from its bus.
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(dev);
+	RTE_VERIFY(dev->bus);
+
+	bus = dev->bus;
+	TAILQ_REMOVE(&bus->device_list, dev, next);
+	dev->bus = NULL;
+}
+
+/** @internal
+ * Associate a driver with a bus.
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(drv);
+
+	TAILQ_INSERT_TAIL(&bus->driver_list, drv, next);
+	drv->bus = bus;
+}
+
+/** @internal
+ * Disassociate a driver from bus.
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(drv);
+	RTE_VERIFY(drv->bus);
+
+	bus = drv->bus;
+	TAILQ_REMOVE(&bus->driver_list, drv, next);
+	drv->bus = NULL;
+}
+
+/**
+ * Get the bus handle using its name
+ */
+struct rte_bus *
+rte_eal_get_bus(const char *bus_name)
+{
+	struct rte_bus *bus;
+
+	RTE_VERIFY(bus_name);
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		RTE_VERIFY(bus->name);
+
+		if (!strcmp(bus_name, bus->name)) {
+			RTE_LOG(DEBUG, EAL, "Returning Bus object %p\n", bus);
+			return bus;
+		}
+	}
+
+	/* Unable to find bus requested */
+	return NULL;
+}
+
+/* register a bus */
+void
+rte_eal_bus_register(struct rte_bus *bus)
+{
+	RTE_VERIFY(bus);
+	RTE_VERIFY(bus->name && strlen(bus->name));
+
+	/* Initialize the driver and device list associated with the bus */
+	TAILQ_INIT(&(bus->driver_list));
+	TAILQ_INIT(&(bus->device_list));
+
+	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Registered [%s] bus.\n", bus->name);
+}
+
+/* unregister a bus */
+void
+rte_eal_bus_unregister(struct rte_bus *bus)
+{
+	/* All devices and drivers associated with the bus should have been
+	 * 'device->uninit' and 'driver->remove()' already.
+	 */
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->driver_list)));
+	RTE_VERIFY(TAILQ_EMPTY(&(bus->device_list)));
+
+	/* TODO: For each device, call its rte_device->driver->remove()
+	 * and rte_eal_bus_remove_driver()
+	 */
+
+	TAILQ_REMOVE(&rte_bus_list, bus, next);
+	RTE_LOG(INFO, EAL, "Unregistered [%s] bus.\n", bus->name);
+}
+
+/* dump one bus info */
+static int
+bus_dump_one(FILE *f, struct rte_bus *bus)
+{
+	int ret;
+
+	/* For now, dump only the bus name */
+	ret = fprintf(f, " %s\n", bus->name);
+
+	/* Error in case of inability in writing to stream */
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void
+rte_eal_bus_dump(FILE *f)
+{
+	int ret;
+	struct rte_bus *bus;
+
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		ret = bus_dump_one(f, bus);
+		if (ret) {
+			RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
+				ret);
+			break;
+		}
+	}
+}
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
new file mode 100644
index 0000000..f0297a9
--- /dev/null
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -0,0 +1,174 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_BUS_H_
+#define _RTE_BUS_H_
+
+/**
+ * @file
+ *
+ * RTE PMD Bus Abstraction interfaces
+ *
+ * This file exposes APIs and Interfaces for Bus Abstraction over the devices
+ * drivers in EAL.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_dev.h>
+
+/** Double linked list of buses */
+TAILQ_HEAD(rte_bus_list, rte_bus);
+
+/* Global Bus list */
+extern struct rte_bus_list rte_bus_list;
+
+struct rte_bus {
+	TAILQ_ENTRY(rte_bus) next;   /**< Next bus object in linked list */
+	struct rte_driver_list driver_list;
+				     /**< List of all drivers on bus */
+	struct rte_device_list device_list;
+				     /**< List of all devices on bus */
+	const char *name;            /**< Name of the bus */
+};
+
+/** @internal
+ * Add a device to a bus.
+ *
+ * @param bus
+ *	Bus on which device is to be added
+ * @param dev
+ *	Device handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_device(struct rte_bus *bus, struct rte_device *dev);
+
+/** @internal
+ * Remove a device from its bus.
+ *
+ * @param dev
+ *	Device handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_device(struct rte_device *dev);
+
+/** @internal
+ * Associate a driver with a bus.
+ *
+ * @param bus
+ *	Bus on which driver is to be added
+ * @param dev
+ *	Driver handle
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_add_driver(struct rte_bus *bus, struct rte_driver *drv);
+
+/** @internal
+ * Disassociate a driver from its bus.
+ *
+ * @param dev
+ *	Driver handle to remove
+ * @return
+ *	None
+ */
+void
+rte_eal_bus_remove_driver(struct rte_driver *drv);
+
+/**
+ * Register a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be registered.
+ */
+void rte_eal_bus_register(struct rte_bus *bus);
+
+/**
+ * Unregister a Bus handler.
+ *
+ * @param driver
+ *   A pointer to a rte_bus structure describing the bus
+ *   to be unregistered.
+ */
+void rte_eal_bus_unregister(struct rte_bus *bus);
+
+/**
+ * Obtain handle for bus given its name.
+ *
+ * @param bus_name
+ *	Name of the bus handle to search
+ * @return
+ *	Pointer to Bus object if name matches any registered bus object
+ *	NULL, if no matching bus found
+ */
+struct rte_bus *rte_eal_get_bus(const char *bus_name);
+
+/**
+ * Dump information of all the buses registered with EAL.
+ *
+ * @param f
+ *	A valid and open output stream handle
+ *
+ * @return
+ *	 0 in case of success
+ *	!0 in case there is error in opening the output stream
+ */
+void rte_eal_bus_dump(FILE *f);
+
+/** Helper for Bus registration. The constructor has higher priority than
+ * PMD constructors
+ */
+#define RTE_REGISTER_BUS(nm, bus) \
+static void __attribute__((constructor(101), used)) businitfn_ ##nm(void) \
+{\
+	(bus).name = RTE_STR(nm);\
+	rte_eal_bus_register(&bus); \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_BUS_H */
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 8840380..4004f9a 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -122,6 +122,7 @@ struct rte_driver;
  */
 struct rte_device {
 	TAILQ_ENTRY(rte_device) next; /**< Next device */
+	struct rte_bus *bus;          /**< Device connected to this bus */
 	struct rte_driver *driver;    /**< Associated driver */
 	int numa_node;                /**< NUMA node connection */
 	struct rte_devargs *devargs;  /**< Device user arguments */
@@ -148,6 +149,7 @@ void rte_eal_device_remove(struct rte_device *dev);
  */
 struct rte_driver {
 	TAILQ_ENTRY(rte_driver) next;  /**< Next in list. */
+	struct rte_bus *bus;           /**< Bus serviced by this driver */
 	const char *name;                   /**< Driver name. */
 	const char *alias;              /**< Driver alias. */
 };
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 4e206f0..aa874a5 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -87,6 +87,7 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_cpuflags.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_string_fns.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_hexdump.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_devargs.c
+SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_bus.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_dev.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_options.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_thread.c
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 83721ba..c873a7f 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -178,3 +178,18 @@ DPDK_16.11 {
 	rte_eal_vdrv_unregister;
 
 } DPDK_16.07;
+
+DPDK_17.02 {
+	global:
+
+	rte_bus_list;
+	rte_eal_bus_add_device;
+	rte_eal_bus_add_driver;
+	rte_eal_get_bus;
+	rte_eal_bus_dump;
+	rte_eal_bus_register;
+	rte_eal_bus_remove_device;
+	rte_eal_bus_remove_driver;
+	rte_eal_bus_unregister;
+
+} DPDK_16.11;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 01/13] eal: define container_of macro
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev
  Cc: thomas.monjalon, david.marchand, Jan Blunck, Jan Viktorin,
	Shreyansh Jain
In-Reply-To: <1480846288-2517-1-git-send-email-shreyansh.jain@nxp.com>

From: Jan Blunck <jblunck@infradead.org>

This macro is based on Jan Viktorin's original patch but also checks the
type of the passed pointer against the type of the member.

Signed-off-by: Jan Viktorin <viktorin@rehivetech.com>
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
[jblunck@infradead.org: add type checking and __extension__]
Signed-off-by: Jan Blunck <jblunck@infradead.org>
---
 lib/librte_eal/common/include/rte_common.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index db5ac91..8dda3e2 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -331,6 +331,26 @@ rte_bsf32(uint32_t v)
 #define offsetof(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
 #endif
 
+/**
+ * Return pointer to the wrapping struct instance.
+ *
+ * Example:
+ *
+ *  struct wrapper {
+ *      ...
+ *      struct child c;
+ *      ...
+ *  };
+ *
+ *  struct child *x = obtain(...);
+ *  struct wrapper *w = container_of(x, struct wrapper, c);
+ */
+#ifndef container_of
+#define container_of(ptr, type, member)	__extension__ ({		\
+			typeof(((type *)0)->member) *_ptr = (ptr);	\
+			(type *)(((char *)_ptr) - offsetof(type, member)); })
+#endif
+
 #define _RTE_STR(x) #x
 /** Take a macro value and get a string version of it */
 #define RTE_STR(x) _RTE_STR(x)
-- 
2.7.4

^ permalink raw reply related

* [PATCH 00/13] Introducing EAL Bus-Device-Driver Model
From: Shreyansh Jain @ 2016-12-04 10:11 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, david.marchand, Shreyansh Jain

DPDK has been inherently a PCI inclined framework. Because of this, the
design of device tree (or list) within DPDK is also PCI inclined. A
non-PCI device doesn't have a way of being expressed without using hooks
started from EAL to PMD.

:: Overview of the Proposed Changes ::

Assuming the below graph for a computing node:

        device A1
          |
  +==.===='==============.============+ Bus A.
     |                    `--> driver A11     \
  device A2                `-> driver A12      \______
                                                |CPU |
                                                /`````
        device B1                              /
          |                                   /
  +==.===='==============.============+ Bus B`
     |                    `--> driver B11
  device B2                `-> driver B12


 - One or more buses are connected to a CPU (or core)
 - One or more devices are conneted to a Bus
 - Drivers are running instances which manage one or more devices
 - Bus is responsible for identifying devices (and interrupt propogation)
 - Driver is responsible for initializing the device

In context of DPDK EAL:
 - rte_bus, represents a Bus. An implementation of a physical bus would
   instantiate this class.
 - Buses are registered just like a PMD - RTE_REGISTER_BUS()
   `- Thus, implementation for PCI would instantiate a rte_bus, give it a
      name and provide scan/match hooks.
    - Currently, priority of RTE_REGISTER_BUS constructor has been set to
      101 to make sure bus is registered *before* drivers are.
 - Each registered bus is part of a doubly list.
   -- Each device refers to rte_bus on which it belongs
   -- Each driver refers to rte_bus with which it is associated
   -- Device and Drivers lists are part of rte_bus
   -- NO global device/driver list would exist
 - When a PMD wants to register itself, it would 'add' itself to an
   existing bus. Which essentially converts to adding the driver to
   a bus specific driver_list.
 - Bus would perform a scan and 'add' devices scanned to its list.
 - Bus would perform a probe and link devices and drivers on each bus and
   invoking a series of probes
   `-- There are some parallel work for combining scan/probe in EAL [5]
       and also for doing away with a independent scan function all
       together [6].


The view would be almost like:

                                  __ rte_bus_list
                                 /
                     +----------'---+
                     |rte_bus       |
                     | driver_list------> device_list for this bus
                     | device_list----    
                     | scan()       | `-> driver_list for this bus
                     | match()      |
                     | probe()      |
                     |              |
                     +--|------|----+
              _________/        \_________
    +--------/----+                     +-\---------------+
    |rte_device   |                     |rte_driver       |
    | *rte_bus    |                     | *rte_bus        |
    | rte_driver  |                     | probe()         |
    |             |                     | remove()        |
    |  devargs    |                     |                 |
    +---||--------+                     +---------|||-----+
        ||                                        '''      
        | \                                        \\\
        |  \_____________                           \\\
        |                \                          |||
 +------|---------+ +----|----------+               |||
 |rte_pci_device  | |rte_xxx_device |               |||
 | PCI specific   | | xxx device    |               |||
 | info (mem,)    | | specific fns  |              / | \
 +----------------+ +---------------+             /  |  \
                            _____________________/  /    \
                           /                    ___/      \
            +-------------'--+    +------------'---+    +--'------------+
            |rte_pci_driver  |    |rte_vdev_driver |    |rte_xxx_driver |
            | PCI id table,  |    | <probably,     |    | ....          |
            | other driver   |    |  nothing>      |    +---------------+
            | data           |    |  ...           |
            |  probe()       |    +----------------+
            |  remove()      |
            +----------------+

In continuation to the RFC posted on 17/Nov [9],
A series of patches is being posted which attempts to create:
 1. A basic bus model
    `- define rte_bus and associated methods/helpers
    `- test infrastructure to test the Bus infra
 2. Changes in EAL to support PCI as a bus
    `- a "pci" bus is registered
    `- existing scan/match/probe are modified to allow for bus integration
    `- PCI Device and Driver list, which were global entities, have been
       moved to rte_bus->[device/driver]_list

I have sanity tested this patch over a XeonD X552 available with me, as
well as part of PoC for verifying NXP's DPAA2 PMD (being pushed out in a
separate series). Exhaustive testing is still pending.

:: Brief about Patch Layout ::

0001:      Container_of patch from [3]
0002~0003: Introducing the basic Bus model and associated test case
0004:      Add scan and match callbacks for the Bus and updated test case
0005:      Support insertion of device rather than addition to tail
0006:      Integrate bus scan/match with EAL, without any effective driver
0007:      rte_pci_driver->probe replaced with rte_driver->probe
0008:      Integrate probe of drivers with EAL
0009:      Split the existing PCI probe into match and probe
0010:      Make PCI probe/match work on rte_driver/device rather than
           rte_pci_device/rte_pci_driver
0011:      Patch from Ben [8], part of series [2]
0012~0013: Enable Scan/Match/probe on Bus from EAL and remove unused
           functions and lists 

:: Pending Changes/Caveats ::

0. eth_dev still contains rte_pci_device. I am banking on Jan's patches [1]
   for conversion to a macro (ETH_DEV_PCI_DEV) and subsequent replacement
   of all pci_dev usage in eth_dev.

1. One of the major changes pending, as against proposed in RFC, is the
   removal of eth_driver.
   Being a large change, and independent one, this would be done in a
   separate series of patches. []

2. app/test/test_pci.c is still not modified. It is rendered uncompilable
   as most of the APIs it was calling don't exist anymore. I will push a
   v2 which would include a complete re-write of test_pci (or, if someone
   can help me that, it would be awesome).

3. This patchset only moves the PCI into a bus. And, that movement is also
   currently part of the EAL (lib/librte_eal/linux)
   - there was an open question in RFC about where to place the PCI bus
     instance - whether in drivers/bus/... or in lib/librte_bus/... or
     lib/librte_eal/...; This patch uses the last option. But, movement
     only impacts placement of Makefiles. Please convey your reservations
     for current placement.
   - It also impacts the point (8) about priority use in constructor

4. Though the implementation for bus is common for Linux and BSD, the PCI
   bus implementation has been done/tested only for Linux.

5. There was a suggestion from Jan Blunk about a helper iterator within the
   rte_bus. I will send this out in v2.

6. Cyptodev and VDEV changes are still pending. Jan has already conveyed
   that he would be working on the VDEV part. I will work on the Crypto
   part and target that for v2.

7. The overall layout for driver probing has changed a little.
   earlier, it was:
    rte_eal_init()
     `-> rte_eal_pci_probe() (and parallel for VDEV)
         `-> rte_pci_driver->probe()
             `-> eth_driver->eth_dev_init()

   now, it would be:
    rte_eal_bus_probe()
    `-> bus->prove() (*) <- Iterator for PCI device/driver;
        |                   old rte_eal_pci_probe()
        `-> rte_driver->probe() <- create eth_dev
            `-> rte_pci_driver->probe() <- PMD init; old eth_dev_init

   (*) Buses don't do probe. But in DPDK, EAL was doing this. This patch
       pushes that responsibility a layer down, towards rte_bus.
       See Patch 0008 for more explanantion

       Also, rte_driver->probe() creating eth_dev certainly sounds a little
       wrong - but, I would like to get your opinion on how to lay this
       order of which layer ethernet device corresponds to.
       1) Which layer should allocate eth_dev?
          `-> My take: rte_driver->probe()
       2) which layer should fill the eth_dev?
          `-> My take: rte_xxx_driver->probe()
       3) Is init/uninit better name for rte_xxx_driver()->probe() if all
          they do is initialize the ethernet device?

 8. RTE_REGISTER_BUS has been declared with contructor priority of 101
    It is important that Bus is registered *before* drivers are registered.
    Only way I could find to assure that was via 
    __attribute(contructor(priority)) of GCC. I am not sure how it would
    behave on other compilers. Any suggestions?

:: Some known issues ::

 - Checkpatch is failing on patch 0001
 - app/test/test_pci.c compilation is failing, if enabled. By default it
   seems to be disabled (CONFIG_RTE_APP_TEST_RESOURCE_TAR)
 - Bump to librte_eal version

:: References ::

[1] http://dpdk.org/ml/archives/dev/2016-November/050186.html
[2] http://dpdk.org/ml/archives/dev/2016-November/050622.html
[3] http://dpdk.org/ml/archives/dev/2016-November/050416.html
[4] http://dpdk.org/ml/archives/dev/2016-November/050567.html
[5] http://dpdk.org/ml/archives/dev/2016-November/050628.html
[6] http://dpdk.org/ml/archives/dev/2016-November/050415.html
[7] http://dpdk.org/ml/archives/dev/2016-November/050443.html
[8] http://dpdk.org/ml/archives/dev/2016-November/050624.html
[9] http://dpdk.org/ml/archives/dev/2016-November/050296.html

Ben Walker (1):
  pci: Pass rte_pci_addr to functions instead of separate args

Jan Blunck (1):
  eal: define container_of macro

Shreyansh Jain (11):
  eal/bus: introduce bus abstraction
  test: add basic bus infrastructure tests
  eal/bus: add scan and match support
  eal/bus: add support for inserting a device on a bus
  eal: integrate bus scan and probe with EAL
  pci: replace probe and remove handlers with rte_driver
  eal: enable probe and remove from bus infrastructure
  pci: split match and probe function
  eal/pci: generalize args of PCI scan/match towards RTE device/driver
  eal: enable PCI bus
  eal/pci: remove PCI probe and init calls

 app/test/Makefile                               |   2 +-
 app/test/test.h                                 |   2 +
 app/test/test_bus.c                             | 688 ++++++++++++++++++++++++
 app/test/test_pci.c                             |   2 +-
 drivers/net/bnx2x/bnx2x_ethdev.c                |  12 +-
 drivers/net/bnxt/bnxt_ethdev.c                  |   6 +-
 drivers/net/cxgbe/cxgbe_ethdev.c                |   6 +-
 drivers/net/e1000/em_ethdev.c                   |   6 +-
 drivers/net/e1000/igb_ethdev.c                  |  12 +-
 drivers/net/ena/ena_ethdev.c                    |   6 +-
 drivers/net/enic/enic_ethdev.c                  |   6 +-
 drivers/net/fm10k/fm10k_ethdev.c                |   6 +-
 drivers/net/i40e/i40e_ethdev.c                  |   6 +-
 drivers/net/i40e/i40e_ethdev_vf.c               |   6 +-
 drivers/net/ixgbe/ixgbe_ethdev.c                |  12 +-
 drivers/net/mlx4/mlx4.c                         |   6 +-
 drivers/net/mlx5/mlx5.c                         |   4 +-
 drivers/net/nfp/nfp_net.c                       |   6 +-
 drivers/net/qede/qede_ethdev.c                  |  16 +-
 drivers/net/szedata2/rte_eth_szedata2.c         |   6 +-
 drivers/net/virtio/virtio_ethdev.c              |   4 +-
 drivers/net/vmxnet3/vmxnet3_ethdev.c            |   6 +-
 lib/librte_eal/bsdapp/eal/eal.c                 |  12 +-
 lib/librte_eal/bsdapp/eal/eal_pci.c             |  53 +-
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |  18 +-
 lib/librte_eal/common/Makefile                  |   2 +-
 lib/librte_eal/common/eal_common_bus.c          | 285 ++++++++++
 lib/librte_eal/common/eal_common_pci.c          | 335 +++++++-----
 lib/librte_eal/common/eal_private.h             |  14 +-
 lib/librte_eal/common/include/rte_bus.h         | 262 +++++++++
 lib/librte_eal/common/include/rte_common.h      |  20 +
 lib/librte_eal/common/include/rte_dev.h         |  14 +
 lib/librte_eal/common/include/rte_pci.h         |  32 +-
 lib/librte_eal/linuxapp/eal/Makefile            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c               |  12 +-
 lib/librte_eal/linuxapp/eal/eal_pci.c           |  82 +--
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |  18 +-
 lib/librte_ether/rte_ethdev.c                   |  16 +-
 lib/librte_ether/rte_ethdev.h                   |   6 +-
 39 files changed, 1717 insertions(+), 291 deletions(-)
 create mode 100644 app/test/test_bus.c
 create mode 100644 lib/librte_eal/common/eal_common_bus.c
 create mode 100644 lib/librte_eal/common/include/rte_bus.h

-- 
2.7.4

^ permalink raw reply

* Reading from a pcap file
From: Keren Hochman @ 2016-12-04  7:33 UTC (permalink / raw)
  To: dev

Hi,
When reading from a pcap file:
*--vdev eth_pcap0, rx_pcap='tmp'*
and using *rte_ring_dequeue_burst*
What is the correct way to know when the file had finished?

Thanks, Keren

^ permalink raw reply

* Filtering acording to port/cidr ip
From: Keren Hochman @ 2016-12-04  7:22 UTC (permalink / raw)
  To: dev

Hello,
Is there a way to filter packets which received by dpdk kernel or libpcap
according to ip mask and port ? I need to support fragmented ip packets and
fragmented tcp packets.
Can I use *Packet Classification* for this purpose*? *
Thank you, Keren

^ permalink raw reply

* [PATCH 29/29] net/ixgbe/base: update version of basical codes in README
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

update the version of shared codes to cid-ixgbe.2016.11.21.tar.gz,
all files in net/ixgbe/base are developped by another team and
DPDK PMD uses them accordingly.

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/README | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ixgbe/base/README b/drivers/net/ixgbe/base/README
index 6b54c31..84773ff 100644
--- a/drivers/net/ixgbe/base/README
+++ b/drivers/net/ixgbe/base/README
@@ -34,7 +34,8 @@ Intel® IXGBE driver
 ===================
 
 This directory contains source code of FreeBSD ixgbe driver of version
-cid-10g-shared-code.2016.08.15 released by ND. The sub-directory of base/
+cid-10g-shared-code.2016.08.15 released by the team which develop
+basical drivers for any ixgbe NIC. The sub-directory of base/
 contains the original source package.
 This driver is valid for the product(s) listed below
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 28/29] net/ixgbe/base: report physical layer for SGMII PHY type
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

For the PHY type SGMII, we need to report the physical layer
so the OS can display the correct link connection.

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_x550.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c
index a57ba74..782ca91 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -3693,6 +3693,9 @@ u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
 		if (hw->phy.speeds_supported & IXGBE_LINK_SPEED_10_FULL)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T;
 		break;
+	case ixgbe_phy_sgmii:
+		physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+		break;
 	default:
 		break;
 	}
-- 
2.7.4

^ permalink raw reply related

* [PATCH 27/29] net/ixgbe/base: add write flush required by Inphi
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

This patch updates Inphi configuration to flush the register write with
a reg read. Inphi is configured in ixgbe_setup_mac_link_sfp_x550a.
The Inphy setup flow has been updated to read configuration reg, write
only linear/non-linear, and then read (write flush).

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_x550.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c
index 4a98530..a57ba74 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -2834,12 +2834,26 @@ s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw,
 
 		/* Configure CS4227/CS4223 LINE side to proper mode. */
 		reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset;
+
+		ret_val = hw->phy.ops.read_reg(hw, reg_slice,
+					IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
+
+		if (ret_val != IXGBE_SUCCESS)
+			return ret_val;
+
+		reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) |
+				 (IXGBE_CS4227_EDC_MODE_SR << 1));
+
 		if (setup_linear)
 			reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
 		else
 			reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
 		ret_val = hw->phy.ops.write_reg(hw, reg_slice,
 					 IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext);
+
+		/* Flush previous write with a read */
+		ret_val = hw->phy.ops.read_reg(hw, reg_slice,
+					IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
 	}
 	return ret_val;
 }
-- 
2.7.4

^ permalink raw reply related

* [PATCH 26/29] net/ixgbe/base: remove unused old EEE code
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

remove unused old EEE code.

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_x550.c | 113 +-----------------------------------
 drivers/net/ixgbe/base/ixgbe_x550.h |   2 -
 2 files changed, 1 insertion(+), 114 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c
index 2aaed6b..4a98530 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -942,6 +942,7 @@ s32 ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw)
 				      ixgbe_write_i2c_combined_generic_unlocked;
 	link->addr = IXGBE_CS4227;
 
+
 	return ret_val;
 }
 
@@ -1109,118 +1110,6 @@ s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw)
 }
 
 /**
- * ixgbe_enable_eee_x550 - Enable EEE support
- * @hw: pointer to hardware structure
- */
-STATIC s32 ixgbe_enable_eee_x550(struct ixgbe_hw *hw)
-{
-	u32 link_reg;
-	s32 status;
-
-	switch (hw->device_id) {
-	case IXGBE_DEV_ID_X550EM_A_KR:
-	case IXGBE_DEV_ID_X550EM_A_KR_L:
-		status = hw->mac.ops.read_iosf_sb_reg(hw,
-					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg);
-		if (status != IXGBE_SUCCESS)
-			return status;
-
-		link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR |
-			    IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX;
-
-		/* Don't advertise FEC capability when EEE enabled. */
-		link_reg &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC;
-
-		status = hw->mac.ops.write_iosf_sb_reg(hw,
-					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-					IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
-		if (status != IXGBE_SUCCESS)
-			return status;
-		break;
-	default:
-		break;
-	}
-
-	return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_disable_eee_x550 - Disable EEE support
- * @hw: pointer to hardware structure
- */
-STATIC s32 ixgbe_disable_eee_x550(struct ixgbe_hw *hw)
-{
-	u32 link_reg;
-	s32 status;
-
-	switch (hw->device_id) {
-	case IXGBE_DEV_ID_X550EM_X_KR:
-	case IXGBE_DEV_ID_X550EM_A_KR:
-	case IXGBE_DEV_ID_X550EM_A_KR_L:
-		status = hw->mac.ops.read_iosf_sb_reg(hw,
-					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg);
-		if (status != IXGBE_SUCCESS)
-			return status;
-
-		link_reg &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR |
-			      IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX);
-
-		/* Advertise FEC capability when EEE is disabled. */
-		link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC;
-
-		status = hw->mac.ops.write_iosf_sb_reg(hw,
-					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-					IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg);
-		if (status != IXGBE_SUCCESS)
-			return status;
-		break;
-	default:
-		break;
-	}
-
-	return IXGBE_SUCCESS;
-}
-
-/**
- *  ixgbe_setup_eee_X550 - Enable/disable EEE support
- *  @hw: pointer to the HW structure
- *  @enable_eee: boolean flag to enable EEE
- *
- *  Enable/disable EEE based on enable_eee flag.
- *  Auto-negotiation must be started after BASE-T EEE bits in PHY register 7.3C
- *  are modified.
- *
- **/
-s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee)
-{
-	s32 status;
-	u32 eeer;
-
-	DEBUGFUNC("ixgbe_setup_eee_X550");
-
-	eeer = IXGBE_READ_REG(hw, IXGBE_EEER);
-	/* Enable or disable EEE per flag */
-	if (enable_eee) {
-		eeer |= (IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
-
-		status = ixgbe_enable_eee_x550(hw);
-		if (status)
-			return status;
-	} else {
-		eeer &= ~(IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN);
-
-		status = ixgbe_disable_eee_x550(hw);
-		if (status)
-			return status;
-	}
-	IXGBE_WRITE_REG(hw, IXGBE_EEER, eeer);
-
-	return IXGBE_SUCCESS;
-}
-
-/**
  * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning
  * @hw: pointer to hardware structure
  * @enable: enable or disable source address pruning
diff --git a/drivers/net/ixgbe/base/ixgbe_x550.h b/drivers/net/ixgbe/base/ixgbe_x550.h
index 2d1876b..30ca5df 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.h
+++ b/drivers/net/ixgbe/base/ixgbe_x550.h
@@ -57,8 +57,6 @@ s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset,
 u16				*data);
 s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset,
 				    u16 data);
-s32 ixgbe_set_eee_X550(struct ixgbe_hw *hw, bool enable_eee);
-s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee);
 void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable,
 					   unsigned int pool);
 void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
-- 
2.7.4

^ permalink raw reply related

* [PATCH 25/29] net/ixgbe/base: fix incorrect IXGBE LSWFW register
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

This register was incorrect when compared to the data sheet.
Even though the Linux kernel and DPDK polling mode driver doesn't
currently use this register, it is better to fix it upstream.

Fixes: af75078fece3 ("first public release")

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_type.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h
index f1761a3..49b71c5 100644
--- a/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/drivers/net/ixgbe/base/ixgbe_type.h
@@ -153,7 +153,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define IXGBE_DEV_ID_X550EM_X_VF		0x15A8
 #define IXGBE_DEV_ID_X550EM_X_VF_HV		0x15A9
 
-#define IXGBE_CAT(r, m) IXGBE_##r##m
+#define IXGBE_CAT(r,m) IXGBE_##r##m
 
 #define IXGBE_BY_MAC(_hw, r) ((_hw)->mvals[IXGBE_CAT(r, _IDX)])
 
@@ -1045,7 +1045,7 @@ struct ixgbe_dmac_config {
 #define IXGBE_FTFT		0x09400 /* 0x9400-0x97FC */
 #define IXGBE_METF(_i)		(0x05190 + ((_i) * 4)) /* 4 of these (0-3) */
 #define IXGBE_MDEF_EXT(_i)	(0x05160 + ((_i) * 4)) /* 8 of these (0-7) */
-#define IXGBE_LSWFW		0x15014
+#define IXGBE_LSWFW		0x15F14
 #define IXGBE_BMCIP(_i)		(0x05050 + ((_i) * 4)) /* 0x5050-0x505C */
 #define IXGBE_BMCIPVAL		0x05060
 #define IXGBE_BMCIP_IPADDR_TYPE	0x00000001
-- 
2.7.4

^ permalink raw reply related

* [PATCH 24/29] net/ixgbe/base: add EEE support for DNL-controlled PHYs
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

This patch adds EEE support for DNL-controlled PHYs. Because DNL
does not indicate EEE capability or status, this patch simply
assumes that it is supported. As soon as there is a DNL-supported
PHY that does not support EEE, there will be defects in this area
because the driver will not report the EEE status correctly.
This also deletes some now-unused definitions from an earlier
Marvell PHY implementation and combines a device ID check into a
switch statement.

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_type.h |  8 --------
 drivers/net/ixgbe/base/ixgbe_x550.c | 15 +++++++--------
 2 files changed, 7 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h
index 9ec17a9..f1761a3 100644
--- a/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/drivers/net/ixgbe/base/ixgbe_type.h
@@ -3720,14 +3720,6 @@ enum ixgbe_fc_mode {
 	ixgbe_fc_default
 };
 
-/* Master/slave control */
-enum ixgbe_ms_type {
-	ixgbe_ms_hw_default = 0,
-	ixgbe_ms_force_master,
-	ixgbe_ms_force_slave,
-	ixgbe_ms_auto
-};
-
 /* Smart Speed Settings */
 #define IXGBE_SMARTSPEED_MAX_RETRIES	3
 enum ixgbe_smart_speed {
diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c
index 49b59e7..2aaed6b 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -896,19 +896,18 @@ s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw)
 		break;
 	}
 
-	if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T) ||
-		(hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) {
+	switch (hw->device_id) {
+	case IXGBE_DEV_ID_X550EM_A_1G_T:
+	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
 		mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a;
 		mac->ops.setup_fc = ixgbe_fc_autoneg_fw;
-	}
-
-	switch (hw->device_id) {
-	case IXGBE_DEV_ID_X550EM_A_KR:
-	case IXGBE_DEV_ID_X550EM_A_KR_L:
 		mac->ops.setup_eee = ixgbe_setup_eee_fw;
+		hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
+					       IXGBE_LINK_SPEED_1GB_FULL;
+		hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
 		break;
 	default:
-		mac->ops.setup_eee = NULL;
+		break;
 	}
 
 	return ret_val;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 23/29] net/ixgbe/base: update FW PHY flow control
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

This patch removes the flow control conversion from rx and tx to pause and
asymmetric pause, as that is handled by the call to ixgbe_negotiate_fc.
Performing the conversion prior to calling ixgbe_negotiate_fc results in
an incorrect fc mode if RX only pause is selected when the link partner is
advertising TX.

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_x550.c | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c b/drivers/net/ixgbe/base/ixgbe_x550.c
index f1f1fbe..49b59e7 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -4199,7 +4199,6 @@ void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
 	ixgbe_link_speed speed;
 	bool link_up;
-	u32 fc;
 
 	/* AN should have completed when the cable was plugged in.
 	 * Look for reasons to bail out.  Bail out if:
@@ -4227,21 +4226,8 @@ void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
 		goto out;
 	}
 
-	/* Get the advertized flow control and modify it to indicate
-	 * pause and asymmetric pause instead of rx and tx
-	 */
-	fc = info[0];
-	if (fc & FW_PHY_ACT_GET_LINK_INFO_FC_RX)
-		fc ^= FW_PHY_ACT_GET_LINK_INFO_FC_TX;
-
-	/* Modify link partner's flow control to indicate pause and
-	 * asymmetric pause instead of rx and tx
-	 */
-	if (fc & FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX)
-		fc ^= FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX;
-
 	/* Negotiate the flow control */
-	status = ixgbe_negotiate_fc(hw, fc, fc,
+	status = ixgbe_negotiate_fc(hw, info[0], info[0],
 				    FW_PHY_ACT_GET_LINK_INFO_FC_RX,
 				    FW_PHY_ACT_GET_LINK_INFO_FC_TX,
 				    FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX,
-- 
2.7.4

^ permalink raw reply related

* [PATCH 22/29] net/ixgbe/base: remove unused PHY ID
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

The first PHY ID for X550 was only used on original HW and
never released. So remove these unused PHY ID.

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_phy.c  | 1 -
 drivers/net/ixgbe/base/ixgbe_type.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_phy.c b/drivers/net/ixgbe/base/ixgbe_phy.c
index 209e9d0..5ad4dfe 100644
--- a/drivers/net/ixgbe/base/ixgbe_phy.c
+++ b/drivers/net/ixgbe/base/ixgbe_phy.c
@@ -457,7 +457,6 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
 	case TN1010_PHY_ID:
 		phy_type = ixgbe_phy_tn;
 		break;
-	case X550_PHY_ID1:
 	case X550_PHY_ID2:
 	case X550_PHY_ID3:
 	case X540_PHY_ID:
diff --git a/drivers/net/ixgbe/base/ixgbe_type.h b/drivers/net/ixgbe/base/ixgbe_type.h
index 9851d84..9ec17a9 100644
--- a/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/drivers/net/ixgbe/base/ixgbe_type.h
@@ -1647,7 +1647,6 @@ struct ixgbe_dmac_config {
 #define TN1010_PHY_ID	0x00A19410
 #define TNX_FW_REV	0xB
 #define X540_PHY_ID	0x01540200
-#define X550_PHY_ID1	0x01540220
 #define X550_PHY_ID2	0x01540223
 #define X550_PHY_ID3	0x01540221
 #define X557_PHY_ID	0x01540240
-- 
2.7.4

^ permalink raw reply related

* [PATCH 21/29] net/ixgbe/base: remove unneeded MAC check
From: Wei Dai @ 2016-12-04  6:31 UTC (permalink / raw)
  To: helin.zhang, konstantin.ananyev; +Cc: dev, Wei Dai
In-Reply-To: <1480833100-48545-1-git-send-email-wei.dai@intel.com>

ixgbe_read_i2c_combined_generic_int() is only used by devices >= X550.
Set the initial value accordingly and remove the MAC check.

Signed-off-by: Wei Dai <wei.dai@intel.com>
---
 drivers/net/ixgbe/base/ixgbe_phy.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_phy.c b/drivers/net/ixgbe/base/ixgbe_phy.c
index 8901fc1..209e9d0 100644
--- a/drivers/net/ixgbe/base/ixgbe_phy.c
+++ b/drivers/net/ixgbe/base/ixgbe_phy.c
@@ -113,7 +113,7 @@ s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg,
 					u16 *val, bool lock)
 {
 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
-	int max_retry = 10;
+	int max_retry = 3;
 	int retry = 0;
 	u8 csum_byte;
 	u8 high_bits;
@@ -121,8 +121,6 @@ s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, u16 reg,
 	u8 reg_high;
 	u8 csum;
 
-	if (hw->mac.type >= ixgbe_mac_X550)
-		max_retry = 3;
 	reg_high = ((reg >> 7) & 0xFE) | 1;	/* Indicate read combined */
 	csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF);
 	csum = ~csum;
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox