[dpdk-dev,V12,2/3] eal: add uevent pass and process function

Message ID 1516248723-16985-2-git-send-email-jia.guo@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Guo, Jia Jan. 18, 2018, 4:12 a.m. UTC
  In order to handle the uevent which have been detected from the kernel
side, add uevent process function, let hot plug event to be example to
show uevent mechanism how to pass the uevent and process the uevent.

About uevent passing and processing, add below functions in linux eal
dev layer. FreeBSD not support uevent ,so let it to be void and do not
implement in function.
a.dev_uev_parse
b.dev_uev_receive
c.dev_uev_process

Signed-off-by: Jeff Guo <jia.guo@intel.com>
---
v12->v11:
base on newer kernel driver, delete some unuse param in event subsystem
---
 lib/librte_eal/common/include/rte_dev.h |  16 +++++
 lib/librte_eal/linuxapp/eal/eal_dev.c   | 110 +++++++++++++++++++++++++++++++-
 2 files changed, 124 insertions(+), 2 deletions(-)
  

Comments

Jingjing Wu Jan. 24, 2018, 3 p.m. UTC | #1
> -----Original Message-----
> From: Guo, Jia
> Sent: Thursday, January 18, 2018 12:12 PM
> To: stephen@networkplumber.org; Richardson, Bruce <bruce.richardson@intel.com>;
> Yigit, Ferruh <ferruh.yigit@intel.com>; gaetan.rivet@6wind.com
> Cc: Ananyev, Konstantin <konstantin.ananyev@intel.com>; jblunck@infradead.org;
> shreyansh.jain@nxp.com; Wu, Jingjing <jingjing.wu@intel.com>; dev@dpdk.org; Guo, Jia
> <jia.guo@intel.com>; thomas@monjalon.net; Zhang, Helin <helin.zhang@intel.com>;
> motih@mellanox.com
> Subject: [PATCH V12 2/3] eal: add uevent pass and process function
> 
> In order to handle the uevent which have been detected from the kernel
> side, add uevent process function, let hot plug event to be example to
> show uevent mechanism how to pass the uevent and process the uevent.
> 
> About uevent passing and processing, add below functions in linux eal
> dev layer. FreeBSD not support uevent ,so let it to be void and do not
> implement in function.
> a.dev_uev_parse
> b.dev_uev_receive
> c.dev_uev_process
> 
> Signed-off-by: Jeff Guo <jia.guo@intel.com>


Reviewed-by: Jingjing Wu <jingjing.wu@intel.com>
  

Patch

diff --git a/lib/librte_eal/common/include/rte_dev.h b/lib/librte_eal/common/include/rte_dev.h
index 25e6747..b3733bf 100644
--- a/lib/librte_eal/common/include/rte_dev.h
+++ b/lib/librte_eal/common/include/rte_dev.h
@@ -51,6 +51,22 @@  extern "C" {
 
 #include <rte_log.h>
 
+#define RTE_EAL_UEV_MSG_LEN 4096
+#define RTE_EAL_UEV_MSG_ELEM_LEN 128
+
+enum rte_dev_state {
+	RTE_DEV_UNDEFINED,	/**< unknown device state */
+	RTE_DEV_FAULT,	/**< device fault or error */
+	RTE_DEV_PARSED,	/**< device has been scanned on bus*/
+	RTE_DEV_PROBED,	/**< device has been probed driver  */
+};
+
+enum rte_dev_event_subsystem {
+	RTE_DEV_EVENT_SUBSYSTEM_UIO,
+	RTE_DEV_EVENT_SUBSYSTEM_VFIO,
+	RTE_DEV_EVENT_SUBSYSTEM_MAX
+};
+
 /**
  * The device event type.
  */
diff --git a/lib/librte_eal/linuxapp/eal/eal_dev.c b/lib/librte_eal/linuxapp/eal/eal_dev.c
index f243c2e..31c7da8 100644
--- a/lib/librte_eal/linuxapp/eal/eal_dev.c
+++ b/lib/librte_eal/linuxapp/eal/eal_dev.c
@@ -79,10 +79,116 @@  dev_monitor_enable(int netlink_fd)
 	return -1;
 }
 
+static void
+dev_uev_parse(const char *buf, struct rte_dev_event *event)
+{
+	char action[RTE_EAL_UEV_MSG_ELEM_LEN];
+	char subsystem[RTE_EAL_UEV_MSG_ELEM_LEN];
+	char dev_path[RTE_EAL_UEV_MSG_ELEM_LEN];
+	char pci_slot_name[RTE_EAL_UEV_MSG_ELEM_LEN];
+	int i = 0;
+
+	memset(action, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
+	memset(subsystem, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
+	memset(dev_path, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
+	memset(pci_slot_name, 0, RTE_EAL_UEV_MSG_ELEM_LEN);
+
+	while (i < RTE_EAL_UEV_MSG_LEN) {
+		for (; i < RTE_EAL_UEV_MSG_LEN; i++) {
+			if (*buf)
+				break;
+			buf++;
+		}
+		if (!strncmp(buf, "libudev", 7)) {
+			buf += 7;
+			i += 7;
+			return;
+		}
+		if (!strncmp(buf, "ACTION=", 7)) {
+			buf += 7;
+			i += 7;
+			snprintf(action, sizeof(action), "%s", buf);
+		} else if (!strncmp(buf, "DEVPATH=", 8)) {
+			buf += 8;
+			i += 8;
+			snprintf(dev_path, sizeof(dev_path), "%s", buf);
+		} else if (!strncmp(buf, "SUBSYSTEM=", 10)) {
+			buf += 10;
+			i += 10;
+			snprintf(subsystem, sizeof(subsystem), "%s", buf);
+		} else if (!strncmp(buf, "PCI_SLOT_NAME=", 14)) {
+			buf += 14;
+			i += 14;
+			snprintf(pci_slot_name, sizeof(subsystem), "%s", buf);
+			event->devname = pci_slot_name;
+		}
+		for (; i < RTE_EAL_UEV_MSG_LEN; i++) {
+			if (*buf == '\0')
+				break;
+			buf++;
+		}
+	}
+
+	if (!strncmp(subsystem, "pci", 3))
+		event->subsystem = RTE_DEV_EVENT_SUBSYSTEM_UIO;
+	if (!strncmp(action, "add", 3))
+		event->type = RTE_DEV_EVENT_ADD;
+	if (!strncmp(action, "remove", 6))
+		event->type = RTE_DEV_EVENT_REMOVE;
+	event->devname = pci_slot_name;
+}
+
+static int
+dev_uev_receive(int fd, struct rte_dev_event *uevent)
+{
+	int ret;
+	char buf[RTE_EAL_UEV_MSG_LEN];
+
+	memset(uevent, 0, sizeof(struct rte_dev_event));
+	memset(buf, 0, RTE_EAL_UEV_MSG_LEN);
+
+	ret = recv(fd, buf, RTE_EAL_UEV_MSG_LEN - 1, MSG_DONTWAIT);
+	if (ret < 0) {
+		RTE_LOG(ERR, EAL,
+		"Socket read error(%d): %s\n",
+		errno, strerror(errno));
+		return -1;
+	} else if (ret == 0)
+		/* connection closed */
+		return -1;
+
+	dev_uev_parse(buf, uevent);
+
+	return 0;
+}
+
 static int
-dev_uev_process(__rte_unused struct epoll_event *events, __rte_unused int nfds)
+dev_uev_process(struct epoll_event *events, int nfds)
 {
-	/* TODO: device uevent processing */
+	struct rte_dev_event uevent;
+	int i;
+
+	for (i = 0; i < nfds; i++) {
+		/**
+		 * check device uevent from kernel side, no need to check
+		 * uevent from udev.
+		 */
+		if (dev_uev_receive(events[i].data.fd, &uevent))
+			return 0;
+
+		/* default handle all pci devcie when is being hot plug */
+		if (uevent.subsystem == RTE_DEV_EVENT_SUBSYSTEM_UIO) {
+			if (uevent.type == RTE_DEV_EVENT_REMOVE) {
+				return(_rte_dev_callback_process(
+					uevent.devname,
+					RTE_DEV_EVENT_REMOVE, NULL));
+			} else if (uevent.type == RTE_DEV_EVENT_ADD) {
+				return(_rte_dev_callback_process(
+					uevent.devname,
+					RTE_DEV_EVENT_ADD, NULL));
+			}
+		}
+	}
 	return 0;
 }