get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/88077/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 88077,
    "url": "https://patches.dpdk.org/api/patches/88077/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1613979352-4864-2-git-send-email-wei.huang@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1613979352-4864-2-git-send-email-wei.huang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1613979352-4864-2-git-send-email-wei.huang@intel.com",
    "date": "2021-02-22T07:35:49",
    "name": "[v15,1/4] raw/ifpga: add fpga rsu APIs",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2547d1f36daa25fc32f8f3bb1eb765308a0215d4",
    "submitter": {
        "id": 2033,
        "url": "https://patches.dpdk.org/api/people/2033/?format=api",
        "name": "Wei Huang",
        "email": "wei.huang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "https://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1613979352-4864-2-git-send-email-wei.huang@intel.com/mbox/",
    "series": [
        {
            "id": 15326,
            "url": "https://patches.dpdk.org/api/series/15326/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=15326",
            "date": "2021-02-22T07:35:48",
            "name": "raw/ifpga: add extra OPAE APIs",
            "version": 15,
            "mbox": "https://patches.dpdk.org/series/15326/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/88077/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/88077/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id A5584A034F;\n\tMon, 22 Feb 2021 08:35:55 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 1217422A267;\n\tMon, 22 Feb 2021 08:35:51 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n by mails.dpdk.org (Postfix) with ESMTP id 7005C22A26C;\n Mon, 22 Feb 2021 08:35:48 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 21 Feb 2021 23:35:48 -0800",
            "from unknown (HELO sh_lab5_1.sh.intel.com) ([10.238.175.190])\n by fmsmga001.fm.intel.com with ESMTP; 21 Feb 2021 23:35:45 -0800"
        ],
        "IronPort-SDR": [
            "\n iOeWOm9jvw1LCzfRQbPPOqFHGJrckZTKuW37p0awANn+sa0uSfUo0m+ulJrkch6n/3PJpmE0fX\n 1WS5CMeNi8VQ==",
            "\n ec/geeGcL25Ea0Mm+nh/v0awiK8rwFdzFPfSR8C+L0zU16bcC/cndF5Hqhi4rkAuylX2OBsI2p\n sMa1PFSpp7Gg=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9902\"; a=\"183640822\"",
            "E=Sophos;i=\"5.81,196,1610438400\"; d=\"scan'208\";a=\"183640822\"",
            "E=Sophos;i=\"5.81,196,1610438400\"; d=\"scan'208\";a=\"498391220\""
        ],
        "X-ExtLoop1": "1",
        "From": "Wei Huang <wei.huang@intel.com>",
        "To": "dev@dpdk.org,\n\trosen.xu@intel.com,\n\tqi.z.zhang@intel.com",
        "Cc": "stable@dpdk.org, tianfei.zhang@intel.com, ferruh.yigit@intel.com,\n Wei Huang <wei.huang@intel.com>",
        "Date": "Mon, 22 Feb 2021 02:35:49 -0500",
        "Message-Id": "<1613979352-4864-2-git-send-email-wei.huang@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1613979352-4864-1-git-send-email-wei.huang@intel.com>",
        "References": "<1613963747-30047-1-git-send-email-wei.huang@intel.com>\n <1613979352-4864-1-git-send-email-wei.huang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v15 1/4] raw/ifpga: add fpga rsu APIs",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "RSU (Remote System Update) depends on secure manager which may be\ndifferent on various implementations, so a new secure manager device\nis implemented for adapting such difference.\nThere are five APIs added:\n1. rte_pmd_ifpga_get_dev_id() get raw device ID of ifpga device from\nPCI address like 'Domain:Bus:Dev.Func'.\n2. rte_pmd_ifpga_update_flash() update flash with specific image file.\n3. rte_pmd_ifpga_stop_update() abort flash update process.\n4. rte_pmd_ifpga_reboot_try() check current ifpga status and change it\nto reboot status if it is idle.\n5. rte_pmd_ifpga_reload() trigger full reconfiguration of ifpga device.\n\nSigned-off-by: Wei Huang <wei.huang@intel.com>\nAcked-by: Tianfei Zhang <tianfei.zhang@intel.com>\nAcked-by: Rosen Xu <rosen.xu@intel.com>\n---\nv2: fix coding style issue in ifpga_fme_rsu.c and ifpga_sec_mgr.c\n---\nv3: fix compilation issues in ifpga_fme_rsu.c\n---\nv4: fix compilation issues in opae_intel_max10.c\n---\nv5: implement APIs in rte_pmd_ifpga.c\n---\n doc/api/doxy-api-index.md                 |   3 +-\n drivers/raw/ifpga/base/ifpga_api.c        |  26 +\n drivers/raw/ifpga/base/ifpga_fme.c        |   8 +\n drivers/raw/ifpga/base/ifpga_fme_rsu.c    | 428 +++++++++++++++\n drivers/raw/ifpga/base/ifpga_hw.h         |   1 +\n drivers/raw/ifpga/base/ifpga_sec_mgr.c    | 639 ++++++++++++++++++++++\n drivers/raw/ifpga/base/ifpga_sec_mgr.h    |  93 ++++\n drivers/raw/ifpga/base/meson.build        |   2 +\n drivers/raw/ifpga/base/opae_hw_api.c      |  59 ++\n drivers/raw/ifpga/base/opae_hw_api.h      |  10 +\n drivers/raw/ifpga/base/opae_intel_max10.c |  48 ++\n drivers/raw/ifpga/base/opae_intel_max10.h |  44 ++\n drivers/raw/ifpga/meson.build             |   4 +-\n drivers/raw/ifpga/rte_pmd_ifpga.c         | 163 ++++++\n drivers/raw/ifpga/rte_pmd_ifpga.h         | 132 +++++\n drivers/raw/ifpga/version.map             |  11 +\n 16 files changed, 1669 insertions(+), 2 deletions(-)\n create mode 100644 drivers/raw/ifpga/base/ifpga_fme_rsu.c\n create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.c\n create mode 100644 drivers/raw/ifpga/base/ifpga_sec_mgr.h\n create mode 100644 drivers/raw/ifpga/rte_pmd_ifpga.c\n create mode 100644 drivers/raw/ifpga/rte_pmd_ifpga.h",
    "diff": "diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md\nindex 748514e243..8a48af1042 100644\n--- a/doc/api/doxy-api-index.md\n+++ b/doc/api/doxy-api-index.md\n@@ -56,7 +56,8 @@ The public API headers are grouped by topics:\n   [dpaa2_qdma]         (@ref rte_pmd_dpaa2_qdma.h),\n   [crypto_scheduler]   (@ref rte_cryptodev_scheduler.h),\n   [dlb]                (@ref rte_pmd_dlb.h),\n-  [dlb2]               (@ref rte_pmd_dlb2.h)\n+  [dlb2]               (@ref rte_pmd_dlb2.h),\n+  [ifpga]              (@ref rte_pmd_ifpga.h)\n \n - **memory**:\n   [memseg]             (@ref rte_memory.h),\ndiff --git a/drivers/raw/ifpga/base/ifpga_api.c b/drivers/raw/ifpga/base/ifpga_api.c\nindex 1ff57fa188..1aedf150bc 100644\n--- a/drivers/raw/ifpga/base/ifpga_api.c\n+++ b/drivers/raw/ifpga/base/ifpga_api.c\n@@ -5,6 +5,7 @@\n #include \"ifpga_api.h\"\n #include \"ifpga_enumerate.h\"\n #include \"ifpga_feature_dev.h\"\n+#include \"ifpga_sec_mgr.h\"\n \n #include \"opae_hw_api.h\"\n \n@@ -228,11 +229,36 @@ static int ifpga_mgr_get_board_info(struct opae_manager *mgr,\n \treturn 0;\n }\n \n+static int ifpga_mgr_update_flash(struct opae_manager *mgr, const char *image,\n+\tu64 *status)\n+{\n+\tstruct ifpga_fme_hw *fme = mgr->data;\n+\n+\treturn fpga_update_flash(fme, image, status);\n+}\n+\n+static int ifpga_mgr_stop_flash_update(struct opae_manager *mgr, int force)\n+{\n+\tstruct ifpga_fme_hw *fme = mgr->data;\n+\n+\treturn fpga_stop_flash_update(fme, force);\n+}\n+\n+static int ifpga_mgr_reload(struct opae_manager *mgr, int type, int page)\n+{\n+\tstruct ifpga_fme_hw *fme = mgr->data;\n+\n+\treturn fpga_reload(fme, type, page);\n+}\n+\n struct opae_manager_ops ifpga_mgr_ops = {\n \t.flash = ifpga_mgr_flash,\n \t.get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info,\n \t.get_sensor_value = ifpga_mgr_get_sensor_value,\n \t.get_board_info = ifpga_mgr_get_board_info,\n+\t.update_flash = ifpga_mgr_update_flash,\n+\t.stop_flash_update = ifpga_mgr_stop_flash_update,\n+\t.reload = ifpga_mgr_reload,\n };\n \n static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset,\ndiff --git a/drivers/raw/ifpga/base/ifpga_fme.c b/drivers/raw/ifpga/base/ifpga_fme.c\nindex f29ff3159b..34fd9a818e 100644\n--- a/drivers/raw/ifpga/base/ifpga_fme.c\n+++ b/drivers/raw/ifpga/base/ifpga_fme.c\n@@ -7,6 +7,7 @@\n #include \"opae_intel_max10.h\"\n #include \"opae_i2c.h\"\n #include \"opae_at24_eeprom.h\"\n+#include \"ifpga_sec_mgr.h\"\n \n #define PWR_THRESHOLD_MAX       0x7F\n \n@@ -1152,6 +1153,12 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)\n \tif (spi_self_checking(max10))\n \t\tgoto spi_fail;\n \n+\tret = init_sec_mgr(fme);\n+\tif (ret) {\n+\t\tdev_err(fme, \"security manager init fail\\n\");\n+\t\tgoto spi_fail;\n+\t}\n+\n \treturn ret;\n \n spi_fail:\n@@ -1165,6 +1172,7 @@ static void fme_nios_spi_uinit(struct ifpga_feature *feature)\n {\n \tstruct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;\n \n+\trelease_sec_mgr(fme);\n \tif (fme->max10_dev)\n \t\tintel_max10_device_remove(fme->max10_dev);\n }\ndiff --git a/drivers/raw/ifpga/base/ifpga_fme_rsu.c b/drivers/raw/ifpga/base/ifpga_fme_rsu.c\nnew file mode 100644\nindex 0000000000..28198abd78\n--- /dev/null\n+++ b/drivers/raw/ifpga/base/ifpga_fme_rsu.c\n@@ -0,0 +1,428 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <fcntl.h>\n+#include <signal.h>\n+#include <unistd.h>\n+#include \"ifpga_sec_mgr.h\"\n+\n+static struct ifpga_sec_mgr *sec_mgr;\n+\n+static void set_rsu_control(struct ifpga_sec_mgr *smgr, uint32_t ctrl)\n+{\n+\tif (smgr && smgr->rsu_control)\n+\t\t*smgr->rsu_control = ctrl;\n+}\n+\n+static uint32_t get_rsu_control(struct ifpga_sec_mgr *smgr)\n+{\n+\tif (smgr && smgr->rsu_control)\n+\t\treturn *smgr->rsu_control;\n+\treturn 0;\n+}\n+\n+static void set_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t status,\n+\tuint32_t progress)\n+{\n+\tif (smgr && smgr->rsu_status)\n+\t\t*smgr->rsu_status = IFPGA_RSU_STATUS(status, progress);\n+}\n+\n+static void get_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t *status,\n+\tuint32_t *progress)\n+{\n+\tif (smgr && smgr->rsu_status) {\n+\t\tif (status)\n+\t\t\t*status = IFPGA_RSU_GET_STAT(*smgr->rsu_status);\n+\t\tif (progress)\n+\t\t\t*progress = IFPGA_RSU_GET_PROG(*smgr->rsu_status);\n+\t}\n+}\n+\n+static void sig_handler(int sig, siginfo_t *info, void *data)\n+{\n+\t(void)(info);\n+\t(void)(data);\n+\n+\tswitch (sig) {\n+\tcase SIGINT:\n+\t\tif (sec_mgr) {\n+\t\t\tdev_info(sec_mgr, \"Interrupt secure flash update\"\n+\t\t\t\t\" by keyboard\\n\");\n+\t\t\tset_rsu_control(sec_mgr, IFPGA_RSU_ABORT);\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+static void log_time(time_t t, const char *msg)\n+{\n+\tuint32_t h = 0;\n+\tuint32_t m = 0;\n+\tuint32_t s = 0;\n+\n+\tif (t < 60) {\n+\t\ts = (uint32_t)t;\n+\t} else if (t < 3600) {\n+\t\ts = (uint32_t)(t % 60);\n+\t\tm = (uint32_t)(t / 60);\n+\t} else {\n+\t\ts = (uint32_t)(t % 60);\n+\t\tm = (uint32_t)((t % 3600) / 60);\n+\t\th = (uint32_t)(t / 3600);\n+\t}\n+\tprintf(\"%s - %02u:%02u:%02u\\n\", msg, h, m, s);\n+}\n+\n+static int start_flash_update(struct ifpga_sec_mgr *smgr)\n+{\n+\tif (!smgr)\n+\t\treturn -ENODEV;\n+\n+\tif (!smgr->ops || !smgr->ops->prepare)\n+\t\treturn -EINVAL;\n+\n+\treturn smgr->ops->prepare(smgr);\n+}\n+\n+static int write_flash_image(struct ifpga_sec_mgr *smgr, const char *image,\n+\tuint32_t offset)\n+{\n+\tvoid *buf = NULL;\n+\tint retry = 0;\n+\tuint32_t length = 0;\n+\tuint32_t to_transfer = 0;\n+\tuint32_t one_percent = 0;\n+\tuint32_t prog = 0;\n+\tuint32_t old_prog = -1;\n+\tssize_t read_size = 0;\n+\tint fd = -1;\n+\tint ret = 0;\n+\n+\tif (!smgr)\n+\t\treturn -ENODEV;\n+\n+\tif (!smgr->ops || !smgr->ops->write_blk)\n+\t\treturn -EINVAL;\n+\n+\tfd = open(image, O_RDONLY);\n+\tif (fd < 0) {\n+\t\tdev_err(smgr,\n+\t\t\t\"Failed to open \\'%s\\' for RD [e:%s]\\n\",\n+\t\t\timage, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\n+\tbuf = malloc(IFPGA_RSU_DATA_BLK_SIZE);\n+\tif (!buf) {\n+\t\tdev_err(smgr, \"Failed to allocate memory for flash update\\n\");\n+\t\tclose(fd);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tlength = smgr->rsu_length;\n+\tone_percent = length / 100;\n+\tdo {\n+\t\tto_transfer = (length > IFPGA_RSU_DATA_BLK_SIZE) ?\n+\t\t\tIFPGA_RSU_DATA_BLK_SIZE : length;\n+\t\tlseek(fd, offset, SEEK_SET);\n+\t\tread_size = read(fd, buf, to_transfer);\n+\t\tif (read_size < 0) {\n+\t\t\tdev_err(smgr, \"Failed to read from \\'%s\\' [e:%s]\\n\",\n+\t\t\t\timage, strerror(errno));\n+\t\t\tret = -EIO;\n+\t\t\tgoto end;\n+\t\t}\n+\t\tif ((uint32_t)read_size != to_transfer) {\n+\t\t\tdev_err(smgr,\n+\t\t\t\t\"Read length %zd is not expected [e:%u]\\n\",\n+\t\t\t\tread_size, to_transfer);\n+\t\t\tret = -EIO;\n+\t\t\tgoto end;\n+\t\t}\n+\n+\t\tretry = 0;\n+\t\tdo {\n+\t\t\tif (get_rsu_control(smgr) == IFPGA_RSU_ABORT) {\n+\t\t\t\tret = -EAGAIN;\n+\t\t\t\tgoto end;\n+\t\t\t}\n+\t\t\tret = smgr->ops->write_blk(smgr, buf, offset,\n+\t\t\t\tto_transfer);\n+\t\t\tif (ret == 0)\n+\t\t\t\tbreak;\n+\t\t\tsleep(1);\n+\t\t} while (++retry <= IFPGA_RSU_WRITE_RETRY);\n+\t\tif (retry > IFPGA_RSU_WRITE_RETRY) {\n+\t\t\tdev_err(smgr, \"Failed to write to staging area 0x%x\\n\",\n+\t\t\t\toffset);\n+\t\t\tret = -EAGAIN;\n+\t\t\tgoto end;\n+\t\t}\n+\n+\t\tlength -= to_transfer;\n+\t\toffset += to_transfer;\n+\t\tprog = offset / one_percent;\n+\t\tif (prog != old_prog) {\n+\t\t\tprintf(\"\\r%d%%\", prog);\n+\t\t\tfflush(stdout);\n+\t\t\tset_rsu_status(smgr, IFPGA_RSU_READY, prog);\n+\t\t\told_prog = prog;\n+\t\t}\n+\t} while (length > 0);\n+\tset_rsu_status(smgr, IFPGA_RSU_READY, 100);\n+\tprintf(\"\\n\");\n+\n+end:\n+\tfree(buf);\n+\tclose(fd);\n+\treturn ret;\n+}\n+\n+static int apply_flash_update(struct ifpga_sec_mgr *smgr)\n+{\n+\tuint32_t one_percent = 0;\n+\tuint32_t one_percent_time = 0;\n+\tuint32_t prog = 0;\n+\tuint32_t old_prog = -1;\n+\tuint32_t copy_time = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr)\n+\t\treturn -ENODEV;\n+\n+\tif (!smgr->ops || !smgr->ops->write_done || !smgr->ops->check_complete)\n+\t\treturn -EINVAL;\n+\n+\tif (smgr->ops->write_done(smgr) < 0) {\n+\t\tdev_err(smgr, \"Failed to apply flash update\\n\");\n+\t\treturn -EAGAIN;\n+\t}\n+\n+\tone_percent = (smgr->rsu_length + 99) / 100;\n+\tif (smgr->copy_speed == 0)   /* avoid zero divide fault */\n+\t\tsmgr->copy_speed = 1;\n+\tone_percent_time = (one_percent + smgr->copy_speed - 1) /\n+\t\tsmgr->copy_speed;\n+\tif (one_percent_time == 0)   /* avoid zero divide fault */\n+\t\tone_percent_time = 1;\n+\n+\tdo {\n+\t\tret = smgr->ops->check_complete(smgr);\n+\t\tif (ret != -EAGAIN)\n+\t\t\tbreak;\n+\t\tsleep(1);\n+\t\tcopy_time += 1;\n+\t\tprog = copy_time / one_percent_time;\n+\t\tif (prog >= 100)\n+\t\t\tprog = 99;\n+\t\tif (prog != old_prog) {\n+\t\t\tprintf(\"\\r%d%%\", prog);\n+\t\t\tfflush(stdout);\n+\t\t\tset_rsu_status(smgr, IFPGA_RSU_COPYING, prog);\n+\t\t\told_prog = prog;\n+\t\t}\n+\t} while (true);\n+\n+\tif (ret < 0) {\n+\t\tprintf(\"\\n\");\n+\t\tdev_err(smgr, \"Failed to complete secure flash update\\n\");\n+\t} else {\n+\t\tprintf(\"\\r100%%\\n\");\n+\t\tset_rsu_status(smgr, IFPGA_RSU_COPYING, 100);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int secure_update_cancel(struct ifpga_sec_mgr *smgr)\n+{\n+\tif (!smgr)\n+\t\treturn -ENODEV;\n+\n+\tif (!smgr->ops || !smgr->ops->cancel)\n+\t\treturn -EINVAL;\n+\n+\treturn smgr->ops->cancel(smgr);\n+}\n+\n+static int secure_update_status(struct ifpga_sec_mgr *smgr, uint64_t *status)\n+{\n+\tif (!smgr)\n+\t\treturn -ENODEV;\n+\n+\tif (!smgr->ops || !smgr->ops->get_hw_errinfo)\n+\t\treturn -EINVAL;\n+\n+\tif (status)\n+\t\t*status = smgr->ops->get_hw_errinfo(smgr);\n+\n+\treturn 0;\n+}\n+\n+int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,\n+\tuint64_t *status)\n+{\n+\tstruct ifpga_hw *hw = NULL;\n+\tstruct ifpga_sec_mgr *smgr = NULL;\n+\tuint32_t rsu_stat = 0;\n+\tint fd = -1;\n+\tstruct sigaction old_sigint_action;\n+\tstruct sigaction sa;\n+\ttime_t start;\n+\tint ret = 0;\n+\n+\tif (!fme || !image || !status) {\n+\t\tdev_err(fme, \"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\thw = (struct ifpga_hw *)fme->parent;\n+\tif (!hw) {\n+\t\tdev_err(fme, \"Parent of FME not found\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tsmgr = (struct ifpga_sec_mgr *)fme->sec_mgr;\n+\tif (!smgr || !smgr->max10_dev) {\n+\t\tdev_err(smgr, \"Security manager not initialized\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\topae_adapter_lock(hw->adapter, -1);\n+\tget_rsu_status(smgr, &rsu_stat, NULL);\n+\tif (rsu_stat != IFPGA_RSU_IDLE) {\n+\t\topae_adapter_unlock(hw->adapter);\n+\t\tif (rsu_stat == IFPGA_RSU_REBOOT)\n+\t\t\tdev_info(smgr, \"Reboot is in progress\\n\");\n+\t\telse\n+\t\t\tdev_info(smgr, \"Update is in progress\\n\");\n+\t\treturn -EAGAIN;\n+\t}\n+\tset_rsu_control(smgr, 0);\n+\tset_rsu_status(smgr, IFPGA_RSU_PREPARE, 0);\n+\topae_adapter_unlock(hw->adapter);\n+\n+\tfd = open(image, O_RDONLY);\n+\tif (fd < 0) {\n+\t\tdev_err(smgr,\n+\t\t\t\"Failed to open \\'%s\\' for RD [e:%s]\\n\",\n+\t\t\timage, strerror(errno));\n+\t\treturn -EIO;\n+\t}\n+\tsmgr->rsu_length = lseek(fd, 0, SEEK_END);\n+\tclose(fd);\n+\n+\tif (smgr->max10_dev->staging_area_size < smgr->rsu_length) {\n+\t\tdev_err(dev, \"Size of staging area is small than image length \"\n+\t\t\t\"[%u<%u]\\n\", smgr->max10_dev->staging_area_size,\n+\t\t\tsmgr->rsu_length);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tprintf(\"Updating from file \\'%s\\' with size %u\\n\",\n+\t\timage, smgr->rsu_length);\n+\n+\tsec_mgr = smgr;\n+\tmemset(&sa, 0, sizeof(struct sigaction));\n+\tsa.sa_flags = SA_SIGINFO | SA_RESETHAND;\n+\tsa.sa_sigaction = sig_handler;\n+\tret = sigaction(SIGINT, &sa, &old_sigint_action);\n+\tif (ret < 0) {\n+\t\tdev_warn(dev, \"Failed to register signal handler\"\n+\t\t\t\" [e:%d]\\n\", ret);\n+\t\tsec_mgr = NULL;\n+\t}\n+\n+\tstart = time(NULL);\n+\tlog_time(time(NULL) - start, \"Starting secure flash update\");\n+\tret = start_flash_update(smgr);\n+\tif (ret < 0)\n+\t\tgoto end;\n+\n+\tset_rsu_status(smgr, IFPGA_RSU_READY, 0);\n+\tlog_time(time(NULL) - start, \"Writing to staging area\");\n+\tret = write_flash_image(smgr, image, 0);\n+\tif (ret < 0)\n+\t\tgoto end;\n+\n+\tset_rsu_status(smgr, IFPGA_RSU_COPYING, 0);\n+\tlog_time(time(NULL) - start, \"Applying secure flash update\");\n+\tret = apply_flash_update(smgr);\n+\n+end:\n+\tif (sec_mgr) {\n+\t\tsec_mgr = NULL;\n+\t\tif (sigaction(SIGINT, &old_sigint_action, NULL) < 0)\n+\t\t\tdev_err(smgr, \"Failed to unregister signal handler\\n\");\n+\t}\n+\n+\tsecure_update_status(smgr, status);\n+\tif (ret < 0) {\n+\t\tlog_time(time(NULL) - start, \"Secure flash update ERROR\");\n+\t\tif (ret == -EAGAIN)\n+\t\t\tsecure_update_cancel(smgr);\n+\t} else {\n+\t\tlog_time(time(NULL) - start, \"Secure flash update OK\");\n+\t}\n+\tset_rsu_status(smgr, IFPGA_RSU_IDLE, 0);\n+\n+\treturn ret;\n+}\n+\n+int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)\n+{\n+\tstruct ifpga_sec_mgr *smgr = NULL;\n+\tuint32_t status = 0;\n+\tint retry = IFPGA_RSU_CANCEL_RETRY;\n+\tint ret = 0;\n+\n+\tif (!fme) {\n+\t\tdev_err(fme, \"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\tsmgr = (struct ifpga_sec_mgr *)fme->sec_mgr;\n+\n+\tget_rsu_status(smgr, &status, NULL);\n+\tif (status != IFPGA_RSU_IDLE) {\n+\t\tdev_info(smgr, \"Cancel secure flash update\\n\");\n+\t\tset_rsu_control(smgr, IFPGA_RSU_ABORT);\n+\t}\n+\n+\tif (force) {\n+\t\tsleep(2);\n+\t\tdo {\n+\t\t\tget_rsu_status(smgr, &status, NULL);\n+\t\t\tif (status == IFPGA_RSU_IDLE)\n+\t\t\t\tbreak;\n+\t\t\tif (secure_update_cancel(smgr) == 0)\n+\t\t\t\tset_rsu_status(smgr, IFPGA_RSU_IDLE, 0);\n+\t\t\tsleep(1);\n+\t\t} while (--retry > 0);\n+\t\tif (retry <= 0) {\n+\t\t\tdev_err(smgr, \"Failed to stop flash update\\n\");\n+\t\t\tret = -EAGAIN;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+int fpga_reload(struct ifpga_fme_hw *fme, int type, int page)\n+{\n+\tstruct ifpga_sec_mgr *smgr = NULL;\n+\n+\tif (!fme) {\n+\t\tdev_err(fme, \"Input parameter of %s is invalid\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n+\tsmgr = (struct ifpga_sec_mgr *)fme->sec_mgr;\n+\n+\tif (!smgr || !smgr->ops || !smgr->ops->reload)\n+\t\treturn -EINVAL;\n+\n+\treturn smgr->ops->reload(smgr, type, page);\n+}\ndiff --git a/drivers/raw/ifpga/base/ifpga_hw.h b/drivers/raw/ifpga/base/ifpga_hw.h\nindex 7c3307fe77..ed5edc6016 100644\n--- a/drivers/raw/ifpga/base/ifpga_hw.h\n+++ b/drivers/raw/ifpga/base/ifpga_hw.h\n@@ -91,6 +91,7 @@ struct ifpga_fme_hw {\n \tstruct opae_board_info board_info;\n \tint nums_eth_dev;\n \tunsigned int nums_acc_region;\n+\tvoid *sec_mgr;\n };\n \n enum ifpga_port_state {\ndiff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.c b/drivers/raw/ifpga/base/ifpga_sec_mgr.c\nnew file mode 100644\nindex 0000000000..4cf1db3049\n--- /dev/null\n+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.c\n@@ -0,0 +1,639 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <fcntl.h>\n+#include <signal.h>\n+#include <unistd.h>\n+#include \"ifpga_sec_mgr.h\"\n+\n+\n+static const char * const rsu_prog[] = {\"IDLE\", \"PREPARING\", \"SLEEPING\",\n+\t\"READY\", \"AUTHENTICATING\", \"COPYING\", \"CANCELLATION\", \"PROGRAMMING_KEY\",\n+\t\"DONE\", \"PKVL_DONE\"};\n+static const char * const rsu_statl[] = {\"NORMAL\", \"TIMEOUT\", \"AUTH_FAIL\",\n+\t\"COPY_FAIL\", \"FATAL\", \"PKVL_REJECT\", \"NON_INCR\", \"ERASE_FAIL\",\n+\t\"WEAROUT\"};\n+static const char * const rsu_stath[] = {\"NIOS_OK\", \"USER_OK\", \"FACTORY_OK\",\n+\t\"USER_FAIL\", \"FACTORY_FAIL\", \"NIOS_FLASH_ERR\", \"FPGA_FLASH_ERR\"};\n+\n+static const char *rsu_progress_name(uint32_t prog)\n+{\n+\tif (prog > SEC_PROGRESS_PKVL_PROM_DONE)\n+\t\treturn \"UNKNOWN\";\n+\telse\n+\t\treturn rsu_prog[prog];\n+}\n+\n+static const char *rsu_status_name(uint32_t stat)\n+{\n+\tif (stat >= SEC_STATUS_NIOS_OK) {\n+\t\tif (stat > SEC_STATUS_FPGA_FLASH_ERR)\n+\t\t\treturn \"UNKNOWN\";\n+\t\telse\n+\t\t\treturn rsu_stath[stat-SEC_STATUS_NIOS_OK];\n+\t} else {\n+\t\tif (stat > SEC_STATUS_WEAROUT)\n+\t\t\treturn \"UNKNOWN\";\n+\t\telse\n+\t\t\treturn rsu_statl[stat];\n+\t}\n+}\n+\n+static bool secure_start_done(uint32_t doorbell)\n+{\n+\treturn (SEC_STATUS_G(doorbell) == SEC_STATUS_ERASE_FAIL ||\n+\t\tSEC_STATUS_G(doorbell) == SEC_STATUS_WEAROUT ||\n+\t\t(SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_IDLE &&\n+\t\tSEC_PROGRESS_G(doorbell) != SEC_PROGRESS_RSU_DONE));\n+}\n+\n+static bool secure_prog_ready(uint32_t doorbell)\n+{\n+\treturn (SEC_PROGRESS_G(doorbell) != SEC_PROGRESS_READY);\n+}\n+\n+static int poll_timeout(struct intel_max10_device *dev, uint32_t offset,\n+\tbool (*cond)(uint32_t), uint32_t interval_ms, uint32_t timeout_ms)\n+{\n+\tuint32_t val = 0;\n+\tint ret = 0;\n+\n+\tfor (;;) {\n+\t\tret = max10_sys_read(dev, offset, &val);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to read max10 register 0x%x [e:%d]\\n\",\n+\t\t\t\toffset, ret);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (cond(val)) {\n+\t\t\tdev_debug(dev,\n+\t\t\t\t\"Read 0x%08x from max10 register 0x%x \"\n+\t\t\t\t\"[poll success]\\n\", val, offset);\n+\t\t\tret = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (timeout_ms > interval_ms)\n+\t\t\ttimeout_ms -= interval_ms;\n+\t\telse\n+\t\t\ttimeout_ms = 0;\n+\t\tif (timeout_ms == 0) {\n+\t\t\tdev_debug(dev,\n+\t\t\t\t\"Read 0x%08x from max10 register 0x%x \"\n+\t\t\t\t\"[poll timeout]\\n\", val, offset);\n+\t\t\tret = -ETIMEDOUT;\n+\t\t\tbreak;\n+\t\t}\n+\t\tmsleep(interval_ms);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int n3000_secure_update_start(struct intel_max10_device *dev)\n+{\n+\tuint32_t doorbell = 0;\n+\tuint32_t prog = 0;\n+\tuint32_t status = 0;\n+\tint ret = 0;\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tprog = SEC_PROGRESS_G(doorbell);\n+\tif ((prog != SEC_PROGRESS_IDLE) && (prog != SEC_PROGRESS_RSU_DONE)) {\n+\t\tdev_debug(dev, \"Current RSU progress is %s\\n\",\n+\t\t\trsu_progress_name(prog));\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tret = max10_sys_update_bits(dev, MAX10_DOORBELL,\n+\t\tRSU_REQUEST | HOST_STATUS, RSU_REQUEST);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to updt max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = poll_timeout(dev, MAX10_DOORBELL, secure_start_done,\n+\t\tIFPGA_SEC_START_INTERVAL_MS, IFPGA_SEC_START_TIMEOUT_MS);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to poll max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tstatus = SEC_STATUS_G(doorbell);\n+\tif (status == SEC_STATUS_WEAROUT)\n+\t\treturn -EAGAIN;\n+\n+\tif (status == SEC_STATUS_ERASE_FAIL)\n+\t\treturn -EIO;\n+\n+\treturn 0;\n+}\n+\n+static int n3000_cancel(struct ifpga_sec_mgr *smgr)\n+{\n+\tstruct intel_max10_device *dev = NULL;\n+\tuint32_t doorbell = 0;\n+\tuint32_t prog = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr || !smgr->max10_dev)\n+\t\treturn -ENODEV;\n+\tdev = (struct intel_max10_device *)smgr->max10_dev;\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tprog = SEC_PROGRESS_G(doorbell);\n+\tif (prog == SEC_PROGRESS_IDLE)\n+\t\treturn 0;\n+\tif (prog != SEC_PROGRESS_READY)\n+\t\treturn -EBUSY;\n+\n+\treturn max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,\n+\t\tHOST_STATUS_S(HOST_STATUS_ABORT_RSU));\n+}\n+\n+static int n3000_prepare(struct ifpga_sec_mgr *smgr)\n+{\n+\tstruct intel_max10_device *dev = NULL;\n+\tint retry = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr || !smgr->max10_dev)\n+\t\treturn -ENODEV;\n+\tdev = (struct intel_max10_device *)smgr->max10_dev;\n+\n+\tret = n3000_secure_update_start(dev);\n+\tif (ret == -EBUSY)\n+\t\tn3000_cancel(smgr);\n+\n+\twhile (ret) {\n+\t\tif (++retry > IFPGA_RSU_START_RETRY)\n+\t\t\tbreak;\n+\t\tmsleep(1000);\n+\t\tret = n3000_secure_update_start(dev);\n+\t}\n+\tif (retry > IFPGA_RSU_START_RETRY) {\n+\t\tdev_err(dev, \"Failed to start secure flash update\\n\");\n+\t\tret = -EAGAIN;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int n3000_bulk_write(struct intel_max10_device *dev, uint32_t addr,\n+\tchar *buf, uint32_t len)\n+{\n+\tuint32_t i = 0;\n+\tuint32_t n = 0;\n+\tuint32_t v = 0;\n+\tuint32_t p = 0;\n+\tint ret = 0;\n+\n+\tif (len & 0x3) {\n+\t\tdev_err(dev,\n+\t\t\t\"Length of data block is not 4 bytes aligned [e:%u]\\n\",\n+\t\t\tlen);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tn = len >> 2;\n+\tfor (i = 0; i < n; i++) {\n+\t\tp = i << 2;\n+\t\tv = *(uint32_t *)(buf + p);\n+\t\tret = max10_reg_write(dev, addr + p, v);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to write to staging area 0x%08x [e:%d]\\n\",\n+\t\t\t\taddr + p, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tusleep(1);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int n3000_write_blk(struct ifpga_sec_mgr *smgr, char *buf,\n+\tuint32_t offset, uint32_t len)\n+{\n+\tstruct intel_max10_device *dev = NULL;\n+\tuint32_t doorbell = 0;\n+\tuint32_t prog = 0;\n+\tuint32_t m = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr || !smgr->max10_dev)\n+\t\treturn -ENODEV;\n+\tdev = (struct intel_max10_device *)smgr->max10_dev;\n+\n+\tif (offset + len > dev->staging_area_size) {\n+\t\tdev_err(dev,\n+\t\t\t\"Write position would be out of staging area [e:%u]\\n\",\n+\t\t\tdev->staging_area_size);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tprog = SEC_PROGRESS_G(doorbell);\n+\tif (prog == SEC_PROGRESS_PREPARE)\n+\t\treturn -EAGAIN;\n+\telse if (prog != SEC_PROGRESS_READY)\n+\t\treturn -EBUSY;\n+\n+\tm = len & 0x3;\n+\tif (m != 0)\n+\t\tlen += 4 - m;   /* make length to 4 bytes align */\n+\n+\treturn n3000_bulk_write(dev, dev->staging_area_base + offset, buf, len);\n+}\n+\n+static int n3000_write_done(struct ifpga_sec_mgr *smgr)\n+{\n+\tstruct intel_max10_device *dev = NULL;\n+\tuint32_t doorbell = 0;\n+\tuint32_t prog = 0;\n+\tuint32_t status = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr || !smgr->max10_dev)\n+\t\treturn -ENODEV;\n+\tdev = (struct intel_max10_device *)smgr->max10_dev;\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tprog = SEC_PROGRESS_G(doorbell);\n+\tif (prog != SEC_PROGRESS_READY)\n+\t\treturn -EBUSY;\n+\n+\tret = max10_sys_update_bits(dev, MAX10_DOORBELL, HOST_STATUS,\n+\t\tHOST_STATUS_S(HOST_STATUS_WRITE_DONE));\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to update max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = poll_timeout(dev, MAX10_DOORBELL, secure_prog_ready,\n+\t\tIFPGA_NIOS_HANDSHAKE_INTERVAL_MS,\n+\t\tIFPGA_NIOS_HANDSHAKE_TIMEOUT_MS);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to poll max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tstatus = SEC_STATUS_G(doorbell);\n+\tswitch (status) {\n+\tcase SEC_STATUS_NORMAL:\n+\tcase SEC_STATUS_NIOS_OK:\n+\tcase SEC_STATUS_USER_OK:\n+\tcase SEC_STATUS_FACTORY_OK:\n+\t\tret = 0;\n+\t\tbreak;\n+\tdefault:\n+\t\tret = -EIO;\n+\t\tbreak;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int n3000_check_complete(struct ifpga_sec_mgr *smgr)\n+{\n+\tstruct intel_max10_device *dev = NULL;\n+\tuint32_t doorbell = 0;\n+\tuint32_t status = 0;\n+\tuint32_t prog = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr || !smgr->max10_dev)\n+\t\treturn -ENODEV;\n+\tdev = (struct intel_max10_device *)smgr->max10_dev;\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\n+\tstatus = SEC_STATUS_G(doorbell);\n+\tswitch (status) {\n+\tcase SEC_STATUS_NORMAL:\n+\tcase SEC_STATUS_NIOS_OK:\n+\tcase SEC_STATUS_USER_OK:\n+\tcase SEC_STATUS_FACTORY_OK:\n+\tcase SEC_STATUS_WEAROUT:\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EIO;\n+\t}\n+\n+\tprog = SEC_PROGRESS_G(doorbell);\n+\tswitch (prog) {\n+\tcase SEC_PROGRESS_IDLE:\n+\tcase SEC_PROGRESS_RSU_DONE:\n+\t\treturn 0;\n+\tcase SEC_PROGRESS_AUTHENTICATING:\n+\tcase SEC_PROGRESS_COPYING:\n+\tcase SEC_PROGRESS_UPDATE_CANCEL:\n+\tcase SEC_PROGRESS_PROGRAM_KEY_HASH:\n+\t\treturn -EAGAIN;\n+\tcase SEC_PROGRESS_PREPARE:\n+\tcase SEC_PROGRESS_READY:\n+\t\treturn -EBUSY;\n+\tdefault:\n+\t\treturn -EIO;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int n3000_reload_fpga(struct intel_max10_device *dev, int page)\n+{\n+\tint ret = 0;\n+\n+\tdev_info(dev, \"Reload FPGA\\n\");\n+\n+\tif (!dev || ((page != 0) && (page != 1))) {\n+\t\tdev_err(dev, \"Input parameter of %s is invalid\\n\", __func__);\n+\t\tret = -EINVAL;\n+\t\tgoto end;\n+\t}\n+\n+\tif (dev->flags & MAX10_FLAGS_SECURE) {\n+\t\tret = max10_sys_update_bits(dev, FPGA_RECONF_REG,\n+\t\t\tSFPGA_RP_LOAD, 0);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to update max10 reconfig register [e:%d]\\n\",\n+\t\t\t\tret);\n+\t\t\tgoto end;\n+\t\t}\n+\t\tret = max10_sys_update_bits(dev, FPGA_RECONF_REG,\n+\t\t\tSFPGA_RP_LOAD | SFPGA_RECONF_PAGE,\n+\t\t\tSFPGA_RP_LOAD | SFPGA_PAGE(page));\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to update max10 reconfig register [e:%d]\\n\",\n+\t\t\t\tret);\n+\t\t\tgoto end;\n+\t\t}\n+\t} else {\n+\t\tret = max10_sys_update_bits(dev, RSU_REG, FPGA_RP_LOAD, 0);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to update max10 rsu register [e:%d]\\n\",\n+\t\t\t\tret);\n+\t\t\tgoto end;\n+\t\t}\n+\t\tret = max10_sys_update_bits(dev, RSU_REG,\n+\t\t\tFPGA_RP_LOAD | FPGA_RECONF_PAGE,\n+\t\t\tFPGA_RP_LOAD | FPGA_PAGE(page));\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to update max10 rsu register [e:%d]\\n\",\n+\t\t\t\tret);\n+\t\t\tgoto end;\n+\t\t}\n+\t}\n+\n+\tret = max10_sys_update_bits(dev, FPGA_RECONF_REG, COUNTDOWN_START, 0);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to update max10 reconfig register [e:%d]\\n\",\n+\t\t\tret);\n+\t\tgoto end;\n+\t}\n+\n+\tret = max10_sys_update_bits(dev, FPGA_RECONF_REG, COUNTDOWN_START,\n+\t\tCOUNTDOWN_START);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to update max10 reconfig register [e:%d]\\n\",\n+\t\t\tret);\n+\t}\n+end:\n+\tif (ret < 0)\n+\t\tdev_err(dev, \"Failed to reload FPGA\\n\");\n+\n+\treturn ret;\n+}\n+\n+static int n3000_reload_bmc(struct intel_max10_device *dev, int page)\n+{\n+\tuint32_t val = 0;\n+\tint ret = 0;\n+\n+\tdev_info(dev, \"Reload BMC\\n\");\n+\n+\tif (!dev || ((page != 0) && (page != 1))) {\n+\t\tdev_err(dev, \"Input parameter of %s is invalid\\n\", __func__);\n+\t\tret = -EINVAL;\n+\t\tgoto end;\n+\t}\n+\n+\tif (dev->flags & MAX10_FLAGS_SECURE) {\n+\t\tret = max10_sys_update_bits(dev, MAX10_DOORBELL,\n+\t\t\tCONFIG_SEL | REBOOT_REQ,\n+\t\t\tCONFIG_SEL_S(page) | REBOOT_REQ);\n+\t} else {\n+\t\tval = (page == 0) ? 0x1 : 0x3;\n+\t\tret = max10_reg_write(dev, IFPGA_DUAL_CFG_CTRL1, val);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to write to dual config1 register [e:%d]\\n\",\n+\t\t\t\tret);\n+\t\t\tgoto end;\n+\t\t}\n+\n+\t\tret = max10_reg_write(dev, IFPGA_DUAL_CFG_CTRL0, 0x1);\n+\t\tif (ret < 0) {\n+\t\t\tif (ret == -EIO) {\n+\t\t\t\tret = 0;\n+\t\t\t\tgoto end;\n+\t\t\t}\n+\t\t\tdev_err(dev,\n+\t\t\t\t\"Failed to write to dual config0 register [e:%d]\\n\",\n+\t\t\t\tret);\n+\t\t}\n+\t}\n+\n+end:\n+\tif (ret < 0)\n+\t\tdev_err(dev, \"Failed to reload BMC\\n\");\n+\n+\treturn ret;\n+}\n+\n+static int n3000_reload(struct ifpga_sec_mgr *smgr, int type, int page)\n+{\n+\tint psel = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr || !smgr->max10_dev)\n+\t\treturn -ENODEV;\n+\n+\tif (type == IFPGA_BOOT_TYPE_FPGA) {\n+\t\tpsel = (page == IFPGA_BOOT_PAGE_FACTORY ? 0 : 1);\n+\t\tret = n3000_reload_fpga(smgr->max10_dev, psel);\n+\t} else if (type == IFPGA_BOOT_TYPE_BMC) {\n+\t\tpsel = (page == IFPGA_BOOT_PAGE_FACTORY ? 1 : 0);\n+\t\tret = n3000_reload_bmc(smgr->max10_dev, psel);\n+\t} else {\n+\t\tret = -EINVAL;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static uint64_t n3000_get_hw_errinfo(struct ifpga_sec_mgr *smgr)\n+{\n+\tstruct intel_max10_device *dev = NULL;\n+\tuint32_t doorbell = 0;\n+\tuint32_t stat = 0;\n+\tuint32_t prog = 0;\n+\tuint32_t auth_result = 0;\n+\tint ret = 0;\n+\n+\tif (!smgr || !smgr->max10_dev)\n+\t\treturn -ENODEV;\n+\tdev = (struct intel_max10_device *)smgr->max10_dev;\n+\n+\tret = max10_sys_read(dev, MAX10_DOORBELL, &doorbell);\n+\tif (ret < 0) {\n+\t\tdev_err(dev, \"Failed to read max10 doorbell register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn -1;\n+\t}\n+\tstat = SEC_STATUS_G(doorbell);\n+\tprog = SEC_PROGRESS_G(doorbell);\n+\tdev_debug(dev, \"Current RSU status is %s, progress is %s\\n\",\n+\t\trsu_status_name(stat), rsu_progress_name(prog));\n+\n+\tret = max10_sys_read(dev, MAX10_AUTH_RESULT, &auth_result);\n+\tif (ret < 0) {\n+\t\tdev_err(dev,\n+\t\t\t\"Failed to read authenticate result register [e:%d]\\n\",\n+\t\t\tret);\n+\t\treturn -1;\n+\t}\n+\n+\treturn (uint64_t)doorbell << 32 | (uint64_t)auth_result;\n+}\n+\n+static const struct ifpga_sec_ops n3000_sec_ops = {\n+\t.prepare = n3000_prepare,\n+\t.write_blk = n3000_write_blk,\n+\t.write_done = n3000_write_done,\n+\t.check_complete = n3000_check_complete,\n+\t.reload = n3000_reload,\n+\t.cancel = n3000_cancel,\n+\t.cleanup = NULL,\n+\t.get_hw_errinfo = n3000_get_hw_errinfo,\n+};\n+\n+int init_sec_mgr(struct ifpga_fme_hw *fme)\n+{\n+\tstruct ifpga_hw *hw = NULL;\n+\topae_share_data *sd = NULL;\n+\tstruct ifpga_sec_mgr *smgr = NULL;\n+\n+\tif (!fme || !fme->max10_dev)\n+\t\treturn -ENODEV;\n+\n+\tsmgr = (struct ifpga_sec_mgr *)malloc(sizeof(*smgr));\n+\tif (!smgr) {\n+\t\tdev_err(NULL, \"Failed to allocate memory for security manager\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tfme->sec_mgr = smgr;\n+\n+\thw = (struct ifpga_hw *)fme->parent;\n+\tif (hw && hw->adapter && hw->adapter->shm.ptr) {\n+\t\tsd = (opae_share_data *)hw->adapter->shm.ptr;\n+\t\tsmgr->rsu_control = &sd->rsu_ctrl;\n+\t\tsmgr->rsu_status = &sd->rsu_stat;\n+\t} else {\n+\t\tsmgr->rsu_control = NULL;\n+\t\tsmgr->rsu_status = NULL;\n+\t}\n+\n+\tif ((hw->pci_data->device_id == IFPGA_N3000_DID) &&\n+\t\t(hw->pci_data->vendor_id == IFPGA_N3000_VID)) {\n+\t\tsmgr->ops = &n3000_sec_ops;\n+\t\tsmgr->copy_speed = IFPGA_N3000_COPY_SPEED;\n+\t} else {\n+\t\tdev_err(NULL, \"No operation for security manager\\n\");\n+\t\tsmgr->ops = NULL;\n+\t}\n+\n+\tsmgr->fme = fme;\n+\tsmgr->max10_dev = fme->max10_dev;\n+\n+\treturn 0;\n+}\n+\n+void release_sec_mgr(struct ifpga_fme_hw *fme)\n+{\n+\tstruct ifpga_sec_mgr *smgr = NULL;\n+\n+\tif (fme) {\n+\t\tsmgr = (struct ifpga_sec_mgr *)fme->sec_mgr;\n+\t\tif (smgr) {\n+\t\t\tfme->sec_mgr = NULL;\n+\t\t\tfree(smgr);\n+\t\t}\n+\t}\n+}\ndiff --git a/drivers/raw/ifpga/base/ifpga_sec_mgr.h b/drivers/raw/ifpga/base/ifpga_sec_mgr.h\nnew file mode 100644\nindex 0000000000..fbeba561f4\n--- /dev/null\n+++ b/drivers/raw/ifpga/base/ifpga_sec_mgr.h\n@@ -0,0 +1,93 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _IFPGA_FME_RSU_H_\n+#define _IFPGA_FME_RSU_H_\n+\n+\n+#include \"ifpga_hw.h\"\n+\n+#define IFPGA_N3000_VID     0x8086\n+#define IFPGA_N3000_DID     0x0b30\n+\n+#define IFPGA_BOOT_TYPE_FPGA     0\n+#define IFPGA_BOOT_TYPE_BMC      1\n+\n+#define IFPGA_BOOT_PAGE_FACTORY  0\n+#define IFPGA_BOOT_PAGE_USER     1\n+\n+#define IFPGA_RSU_DATA_BLK_SIZE  32768\n+#define IFPGA_RSU_START_RETRY    120\n+#define IFPGA_RSU_WRITE_RETRY    10\n+#define IFPGA_RSU_CANCEL_RETRY   30\n+\n+#define IFPGA_N3000_COPY_SPEED   42700\n+\n+/* status */\n+#define IFPGA_RSU_IDLE       0\n+#define IFPGA_RSU_PREPARE    1\n+#define IFPGA_RSU_READY      2\n+#define IFPGA_RSU_COPYING    3\n+#define IFPGA_RSU_REBOOT     4\n+\n+#define IFPGA_RSU_GET_STAT(v)  (((v) >> 16) & 0xffff)\n+#define IFPGA_RSU_GET_PROG(v)  ((v) & 0xffff)\n+#define IFPGA_RSU_STATUS(s, p) ((((s) << 16) & 0xffff0000) | ((p) & 0xffff))\n+\n+/* control */\n+#define IFPGA_RSU_ABORT      1\n+\n+#define IFPGA_DUAL_CFG_CTRL0     0x200020\n+#define IFPGA_DUAL_CFG_CTRL1     0x200024\n+\n+#define IFPGA_SEC_START_INTERVAL_MS       100\n+#define IFPGA_SEC_START_TIMEOUT_MS        20000\n+#define IFPGA_NIOS_HANDSHAKE_INTERVAL_MS  100\n+#define IFPGA_NIOS_HANDSHAKE_TIMEOUT_MS   5000\n+\n+#define IFPGA_RSU_ERR_HW_ERROR\t\t-1\n+#define IFPGA_RSU_ERR_TIMEOUT\t\t-2\n+#define IFPGA_RSU_ERR_CANCELED\t\t-3\n+#define IFPGA_RSU_ERR_BUSY\t\t\t-4\n+#define IFPGA_RSU_ERR_INVALID_SIZE\t-5\n+#define IFPGA_RSU_ERR_RW_ERROR\t\t-6\n+#define IFPGA_RSU_ERR_WEAROUT\t\t-7\n+#define IFPGA_RSU_ERR_FILE_READ\t\t-8\n+\n+struct ifpga_sec_mgr;\n+\n+struct ifpga_sec_ops {\n+\tint (*prepare)(struct ifpga_sec_mgr *smgr);\n+\tint (*write_blk)(struct ifpga_sec_mgr *smgr, char *buf, uint32_t offset,\n+\t\tuint32_t size);\n+\tint (*write_done)(struct ifpga_sec_mgr *smgr);\n+\tint (*check_complete)(struct ifpga_sec_mgr *smgr);\n+\tint (*reload)(struct ifpga_sec_mgr *smgr, int type, int page);\n+\tint (*cancel)(struct ifpga_sec_mgr *smgr);\n+\tvoid (*cleanup)(struct ifpga_sec_mgr *smgr);\n+\tu64 (*get_hw_errinfo)(struct ifpga_sec_mgr *smgr);\n+};\n+\n+struct ifpga_sec_mgr {\n+\tstruct ifpga_fme_hw *fme;\n+\tstruct intel_max10_device *max10_dev;\n+\tunsigned int rsu_length;\n+\t/* number of bytes that copied from staging area to working area\n+\t * in one second, which is calculated by experiment\n+\t */\n+\tunsigned int copy_speed;\n+\tunsigned int *rsu_control;\n+\tunsigned int *rsu_status;\n+\tconst struct ifpga_sec_ops *ops;\n+};\n+\n+int init_sec_mgr(struct ifpga_fme_hw *fme);\n+void release_sec_mgr(struct ifpga_fme_hw *fme);\n+int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,\n+\tuint64_t *status);\n+int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force);\n+int fpga_reload(struct ifpga_fme_hw *fme, int type, int page);\n+\n+\n+#endif /* _IFPGA_FME_RSU_H_ */\ndiff --git a/drivers/raw/ifpga/base/meson.build b/drivers/raw/ifpga/base/meson.build\nindex da2d6e33ca..3549afafa1 100644\n--- a/drivers/raw/ifpga/base/meson.build\n+++ b/drivers/raw/ifpga/base/meson.build\n@@ -12,6 +12,8 @@ sources = [\n \t'ifpga_port.c',\n \t'ifpga_port_error.c',\n \t'ifpga_fme_pr.c',\n+\t'ifpga_fme_rsu.c',\n+\t'ifpga_sec_mgr.c',\n \t'opae_hw_api.c',\n \t'opae_ifpga_hw_api.c',\n \t'opae_debug.c',\ndiff --git a/drivers/raw/ifpga/base/opae_hw_api.c b/drivers/raw/ifpga/base/opae_hw_api.c\nindex d5cd5fe608..86ad88f720 100644\n--- a/drivers/raw/ifpga/base/opae_hw_api.c\n+++ b/drivers/raw/ifpga/base/opae_hw_api.c\n@@ -470,6 +470,8 @@ static void opae_adapter_shm_init(struct opae_adapter *adapter)\n \topae_mutex_init(&sd->i2c_mutex);\n \tsd->ref_cnt = 0;\n \tsd->dtb_size = SHM_BLK_SIZE;\n+\tsd->rsu_ctrl = 0;\n+\tsd->rsu_stat = 0;\n }\n \n static void *opae_adapter_shm_alloc(struct opae_adapter *adapter)\n@@ -964,3 +966,60 @@ opae_mgr_get_board_info(struct opae_manager *mgr,\n \n \treturn -ENOENT;\n }\n+\n+/**\n+ * opae_mgr_update_flash -  update image in flash.\n+ * @mgr: targeted manager\n+ * @image: name of image file\n+ * @status: status of update\n+ *\n+ * Return: 0 on success, otherwise error code.\n+ */\n+int opae_mgr_update_flash(struct opae_manager *mgr, const char *image,\n+\tuint64_t *status)\n+{\n+\tif (!mgr)\n+\t\treturn -EINVAL;\n+\n+\tif (mgr->ops && mgr->ops->update_flash)\n+\t\treturn mgr->ops->update_flash(mgr, image, status);\n+\n+\treturn -ENOENT;\n+}\n+\n+/**\n+ * opae_stop_flash_update -  stop flash update.\n+ * @mgr: targeted manager\n+ * @force: make sure the update process is stopped\n+ *\n+ * Return: 0 on success, otherwise error code.\n+ */\n+int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force)\n+{\n+\tif (!mgr)\n+\t\treturn -EINVAL;\n+\n+\tif (mgr->ops && mgr->ops->stop_flash_update)\n+\t\treturn mgr->ops->stop_flash_update(mgr, force);\n+\n+\treturn -ENOENT;\n+}\n+\n+/**\n+ * opae_mgr_reload -  reload FPGA.\n+ * @mgr: targeted manager\n+ * @type: FPGA type\n+ * @page: reload from which page\n+ *\n+ * Return: 0 on success, otherwise error code.\n+ */\n+int opae_mgr_reload(struct opae_manager *mgr, int type, int page)\n+{\n+\tif (!mgr)\n+\t\treturn -EINVAL;\n+\n+\tif (mgr->ops && mgr->ops->reload)\n+\t\treturn mgr->ops->reload(mgr, type, page);\n+\n+\treturn -ENOENT;\n+}\ndiff --git a/drivers/raw/ifpga/base/opae_hw_api.h b/drivers/raw/ifpga/base/opae_hw_api.h\nindex e99ee4564c..91d26d9b5b 100644\n--- a/drivers/raw/ifpga/base/opae_hw_api.h\n+++ b/drivers/raw/ifpga/base/opae_hw_api.h\n@@ -55,6 +55,10 @@ struct opae_manager_ops {\n \t\t\tunsigned int *value);\n \tint (*get_board_info)(struct opae_manager *mgr,\n \t\t\tstruct opae_board_info **info);\n+\tint (*update_flash)(struct opae_manager *mgr, const char *image,\n+\t\t\tu64 *status);\n+\tint (*stop_flash_update)(struct opae_manager *mgr, int force);\n+\tint (*reload)(struct opae_manager *mgr, int type, int page);\n };\n \n /* networking management ops in FME */\n@@ -276,6 +280,8 @@ typedef struct {\n \t\t\tpthread_mutex_t i2c_mutex;\n \t\t\tu32 ref_cnt;    /* reference count of shared memory */\n \t\t\tu32 dtb_size;   /* actual length of DTB data in byte */\n+\t\t\tu32 rsu_ctrl;   /* used to control rsu */\n+\t\t\tu32 rsu_stat;   /* used to report status for rsu */\n \t\t};\n \t};\n \tu8 dtb[SHM_BLK_SIZE];   /* DTB data */\n@@ -354,4 +360,8 @@ int opae_manager_eth_group_read_reg(struct opae_manager *mgr, u8 group_id,\n \t\tu8 type, u8 index, u16 addr, u32 *data);\n int opae_mgr_get_board_info(struct opae_manager *mgr,\n \t\tstruct opae_board_info **info);\n+int opae_mgr_update_flash(struct opae_manager *mgr, const char *image,\n+\t\tuint64_t *status);\n+int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force);\n+int opae_mgr_reload(struct opae_manager *mgr, int type, int page);\n #endif /* _OPAE_HW_API_H_*/\ndiff --git a/drivers/raw/ifpga/base/opae_intel_max10.c b/drivers/raw/ifpga/base/opae_intel_max10.c\nindex 1a526ea549..443e248fb3 100644\n--- a/drivers/raw/ifpga/base/opae_intel_max10.c\n+++ b/drivers/raw/ifpga/base/opae_intel_max10.c\n@@ -51,6 +51,22 @@ int max10_sys_write(struct intel_max10_device *dev,\n \treturn max10_reg_write(dev, dev->base + offset, val);\n }\n \n+int max10_sys_update_bits(struct intel_max10_device *dev, unsigned int offset,\n+\t\t\t\t\tunsigned int msk, unsigned int val)\n+{\n+\tint ret = 0;\n+\tunsigned int temp = 0;\n+\n+\tret = max10_sys_read(dev, offset, &temp);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\ttemp &= ~msk;\n+\ttemp |= val & msk;\n+\n+\treturn max10_sys_write(dev, offset, temp);\n+}\n+\n static struct max10_compatible_id max10_id_table[] = {\n \t{.compatible = MAX10_PAC,},\n \t{.compatible = MAX10_PAC_N3000,},\n@@ -557,6 +573,36 @@ static int check_max10_version(struct intel_max10_device *dev)\n \treturn -ENODEV;\n }\n \n+static int max10_staging_area_init(struct intel_max10_device *dev)\n+{\n+\tchar *fdt_root = dev->fdt_root;\n+\tint ret, offset = 0;\n+\tu64 start, size;\n+\n+\tif (!fdt_root) {\n+\t\tdev_debug(dev,\n+\t\t\t\"skip staging area init as not find Device Tree\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tdev->staging_area_size = 0;\n+\n+\tfdt_for_each_subnode(offset, fdt_root, 0) {\n+\t\tif (fdt_node_check_compatible(fdt_root, offset,\n+\t\t\t\t\t      \"ifpga-sec-mgr,staging-area\"))\n+\t\t\tcontinue;\n+\n+\t\tret = fdt_get_reg(fdt_root, offset, 0, &start, &size);\n+\t\tif (!ret) {\n+\t\t\tdev->staging_area_base = start;\n+\t\t\tdev->staging_area_size = size;\n+\t\t}\n+\t\treturn ret;\n+\t}\n+\n+\treturn -ENODEV;\n+}\n+\n static int\n max10_secure_hw_init(struct intel_max10_device *dev)\n {\n@@ -581,6 +627,8 @@ max10_secure_hw_init(struct intel_max10_device *dev)\n \n \tmax10_sensor_init(dev, sysmgr_offset);\n \n+\tmax10_staging_area_init(dev);\n+\n \treturn 0;\n }\n \ndiff --git a/drivers/raw/ifpga/base/opae_intel_max10.h b/drivers/raw/ifpga/base/opae_intel_max10.h\nindex 123cdc48b9..670683f017 100644\n--- a/drivers/raw/ifpga/base/opae_intel_max10.h\n+++ b/drivers/raw/ifpga/base/opae_intel_max10.h\n@@ -38,6 +38,8 @@ struct intel_max10_device {\n \tunsigned int base; /* max10 base address */\n \tu16 bus;\n \tstruct opae_sensor_list opae_sensor_list;\n+\tu32 staging_area_base;\n+\tu32 staging_area_size;\n };\n \n /* retimer speed */\n@@ -98,6 +100,7 @@ struct opae_retimer_status {\n #define   MAX10_MAC_COUNT\tGENMASK(23, 16)\n #define RSU_REG\t\t\t0x2c\n #define   FPGA_RECONF_PAGE\tGENMASK(2, 0)\n+#define   FPGA_PAGE(p)\t\t((p) & 0x1)\n #define   FPGA_RP_LOAD\t\tBIT(3)\n #define   NIOS2_PRERESET\tBIT(4)\n #define   NIOS2_HANG\t\tBIT(5)\n@@ -106,6 +109,9 @@ struct opae_retimer_status {\n #define   NIOS2_I2C2_POLL_STOP\tBIT(13)\n #define   PKVL_EEPROM_LOAD\tBIT(31)\n #define FPGA_RECONF_REG\t\t0x30\n+#define   SFPGA_RECONF_PAGE\tGENMASK(22, 20)\n+#define   SFPGA_PAGE(p)\t\t(((p) & 0x1) << 20)\n+#define   SFPGA_RP_LOAD\t\tBIT(23)\n #define MAX10_TEST_REG\t\t0x3c\n #define   COUNTDOWN_START\tBIT(18)\n #define MAX10_BUILD_VER\t\t0x68\n@@ -118,8 +124,44 @@ struct opae_retimer_status {\n #define MAX10_DOORBELL\t\t0x400\n #define   RSU_REQUEST\t\tBIT(0)\n #define   SEC_PROGRESS\t\tGENMASK(7, 4)\n+#define   SEC_PROGRESS_G(v)\t(((v) >> 4) & 0xf)\n+#define   SEC_PROGRESS_IDLE\t\t\t\t0x0\n+#define   SEC_PROGRESS_PREPARE\t\t\t0x1\n+#define   SEC_PROGRESS_SLEEP\t\t\t0x2\n+#define   SEC_PROGRESS_READY\t\t\t0x3\n+#define   SEC_PROGRESS_AUTHENTICATING\t0x4\n+#define   SEC_PROGRESS_COPYING\t\t\t0x5\n+#define   SEC_PROGRESS_UPDATE_CANCEL\t0x6\n+#define   SEC_PROGRESS_PROGRAM_KEY_HASH\t0x7\n+#define   SEC_PROGRESS_RSU_DONE\t\t\t0x8\n+#define   SEC_PROGRESS_PKVL_PROM_DONE\t0x9\n #define   HOST_STATUS\t\tGENMASK(11, 8)\n+#define   HOST_STATUS_S(v)\t(((v) << 8) & 0xf00)\n+#define   HOST_STATUS_IDLE\t\t\t0x0\n+#define   HOST_STATUS_WRITE_DONE\t0x1\n+#define   HOST_STATUS_ABORT_RSU\t\t0x2\n #define   SEC_STATUS\t\tGENMASK(23, 16)\n+#define   SEC_STATUS_G(v)\t(((v) >> 16) & 0xff)\n+#define   SEC_STATUS_NORMAL\t\t\t0x0\n+#define   SEC_STATUS_TIMEOUT\t\t0x1\n+#define   SEC_STATUS_AUTH_FAIL\t\t0x2\n+#define   SEC_STATUS_COPY_FAIL\t\t0x3\n+#define   SEC_STATUS_FATAL\t\t\t0x4\n+#define   SEC_STATUS_PKVL_REJECT\t0x5\n+#define   SEC_STATUS_NON_INC\t\t0x6\n+#define   SEC_STATUS_ERASE_FAIL\t\t0x7\n+#define   SEC_STATUS_WEAROUT\t\t0x8\n+#define   SEC_STATUS_NIOS_OK\t\t0x80\n+#define   SEC_STATUS_USER_OK\t\t0x81\n+#define   SEC_STATUS_FACTORY_OK\t\t0x82\n+#define   SEC_STATUS_USER_FAIL\t\t0x83\n+#define   SEC_STATUS_FACTORY_FAIL\t0x84\n+#define   SEC_STATUS_NIOS_FLASH_ERR\t0x85\n+#define   SEC_STATUS_FPGA_FLASH_ERR\t0x86\n+#define   CONFIG_SEL\t\tBIT(28)\n+#define   CONFIG_SEL_S(v)\t(((v) & 0x1) << 28)\n+#define   REBOOT_REQ\t\tBIT(29)\n+#define MAX10_AUTH_RESULT\t0x404\n \n /* PKVL related registers, in system register region */\n #define PKVL_POLLING_CTRL\t\t0x80\n@@ -149,6 +191,8 @@ int max10_sys_read(struct intel_max10_device *dev,\n \tunsigned int offset, unsigned int *val);\n int max10_sys_write(struct intel_max10_device *dev,\n \tunsigned int offset, unsigned int val);\n+int max10_sys_update_bits(struct intel_max10_device *dev,\n+\tunsigned int offset, unsigned int msk, unsigned int val);\n struct intel_max10_device *\n intel_max10_device_probe(struct altera_spi_device *spi,\n \t\tint chipselect);\ndiff --git a/drivers/raw/ifpga/meson.build b/drivers/raw/ifpga/meson.build\nindex 027ff80562..60ea59ae28 100644\n--- a/drivers/raw/ifpga/meson.build\n+++ b/drivers/raw/ifpga/meson.build\n@@ -13,8 +13,10 @@ objs = [base_objs]\n deps += ['ethdev', 'rawdev', 'pci', 'bus_pci', 'kvargs',\n \t'bus_vdev', 'bus_ifpga', 'net', 'net_i40e', 'net_ipn3ke']\n \n-sources = files('ifpga_rawdev.c')\n+sources = files('ifpga_rawdev.c', 'rte_pmd_ifpga.c')\n \n includes += include_directories('base')\n includes += include_directories('../../net/ipn3ke')\n includes += include_directories('../../net/i40e')\n+\n+headers = files('rte_pmd_ifpga.h')\ndiff --git a/drivers/raw/ifpga/rte_pmd_ifpga.c b/drivers/raw/ifpga/rte_pmd_ifpga.c\nnew file mode 100644\nindex 0000000000..af6f175e98\n--- /dev/null\n+++ b/drivers/raw/ifpga/rte_pmd_ifpga.c\n@@ -0,0 +1,163 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 Intel Corporation\n+ */\n+\n+#include <rte_pci.h>\n+#include <rte_bus_pci.h>\n+#include <rte_rawdev.h>\n+#include <rte_rawdev_pmd.h>\n+#include \"rte_pmd_ifpga.h\"\n+#include \"ifpga_rawdev.h\"\n+#include \"base/ifpga_sec_mgr.h\"\n+\n+\n+int\n+rte_pmd_ifpga_get_dev_id(const char *pci_addr, uint16_t *dev_id)\n+{\n+\tstruct rte_pci_addr addr;\n+\tstruct rte_rawdev *rdev = NULL;\n+\tchar rdev_name[RTE_RAWDEV_NAME_MAX_LEN] = {0};\n+\n+\tif (!pci_addr || !dev_id) {\n+\t\tIFPGA_RAWDEV_PMD_ERR(\"Input parameter is invalid.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (strnlen(pci_addr, PCI_PRI_STR_SIZE) == PCI_PRI_STR_SIZE) {\n+\t\tIFPGA_RAWDEV_PMD_ERR(\"PCI address is too long.\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (rte_pci_addr_parse(pci_addr, &addr)) {\n+\t\tIFPGA_RAWDEV_PMD_ERR(\"PCI address %s is invalid.\", pci_addr);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tsnprintf(rdev_name, RTE_RAWDEV_NAME_MAX_LEN, \"IFPGA:%02x:%02x.%x\",\n+\t\taddr.bus, addr.devid, addr.function);\n+\trdev = rte_rawdev_pmd_get_named_dev(rdev_name);\n+\tif (!rdev) {\n+\t\tIFPGA_RAWDEV_PMD_DEBUG(\"%s is not probed by ifpga driver.\",\n+\t\t\tpci_addr);\n+\t\treturn -ENODEV;\n+\t}\n+\t*dev_id = rdev->dev_id;\n+\n+\treturn 0;\n+}\n+\n+static struct rte_rawdev *\n+get_rte_rawdev(uint16_t dev_id)\n+{\n+\tstruct rte_rawdev *dev = NULL;\n+\n+\tif (dev_id >= RTE_RAWDEV_MAX_DEVS)\n+\t\treturn NULL;\n+\n+\tdev = &rte_rawdevs[dev_id];\n+\tif (dev->attached == RTE_RAWDEV_ATTACHED)\n+\t\treturn dev;\n+\n+\treturn NULL;\n+}\n+\n+static struct opae_adapter *\n+get_opae_adapter(uint16_t dev_id)\n+{\n+\tstruct rte_rawdev *dev = NULL;\n+\tstruct opae_adapter *adapter = NULL;\n+\n+\tdev = get_rte_rawdev(dev_id);\n+\tif (!dev) {\n+\t\tIFPGA_RAWDEV_PMD_ERR(\"Device ID %u is invalid.\", dev_id);\n+\t\treturn NULL;\n+\t}\n+\n+\tadapter = ifpga_rawdev_get_priv(dev);\n+\tif (!adapter) {\n+\t\tIFPGA_RAWDEV_PMD_ERR(\"Adapter is not registered.\");\n+\t\treturn NULL;\n+\t}\n+\n+\treturn adapter;\n+}\n+\n+static opae_share_data *\n+get_share_data(struct opae_adapter *adapter)\n+{\n+\topae_share_data *sd = NULL;\n+\n+\tif (!adapter)\n+\t\treturn NULL;\n+\n+\tsd = (opae_share_data *)adapter->shm.ptr;\n+\tif (!sd) {\n+\t\tIFPGA_RAWDEV_PMD_ERR(\"Share data is not initialized.\");\n+\t\treturn NULL;\n+\t}\n+\n+\treturn sd;\n+}\n+\n+int\n+rte_pmd_ifpga_update_flash(uint16_t dev_id, const char *image,\n+\tuint64_t *status)\n+{\n+\tstruct opae_adapter *adapter = NULL;\n+\n+\tadapter = get_opae_adapter(dev_id);\n+\tif (!adapter)\n+\t\treturn -ENODEV;\n+\n+\treturn opae_mgr_update_flash(adapter->mgr, image, status);\n+}\n+\n+int\n+rte_pmd_ifpga_stop_update(uint16_t dev_id, int force)\n+{\n+\tstruct opae_adapter *adapter = NULL;\n+\n+\tadapter = get_opae_adapter(dev_id);\n+\tif (!adapter)\n+\t\treturn -ENODEV;\n+\n+\treturn opae_mgr_stop_flash_update(adapter->mgr, force);\n+}\n+\n+int\n+rte_pmd_ifpga_reboot_try(uint16_t dev_id)\n+{\n+\tstruct opae_adapter *adapter = NULL;\n+\topae_share_data *sd = NULL;\n+\n+\tadapter = get_opae_adapter(dev_id);\n+\tif (!adapter)\n+\t\treturn -ENODEV;\n+\n+\tsd = get_share_data(adapter);\n+\tif (!sd)\n+\t\treturn -ENOMEM;\n+\n+\topae_adapter_lock(adapter, -1);\n+\tif (IFPGA_RSU_GET_STAT(sd->rsu_stat) != IFPGA_RSU_IDLE) {\n+\t\topae_adapter_unlock(adapter);\n+\t\tIFPGA_RAWDEV_PMD_WARN(\"Update or reboot is in progress.\");\n+\t\treturn -EBUSY;\n+\t}\n+\tsd->rsu_stat = IFPGA_RSU_STATUS(IFPGA_RSU_REBOOT, 0);\n+\topae_adapter_unlock(adapter);\n+\n+\treturn 0;\n+}\n+\n+int\n+rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page)\n+{\n+\tstruct opae_adapter *adapter = NULL;\n+\n+\tadapter = get_opae_adapter(dev_id);\n+\tif (!adapter)\n+\t\treturn -ENODEV;\n+\n+\treturn opae_mgr_reload(adapter->mgr, type, page);\n+}\ndiff --git a/drivers/raw/ifpga/rte_pmd_ifpga.h b/drivers/raw/ifpga/rte_pmd_ifpga.h\nnew file mode 100644\nindex 0000000000..023a011116\n--- /dev/null\n+++ b/drivers/raw/ifpga/rte_pmd_ifpga.h\n@@ -0,0 +1,132 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 Intel Corporation\n+ */\n+\n+#ifndef _RTE_PMD_IFPGA_H_\n+#define _RTE_PMD_IFPGA_H_\n+\n+/**\n+ * @file rte_pmd_ifpga.h\n+ *\n+ * ifpga PMD specific functions.\n+ *\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ */\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ * Get raw device ID from PCI address string like 'Domain:Bus:Dev.Func'\n+ *\n+ * @param pci_addr\n+ *    The PCI address of specified Intel FPGA device.\n+ * @param dev_id\n+ *    The buffer to output device ID.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-EINVAL) if bad parameter.\n+ *   - (-ENODEV) if FPGA is not probed by ifpga driver.\n+ */\n+__rte_experimental\n+int\n+rte_pmd_ifpga_get_dev_id(const char *pci_addr, uint16_t *dev_id);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ * Update image flash of specified Intel FPGA device\n+ *\n+ * @param dev_id\n+ *   The raw device ID of specified Intel FPGA device.\n+ * @param image\n+ *   The image file name string.\n+ * @param status\n+ *   The detailed update status for debug.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENODEV) if dev_id is invalid.\n+ *   - (-EINVAL) if bad parameter or staging area is not initialized.\n+ *   - (-EBUSY) if FPGA is updating or rebooting.\n+ *   - (-EIO) if failed to open image file.\n+ */\n+__rte_experimental\n+int\n+rte_pmd_ifpga_update_flash(uint16_t dev_id, const char *image,\n+\tuint64_t *status);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ * Stop flash update of specified Intel FPGA device\n+ *\n+ * @param dev_id\n+ *   The raw device ID of specified Intel FPGA device.\n+ * @param force\n+ *   Abort the update process by writing register if set non-zero.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENODEV) if dev_id is invalid.\n+ *   - (-EINVAL) if bad parameter.\n+ *   - (-EAGAIN) if failed with force.\n+ */\n+__rte_experimental\n+int\n+rte_pmd_ifpga_stop_update(uint16_t dev_id, int force);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ * Check current Intel FPGA status and change it to reboot status if it is idle\n+ *\n+ * @param dev_id\n+ *    The raw device ID of specified Intel FPGA device.\n+ * @return\n+ *   - (0) if FPGA is ready to reboot.\n+ *   - (-ENODEV) if dev_id is invalid.\n+ *   - (-ENOMEM) if share data is not initialized.\n+ *   - (-EBUSY) if FPGA is updating or rebooting.\n+ */\n+__rte_experimental\n+int\n+rte_pmd_ifpga_reboot_try(uint16_t dev_id);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ * Trigger full reconfiguration of specified Intel FPGA device\n+ *\n+ * @param dev_id\n+ *    The raw device ID of specified Intel FPGA device.\n+ * @param type\n+ *    Select reconfiguration type.\n+ *    0 - reconfigure FPGA only.\n+ *    1 - reboot the whole card including FPGA.\n+ * @param page\n+ *    Select image from which flash partition.\n+ *    0 - factory partition.\n+ *    1 - user partition.\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-ENODEV) if dev_id is invalid.\n+ *   - (-EINVAL) if bad parameter.\n+ *   - (-EBUSY) if failed to access BMC register.\n+ */\n+__rte_experimental\n+int\n+rte_pmd_ifpga_reload(uint16_t dev_id, int type, int page);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_PMD_IFPGA_H_ */\ndiff --git a/drivers/raw/ifpga/version.map b/drivers/raw/ifpga/version.map\nindex 4a76d1d52d..16584f7fe4 100644\n--- a/drivers/raw/ifpga/version.map\n+++ b/drivers/raw/ifpga/version.map\n@@ -1,3 +1,14 @@\n DPDK_21 {\n \tlocal: *;\n };\n+\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\t# added in 21.05\n+\trte_pmd_ifpga_get_dev_id;\n+\trte_pmd_ifpga_update_flash;\n+\trte_pmd_ifpga_stop_update;\n+\trte_pmd_ifpga_reboot_try;\n+\trte_pmd_ifpga_reload;\n+};\n",
    "prefixes": [
        "v15",
        "1/4"
    ]
}