[dpdk-dev,V15,2/2] pci: add driver auto bind for hot insertion
Checks
Commit Message
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@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(+)
@@ -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 "
@@ -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)
{
@@ -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.
*
@@ -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)
{