[dpdk-dev] [PATCH V15 2/2] pci: add driver auto bind for hot insertion

Jeff Guo jia.guo at intel.com
Wed Mar 21 07:11:33 CET 2018


Normally we use drivectl or dpdk-devbind.py to bind kernel driver before
application running, so if we want to automatically driver binding after
application run, need to implement a auto bind function, that would
benefit for hot insertion case, when detect hot insertion uevent of
device, user could auto bind the driver according some user policy and
then attach device, let app running smoothly when hotplug behavior occur.

Signed-off-by: Jeff Guo <jia.guo at intel.com>
---
v15->v14:
delete bind_driver in bus ops, replace to add bind_driver api in eal
dev to let app directly call
---
 app/test-pmd/testpmd.c                  | 17 ++++++++++++
 lib/librte_eal/bsdapp/eal/eal_dev.c     |  7 +++++
 lib/librte_eal/common/include/rte_dev.h | 15 ++++++++++
 lib/librte_eal/linuxapp/eal/eal_dev.c   | 49 +++++++++++++++++++++++++++++++++
 4 files changed, 88 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 1c4afea..7eb9c48 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -2174,6 +2174,18 @@ in_hotplug_list(const char *dev_name)
 	return false;
 }
 
+static enum rte_kernel_driver
+get_hotplug_driver(const char *dev_name)
+{
+	struct hotplug_request *hp_request = NULL;
+
+	TAILQ_FOREACH(hp_request, &hp_list, next) {
+		if (!strcmp(hp_request->dev_name, dev_name))
+			return hp_request->dev_kdrv;
+	}
+	return -1;
+}
+
 static int
 hotplug_list_add(struct rte_device *device, enum rte_kernel_driver device_kdrv)
 {
@@ -2226,6 +2238,11 @@ eth_uevent_callback(char *device_name, enum rte_dev_event_type type, void *arg)
 				"device removal\n");
 		break;
 	case RTE_DEV_EVENT_ADD:
+		/**
+		 * bind the driver to the device
+		 * before process of hot plug adding device
+		 */
+		rte_dev_bind_driver(dev_name, get_hotplug_driver(dev_name));
 		if (rte_eal_alarm_set(100000,
 			add_uevent_callback, dev_name))
 			fprintf(stderr, "Could not set up deferred "
diff --git a/lib/librte_eal/bsdapp/eal/eal_dev.c b/lib/librte_eal/bsdapp/eal/eal_dev.c
index a076ec7..7f8175b 100644
--- a/lib/librte_eal/bsdapp/eal/eal_dev.c
+++ b/lib/librte_eal/bsdapp/eal/eal_dev.c
@@ -33,6 +33,13 @@ rte_dev_event_monitor_stop(void)
 }
 
 int __rte_experimental
+rte_dev_bind_driver(const char *dev_name, enum rte_kernel_driver kdrv_type)
+{
+	RTE_LOG(ERR, EAL, "Not support device bind driver for FreeBSD\n");
+	return -1;
+}
+
+int __rte_experimental
 rte_dev_failure_handler(struct rte_device *dev,
 					enum rte_kernel_driver kdrv_type)
 {
diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 10a5fcf..e87639f 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -408,6 +408,21 @@ int __rte_experimental
 rte_dev_event_monitor_stop(void);
 
 /**
+ * It can be used to bind a device to a specific type of driver.
+ *
+ * @param dev_name
+ *  The device name.
+ * @param kdrv_type
+ *  The specific kernel driver's type.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value.
+ */
+int __rte_experimental
+rte_dev_bind_driver(const char *dev_name, enum rte_kernel_driver kdrv_type);
+
+/**
  * It can be used to do device failure handler to avoid
  * system core dump when failure occur.
  *
diff --git a/lib/librte_eal/linuxapp/eal/eal_dev.c b/lib/librte_eal/linuxapp/eal/eal_dev.c
index fa63105..9b4adc6 100644
--- a/lib/librte_eal/linuxapp/eal/eal_dev.c
+++ b/lib/librte_eal/linuxapp/eal/eal_dev.c
@@ -227,6 +227,55 @@ rte_dev_event_monitor_stop(void)
 }
 
 int __rte_experimental
+rte_dev_bind_driver(const char *dev_name, enum rte_kernel_driver kdrv_type)
+{
+	const char *kdrv_name;
+	char drv_override_path[1024];
+	int drv_override_fd;
+
+	if (!dev_name || !kdrv_type)
+		return -1;
+
+	switch (kdrv_type) {
+	case RTE_KDRV_IGB_UIO:
+		kdrv_name = "igb_uio";
+		break;
+	case RTE_KDRV_VFIO:
+		kdrv_name = "vfio-pci";
+		break;
+	case RTE_KDRV_UIO_GENERIC:
+		kdrv_name = "uio_pci_generic";
+		break;
+	default:
+		break;
+	}
+
+	snprintf(drv_override_path, sizeof(drv_override_path),
+		"/sys/bus/pci/devices/%s/driver_override", dev_name);
+
+	/* specify the driver for a device by writing to driver_override */
+	drv_override_fd = open(drv_override_path, O_WRONLY);
+	if (drv_override_fd < 0) {
+		RTE_LOG(ERR, EAL, "Cannot open %s: %s\n",
+			drv_override_path, strerror(errno));
+		goto err;
+	}
+
+	if (write(drv_override_fd, kdrv_name, sizeof(kdrv_name)) < 0) {
+		RTE_LOG(ERR, EAL,
+			"Error: bind failed - Cannot write "
+			"driver %s to device %s\n", kdrv_name, dev_name);
+		goto err;
+	}
+
+	close(drv_override_fd);
+	return 0;
+err:
+	close(drv_override_fd);
+	return -1;
+}
+
+int __rte_experimental
 rte_dev_failure_handler(struct rte_device *dev,
 					enum rte_kernel_driver kdrv_type)
 {
-- 
2.7.4



More information about the dev mailing list