get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 105245,
    "url": "http://patches.dpdk.org/api/patches/105245/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/96b2447e86b87b04291fed135aa980c30fec369e.1639636621.git.songyl@ramaxel.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<96b2447e86b87b04291fed135aa980c30fec369e.1639636621.git.songyl@ramaxel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/96b2447e86b87b04291fed135aa980c30fec369e.1639636621.git.songyl@ramaxel.com",
    "date": "2021-12-18T02:51:30",
    "name": "[v1,03/25] net/spnic: add mbox message channel",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "a3178f525d407dfb0afb774ba40ab334719445a2",
    "submitter": {
        "id": 2455,
        "url": "http://patches.dpdk.org/api/people/2455/?format=api",
        "name": "Yanling Song",
        "email": "songyl@ramaxel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/96b2447e86b87b04291fed135aa980c30fec369e.1639636621.git.songyl@ramaxel.com/mbox/",
    "series": [
        {
            "id": 20973,
            "url": "http://patches.dpdk.org/api/series/20973/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=20973",
            "date": "2021-12-18T02:51:28",
            "name": "Net/SPNIC: support SPNIC into DPDK 22.03",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/20973/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/105245/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/105245/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 34D75A04A4;\n\tSat, 18 Dec 2021 03:53:02 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 19ECD41177;\n\tSat, 18 Dec 2021 03:52:26 +0100 (CET)",
            "from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186])\n by mails.dpdk.org (Postfix) with ESMTP id C39C741165\n for <dev@dpdk.org>; Sat, 18 Dec 2021 03:52:23 +0100 (CET)",
            "from V12DG1MBS01.ramaxel.local (v12dg1mbs01.ramaxel.local\n [172.26.18.31])\n by VLXDG1SPAM1.ramaxel.com with ESMTPS id 1BI2pxFu010302\n (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);\n Sat, 18 Dec 2021 10:51:59 +0800 (GMT-8)\n (envelope-from songyl@ramaxel.com)",
            "from localhost.localdomain (10.64.9.47) by V12DG1MBS01.ramaxel.local\n (172.26.18.31) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2308.14; Sat, 18\n Dec 2021 10:51:58 +0800"
        ],
        "From": "Yanling Song <songyl@ramaxel.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<songyl@ramaxel.com>, <yanling.song@linux.dev>, <yanggan@ramaxel.com>,\n <ferruh.yigit@intel.com>",
        "Subject": "[PATCH v1 03/25] net/spnic: add mbox message channel",
        "Date": "Sat, 18 Dec 2021 10:51:30 +0800",
        "Message-ID": "\n <96b2447e86b87b04291fed135aa980c30fec369e.1639636621.git.songyl@ramaxel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<cover.1639636621.git.songyl@ramaxel.com>",
        "References": "<cover.1639636621.git.songyl@ramaxel.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.64.9.47]",
        "X-ClientProxiedBy": "V12DG1MBS01.ramaxel.local (172.26.18.31) To\n V12DG1MBS01.ramaxel.local (172.26.18.31)",
        "X-DNSRBL": "",
        "X-MAIL": "VLXDG1SPAM1.ramaxel.com 1BI2pxFu010302",
        "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"
    },
    "content": "This patch adds a message channel named mbox which can send\nmessage form PF/VF driver to hardware or sned message from\nVF to PF.\n\nSigned-off-by: Yanling Song <songyl@ramaxel.com>\n---\n drivers/net/spnic/base/meson.build   |    3 +-\n drivers/net/spnic/base/spnic_hwdev.c |   69 ++\n drivers/net/spnic/base/spnic_hwdev.h |    6 +\n drivers/net/spnic/base/spnic_mbox.c  | 1158 ++++++++++++++++++++++++++\n drivers/net/spnic/base/spnic_mbox.h  |  202 +++++\n drivers/net/spnic/base/spnic_mgmt.h  |   36 +\n 6 files changed, 1473 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/spnic/base/spnic_mbox.c\n create mode 100644 drivers/net/spnic/base/spnic_mbox.h\n create mode 100644 drivers/net/spnic/base/spnic_mgmt.h",
    "diff": "diff --git a/drivers/net/spnic/base/meson.build b/drivers/net/spnic/base/meson.build\nindex edd6e94772..de80eef7c4 100644\n--- a/drivers/net/spnic/base/meson.build\n+++ b/drivers/net/spnic/base/meson.build\n@@ -3,7 +3,8 @@\n \n sources = [\n \t'spnic_hwdev.c',\n-\t'spnic_hwif.c'\n+\t'spnic_hwif.c',\n+\t'spnic_mbox.c'\n ]\n \n extra_flags = []\ndiff --git a/drivers/net/spnic/base/spnic_hwdev.c b/drivers/net/spnic/base/spnic_hwdev.c\nindex de73f244fd..bcecbaa895 100644\n--- a/drivers/net/spnic/base/spnic_hwdev.c\n+++ b/drivers/net/spnic/base/spnic_hwdev.c\n@@ -5,8 +5,66 @@\n #include \"spnic_compat.h\"\n #include \"spnic_csr.h\"\n #include \"spnic_hwif.h\"\n+#include \"spnic_mgmt.h\"\n+#include \"spnic_mbox.h\"\n #include \"spnic_hwdev.h\"\n \n+int vf_handle_pf_comm_mbox(void *handle, __rte_unused void *pri_handle,\n+\t\t\t   __rte_unused u16 cmd, __rte_unused void *buf_in,\n+\t\t\t   __rte_unused u16 in_size, __rte_unused void *buf_out,\n+\t\t\t   __rte_unused u16 *out_size)\n+{\n+\tstruct spnic_hwdev *hwdev = handle;\n+\n+\tif (!hwdev)\n+\t\treturn -EINVAL;\n+\n+\tPMD_DRV_LOG(WARNING, \"Unsupported pf mbox event %d to process\", cmd);\n+\n+\treturn 0;\n+}\n+\n+static int init_mgmt_channel(struct spnic_hwdev *hwdev)\n+{\n+\tint err;\n+\n+\terr = spnic_func_to_func_init(hwdev);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Init mailbox channel failed\");\n+\t\tgoto func_to_func_init_err;\n+\t}\n+\n+\treturn 0;\n+\n+func_to_func_init_err:\n+\n+\treturn err;\n+}\n+\n+static void free_mgmt_channel(struct spnic_hwdev *hwdev)\n+{\n+\tspnic_func_to_func_free(hwdev);\n+}\n+\n+\n+static int spnic_init_comm_ch(struct spnic_hwdev *hwdev)\n+{\n+\tint err;\n+\n+\terr = init_mgmt_channel(hwdev);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Init mgmt channel failed\");\n+\t\treturn err;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void spnic_uninit_comm_ch(struct spnic_hwdev *hwdev)\n+{\n+\tfree_mgmt_channel(hwdev);\n+}\n+\n int spnic_init_hwdev(struct spnic_hwdev *hwdev)\n {\n \tint err;\n@@ -25,8 +83,17 @@ int spnic_init_hwdev(struct spnic_hwdev *hwdev)\n \t\tgoto init_hwif_err;\n \t}\n \n+\terr = spnic_init_comm_ch(hwdev);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Init communication channel failed\");\n+\t\tgoto init_comm_ch_err;\n+\t}\n+\n \treturn 0;\n \n+init_comm_ch_err:\n+\tspnic_free_hwif(hwdev);\n+\n init_hwif_err:\n \trte_free(hwdev->chip_fault_stats);\n \n@@ -35,6 +102,8 @@ int spnic_init_hwdev(struct spnic_hwdev *hwdev)\n \n void spnic_free_hwdev(struct spnic_hwdev *hwdev)\n {\n+\tspnic_uninit_comm_ch(hwdev);\n+\n \tspnic_free_hwif(hwdev);\n \n \trte_free(hwdev->chip_fault_stats);\ndiff --git a/drivers/net/spnic/base/spnic_hwdev.h b/drivers/net/spnic/base/spnic_hwdev.h\nindex a6cb8bc36e..b3a8b32287 100644\n--- a/drivers/net/spnic/base/spnic_hwdev.h\n+++ b/drivers/net/spnic/base/spnic_hwdev.h\n@@ -17,12 +17,18 @@ struct spnic_hwdev {\n \tuint16_t port_id;\n \n \tstruct spnic_hwif *hwif;\n+\tstruct spnic_mbox *func_to_func;\n \tu8 *chip_fault_stats;\n \n \tu16 max_vfs;\n \tu16 link_status;\n };\n \n+int vf_handle_pf_comm_mbox(void *handle, __rte_unused void *pri_handle,\n+\t\t\t   __rte_unused u16 cmd, __rte_unused void *buf_in,\n+\t\t\t   __rte_unused u16 in_size, __rte_unused void *buf_out,\n+\t\t\t   __rte_unused u16 *out_size);\n+\n int spnic_init_hwdev(struct spnic_hwdev *hwdev);\n \n void spnic_free_hwdev(struct spnic_hwdev *hwdev);\ndiff --git a/drivers/net/spnic/base/spnic_mbox.c b/drivers/net/spnic/base/spnic_mbox.c\nnew file mode 100644\nindex 0000000000..d019612cef\n--- /dev/null\n+++ b/drivers/net/spnic/base/spnic_mbox.c\n@@ -0,0 +1,1158 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd\n+ */\n+\n+#include <rte_atomic.h>\n+#include <ethdev_driver.h>\n+#include \"spnic_compat.h\"\n+#include \"spnic_hwdev.h\"\n+#include \"spnic_csr.h\"\n+#include \"spnic_hwif.h\"\n+#include \"spnic_mgmt.h\"\n+#include \"spnic_mbox.h\"\n+\n+#define SPNIC_MBOX_INT_DST_FUNC_SHIFT\t\t\t\t0\n+#define SPNIC_MBOX_INT_DST_AEQN_SHIFT\t\t\t\t10\n+#define SPNIC_MBOX_INT_SRC_RESP_AEQN_SHIFT\t\t\t12\n+#define SPNIC_MBOX_INT_STAT_DMA_SHIFT\t\t\t\t14\n+/* The size of data to be send (unit of 4 bytes) */\n+#define SPNIC_MBOX_INT_TX_SIZE_SHIFT\t\t\t\t20\n+/* SO_RO(strong order, relax order) */\n+#define SPNIC_MBOX_INT_STAT_DMA_SO_RO_SHIFT\t\t\t25\n+#define SPNIC_MBOX_INT_WB_EN_SHIFT\t\t\t\t28\n+\n+#define SPNIC_MBOX_INT_DST_AEQN_MASK\t\t\t\t0x3\n+#define SPNIC_MBOX_INT_SRC_RESP_AEQN_MASK\t\t\t0x3\n+#define SPNIC_MBOX_INT_STAT_DMA_MASK\t\t\t\t0x3F\n+#define SPNIC_MBOX_INT_TX_SIZE_MASK\t\t\t\t0x1F\n+#define SPNIC_MBOX_INT_STAT_DMA_SO_RO_MASK\t\t\t0x3\n+#define SPNIC_MBOX_INT_WB_EN_MASK\t\t\t\t0x1\n+\n+#define SPNIC_MBOX_INT_SET(val, field)\t\\\n+\t\t\t(((val) & SPNIC_MBOX_INT_##field##_MASK) << \\\n+\t\t\tSPNIC_MBOX_INT_##field##_SHIFT)\n+\n+enum spnic_mbox_tx_status {\n+\tTX_NOT_DONE = 1,\n+};\n+\n+#define SPNIC_MBOX_CTRL_TRIGGER_AEQE_SHIFT\t\t\t0\n+/* Specifies the issue request for the message data.\n+ * 0 - Tx request is done;\n+ * 1 - Tx request is in process.\n+ */\n+#define SPNIC_MBOX_CTRL_TX_STATUS_SHIFT\t\t\t\t1\n+#define SPNIC_MBOX_CTRL_DST_FUNC_SHIFT\t\t\t\t16\n+\n+#define SPNIC_MBOX_CTRL_TRIGGER_AEQE_MASK\t\t\t0x1\n+#define SPNIC_MBOX_CTRL_TX_STATUS_MASK\t\t\t\t0x1\n+#define SPNIC_MBOX_CTRL_DST_FUNC_MASK\t\t\t\t0x1FFF\n+\n+#define SPNIC_MBOX_CTRL_SET(val, field)\t\\\n+\t\t\t(((val) & SPNIC_MBOX_CTRL_##field##_MASK) << \\\n+\t\t\tSPNIC_MBOX_CTRL_##field##_SHIFT)\n+\n+#define MBOX_SEGLEN_MASK\t\t\t\\\n+\t\tSPNIC_MSG_HEADER_SET(SPNIC_MSG_HEADER_SEG_LEN_MASK, SEG_LEN)\n+\n+#define MBOX_MSG_POLLING_TIMEOUT\t300000\n+#define SPNIC_MBOX_COMP_TIME\t\t300000U\n+\n+#define MBOX_MAX_BUF_SZ\t\t\t2048UL\n+#define MBOX_HEADER_SZ\t\t\t8\n+#define SPNIC_MBOX_DATA_SIZE\t\t(MBOX_MAX_BUF_SZ - MBOX_HEADER_SZ)\n+\n+#define MBOX_TLP_HEADER_SZ\t\t16\n+\n+/* Mbox size is 64B, 8B for mbox_header, 8B reserved */\n+#define MBOX_SEG_LEN\t\t\t48\n+#define MBOX_SEG_LEN_ALIGN\t\t4\n+#define MBOX_WB_STATUS_LEN\t\t16UL\n+\n+/* Mbox write back status is 16B, only first 4B is used */\n+#define MBOX_WB_STATUS_ERRCODE_MASK\t\t0xFFFF\n+#define MBOX_WB_STATUS_MASK\t\t\t0xFF\n+#define MBOX_WB_ERROR_CODE_MASK\t\t\t0xFF00\n+#define MBOX_WB_STATUS_FINISHED_SUCCESS\t\t0xFF\n+#define MBOX_WB_STATUS_FINISHED_WITH_ERR\t0xFE\n+#define MBOX_WB_STATUS_NOT_FINISHED\t\t0x00\n+\n+#define MBOX_STATUS_FINISHED(wb)\t\\\n+\t(((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED)\n+#define MBOX_STATUS_SUCCESS(wb)\t\t\\\n+\t(((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS)\n+#define MBOX_STATUS_ERRCODE(wb)\t\t\\\n+\t((wb) & MBOX_WB_ERROR_CODE_MASK)\n+\n+#define SEQ_ID_START_VAL\t\t\t0\n+#define SEQ_ID_MAX_VAL\t\t\t\t42\n+\n+#define DST_AEQ_IDX_DEFAULT_VAL\t\t\t0\n+#define SRC_AEQ_IDX_DEFAULT_VAL\t\t\t0\n+#define NO_DMA_ATTRIBUTE_VAL\t\t\t0\n+\n+#define MBOX_MSG_NO_DATA_LEN\t\t\t1\n+\n+#define MBOX_BODY_FROM_HDR(header)\t((u8 *)(header) + MBOX_HEADER_SZ)\n+#define MBOX_AREA(hwif)\t\t\t\\\n+\t((hwif)->cfg_regs_base + SPNIC_FUNC_CSR_MAILBOX_DATA_OFF)\n+\n+#define IS_PF_OR_PPF_SRC(src_func_idx)\t((src_func_idx) < SPNIC_MAX_PF_FUNCS)\n+\n+#define MBOX_RESPONSE_ERROR\t\t0x1\n+#define MBOX_MSG_ID_MASK\t\t0xF\n+#define MBOX_MSG_ID(func_to_func)\t((func_to_func)->send_msg_id)\n+#define MBOX_MSG_ID_INC(func_to_func)\t((MBOX_MSG_ID(func_to_func) + 1) & \\\n+\t\t\t\t\tMBOX_MSG_ID_MASK)\n+\n+/* Max message counter waits to process for one function */\n+#define SPNIC_MAX_MSG_CNT_TO_PROCESS\t10\n+\n+enum mbox_ordering_type {\n+\tSTRONG_ORDER,\n+};\n+\n+enum mbox_write_back_type {\n+\tWRITE_BACK = 1,\n+};\n+\n+enum mbox_aeq_trig_type {\n+\tNOT_TRIGGER,\n+\tTRIGGER,\n+};\n+\n+static int send_mbox_to_func(struct spnic_mbox *func_to_func,\n+\t\t\t     enum spnic_mod_type mod, u16 cmd, void *msg,\n+\t\t\t     u16 msg_len, u16 dst_func,\n+\t\t\t     enum spnic_msg_direction_type direction,\n+\t\t\t     enum spnic_msg_ack_type ack_type,\n+\t\t\t     struct mbox_msg_info *msg_info);\n+static int send_tlp_mbox_to_func(struct spnic_mbox *func_to_func,\n+\t\t\t\t enum spnic_mod_type mod, u16 cmd, void *msg,\n+\t\t\t\t u16 msg_len, u16 dst_func,\n+\t\t\t\t enum spnic_msg_direction_type direction,\n+\t\t\t\t enum spnic_msg_ack_type ack_type,\n+\t\t\t\t struct mbox_msg_info *msg_info);\n+\n+static int recv_vf_mbox_handler(struct spnic_mbox *func_to_func,\n+\t\t\t\tstruct spnic_recv_mbox *recv_mbox,\n+\t\t\t\tvoid *buf_out, u16 *out_size,\n+\t\t\t\t__rte_unused void *param)\n+{\n+\tint err = 0;\n+\n+\tswitch (recv_mbox->mod) {\n+\tcase SPNIC_MOD_COMM:\n+\t\terr = vf_handle_pf_comm_mbox(func_to_func->hwdev, func_to_func,\n+\t\t\t\t\t     recv_mbox->cmd, recv_mbox->mbox,\n+\t\t\t\t\t     recv_mbox->mbox_len,\n+\t\t\t\t\t     buf_out, out_size);\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"No handler, mod: %d\", recv_mbox->mod);\n+\t\terr = SPNIC_MBOX_VF_CMD_ERROR;\n+\t\tbreak;\n+\t}\n+\n+\treturn err;\n+}\n+\n+static void response_for_recv_func_mbox(struct spnic_mbox *func_to_func,\n+\t\t\t\t\tstruct spnic_recv_mbox *recv_mbox,\n+\t\t\t\t\tint err, u16 out_size, u16 src_func_idx)\n+{\n+\tstruct mbox_msg_info msg_info = {0};\n+\n+\tif (recv_mbox->ack_type == SPNIC_MSG_ACK) {\n+\t\tmsg_info.msg_id = recv_mbox->msg_info.msg_id;\n+\t\tif (err)\n+\t\t\tmsg_info.status = SPNIC_MBOX_PF_SEND_ERR;\n+\n+\t\tif (IS_TLP_MBX(src_func_idx))\n+\t\t\tsend_tlp_mbox_to_func(func_to_func, recv_mbox->mod,\n+\t\t\t\t\t      recv_mbox->cmd,\n+\t\t\t\t\t      recv_mbox->buf_out, out_size,\n+\t\t\t\t\t      src_func_idx, SPNIC_MSG_RESPONSE,\n+\t\t\t\t\t      SPNIC_MSG_NO_ACK, &msg_info);\n+\t\telse\n+\t\t\tsend_mbox_to_func(func_to_func, recv_mbox->mod,\n+\t\t\t\t\t  recv_mbox->cmd, recv_mbox->buf_out,\n+\t\t\t\t\t  out_size, src_func_idx,\n+\t\t\t\t\t  SPNIC_MSG_RESPONSE,\n+\t\t\t\t\t  SPNIC_MSG_NO_ACK, &msg_info);\n+\t}\n+}\n+\n+static void recv_func_mbox_handler(struct spnic_mbox *func_to_func,\n+\t\t\t\t   struct spnic_recv_mbox *recv_mbox,\n+\t\t\t\t   u16 src_func_idx, void *param)\n+{\n+\tstruct spnic_hwdev *hwdev = func_to_func->hwdev;\n+\tvoid *buf_out = recv_mbox->buf_out;\n+\tu16 out_size = MBOX_MAX_BUF_SZ;\n+\tint err = 0;\n+\n+\tif (SPNIC_IS_VF(hwdev)) {\n+\t\terr = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out,\n+\t\t\t\t\t   &out_size, param);\n+\t} else {\n+\t\terr = -EINVAL;\n+\t\tPMD_DRV_LOG(ERR, \"PMD doesn't support non-VF handle mailbox message\");\n+\t}\n+\n+\tif (!out_size || err)\n+\t\tout_size = MBOX_MSG_NO_DATA_LEN;\n+\n+\tif (recv_mbox->ack_type == SPNIC_MSG_ACK) {\n+\t\tresponse_for_recv_func_mbox(func_to_func, recv_mbox, err,\n+\t\t\t\t\t    out_size, src_func_idx);\n+\t}\n+}\n+\n+static void resp_mbox_handler(struct spnic_mbox *func_to_func,\n+\t\t\t      struct spnic_recv_mbox *recv_mbox)\n+{\n+\trte_spinlock_lock(&func_to_func->mbox_lock);\n+\tif (recv_mbox->msg_info.msg_id == func_to_func->send_msg_id &&\n+\t    func_to_func->event_flag == EVENT_START)\n+\t\tfunc_to_func->event_flag = EVENT_SUCCESS;\n+\telse\n+\t\tPMD_DRV_LOG(ERR, \"Mbox response timeout, current send msg id(0x%x), \"\n+\t\t\t    \"recv msg id(0x%x), status(0x%x)\",\n+\t\t\t    func_to_func->send_msg_id,\n+\t\t\t    recv_mbox->msg_info.msg_id,\n+\t\t\t    recv_mbox->msg_info.status);\n+\trte_spinlock_unlock(&func_to_func->mbox_lock);\n+}\n+\n+static bool check_mbox_segment(struct spnic_recv_mbox *recv_mbox,\n+\t\t\t       u64 mbox_header)\n+{\n+\tu8 seq_id, seg_len, msg_id, mod;\n+\tu16 src_func_idx, cmd;\n+\n+\tseq_id = SPNIC_MSG_HEADER_GET(mbox_header, SEQID);\n+\tseg_len = SPNIC_MSG_HEADER_GET(mbox_header, SEG_LEN);\n+\tsrc_func_idx = SPNIC_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);\n+\tmsg_id = SPNIC_MSG_HEADER_GET(mbox_header, MSG_ID);\n+\tmod = SPNIC_MSG_HEADER_GET(mbox_header, MODULE);\n+\tcmd = SPNIC_MSG_HEADER_GET(mbox_header, CMD);\n+\n+\tif (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN)\n+\t\tgoto seg_err;\n+\n+\tif (seq_id == 0) {\n+\t\trecv_mbox->seq_id = seq_id;\n+\t\trecv_mbox->msg_info.msg_id = msg_id;\n+\t\trecv_mbox->mod = mod;\n+\t\trecv_mbox->cmd = cmd;\n+\t} else {\n+\t\tif ((seq_id != recv_mbox->seq_id + 1) ||\n+\t\t    msg_id != recv_mbox->msg_info.msg_id ||\n+\t\t    mod != recv_mbox->mod || cmd != recv_mbox->cmd)\n+\t\t\tgoto seg_err;\n+\n+\t\trecv_mbox->seq_id = seq_id;\n+\t}\n+\n+\treturn true;\n+\n+seg_err:\n+\tPMD_DRV_LOG(ERR, \"Mailbox segment check failed, src func id: 0x%x, \"\n+\t\t\"front seg info: seq id: 0x%x, msg id: 0x%x, mod: 0x%x, \"\n+\t\t\"cmd: 0x%x\\n\",\n+\t\tsrc_func_idx, recv_mbox->seq_id, recv_mbox->msg_info.msg_id,\n+\t\trecv_mbox->mod, recv_mbox->cmd);\n+\tPMD_DRV_LOG(ERR, \"Current seg info: seg len: 0x%x, seq id: 0x%x, \"\n+\t\t\"msg id: 0x%x, mod: 0x%x, cmd: 0x%x\\n\",\n+\t\tseg_len, seq_id, msg_id, mod, cmd);\n+\n+\treturn false;\n+}\n+\n+static int recv_mbox_handler(struct spnic_mbox *func_to_func, void *header,\n+\t\t\t     struct spnic_recv_mbox *recv_mbox, void *param)\n+{\n+\tu64 mbox_header = *((u64 *)header);\n+\tvoid *mbox_body = MBOX_BODY_FROM_HDR(header);\n+\tu16 src_func_idx;\n+\tint pos;\n+\tu8 seq_id;\n+\n+\tseq_id = SPNIC_MSG_HEADER_GET(mbox_header, SEQID);\n+\tsrc_func_idx = SPNIC_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);\n+\n+\tif (!check_mbox_segment(recv_mbox, mbox_header)) {\n+\t\trecv_mbox->seq_id = SEQ_ID_MAX_VAL;\n+\t\treturn SPNIC_MSG_HANDLER_RES;\n+\t}\n+\n+\tpos = seq_id * MBOX_SEG_LEN;\n+\tmemcpy((u8 *)recv_mbox->mbox + pos, mbox_body,\n+\t       SPNIC_MSG_HEADER_GET(mbox_header, SEG_LEN));\n+\n+\tif (!SPNIC_MSG_HEADER_GET(mbox_header, LAST))\n+\t\treturn SPNIC_MSG_HANDLER_RES;\n+\n+\trecv_mbox->cmd = SPNIC_MSG_HEADER_GET(mbox_header, CMD);\n+\trecv_mbox->mod = SPNIC_MSG_HEADER_GET(mbox_header, MODULE);\n+\trecv_mbox->mbox_len = SPNIC_MSG_HEADER_GET(mbox_header, MSG_LEN);\n+\trecv_mbox->ack_type = SPNIC_MSG_HEADER_GET(mbox_header, NO_ACK);\n+\trecv_mbox->msg_info.msg_id = SPNIC_MSG_HEADER_GET(mbox_header, MSG_ID);\n+\trecv_mbox->msg_info.status = SPNIC_MSG_HEADER_GET(mbox_header, STATUS);\n+\trecv_mbox->seq_id = SEQ_ID_MAX_VAL;\n+\n+\tif (SPNIC_MSG_HEADER_GET(mbox_header, DIRECTION) ==\n+\t    SPNIC_MSG_RESPONSE) {\n+\t\tresp_mbox_handler(func_to_func, recv_mbox);\n+\t\treturn 0;\n+\t}\n+\n+\trecv_func_mbox_handler(func_to_func, recv_mbox, src_func_idx, param);\n+\n+\treturn SPNIC_MSG_HANDLER_RES;\n+}\n+\n+int spnic_mbox_func_aeqe_handler(void *handle, u8 *header,\n+\t\t\t\t __rte_unused u8 size, void *param)\n+{\n+\tstruct spnic_mbox *func_to_func = NULL;\n+\tstruct spnic_recv_mbox *recv_mbox = NULL;\n+\tu64 mbox_header = *((u64 *)header);\n+\tu64 src, dir;\n+\n+\tfunc_to_func = ((struct spnic_hwdev *)handle)->func_to_func;\n+\n+\tdir = SPNIC_MSG_HEADER_GET(mbox_header, DIRECTION);\n+\tsrc = SPNIC_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);\n+\n+\tif (src >= SPNIC_MAX_FUNCTIONS && src != SPNIC_MGMT_SRC_ID) {\n+\t\tPMD_DRV_LOG(ERR, \"Mailbox source function id: %u is invalid\",\n+\t\t\t    (u32)src);\n+\t\treturn SPNIC_MSG_HANDLER_RES;\n+\t}\n+\n+\tsrc = (src == SPNIC_MGMT_SRC_ID) ? SPNIC_MAX_FUNCTIONS : src;\n+\n+\trecv_mbox = (dir == SPNIC_MSG_DIRECT_SEND) ?\n+\t\t    &func_to_func->mbox_send[src] :\n+\t\t    &func_to_func->mbox_resp[src];\n+\n+\treturn recv_mbox_handler(func_to_func, (u64 *)header, recv_mbox, param);\n+}\n+\n+static void clear_mbox_status(struct spnic_send_mbox *mbox)\n+{\n+\t*mbox->wb_status = 0;\n+\n+\t/* Clear mailbox write back status */\n+\trte_wmb();\n+}\n+\n+static void mbox_copy_header(struct spnic_send_mbox *mbox, u64 *header)\n+{\n+\tu32 *data = (u32 *)header;\n+\tu32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32);\n+\n+\tfor (i = 0; i < idx_max; i++) {\n+\t\trte_write32(cpu_to_be32(*(data + i)),\n+\t\t\t    mbox->data + i * sizeof(u32));\n+\t}\n+}\n+\n+#define MBOX_DMA_MSG_INIT_XOR_VAL\t0x5a5a5a5a\n+static u32 mbox_dma_msg_xor(u32 *data, u16 msg_len)\n+{\n+\tu32 xor = MBOX_DMA_MSG_INIT_XOR_VAL;\n+\tu16 dw_len = msg_len / sizeof(u32);\n+\tu16 i;\n+\n+\tfor (i = 0; i < dw_len; i++)\n+\t\txor ^= data[i];\n+\n+\treturn xor;\n+}\n+\n+static void mbox_copy_send_data_addr(struct spnic_send_mbox *mbox, u16 seg_len)\n+{\n+\tu32 addr_h, addr_l, xor;\n+\n+\txor = mbox_dma_msg_xor(mbox->sbuff_vaddr, seg_len);\n+\taddr_h = upper_32_bits(mbox->sbuff_paddr);\n+\taddr_l = lower_32_bits(mbox->sbuff_paddr);\n+\n+\trte_write32(cpu_to_be32(xor), mbox->data + MBOX_HEADER_SZ);\n+\trte_write32(cpu_to_be32(addr_h),\n+\t\t    mbox->data + MBOX_HEADER_SZ + sizeof(u32));\n+\trte_write32(cpu_to_be32(addr_l),\n+\t\t     mbox->data + MBOX_HEADER_SZ + 2 * sizeof(u32));\n+\trte_write32(cpu_to_be32(seg_len),\n+\t\t     mbox->data + MBOX_HEADER_SZ + 3 * sizeof(u32));\n+\t/* Reserved */\n+\trte_write32(0, mbox->data + MBOX_HEADER_SZ + 4 * sizeof(u32));\n+\trte_write32(0, mbox->data + MBOX_HEADER_SZ + 5 * sizeof(u32));\n+}\n+\n+static void mbox_copy_send_data(struct spnic_send_mbox *mbox, void *seg,\n+\t\t\t\tu16 seg_len)\n+{\n+\tu32 *data = seg;\n+\tu32 data_len, chk_sz = sizeof(u32);\n+\tu32 i, idx_max;\n+\n+\tdata_len = seg_len;\n+\tidx_max = RTE_ALIGN(data_len, chk_sz) / chk_sz;\n+\n+\tfor (i = 0; i < idx_max; i++) {\n+\t\trte_write32(cpu_to_be32(*(data + i)),\n+\t\t\t    mbox->data + MBOX_HEADER_SZ + i * sizeof(u32));\n+\t}\n+}\n+\n+static void write_mbox_msg_attr(struct spnic_mbox *func_to_func,\n+\t\t\t\tu16 dst_func, u16 dst_aeqn, u16 seg_len)\n+{\n+\tu32 mbox_int, mbox_ctrl;\n+\n+\t/* If VF, function ids must self-learning by HW(PPF=1 PF=0) */\n+\tif (SPNIC_IS_VF(func_to_func->hwdev) &&\n+\t    dst_func != SPNIC_MGMT_SRC_ID) {\n+\t\tif (dst_func == SPNIC_HWIF_PPF_IDX(func_to_func->hwdev->hwif))\n+\t\t\tdst_func = 1;\n+\t\telse\n+\t\t\tdst_func = 0;\n+\t}\n+\n+\tmbox_int = SPNIC_MBOX_INT_SET(dst_aeqn, DST_AEQN) |\n+\t\t   SPNIC_MBOX_INT_SET(0, SRC_RESP_AEQN) |\n+\t\t   SPNIC_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) |\n+\t\t   SPNIC_MBOX_INT_SET(RTE_ALIGN(seg_len + MBOX_HEADER_SZ,\n+\t\t\t\t\t\t MBOX_SEG_LEN_ALIGN) >> 2,\n+\t\t\t\t       TX_SIZE) |\n+\t\t   SPNIC_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) |\n+\t\t   SPNIC_MBOX_INT_SET(WRITE_BACK, WB_EN);\n+\n+\tspnic_hwif_write_reg(func_to_func->hwdev->hwif,\n+\t\t\t      SPNIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, mbox_int);\n+\n+\trte_wmb(); /* Writing the mbox intr attributes */\n+\tmbox_ctrl = SPNIC_MBOX_CTRL_SET(TX_NOT_DONE, TX_STATUS);\n+\n+\tmbox_ctrl |= SPNIC_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE);\n+\n+\tmbox_ctrl |= SPNIC_MBOX_CTRL_SET(dst_func, DST_FUNC);\n+\n+\tspnic_hwif_write_reg(func_to_func->hwdev->hwif,\n+\t\t\t      SPNIC_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl);\n+}\n+\n+static void dump_mbox_reg(struct spnic_hwdev *hwdev)\n+{\n+\tu32 val;\n+\n+\tval = spnic_hwif_read_reg(hwdev->hwif,\n+\t\t\t\t  SPNIC_FUNC_CSR_MAILBOX_CONTROL_OFF);\n+\tPMD_DRV_LOG(ERR, \"Mailbox control reg: 0x%x\", val);\n+\tval = spnic_hwif_read_reg(hwdev->hwif,\n+\t\t\t\t  SPNIC_FUNC_CSR_MAILBOX_INT_OFFSET_OFF);\n+\tPMD_DRV_LOG(ERR, \"Mailbox interrupt offset: 0x%x\", val);\n+}\n+\n+static u16 get_mbox_status(struct spnic_send_mbox *mbox)\n+{\n+\t/* Write back is 16B, but only use first 4B */\n+\tu64 wb_val = be64_to_cpu(*mbox->wb_status);\n+\n+\trte_rmb(); /* Verify reading before check */\n+\n+\treturn (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK);\n+}\n+\n+static int send_mbox_seg(struct spnic_mbox *func_to_func, u64 header,\n+\t\t\t u16 dst_func, void *seg, u16 seg_len,\n+\t\t\t __rte_unused void *msg_info)\n+{\n+\tstruct spnic_send_mbox *send_mbox = &func_to_func->send_mbox;\n+\tstruct spnic_hwdev *hwdev = func_to_func->hwdev;\n+\tu8 num_aeqs = hwdev->hwif->attr.num_aeqs;\n+\tu16 dst_aeqn, wb_status = 0, errcode;\n+\tu16 seq_dir = SPNIC_MSG_HEADER_GET(header, DIRECTION);\n+\tu32 cnt = 0;\n+\n+\t/* Mbox to mgmt cpu, hardware doesn't care dst aeq id */\n+\tif (num_aeqs >= 2)\n+\t\tdst_aeqn = (seq_dir == SPNIC_MSG_DIRECT_SEND) ?\n+\t\t\t   SPNIC_ASYNC_MSG_AEQ : SPNIC_MBOX_RSP_MSG_AEQ;\n+\telse\n+\t\tdst_aeqn = 0;\n+\n+\tclear_mbox_status(send_mbox);\n+\n+\tmbox_copy_header(send_mbox, &header);\n+\n+\tmbox_copy_send_data(send_mbox, seg, seg_len);\n+\n+\twrite_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len);\n+\n+\trte_wmb(); /* Writing the mbox msg attributes */\n+\n+\twhile (cnt < MBOX_MSG_POLLING_TIMEOUT) {\n+\t\twb_status = get_mbox_status(send_mbox);\n+\t\tif (MBOX_STATUS_FINISHED(wb_status))\n+\t\t\tbreak;\n+\n+\t\trte_delay_ms(1);\n+\t\tcnt++;\n+\t}\n+\n+\tif (cnt == MBOX_MSG_POLLING_TIMEOUT) {\n+\t\tPMD_DRV_LOG(ERR, \"Send mailbox segment timeout, wb status: 0x%x\",\n+\t\t\t    wb_status);\n+\t\tdump_mbox_reg(hwdev);\n+\t\treturn -ETIMEDOUT;\n+\t}\n+\n+\tif (!MBOX_STATUS_SUCCESS(wb_status)) {\n+\t\tPMD_DRV_LOG(ERR, \"Send mailbox segment to function %d error, wb status: 0x%x\",\n+\t\t\t    dst_func, wb_status);\n+\t\terrcode = MBOX_STATUS_ERRCODE(wb_status);\n+\t\treturn errcode ? errcode : -EFAULT;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int send_tlp_mbox_seg(struct spnic_mbox *func_to_func, u64 header,\n+\t\t\t     u16 dst_func, void *seg, u16 seg_len,\n+\t\t\t     __rte_unused void *msg_info)\n+{\n+\tstruct spnic_send_mbox *send_mbox = &func_to_func->send_mbox;\n+\tstruct spnic_hwdev *hwdev = func_to_func->hwdev;\n+\tu8 num_aeqs = hwdev->hwif->attr.num_aeqs;\n+\tu16 dst_aeqn, wb_status = 0, errcode;\n+\tu16 seq_dir = SPNIC_MSG_HEADER_GET(header, DIRECTION);\n+\tu32 cnt = 0;\n+\n+\t/* Mbox to mgmt cpu, hardware doesn't care dst aeq id */\n+\tif (num_aeqs >= 2)\n+\t\tdst_aeqn = (seq_dir == SPNIC_MSG_DIRECT_SEND) ?\n+\t\t\t    SPNIC_ASYNC_MSG_AEQ : SPNIC_MBOX_RSP_MSG_AEQ;\n+\telse\n+\t\tdst_aeqn = 0;\n+\n+\tclear_mbox_status(send_mbox);\n+\n+\tmbox_copy_header(send_mbox, &header);\n+\n+\t/* Copy data to DMA buffer */\n+\tmemcpy(send_mbox->sbuff_vaddr, seg, seg_len);\n+\n+\t/* Copy data address to mailbox ctrl csr */\n+\tmbox_copy_send_data_addr(send_mbox, seg_len);\n+\n+\t/* Send tlp mailbox, needs to change the txsize to 16 */\n+\twrite_mbox_msg_attr(func_to_func, dst_func, dst_aeqn,\n+\t\t\t    MBOX_TLP_HEADER_SZ);\n+\n+\trte_wmb(); /* Writing the mbox msg attributes */\n+\n+\twhile (cnt < MBOX_MSG_POLLING_TIMEOUT) {\n+\t\twb_status = get_mbox_status(send_mbox);\n+\t\tif (MBOX_STATUS_FINISHED(wb_status))\n+\t\t\tbreak;\n+\n+\t\trte_delay_ms(1);\n+\t\tcnt++;\n+\t}\n+\n+\tif (cnt == MBOX_MSG_POLLING_TIMEOUT) {\n+\t\tPMD_DRV_LOG(ERR, \"Send mailbox segment timeout, wb status: 0x%x\",\n+\t\t\t    wb_status);\n+\t\tdump_mbox_reg(hwdev);\n+\t\treturn -ETIMEDOUT;\n+\t}\n+\n+\tif (!MBOX_STATUS_SUCCESS(wb_status)) {\n+\t\tPMD_DRV_LOG(ERR, \"Send mailbox segment to function %d error, wb status: 0x%x\",\n+\t\t\t    dst_func, wb_status);\n+\t\terrcode = MBOX_STATUS_ERRCODE(wb_status);\n+\t\treturn errcode ? errcode : -EFAULT;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int send_mbox_to_func(struct spnic_mbox *func_to_func,\n+\t\t\t     enum spnic_mod_type mod, u16 cmd, void *msg,\n+\t\t\t     u16 msg_len, u16 dst_func,\n+\t\t\t     enum spnic_msg_direction_type direction,\n+\t\t\t     enum spnic_msg_ack_type ack_type,\n+\t\t\t     struct mbox_msg_info *msg_info)\n+{\n+\tint err = 0;\n+\tu32 seq_id = 0;\n+\tu16 seg_len = MBOX_SEG_LEN;\n+\tu16 rsp_aeq_id, left = msg_len;\n+\tu8 *msg_seg = (u8 *)msg;\n+\tu64 header = 0;\n+\n+\trsp_aeq_id = SPNIC_MBOX_RSP_MSG_AEQ;\n+\n+\terr = spnic_mutex_lock(&func_to_func->msg_send_mutex);\n+\tif (err)\n+\t\treturn err;\n+\n+\theader = SPNIC_MSG_HEADER_SET(msg_len, MSG_LEN) |\n+\t\t SPNIC_MSG_HEADER_SET(mod, MODULE) |\n+\t\t SPNIC_MSG_HEADER_SET(seg_len, SEG_LEN) |\n+\t\t SPNIC_MSG_HEADER_SET(ack_type, NO_ACK) |\n+\t\t SPNIC_MSG_HEADER_SET(SPNIC_DATA_INLINE, DATA_TYPE) |\n+\t\t SPNIC_MSG_HEADER_SET(SEQ_ID_START_VAL, SEQID) |\n+\t\t SPNIC_MSG_HEADER_SET(NOT_LAST_SEGMENT, LAST) |\n+\t\t SPNIC_MSG_HEADER_SET(direction, DIRECTION) |\n+\t\t SPNIC_MSG_HEADER_SET(cmd, CMD) |\n+\t\t /* The VF's offset to it's associated PF */\n+\t\t SPNIC_MSG_HEADER_SET(msg_info->msg_id, MSG_ID) |\n+\t\t SPNIC_MSG_HEADER_SET(rsp_aeq_id, AEQ_ID) |\n+\t\t SPNIC_MSG_HEADER_SET(SPNIC_MSG_FROM_MBOX, SOURCE) |\n+\t\t SPNIC_MSG_HEADER_SET(!!msg_info->status, STATUS);\n+\n+\twhile (!(SPNIC_MSG_HEADER_GET(header, LAST))) {\n+\t\tif (left <= MBOX_SEG_LEN) {\n+\t\t\theader &= ~MBOX_SEGLEN_MASK;\n+\t\t\theader |= SPNIC_MSG_HEADER_SET(left, SEG_LEN);\n+\t\t\theader |= SPNIC_MSG_HEADER_SET(LAST_SEGMENT, LAST);\n+\n+\t\t\tseg_len = left;\n+\t\t}\n+\n+\t\terr = send_mbox_seg(func_to_func, header, dst_func, msg_seg,\n+\t\t\t\t    seg_len, msg_info);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Send mbox seg failed, seq_id: 0x%x\",\n+\t\t\t\t    (u8)SPNIC_MSG_HEADER_GET(header, SEQID));\n+\n+\t\t\tgoto send_err;\n+\t\t}\n+\n+\t\tleft -= MBOX_SEG_LEN;\n+\t\tmsg_seg += MBOX_SEG_LEN;\n+\n+\t\tseq_id++;\n+\t\theader &= ~(SPNIC_MSG_HEADER_SET(SPNIC_MSG_HEADER_SEQID_MASK,\n+\t\t\t\t\t\t  SEQID));\n+\t\theader |= SPNIC_MSG_HEADER_SET(seq_id, SEQID);\n+\t}\n+\n+send_err:\n+\t(void)spnic_mutex_unlock(&func_to_func->msg_send_mutex);\n+\n+\treturn err;\n+}\n+\n+static int send_tlp_mbox_to_func(struct spnic_mbox *func_to_func,\n+\t\t\t\t enum spnic_mod_type mod, u16 cmd, void *msg,\n+\t\t\t\t u16 msg_len, u16 dst_func,\n+\t\t\t\t enum spnic_msg_direction_type direction,\n+\t\t\t\t enum spnic_msg_ack_type ack_type,\n+\t\t\t\t struct mbox_msg_info *msg_info)\n+{\n+\tstruct spnic_hwdev *hwdev = func_to_func->hwdev;\n+\tu8 *msg_seg = (u8 *)msg;\n+\tint err = 0;\n+\tu16 rsp_aeq_id;\n+\tu64 header = 0;\n+\n+\trsp_aeq_id = SPNIC_MBOX_RSP_MSG_AEQ;\n+\n+\terr = spnic_mutex_lock(&func_to_func->msg_send_mutex);\n+\tif (err)\n+\t\treturn err;\n+\n+\theader = SPNIC_MSG_HEADER_SET(MBOX_TLP_HEADER_SZ, MSG_LEN) |\n+\t\t SPNIC_MSG_HEADER_SET(MBOX_TLP_HEADER_SZ, SEG_LEN) |\n+\t\t SPNIC_MSG_HEADER_SET(mod, MODULE) |\n+\t\t SPNIC_MSG_HEADER_SET(LAST_SEGMENT, LAST) |\n+\t\t SPNIC_MSG_HEADER_SET(ack_type, NO_ACK) |\n+\t\t SPNIC_MSG_HEADER_SET(SPNIC_DATA_DMA, DATA_TYPE) |\n+\t\t SPNIC_MSG_HEADER_SET(SEQ_ID_START_VAL, SEQID) |\n+\t\t SPNIC_MSG_HEADER_SET(direction, DIRECTION) |\n+\t\t SPNIC_MSG_HEADER_SET(cmd, CMD) |\n+\t\t SPNIC_MSG_HEADER_SET(msg_info->msg_id, MSG_ID) |\n+\t\t SPNIC_MSG_HEADER_SET(rsp_aeq_id, AEQ_ID) |\n+\t\t SPNIC_MSG_HEADER_SET(SPNIC_MSG_FROM_MBOX, SOURCE) |\n+\t\t SPNIC_MSG_HEADER_SET(!!msg_info->status, STATUS) |\n+\t\t SPNIC_MSG_HEADER_SET(spnic_global_func_id(hwdev),\n+\t\t\t\t       SRC_GLB_FUNC_IDX);\n+\n+\terr = send_tlp_mbox_seg(func_to_func, header, dst_func, msg_seg,\n+\t\t\t\tmsg_len, msg_info);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Send mbox seg failed, seq_id: 0x%x\",\n+\t\t\t    (u8)SPNIC_MSG_HEADER_GET(header, SEQID));\n+\t}\n+\n+\t(void)spnic_mutex_unlock(&func_to_func->msg_send_mutex);\n+\n+\treturn err;\n+}\n+\n+static void set_mbox_to_func_event(struct spnic_mbox *func_to_func,\n+\t\t\t\t   enum mbox_event_state event_flag)\n+{\n+\trte_spinlock_lock(&func_to_func->mbox_lock);\n+\tfunc_to_func->event_flag = event_flag;\n+\trte_spinlock_unlock(&func_to_func->mbox_lock);\n+}\n+\n+static int spnic_mbox_to_func(struct spnic_mbox *func_to_func,\n+\t\t\t      enum spnic_mod_type mod, u16 cmd, u16 dst_func,\n+\t\t\t      void *buf_in, u16 in_size, void *buf_out,\n+\t\t\t      u16 *out_size, u32 timeout)\n+{\n+\t/* Use mbox_resp to hole data which responsed from other function */\n+\tstruct spnic_recv_mbox *mbox_for_resp = NULL;\n+\tstruct mbox_msg_info msg_info = {0};\n+\tu16 mbox_rsp_idx;\n+\tint err;\n+\n+\tmbox_rsp_idx = (dst_func == SPNIC_MGMT_SRC_ID) ?\n+\t\t\tSPNIC_MAX_FUNCTIONS : dst_func;\n+\n+\tmbox_for_resp = &func_to_func->mbox_resp[mbox_rsp_idx];\n+\n+\terr = spnic_mutex_lock(&func_to_func->mbox_send_mutex);\n+\tif (err)\n+\t\treturn err;\n+\n+\tmsg_info.msg_id = MBOX_MSG_ID_INC(func_to_func);\n+\tfunc_to_func->send_msg_id = msg_info.msg_id;\n+\n+\tset_mbox_to_func_event(func_to_func, EVENT_START);\n+\n+\tif (IS_TLP_MBX(dst_func))\n+\t\terr = send_tlp_mbox_to_func(func_to_func, mod, cmd, buf_in,\n+\t\t\t\t\t    in_size, dst_func,\n+\t\t\t\t\t    SPNIC_MSG_DIRECT_SEND,\n+\t\t\t\t\t    SPNIC_MSG_ACK, &msg_info);\n+\telse\n+\t\terr = send_mbox_to_func(func_to_func, mod, cmd, buf_in,\n+\t\t\t\t\tin_size, dst_func,\n+\t\t\t\t\tSPNIC_MSG_DIRECT_SEND,\n+\t\t\t\t\tSPNIC_MSG_ACK, &msg_info);\n+\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Send mailbox failed, msg_id: %d\",\n+\t\t\t    msg_info.msg_id);\n+\t\tset_mbox_to_func_event(func_to_func, EVENT_FAIL);\n+\t\tgoto send_err;\n+\t}\n+\n+\tif (mod != mbox_for_resp->mod || cmd != mbox_for_resp->cmd) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid response mbox message, mod: 0x%x, cmd: 0x%x, expect mod: 0x%x, cmd: 0x%x, timeout0x%x\\n\",\n+\t\t\t    mbox_for_resp->mod, mbox_for_resp->cmd, mod, cmd, timeout);\n+\t\terr = -EFAULT;\n+\t\tgoto send_err;\n+\t}\n+\n+\tif (mbox_for_resp->msg_info.status) {\n+\t\terr = mbox_for_resp->msg_info.status;\n+\t\tgoto send_err;\n+\t}\n+\n+\tif (buf_out && out_size) {\n+\t\tif (*out_size < mbox_for_resp->mbox_len) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Invalid response mbox message length: %d for \"\n+\t\t\t\t    \"mod: %d cmd: %d, should less than: %d\",\n+\t\t\t\t    mbox_for_resp->mbox_len, mod, cmd,\n+\t\t\t\t    *out_size);\n+\t\t\terr = -EFAULT;\n+\t\t\tgoto send_err;\n+\t\t}\n+\n+\t\tif (mbox_for_resp->mbox_len)\n+\t\t\tmemcpy(buf_out, mbox_for_resp->mbox,\n+\t\t\t       mbox_for_resp->mbox_len);\n+\n+\t\t*out_size = mbox_for_resp->mbox_len;\n+\t}\n+\n+send_err:\n+\t(void)spnic_mutex_unlock(&func_to_func->mbox_send_mutex);\n+\n+\treturn err;\n+}\n+\n+static int mbox_func_params_valid(__rte_unused struct spnic_mbox *func_to_func,\n+\t\t\t\t  void *buf_in, u16 in_size)\n+{\n+\tif (!buf_in || !in_size)\n+\t\treturn -EINVAL;\n+\n+\tif (in_size > SPNIC_MBOX_DATA_SIZE) {\n+\t\tPMD_DRV_LOG(ERR, \"Mbox msg len(%d) exceed limit(%u)\",\n+\t\t\t    in_size, (u8)SPNIC_MBOX_DATA_SIZE);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int spnic_mbox_to_func_no_ack(struct spnic_hwdev *hwdev, u16 func_idx,\n+\t\t\t\t     enum spnic_mod_type mod, u16 cmd,\n+\t\t\t\t     void *buf_in, u16 in_size)\n+{\n+\tstruct spnic_mbox *func_to_func = hwdev->func_to_func;\n+\tstruct mbox_msg_info msg_info = {0};\n+\tint err;\n+\n+\terr = mbox_func_params_valid(hwdev->func_to_func, buf_in, in_size);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = spnic_mutex_lock(&func_to_func->mbox_send_mutex);\n+\tif (err)\n+\t\treturn err;\n+\n+\tif (IS_TLP_MBX(func_idx))\n+\t\terr = send_tlp_mbox_to_func(func_to_func, mod, cmd,\n+\t\t\t\t\t    buf_in, in_size, func_idx,\n+\t\t\t\t\t    SPNIC_MSG_DIRECT_SEND,\n+\t\t\t\t\t    SPNIC_MSG_NO_ACK, &msg_info);\n+\telse\n+\t\terr = send_mbox_to_func(func_to_func, mod, cmd,\n+\t\t\t\t\tbuf_in, in_size, func_idx,\n+\t\t\t\t\tSPNIC_MSG_DIRECT_SEND,\n+\t\t\t\t\tSPNIC_MSG_NO_ACK, &msg_info);\n+\tif (err)\n+\t\tPMD_DRV_LOG(ERR, \"Send mailbox no ack failed\");\n+\n+\t(void)spnic_mutex_unlock(&func_to_func->mbox_send_mutex);\n+\n+\treturn err;\n+}\n+\n+int spnic_send_mbox_to_mgmt(struct spnic_hwdev *hwdev, enum spnic_mod_type mod,\n+\t\t\t    u16 cmd, void *buf_in, u16 in_size, void *buf_out,\n+\t\t\t    u16 *out_size, u32 timeout)\n+{\n+\tstruct spnic_mbox *func_to_func = hwdev->func_to_func;\n+\tint err;\n+\n+\terr = mbox_func_params_valid(func_to_func, buf_in, in_size);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn spnic_mbox_to_func(func_to_func, mod, cmd, SPNIC_MGMT_SRC_ID,\n+\t\t\t\t  buf_in, in_size, buf_out, out_size, timeout);\n+}\n+\n+void spnic_response_mbox_to_mgmt(struct spnic_hwdev *hwdev,\n+\t\t\t\t enum spnic_mod_type mod, u16 cmd,\n+\t\t\t\t void *buf_in, u16 in_size, u16 msg_id)\n+{\n+\tstruct mbox_msg_info msg_info;\n+\tu16 dst_func;\n+\n+\tmsg_info.msg_id = (u8)msg_id;\n+\tmsg_info.status = 0;\n+\tdst_func = SPNIC_MGMT_SRC_ID;\n+\n+\tif (IS_TLP_MBX(dst_func))\n+\t\tsend_tlp_mbox_to_func(hwdev->func_to_func, mod, cmd, buf_in,\n+\t\t\t\t      in_size, SPNIC_MGMT_SRC_ID,\n+\t\t\t\t      SPNIC_MSG_RESPONSE, SPNIC_MSG_NO_ACK,\n+\t\t\t\t      &msg_info);\n+\telse\n+\t\tsend_mbox_to_func(hwdev->func_to_func, mod, cmd, buf_in,\n+\t\t\t\t  in_size, SPNIC_MGMT_SRC_ID,\n+\t\t\t\t  SPNIC_MSG_RESPONSE, SPNIC_MSG_NO_ACK,\n+\t\t\t\t  &msg_info);\n+}\n+\n+int spnic_send_mbox_to_mgmt_no_ack(struct spnic_hwdev *hwdev,\n+\t\t\t\t   enum spnic_mod_type mod, u16 cmd,\n+\t\t\t\t   void *buf_in, u16 in_size)\n+{\n+\tstruct spnic_mbox *func_to_func = hwdev->func_to_func;\n+\tint err;\n+\n+\terr = mbox_func_params_valid(func_to_func, buf_in, in_size);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn spnic_mbox_to_func_no_ack(hwdev, SPNIC_MGMT_SRC_ID, mod, cmd,\n+\t\t\t\t\t buf_in, in_size);\n+}\n+\n+int spnic_mbox_to_pf(struct spnic_hwdev *hwdev, enum spnic_mod_type mod,\n+\t\t     u16 cmd, void *buf_in, u16 in_size, void *buf_out,\n+\t\t     u16 *out_size, u32 timeout)\n+{\n+\tint err;\n+\n+\tif (!hwdev)\n+\t\treturn -EINVAL;\n+\n+\terr = mbox_func_params_valid(hwdev->func_to_func, buf_in, in_size);\n+\tif (err)\n+\t\treturn err;\n+\n+\tif (!SPNIC_IS_VF(hwdev)) {\n+\t\tPMD_DRV_LOG(ERR, \"Params error, func_type: %d\",\n+\t\t\t    spnic_func_type(hwdev));\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn spnic_mbox_to_func(hwdev->func_to_func, mod, cmd,\n+\t\t\t\t  spnic_pf_id_of_vf(hwdev), buf_in, in_size,\n+\t\t\t\t  buf_out, out_size, timeout);\n+}\n+\n+int spnic_mbox_to_vf(struct spnic_hwdev *hwdev, enum spnic_mod_type mod,\n+\t\t     u16 vf_id, u16 cmd, void *buf_in, u16 in_size,\n+\t\t     void *buf_out, u16 *out_size, u32 timeout)\n+{\n+\tstruct spnic_mbox *func_to_func = NULL;\n+\tu16 dst_func_idx;\n+\tint err = 0;\n+\n+\tif (!hwdev)\n+\t\treturn -EINVAL;\n+\n+\tfunc_to_func = hwdev->func_to_func;\n+\terr = mbox_func_params_valid(func_to_func, buf_in, in_size);\n+\tif (err)\n+\t\treturn err;\n+\n+\tif (SPNIC_IS_VF(hwdev)) {\n+\t\tPMD_DRV_LOG(ERR, \"Params error, func_type: %d\",\n+\t\t\t    spnic_func_type(hwdev));\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!vf_id) {\n+\t\tPMD_DRV_LOG(ERR, \"VF id: %d error!\", vf_id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/*\n+\t * The sum of vf_offset_to_pf + vf_id is the VF's global function id of\n+\t * VF in this pf\n+\t */\n+\tdst_func_idx = spnic_glb_pf_vf_offset(hwdev) + vf_id;\n+\n+\treturn spnic_mbox_to_func(func_to_func, mod, cmd, dst_func_idx, buf_in,\n+\t\t\t\t  in_size, buf_out, out_size, timeout);\n+}\n+\n+static int init_mbox_info(struct spnic_recv_mbox *mbox_info,\n+\t\t\t  int mbox_max_buf_sz)\n+{\n+\tint err;\n+\n+\tmbox_info->seq_id = SEQ_ID_MAX_VAL;\n+\n+\tmbox_info->mbox = rte_zmalloc(\"mbox\", (size_t)mbox_max_buf_sz, 1);\n+\tif (!mbox_info->mbox)\n+\t\treturn -ENOMEM;\n+\n+\tmbox_info->buf_out = rte_zmalloc(\"mbox_buf_out\",\n+\t\t\t\t\t (size_t)mbox_max_buf_sz, 1);\n+\tif (!mbox_info->buf_out) {\n+\t\terr = -ENOMEM;\n+\t\tgoto alloc_buf_out_err;\n+\t}\n+\n+\treturn 0;\n+\n+alloc_buf_out_err:\n+\trte_free(mbox_info->mbox);\n+\n+\treturn err;\n+}\n+\n+static void clean_mbox_info(struct spnic_recv_mbox *mbox_info)\n+{\n+\trte_free(mbox_info->buf_out);\n+\trte_free(mbox_info->mbox);\n+}\n+\n+static int alloc_mbox_info(struct spnic_recv_mbox *mbox_info,\n+\t\t\t   int mbox_max_buf_sz)\n+{\n+\tu16 func_idx, i;\n+\tint err;\n+\n+\tfor (func_idx = 0; func_idx < SPNIC_MAX_FUNCTIONS + 1; func_idx++) {\n+\t\terr = init_mbox_info(&mbox_info[func_idx], mbox_max_buf_sz);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Init mbox info failed\");\n+\t\t\tgoto init_mbox_info_err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+init_mbox_info_err:\n+\tfor (i = 0; i < func_idx; i++)\n+\t\tclean_mbox_info(&mbox_info[i]);\n+\n+\treturn err;\n+}\n+\n+static void free_mbox_info(struct spnic_recv_mbox *mbox_info)\n+{\n+\tu16 func_idx;\n+\n+\tfor (func_idx = 0; func_idx < SPNIC_MAX_FUNCTIONS + 1; func_idx++)\n+\t\tclean_mbox_info(&mbox_info[func_idx]);\n+}\n+\n+static void prepare_send_mbox(struct spnic_mbox *func_to_func)\n+{\n+\tstruct spnic_send_mbox *send_mbox = &func_to_func->send_mbox;\n+\n+\tsend_mbox->data = MBOX_AREA(func_to_func->hwdev->hwif);\n+}\n+\n+static int alloc_mbox_wb_status(struct spnic_mbox *func_to_func)\n+{\n+\tstruct spnic_send_mbox *send_mbox = &func_to_func->send_mbox;\n+\tstruct spnic_hwdev *hwdev = func_to_func->hwdev;\n+\tu32 addr_h, addr_l;\n+\n+\tsend_mbox->wb_mz = rte_eth_dma_zone_reserve(hwdev->eth_dev, \"wb_mz\", 0,\n+\t\t\t\t\t\t    MBOX_WB_STATUS_LEN,\n+\t\t\t\t\t\t    RTE_CACHE_LINE_SIZE,\n+\t\t\t\t\t\t    SOCKET_ID_ANY);\n+\tif (!send_mbox->wb_mz)\n+\t\treturn -ENOMEM;\n+\n+\tsend_mbox->wb_vaddr = send_mbox->wb_mz->addr;\n+\tsend_mbox->wb_paddr = send_mbox->wb_mz->iova;\n+\tsend_mbox->wb_status = send_mbox->wb_vaddr;\n+\n+\taddr_h = upper_32_bits(send_mbox->wb_paddr);\n+\taddr_l = lower_32_bits(send_mbox->wb_paddr);\n+\n+\tspnic_hwif_write_reg(hwdev->hwif, SPNIC_FUNC_CSR_MAILBOX_RESULT_H_OFF,\n+\t\t\t      addr_h);\n+\tspnic_hwif_write_reg(hwdev->hwif, SPNIC_FUNC_CSR_MAILBOX_RESULT_L_OFF,\n+\t\t\t      addr_l);\n+\n+\treturn 0;\n+}\n+\n+static void free_mbox_wb_status(struct spnic_mbox *func_to_func)\n+{\n+\tstruct spnic_send_mbox *send_mbox = &func_to_func->send_mbox;\n+\tstruct spnic_hwdev *hwdev = func_to_func->hwdev;\n+\n+\tspnic_hwif_write_reg(hwdev->hwif,\n+\t\t\t      SPNIC_FUNC_CSR_MAILBOX_RESULT_H_OFF, 0);\n+\tspnic_hwif_write_reg(hwdev->hwif,\n+\t\t\t      SPNIC_FUNC_CSR_MAILBOX_RESULT_L_OFF, 0);\n+\n+\trte_memzone_free(send_mbox->wb_mz);\n+}\n+\n+static int alloc_mbox_tlp_buffer(struct spnic_mbox *func_to_func)\n+{\n+\tstruct spnic_send_mbox *send_mbox = &func_to_func->send_mbox;\n+\tstruct spnic_hwdev *hwdev = func_to_func->hwdev;\n+\n+\tsend_mbox->sbuff_mz = rte_eth_dma_zone_reserve(hwdev->eth_dev,\n+\t\t\t\t\t\t       \"sbuff_mz\", 0,\n+\t\t\t\t\t\t       MBOX_MAX_BUF_SZ,\n+\t\t\t\t\t\t       MBOX_MAX_BUF_SZ,\n+\t\t\t\t\t\t       SOCKET_ID_ANY);\n+\tif (!send_mbox->sbuff_mz)\n+\t\treturn -ENOMEM;\n+\n+\tsend_mbox->sbuff_vaddr = send_mbox->sbuff_mz->addr;\n+\tsend_mbox->sbuff_paddr = send_mbox->sbuff_mz->iova;\n+\n+\treturn 0;\n+}\n+\n+static void free_mbox_tlp_buffer(struct spnic_mbox *func_to_func)\n+{\n+\tstruct spnic_send_mbox *send_mbox = &func_to_func->send_mbox;\n+\n+\trte_memzone_free(send_mbox->sbuff_mz);\n+}\n+\n+int spnic_func_to_func_init(struct spnic_hwdev *hwdev)\n+{\n+\tstruct spnic_mbox *func_to_func;\n+\tint err;\n+\n+\tfunc_to_func = rte_zmalloc(\"func_to_func\", sizeof(*func_to_func), 1);\n+\tif (!func_to_func)\n+\t\treturn -ENOMEM;\n+\n+\thwdev->func_to_func = func_to_func;\n+\tfunc_to_func->hwdev = hwdev;\n+\t(void)spnic_mutex_init(&func_to_func->mbox_send_mutex, NULL);\n+\t(void)spnic_mutex_init(&func_to_func->msg_send_mutex, NULL);\n+\trte_spinlock_init(&func_to_func->mbox_lock);\n+\n+\terr = alloc_mbox_info(func_to_func->mbox_send, MBOX_MAX_BUF_SZ);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Alloc mem for mbox_active failed\");\n+\t\tgoto alloc_mbox_for_send_err;\n+\t}\n+\n+\terr = alloc_mbox_info(func_to_func->mbox_resp, MBOX_MAX_BUF_SZ);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Alloc mem for mbox_passive failed\");\n+\t\tgoto alloc_mbox_for_resp_err;\n+\t}\n+\n+\terr = alloc_mbox_tlp_buffer(func_to_func);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Alloc mbox send buffer failed\");\n+\t\tgoto alloc_tlp_buffer_err;\n+\t}\n+\n+\terr = alloc_mbox_wb_status(func_to_func);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Alloc mbox write back status failed\");\n+\t\tgoto alloc_wb_status_err;\n+\t}\n+\n+\tprepare_send_mbox(func_to_func);\n+\n+\treturn 0;\n+\n+alloc_wb_status_err:\n+\tfree_mbox_tlp_buffer(func_to_func);\n+\n+alloc_tlp_buffer_err:\n+\tfree_mbox_info(func_to_func->mbox_resp);\n+\n+alloc_mbox_for_resp_err:\n+\tfree_mbox_info(func_to_func->mbox_send);\n+\n+alloc_mbox_for_send_err:\n+\t(void)spnic_mutex_destroy(&func_to_func->msg_send_mutex);\n+\t(void)spnic_mutex_destroy(&func_to_func->mbox_send_mutex);\n+\trte_free(func_to_func);\n+\n+\treturn err;\n+}\n+\n+void spnic_func_to_func_free(struct spnic_hwdev *hwdev)\n+{\n+\tstruct spnic_mbox *func_to_func = hwdev->func_to_func;\n+\n+\tfree_mbox_wb_status(func_to_func);\n+\tfree_mbox_tlp_buffer(func_to_func);\n+\tfree_mbox_info(func_to_func->mbox_resp);\n+\tfree_mbox_info(func_to_func->mbox_send);\n+\t(void)spnic_mutex_destroy(&func_to_func->mbox_send_mutex);\n+\t(void)spnic_mutex_destroy(&func_to_func->msg_send_mutex);\n+\n+\trte_free(func_to_func);\n+}\ndiff --git a/drivers/net/spnic/base/spnic_mbox.h b/drivers/net/spnic/base/spnic_mbox.h\nnew file mode 100644\nindex 0000000000..446471e8f8\n--- /dev/null\n+++ b/drivers/net/spnic/base/spnic_mbox.h\n@@ -0,0 +1,202 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd\n+ */\n+\n+#ifndef _SPNIC_MBOX_H_\n+#define _SPNIC_MBOX_H_\n+\n+#define SPNIC_MBOX_PF_SEND_ERR\t\t0x1\n+#define SPNIC_MBOX_PF_BUSY_ACTIVE_FW\t0x2\n+#define SPNIC_MBOX_VF_CMD_ERROR         0x3\n+\n+#define SPNIC_MGMT_SRC_ID\t\t0x1FFF\n+#define SPNIC_MAX_FUNCTIONS\t\t4096\n+#define SPNIC_MAX_PF_FUNCS\t\t32\n+\n+/* Message header define */\n+#define SPNIC_MSG_HEADER_SRC_GLB_FUNC_IDX_SHIFT                 0\n+#define SPNIC_MSG_HEADER_STATUS_SHIFT\t\t\t\t13\n+#define SPNIC_MSG_HEADER_SOURCE_SHIFT\t\t\t\t15\n+#define SPNIC_MSG_HEADER_AEQ_ID_SHIFT\t\t\t\t16\n+#define SPNIC_MSG_HEADER_MSG_ID_SHIFT\t\t\t\t18\n+#define SPNIC_MSG_HEADER_CMD_SHIFT\t\t\t\t22\n+\n+#define SPNIC_MSG_HEADER_MSG_LEN_SHIFT\t\t\t\t32\n+#define SPNIC_MSG_HEADER_MODULE_SHIFT\t\t\t\t43\n+#define SPNIC_MSG_HEADER_SEG_LEN_SHIFT\t\t\t\t48\n+#define SPNIC_MSG_HEADER_NO_ACK_SHIFT\t\t\t\t54\n+#define SPNIC_MSG_HEADER_DATA_TYPE_SHIFT\t\t\t55\n+#define SPNIC_MSG_HEADER_SEQID_SHIFT\t\t\t\t56\n+#define SPNIC_MSG_HEADER_LAST_SHIFT\t\t\t\t62\n+#define SPNIC_MSG_HEADER_DIRECTION_SHIFT\t\t\t63\n+\n+#define SPNIC_MSG_HEADER_CMD_MASK\t\t\t\t0x3FF\n+#define SPNIC_MSG_HEADER_MSG_ID_MASK\t\t\t\t0xF\n+#define SPNIC_MSG_HEADER_AEQ_ID_MASK\t\t\t\t0x3\n+#define SPNIC_MSG_HEADER_SOURCE_MASK\t\t\t\t0x1\n+#define SPNIC_MSG_HEADER_STATUS_MASK\t\t\t\t0x1\n+#define SPNIC_MSG_HEADER_SRC_GLB_FUNC_IDX_MASK\t\t\t0x1FFF\n+\n+#define SPNIC_MSG_HEADER_MSG_LEN_MASK\t\t\t\t0x7FF\n+#define SPNIC_MSG_HEADER_MODULE_MASK\t\t\t\t0x1F\n+#define SPNIC_MSG_HEADER_SEG_LEN_MASK\t\t\t\t0x3F\n+#define SPNIC_MSG_HEADER_NO_ACK_MASK\t\t\t\t0x1\n+#define SPNIC_MSG_HEADER_DATA_TYPE_MASK                         0x1\n+#define SPNIC_MSG_HEADER_SEQID_MASK\t\t\t\t0x3F\n+#define SPNIC_MSG_HEADER_LAST_MASK\t\t\t\t0x1\n+#define SPNIC_MSG_HEADER_DIRECTION_MASK                         0x1\n+\n+#define SPNIC_MSG_HEADER_GET(val, field)\t\\\n+\t\t\t(((val) >> SPNIC_MSG_HEADER_##field##_SHIFT) & \\\n+\t\t\tSPNIC_MSG_HEADER_##field##_MASK)\n+#define SPNIC_MSG_HEADER_SET(val, field)\t\\\n+\t\t\t((u64)(((u64)(val)) &\t\\\n+\t\t\tSPNIC_MSG_HEADER_##field##_MASK) << \\\n+\t\t\tSPNIC_MSG_HEADER_##field##_SHIFT)\n+\n+#define IS_TLP_MBX(dst_func) ((dst_func) == SPNIC_MGMT_SRC_ID)\n+\n+enum spnic_msg_direction_type {\n+\tSPNIC_MSG_DIRECT_SEND\t= 0,\n+\tSPNIC_MSG_RESPONSE\t= 1\n+};\n+\n+enum spnic_msg_segment_type {\n+\tNOT_LAST_SEGMENT = 0,\n+\tLAST_SEGMENT\t = 1\n+};\n+\n+enum spnic_msg_ack_type {\n+\tSPNIC_MSG_ACK,\n+\tSPNIC_MSG_NO_ACK\n+};\n+\n+enum spnic_data_type {\n+\tSPNIC_DATA_INLINE\t= 0,\n+\tSPNIC_DATA_DMA\t\t= 1\n+};\n+\n+enum spnic_msg_src_type {\n+\tSPNIC_MSG_FROM_MGMT = 0,\n+\tSPNIC_MSG_FROM_MBOX = 1\n+};\n+\n+enum spnic_msg_aeq_type {\n+\tSPNIC_ASYNC_MSG_AEQ = 0,\n+\t/* Indicate dest func or mgmt cpu  which aeq to response mbox message */\n+\tSPNIC_MBOX_RSP_MSG_AEQ\t= 1,\n+\t/* Indicate mgmt cpu  which aeq to response api cmd message */\n+\tSPNIC_MGMT_RSP_MSG_AEQ\t= 2\n+};\n+\n+enum spnic_mbox_seg_errcode {\n+\tMBOX_ERRCODE_NO_ERRORS = 0,\n+\t/* VF sends the mailbox data to the wrong destination functions */\n+\tMBOX_ERRCODE_VF_TO_WRONG_FUNC = 0x100,\n+\t/* PPF sends the mailbox data to the wrong destination functions */\n+\tMBOX_ERRCODE_PPF_TO_WRONG_FUNC = 0x200,\n+\t/* PF sends the mailbox data to the wrong destination functions */\n+\tMBOX_ERRCODE_PF_TO_WRONG_FUNC = 0x300,\n+\t/* The mailbox data size is set to all zero */\n+\tMBOX_ERRCODE_ZERO_DATA_SIZE = 0x400,\n+\t/* The sender function attribute has not been learned by CPI hardware */\n+\tMBOX_ERRCODE_UNKNOWN_SRC_FUNC = 0x500,\n+\t/* The receiver function attr has not been learned by CPI hardware */\n+\tMBOX_ERRCODE_UNKNOWN_DES_FUNC = 0x600\n+};\n+\n+struct mbox_msg_info {\n+\tu8 msg_id;\n+\tu8 status; /* Can only use 3 bit */\n+};\n+\n+struct spnic_recv_mbox {\n+\tvoid *mbox;\n+\tvoid *buf_out;\n+\tu16 cmd;\n+\tu16 mbox_len;\n+\tenum spnic_mod_type mod;\n+\tenum spnic_msg_ack_type ack_type;\n+\tu8 seq_id;\n+\tstruct mbox_msg_info msg_info;\n+};\n+\n+struct spnic_send_mbox {\n+\tu8 *data;\n+\n+\tu64 *wb_status; /* Write back status */\n+\n+\tconst struct rte_memzone *wb_mz;\n+\tvoid *wb_vaddr;\n+\trte_iova_t wb_paddr;\n+\n+\tconst struct rte_memzone *sbuff_mz;\n+\tvoid *sbuff_vaddr;\n+\trte_iova_t sbuff_paddr;\n+};\n+\n+enum mbox_event_state {\n+\tEVENT_START = 0,\n+\tEVENT_FAIL,\n+\tEVENT_SUCCESS,\n+\tEVENT_TIMEOUT,\n+\tEVENT_END\n+};\n+\n+enum spnic_mbox_cb_state {\n+\tSPNIC_VF_MBOX_CB_REG = 0,\n+\tSPNIC_VF_MBOX_CB_RUNNING,\n+\tSPNIC_PF_MBOX_CB_REG,\n+\tSPNIC_PF_MBOX_CB_RUNNING,\n+\tSPNIC_PPF_MBOX_CB_REG,\n+\tSPNIC_PPF_MBOX_CB_RUNNING,\n+\tSPNIC_PPF_TO_PF_MBOX_CB_REG,\n+\tSPNIC_PPF_TO_PF_MBOX_CB_RUNNIG\n+};\n+\n+struct spnic_mbox {\n+\tstruct spnic_hwdev *hwdev;\n+\n+\tpthread_mutex_t mbox_send_mutex;\n+\tpthread_mutex_t msg_send_mutex;\n+\n+\tstruct spnic_send_mbox send_mbox;\n+\n+\t/* Last element for mgmt */\n+\tstruct spnic_recv_mbox\tmbox_resp[SPNIC_MAX_FUNCTIONS + 1];\n+\tstruct spnic_recv_mbox\tmbox_send[SPNIC_MAX_FUNCTIONS + 1];\n+\n+\tu8 send_msg_id;\n+\tenum mbox_event_state event_flag;\n+\t/* Lock for mbox event flag */\n+\trte_spinlock_t mbox_lock;\n+};\n+\n+int spnic_mbox_func_aeqe_handler(void *handle, u8 *header, __rte_unused u8 size,\n+\t\t\t\t void *param);\n+\n+int spnic_func_to_func_init(struct spnic_hwdev *hwdev);\n+\n+void spnic_func_to_func_free(struct spnic_hwdev *hwdev);\n+\n+int spnic_send_mbox_to_mgmt(struct spnic_hwdev *hwdev, enum spnic_mod_type mod,\n+\t\t\t    u16 cmd, void *buf_in, u16 in_size, void *buf_out,\n+\t\t\t    u16 *out_size, u32 timeout);\n+\n+void spnic_response_mbox_to_mgmt(struct spnic_hwdev *hwdev,\n+\t\t\t\t enum spnic_mod_type mod, u16 cmd,\n+\t\t\t\t void *buf_in, u16 in_size, u16 msg_id);\n+\n+int spnic_send_mbox_to_mgmt_no_ack(struct spnic_hwdev *hwdev,\n+\t\t\t\t   enum spnic_mod_type mod, u16 cmd,\n+\t\t\t\t   void *buf_in, u16 in_size);\n+\n+int spnic_mbox_to_pf(struct spnic_hwdev *hwdev, enum spnic_mod_type mod,\n+\t\t     u16 cmd, void *buf_in, u16 in_size, void *buf_out,\n+\t\t     u16 *out_size, u32 timeout);\n+\n+int spnic_mbox_to_vf(struct spnic_hwdev *hwdev, enum spnic_mod_type mod,\n+\t\t     u16 vf_id, u16 cmd, void *buf_in, u16 in_size,\n+\t\t     void *buf_out, u16 *out_size, u32 timeout);\n+\n+#endif /* _SPNIC_MBOX_H_ */\ndiff --git a/drivers/net/spnic/base/spnic_mgmt.h b/drivers/net/spnic/base/spnic_mgmt.h\nnew file mode 100644\nindex 0000000000..37d0410473\n--- /dev/null\n+++ b/drivers/net/spnic/base/spnic_mgmt.h\n@@ -0,0 +1,36 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd\n+ */\n+\n+#ifndef _SPNIC_MGMT_H_\n+#define _SPNIC_MGMT_H_\n+\n+#define SPNIC_MSG_HANDLER_RES\t(-1)\n+\n+/* Cmdq module type */\n+enum spnic_mod_type {\n+\tSPNIC_MOD_COMM = 0, /* HW communication module */\n+\tSPNIC_MOD_L2NIC = 1, /* L2NIC module */\n+\tSPNIC_MOD_ROCE = 2,\n+\tSPNIC_MOD_PLOG = 3,\n+\tSPNIC_MOD_TOE = 4,\n+\tSPNIC_MOD_FLR = 5,\n+\tSPNIC_MOD_FC = 6,\n+\tSPNIC_MOD_CFGM = 7, /* Configuration module */\n+\tSPNIC_MOD_CQM = 8,\n+\tSPNIC_MOD_VSWITCH = 9,\n+\tCOMM_MOD_FC = 10,\n+\tSPNIC_MOD_OVS = 11,\n+\tSPNIC_MOD_DSW = 12,\n+\tSPNIC_MOD_MIGRATE = 13,\n+\tSPNIC_MOD_HILINK = 14,\n+\tSPNIC_MOD_CRYPT = 15, /* Secure crypto module */\n+\tSPNIC_MOD_HW_MAX = 16, /* Hardware max module id */\n+\n+\t/* Software module id, for PF/VF and multi-host */\n+\tSPNIC_MOD_SW_FUNC = 17,\n+\tSPNIC_MOD_IOE = 18,\n+\tSPNIC_MOD_MAX\n+};\n+\n+#endif /* _SPNIC_MGMT_H_ */\n",
    "prefixes": [
        "v1",
        "03/25"
    ]
}