All of lore.kernel.org
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg
@ 2021-03-03  2:34 Wei Huang
  2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 1/3] raw/ifpga: add fpga rsu APIs Wei Huang
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Wei Huang @ 2021-03-03  2:34 UTC (permalink / raw)
  To: dev, rosen.xu, qi.z.zhang; +Cc: stable, tianfei.zhang, ferruh.yigit, Wei Huang

Cyborg is part of OpenStack, it needs some extra APIs to manage
devices with Intel FPGA. These patches add APIs to meet Cyborg
requirement.

Main changes from v15:
- remove example from the patch set

Wei Huang (3):
  raw/ifpga: add fpga rsu APIs
  raw/ifpga: add APIs to get fpga information
  raw/ifpga: add miscellaneous APIs

 doc/api/doxy-api-index.md                  |   3 +-
 doc/api/doxy-api.conf.in                   |   1 +
 drivers/raw/ifpga/base/ifpga_api.c         |  34 ++
 drivers/raw/ifpga/base/ifpga_defines.h     |   1 +
 drivers/raw/ifpga/base/ifpga_feature_dev.c |  21 +
 drivers/raw/ifpga/base/ifpga_feature_dev.h |   1 +
 drivers/raw/ifpga/base/ifpga_fme.c         |  36 +-
 drivers/raw/ifpga/base/ifpga_fme_rsu.c     | 428 ++++++++++++++
 drivers/raw/ifpga/base/ifpga_hw.h          |   1 +
 drivers/raw/ifpga/base/ifpga_sec_mgr.c     | 639 +++++++++++++++++++++
 drivers/raw/ifpga/base/ifpga_sec_mgr.h     |  93 +++
 drivers/raw/ifpga/base/meson.build         |   2 +
 drivers/raw/ifpga/base/opae_hw_api.c       |  77 +++
 drivers/raw/ifpga/base/opae_hw_api.h       |  12 +
 drivers/raw/ifpga/base/opae_ifpga_hw_api.h |   1 +
 drivers/raw/ifpga/base/opae_intel_max10.c  |  48 ++
 drivers/raw/ifpga/base/opae_intel_max10.h  |  44 ++
 drivers/raw/ifpga/ifpga_rawdev.c           |  30 +
 drivers/raw/ifpga/ifpga_rawdev.h           |   7 +-
 drivers/raw/ifpga/meson.build              |   4 +-
 drivers/raw/ifpga/rte_pmd_ifpga.c          | 429 ++++++++++++++
 drivers/raw/ifpga/rte_pmd_ifpga.h          | 308 ++++++++++
 drivers/raw/ifpga/version.map              |  18 +
 23 files changed, 2233 insertions(+), 5 deletions(-)
 create mode 100644 drivers/raw/ifpga/base/ifpga_fme_rsu.c
 create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.c
 create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.h
 create mode 100644 drivers/raw/ifpga/rte_pmd_ifpga.c
 create mode 100644 drivers/raw/ifpga/rte_pmd_ifpga.h

-- 
2.29.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH v16 1/3] raw/ifpga: add fpga rsu APIs
  2021-03-03  2:34 [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Wei Huang
@ 2021-03-03  2:34 ` Wei Huang
  2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 2/3] raw/ifpga: add APIs to get fpga information Wei Huang
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Wei Huang @ 2021-03-03  2:34 UTC (permalink / raw)
  To: dev, rosen.xu, qi.z.zhang; +Cc: stable, tianfei.zhang, ferruh.yigit, Wei Huang

RSU (Remote System Update) depends on secure manager which may be
different on various implementations, so a new secure manager device
is implemented for adapting such difference.
There are five APIs added:
1. rte_pmd_ifpga_get_dev_id() get raw device ID of ifpga device from
PCI address like 'Domain:Bus:Dev.Func'.
2. rte_pmd_ifpga_update_flash() update flash with specific image file.
3. rte_pmd_ifpga_stop_update() abort flash update process.
4. rte_pmd_ifpga_reboot_try() check current ifpga status and change it
to reboot status if it is idle.
5. rte_pmd_ifpga_reload() trigger full reconfiguration of ifpga device.

Signed-off-by: Wei Huang <wei.huang@intel.com>
Acked-by: Tianfei Zhang <tianfei.zhang@intel.com>
Acked-by: Rosen Xu <rosen.xu@intel.com>
---
v2: fix coding style issue in ifpga_fme_rsu.c and ifpga_sec_mgr.c
---
v3: fix compilation issues in ifpga_fme_rsu.c
---
v4: fix compilation issues in opae_intel_max10.c
---
v5: implement APIs in rte_pmd_ifpga.c
---
 doc/api/doxy-api-index.md                 |   3 +-
 doc/api/doxy-api.conf.in                  |   1 +
 drivers/raw/ifpga/base/ifpga_api.c        |  26 +
 drivers/raw/ifpga/base/ifpga_fme.c        |   8 +
 drivers/raw/ifpga/base/ifpga_fme_rsu.c    | 428 +++++++++++++++
 drivers/raw/ifpga/base/ifpga_hw.h         |   1 +
 drivers/raw/ifpga/base/ifpga_sec_mgr.c    | 639 ++++++++++++++++++++++
 drivers/raw/ifpga/base/ifpga_sec_mgr.h    |  93 ++++
 drivers/raw/ifpga/base/meson.build        |   2 +
 drivers/raw/ifpga/base/opae_hw_api.c      |  59 ++
 drivers/raw/ifpga/base/opae_hw_api.h      |  10 +
 drivers/raw/ifpga/base/opae_intel_max10.c |  48 ++
 drivers/raw/ifpga/base/opae_intel_max10.h |  44 ++
 drivers/raw/ifpga/meson.build             |   4 +-
 drivers/raw/ifpga/rte_pmd_ifpga.c         | 163 ++++++
 drivers/raw/ifpga/rte_pmd_ifpga.h         | 132 +++++
 drivers/raw/ifpga/version.map             |  11 +
 17 files changed, 1670 insertions(+), 2 deletions(-)
 create mode 100644 drivers/raw/ifpga/base/ifpga_fme_rsu.c
 create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.c
 create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.h
 create mode 100644 drivers/raw/ifpga/rte_pmd_ifpga.c
 create mode 100644 drivers/raw/ifpga/rte_pmd_ifpga.h

diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 748514e243..8a48af1042 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -56,7 +56,8 @@ The public API headers are grouped by topics:
   [dpaa2_qdma]         (@ref rte_pmd_dpaa2_qdma.h),
   [crypto_scheduler]   (@ref rte_cryptodev_scheduler.h),
   [dlb]                (@ref rte_pmd_dlb.h),
-  [dlb2]               (@ref rte_pmd_dlb2.h)
+  [dlb2]               (@ref rte_pmd_dlb2.h),
+  [ifpga]              (@ref rte_pmd_ifpga.h)
 
 - **memory**:
   [memseg]             (@ref rte_memory.h),
diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in
index 5c883b613b..5eb31508fd 100644
--- a/doc/api/doxy-api.conf.in
+++ b/doc/api/doxy-api.conf.in
@@ -23,6 +23,7 @@ INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \
                           @TOPDIR@/drivers/net/softnic \
                           @TOPDIR@/drivers/raw/dpaa2_cmdif \
                           @TOPDIR@/drivers/raw/dpaa2_qdma \
+                          @TOPDIR@/drivers/raw/ifpga \
                           @TOPDIR@/drivers/raw/ioat \
                           @TOPDIR@/lib/librte_eal/include \
                           @TOPDIR@/lib/librte_eal/include/generic \
diff --git a/drivers/raw/ifpga/base/ifpga_api.c b/drivers/raw/ifpga/base/ifpga_api.c
index 1ff57fa188..1aedf150bc 100644
--- a/drivers/raw/ifpga/base/ifpga_api.c
+++ b/drivers/raw/ifpga/base/ifpga_api.c
@@ -5,6 +5,7 @@
 #include "ifpga_api.h"
 #include "ifpga_enumerate.h"
 #include "ifpga_feature_dev.h"
+#include "ifpga_sec_mgr.h"
 
 #include "opae_hw_api.h"
 
@@ -228,11 +229,36 @@ static int ifpga_mgr_get_board_info(struct opae_manager *mgr,
 	return 0;
 }
 
+static int ifpga_mgr_update_flash(struct opae_manager *mgr, const char *image,
+	u64 *status)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fpga_update_flash(fme, image, status);
+}
+
+static int ifpga_mgr_stop_flash_update(struct opae_manager *mgr, int force)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fpga_stop_flash_update(fme, force);
+}
+
+static int ifpga_mgr_reload(struct opae_manager *mgr, int type, int page)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fpga_reload(fme, type, page);
+}
+
 struct opae_manager_ops ifpga_mgr_ops = {
 	.flash = ifpga_mgr_flash,
 	.get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info,
 	.get_sensor_value = ifpga_mgr_get_sensor_value,
 	.get_board_info = ifpga_mgr_get_board_info,
+	.update_flash = ifpga_mgr_update_flash,
+	.stop_flash_update = ifpga_mgr_stop_flash_update,
+	.reload = ifpga_mgr_reload,
 };
 
 static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset,
diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c
index f29ff3159b..34fd9a818e 100644
--- a/drivers/raw/ifpga/base/ifpga_fme.c
+++ b/drivers/raw/ifpga/base/ifpga_fme.c
@@ -7,6 +7,7 @@
 #include "opae_intel_max10.h"
 #include "opae_i2c.h"
 #include "opae_at24_eeprom.h"
+#include "ifpga_sec_mgr.h"
 
 #define PWR_THRESHOLD_MAX       0x7F
 
@@ -1152,6 +1153,12 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)
 	if (spi_self_checking(max10))
 		goto spi_fail;
 
+	ret = init_sec_mgr(fme);
+	if (ret) {
+		dev_err(fme, "security manager init fail\n");
+		goto spi_fail;
+	}
+
 	return ret;
 
 spi_fail:
@@ -1165,6 +1172,7 @@ static void fme_nios_spi_uinit(struct ifpga_feature *feature)
 {
 	struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
 
+	release_sec_mgr(fme);
 	if (fme->max10_dev)
 		intel_max10_device_remove(fme->max10_dev);
 }
diff --git a/drivers/raw/ifpga/base/ifpga_fme_rsu.c b/drivers/raw/ifpga/base/ifpga_fme_rsu.c
new file mode 100644
index 0000000000..28198abd78
--- /dev/null
+++ b/drivers/raw/ifpga/base/ifpga_fme_rsu.c
@@ -0,0 +1,428 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include "ifpga_sec_mgr.h"
+
+static struct ifpga_sec_mgr *sec_mgr;
+
+static void set_rsu_control(struct ifpga_sec_mgr *smgr, uint32_t ctrl)
+{
+	if (smgr && smgr->rsu_control)
+		*smgr->rsu_control = ctrl;
+}
+
+static uint32_t get_rsu_control(struct ifpga_sec_mgr *smgr)
+{
+	if (smgr && smgr->rsu_control)
+		return *smgr->rsu_control;
+	return 0;
+}
+
+static void set_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t status,
+	uint32_t progress)
+{
+	if (smgr && smgr->rsu_status)
+		*smgr->rsu_status = IFPGA_RSU_STATUS(status, progress);
+}
+
+static void get_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t *status,
+	uint32_t *progress)
+{
+	if (smgr && smgr->rsu_status) {
+		if (status)
+			*status = IFPGA_RSU_GET_STAT(*smgr->rsu_status);
+		if (progress)
+			*progress = IFPGA_RSU_GET_PROG(*smgr->rsu_status);
+	}
+}
+
+static void sig_handler(int sig, siginfo_t *info, void *data)
+{
+	(void)(info);
+	(void)(data);
+
+	switch (sig) {
+	case SIGINT:
+		if (sec_mgr) {
+			dev_info(sec_mgr, "Interrupt secure flash update"
+				" by keyboard\n");
+			set_rsu_control(sec_mgr, IFPGA_RSU_ABORT);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void log_time(time_t t, const char *msg)
+{
+	uint32_t h = 0;
+	uint32_t m = 0;
+	uint32_t s = 0;
+
+	if (t < 60) {
+		s = (uint32_t)t;
+	} else if (t < 3600) {
+		s = (uint32_t)(t % 60);
+		m = (uint32_t)(t / 60);
+	} else {
+		s = (uint32_t)(t % 60);
+		m = (uint32_t)((t % 3600) / 60);
+		h = (uint32_t)(t / 3600);
+	}
+	printf("%s - %02u:%02u:%02u\n", msg, h, m, s);
+}
+
+static int start_flash_update(struct ifpga_sec_mgr *smgr)
+{
+	if (!smgr)
+		return -ENODEV;
+
+	if (!smgr->ops || !smgr->ops->prepare)
+		return -EINVAL;
+
+	return smgr->ops->prepare(smgr);
+}
+
+static int write_flash_image(struct ifpga_sec_mgr *smgr, const char *image,
+	uint32_t offset)
+{
+	void *buf = NULL;
+	int retry = 0;
+	uint32_t length = 0;
+	uint32_t to_transfer = 0;
+	uint32_t one_percent = 0;
+	uint32_t prog = 0;
+	uint32_t old_prog = -1;
+	ssize_t read_size = 0;
+	int fd = -1;
+	int ret = 0;
+
+	if (!smgr)
+		return -ENODEV;
+
+	if (!smgr->ops || !smgr->ops->write_blk)
+		return -EINVAL;
+
+	fd = open(image, O_RDONLY);
+	if (fd < 0) {
+		dev_err(smgr,
+			"Failed to open \'%s\' for RD [e:%s]\n",
+			image, strerror(errno));
+		return -EIO;
+	}
+
+	buf = malloc(IFPGA_RSU_DATA_BLK_SIZE);
+	if (!buf) {
+		dev_err(smgr, "Failed to allocate memory for flash update\n");
+		close(fd);
+		return -ENOMEM;
+	}
+
+	length = smgr->rsu_length;
+	one_percent = length / 100;
+	do {
+		to_transfer = (length > IFPGA_RSU_DATA_BLK_SIZE) ?
+			IFPGA_RSU_DATA_BLK_SIZE : length;
+		lseek(fd, offset, SEEK_SET);
+		read_size = read(fd, buf, to_transfer);
+		if (read_size < 0) {
+			dev_err(smgr, "Failed to read from \'%s\' [e:%s]\n",
+				image, strerror(errno));
+			ret = -EIO;
+			goto end;
+		}
+		if ((uint32_t)read_size != to_transfer) {
+			dev_err(smgr,
+				"Read length %zd is not expected [e:%u]\n",
+				read_size, to_transfer);
+			ret = -EIO;
+			goto end;
+		}
+
+		retry = 0;
+		do {
+			if (get_rsu_control(smgr) == IFPGA_RSU_ABORT) {
+				ret = -EAGAIN;
+				goto end;
+			}
+			ret = smgr->ops->write_blk(smgr, buf, offset,
+				to_transfer);
+			if (ret == 0)
+				break;
+			sleep(1);
+		} while (++retry <= IFPGA_RSU_WRITE_RETRY);
+		if (retry > IFPGA_RSU_WRITE_RETRY) {
+			dev_err(smgr, "Failed to write to staging area 0x%x\n",
+				offset);
+			ret = -EAGAIN;
+			goto end;
+		}
+
+		length -= to_transfer;
+		offset += to_transfer;
+		prog = offset / one_percent;
+		if (prog != old_prog) {
+			printf("\r%d%%", prog);
+			fflush(stdout);
+			set_rsu_status(smgr, IFPGA_RSU_READY, prog);
+			old_prog = prog;
+		}
+	} while (length > 0);
+	set_rsu_status(smgr, IFPGA_RSU_READY, 100);
+	printf("\n");
+
+end:
+	free(buf);
+	close(fd);
+	return ret;
+}
+
+static int apply_flash_update(struct ifpga_sec_mgr *smgr)
+{
+	uint32_t one_percent = 0;
+	uint32_t one_percent_time = 0;
+	uint32_t prog = 0;
+	uint32_t old_prog = -1;
+	uint32_t copy_time = 0;
+	int ret = 0;
+
+	if (!smgr)
+		return -ENODEV;
+
+	if (!smgr->ops || !smgr->ops->write_done || !smgr->ops->check_complete)
+		return -EINVAL;
+
+	if (smgr->ops->write_done(smgr) < 0) {
+		dev_err(smgr, "Failed to apply flash update\n");
+		return -EAGAIN;
+	}
+
+	one_percent = (smgr->rsu_length + 99) / 100;
+	if (smgr->copy_speed == 0)   /* avoid zero divide fault */
+		smgr->copy_speed = 1;
+	one_percent_time = (one_percent + smgr->copy_speed - 1) /
+		smgr->copy_speed;
+	if (one_percent_time == 0)   /* avoid zero divide fault */
+		one_percent_time = 1;
+
+	do {
+		ret = smgr->ops->check_complete(smgr);
+		if (ret != -EAGAIN)
+			break;
+		sleep(1);
+		copy_time += 1;
+		prog = copy_time / one_percent_time;
+		if (prog >= 100)
+			prog = 99;
+		if (prog != old_prog) {
+			printf("\r%d%%", prog);
+			fflush(stdout);
+			set_rsu_status(smgr, IFPGA_RSU_COPYING, prog);
+			old_prog = prog;
+		}
+	} while (true);
+
+	if (ret < 0) {
+		printf("\n");
+		dev_err(smgr, "Failed to complete secure flash update\n");
+	} else {
+		printf("\r100%%\n");
+		set_rsu_status(smgr, IFPGA_RSU_COPYING, 100);
+	}
+
+	return ret;
+}
+
+static int secure_update_cancel(struct ifpga_sec_mgr *smgr)
+{
+	if (!smgr)
+		return -ENODEV;
+
+	if (!smgr->ops || !smgr->ops->cancel)
+		return -EINVAL;
+
+	return smgr->ops->cancel(smgr);
+}
+
+static int secure_update_status(struct ifpga_sec_mgr *smgr, uint64_t *status)
+{
+	if (!smgr)
+		return -ENODEV;
+
+	if (!smgr->ops || !smgr->ops->get_hw_errinfo)
+		return -EINVAL;
+
+	if (status)
+		*status = smgr->ops->get_hw_errinfo(smgr);
+
+	return 0;
+}
+
+int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
+	uint64_t *status)
+{
+	struct ifpga_hw *hw = NULL;
+	struct ifpga_sec_mgr *smgr = NULL;
+	uint32_t rsu_stat = 0;
+	int fd = -1;
+	struct sigaction old_sigint_action;
+	struct sigaction sa;
+	time_t start;
+	int ret = 0;
+
+	if (!fme || !image || !status) {
+		dev_err(fme, "Input parameter of %s is invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	hw = (struct ifpga_hw *)fme->parent;
+	if (!hw) {
+		dev_err(fme, "Parent of FME not found\n");
+		return -ENODEV;
+	}
+
+	smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
+	if (!smgr || !smgr->max10_dev) {
+		dev_err(smgr, "Security manager not initialized\n");
+		return -ENODEV;
+	}
+
+	opae_adapter_lock(hw->adapter, -1);
+	get_rsu_status(smgr, &rsu_stat, NULL);
+	if (rsu_stat != IFPGA_RSU_IDLE) {
+		opae_adapter_unlock(hw->adapter);
+		if (rsu_stat == IFPGA_RSU_REBOOT)
+			dev_info(smgr, "Reboot is in progress\n");
+		else
+			dev_info(smgr, "Update is in progress\n");
+		return -EAGAIN;
+	}
+	set_rsu_control(smgr, 0);
+	set_rsu_status(smgr, IFPGA_RSU_PREPARE, 0);
+	opae_adapter_unlock(hw->adapter);
+
+	fd = open(image, O_RDONLY);
+	if (fd < 0) {
+		dev_err(smgr,
+			"Failed to open \'%s\' for RD [e:%s]\n",
+			image, strerror(errno));
+		return -EIO;
+	}
+	smgr->rsu_length = lseek(fd, 0, SEEK_END);
+	close(fd);
+
+	if (smgr->max10_dev->staging_area_size < smgr->rsu_length) {
+		dev_err(dev, "Size of staging area is small than image length "
+			"[%u<%u]\n", smgr->max10_dev->staging_area_size,
+			smgr->rsu_length);
+		return -EINVAL;
+	}
+
+	printf("Updating from file \'%s\' with size %u\n",
+		image, smgr->rsu_length);
+
+	sec_mgr = smgr;
+	memset(&sa, 0, sizeof(struct sigaction));
+	sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
+	sa.sa_sigaction = sig_handler;
+	ret = sigaction(SIGINT, &sa, &old_sigint_action);
+	if (ret < 0) {
+		dev_warn(dev, "Failed to register signal handler"
+			" [e:%d]\n", ret);
+		sec_mgr = NULL;
+	}
+
+	start = time(NULL);
+	log_time(time(NULL) - start, "Starting secure flash update");
+	ret = start_flash_update(smgr);
+	if (ret < 0)
+		goto end;
+
+	set_rsu_status(smgr, IFPGA_RSU_READY, 0);
+	log_time(time(NULL) - start, "Writing to staging area");
+	ret = write_flash_image(smgr, image, 0);
+	if (ret < 0)
+		goto end;
+
+	set_rsu_status(smgr, IFPGA_RSU_COPYING, 0);
+	log_time(time(NULL) - start, "Applying secure flash update");
+	ret = apply_flash_update(smgr);
+
+end:
+	if (sec_mgr) {
+		sec_mgr = NULL;
+		if (sigaction(SIGINT, &old_sigint_action, NULL) < 0)
+			dev_err(smgr, "Failed to unregister signal handler\n");
+	}
+
+	secure_update_status(smgr, status);
+	if (ret < 0) {
+		log_time(time(NULL) - start, "Secure flash update ERROR");
+		if (ret == -EAGAIN)
+			secure_update_cancel(smgr);
+	} else {
+		log_time(time(NULL) - start, "Secure flash update OK");
+	}
+	set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
+
+	return ret;
+}
+
+int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)
+{
+	struct ifpga_sec_mgr *smgr = NULL;
+	uint32_t status = 0;
+	int retry = IFPGA_RSU_CANCEL_RETRY;
+	int ret = 0;
+
+	if (!fme) {
+		dev_err(fme, "Input parameter of %s is invalid\n", __func__);
+		return -EINVAL;
+	}
+	smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
+
+	get_rsu_status(smgr, &status, NULL);
+	if (status != IFPGA_RSU_IDLE) {
+		dev_info(smgr, "Cancel secure flash update\n");
+		set_rsu_control(smgr, IFPGA_RSU_ABORT);
+	}
+
+	if (force) {
+		sleep(2);
+		do {
+			get_rsu_status(smgr, &status, NULL);
+			if (status == IFPGA_RSU_IDLE)
+				break;
+			if (secure_update_cancel(smgr) == 0)
+				set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
+			sleep(1);
+		} while (--retry > 0);
+		if (retry <= 0) {
+			dev_err(smgr, "Failed to stop flash update\n");
+			ret = -EAGAIN;
+		}
+	}
+
+	return ret;
+}
+
+int fpga_reload(struct ifpga_fme_hw *fme, int type, int page)
+{
+	struct ifpga_sec_mgr *smgr = NULL;
+
+	if (!fme) {
+		dev_err(fme, "Input parameter of %s is invalid\n", __func__);
+		return -EINVAL;
+	}
+	smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
+
+	if (!smgr || !smgr->ops || !smgr->ops->reload)
+		return -EINVAL;
+
+	return smgr->ops->reload(smgr, type, page);
+}
diff --git a/drivers/raw/ifpga/base/ifpga_hw.h b/drivers/raw/ifpga/base/ifpga_hw.h
index 7c3307fe77..ed5edc6016 100644
--- a/drivers/raw/ifpga/base/ifpga_hw.h
+++ b/drivers/raw/ifpga/base/ifpga_hw.h
@@ -91,6 +91,7 @@ struct ifpga_fme_hw {
 	struct opae_board_info board_info;
 	int nums_eth_dev;
 	unsigned int nums_acc_region;
+	void *sec_mgr;
 };
 
 enum ifpga_port_state {
diff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.c b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
new file mode 100644
index 0000000000..4cf1db3049
--- /dev/null
+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.c
@@ -0,0 +1,639 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include "ifpga_sec_mgr.h"
+
+
+static const char * const rsu_prog[] = {"IDLE", "PREPARING", "SLEEPING",
+	"READY", "AUTHENTICATING", "COPYING", "CANCELLATION", "PROGRAMMING_KEY",
+	"DONE", "PKVL_DONE"};
+static const char * const rsu_statl[] = {"NORMAL", "TIMEOUT", "AUTH_FAIL",
+	"COPY_FAIL", "FATAL", "PKVL_REJECT", "NON_INCR", "ERASE_FAIL",
+	"WEAROUT"};
+static const char * const rsu_stath[] = {"NIOS_OK", "USER_OK", "FACTORY_OK",
+	"USER_FAIL", "FACTORY_FAIL", "NIOS_FLASH_ERR", "FPGA_FLASH_ERR"};
+
+static const char *rsu_progress_name(uint32_t prog)
+{
+	if (prog > SEC_PROGRESS_PKVL_PROM_DONE)
+		return "UNKNOWN";
+	else
+		return rsu_prog[prog];
+}
+
+static const char *rsu_status_name(uint32_t stat)
+{
+	if (stat >= SEC_STATUS_NIOS_OK) {
+		if (stat > SEC_STATUS_FPGA_FLASH_ERR)
+			return "UNKNOWN";
+		else
+			return rsu_stath[stat-SEC_STATUS_NIOS_OK];
+	} else {
+		if (stat > SEC_STATUS_WEAROUT)
+			return "UNKNOWN";
+		else
+			return rsu_statl[stat];
+	}
+}
+
+static bool secure_start_done(uint32_t doorbell)
+{
+	return (SEC_STATUS_G(doorbell) == SEC_STATUS_ERASE_FAIL ||
+		SEC_STATUS_G(doorbell) == SEC_STATUS_WEAROUT ||
+		(SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_IDLE &&
+		SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_RSU_DONE));
+}
+
+static bool secure_prog_ready(uint32_t doorbell)
+{
+	return (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY);
+}
+
+static int poll_timeout(struct intel_max10_device *dev, uint32_t offset,
+	bool (*cond)(uint32_t), uint32_t interval_ms, uint32_t timeout_ms)
+{
+	uint32_t val = 0;
+	int ret = 0;
+
+	for (;;) {
+		ret = max10_sys_read(dev, offset, &val);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to read max10 register 0x%x [e:%d]\n",
+				offset, ret);
+			break;
+		}
+
+		if (cond(val)) {
+			dev_debug(dev,
+				"Read 0x%08x from max10 register 0x%x "
+				"[poll success]\n", val, offset);
+			ret = 0;
+			break;
+		}
+		if (timeout_ms > interval_ms)
+			timeout_ms -= interval_ms;
+		else
+			timeout_ms = 0;
+		if (timeout_ms == 0) {
+			dev_debug(dev,
+				"Read 0x%08x from max10 register 0x%x "
+				"[poll timeout]\n", val, offset);
+			ret = -ETIMEDOUT;
+			break;
+		}
+		msleep(interval_ms);
+	}
+
+	return ret;
+}
+
+static int n3000_secure_update_start(struct intel_max10_device *dev)
+{
+	uint32_t doorbell = 0;
+	uint32_t prog = 0;
+	uint32_t status = 0;
+	int ret = 0;
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	prog = SEC_PROGRESS_G(doorbell);
+	if ((prog != SEC_PROGRESS_IDLE) && (prog != SEC_PROGRESS_RSU_DONE)) {
+		dev_debug(dev, "Current RSU progress is %s\n",
+			rsu_progress_name(prog));
+		return -EBUSY;
+	}
+
+	ret = max10_sys_update_bits(dev, MAX10_DOORBELL,
+		RSU_REQUEST | HOST_STATUS, RSU_REQUEST);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to updt max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	ret = poll_timeout(dev, MAX10_DOORBELL, secure_start_done,
+		IFPGA_SEC_START_INTERVAL_MS, IFPGA_SEC_START_TIMEOUT_MS);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to poll max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	status = SEC_STATUS_G(doorbell);
+	if (status == SEC_STATUS_WEAROUT)
+		return -EAGAIN;
+
+	if (status == SEC_STATUS_ERASE_FAIL)
+		return -EIO;
+
+	return 0;
+}
+
+static int n3000_cancel(struct ifpga_sec_mgr *smgr)
+{
+	struct intel_max10_device *dev = NULL;
+	uint32_t doorbell = 0;
+	uint32_t prog = 0;
+	int ret = 0;
+
+	if (!smgr || !smgr->max10_dev)
+		return -ENODEV;
+	dev = (struct intel_max10_device *)smgr->max10_dev;
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	prog = SEC_PROGRESS_G(doorbell);
+	if (prog == SEC_PROGRESS_IDLE)
+		return 0;
+	if (prog != SEC_PROGRESS_READY)
+		return -EBUSY;
+
+	return max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,
+		HOST_STATUS_S(HOST_STATUS_ABORT_RSU));
+}
+
+static int n3000_prepare(struct ifpga_sec_mgr *smgr)
+{
+	struct intel_max10_device *dev = NULL;
+	int retry = 0;
+	int ret = 0;
+
+	if (!smgr || !smgr->max10_dev)
+		return -ENODEV;
+	dev = (struct intel_max10_device *)smgr->max10_dev;
+
+	ret = n3000_secure_update_start(dev);
+	if (ret == -EBUSY)
+		n3000_cancel(smgr);
+
+	while (ret) {
+		if (++retry > IFPGA_RSU_START_RETRY)
+			break;
+		msleep(1000);
+		ret = n3000_secure_update_start(dev);
+	}
+	if (retry > IFPGA_RSU_START_RETRY) {
+		dev_err(dev, "Failed to start secure flash update\n");
+		ret = -EAGAIN;
+	}
+
+	return ret;
+}
+
+static int n3000_bulk_write(struct intel_max10_device *dev, uint32_t addr,
+	char *buf, uint32_t len)
+{
+	uint32_t i = 0;
+	uint32_t n = 0;
+	uint32_t v = 0;
+	uint32_t p = 0;
+	int ret = 0;
+
+	if (len & 0x3) {
+		dev_err(dev,
+			"Length of data block is not 4 bytes aligned [e:%u]\n",
+			len);
+		return -EINVAL;
+	}
+
+	n = len >> 2;
+	for (i = 0; i < n; i++) {
+		p = i << 2;
+		v = *(uint32_t *)(buf + p);
+		ret = max10_reg_write(dev, addr + p, v);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to write to staging area 0x%08x [e:%d]\n",
+				addr + p, ret);
+			return ret;
+		}
+		usleep(1);
+	}
+
+	return 0;
+}
+
+static int n3000_write_blk(struct ifpga_sec_mgr *smgr, char *buf,
+	uint32_t offset, uint32_t len)
+{
+	struct intel_max10_device *dev = NULL;
+	uint32_t doorbell = 0;
+	uint32_t prog = 0;
+	uint32_t m = 0;
+	int ret = 0;
+
+	if (!smgr || !smgr->max10_dev)
+		return -ENODEV;
+	dev = (struct intel_max10_device *)smgr->max10_dev;
+
+	if (offset + len > dev->staging_area_size) {
+		dev_err(dev,
+			"Write position would be out of staging area [e:%u]\n",
+			dev->staging_area_size);
+		return -ENOMEM;
+	}
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	prog = SEC_PROGRESS_G(doorbell);
+	if (prog == SEC_PROGRESS_PREPARE)
+		return -EAGAIN;
+	else if (prog != SEC_PROGRESS_READY)
+		return -EBUSY;
+
+	m = len & 0x3;
+	if (m != 0)
+		len += 4 - m;   /* make length to 4 bytes align */
+
+	return n3000_bulk_write(dev, dev->staging_area_base + offset, buf, len);
+}
+
+static int n3000_write_done(struct ifpga_sec_mgr *smgr)
+{
+	struct intel_max10_device *dev = NULL;
+	uint32_t doorbell = 0;
+	uint32_t prog = 0;
+	uint32_t status = 0;
+	int ret = 0;
+
+	if (!smgr || !smgr->max10_dev)
+		return -ENODEV;
+	dev = (struct intel_max10_device *)smgr->max10_dev;
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	prog = SEC_PROGRESS_G(doorbell);
+	if (prog != SEC_PROGRESS_READY)
+		return -EBUSY;
+
+	ret = max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,
+		HOST_STATUS_S(HOST_STATUS_WRITE_DONE));
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to update max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	ret = poll_timeout(dev, MAX10_DOORBELL, secure_prog_ready,
+		IFPGA_NIOS_HANDSHAKE_INTERVAL_MS,
+		IFPGA_NIOS_HANDSHAKE_TIMEOUT_MS);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to poll max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	status = SEC_STATUS_G(doorbell);
+	switch (status) {
+	case SEC_STATUS_NORMAL:
+	case SEC_STATUS_NIOS_OK:
+	case SEC_STATUS_USER_OK:
+	case SEC_STATUS_FACTORY_OK:
+		ret = 0;
+		break;
+	default:
+		ret = -EIO;
+		break;
+	}
+
+	return ret;
+}
+
+static int n3000_check_complete(struct ifpga_sec_mgr *smgr)
+{
+	struct intel_max10_device *dev = NULL;
+	uint32_t doorbell = 0;
+	uint32_t status = 0;
+	uint32_t prog = 0;
+	int ret = 0;
+
+	if (!smgr || !smgr->max10_dev)
+		return -ENODEV;
+	dev = (struct intel_max10_device *)smgr->max10_dev;
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return ret;
+	}
+
+	status = SEC_STATUS_G(doorbell);
+	switch (status) {
+	case SEC_STATUS_NORMAL:
+	case SEC_STATUS_NIOS_OK:
+	case SEC_STATUS_USER_OK:
+	case SEC_STATUS_FACTORY_OK:
+	case SEC_STATUS_WEAROUT:
+		break;
+	default:
+		return -EIO;
+	}
+
+	prog = SEC_PROGRESS_G(doorbell);
+	switch (prog) {
+	case SEC_PROGRESS_IDLE:
+	case SEC_PROGRESS_RSU_DONE:
+		return 0;
+	case SEC_PROGRESS_AUTHENTICATING:
+	case SEC_PROGRESS_COPYING:
+	case SEC_PROGRESS_UPDATE_CANCEL:
+	case SEC_PROGRESS_PROGRAM_KEY_HASH:
+		return -EAGAIN;
+	case SEC_PROGRESS_PREPARE:
+	case SEC_PROGRESS_READY:
+		return -EBUSY;
+	default:
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int n3000_reload_fpga(struct intel_max10_device *dev, int page)
+{
+	int ret = 0;
+
+	dev_info(dev, "Reload FPGA\n");
+
+	if (!dev || ((page != 0) && (page != 1))) {
+		dev_err(dev, "Input parameter of %s is invalid\n", __func__);
+		ret = -EINVAL;
+		goto end;
+	}
+
+	if (dev->flags & MAX10_FLAGS_SECURE) {
+		ret = max10_sys_update_bits(dev, FPGA_RECONF_REG,
+			SFPGA_RP_LOAD, 0);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to update max10 reconfig register [e:%d]\n",
+				ret);
+			goto end;
+		}
+		ret = max10_sys_update_bits(dev, FPGA_RECONF_REG,
+			SFPGA_RP_LOAD | SFPGA_RECONF_PAGE,
+			SFPGA_RP_LOAD | SFPGA_PAGE(page));
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to update max10 reconfig register [e:%d]\n",
+				ret);
+			goto end;
+		}
+	} else {
+		ret = max10_sys_update_bits(dev, RSU_REG, FPGA_RP_LOAD, 0);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to update max10 rsu register [e:%d]\n",
+				ret);
+			goto end;
+		}
+		ret = max10_sys_update_bits(dev, RSU_REG,
+			FPGA_RP_LOAD | FPGA_RECONF_PAGE,
+			FPGA_RP_LOAD | FPGA_PAGE(page));
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to update max10 rsu register [e:%d]\n",
+				ret);
+			goto end;
+		}
+	}
+
+	ret = max10_sys_update_bits(dev, FPGA_RECONF_REG, COUNTDOWN_START, 0);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to update max10 reconfig register [e:%d]\n",
+			ret);
+		goto end;
+	}
+
+	ret = max10_sys_update_bits(dev, FPGA_RECONF_REG, COUNTDOWN_START,
+		COUNTDOWN_START);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to update max10 reconfig register [e:%d]\n",
+			ret);
+	}
+end:
+	if (ret < 0)
+		dev_err(dev, "Failed to reload FPGA\n");
+
+	return ret;
+}
+
+static int n3000_reload_bmc(struct intel_max10_device *dev, int page)
+{
+	uint32_t val = 0;
+	int ret = 0;
+
+	dev_info(dev, "Reload BMC\n");
+
+	if (!dev || ((page != 0) && (page != 1))) {
+		dev_err(dev, "Input parameter of %s is invalid\n", __func__);
+		ret = -EINVAL;
+		goto end;
+	}
+
+	if (dev->flags & MAX10_FLAGS_SECURE) {
+		ret = max10_sys_update_bits(dev, MAX10_DOORBELL,
+			CONFIG_SEL | REBOOT_REQ,
+			CONFIG_SEL_S(page) | REBOOT_REQ);
+	} else {
+		val = (page == 0) ? 0x1 : 0x3;
+		ret = max10_reg_write(dev, IFPGA_DUAL_CFG_CTRL1, val);
+		if (ret < 0) {
+			dev_err(dev,
+				"Failed to write to dual config1 register [e:%d]\n",
+				ret);
+			goto end;
+		}
+
+		ret = max10_reg_write(dev, IFPGA_DUAL_CFG_CTRL0, 0x1);
+		if (ret < 0) {
+			if (ret == -EIO) {
+				ret = 0;
+				goto end;
+			}
+			dev_err(dev,
+				"Failed to write to dual config0 register [e:%d]\n",
+				ret);
+		}
+	}
+
+end:
+	if (ret < 0)
+		dev_err(dev, "Failed to reload BMC\n");
+
+	return ret;
+}
+
+static int n3000_reload(struct ifpga_sec_mgr *smgr, int type, int page)
+{
+	int psel = 0;
+	int ret = 0;
+
+	if (!smgr || !smgr->max10_dev)
+		return -ENODEV;
+
+	if (type == IFPGA_BOOT_TYPE_FPGA) {
+		psel = (page == IFPGA_BOOT_PAGE_FACTORY ? 0 : 1);
+		ret = n3000_reload_fpga(smgr->max10_dev, psel);
+	} else if (type == IFPGA_BOOT_TYPE_BMC) {
+		psel = (page == IFPGA_BOOT_PAGE_FACTORY ? 1 : 0);
+		ret = n3000_reload_bmc(smgr->max10_dev, psel);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static uint64_t n3000_get_hw_errinfo(struct ifpga_sec_mgr *smgr)
+{
+	struct intel_max10_device *dev = NULL;
+	uint32_t doorbell = 0;
+	uint32_t stat = 0;
+	uint32_t prog = 0;
+	uint32_t auth_result = 0;
+	int ret = 0;
+
+	if (!smgr || !smgr->max10_dev)
+		return -ENODEV;
+	dev = (struct intel_max10_device *)smgr->max10_dev;
+
+	ret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read max10 doorbell register [e:%d]\n",
+			ret);
+		return -1;
+	}
+	stat = SEC_STATUS_G(doorbell);
+	prog = SEC_PROGRESS_G(doorbell);
+	dev_debug(dev, "Current RSU status is %s, progress is %s\n",
+		rsu_status_name(stat), rsu_progress_name(prog));
+
+	ret = max10_sys_read(dev, MAX10_AUTH_RESULT, &auth_result);
+	if (ret < 0) {
+		dev_err(dev,
+			"Failed to read authenticate result register [e:%d]\n",
+			ret);
+		return -1;
+	}
+
+	return (uint64_t)doorbell << 32 | (uint64_t)auth_result;
+}
+
+static const struct ifpga_sec_ops n3000_sec_ops = {
+	.prepare = n3000_prepare,
+	.write_blk = n3000_write_blk,
+	.write_done = n3000_write_done,
+	.check_complete = n3000_check_complete,
+	.reload = n3000_reload,
+	.cancel = n3000_cancel,
+	.cleanup = NULL,
+	.get_hw_errinfo = n3000_get_hw_errinfo,
+};
+
+int init_sec_mgr(struct ifpga_fme_hw *fme)
+{
+	struct ifpga_hw *hw = NULL;
+	opae_share_data *sd = NULL;
+	struct ifpga_sec_mgr *smgr = NULL;
+
+	if (!fme || !fme->max10_dev)
+		return -ENODEV;
+
+	smgr = (struct ifpga_sec_mgr *)malloc(sizeof(*smgr));
+	if (!smgr) {
+		dev_err(NULL, "Failed to allocate memory for security manager\n");
+		return -ENOMEM;
+	}
+	fme->sec_mgr = smgr;
+
+	hw = (struct ifpga_hw *)fme->parent;
+	if (hw && hw->adapter && hw->adapter->shm.ptr) {
+		sd = (opae_share_data *)hw->adapter->shm.ptr;
+		smgr->rsu_control = &sd->rsu_ctrl;
+		smgr->rsu_status = &sd->rsu_stat;
+	} else {
+		smgr->rsu_control = NULL;
+		smgr->rsu_status = NULL;
+	}
+
+	if ((hw->pci_data->device_id == IFPGA_N3000_DID) &&
+		(hw->pci_data->vendor_id == IFPGA_N3000_VID)) {
+		smgr->ops = &n3000_sec_ops;
+		smgr->copy_speed = IFPGA_N3000_COPY_SPEED;
+	} else {
+		dev_err(NULL, "No operation for security manager\n");
+		smgr->ops = NULL;
+	}
+
+	smgr->fme = fme;
+	smgr->max10_dev = fme->max10_dev;
+
+	return 0;
+}
+
+void release_sec_mgr(struct ifpga_fme_hw *fme)
+{
+	struct ifpga_sec_mgr *smgr = NULL;
+
+	if (fme) {
+		smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
+		if (smgr) {
+			fme->sec_mgr = NULL;
+			free(smgr);
+		}
+	}
+}
diff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.h b/drivers/raw/ifpga/base/ifpga_sec_mgr.h
new file mode 100644
index 0000000000..fbeba561f4
--- /dev/null
+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef _IFPGA_FME_RSU_H_
+#define _IFPGA_FME_RSU_H_
+
+
+#include "ifpga_hw.h"
+
+#define IFPGA_N3000_VID     0x8086
+#define IFPGA_N3000_DID     0x0b30
+
+#define IFPGA_BOOT_TYPE_FPGA     0
+#define IFPGA_BOOT_TYPE_BMC      1
+
+#define IFPGA_BOOT_PAGE_FACTORY  0
+#define IFPGA_BOOT_PAGE_USER     1
+
+#define IFPGA_RSU_DATA_BLK_SIZE  32768
+#define IFPGA_RSU_START_RETRY    120
+#define IFPGA_RSU_WRITE_RETRY    10
+#define IFPGA_RSU_CANCEL_RETRY   30
+
+#define IFPGA_N3000_COPY_SPEED   42700
+
+/* status */
+#define IFPGA_RSU_IDLE       0
+#define IFPGA_RSU_PREPARE    1
+#define IFPGA_RSU_READY      2
+#define IFPGA_RSU_COPYING    3
+#define IFPGA_RSU_REBOOT     4
+
+#define IFPGA_RSU_GET_STAT(v)  (((v) >> 16) & 0xffff)
+#define IFPGA_RSU_GET_PROG(v)  ((v) & 0xffff)
+#define IFPGA_RSU_STATUS(s, p) ((((s) << 16) & 0xffff0000) | ((p) & 0xffff))
+
+/* control */
+#define IFPGA_RSU_ABORT      1
+
+#define IFPGA_DUAL_CFG_CTRL0     0x200020
+#define IFPGA_DUAL_CFG_CTRL1     0x200024
+
+#define IFPGA_SEC_START_INTERVAL_MS       100
+#define IFPGA_SEC_START_TIMEOUT_MS        20000
+#define IFPGA_NIOS_HANDSHAKE_INTERVAL_MS  100
+#define IFPGA_NIOS_HANDSHAKE_TIMEOUT_MS   5000
+
+#define IFPGA_RSU_ERR_HW_ERROR		-1
+#define IFPGA_RSU_ERR_TIMEOUT		-2
+#define IFPGA_RSU_ERR_CANCELED		-3
+#define IFPGA_RSU_ERR_BUSY			-4
+#define IFPGA_RSU_ERR_INVALID_SIZE	-5
+#define IFPGA_RSU_ERR_RW_ERROR		-6
+#define IFPGA_RSU_ERR_WEAROUT		-7
+#define IFPGA_RSU_ERR_FILE_READ		-8
+
+struct ifpga_sec_mgr;
+
+struct ifpga_sec_ops {
+	int (*prepare)(struct ifpga_sec_mgr *smgr);
+	int (*write_blk)(struct ifpga_sec_mgr *smgr, char *buf, uint32_t offset,
+		uint32_t size);
+	int (*write_done)(struct ifpga_sec_mgr *smgr);
+	int (*check_complete)(struct ifpga_sec_mgr *smgr);
+	int (*reload)(struct ifpga_sec_mgr *smgr, int type, int page);
+	int (*cancel)(struct ifpga_sec_mgr *smgr);
+	void (*cleanup)(struct ifpga_sec_mgr *smgr);
+	u64 (*get_hw_errinfo)(struct ifpga_sec_mgr *smgr);
+};
+
+struct ifpga_sec_mgr {
+	struct ifpga_fme_hw *fme;
+	struct intel_max10_device *max10_dev;
+	unsigned int rsu_length;
+	/* number of bytes that copied from staging area to working area
+	 * in one second, which is calculated by experiment
+	 */
+	unsigned int copy_speed;
+	unsigned int *rsu_control;
+	unsigned int *rsu_status;
+	const struct ifpga_sec_ops *ops;
+};
+
+int init_sec_mgr(struct ifpga_fme_hw *fme);
+void release_sec_mgr(struct ifpga_fme_hw *fme);
+int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
+	uint64_t *status);
+int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force);
+int fpga_reload(struct ifpga_fme_hw *fme, int type, int page);
+
+
+#endif /* _IFPGA_FME_RSU_H_ */
diff --git a/drivers/raw/ifpga/base/meson.build b/drivers/raw/ifpga/base/meson.build
index da2d6e33ca..3549afafa1 100644
--- a/drivers/raw/ifpga/base/meson.build
+++ b/drivers/raw/ifpga/base/meson.build
@@ -12,6 +12,8 @@ sources = [
 	'ifpga_port.c',
 	'ifpga_port_error.c',
 	'ifpga_fme_pr.c',
+	'ifpga_fme_rsu.c',
+	'ifpga_sec_mgr.c',
 	'opae_hw_api.c',
 	'opae_ifpga_hw_api.c',
 	'opae_debug.c',
diff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c
index d5cd5fe608..86ad88f720 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.c
+++ b/drivers/raw/ifpga/base/opae_hw_api.c
@@ -470,6 +470,8 @@ static void opae_adapter_shm_init(struct opae_adapter *adapter)
 	opae_mutex_init(&sd->i2c_mutex);
 	sd->ref_cnt = 0;
 	sd->dtb_size = SHM_BLK_SIZE;
+	sd->rsu_ctrl = 0;
+	sd->rsu_stat = 0;
 }
 
 static void *opae_adapter_shm_alloc(struct opae_adapter *adapter)
@@ -964,3 +966,60 @@ opae_mgr_get_board_info(struct opae_manager *mgr,
 
 	return -ENOENT;
 }
+
+/**
+ * opae_mgr_update_flash -  update image in flash.
+ * @mgr: targeted manager
+ * @image: name of image file
+ * @status: status of update
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_update_flash(struct opae_manager *mgr, const char *image,
+	uint64_t *status)
+{
+	if (!mgr)
+		return -EINVAL;
+
+	if (mgr->ops && mgr->ops->update_flash)
+		return mgr->ops->update_flash(mgr, image, status);
+
+	return -ENOENT;
+}
+
+/**
+ * opae_stop_flash_update -  stop flash update.
+ * @mgr: targeted manager
+ * @force: make sure the update process is stopped
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force)
+{
+	if (!mgr)
+		return -EINVAL;
+
+	if (mgr->ops && mgr->ops->stop_flash_update)
+		return mgr->ops->stop_flash_update(mgr, force);
+
+	return -ENOENT;
+}
+
+/**
+ * opae_mgr_reload -  reload FPGA.
+ * @mgr: targeted manager
+ * @type: FPGA type
+ * @page: reload from which page
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_reload(struct opae_manager *mgr, int type, int page)
+{
+	if (!mgr)
+		return -EINVAL;
+
+	if (mgr->ops && mgr->ops->reload)
+		return mgr->ops->reload(mgr, type, page);
+
+	return -ENOENT;
+}
diff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h
index e99ee4564c..91d26d9b5b 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.h
+++ b/drivers/raw/ifpga/base/opae_hw_api.h
@@ -55,6 +55,10 @@ struct opae_manager_ops {
 			unsigned int *value);
 	int (*get_board_info)(struct opae_manager *mgr,
 			struct opae_board_info **info);
+	int (*update_flash)(struct opae_manager *mgr, const char *image,
+			u64 *status);
+	int (*stop_flash_update)(struct opae_manager *mgr, int force);
+	int (*reload)(struct opae_manager *mgr, int type, int page);
 };
 
 /* networking management ops in FME */
@@ -276,6 +280,8 @@ typedef struct {
 			pthread_mutex_t i2c_mutex;
 			u32 ref_cnt;    /* reference count of shared memory */
 			u32 dtb_size;   /* actual length of DTB data in byte */
+			u32 rsu_ctrl;   /* used to control rsu */
+			u32 rsu_stat;   /* used to report status for rsu */
 		};
 	};
 	u8 dtb[SHM_BLK_SIZE];   /* DTB data */
@@ -354,4 +360,8 @@ int opae_manager_eth_group_read_reg(struct opae_manager *mgr, u8 group_id,
 		u8 type, u8 index, u16 addr, u32 *data);
 int opae_mgr_get_board_info(struct opae_manager *mgr,
 		struct opae_board_info **info);
+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);
 #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 1a526ea549..443e248fb3 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.c
+++ b/drivers/raw/ifpga/base/opae_intel_max10.c
@@ -51,6 +51,22 @@ int max10_sys_write(struct intel_max10_device *dev,
 	return max10_reg_write(dev, dev->base + offset, val);
 }
 
+int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset,
+					unsigned int msk, unsigned int val)
+{
+	int ret = 0;
+	unsigned int temp = 0;
+
+	ret = max10_sys_read(dev, offset, &temp);
+	if (ret < 0)
+		return ret;
+
+	temp &= ~msk;
+	temp |= val & msk;
+
+	return max10_sys_write(dev, offset, temp);
+}
+
 static struct max10_compatible_id max10_id_table[] = {
 	{.compatible = MAX10_PAC,},
 	{.compatible = MAX10_PAC_N3000,},
@@ -557,6 +573,36 @@ static int check_max10_version(struct intel_max10_device *dev)
 	return -ENODEV;
 }
 
+static int max10_staging_area_init(struct intel_max10_device *dev)
+{
+	char *fdt_root = dev->fdt_root;
+	int ret, offset = 0;
+	u64 start, size;
+
+	if (!fdt_root) {
+		dev_debug(dev,
+			"skip staging area init as not find Device Tree\n");
+		return -ENODEV;
+	}
+
+	dev->staging_area_size = 0;
+
+	fdt_for_each_subnode(offset, fdt_root, 0) {
+		if (fdt_node_check_compatible(fdt_root, offset,
+					      "ifpga-sec-mgr,staging-area"))
+			continue;
+
+		ret = fdt_get_reg(fdt_root, offset, 0, &start, &size);
+		if (!ret) {
+			dev->staging_area_base = start;
+			dev->staging_area_size = size;
+		}
+		return ret;
+	}
+
+	return -ENODEV;
+}
+
 static int
 max10_secure_hw_init(struct intel_max10_device *dev)
 {
@@ -581,6 +627,8 @@ max10_secure_hw_init(struct intel_max10_device *dev)
 
 	max10_sensor_init(dev, sysmgr_offset);
 
+	max10_staging_area_init(dev);
+
 	return 0;
 }
 
diff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h
index 123cdc48b9..670683f017 100644
--- a/drivers/raw/ifpga/base/opae_intel_max10.h
+++ b/drivers/raw/ifpga/base/opae_intel_max10.h
@@ -38,6 +38,8 @@ struct intel_max10_device {
 	unsigned int base; /* max10 base address */
 	u16 bus;
 	struct opae_sensor_list opae_sensor_list;
+	u32 staging_area_base;
+	u32 staging_area_size;
 };
 
 /* retimer speed */
@@ -98,6 +100,7 @@ struct opae_retimer_status {
 #define   MAX10_MAC_COUNT	GENMASK(23, 16)
 #define RSU_REG			0x2c
 #define   FPGA_RECONF_PAGE	GENMASK(2, 0)
+#define   FPGA_PAGE(p)		((p) & 0x1)
 #define   FPGA_RP_LOAD		BIT(3)
 #define   NIOS2_PRERESET	BIT(4)
 #define   NIOS2_HANG		BIT(5)
@@ -106,6 +109,9 @@ struct opae_retimer_status {
 #define   NIOS2_I2C2_POLL_STOP	BIT(13)
 #define   PKVL_EEPROM_LOAD	BIT(31)
 #define FPGA_RECONF_REG		0x30
+#define   SFPGA_RECONF_PAGE	GENMASK(22, 20)
+#define   SFPGA_PAGE(p)		(((p) & 0x1) << 20)
+#define   SFPGA_RP_LOAD		BIT(23)
 #define MAX10_TEST_REG		0x3c
 #define   COUNTDOWN_START	BIT(18)
 #define MAX10_BUILD_VER		0x68
@@ -118,8 +124,44 @@ struct opae_retimer_status {
 #define MAX10_DOORBELL		0x400
 #define   RSU_REQUEST		BIT(0)
 #define   SEC_PROGRESS		GENMASK(7, 4)
+#define   SEC_PROGRESS_G(v)	(((v) >> 4) & 0xf)
+#define   SEC_PROGRESS_IDLE				0x0
+#define   SEC_PROGRESS_PREPARE			0x1
+#define   SEC_PROGRESS_SLEEP			0x2
+#define   SEC_PROGRESS_READY			0x3
+#define   SEC_PROGRESS_AUTHENTICATING	0x4
+#define   SEC_PROGRESS_COPYING			0x5
+#define   SEC_PROGRESS_UPDATE_CANCEL	0x6
+#define   SEC_PROGRESS_PROGRAM_KEY_HASH	0x7
+#define   SEC_PROGRESS_RSU_DONE			0x8
+#define   SEC_PROGRESS_PKVL_PROM_DONE	0x9
 #define   HOST_STATUS		GENMASK(11, 8)
+#define   HOST_STATUS_S(v)	(((v) << 8) & 0xf00)
+#define   HOST_STATUS_IDLE			0x0
+#define   HOST_STATUS_WRITE_DONE	0x1
+#define   HOST_STATUS_ABORT_RSU		0x2
 #define   SEC_STATUS		GENMASK(23, 16)
+#define   SEC_STATUS_G(v)	(((v) >> 16) & 0xff)
+#define   SEC_STATUS_NORMAL			0x0
+#define   SEC_STATUS_TIMEOUT		0x1
+#define   SEC_STATUS_AUTH_FAIL		0x2
+#define   SEC_STATUS_COPY_FAIL		0x3
+#define   SEC_STATUS_FATAL			0x4
+#define   SEC_STATUS_PKVL_REJECT	0x5
+#define   SEC_STATUS_NON_INC		0x6
+#define   SEC_STATUS_ERASE_FAIL		0x7
+#define   SEC_STATUS_WEAROUT		0x8
+#define   SEC_STATUS_NIOS_OK		0x80
+#define   SEC_STATUS_USER_OK		0x81
+#define   SEC_STATUS_FACTORY_OK		0x82
+#define   SEC_STATUS_USER_FAIL		0x83
+#define   SEC_STATUS_FACTORY_FAIL	0x84
+#define   SEC_STATUS_NIOS_FLASH_ERR	0x85
+#define   SEC_STATUS_FPGA_FLASH_ERR	0x86
+#define   CONFIG_SEL		BIT(28)
+#define   CONFIG_SEL_S(v)	(((v) & 0x1) << 28)
+#define   REBOOT_REQ		BIT(29)
+#define MAX10_AUTH_RESULT	0x404
 
 /* PKVL related registers, in system register region */
 #define PKVL_POLLING_CTRL		0x80
@@ -149,6 +191,8 @@ int max10_sys_read(struct intel_max10_device *dev,
 	unsigned int offset, unsigned int *val);
 int max10_sys_write(struct intel_max10_device *dev,
 	unsigned int offset, unsigned int val);
+int max10_sys_update_bits(struct intel_max10_device *dev,
+	unsigned int offset, unsigned int msk, unsigned int val);
 struct intel_max10_device *
 intel_max10_device_probe(struct altera_spi_device *spi,
 		int chipselect);
diff --git a/drivers/raw/ifpga/meson.build b/drivers/raw/ifpga/meson.build
index 027ff80562..60ea59ae28 100644
--- a/drivers/raw/ifpga/meson.build
+++ b/drivers/raw/ifpga/meson.build
@@ -13,8 +13,10 @@ objs = [base_objs]
 deps += ['ethdev', 'rawdev', 'pci', 'bus_pci', 'kvargs',
 	'bus_vdev', 'bus_ifpga', 'net', 'net_i40e', 'net_ipn3ke']
 
-sources = files('ifpga_rawdev.c')
+sources = files('ifpga_rawdev.c', 'rte_pmd_ifpga.c')
 
 includes += include_directories('base')
 includes += include_directories('../../net/ipn3ke')
 includes += include_directories('../../net/i40e')
+
+headers = files('rte_pmd_ifpga.h')
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.c b/drivers/raw/ifpga/rte_pmd_ifpga.c
new file mode 100644
index 0000000000..af6f175e98
--- /dev/null
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.c
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_rawdev.h>
+#include <rte_rawdev_pmd.h>
+#include "rte_pmd_ifpga.h"
+#include "ifpga_rawdev.h"
+#include "base/ifpga_sec_mgr.h"
+
+
+int
+rte_pmd_ifpga_get_dev_id(const char *pci_addr, uint16_t *dev_id)
+{
+	struct rte_pci_addr addr;
+	struct rte_rawdev *rdev = NULL;
+	char rdev_name[RTE_RAWDEV_NAME_MAX_LEN] = {0};
+
+	if (!pci_addr || !dev_id) {
+		IFPGA_RAWDEV_PMD_ERR("Input parameter is invalid.");
+		return -EINVAL;
+	}
+
+	if (strnlen(pci_addr, PCI_PRI_STR_SIZE) == PCI_PRI_STR_SIZE) {
+		IFPGA_RAWDEV_PMD_ERR("PCI address is too long.");
+		return -EINVAL;
+	}
+
+	if (rte_pci_addr_parse(pci_addr, &addr)) {
+		IFPGA_RAWDEV_PMD_ERR("PCI address %s is invalid.", pci_addr);
+		return -EINVAL;
+	}
+
+	snprintf(rdev_name, RTE_RAWDEV_NAME_MAX_LEN, "IFPGA:%02x:%02x.%x",
+		addr.bus, addr.devid, addr.function);
+	rdev = rte_rawdev_pmd_get_named_dev(rdev_name);
+	if (!rdev) {
+		IFPGA_RAWDEV_PMD_DEBUG("%s is not probed by ifpga driver.",
+			pci_addr);
+		return -ENODEV;
+	}
+	*dev_id = rdev->dev_id;
+
+	return 0;
+}
+
+static struct rte_rawdev *
+get_rte_rawdev(uint16_t dev_id)
+{
+	struct rte_rawdev *dev = NULL;
+
+	if (dev_id >= RTE_RAWDEV_MAX_DEVS)
+		return NULL;
+
+	dev = &rte_rawdevs[dev_id];
+	if (dev->attached == RTE_RAWDEV_ATTACHED)
+		return dev;
+
+	return NULL;
+}
+
+static struct opae_adapter *
+get_opae_adapter(uint16_t dev_id)
+{
+	struct rte_rawdev *dev = NULL;
+	struct opae_adapter *adapter = NULL;
+
+	dev = get_rte_rawdev(dev_id);
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("Device ID %u is invalid.", dev_id);
+		return NULL;
+	}
+
+	adapter = ifpga_rawdev_get_priv(dev);
+	if (!adapter) {
+		IFPGA_RAWDEV_PMD_ERR("Adapter is not registered.");
+		return NULL;
+	}
+
+	return adapter;
+}
+
+static opae_share_data *
+get_share_data(struct opae_adapter *adapter)
+{
+	opae_share_data *sd = NULL;
+
+	if (!adapter)
+		return NULL;
+
+	sd = (opae_share_data *)adapter->shm.ptr;
+	if (!sd) {
+		IFPGA_RAWDEV_PMD_ERR("Share data is not initialized.");
+		return NULL;
+	}
+
+	return sd;
+}
+
+int
+rte_pmd_ifpga_update_flash(uint16_t dev_id, const char *image,
+	uint64_t *status)
+{
+	struct opae_adapter *adapter = NULL;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	return opae_mgr_update_flash(adapter->mgr, image, status);
+}
+
+int
+rte_pmd_ifpga_stop_update(uint16_t dev_id, int force)
+{
+	struct opae_adapter *adapter = NULL;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	return opae_mgr_stop_flash_update(adapter->mgr, force);
+}
+
+int
+rte_pmd_ifpga_reboot_try(uint16_t dev_id)
+{
+	struct opae_adapter *adapter = NULL;
+	opae_share_data *sd = NULL;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	sd = get_share_data(adapter);
+	if (!sd)
+		return -ENOMEM;
+
+	opae_adapter_lock(adapter, -1);
+	if (IFPGA_RSU_GET_STAT(sd->rsu_stat) != IFPGA_RSU_IDLE) {
+		opae_adapter_unlock(adapter);
+		IFPGA_RAWDEV_PMD_WARN("Update or reboot is in progress.");
+		return -EBUSY;
+	}
+	sd->rsu_stat = IFPGA_RSU_STATUS(IFPGA_RSU_REBOOT, 0);
+	opae_adapter_unlock(adapter);
+
+	return 0;
+}
+
+int
+rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page)
+{
+	struct opae_adapter *adapter = NULL;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	return opae_mgr_reload(adapter->mgr, type, page);
+}
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.h b/drivers/raw/ifpga/rte_pmd_ifpga.h
new file mode 100644
index 0000000000..023a011116
--- /dev/null
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#ifndef _RTE_PMD_IFPGA_H_
+#define _RTE_PMD_IFPGA_H_
+
+/**
+ * @file rte_pmd_ifpga.h
+ *
+ * ifpga PMD specific functions.
+ *
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get raw device ID from PCI address string like 'Domain:Bus:Dev.Func'
+ *
+ * @param pci_addr
+ *    The PCI address of specified Intel FPGA device.
+ * @param dev_id
+ *    The buffer to output device ID.
+ * @return
+ *   - (0) if successful.
+ *   - (-EINVAL) if bad parameter.
+ *   - (-ENODEV) if FPGA is not probed by ifpga driver.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_get_dev_id(const char *pci_addr, uint16_t *dev_id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Update image flash of specified Intel FPGA device
+ *
+ * @param dev_id
+ *   The raw device ID of specified Intel FPGA device.
+ * @param image
+ *   The image file name string.
+ * @param status
+ *   The detailed update status for debug.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-EINVAL) if bad parameter or staging area is not initialized.
+ *   - (-EBUSY) if FPGA is updating or rebooting.
+ *   - (-EIO) if failed to open image file.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_update_flash(uint16_t dev_id, const char *image,
+	uint64_t *status);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Stop flash update of specified Intel FPGA device
+ *
+ * @param dev_id
+ *   The raw device ID of specified Intel FPGA device.
+ * @param force
+ *   Abort the update process by writing register if set non-zero.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-EINVAL) if bad parameter.
+ *   - (-EAGAIN) if failed with force.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_stop_update(uint16_t dev_id, int force);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Check current Intel FPGA status and change it to reboot status if it is idle
+ *
+ * @param dev_id
+ *    The raw device ID of specified Intel FPGA device.
+ * @return
+ *   - (0) if FPGA is ready to reboot.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-ENOMEM) if share data is not initialized.
+ *   - (-EBUSY) if FPGA is updating or rebooting.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_reboot_try(uint16_t dev_id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Trigger full reconfiguration of specified Intel FPGA device
+ *
+ * @param dev_id
+ *    The raw device ID of specified Intel FPGA device.
+ * @param type
+ *    Select reconfiguration type.
+ *    0 - reconfigure FPGA only.
+ *    1 - reboot the whole card including FPGA.
+ * @param page
+ *    Select image from which flash partition.
+ *    0 - factory partition.
+ *    1 - user partition.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-EINVAL) if bad parameter.
+ *   - (-EBUSY) if failed to access BMC register.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PMD_IFPGA_H_ */
diff --git a/drivers/raw/ifpga/version.map b/drivers/raw/ifpga/version.map
index 4a76d1d52d..16584f7fe4 100644
--- a/drivers/raw/ifpga/version.map
+++ b/drivers/raw/ifpga/version.map
@@ -1,3 +1,14 @@
 DPDK_21 {
 	local: *;
 };
+
+EXPERIMENTAL {
+	global:
+
+	# added in 21.05
+	rte_pmd_ifpga_get_dev_id;
+	rte_pmd_ifpga_update_flash;
+	rte_pmd_ifpga_stop_update;
+	rte_pmd_ifpga_reboot_try;
+	rte_pmd_ifpga_reload;
+};
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH v16 2/3] raw/ifpga: add APIs to get fpga information
  2021-03-03  2:34 [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Wei Huang
  2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 1/3] raw/ifpga: add fpga rsu APIs Wei Huang
@ 2021-03-03  2:34 ` Wei Huang
  2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 3/3] raw/ifpga: add miscellaneous APIs Wei Huang
  2021-03-05  8:54 ` [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Zhang, Qi Z
  3 siblings, 0 replies; 6+ messages in thread
From: Wei Huang @ 2021-03-03  2:34 UTC (permalink / raw)
  To: dev, rosen.xu, qi.z.zhang; +Cc: stable, tianfei.zhang, ferruh.yigit, Wei Huang

There are some information data can be got from FPGA, they are
implemented in below APIs:
1. rte_pmd_ifpga_get_property() get properties of FPGA (include BMC).
2. rte_pmd_ifpga_get_phy_info() get information of PHY connect to FPGA.
3. rte_pmd_ifpga_get_rsu_status() get status of rsu process.

Signed-off-by: Wei Huang <wei.huang@intel.com>
Acked-by: Tianfei Zhang <tianfei.zhang@intel.com>
Acked-by: Rosen Xu <rosen.xu@intel.com>
---
v2: implement APIs in rte_pmd_ifpga.c
---
 drivers/raw/ifpga/base/ifpga_api.c         |   8 +
 drivers/raw/ifpga/base/ifpga_defines.h     |   1 +
 drivers/raw/ifpga/base/ifpga_feature_dev.c |  21 ++
 drivers/raw/ifpga/base/ifpga_feature_dev.h |   1 +
 drivers/raw/ifpga/base/ifpga_fme.c         |  28 ++-
 drivers/raw/ifpga/base/opae_hw_api.c       |  18 ++
 drivers/raw/ifpga/base/opae_hw_api.h       |   2 +
 drivers/raw/ifpga/base/opae_ifpga_hw_api.h |   1 +
 drivers/raw/ifpga/rte_pmd_ifpga.c          | 221 +++++++++++++++++++++
 drivers/raw/ifpga/rte_pmd_ifpga.h          | 110 ++++++++++
 drivers/raw/ifpga/version.map              |   3 +
 11 files changed, 412 insertions(+), 2 deletions(-)

diff --git a/drivers/raw/ifpga/base/ifpga_api.c b/drivers/raw/ifpga/base/ifpga_api.c
index 1aedf150bc..4610ef101e 100644
--- a/drivers/raw/ifpga/base/ifpga_api.c
+++ b/drivers/raw/ifpga/base/ifpga_api.c
@@ -229,6 +229,13 @@ static int ifpga_mgr_get_board_info(struct opae_manager *mgr,
 	return 0;
 }
 
+static int ifpga_mgr_get_uuid(struct opae_manager *mgr, struct uuid *uuid)
+{
+	struct ifpga_fme_hw *fme = mgr->data;
+
+	return fpga_get_pr_uuid(fme, uuid);
+}
+
 static int ifpga_mgr_update_flash(struct opae_manager *mgr, const char *image,
 	u64 *status)
 {
@@ -256,6 +263,7 @@ struct opae_manager_ops ifpga_mgr_ops = {
 	.get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info,
 	.get_sensor_value = ifpga_mgr_get_sensor_value,
 	.get_board_info = ifpga_mgr_get_board_info,
+	.get_uuid = ifpga_mgr_get_uuid,
 	.update_flash = ifpga_mgr_update_flash,
 	.stop_flash_update = ifpga_mgr_stop_flash_update,
 	.reload = ifpga_mgr_reload,
diff --git a/drivers/raw/ifpga/base/ifpga_defines.h b/drivers/raw/ifpga/base/ifpga_defines.h
index 9f0147d1ed..dca1518a83 100644
--- a/drivers/raw/ifpga/base/ifpga_defines.h
+++ b/drivers/raw/ifpga/base/ifpga_defines.h
@@ -1727,6 +1727,7 @@ struct opae_board_info {
 	u8 seu;
 	u8 ptp;
 
+	u32 boot_page;
 	u32 max10_version;
 	u32 nios_fw_version;
 	u32 nums_of_retimer;
diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.c b/drivers/raw/ifpga/base/ifpga_feature_dev.c
index 0f852a75ad..08135137ad 100644
--- a/drivers/raw/ifpga/base/ifpga_feature_dev.c
+++ b/drivers/raw/ifpga/base/ifpga_feature_dev.c
@@ -87,6 +87,27 @@ int fpga_get_afu_uuid(struct ifpga_port_hw *port, struct uuid *uuid)
 	return 0;
 }
 
+int fpga_get_pr_uuid(struct ifpga_fme_hw *fme, struct uuid *uuid)
+{
+	struct feature_fme_pr *fme_pr;
+	u64 guidl, guidh;
+
+	if (!fme || !uuid)
+		return -EINVAL;
+
+	fme_pr = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_PR_MGMT);
+
+	spinlock_lock(&fme->lock);
+	guidl = readq(&fme_pr->fme_pr_intfc_id_l);
+	guidh = readq(&fme_pr->fme_pr_intfc_id_h);
+	spinlock_unlock(&fme->lock);
+
+	opae_memcpy(uuid->b, &guidl, sizeof(u64));
+	opae_memcpy(uuid->b + 8, &guidh, sizeof(u64));
+
+	return 0;
+}
+
 /* Mask / Unmask Port Errors by the Error Mask register. */
 void port_err_mask(struct ifpga_port_hw *port, bool mask)
 {
diff --git a/drivers/raw/ifpga/base/ifpga_feature_dev.h b/drivers/raw/ifpga/base/ifpga_feature_dev.h
index 2b1309b44a..b355d22b0e 100644
--- a/drivers/raw/ifpga/base/ifpga_feature_dev.h
+++ b/drivers/raw/ifpga/base/ifpga_feature_dev.h
@@ -103,6 +103,7 @@ is_port_feature_present(struct ifpga_port_hw *port, int index)
 }
 
 int fpga_get_afu_uuid(struct ifpga_port_hw *port, struct uuid *uuid);
+int fpga_get_pr_uuid(struct ifpga_fme_hw *fme, struct uuid *uuid);
 
 int __fpga_port_disable(struct ifpga_port_hw *port);
 void __fpga_port_enable(struct ifpga_port_hw *port);
diff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c
index 34fd9a818e..43c7b9c3dc 100644
--- a/drivers/raw/ifpga/base/ifpga_fme.c
+++ b/drivers/raw/ifpga/base/ifpga_fme.c
@@ -101,6 +101,24 @@ static int fme_hdr_get_ports_num(struct ifpga_fme_hw *fme, u64 *ports_num)
 	return 0;
 }
 
+static int fme_hdr_get_port_type(struct ifpga_fme_hw *fme, u64 *port_type)
+{
+	struct feature_fme_header *fme_hdr
+		= get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER);
+	struct feature_fme_port pt;
+	u32 port = (u32)((*port_type >> 32) & 0xffffffff);
+
+	pt.csr = readq(&fme_hdr->port[port]);
+	if (!pt.port_implemented)
+		return -ENODEV;
+	if (pt.afu_access_control)
+		*port_type |= 0x1;
+	else
+		*port_type &= ~0x1;
+
+	return 0;
+}
+
 static int fme_hdr_get_cache_size(struct ifpga_fme_hw *fme, u64 *cache_size)
 {
 	struct feature_fme_header *fme_hdr
@@ -179,6 +197,8 @@ fme_hdr_get_prop(struct ifpga_feature *feature, struct feature_prop *prop)
 		return fme_hdr_get_bitstream_id(fme, &prop->data);
 	case FME_HDR_PROP_BITSTREAM_METADATA:
 		return fme_hdr_get_bitstream_metadata(fme, &prop->data);
+	case FME_HDR_PROP_PORT_TYPE:
+		return fme_hdr_get_port_type(fme, &prop->data);
 	}
 
 	return -ENOENT;
@@ -891,13 +911,17 @@ static int fme_get_board_interface(struct ifpga_fme_hw *fme)
 			fme->board_info.nums_of_fvl,
 			fme->board_info.ports_per_fvl);
 
+	if (max10_sys_read(fme->max10_dev, FPGA_PAGE_INFO, &val))
+		return -EINVAL;
+	fme->board_info.boot_page = val & 0x7;
+
 	if (max10_sys_read(fme->max10_dev, MAX10_BUILD_VER, &val))
 		return -EINVAL;
-	fme->board_info.max10_version = val & 0xffffff;
+	fme->board_info.max10_version = val;
 
 	if (max10_sys_read(fme->max10_dev, NIOS2_FW_VERSION, &val))
 		return -EINVAL;
-	fme->board_info.nios_fw_version = val & 0xffffff;
+	fme->board_info.nios_fw_version = val;
 
 	dev_info(fme, "max10 version 0x%x, nios fw version 0x%x\n",
 		fme->board_info.max10_version,
diff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c
index 86ad88f720..11c9887c7f 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.c
+++ b/drivers/raw/ifpga/base/opae_hw_api.c
@@ -967,6 +967,24 @@ opae_mgr_get_board_info(struct opae_manager *mgr,
 	return -ENOENT;
 }
 
+/**
+ * opae_mgr_get_uuid -  get manager's UUID.
+ * @mgr: targeted manager
+ * @uuid: a pointer to UUID
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_get_uuid(struct opae_manager *mgr, struct uuid *uuid)
+{
+	if (!mgr || !uuid)
+		return -EINVAL;
+
+	if (mgr->ops && mgr->ops->get_uuid)
+		return mgr->ops->get_uuid(mgr, uuid);
+
+	return -ENOENT;
+}
+
 /**
  * opae_mgr_update_flash -  update image in flash.
  * @mgr: targeted manager
diff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h
index 91d26d9b5b..7e04b56471 100644
--- a/drivers/raw/ifpga/base/opae_hw_api.h
+++ b/drivers/raw/ifpga/base/opae_hw_api.h
@@ -55,6 +55,7 @@ struct opae_manager_ops {
 			unsigned int *value);
 	int (*get_board_info)(struct opae_manager *mgr,
 			struct opae_board_info **info);
+	int (*get_uuid)(struct opae_manager *mgr, struct uuid *uuid);
 	int (*update_flash)(struct opae_manager *mgr, const char *image,
 			u64 *status);
 	int (*stop_flash_update)(struct opae_manager *mgr, int force);
@@ -360,6 +361,7 @@ int opae_manager_eth_group_read_reg(struct opae_manager *mgr, u8 group_id,
 		u8 type, u8 index, u16 addr, u32 *data);
 int opae_mgr_get_board_info(struct opae_manager *mgr,
 		struct opae_board_info **info);
+int opae_mgr_get_uuid(struct opae_manager *mgr, struct uuid *uuid);
 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);
diff --git a/drivers/raw/ifpga/base/opae_ifpga_hw_api.h b/drivers/raw/ifpga/base/opae_ifpga_hw_api.h
index bab33862ee..ffdbebf704 100644
--- a/drivers/raw/ifpga/base/opae_ifpga_hw_api.h
+++ b/drivers/raw/ifpga/base/opae_ifpga_hw_api.h
@@ -61,6 +61,7 @@ struct feature_prop {
 #define FME_HDR_PROP_SOCKET_ID		0x5	/* RDONLY */
 #define FME_HDR_PROP_BITSTREAM_ID		0x6	/* RDONLY */
 #define FME_HDR_PROP_BITSTREAM_METADATA	0x7	/* RDONLY */
+#define FME_HDR_PROP_PORT_TYPE		0x8	/* RDWR */
 
 /* FME error reporting feature's properties */
 /* FME error reporting properties format */
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.c b/drivers/raw/ifpga/rte_pmd_ifpga.c
index af6f175e98..8e04e22d5f 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.c
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.c
@@ -8,6 +8,7 @@
 #include <rte_rawdev_pmd.h>
 #include "rte_pmd_ifpga.h"
 #include "ifpga_rawdev.h"
+#include "base/ifpga_api.h"
 #include "base/ifpga_sec_mgr.h"
 
 
@@ -99,6 +100,226 @@ get_share_data(struct opae_adapter *adapter)
 	return sd;
 }
 
+int
+rte_pmd_ifpga_get_rsu_status(uint16_t dev_id, uint32_t *stat, uint32_t *prog)
+{
+	struct opae_adapter *adapter = NULL;
+	opae_share_data *sd = NULL;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	sd = get_share_data(adapter);
+	if (!sd)
+		return -ENOMEM;
+
+	if (stat)
+		*stat = IFPGA_RSU_GET_STAT(sd->rsu_stat);
+	if (prog)
+		*prog = IFPGA_RSU_GET_PROG(sd->rsu_stat);
+
+	return 0;
+}
+
+static int
+ifpga_is_rebooting(struct opae_adapter *adapter)
+{
+	opae_share_data *sd = NULL;
+
+	sd = get_share_data(adapter);
+	if (!sd)
+		return 1;
+
+	if (IFPGA_RSU_GET_STAT(sd->rsu_stat) == IFPGA_RSU_REBOOT) {
+		IFPGA_RAWDEV_PMD_WARN("Reboot is in progress.");
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+get_common_property(struct opae_adapter *adapter,
+	rte_pmd_ifpga_common_prop *prop)
+{
+	struct ifpga_fme_hw *fme = NULL;
+	struct opae_board_info *info = NULL;
+	struct feature_prop fp;
+	struct uuid pr_id;
+	int ret = 0;
+
+	if (!adapter || !prop)
+		return -EINVAL;
+
+	if (!adapter->mgr || !adapter->mgr->data) {
+		IFPGA_RAWDEV_PMD_ERR("Manager is not registered.");
+		return -ENODEV;
+	}
+
+	fme = adapter->mgr->data;
+	fp.feature_id = FME_FEATURE_ID_HEADER;
+	fp.prop_id = FME_HDR_PROP_PORTS_NUM;
+	ret = ifpga_get_prop(fme->parent, FEATURE_FIU_ID_FME, 0, &fp);
+	if (ret) {
+		IFPGA_RAWDEV_PMD_ERR("Failed to get port number.");
+		return ret;
+	}
+	prop->num_ports = fp.data;
+
+	fp.prop_id = FME_HDR_PROP_BITSTREAM_ID;
+	ret = ifpga_get_prop(fme->parent, FEATURE_FIU_ID_FME, 0, &fp);
+	if (ret) {
+		IFPGA_RAWDEV_PMD_ERR("Failed to get bitstream ID.");
+		return ret;
+	}
+	prop->bitstream_id = fp.data;
+
+	fp.prop_id = FME_HDR_PROP_BITSTREAM_METADATA;
+	ret = ifpga_get_prop(fme->parent, FEATURE_FIU_ID_FME, 0, &fp);
+	if (ret) {
+		IFPGA_RAWDEV_PMD_ERR("Failed to get bitstream metadata.");
+		return ret;
+	}
+	prop->bitstream_metadata = fp.data;
+
+	ret = opae_mgr_get_uuid(adapter->mgr, &pr_id);
+	if (ret) {
+		IFPGA_RAWDEV_PMD_ERR("Failed to get PR ID.");
+		return ret;
+	}
+	memcpy(prop->pr_id.b, pr_id.b, sizeof(rte_pmd_ifpga_uuid));
+
+	ret = opae_mgr_get_board_info(adapter->mgr, &info);
+	if (ret) {
+		IFPGA_RAWDEV_PMD_ERR("Failed to get board info.");
+		return ret;
+	}
+	prop->boot_page = info->boot_page;
+	prop->bmc_version = info->max10_version;
+	prop->bmc_nios_version = info->nios_fw_version;
+
+	return 0;
+}
+
+static int
+get_port_property(struct opae_adapter *adapter, uint16_t port,
+	rte_pmd_ifpga_port_prop *prop)
+{
+	struct ifpga_fme_hw *fme = NULL;
+	struct feature_prop fp;
+	struct opae_accelerator *acc = NULL;
+	struct uuid afu_id;
+	int ret = 0;
+
+	if (!adapter || !prop)
+		return -EINVAL;
+
+	if (!adapter->mgr || !adapter->mgr->data) {
+		IFPGA_RAWDEV_PMD_ERR("Manager is not registered.");
+		return -ENODEV;
+	}
+
+	fme = adapter->mgr->data;
+	fp.feature_id = FME_FEATURE_ID_HEADER;
+	fp.prop_id = FME_HDR_PROP_PORT_TYPE;
+	fp.data = port;
+	fp.data <<= 32;
+	ret = ifpga_get_prop(fme->parent, FEATURE_FIU_ID_FME, 0, &fp);
+	if (ret)
+		return ret;
+	prop->type = fp.data & 0xffffffff;
+
+	if (prop->type == 0) {
+		acc = opae_adapter_get_acc(adapter, port);
+		ret = opae_acc_get_uuid(acc, &afu_id);
+		if (ret) {
+			IFPGA_RAWDEV_PMD_ERR("Failed to get port%u AFU ID.",
+				port);
+			return ret;
+		}
+		memcpy(prop->afu_id.b, afu_id.b, sizeof(rte_pmd_ifpga_uuid));
+	}
+
+	return 0;
+}
+
+int
+rte_pmd_ifpga_get_property(uint16_t dev_id, rte_pmd_ifpga_prop *prop)
+{
+	struct opae_adapter *adapter = NULL;
+	uint32_t i = 0;
+	int ret = 0;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	opae_adapter_lock(adapter, -1);
+	if (ifpga_is_rebooting(adapter)) {
+		ret = -EBUSY;
+		goto unlock_dev;
+	}
+
+	ret = get_common_property(adapter, &prop->common);
+	if (ret) {
+		ret = -EIO;
+		goto unlock_dev;
+	}
+
+	for (i = 0; i < prop->common.num_ports; i++) {
+		ret = get_port_property(adapter, i, &prop->port[i]);
+		if (ret) {
+			ret = -EIO;
+			break;
+		}
+	}
+
+unlock_dev:
+	opae_adapter_unlock(adapter);
+	return ret;
+}
+
+int
+rte_pmd_ifpga_get_phy_info(uint16_t dev_id, rte_pmd_ifpga_phy_info *info)
+{
+	struct opae_adapter *adapter = NULL;
+	struct opae_retimer_info rtm_info;
+	struct opae_retimer_status rtm_status;
+	int ret = 0;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	opae_adapter_lock(adapter, -1);
+	if (ifpga_is_rebooting(adapter)) {
+		ret = -EBUSY;
+		goto unlock_dev;
+	}
+
+	ret = opae_manager_get_retimer_info(adapter->mgr, &rtm_info);
+	if (ret) {
+		IFPGA_RAWDEV_PMD_ERR("Failed to get retimer info.");
+		ret = -EIO;
+		goto unlock_dev;
+	}
+	info->num_retimers = rtm_info.nums_retimer;
+
+	ret = opae_manager_get_retimer_status(adapter->mgr, &rtm_status);
+	if (ret) {
+		IFPGA_RAWDEV_PMD_ERR("Failed to get retimer status.");
+		ret = -EIO;
+		goto unlock_dev;
+	}
+	info->link_speed = rtm_status.speed;
+	info->link_status = rtm_status.line_link_bitmap;
+
+unlock_dev:
+	opae_adapter_unlock(adapter);
+	return ret;
+}
+
 int
 rte_pmd_ifpga_update_flash(uint16_t dev_id, const char *image,
 	uint64_t *status)
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.h b/drivers/raw/ifpga/rte_pmd_ifpga.h
index 023a011116..633f6e9d1b 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.h
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.h
@@ -18,6 +18,55 @@
 extern "C" {
 #endif
 
+#include <stdint.h>
+
+#define IFPGA_MAX_PORT_NUM   4
+
+/**
+ * UUID data structure.
+ */
+typedef struct {
+	uint8_t b[16];
+} rte_pmd_ifpga_uuid;
+
+/**
+ * FME property data structure.
+ */
+typedef struct {
+	uint32_t num_ports;
+	uint32_t boot_page;
+	uint64_t bitstream_id;
+	uint64_t bitstream_metadata;
+	rte_pmd_ifpga_uuid pr_id;
+	uint32_t bmc_version;
+	uint32_t bmc_nios_version;
+} rte_pmd_ifpga_common_prop;
+
+/**
+ * port property data structure.
+ */
+typedef struct {
+	rte_pmd_ifpga_uuid afu_id;
+	uint32_t type;   /* AFU memory access control type */
+} rte_pmd_ifpga_port_prop;
+
+/**
+ * FPGA property data structure.
+ */
+typedef struct {
+	rte_pmd_ifpga_common_prop  common;
+	rte_pmd_ifpga_port_prop    port[IFPGA_MAX_PORT_NUM];
+} rte_pmd_ifpga_prop;
+
+/**
+ * PHY information data structure.
+ */
+typedef struct {
+	uint32_t num_retimers;
+	uint32_t link_speed;
+	uint32_t link_status;
+} rte_pmd_ifpga_phy_info;
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
@@ -37,6 +86,67 @@ __rte_experimental
 int
 rte_pmd_ifpga_get_dev_id(const char *pci_addr, uint16_t *dev_id);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get current RSU status of the specified Intel FPGA device
+ *
+ * @param dev_id
+ *    The raw device ID of specified Intel FPGA device.
+ * @param stat
+ *    The buffer to output RSU status.
+ * @param prog
+ *    The buffer to output RSU progress.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-ENOMEM) if share data is not initialized.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_get_rsu_status(uint16_t dev_id, uint32_t *stat, uint32_t *prog);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get FPGA property of specified Intel FPGA device
+ *
+ * @param dev_id
+ *    The raw device ID of specified Intel FPGA device.
+ * @param prop
+ *    The data pointer of FPGA property buffer.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-EBUSY) if FPGA is rebooting.
+ *   - (-EIO) if failed to access hardware.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_get_property(uint16_t dev_id, rte_pmd_ifpga_prop *prop);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get PHY information of specified Intel FPGA device
+ *
+ * @param dev_id
+ *    The raw device ID of specified Intel FPGA device.
+ * @param info
+ *    The data pointer of PHY information buffer.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-EBUSY) if FPGA is rebooting.
+ *   - (-EIO) if failed to access hardware.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_get_phy_info(uint16_t dev_id, rte_pmd_ifpga_phy_info *info);
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
diff --git a/drivers/raw/ifpga/version.map b/drivers/raw/ifpga/version.map
index 16584f7fe4..ca6f7f5810 100644
--- a/drivers/raw/ifpga/version.map
+++ b/drivers/raw/ifpga/version.map
@@ -7,6 +7,9 @@ EXPERIMENTAL {
 
 	# added in 21.05
 	rte_pmd_ifpga_get_dev_id;
+	rte_pmd_ifpga_get_rsu_status;
+	rte_pmd_ifpga_get_property;
+	rte_pmd_ifpga_get_phy_info;
 	rte_pmd_ifpga_update_flash;
 	rte_pmd_ifpga_stop_update;
 	rte_pmd_ifpga_reboot_try;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH v16 3/3] raw/ifpga: add miscellaneous APIs
  2021-03-03  2:34 [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Wei Huang
  2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 1/3] raw/ifpga: add fpga rsu APIs Wei Huang
  2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 2/3] raw/ifpga: add APIs to get fpga information Wei Huang
@ 2021-03-03  2:34 ` Wei Huang
  2021-03-05  8:54 ` [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Zhang, Qi Z
  3 siblings, 0 replies; 6+ messages in thread
From: Wei Huang @ 2021-03-03  2:34 UTC (permalink / raw)
  To: dev, rosen.xu, qi.z.zhang; +Cc: stable, tianfei.zhang, ferruh.yigit, Wei Huang

Below miscellaneous APIs are used to implement OPAE application.
1. rte_pmd_ifpga_get_pci_bus() get PCI bus ifpga driver registered.
2. rte_pmd_ifpga_partial_reconfigure() do partial reconfiguration.
3. rte_pmd_ifpga_cleanup() free software resources allocated by driver.
4. rte_pmd_ifpga_set_rsu_status() set status of rsu process.

Signed-off-by: Wei Huang <wei.huang@intel.com>
Acked-by: Tianfei Zhang <tianfei.zhang@intel.com>
Acked-by: Rosen Xu <rosen.xu@intel.com>
---
v2: implement APIs in rte_pmd_ifpga.c
---
 drivers/raw/ifpga/ifpga_rawdev.c  | 30 ++++++++++++++
 drivers/raw/ifpga/ifpga_rawdev.h  |  7 +++-
 drivers/raw/ifpga/rte_pmd_ifpga.c | 45 +++++++++++++++++++++
 drivers/raw/ifpga/rte_pmd_ifpga.h | 66 +++++++++++++++++++++++++++++++
 drivers/raw/ifpga/version.map     |  4 ++
 5 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 27129b133e..05d79bfcc2 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -1737,3 +1737,33 @@ RTE_PMD_REGISTER_PARAM_STRING(ifpga_rawdev_cfg,
 	"ifpga=<string> "
 	"port=<int> "
 	"afu_bts=<path>");
+
+struct rte_pci_bus *ifpga_get_pci_bus(void)
+{
+	return rte_ifpga_rawdev_pmd.bus;
+}
+
+int ifpga_rawdev_partial_reconfigure(struct rte_rawdev *dev, int port,
+	const char *file)
+{
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("Input parameter is invalid");
+		return -EINVAL;
+	}
+
+	return rte_fpga_do_pr(dev, port, file);
+}
+
+void ifpga_rawdev_cleanup(void)
+{
+	struct ifpga_rawdev *dev;
+	unsigned int i;
+
+	for (i = 0; i < IFPGA_RAWDEV_NUM; i++) {
+		dev = &ifpga_rawdevices[i];
+		if (dev->rawdev) {
+			rte_rawdev_pmd_release(dev->rawdev);
+			dev->rawdev = NULL;
+		}
+	}
+}
diff --git a/drivers/raw/ifpga/ifpga_rawdev.h b/drivers/raw/ifpga/ifpga_rawdev.h
index 7754beb02b..9bbe9a4278 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.h
+++ b/drivers/raw/ifpga/ifpga_rawdev.h
@@ -43,7 +43,7 @@ enum ifpga_rawdev_device_state {
 static inline struct opae_adapter *
 ifpga_rawdev_get_priv(const struct rte_rawdev *rawdev)
 {
-	return rawdev->dev_private;
+	return (struct opae_adapter *)rawdev->dev_private;
 }
 
 #define IFPGA_RAWDEV_MSIX_IRQ_NUM 7
@@ -76,4 +76,9 @@ int
 ifpga_unregister_msix_irq(enum ifpga_irq_type type,
 		int vec_start, rte_intr_callback_fn handler, void *arg);
 
+struct rte_pci_bus *ifpga_get_pci_bus(void);
+int ifpga_rawdev_partial_reconfigure(struct rte_rawdev *dev, int port,
+	const char *file);
+void ifpga_rawdev_cleanup(void);
+
 #endif /* _IFPGA_RAWDEV_H_ */
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.c b/drivers/raw/ifpga/rte_pmd_ifpga.c
index 8e04e22d5f..6e23a2581a 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.c
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.c
@@ -122,6 +122,25 @@ rte_pmd_ifpga_get_rsu_status(uint16_t dev_id, uint32_t *stat, uint32_t *prog)
 	return 0;
 }
 
+int
+rte_pmd_ifpga_set_rsu_status(uint16_t dev_id, uint32_t stat, uint32_t prog)
+{
+	struct opae_adapter *adapter = NULL;
+	opae_share_data *sd = NULL;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	sd = get_share_data(adapter);
+	if (!sd)
+		return -ENOMEM;
+
+	sd->rsu_stat = IFPGA_RSU_STATUS(stat, prog);
+
+	return 0;
+}
+
 static int
 ifpga_is_rebooting(struct opae_adapter *adapter)
 {
@@ -382,3 +401,29 @@ rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page)
 
 	return opae_mgr_reload(adapter->mgr, type, page);
 }
+
+const struct rte_pci_bus *
+rte_pmd_ifpga_get_pci_bus(void)
+{
+	return ifpga_get_pci_bus();
+}
+
+int
+rte_pmd_ifpga_partial_reconfigure(uint16_t dev_id, int port, const char *file)
+{
+	struct rte_rawdev *dev = NULL;
+
+	dev = get_rte_rawdev(dev_id);
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("Device ID %u is invalid.", dev_id);
+		return -EINVAL;
+	}
+
+	return ifpga_rawdev_partial_reconfigure(dev, port, file);
+}
+
+void
+rte_pmd_ifpga_cleanup(void)
+{
+	ifpga_rawdev_cleanup();
+}
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.h b/drivers/raw/ifpga/rte_pmd_ifpga.h
index 633f6e9d1b..47d66ba655 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.h
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.h
@@ -107,6 +107,27 @@ __rte_experimental
 int
 rte_pmd_ifpga_get_rsu_status(uint16_t dev_id, uint32_t *stat, uint32_t *prog);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set current RSU status of the specified Intel FPGA device
+ *
+ * @param dev_id
+ *    The raw device ID of specified Intel FPGA device.
+ * @param stat
+ *    The RSU status value to set.
+ * @param prog
+ *    The RSU progress value to set.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-ENOMEM) if share data is not initialized.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_set_rsu_status(uint16_t dev_id, uint32_t stat, uint32_t prog);
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
@@ -235,6 +256,51 @@ __rte_experimental
 int
 rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get PCI bus the Intel FPGA driver register to
+ *
+ * @return
+ *   - (valid pointer) if successful.
+ *   - (NULL) if the Intel FPGA driver is not registered to any PCI bus.
+ */
+__rte_experimental
+const struct rte_pci_bus *
+rte_pmd_ifpga_get_pci_bus(void);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Perform PR (partial reconfiguration) on specified Intel FPGA device
+ *
+ * @param dev_id
+ *   The raw device ID of specified Intel FPGA device.
+ * @param port
+ *   The port index of the partial reconfiguration area.
+ * @param file
+ *   The GBS (Green BitStream) image file name string.
+ * @return
+ *   - (0) if successful.
+ *   - (-EINVAL) if bad parameter or operation failed.
+ *   - (-ENOMEM) if failed to allocate memory.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_partial_reconfigure(uint16_t dev_id, int port, const char *file);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Free software resources allocated by Intel FPGA PMD
+ */
+__rte_experimental
+void
+rte_pmd_ifpga_cleanup(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/raw/ifpga/version.map b/drivers/raw/ifpga/version.map
index ca6f7f5810..995c419a9b 100644
--- a/drivers/raw/ifpga/version.map
+++ b/drivers/raw/ifpga/version.map
@@ -8,10 +8,14 @@ EXPERIMENTAL {
 	# added in 21.05
 	rte_pmd_ifpga_get_dev_id;
 	rte_pmd_ifpga_get_rsu_status;
+	rte_pmd_ifpga_set_rsu_status;
 	rte_pmd_ifpga_get_property;
 	rte_pmd_ifpga_get_phy_info;
 	rte_pmd_ifpga_update_flash;
 	rte_pmd_ifpga_stop_update;
 	rte_pmd_ifpga_reboot_try;
 	rte_pmd_ifpga_reload;
+	rte_pmd_ifpga_get_pci_bus;
+	rte_pmd_ifpga_partial_reconfigure;
+	rte_pmd_ifpga_cleanup;
 };
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg
  2021-03-03  2:34 [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Wei Huang
                   ` (2 preceding siblings ...)
  2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 3/3] raw/ifpga: add miscellaneous APIs Wei Huang
@ 2021-03-05  8:54 ` Zhang, Qi Z
  3 siblings, 0 replies; 6+ messages in thread
From: Zhang, Qi Z @ 2021-03-05  8:54 UTC (permalink / raw)
  To: Huang, Wei, dev, Xu, Rosen; +Cc: stable, Zhang, Tianfei, Yigit, Ferruh



> -----Original Message-----
> From: Huang, Wei <wei.huang@intel.com>
> Sent: Wednesday, March 3, 2021 10:34 AM
> To: dev@dpdk.org; Xu, Rosen <rosen.xu@intel.com>; Zhang, Qi Z
> <qi.z.zhang@intel.com>
> Cc: stable@dpdk.org; Zhang, Tianfei <tianfei.zhang@intel.com>; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Huang, Wei <wei.huang@intel.com>
> Subject: [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg
> 
> Cyborg is part of OpenStack, it needs some extra APIs to manage devices with
> Intel FPGA. These patches add APIs to meet Cyborg requirement.
> 
> Main changes from v15:
> - remove example from the patch set
> 
> Wei Huang (3):
>   raw/ifpga: add fpga rsu APIs
>   raw/ifpga: add APIs to get fpga information
>   raw/ifpga: add miscellaneous APIs
> 
>  doc/api/doxy-api-index.md                  |   3 +-
>  doc/api/doxy-api.conf.in                   |   1 +
>  drivers/raw/ifpga/base/ifpga_api.c         |  34 ++
>  drivers/raw/ifpga/base/ifpga_defines.h     |   1 +
>  drivers/raw/ifpga/base/ifpga_feature_dev.c |  21 +
>  drivers/raw/ifpga/base/ifpga_feature_dev.h |   1 +
>  drivers/raw/ifpga/base/ifpga_fme.c         |  36 +-
>  drivers/raw/ifpga/base/ifpga_fme_rsu.c     | 428 ++++++++++++++
>  drivers/raw/ifpga/base/ifpga_hw.h          |   1 +
>  drivers/raw/ifpga/base/ifpga_sec_mgr.c     | 639 +++++++++++++++++++++
>  drivers/raw/ifpga/base/ifpga_sec_mgr.h     |  93 +++
>  drivers/raw/ifpga/base/meson.build         |   2 +
>  drivers/raw/ifpga/base/opae_hw_api.c       |  77 +++
>  drivers/raw/ifpga/base/opae_hw_api.h       |  12 +
>  drivers/raw/ifpga/base/opae_ifpga_hw_api.h |   1 +
>  drivers/raw/ifpga/base/opae_intel_max10.c  |  48 ++
> drivers/raw/ifpga/base/opae_intel_max10.h  |  44 ++
>  drivers/raw/ifpga/ifpga_rawdev.c           |  30 +
>  drivers/raw/ifpga/ifpga_rawdev.h           |   7 +-
>  drivers/raw/ifpga/meson.build              |   4 +-
>  drivers/raw/ifpga/rte_pmd_ifpga.c          | 429 ++++++++++++++
>  drivers/raw/ifpga/rte_pmd_ifpga.h          | 308 ++++++++++
>  drivers/raw/ifpga/version.map              |  18 +
>  23 files changed, 2233 insertions(+), 5 deletions(-)  create mode 100644
> drivers/raw/ifpga/base/ifpga_fme_rsu.c
>  create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.c
>  create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.h
>  create mode 100644 drivers/raw/ifpga/rte_pmd_ifpga.c  create mode
> 100644 drivers/raw/ifpga/rte_pmd_ifpga.h
> 
> --
> 2.29.2

Applied to dpdk-next-net-intel.

Thanks
Qi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH v16 3/3] raw/ifpga: add miscellaneous APIs
  2021-03-17  7:59 Wei Huang
@ 2021-03-17  7:59 ` Wei Huang
  0 siblings, 0 replies; 6+ messages in thread
From: Wei Huang @ 2021-03-17  7:59 UTC (permalink / raw)
  To: dev, rosen.xu, qi.z.zhang; +Cc: stable, tianfei.zhang, Wei Huang

Below miscellaneous APIs are used to implement OPAE application.
1. rte_pmd_ifpga_get_pci_bus() get PCI bus ifpga driver registered.
2. rte_pmd_ifpga_partial_reconfigure() do partial reconfiguration.
3. rte_pmd_ifpga_cleanup() free software resources allocated by driver.
4. rte_pmd_ifpga_set_rsu_status() set status of rsu process.

Signed-off-by: Wei Huang <wei.huang@intel.com>
Acked-by: Tianfei Zhang <tianfei.zhang@intel.com>
Acked-by: Rosen Xu <rosen.xu@intel.com>
---
v2: implement APIs in rte_pmd_ifpga.c
---
 drivers/raw/ifpga/ifpga_rawdev.c  | 30 ++++++++++++++
 drivers/raw/ifpga/ifpga_rawdev.h  |  7 +++-
 drivers/raw/ifpga/rte_pmd_ifpga.c | 45 +++++++++++++++++++++
 drivers/raw/ifpga/rte_pmd_ifpga.h | 66 +++++++++++++++++++++++++++++++
 drivers/raw/ifpga/version.map     |  4 ++
 5 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/drivers/raw/ifpga/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 27129b133e..05d79bfcc2 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -1737,3 +1737,33 @@ RTE_PMD_REGISTER_PARAM_STRING(ifpga_rawdev_cfg,
 	"ifpga=<string> "
 	"port=<int> "
 	"afu_bts=<path>");
+
+struct rte_pci_bus *ifpga_get_pci_bus(void)
+{
+	return rte_ifpga_rawdev_pmd.bus;
+}
+
+int ifpga_rawdev_partial_reconfigure(struct rte_rawdev *dev, int port,
+	const char *file)
+{
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("Input parameter is invalid");
+		return -EINVAL;
+	}
+
+	return rte_fpga_do_pr(dev, port, file);
+}
+
+void ifpga_rawdev_cleanup(void)
+{
+	struct ifpga_rawdev *dev;
+	unsigned int i;
+
+	for (i = 0; i < IFPGA_RAWDEV_NUM; i++) {
+		dev = &ifpga_rawdevices[i];
+		if (dev->rawdev) {
+			rte_rawdev_pmd_release(dev->rawdev);
+			dev->rawdev = NULL;
+		}
+	}
+}
diff --git a/drivers/raw/ifpga/ifpga_rawdev.h b/drivers/raw/ifpga/ifpga_rawdev.h
index 7754beb02b..9bbe9a4278 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.h
+++ b/drivers/raw/ifpga/ifpga_rawdev.h
@@ -43,7 +43,7 @@ enum ifpga_rawdev_device_state {
 static inline struct opae_adapter *
 ifpga_rawdev_get_priv(const struct rte_rawdev *rawdev)
 {
-	return rawdev->dev_private;
+	return (struct opae_adapter *)rawdev->dev_private;
 }
 
 #define IFPGA_RAWDEV_MSIX_IRQ_NUM 7
@@ -76,4 +76,9 @@ int
 ifpga_unregister_msix_irq(enum ifpga_irq_type type,
 		int vec_start, rte_intr_callback_fn handler, void *arg);
 
+struct rte_pci_bus *ifpga_get_pci_bus(void);
+int ifpga_rawdev_partial_reconfigure(struct rte_rawdev *dev, int port,
+	const char *file);
+void ifpga_rawdev_cleanup(void);
+
 #endif /* _IFPGA_RAWDEV_H_ */
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.c b/drivers/raw/ifpga/rte_pmd_ifpga.c
index 8e04e22d5f..6e23a2581a 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.c
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.c
@@ -122,6 +122,25 @@ rte_pmd_ifpga_get_rsu_status(uint16_t dev_id, uint32_t *stat, uint32_t *prog)
 	return 0;
 }
 
+int
+rte_pmd_ifpga_set_rsu_status(uint16_t dev_id, uint32_t stat, uint32_t prog)
+{
+	struct opae_adapter *adapter = NULL;
+	opae_share_data *sd = NULL;
+
+	adapter = get_opae_adapter(dev_id);
+	if (!adapter)
+		return -ENODEV;
+
+	sd = get_share_data(adapter);
+	if (!sd)
+		return -ENOMEM;
+
+	sd->rsu_stat = IFPGA_RSU_STATUS(stat, prog);
+
+	return 0;
+}
+
 static int
 ifpga_is_rebooting(struct opae_adapter *adapter)
 {
@@ -382,3 +401,29 @@ rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page)
 
 	return opae_mgr_reload(adapter->mgr, type, page);
 }
+
+const struct rte_pci_bus *
+rte_pmd_ifpga_get_pci_bus(void)
+{
+	return ifpga_get_pci_bus();
+}
+
+int
+rte_pmd_ifpga_partial_reconfigure(uint16_t dev_id, int port, const char *file)
+{
+	struct rte_rawdev *dev = NULL;
+
+	dev = get_rte_rawdev(dev_id);
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("Device ID %u is invalid.", dev_id);
+		return -EINVAL;
+	}
+
+	return ifpga_rawdev_partial_reconfigure(dev, port, file);
+}
+
+void
+rte_pmd_ifpga_cleanup(void)
+{
+	ifpga_rawdev_cleanup();
+}
diff --git a/drivers/raw/ifpga/rte_pmd_ifpga.h b/drivers/raw/ifpga/rte_pmd_ifpga.h
index 633f6e9d1b..47d66ba655 100644
--- a/drivers/raw/ifpga/rte_pmd_ifpga.h
+++ b/drivers/raw/ifpga/rte_pmd_ifpga.h
@@ -107,6 +107,27 @@ __rte_experimental
 int
 rte_pmd_ifpga_get_rsu_status(uint16_t dev_id, uint32_t *stat, uint32_t *prog);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Set current RSU status of the specified Intel FPGA device
+ *
+ * @param dev_id
+ *    The raw device ID of specified Intel FPGA device.
+ * @param stat
+ *    The RSU status value to set.
+ * @param prog
+ *    The RSU progress value to set.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if dev_id is invalid.
+ *   - (-ENOMEM) if share data is not initialized.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_set_rsu_status(uint16_t dev_id, uint32_t stat, uint32_t prog);
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
@@ -235,6 +256,51 @@ __rte_experimental
 int
 rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Get PCI bus the Intel FPGA driver register to
+ *
+ * @return
+ *   - (valid pointer) if successful.
+ *   - (NULL) if the Intel FPGA driver is not registered to any PCI bus.
+ */
+__rte_experimental
+const struct rte_pci_bus *
+rte_pmd_ifpga_get_pci_bus(void);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Perform PR (partial reconfiguration) on specified Intel FPGA device
+ *
+ * @param dev_id
+ *   The raw device ID of specified Intel FPGA device.
+ * @param port
+ *   The port index of the partial reconfiguration area.
+ * @param file
+ *   The GBS (Green BitStream) image file name string.
+ * @return
+ *   - (0) if successful.
+ *   - (-EINVAL) if bad parameter or operation failed.
+ *   - (-ENOMEM) if failed to allocate memory.
+ */
+__rte_experimental
+int
+rte_pmd_ifpga_partial_reconfigure(uint16_t dev_id, int port, const char *file);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
+ *
+ * Free software resources allocated by Intel FPGA PMD
+ */
+__rte_experimental
+void
+rte_pmd_ifpga_cleanup(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/raw/ifpga/version.map b/drivers/raw/ifpga/version.map
index ca6f7f5810..995c419a9b 100644
--- a/drivers/raw/ifpga/version.map
+++ b/drivers/raw/ifpga/version.map
@@ -8,10 +8,14 @@ EXPERIMENTAL {
 	# added in 21.05
 	rte_pmd_ifpga_get_dev_id;
 	rte_pmd_ifpga_get_rsu_status;
+	rte_pmd_ifpga_set_rsu_status;
 	rte_pmd_ifpga_get_property;
 	rte_pmd_ifpga_get_phy_info;
 	rte_pmd_ifpga_update_flash;
 	rte_pmd_ifpga_stop_update;
 	rte_pmd_ifpga_reboot_try;
 	rte_pmd_ifpga_reload;
+	rte_pmd_ifpga_get_pci_bus;
+	rte_pmd_ifpga_partial_reconfigure;
+	rte_pmd_ifpga_cleanup;
 };
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-03-17  8:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-03  2:34 [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Wei Huang
2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 1/3] raw/ifpga: add fpga rsu APIs Wei Huang
2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 2/3] raw/ifpga: add APIs to get fpga information Wei Huang
2021-03-03  2:34 ` [dpdk-dev] [PATCH v16 3/3] raw/ifpga: add miscellaneous APIs Wei Huang
2021-03-05  8:54 ` [dpdk-dev] [PATCH v16 0/3] raw/ifpga: add extra APIs for Cyborg Zhang, Qi Z
2021-03-17  7:59 Wei Huang
2021-03-17  7:59 ` [dpdk-dev] [PATCH v16 3/3] raw/ifpga: add miscellaneous APIs Wei Huang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.