[dpdk-dev] [PATCH v1 11/28] eal/soc: implement probing of drivers

Jan Viktorin viktorin at rehivetech.com
Fri May 6 15:47:53 CEST 2016


Signed-off-by: Jan Viktorin <viktorin at rehivetech.com>
---
 lib/librte_eal/bsdapp/eal/rte_eal_version.map   |   3 +
 lib/librte_eal/common/eal_common_soc.c          | 200 ++++++++++++++++++++++++
 lib/librte_eal/common/include/rte_soc.h         |  25 +++
 lib/librte_eal/linuxapp/eal/eal.c               |   4 +
 lib/librte_eal/linuxapp/eal/rte_eal_version.map |   3 +
 5 files changed, 235 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 4a2eeaf..bd3dd11 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -163,5 +163,8 @@ DPDK_16.07 {
 	rte_eal_soc_unregister;
 	rte_eal_soc_scan;
 	rte_eal_soc_dump;
+	rte_eal_soc_detach;
+	rte_eal_soc_probe;
+	rte_eal_soc_probe_one;
 
 } DPDK_16.04;
diff --git a/lib/librte_eal/common/eal_common_soc.c b/lib/librte_eal/common/eal_common_soc.c
index d8bb6d6..d8f0c00 100644
--- a/lib/librte_eal/common/eal_common_soc.c
+++ b/lib/librte_eal/common/eal_common_soc.c
@@ -36,6 +36,8 @@
 #include <sys/queue.h>
 
 #include <rte_log.h>
+#include <rte_common.h>
+#include <rte_soc.h>
 
 #include "eal_private.h"
 
@@ -58,6 +60,204 @@ const char *soc_get_sysfs_path(void)
 	return path;
 }
 
+static int soc_id_match(const struct rte_soc_id *drv_id,
+		const struct rte_soc_id *dev_id)
+{
+	int i;
+	int j;
+
+	RTE_VERIFY(drv_id != NULL);
+	RTE_VERIFY(dev_id != NULL);
+
+	for (i = 0; drv_id[i].compatible; ++i) {
+		const char *drv_compat = drv_id[i].compatible;
+
+		for (j = 0; dev_id[j].compatible; ++j) {
+			const char *dev_compat = dev_id[j].compatible;
+
+			if (!strcmp(drv_compat, dev_compat))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int
+rte_eal_soc_probe_one_driver(struct rte_soc_driver *dr,
+		struct rte_soc_device *dev)
+{
+	int ret;
+
+	if (!soc_id_match(dr->id_table, dev->id))
+		return 1;
+
+	RTE_LOG(DEBUG, EAL, "SoC device %s\n",
+			dev->addr.name);
+	RTE_LOG(DEBUG, EAL, "  probe driver %s\n", dr->name);
+
+	dev->driver = dr;
+	RTE_VERIFY(dr->devinit != NULL);
+	return dr->devinit(dr, dev);
+}
+
+static int
+soc_probe_all_drivers(struct rte_soc_device *dev)
+{
+	struct rte_soc_driver *dr = NULL;
+	int rc = 0;
+
+	if (dev == NULL)
+		return -1;
+
+	TAILQ_FOREACH(dr, &soc_driver_list, next) {
+		rc = rte_eal_soc_probe_one_driver(dr, dev);
+		if (rc < 0)
+			/* negative value is an error */
+			return -1;
+		if (rc > 0)
+			/* positive value means driver doesn't support it */
+			continue;
+		return 0;
+	}
+	return 1;
+}
+
+/* If the IDs match, call the devuninit() function of the driver. */
+static int
+rte_eal_soc_detach_dev(struct rte_soc_driver *dr,
+		struct rte_soc_device *dev)
+{
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	if (!soc_id_match(dr->id_table, dev->id))
+		return 1;
+
+	RTE_LOG(DEBUG, EAL, "SoC device %s\n",
+			dev->addr.name);
+
+	RTE_LOG(DEBUG, EAL, "  remove driver: %s\n", dr->name);
+
+	if (dr->devuninit && (dr->devuninit(dev) < 0))
+		return -1;	/* negative value is an error */
+
+	/* clear driver structure */
+	dev->driver = NULL;
+
+	return 0;
+}
+
+/*
+ * Call the devuninit() function of all registered drivers for the given
+ * device if their IDs match.
+ *
+ * @return
+ *       0 when successful
+ *      -1 if deinitialization fails
+ *       1 if no driver is found for this device.
+ */
+static int
+soc_detach_all_drivers(struct rte_soc_device *dev)
+{
+	struct rte_soc_driver *dr = NULL;
+	int rc = 0;
+
+	if (dev == NULL)
+		return -1;
+
+	TAILQ_FOREACH(dr, &soc_driver_list, next) {
+		rc = rte_eal_soc_detach_dev(dr, dev);
+		if (rc < 0)
+			/* negative value is an error */
+			return -1;
+		if (rc > 0)
+			/* positive value means driver doesn't support it */
+			continue;
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * Detach device specified by its SoC address.
+ */
+int
+rte_eal_soc_detach(const struct rte_soc_addr *addr)
+{
+	struct rte_soc_device *dev = NULL;
+	int ret = 0;
+
+	if (addr == NULL)
+		return -1;
+
+	TAILQ_FOREACH(dev, &soc_device_list, next) {
+		if (rte_eal_compare_soc_addr(&dev->addr, addr))
+			continue;
+
+		ret = soc_detach_all_drivers(dev);
+		if (ret < 0)
+			goto err_return;
+
+		TAILQ_REMOVE(&soc_device_list, dev, next);
+		return 0;
+	}
+	return -1;
+
+err_return:
+	RTE_LOG(WARNING, EAL, "Requested device %s cannot be used\n",
+			dev->addr.name);
+	return -1;
+}
+
+int
+rte_eal_soc_probe_one(const struct rte_soc_addr *addr)
+{
+	struct rte_soc_device *dev = NULL;
+	int ret = 0;
+
+	if (addr == NULL)
+		return -1;
+
+	TAILQ_FOREACH(dev, &soc_device_list, next) {
+		if (rte_eal_compare_soc_addr(&dev->addr, addr))
+			continue;
+
+		ret = soc_probe_all_drivers(dev);
+		if (ret < 0)
+			goto err_return;
+		return 0;
+	}
+	return -1;
+
+err_return:
+	RTE_LOG(WARNING, EAL,
+		"Requested device %s cannot be used\n", addr->name);
+	return -1;
+}
+
+/*
+ * Scan the SoC devices and call the devinit() function for all registered
+ * drivers that have a matching entry in its id_table for discovered devices.
+ */
+int
+rte_eal_soc_probe(void)
+{
+	struct rte_soc_device *dev = NULL;
+	int probe_all = 0;
+	int ret = 0;
+
+	TAILQ_FOREACH(dev, &soc_device_list, next) {
+
+		ret = soc_probe_all_drivers(dev);
+		if (ret < 0)
+			rte_exit(EXIT_FAILURE, "Requested device %s"
+				 " cannot be used\n", dev->addr.name);
+	}
+
+	return 0;
+}
+
 /* dump one device */
 static int
 soc_dump_one_device(FILE *f, struct rte_soc_device *dev)
diff --git a/lib/librte_eal/common/include/rte_soc.h b/lib/librte_eal/common/include/rte_soc.h
index 6278295..4117ffb 100644
--- a/lib/librte_eal/common/include/rte_soc.h
+++ b/lib/librte_eal/common/include/rte_soc.h
@@ -147,6 +147,31 @@ rte_eal_compare_soc_addr(const struct rte_soc_addr *a0,
 int rte_eal_soc_scan(void);
 
 /**
+ * Probe SoC devices for registered drivers.
+ */
+int rte_eal_soc_probe(void);
+
+/**
+ * Probe the single SoC device.
+ */
+int rte_eal_soc_probe_one(const struct rte_soc_addr *addr);
+
+/**
+ * Close the single SoC device.
+ *
+ * Scan the SoC devices and find the SoC device specified by the SoC
+ * address, then call the devuninit() function for registered driver
+ * that has a matching entry in its id_table for discovered device.
+ *
+ * @param addr
+ *	The SoC address to close.
+ * @return
+ *   - 0 on success.
+ *   - Negative on error.
+ */
+int rte_eal_soc_detach(const struct rte_soc_addr *addr);
+
+/**
  * Dump discovered SoC devices.
  */
 void rte_eal_soc_dump(FILE *f);
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 5f190ff..e697bb0 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -896,6 +896,10 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_pci_probe())
 		rte_panic("Cannot probe PCI\n");
 
+	/* Probe & Initialize SoC devices */
+	if (rte_eal_soc_probe())
+		rte_panic("Cannot probe SoC\n");
+
 	rte_eal_mcfg_complete();
 
 	return fctret;
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 280622f..811cbf8 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -168,5 +168,8 @@ DPDK_16.07 {
 	rte_eal_soc_unregister;
 	rte_eal_soc_scan;
 	rte_eal_soc_dump;
+	rte_eal_soc_detach;
+	rte_eal_soc_probe;
+	rte_eal_soc_probe_one;
 
 } DPDK_16.04;
-- 
2.8.0



More information about the dev mailing list