DPDK patches and discussions
 help / color / mirror / Atom feed
From: Chenbo Xia <chenbo.xia@intel.com>
To: dev@dpdk.org, thomas@monjalon.net, david.marchand@redhat.com
Cc: stephen@networkplumber.org, cunming.liang@intel.com,
	xiuchun.lu@intel.com, miao.li@intel.com, jingjing.wu@intel.com,
	beilei.xing@intel.com
Subject: [dpdk-dev] [PATCH v2 5/9] vfio_user: implement interrupt related APIs
Date: Thu, 14 Jan 2021 14:14:07 +0800	[thread overview]
Message-ID: <20210114061411.39166-6-chenbo.xia@intel.com> (raw)
In-Reply-To: <20210114061411.39166-1-chenbo.xia@intel.com>

This patch implements two interrupt related APIs, which are
rte_vfio_user_get_irq() and rte_vfio_user_set_irq_info().
The former is for devices to get interrupt configuration
(e.g., irqfds). The latter is for setting interrupt information
before vfio-user starts.

Signed-off-by: Chenbo Xia <chenbo.xia@intel.com>
Signed-off-by: Xiuchun Lu <xiuchun.lu@intel.com>
---
 lib/librte_vfio_user/rte_vfio_user.h    |  46 ++++
 lib/librte_vfio_user/version.map        |   2 +
 lib/librte_vfio_user/vfio_user_base.h   |   8 +
 lib/librte_vfio_user/vfio_user_server.c | 300 +++++++++++++++++++++++-
 lib/librte_vfio_user/vfio_user_server.h |   6 +
 5 files changed, 357 insertions(+), 5 deletions(-)

diff --git a/lib/librte_vfio_user/rte_vfio_user.h b/lib/librte_vfio_user/rte_vfio_user.h
index f575017bdf..472ca15529 100644
--- a/lib/librte_vfio_user/rte_vfio_user.h
+++ b/lib/librte_vfio_user/rte_vfio_user.h
@@ -69,6 +69,11 @@ struct rte_vfio_user_regions {
 	struct rte_vfio_user_reg_info reg_info[];
 };
 
+struct rte_vfio_user_irq_info {
+	uint32_t irq_num;
+	struct vfio_irq_info irq_info[];
+};
+
 /**
  *  Below APIs are for vfio-user server (device provider) to use:
  *	*rte_vfio_user_register
@@ -76,8 +81,10 @@ struct rte_vfio_user_regions {
  *	*rte_vfio_user_start
  *	*rte_vfio_get_sock_addr
  *	*rte_vfio_user_get_mem_table
+ *	*rte_vfio_user_get_irq
  *	*rte_vfio_user_set_dev_info
  *	*rte_vfio_user_set_reg_info
+ *	*rte_vfio_user_set_irq_info
  */
 
 /**
@@ -188,4 +195,43 @@ __rte_experimental
 int
 rte_vfio_get_sock_addr(int dev_id, char *buf, size_t len);
 
+/**
+ * Get the irqfds of a vfio-user device.
+ *
+ * @param dev_id
+ *   Vfio-user device ID
+ * @param index
+ *   irq index
+ * @param count
+ *   irq count
+ * @param[out] fds
+ *   Pointer to the irqfds
+ * @return
+ *   0 on success, -1 on failure
+ */
+__rte_experimental
+int
+rte_vfio_user_get_irq(int dev_id, uint32_t index, uint32_t count,
+	int *fds);
+
+/**
+ * Set the irq information for a vfio-user device.
+ *
+ * This information must be set before calling rte_vfio_user_start, and should
+ * not be updated after start. Update after start can be done by unregistration
+ * and re-registration, and then the device-level change can be detected by
+ * vfio-user client.
+ *
+ * @param sock_addr
+ *   Unix domain socket address
+ * @param irq
+ *   IRQ information for the vfio-user device
+ * @return
+ *   0 on success, -1 on failure
+ */
+__rte_experimental
+int
+rte_vfio_user_set_irq_info(const char *sock_addr,
+	struct rte_vfio_user_irq_info *irq);
+
 #endif
diff --git a/lib/librte_vfio_user/version.map b/lib/librte_vfio_user/version.map
index 3a50b5ef0e..621a51a9fc 100644
--- a/lib/librte_vfio_user/version.map
+++ b/lib/librte_vfio_user/version.map
@@ -6,8 +6,10 @@ EXPERIMENTAL {
 	rte_vfio_user_start;
 	rte_vfio_get_sock_addr;
 	rte_vfio_user_get_mem_table;
+	rte_vfio_user_get_irq;
 	rte_vfio_user_set_dev_info;
 	rte_vfio_user_set_reg_info;
+	rte_vfio_user_set_irq_info;
 
 	local: *;
 };
diff --git a/lib/librte_vfio_user/vfio_user_base.h b/lib/librte_vfio_user/vfio_user_base.h
index dd13170298..1780db4322 100644
--- a/lib/librte_vfio_user/vfio_user_base.h
+++ b/lib/librte_vfio_user/vfio_user_base.h
@@ -61,6 +61,12 @@ struct vfio_user_reg {
 	uint8_t rsvd[VFIO_USER_MAX_RSVD];
 };
 
+struct vfio_user_irq_set {
+	struct vfio_irq_set set;
+	/* Reserved for data of irq set */
+	uint8_t rsvd[VFIO_USER_MAX_RSVD];
+};
+
 struct vfio_user_reg_rw {
 	uint64_t reg_offset;
 	uint32_t reg_idx;
@@ -83,6 +89,8 @@ struct vfio_user_msg {
 		struct rte_vfio_user_mem_reg memory[VFIO_USER_MSG_MAX_NREG];
 		struct vfio_device_info dev_info;
 		struct vfio_user_reg reg_info;
+		struct vfio_irq_info irq_info;
+		struct vfio_user_irq_set irq_set;
 		struct vfio_user_reg_rw reg_rw;
 	} payload;
 	int fds[VFIO_USER_MAX_FD];
diff --git a/lib/librte_vfio_user/vfio_user_server.c b/lib/librte_vfio_user/vfio_user_server.c
index 9e98b4ec81..104a0abb77 100644
--- a/lib/librte_vfio_user/vfio_user_server.c
+++ b/lib/librte_vfio_user/vfio_user_server.c
@@ -9,6 +9,7 @@
 #include <sys/socket.h>
 #include <sys/mman.h>
 #include <sys/un.h>
+#include <sys/eventfd.h>
 
 #include "vfio_user_server.h"
 
@@ -310,6 +311,150 @@ vfio_user_device_get_reg_info(struct vfio_user_server *dev,
 	return 0;
 }
 
+static int
+vfio_user_device_get_irq_info(struct vfio_user_server *dev,
+	struct vfio_user_msg *msg)
+{
+	struct vfio_irq_info *irq_info = &msg->payload.irq_info;
+	struct rte_vfio_user_irq_info *info = dev->irqs.info;
+	uint32_t i;
+
+	if (vfio_user_check_msg_fdnum(msg, 0) != 0)
+		return -EINVAL;
+
+	for (i = 0; i < info->irq_num; i++) {
+		if (irq_info->index == info->irq_info[i].index) {
+			irq_info->count = info->irq_info[i].count;
+			irq_info->flags |= info->irq_info[i].flags;
+			break;
+		}
+	}
+	if (i == info->irq_num)
+		return -EINVAL;
+
+	VFIO_USER_LOG(DEBUG, "IRQ info: argsz(0x%x), flags(0x%x), index(0x%x),"
+		" count(0x%x)\n", irq_info->argsz, irq_info->flags,
+		irq_info->index, irq_info->count);
+
+	return 0;
+}
+
+static inline int
+irq_set_trigger(struct vfio_user_irqs *irqs,
+	struct vfio_irq_set *irq_set, struct vfio_user_msg *msg)
+{
+	uint32_t i = irq_set->start;
+	int eventfd;
+
+	switch (irq_set->flags & VFIO_IRQ_SET_DATA_TYPE_MASK) {
+	case VFIO_IRQ_SET_DATA_NONE:
+		if (vfio_user_check_msg_fdnum(msg, 0) != 0)
+			return -EINVAL;
+
+		for (; i < irq_set->start + irq_set->count; i++) {
+			eventfd = irqs->fds[irq_set->index][i];
+			if (eventfd >= 0) {
+				if (eventfd_write(eventfd, (eventfd_t)1))
+					return -errno;
+			}
+		}
+		break;
+	case VFIO_IRQ_SET_DATA_BOOL:
+		if (vfio_user_check_msg_fdnum(msg, 0) != 0)
+			return -EINVAL;
+
+		uint8_t *idx = irq_set->data;
+		for (; i < irq_set->start + irq_set->count; i++, idx++) {
+			eventfd = irqs->fds[irq_set->index][i];
+			if (eventfd >= 0 && *idx == 1) {
+				if (eventfd_write(eventfd, (eventfd_t)1))
+					return -errno;
+			}
+		}
+		break;
+	case VFIO_IRQ_SET_DATA_EVENTFD:
+		if (vfio_user_check_msg_fdnum(msg, irq_set->count) != 0)
+			return -EINVAL;
+
+		int32_t *fds = msg->fds;
+		for (; i < irq_set->start + irq_set->count; i++, fds++) {
+			eventfd = irqs->fds[irq_set->index][i];
+			if (eventfd >= 0)
+				close(eventfd); /* Clear original irqfd*/
+			if (*fds >= 0)
+				irqs->fds[irq_set->index][i] = *fds;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void
+vfio_user_disable_irqs(struct vfio_user_irqs *irqs)
+{
+	struct rte_vfio_user_irq_info *info = irqs->info;
+	uint32_t i, j;
+
+	for (i = 0; i < info->irq_num; i++) {
+		for (j = 0; j < info->irq_info[i].count; j++) {
+			if (irqs->fds[i][j] != -1) {
+				close(irqs->fds[i][j]);
+				irqs->fds[i][j] = -1;
+			}
+		}
+	}
+}
+
+static int
+vfio_user_device_set_irqs(struct vfio_user_server *dev,
+	struct vfio_user_msg *msg)
+{
+	struct vfio_user_irq_set *irq = &msg->payload.irq_set;
+	struct vfio_irq_set *irq_set = &irq->set;
+	struct rte_vfio_user_irq_info *info = dev->irqs.info;
+	int ret = 0;
+
+	if (info->irq_num <= irq_set->index
+		|| info->irq_info[irq_set->index].count <
+		irq_set->start + irq_set->count) {
+		vfio_user_close_msg_fds(msg);
+		return -EINVAL;
+	}
+
+	if (irq_set->count == 0) {
+		if (irq_set->flags & VFIO_IRQ_SET_DATA_NONE) {
+			vfio_user_disable_irqs(&dev->irqs);
+			return 0;
+		}
+		vfio_user_close_msg_fds(msg);
+		return -EINVAL;
+	}
+
+	switch (irq_set->flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+	/* Mask/Unmask not supported for now */
+	case VFIO_IRQ_SET_ACTION_MASK:
+		/* FALLTHROUGH */
+	case VFIO_IRQ_SET_ACTION_UNMASK:
+		return 0;
+	case VFIO_IRQ_SET_ACTION_TRIGGER:
+		ret = irq_set_trigger(&dev->irqs, irq_set, msg);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	VFIO_USER_LOG(DEBUG, "Set IRQ: argsz(0x%x), flags(0x%x), index(0x%x), "
+		"start(0x%x), count(0x%x)\n", irq_set->argsz, irq_set->flags,
+		irq_set->index, irq_set->start, irq_set->count);
+
+	/* Do not reply fds back */
+	msg->fd_num = 0;
+	return ret;
+}
+
 static int
 vfio_user_region_read(struct vfio_user_server *dev,
 	struct vfio_user_msg *msg)
@@ -421,6 +566,50 @@ vfio_user_destroy_mem(struct vfio_user_server *dev)
 	dev->mem = NULL;
 }
 
+static inline void
+vfio_user_destroy_irq(struct vfio_user_server *dev)
+{
+	struct vfio_user_irqs *irq = &dev->irqs;
+	int *fd;
+	uint32_t i, j;
+
+	if (!irq->info)
+		return;
+
+	for (i = 0; i < irq->info->irq_num; i++) {
+		fd = irq->fds[i];
+
+		for (j = 0; j < irq->info->irq_info[i].count; j++) {
+			if (fd[j] != -1)
+				close(fd[j]);
+		}
+
+		free(fd);
+	}
+
+	free(irq->fds);
+}
+
+static inline void
+vfio_user_clean_irqfd(struct vfio_user_server *dev)
+{
+	struct vfio_user_irqs *irq = &dev->irqs;
+	int *fd;
+	uint32_t i, j;
+
+	if (!irq->info)
+		return;
+
+	for (i = 0; i < irq->info->irq_num; i++) {
+		fd = irq->fds[i];
+
+		for (j = 0; j < irq->info->irq_info[i].count; j++) {
+			close(fd[j]);
+			fd[j] = -1;
+		}
+	}
+}
+
 static int
 vfio_user_device_reset(struct vfio_user_server *dev,
 	struct vfio_user_msg *msg)
@@ -436,6 +625,7 @@ vfio_user_device_reset(struct vfio_user_server *dev,
 		return -ENOTSUP;
 
 	vfio_user_destroy_mem_entries(dev->mem);
+	vfio_user_clean_irqfd(dev);
 	dev->is_ready = 0;
 
 	if (dev->ops->reset_device)
@@ -451,8 +641,8 @@ static vfio_user_msg_handler_t vfio_user_msg_handlers[VFIO_USER_MAX] = {
 	[VFIO_USER_DMA_UNMAP] = vfio_user_dma_unmap,
 	[VFIO_USER_DEVICE_GET_INFO] = vfio_user_device_get_info,
 	[VFIO_USER_DEVICE_GET_REGION_INFO] = vfio_user_device_get_reg_info,
-	[VFIO_USER_DEVICE_GET_IRQ_INFO] = NULL,
-	[VFIO_USER_DEVICE_SET_IRQS] = NULL,
+	[VFIO_USER_DEVICE_GET_IRQ_INFO] = vfio_user_device_get_irq_info,
+	[VFIO_USER_DEVICE_SET_IRQS] = vfio_user_device_set_irqs,
 	[VFIO_USER_REGION_READ] = vfio_user_region_read,
 	[VFIO_USER_REGION_WRITE] = vfio_user_region_write,
 	[VFIO_USER_DMA_READ] = NULL,
@@ -856,6 +1046,7 @@ vfio_user_message_handler(int dev_id, int fd)
 	 * to avoid errors in data path handling
 	 */
 	if ((cmd == VFIO_USER_DMA_MAP || cmd == VFIO_USER_DMA_UNMAP ||
+		cmd == VFIO_USER_DEVICE_SET_IRQS ||
 		cmd == VFIO_USER_DEVICE_RESET)
 		&& dev->ops->lock_dp) {
 		dev->ops->lock_dp(dev_id, 1);
@@ -898,7 +1089,8 @@ vfio_user_message_handler(int dev_id, int fd)
 		if (vfio_user_is_ready(dev) && dev->ops->new_device)
 			dev->ops->new_device(dev_id);
 	} else {
-		if ((cmd == VFIO_USER_DMA_MAP || cmd == VFIO_USER_DMA_UNMAP)
+		if ((cmd == VFIO_USER_DMA_MAP || cmd == VFIO_USER_DMA_UNMAP
+			|| cmd == VFIO_USER_DEVICE_SET_IRQS)
 			&& dev->ops->update_status)
 			dev->ops->update_status(dev_id);
 	}
@@ -926,6 +1118,7 @@ vfio_user_sock_read(int fd, void *data)
 		if (dev) {
 			dev->ops->destroy_device(dev_id);
 			vfio_user_destroy_mem_entries(dev->mem);
+			vfio_user_clean_irqfd(dev);
 			dev->is_ready = 0;
 			dev->msg_id = 0;
 		}
@@ -1023,9 +1216,9 @@ vfio_user_start_server(struct vfio_user_server_socket *sk)
 	}
 
 	/* All the info must be set before start */
-	if (!dev->dev_info || !dev->reg) {
+	if (!dev->dev_info || !dev->reg || !dev->irqs.info) {
 		VFIO_USER_LOG(ERR, "Failed to start, "
-			"dev/reg info must be set before start\n");
+			"dev/reg/irq info must be set before start\n");
 		return -1;
 	}
 
@@ -1139,6 +1332,7 @@ rte_vfio_user_unregister(const char *sock_addr)
 		return -1;
 	}
 	vfio_user_destroy_mem(dev);
+	vfio_user_destroy_irq(dev);
 	vfio_user_del_device(dev);
 
 	return 0;
@@ -1301,3 +1495,99 @@ rte_vfio_user_get_mem_table(int dev_id)
 
 	return dev->mem;
 }
+
+int
+rte_vfio_user_get_irq(int dev_id, uint32_t index, uint32_t count, int *fds)
+{
+	struct vfio_user_server *dev;
+	struct vfio_user_irqs *irqs;
+	uint32_t irq_max;
+
+	dev = vfio_user_get_device(dev_id);
+	if (!dev) {
+		VFIO_USER_LOG(ERR, "Failed to get irq info:"
+			"device %d not found.\n", dev_id);
+		return -1;
+	}
+
+	if (!fds)
+		return -1;
+
+	irqs = &dev->irqs;
+	if (index >= irqs->info->irq_num)
+		return -1;
+
+	irq_max = irqs->info->irq_info[index].count;
+	if (count > irq_max)
+		return -1;
+
+	memcpy(fds, dev->irqs.fds[index], count * sizeof(int));
+	return 0;
+}
+
+int
+rte_vfio_user_set_irq_info(const char *sock_addr,
+	struct rte_vfio_user_irq_info *irq)
+{
+	struct vfio_user_server *dev;
+	struct vfio_user_server_socket *sk;
+	uint32_t i;
+	int dev_id, ret;
+
+	if (!irq)
+		return -1;
+
+	pthread_mutex_lock(&vfio_ep_sock.mutex);
+	sk = vfio_user_find_socket(sock_addr);
+	pthread_mutex_unlock(&vfio_ep_sock.mutex);
+
+	if (!sk) {
+		VFIO_USER_LOG(ERR, "Failed to set irq info with sock_addr:"
+			"%s: addr not registered.\n", sock_addr);
+		return -1;
+	}
+
+	dev_id = sk->sock.dev_id;
+	dev = vfio_user_get_device(dev_id);
+	if (!dev) {
+		VFIO_USER_LOG(ERR, "Failed to set irq info:"
+			"device %d not found.\n", dev_id);
+		return -1;
+	}
+
+	if (dev->started) {
+		VFIO_USER_LOG(ERR, "Failed to set irq info for device %d\n"
+			 ", device already started\n", dev_id);
+		return -1;
+	}
+
+	if (dev->irqs.info)
+		vfio_user_destroy_irq(dev);
+
+	dev->irqs.info = irq;
+
+	dev->irqs.fds = malloc(irq->irq_num * sizeof(int *));
+	if (!dev->irqs.fds)
+		return -1;
+
+	for (i = 0; i < irq->irq_num; i++) {
+		uint32_t sz = irq->irq_info[i].count * sizeof(int);
+		dev->irqs.fds[i] = malloc(sz);
+		if (!dev->irqs.fds[i]) {
+			ret = -1;
+			goto exit;
+		}
+
+		memset(dev->irqs.fds[i], 0xFF, sz);
+	}
+
+	return 0;
+exit:
+	for (--i;; i--) {
+		free(dev->irqs.fds[i]);
+		if (i == 0)
+			break;
+	}
+	free(dev->irqs.fds);
+	return ret;
+}
diff --git a/lib/librte_vfio_user/vfio_user_server.h b/lib/librte_vfio_user/vfio_user_server.h
index 0b20ab4e3a..1b4ed4f47c 100644
--- a/lib/librte_vfio_user/vfio_user_server.h
+++ b/lib/librte_vfio_user/vfio_user_server.h
@@ -9,6 +9,11 @@
 
 #include "vfio_user_base.h"
 
+struct vfio_user_irqs {
+	struct rte_vfio_user_irq_info *info;
+	int **fds;
+};
+
 struct vfio_user_server {
 	int dev_id;
 	int is_ready;
@@ -21,6 +26,7 @@ struct vfio_user_server {
 	struct rte_vfio_user_mem *mem;
 	struct vfio_device_info *dev_info;
 	struct rte_vfio_user_regions *reg;
+	struct vfio_user_irqs irqs;
 };
 
 typedef int (*event_handler)(int fd, void *data);
-- 
2.17.1


  parent reply	other threads:[~2021-01-14  6:20 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-18  7:38 [dpdk-dev] [PATCH 0/9] Introduce vfio-user library Chenbo Xia
2020-12-18  7:38 ` [dpdk-dev] [PATCH 1/9] lib: introduce " Chenbo Xia
2020-12-18 17:13   ` Stephen Hemminger
2020-12-19  6:12     ` Xia, Chenbo
2020-12-18 17:17   ` Stephen Hemminger
2020-12-19  6:25     ` Xia, Chenbo
2020-12-18  7:38 ` [dpdk-dev] [PATCH 2/9] vfio_user: implement lifecycle related APIs Chenbo Xia
2021-01-05  8:34   ` Xing, Beilei
2021-01-05  9:58     ` Xia, Chenbo
2020-12-18  7:38 ` [dpdk-dev] [PATCH 3/9] vfio_user: implement device and region " Chenbo Xia
2021-01-06  5:51   ` Xing, Beilei
2021-01-06  7:50     ` Xia, Chenbo
2020-12-18  7:38 ` [dpdk-dev] [PATCH 4/9] vfio_user: implement DMA table and socket address API Chenbo Xia
2020-12-18  7:38 ` [dpdk-dev] [PATCH 5/9] vfio_user: implement interrupt related APIs Chenbo Xia
2020-12-30  1:04   ` Wu, Jingjing
2020-12-30  2:31     ` Xia, Chenbo
2020-12-18  7:38 ` [dpdk-dev] [PATCH 6/9] vfio_user: add client APIs of device attach/detach Chenbo Xia
2020-12-18  7:38 ` [dpdk-dev] [PATCH 7/9] vfio_user: add client APIs of DMA/IRQ/region Chenbo Xia
2021-01-07  2:41   ` Xing, Beilei
2021-01-07  7:26     ` Xia, Chenbo
2020-12-18  7:38 ` [dpdk-dev] [PATCH 8/9] test/vfio_user: introduce functional test Chenbo Xia
2020-12-18  7:38 ` [dpdk-dev] [PATCH 9/9] doc: add vfio-user library guide Chenbo Xia
2021-01-06  5:07   ` Xing, Beilei
2021-01-06  7:43     ` Xia, Chenbo
2020-12-18  9:37 ` [dpdk-dev] [PATCH 0/9] Introduce vfio-user library David Marchand
2020-12-18 14:07   ` Thanos Makatos
2023-06-29 16:10     ` Stephen Hemminger
2023-06-30  1:36       ` Xia, Chenbo
2021-01-14  6:14 ` [dpdk-dev] [PATCH v2 " Chenbo Xia
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 1/9] lib: introduce " Chenbo Xia
2024-02-12 22:53     ` Stephen Hemminger
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 2/9] vfio_user: implement lifecycle related APIs Chenbo Xia
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 3/9] vfio_user: implement device and region " Chenbo Xia
2021-01-14 18:48     ` David Christensen
2021-01-19  3:22       ` Xia, Chenbo
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 4/9] vfio_user: implement DMA table and socket address API Chenbo Xia
2021-01-14  6:14   ` Chenbo Xia [this message]
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 6/9] vfio_user: add client APIs of device attach/detach Chenbo Xia
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 7/9] vfio_user: add client APIs of DMA/IRQ/region Chenbo Xia
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 8/9] test/vfio_user: introduce functional test Chenbo Xia
2021-01-14 19:03     ` David Christensen
2021-01-19  3:27       ` Xia, Chenbo
2021-01-19 18:26         ` David Christensen
2021-01-14  6:14   ` [dpdk-dev] [PATCH v2 9/9] doc: add vfio-user library guide Chenbo Xia
2021-01-15  7:58   ` [dpdk-dev] [PATCH v2 0/9] Introduce vfio-user library David Marchand
2021-01-19  3:13     ` Xia, Chenbo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210114061411.39166-6-chenbo.xia@intel.com \
    --to=chenbo.xia@intel.com \
    --cc=beilei.xing@intel.com \
    --cc=cunming.liang@intel.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=jingjing.wu@intel.com \
    --cc=miao.li@intel.com \
    --cc=stephen@networkplumber.org \
    --cc=thomas@monjalon.net \
    --cc=xiuchun.lu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).