patches for DPDK stable branches
 help / color / mirror / Atom feed
From: Wei Huang <wei.huang@intel.com>
To: dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com,
	hemant.agrawal@nxp.com
Cc: stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com,
	qi.z.zhang@intel.com, Wei Huang <wei.huang@intel.com>
Subject: [PATCH v3 3/4] raw/ifpga/base: update flash operation interface
Date: Fri, 17 Jun 2022 03:19:34 -0400	[thread overview]
Message-ID: <1655450375-10739-4-git-send-email-wei.huang@intel.com> (raw)
In-Reply-To: <1655450375-10739-1-git-send-email-wei.huang@intel.com>

In N6000 ADP platform, SPI protocol, master and QSPI flash are
transparent to host software. The SPI master implemented in PMCI
automatically converts the mailbox commands to the SPI protocol
required by SPI slave.
That means flash operation is different from old platform, new
interfaces are introduced to adapt these changes.

Signed-off-by: Wei Huang <wei.huang@intel.com>
---
 drivers/raw/ifpga/base/ifpga_api.c               |   9 +
 drivers/raw/ifpga/base/ifpga_feature_dev.h       |   2 +
 drivers/raw/ifpga/base/ifpga_fme.c               |   8 +
 drivers/raw/ifpga/base/opae_hw_api.c             |  20 ++
 drivers/raw/ifpga/base/opae_hw_api.h             |   2 +
 drivers/raw/ifpga/base/opae_intel_max10.c        | 282 +++++++++++++++++++++++
 drivers/raw/ifpga/base/opae_intel_max10.h        |  46 ++++
 drivers/raw/ifpga/base/osdep_rte/osdep_generic.h |  10 +
 8 files changed, 379 insertions(+)

diff --git a/drivers/raw/ifpga/base/ifpga_api.c b/drivers/raw/ifpga/base/ifpga_api.c
index f19cc26..098de0c 100644
--- a/drivers/raw/ifpga/base/ifpga_api.c
+++ b/drivers/raw/ifpga/base/ifpga_api.c
@@ -268,6 +268,14 @@ static int ifpga_mgr_reload(struct opae_manager *mgr, int type, int page)
 	return fpga_reload(fme, type, page);
 }
 
+static int ifpga_mgr_read_flash(struct opae_manager *mgr, u32 address,
+		u32 size, void *buf)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fme_mgr_read_flash(fme, address, size, buf);
+}
+
 struct opae_manager_ops ifpga_mgr_ops = {
 	.flash = ifpga_mgr_flash,
 	.get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info,
@@ -277,6 +285,7 @@ struct opae_manager_ops ifpga_mgr_ops = {
 	.update_flash = ifpga_mgr_update_flash,
 	.stop_flash_update = ifpga_mgr_stop_flash_update,
 	.reload = ifpga_mgr_reload,
+	.read_flash = ifpga_mgr_read_flash
 };
 
 static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset,
diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.h b/drivers/raw/ifpga/base/ifpga_feature_dev.h
index a637eb5..7a2f2e5 100644
--- a/drivers/raw/ifpga/base/ifpga_feature_dev.h
+++ b/drivers/raw/ifpga/base/ifpga_feature_dev.h
@@ -223,4 +223,6 @@ int fme_mgr_get_retimer_status(struct ifpga_fme_hw *fme,
 int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme,
 		struct opae_sensor_info *sensor,
 		unsigned int *value);
+int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address,
+		u32 size, void *buf);
 #endif /* _IFPGA_FEATURE_DEV_H_ */
diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c
index 608a352..25ff819 100644
--- a/drivers/raw/ifpga/base/ifpga_fme.c
+++ b/drivers/raw/ifpga/base/ifpga_fme.c
@@ -1658,3 +1658,11 @@ struct ifpga_feature_ops fme_pmci_ops = {
 	.init = fme_pmci_init,
 	.uinit = fme_pmci_uinit,
 };
+
+int fme_mgr_read_flash(struct ifpga_fme_hw *fme, u32 address,
+		u32 size, void *buf)
+{
+	struct intel_max10_device *max10 = fme->max10_dev;
+
+	return opae_read_flash(max10, address, size, buf);
+}
diff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c
index 87256fc..fd08326 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.c
+++ b/drivers/raw/ifpga/base/opae_hw_api.c
@@ -1041,3 +1041,23 @@ int opae_mgr_reload(struct opae_manager *mgr, int type, int page)
 
 	return -ENOENT;
 }
+/**
+ * opae_mgr_read_flash -  read flash content
+ * @mgr: targeted manager
+ * @address: the start address of flash
+ * @size: the size of flash
+ * @buf: the read buffer
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_read_flash(struct opae_manager *mgr, u32 address,
+		u32 size, void *buf)
+{
+	if (!mgr)
+		return -EINVAL;
+
+	if (mgr->ops && mgr->ops->read_flash)
+		return mgr->ops->read_flash(mgr, address, size, buf);
+
+	return -ENOENT;
+}
diff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h
index fd40e09..de1e984 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.h
+++ b/drivers/raw/ifpga/base/opae_hw_api.h
@@ -60,6 +60,7 @@ struct opae_manager_ops {
 			u64 *status);
 	int (*stop_flash_update)(struct opae_manager *mgr, int force);
 	int (*reload)(struct opae_manager *mgr, int type, int page);
+	int (*read_flash)(struct opae_manager *mgr, u32 address, u32 size, void *buf);
 };
 
 /* networking management ops in FME */
@@ -368,4 +369,5 @@ int opae_mgr_update_flash(struct opae_manager *mgr, const char *image,
 		uint64_t *status);
 int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force);
 int opae_mgr_reload(struct opae_manager *mgr, int type, int page);
+int opae_mgr_read_flash(struct opae_manager *mgr, u32 address, u32 size, void *buf);
 #endif /* _OPAE_HW_API_H_*/
diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c
index 26f323c..9c01729 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.c
+++ b/drivers/raw/ifpga/base/opae_intel_max10.c
@@ -58,6 +58,279 @@ int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset,
 	return max10_sys_write(dev, offset, temp);
 }
 
+static int n3000_bulk_raw_write(struct intel_max10_device *dev, uint32_t addr,
+	void *buf, uint32_t len)
+{
+	uint32_t v = 0;
+	uint32_t i = 0;
+	char *p = buf;
+	int ret = 0;
+
+	len = IFPGA_ALIGN(len, 4);
+
+	for (i = 0; i < len; i += 4) {
+		v = *(uint32_t *)(p + i);
+		ret = max10_reg_write(dev, addr + i, v);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to write to staging area 0x%08x [e:%d]\n",
+				addr + i, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int n3000_bulk_raw_read(struct intel_max10_device *dev,
+		uint32_t addr, void *buf, uint32_t len)
+{
+	u32 v, i;
+	char *p = buf;
+	int ret;
+
+	len = IFPGA_ALIGN(len, 4);
+
+	for (i = 0; i < len; i += 4) {
+		ret = max10_reg_read(dev, addr + i, &v);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to write to staging area 0x%08x [e:%d]\n",
+				addr + i, ret);
+			return ret;
+		}
+		*(u32 *)(p + i) = v;
+	}
+
+	return 0;
+}
+
+static int n3000_flash_read(struct intel_max10_device *dev,
+		u32 addr, void *buf, u32 size)
+{
+	if (!dev->raw_blk_ops.read_blk)
+		return -ENODEV;
+
+	return dev->raw_blk_ops.read_blk(dev, addr, buf, size);
+}
+
+static int n3000_flash_write(struct intel_max10_device *dev,
+		u32 addr, void *buf, u32 size)
+{
+	if (!dev->raw_blk_ops.write_blk)
+		return -ENODEV;
+
+	return dev->raw_blk_ops.write_blk(dev, addr, buf, size);
+}
+
+static u32
+pmci_get_write_space(struct intel_max10_device *dev, u32 size)
+{
+	u32 count, val;
+	int ret;
+
+	ret = opae_readl_poll_timeout(dev->mmio + PMCI_FLASH_CTRL, val,
+				GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) ==
+				PMCI_FIFO_MAX_WORDS,
+				PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US);
+	if (ret == -ETIMEDOUT)
+		return 0;
+
+	count = GET_FIELD(PMCI_FLASH_FIFO_SPACE, val) * 4;
+
+	return (size > count) ? count : size;
+}
+
+static void pmci_write_fifo(void __iomem *base, char *buf, size_t count)
+{
+	size_t i;
+	u32 val;
+
+	for (i = 0; i < count/4 ; i++) {
+		val = *(u32 *)(buf + i * 4);
+		writel(val, base);
+	}
+}
+
+static void pmci_read_fifo(void __iomem *base, char *buf, size_t count)
+{
+	size_t i;
+	u32 val;
+
+	for (i = 0; i < count/4; i++) {
+		val = readl(base);
+		*(u32 *)(buf + i * 4) = val;
+	}
+}
+
+static int
+__pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
+		void *buf, u32 size)
+{
+	UNUSED(addr);
+	u32 blk_size, n_offset = 0;
+
+	while (size) {
+		blk_size = pmci_get_write_space(dev, size);
+		if (blk_size == 0) {
+			dev_err(pmci->dev, "get FIFO available size fail\n");
+			return -EIO;
+		}
+		size -= blk_size;
+		pmci_write_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + n_offset,
+				blk_size);
+		n_offset += blk_size;
+	}
+
+	return 0;
+}
+
+static int
+pmci_flash_bulk_write(struct intel_max10_device *dev, u32 addr,
+		void *buf, u32 size)
+{
+	int ret;
+
+	pthread_mutex_lock(dev->bmc_ops.mutex);
+
+	ret = __pmci_flash_bulk_write(dev, addr, buf, size);
+
+	pthread_mutex_unlock(dev->bmc_ops.mutex);
+	return ret;
+}
+
+static int
+pmci_set_flash_host_mux(struct intel_max10_device *dev, bool request)
+{
+	u32 ctrl;
+	int ret;
+
+	ret = max10_sys_update_bits(dev,
+			m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL,
+			FLASH_HOST_REQUEST,
+			SET_FIELD(FLASH_HOST_REQUEST, request));
+	if (ret)
+		return ret;
+
+	return opae_max10_read_poll_timeout(dev, m10bmc_base(dev) + M10BMC_PMCI_FLASH_CTRL,
+			ctrl, request ? (get_flash_mux(ctrl) == FLASH_MUX_HOST) :
+			(get_flash_mux(ctrl) != FLASH_MUX_HOST),
+			PMCI_FLASH_INT_US, PMCI_FLASH_TIMEOUT_US);
+}
+
+static int
+pmci_get_mux(struct intel_max10_device *dev)
+{
+	pthread_mutex_lock(dev->bmc_ops.mutex);
+	return pmci_set_flash_host_mux(dev, true);
+}
+
+static int
+pmci_put_mux(struct intel_max10_device *dev)
+{
+	int ret;
+
+	ret = pmci_set_flash_host_mux(dev, false);
+	pthread_mutex_unlock(dev->bmc_ops.mutex);
+	return ret;
+}
+
+static int
+__pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
+		     void *buf, u32 size)
+{
+	u32 blk_size, offset = 0, val;
+	int ret;
+
+	while (size) {
+		blk_size = min_t(u32, size, PMCI_READ_BLOCK_SIZE);
+
+		opae_writel(addr + offset, dev->mmio + PMCI_FLASH_ADDR);
+
+		opae_writel(SET_FIELD(PMCI_FLASH_READ_COUNT, blk_size / 4)
+				| PMCI_FLASH_RD_MODE,
+			dev->mmio + PMCI_FLASH_CTRL);
+
+		ret = opae_readl_poll_timeout((dev->mmio + PMCI_FLASH_CTRL),
+				val, !(val & PMCI_FLASH_BUSY),
+				PMCI_FLASH_INT_US,
+				PMCI_FLASH_TIMEOUT_US);
+		if (ret) {
+			dev_err(dev, "%s timed out on reading flash 0x%xn",
+				__func__, val);
+			return ret;
+		}
+
+		pmci_read_fifo(dev->mmio + PMCI_FLASH_FIFO, (char *)buf + offset,
+				blk_size);
+
+		size -= blk_size;
+		offset += blk_size;
+
+		opae_writel(0, dev->mmio + PMCI_FLASH_CTRL);
+	}
+
+	return 0;
+}
+
+static int
+pmci_flash_bulk_read(struct intel_max10_device *dev, u32 addr,
+		     void *buf, u32 size)
+{
+	int ret;
+
+	ret = pmci_get_mux(dev);
+	if (ret)
+		goto fail;
+
+	ret = __pmci_flash_bulk_read(dev, addr, buf, size);
+	if (ret)
+		goto fail;
+
+	return pmci_put_mux(dev);
+
+fail:
+	pmci_put_mux(dev);
+	return ret;
+}
+
+static int pmci_check_flash_address(u32 start, u32 end)
+{
+	if (start < PMCI_FLASH_START || end > PMCI_FLASH_END)
+		return -EINVAL;
+
+	return 0;
+}
+
+int opae_read_flash(struct intel_max10_device *dev, u32 addr,
+		u32 size, void *buf)
+{
+	int ret;
+
+	if (!dev->bmc_ops.flash_read)
+		return -ENODEV;
+
+	if (!buf)
+		return -EINVAL;
+
+	if (dev->bmc_ops.check_flash_range) {
+		ret = dev->bmc_ops.check_flash_range(addr, addr + size);
+		if (ret)
+			return ret;
+	} else {
+		u32 top_addr = dev->staging_area_base + dev->staging_area_size;
+		if ((addr < dev->staging_area_base) ||
+			((addr + size) >= top_addr))
+			return -EINVAL;
+	}
+
+	ret = dev->bmc_ops.flash_read(dev, addr, buf, size);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int max10_spi_read(struct intel_max10_device *dev,
 	unsigned int addr, unsigned int *val)
 {
@@ -841,6 +1114,11 @@ int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val)
 		dev->ops = &m10bmc_n3000_regmap;
 		dev->csr = &m10bmc_spi_csr;
 
+		dev->raw_blk_ops.write_blk = n3000_bulk_raw_write;
+		dev->raw_blk_ops.read_blk = n3000_bulk_raw_read;
+		dev->bmc_ops.flash_read = n3000_flash_read;
+		dev->bmc_ops.flash_write = n3000_flash_write;
+
 		/* check the max10 version */
 		ret = check_max10_version(dev);
 		if (ret) {
@@ -871,6 +1149,10 @@ int max10_get_bmcfw_version(struct intel_max10_device *dev, unsigned int *val)
 		dev->staging_area_size = MAX_STAGING_AREA_SIZE;
 		dev->flags |= MAX10_FLAGS_SECURE;
 
+		dev->bmc_ops.flash_read = pmci_flash_bulk_read;
+		dev->bmc_ops.flash_write = pmci_flash_bulk_write;
+		dev->bmc_ops.check_flash_range = pmci_check_flash_address;
+
 		ret = pthread_mutex_init(&dev->bmc_ops.lock, NULL);
 		if (ret)
 			return ret;
diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h
index 6a1b122..0f3360e 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.h
+++ b/drivers/raw/ifpga/base/opae_intel_max10.h
@@ -62,9 +62,22 @@ struct m10bmc_csr {
 };
 
 /**
+ * struct flash_raw_blk_ops - device specific operations for flash R/W
+ * @write_blk: write a block of data to flash
+ * @read_blk: read a block of data from flash
+ */
+struct flash_raw_blk_ops {
+	int (*write_blk)(struct intel_max10_device *dev, uint32_t addr,
+			void *buf, uint32_t size);
+	int (*read_blk)(struct intel_max10_device *dev, uint32_t addr,
+			void *buf, uint32_t size);
+};
+
+/**
  * struct m10bmc_ops - device specific operations
  * @lock: prevent concurrent flash read/write
  * @mutex: prevent concurrent bmc read/write
+ * @check_flash_range: validate flash address
  * @flash_read: read a block of data from flash
  * @flash_write: write a block of data to flash
  */
@@ -92,6 +105,7 @@ struct intel_max10_device {
 	enum m10bmc_type type;
 	const struct m10bmc_regmap *ops;
 	const struct m10bmc_csr *csr;
+	struct flash_raw_blk_ops raw_blk_ops;
 	struct m10bmc_ops bmc_ops;
 	u8 *mmio; /* mmio address for PMCI */
 };
@@ -431,6 +445,22 @@ struct opae_sensor_info {
 #define PMCI_FPGA_RECONF_PAGE  GENMASK(22, 20)
 #define PMCI_FPGA_RP_LOAD      BIT(23)
 
+#define PMCI_FLASH_CTRL 0x40
+#define PMCI_FLASH_WR_MODE BIT(0)
+#define PMCI_FLASH_RD_MODE BIT(1)
+#define PMCI_FLASH_BUSY    BIT(2)
+#define PMCI_FLASH_FIFO_SPACE GENMASK(13, 4)
+#define PMCI_FLASH_READ_COUNT GENMASK(25, 16)
+
+#define PMCI_FLASH_INT_US       1
+#define PMCI_FLASH_TIMEOUT_US   10000
+
+#define PMCI_FLASH_ADDR 0x44
+#define PMCI_FLASH_FIFO 0x800
+#define PMCI_READ_BLOCK_SIZE 0x800
+#define PMCI_FIFO_MAX_BYTES 0x800
+#define PMCI_FIFO_MAX_WORDS (PMCI_FIFO_MAX_BYTES / 4)
+
 #define M10BMC_PMCI_FPGA_POC	0xb0
 #define PMCI_FPGA_POC		BIT(0)
 #define PMCI_NIOS_REQ_CLEAR	BIT(1)
@@ -447,6 +477,16 @@ struct opae_sensor_info {
 #define PMCI_FPGA_BOOT_PAGE  GENMASK(2, 0)
 #define PMCI_FPGA_CONFIGURED  BIT(3)
 
+#define M10BMC_PMCI_FLASH_CTRL 0x1d0
+#define FLASH_MUX_SELECTION GENMASK(2, 0)
+#define FLASH_MUX_IDLE 0
+#define FLASH_MUX_NIOS 1
+#define FLASH_MUX_HOST 2
+#define FLASH_MUX_PFL  4
+#define get_flash_mux(mux)  GET_FIELD(FLASH_MUX_SELECTION, mux)
+#define FLASH_NIOS_REQUEST BIT(4)
+#define FLASH_HOST_REQUEST BIT(5)
+
 #define M10BMC_PMCI_SDM_CTRL_STS 0x230
 #define PMCI_SDM_IMG_REQ	BIT(0)
 #define PMCI_SDM_STAT GENMASK(23, 16)
@@ -472,4 +512,10 @@ struct opae_sensor_info {
 #define SDM_STAT_CS_MIS   0x12
 #define SDM_STAT_PR_MIS   0x13
 #define SDM_STAT_MAX SDM_STAT_PR_MIS
+
+#define PMCI_FLASH_START 0x10000
+#define PMCI_FLASH_END 0xC7FFFFF
+
+int opae_read_flash(struct intel_max10_device *dev, u32 addr,
+		u32 size, void *buf);
 #endif
diff --git a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
index 3ff49a8..68499e6 100644
--- a/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
+++ b/drivers/raw/ifpga/base/osdep_rte/osdep_generic.h
@@ -39,6 +39,16 @@
 #define min(a, b) RTE_MIN(a, b)
 #define max(a, b) RTE_MAX(a, b)
 
+#define min_t(type, x, y) ({                    \
+	type __min1 = (x);                      \
+	type __min2 = (y);                      \
+	__min1 < __min2 ? __min1 : __min2; })
+
+#define max_t(type, x, y) ({                    \
+	type __max1 = (x);                      \
+	type __max2 = (y);                      \
+	__max1 > __max2 ? __max1 : __max2; })
+
 #define spinlock_t rte_spinlock_t
 #define spinlock_init(x) rte_spinlock_init(x)
 #define spinlock_lock(x) rte_spinlock_lock(x)
-- 
1.8.3.1


  parent reply	other threads:[~2022-06-17  7:11 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-25  1:51 [PATCH v1 0/2] Update rsu implementation Wei Huang
2022-05-25  1:51 ` [PATCH v1 1/2] raw/ifpga/base: add pmci driver Wei Huang
2022-05-25  1:51 ` [PATCH v1 2/2] raw/ifpga: update secure rsu Wei Huang
2022-06-10  2:24 ` [PATCH v2 0/2] update rsu implementation Wei Huang
2022-06-10  2:24   ` [PATCH v2 1/2] raw/ifpga/base: add pmci driver Wei Huang
2022-06-13  7:01     ` Zhang, Tianfei
2022-06-13  7:29       ` Huang, Wei
2022-06-10  2:25   ` [PATCH v2 2/2] raw/ifpga: update secure rsu Wei Huang
2022-06-17  7:19   ` [PATCH v3 0/4] introduce PMCI driver Wei Huang
2022-06-17  7:19     ` [PATCH v3 1/4] raw/ifpga/base: add PMCI base driver Wei Huang
2022-06-17  8:57       ` Zhang, Tianfei
2022-06-17 14:41       ` Xu, Rosen
2022-06-17  7:19     ` [PATCH v3 2/4] raw/ifpga/base: update board information Wei Huang
2022-06-17  8:57       ` Zhang, Tianfei
2022-06-17 14:42       ` Xu, Rosen
2022-06-17  7:19     ` Wei Huang [this message]
2022-06-17  8:58       ` [PATCH v3 3/4] raw/ifpga/base: update flash operation interface Zhang, Tianfei
2022-06-17 14:42       ` Xu, Rosen
2022-06-17  7:19     ` [PATCH v3 4/4] raw/ifpga/base: add PMCI sensor driver Wei Huang
2022-06-17  8:58       ` Zhang, Tianfei
2022-06-17 14:43       ` Xu, Rosen
2022-06-20 15:35     ` [PATCH v3 0/4] introduce PMCI driver Thomas Monjalon
2023-09-29 15:31   ` [PATCH v2 0/2] update rsu implementation David Marchand

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=1655450375-10739-4-git-send-email-wei.huang@intel.com \
    --to=wei.huang@intel.com \
    --cc=dev@dpdk.org \
    --cc=hemant.agrawal@nxp.com \
    --cc=nipun.gupta@nxp.com \
    --cc=qi.z.zhang@intel.com \
    --cc=rosen.xu@intel.com \
    --cc=stable@dpdk.org \
    --cc=thomas@monjalon.net \
    --cc=tianfei.zhang@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).