[v12,1/4] raw/ifpga: add fpga rsu function

Message ID 1611643528-18311-2-git-send-email-wei.huang@intel.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series raw/ifpga: add extra OPAE APIs |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Wei Huang Jan. 26, 2021, 6:45 a.m. UTC
  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 three major functions added:
1. ifpga_rawdev_update_flash() updates flash with specific image file.
2. ifpga_rawdev_stop_flash_update() aborts flash update process.
3. ifpga_rawdev_reload() reloads FPGA from updated flash.

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
---
 drivers/raw/ifpga/base/ifpga_api.c        |  26 +
 drivers/raw/ifpga/base/ifpga_fme.c        |   8 +
 drivers/raw/ifpga/base/ifpga_fme_rsu.c    | 435 +++++++++++++++
 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    |  89 +++
 drivers/raw/ifpga/base/meson.build        |   2 +
 drivers/raw/ifpga/base/opae_hw_api.c      |  59 ++
 drivers/raw/ifpga/base/opae_hw_api.h      |  11 +
 drivers/raw/ifpga/base/opae_intel_max10.c |  48 ++
 drivers/raw/ifpga/base/opae_intel_max10.h |  44 ++
 drivers/raw/ifpga/ifpga_rawdev.c          |  55 ++
 drivers/raw/ifpga/ifpga_rawdev.h          |   7 +-
 13 files changed, 1423 insertions(+), 1 deletion(-)
 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
  

Comments

Ferruh Yigit Jan. 28, 2021, 1:24 p.m. UTC | #1
On 1/26/2021 6:45 AM, Wei Huang wrote:
> 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 three major functions added:
> 1. ifpga_rawdev_update_flash() updates flash with specific image file.
> 2. ifpga_rawdev_stop_flash_update() aborts flash update process.
> 3. ifpga_rawdev_reload() reloads FPGA from updated flash.
> 
> 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
> ---

<...>

> @@ -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);
>   
> +int ifpga_rawdev_update_flash(struct rte_rawdev *dev, const char *image,
> +	uint64_t *status);
> +int ifpga_rawdev_stop_flash_update(struct rte_rawdev *dev, int force);
> +int ifpga_rawdev_reload(struct rte_rawdev *dev, int type, int page);
> +
>   #endif /* _IFPGA_RAWDEV_H_ */
> 

Hi Wei, Rosen,

This patch introduces three new PMD specific APIs, adding new API has some 
requirements.

1)
There must be a header file for user application to include, that has the 
definitions of the APIs.

This header file should be installed in meson via "headers = ..." syntax.

Indeed for rawdev a header always should be installed, because of the rawdev 
design, the user application should know about the some driver structures, to 
share those structures PMD should provide a header. This header seems missing.

You can start for providing the missing header, even before this patch.

Header file should be named as 'rte_pmd_.....', and since it is a public header 
now it should be fully documented via doxygen comments.

This header file should be added to 'doc/api/doxy-api-index.md' for API 
documentathion.

2)
All APIs should start with 'rte_pmd_' prefix.

3)
All APIs should be in the .map file

4)
Since these are new APIs, they should be marked as experimental. This is done 
both documenting this in the doxygen comments and marking the function 
decleration via '__rte_experimental' tag

5)
Please don't use "struct rte_rawdev *dev" as a argument in the APIs, since that 
structure is rawdev internal structures, applications (that will call your API) 
should not know or access to this struct.
Instead you can you 'dev_id' (ethdev 'port_id' equivalent) in the API, as done 
in the rawdev APIs. Driver can easily get the rawdevice from 'dev_id'.

cc'ed Ray & Hemant in case I missed something related to rawdev and API/ABIs.


And for the ifpga implementation, it is hard for me to review it, I trust Rosen 
for it.
  
Wei Huang Jan. 29, 2021, 7:38 a.m. UTC | #2
-----Original Message-----
From: Ferruh Yigit <ferruh.yigit@intel.com> 
Sent: Thursday, January 28, 2021 21:25
To: Huang, Wei <wei.huang@intel.com>; 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>; Ray Kinsella <mdr@ashroe.eu>; Hemant Agrawal <hemant.agrawal@nxp.com>
Subject: Re: [dpdk-dev] [PATCH v12 1/4] raw/ifpga: add fpga rsu function

On 1/26/2021 6:45 AM, Wei Huang wrote:
> 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 three major functions added:
> 1. ifpga_rawdev_update_flash() updates flash with specific image file.
> 2. ifpga_rawdev_stop_flash_update() aborts flash update process.
> 3. ifpga_rawdev_reload() reloads FPGA from updated flash.
> 
> 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
> ---

<...>

> @@ -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);
>   
> +int ifpga_rawdev_update_flash(struct rte_rawdev *dev, const char *image,
> +	uint64_t *status);
> +int ifpga_rawdev_stop_flash_update(struct rte_rawdev *dev, int 
> +force); int ifpga_rawdev_reload(struct rte_rawdev *dev, int type, int 
> +page);
> +
>   #endif /* _IFPGA_RAWDEV_H_ */
> 

Hi Wei, Rosen,

This patch introduces three new PMD specific APIs, adding new API has some requirements.

1)
There must be a header file for user application to include, that has the definitions of the APIs.

This header file should be installed in meson via "headers = ..." syntax.

Indeed for rawdev a header always should be installed, because of the rawdev design, the user application should know about the some driver structures, to share those structures PMD should provide a header. This header seems missing.

You can start for providing the missing header, even before this patch.

Header file should be named as 'rte_pmd_.....', and since it is a public header now it should be fully documented via doxygen comments.

This header file should be added to 'doc/api/doxy-api-index.md' for API documentathion.
OK, I will add rte_pmd_ifpga.h.
2)
All APIs should start with 'rte_pmd_' prefix.
OK, I will use 'rte_pmd_' prefix before driver APIs.
3)
All APIs should be in the .map file
OK, I will add them into .map file.
4)
Since these are new APIs, they should be marked as experimental. This is done both documenting this in the doxygen comments and marking the function decleration via '__rte_experimental' tag
How to document it in doxygen comments ? Could you give an example ?
5)
Please don't use "struct rte_rawdev *dev" as a argument in the APIs, since that structure is rawdev internal structures, applications (that will call your API) should not know or access to this struct.
Instead you can you 'dev_id' (ethdev 'port_id' equivalent) in the API, as done in the rawdev APIs. Driver can easily get the rawdevice from 'dev_id'.
OK, I will use dev_id in driver APIs' argument.
cc'ed Ray & Hemant in case I missed something related to rawdev and API/ABIs.


And for the ifpga implementation, it is hard for me to review it, I trust Rosen for it.
  
Ferruh Yigit Jan. 29, 2021, 8:59 a.m. UTC | #3
On 1/29/2021 7:38 AM, Huang, Wei wrote:
> 
> 
> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@intel.com>
> Sent: Thursday, January 28, 2021 21:25
> To: Huang, Wei <wei.huang@intel.com>; 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>; Ray Kinsella <mdr@ashroe.eu>; Hemant Agrawal <hemant.agrawal@nxp.com>
> Subject: Re: [dpdk-dev] [PATCH v12 1/4] raw/ifpga: add fpga rsu function
> 
> On 1/26/2021 6:45 AM, Wei Huang wrote:
>> 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 three major functions added:
>> 1. ifpga_rawdev_update_flash() updates flash with specific image file.
>> 2. ifpga_rawdev_stop_flash_update() aborts flash update process.
>> 3. ifpga_rawdev_reload() reloads FPGA from updated flash.
>>
>> 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
>> ---
> 
> <...>
> 
>> @@ -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);
>>
>> +int ifpga_rawdev_update_flash(struct rte_rawdev *dev, const char *image,
>> +uint64_t *status);
>> +int ifpga_rawdev_stop_flash_update(struct rte_rawdev *dev, int
>> +force); int ifpga_rawdev_reload(struct rte_rawdev *dev, int type, int
>> +page);
>> +
>>    #endif /* _IFPGA_RAWDEV_H_ */
>>
> 
> Hi Wei, Rosen,
> 
> This patch introduces three new PMD specific APIs, adding new API has some requirements.
> 
> 1)
> There must be a header file for user application to include, that has the definitions of the APIs.
> 
> This header file should be installed in meson via "headers = ..." syntax.
> 
> Indeed for rawdev a header always should be installed, because of the rawdev design, the user application should know about the some driver structures, to share those structures PMD should provide a header. This header seems missing.
> 
> You can start for providing the missing header, even before this patch.
> 
> Header file should be named as 'rte_pmd_.....', and since it is a public header now it should be fully documented via doxygen comments.
> 
> This header file should be added to 'doc/api/doxy-api-index.md' for API documentathion.
> OK, I will add rte_pmd_ifpga.h.
> 2)
> All APIs should start with 'rte_pmd_' prefix.
> OK, I will use 'rte_pmd_' prefix before driver APIs.
> 3)
> All APIs should be in the .map file
> OK, I will add them into .map file.

Btw, in the .map, it needs a special block for the experimental APIs, and since 
all your APIs will be experimental at this stage, they will all go in that 
block, it is like:

EXPERIMENTAL {
	global:

	# added in <dpdk release version>
	<list of APIs>
};

> 4)
> Since these are new APIs, they should be marked as experimental. This is done both documenting this in the doxygen comments and marking the function decleration via '__rte_experimental' tag
> How to document it in doxygen comments ? Could you give an example ?

Sample:
https://git.dpdk.org/dpdk/tree/lib/librte_ethdev/rte_ethdev.h?h=v20.11#n2105

It is simply adding a note/warning that is saying API is experimental.

> 5)
> Please don't use "struct rte_rawdev *dev" as a argument in the APIs, since that structure is rawdev internal structures, applications (that will call your API) should not know or access to this struct.
> Instead you can you 'dev_id' (ethdev 'port_id' equivalent) in the API, as done in the rawdev APIs. Driver can easily get the rawdevice from 'dev_id'.
> OK, I will use dev_id in driver APIs' argument.
> cc'ed Ray & Hemant in case I missed something related to rawdev and API/ABIs.
> 
> 
> And for the ifpga implementation, it is hard for me to review it, I trust Rosen for it.
>
  

Patch

diff --git a/drivers/raw/ifpga/base/ifpga_api.c b/drivers/raw/ifpga/base/ifpga_api.c
index 1ff57fa18..1aedf150b 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 f29ff3159..34fd9a818 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 000000000..fad1ac416
--- /dev/null
+++ b/drivers/raw/ifpga/base/ifpga_fme_rsu.c
@@ -0,0 +1,435 @@ 
+/* 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 = ((status << 16) & 0xffff0000) |
+			(progress & 0xffff);
+}
+
+static void get_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t *status,
+	uint32_t *progress)
+{
+	if (smgr && smgr->rsu_status) {
+		if (status)
+			*status = (*smgr->rsu_status >> 16) & 0xffff;
+		if (progress)
+			*progress = *smgr->rsu_status & 0xffff;
+	}
+	if (smgr && smgr->rsu_status) {
+		if (status)
+			*status = (*smgr->rsu_status >> 16) & 0xffff;
+		if (progress)
+			*progress = *smgr->rsu_status & 0xffff;
+	}
+}
+
+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 7c3307fe7..ed5edc601 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 000000000..4cf1db304
--- /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 000000000..17f38ca68
--- /dev/null
+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.h
@@ -0,0 +1,89 @@ 
+/* 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
+
+/* 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 da2d6e33c..3549afafa 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 d5cd5fe60..86ad88f72 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 e99ee4564..c819dc3d2 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,9 @@  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 1a526ea54..443e248fb 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 123cdc48b..670683f01 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/ifpga_rawdev.c b/drivers/raw/ifpga/ifpga_rawdev.c
index 27129b133..660ea2051 100644
--- a/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/drivers/raw/ifpga/ifpga_rawdev.c
@@ -1737,3 +1737,58 @@  RTE_PMD_REGISTER_PARAM_STRING(ifpga_rawdev_cfg,
 	"ifpga=<string> "
 	"port=<int> "
 	"afu_bts=<path>");
+
+int ifpga_rawdev_update_flash(struct rte_rawdev *dev, const char *image,
+	uint64_t *status)
+{
+	struct opae_adapter *adapter = NULL;
+
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("rawdev is invalid");
+		return -EINVAL;
+	}
+
+	adapter = ifpga_rawdev_get_priv(dev);
+	if (!adapter) {
+		IFPGA_RAWDEV_PMD_ERR("adapter is invalid");
+		return -ENODEV;
+	}
+
+	return opae_mgr_update_flash(adapter->mgr, image, status);
+}
+
+int ifpga_rawdev_stop_flash_update(struct rte_rawdev *dev, int force)
+{
+	struct opae_adapter *adapter = NULL;
+
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("rawdev is invalid");
+		return -EINVAL;
+	}
+
+	adapter = ifpga_rawdev_get_priv(dev);
+	if (!adapter) {
+		IFPGA_RAWDEV_PMD_ERR("adapter is invalid");
+		return -ENODEV;
+	}
+
+	return opae_mgr_stop_flash_update(adapter->mgr, force);
+}
+
+int ifpga_rawdev_reload(struct rte_rawdev *dev, int type, int page)
+{
+	struct opae_adapter *adapter = NULL;
+
+	if (!dev) {
+		IFPGA_RAWDEV_PMD_ERR("rawdev is invalid");
+		return -EINVAL;
+	}
+
+	adapter = ifpga_rawdev_get_priv(dev);
+	if (!adapter) {
+		IFPGA_RAWDEV_PMD_ERR("adapter is invalid");
+		return -ENODEV;
+	}
+
+	return opae_mgr_reload(adapter->mgr, type, page);
+}
diff --git a/drivers/raw/ifpga/ifpga_rawdev.h b/drivers/raw/ifpga/ifpga_rawdev.h
index 7754beb02..bf74a5eb3 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);
 
+int ifpga_rawdev_update_flash(struct rte_rawdev *dev, const char *image,
+	uint64_t *status);
+int ifpga_rawdev_stop_flash_update(struct rte_rawdev *dev, int force);
+int ifpga_rawdev_reload(struct rte_rawdev *dev, int type, int page);
+
 #endif /* _IFPGA_RAWDEV_H_ */