get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 105476,
    "url": "http://patches.dpdk.org/api/patches/105476/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/9bd5f153c85f940edfd21cd1895ca784d0a94389.1640783513.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": "<9bd5f153c85f940edfd21cd1895ca784d0a94389.1640783513.git.songyl@ramaxel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/9bd5f153c85f940edfd21cd1895ca784d0a94389.1640783513.git.songyl@ramaxel.com",
    "date": "2021-12-29T13:37:35",
    "name": "[v5,07/26] net/spnic: add interface handling cmdq message",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "dac07259747748b9a631408ba33efe7cbfbe24ac",
    "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/9bd5f153c85f940edfd21cd1895ca784d0a94389.1640783513.git.songyl@ramaxel.com/mbox/",
    "series": [
        {
            "id": 21038,
            "url": "http://patches.dpdk.org/api/series/21038/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=21038",
            "date": "2021-12-29T13:37:28",
            "name": "Net/SPNIC: support SPNIC into DPDK 22.03",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/21038/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/105476/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/105476/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 13392A034D;\n\tWed, 29 Dec 2021 14:39:04 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 9D59541156;\n\tWed, 29 Dec 2021 14:38:35 +0100 (CET)",
            "from VLXDG1SPAM1.ramaxel.com (email.ramaxel.com [221.4.138.186])\n by mails.dpdk.org (Postfix) with ESMTP id 5FA3941155\n for <dev@dpdk.org>; Wed, 29 Dec 2021 14:38:33 +0100 (CET)",
            "from V12DG1MBS01.ramaxel.local (v12dg1mbs01.ramaxel.local\n [172.26.18.31])\n by VLXDG1SPAM1.ramaxel.com with ESMTPS id 1BTDc0Mg069879\n (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);\n Wed, 29 Dec 2021 21:38:00 +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; Wed, 29\n Dec 2021 21:37:59 +0800"
        ],
        "From": "Yanling Song <songyl@ramaxel.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<songyl@ramaxel.com>, <yanling.song@linux.dev>, <yanggan@ramaxel.com>,\n <xuyun@ramaxel.com>, <ferruh.yigit@intel.com>,\n <stephen@networkplumber.org>, <lihuisong@huawei.com>",
        "Subject": "[PATCH v5 07/26] net/spnic: add interface handling cmdq message",
        "Date": "Wed, 29 Dec 2021 21:37:35 +0800",
        "Message-ID": "\n <9bd5f153c85f940edfd21cd1895ca784d0a94389.1640783513.git.songyl@ramaxel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<cover.1640783513.git.songyl@ramaxel.com>",
        "References": "<cover.1640783513.git.songyl@ramaxel.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.64.9.47]",
        "X-ClientProxiedBy": "V12DG1MBS03.ramaxel.local (172.26.18.33) To\n V12DG1MBS01.ramaxel.local (172.26.18.31)",
        "X-DNSRBL": "",
        "X-MAIL": "VLXDG1SPAM1.ramaxel.com 1BTDc0Mg069879",
        "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 commit adds cmdq_sync_cmd_direct_resp() and\ncmdq_sync_cmd_detail_resp() interfaces by which driver can send\ncmdq message using wqe a data structure describe the buffer.\n\nSigned-off-by: Yanling Song <songyl@ramaxel.com>\n---\n drivers/net/spnic/base/meson.build     |   1 +\n drivers/net/spnic/base/spnic_cmdq.c    | 673 +++++++++++++++++++++++++\n drivers/net/spnic/base/spnic_cmdq.h    |  20 +\n drivers/net/spnic/base/spnic_hw_comm.c |  41 ++\n drivers/net/spnic/base/spnic_hwdev.c   |   8 +-\n drivers/net/spnic/base/spnic_hwdev.h   |  13 +\n drivers/net/spnic/base/spnic_wq.c      | 139 +++++\n drivers/net/spnic/base/spnic_wq.h      |  70 ++-\n 8 files changed, 960 insertions(+), 5 deletions(-)\n create mode 100644 drivers/net/spnic/base/spnic_wq.c",
    "diff": "diff --git a/drivers/net/spnic/base/meson.build b/drivers/net/spnic/base/meson.build\nindex 5e4efac7be..da6d6ee4a2 100644\n--- a/drivers/net/spnic/base/meson.build\n+++ b/drivers/net/spnic/base/meson.build\n@@ -10,6 +10,7 @@ sources = [\n \t'spnic_nic_event.c',\n \t'spnic_cmdq.c',\n \t'spnic_hw_comm.c',\n+\t'spnic_wq.c'\n ]\n \n extra_flags = []\ndiff --git a/drivers/net/spnic/base/spnic_cmdq.c b/drivers/net/spnic/base/spnic_cmdq.c\nindex ccfcf739a0..b8950f91c2 100644\n--- a/drivers/net/spnic/base/spnic_cmdq.c\n+++ b/drivers/net/spnic/base/spnic_cmdq.c\n@@ -12,6 +12,71 @@\n #include \"spnic_mgmt.h\"\n #include \"spnic_cmdq.h\"\n \n+#define CMDQ_CMD_TIMEOUT\t\t\t\t300000 /* Millisecond */\n+\n+#define UPPER_8_BITS(data)\t\t\t\t(((data) >> 8) & 0xFF)\n+#define LOWER_8_BITS(data)\t\t\t\t((data) & 0xFF)\n+\n+#define CMDQ_DB_INFO_HI_PROD_IDX_SHIFT\t\t\t0\n+#define CMDQ_DB_INFO_HI_PROD_IDX_MASK\t\t\t0xFFU\n+\n+#define CMDQ_DB_INFO_SET(val, member)\t\t\t\\\n+\t\t\t((((u32)(val)) & CMDQ_DB_INFO_##member##_MASK) \\\n+\t\t\t<< CMDQ_DB_INFO_##member##_SHIFT)\n+#define CMDQ_DB_INFO_UPPER_32(val) ((u64)(val) << 32)\n+\n+#define CMDQ_DB_HEAD_QUEUE_TYPE_SHIFT\t\t\t23\n+#define CMDQ_DB_HEAD_CMDQ_TYPE_SHIFT\t\t\t24\n+#define CMDQ_DB_HEAD_SRC_TYPE_SHIFT\t\t\t27\n+#define CMDQ_DB_HEAD_QUEUE_TYPE_MASK\t\t\t0x1U\n+#define CMDQ_DB_HEAD_CMDQ_TYPE_MASK\t\t\t0x7U\n+#define CMDQ_DB_HEAD_SRC_TYPE_MASK\t\t\t0x1FU\n+#define CMDQ_DB_HEAD_SET(val, member)\t\t\t\\\n+\t((((u32)(val)) & CMDQ_DB_HEAD_##member##_MASK) << \\\n+\tCMDQ_DB_HEAD_##member##_SHIFT)\n+\n+#define CMDQ_CTRL_PI_SHIFT\t\t\t\t0\n+#define CMDQ_CTRL_CMD_SHIFT\t\t\t\t16\n+#define CMDQ_CTRL_MOD_SHIFT\t\t\t\t24\n+#define CMDQ_CTRL_ACK_TYPE_SHIFT\t\t\t29\n+#define CMDQ_CTRL_HW_BUSY_BIT_SHIFT\t\t\t31\n+\n+#define CMDQ_CTRL_PI_MASK\t\t\t\t0xFFFFU\n+#define CMDQ_CTRL_CMD_MASK\t\t\t\t0xFFU\n+#define CMDQ_CTRL_MOD_MASK\t\t\t\t0x1FU\n+#define CMDQ_CTRL_ACK_TYPE_MASK\t\t\t\t0x3U\n+#define CMDQ_CTRL_HW_BUSY_BIT_MASK\t\t\t0x1U\n+\n+#define CMDQ_CTRL_SET(val, member)\t\t\\\n+\t(((u32)(val) & CMDQ_CTRL_##member##_MASK) << CMDQ_CTRL_##member##_SHIFT)\n+\n+#define CMDQ_CTRL_GET(val, member)\t\t\\\n+\t(((val) >> CMDQ_CTRL_##member##_SHIFT) & CMDQ_CTRL_##member##_MASK)\n+\n+#define CMDQ_WQE_HEADER_BUFDESC_LEN_SHIFT\t\t0\n+#define CMDQ_WQE_HEADER_COMPLETE_FMT_SHIFT\t\t15\n+#define CMDQ_WQE_HEADER_DATA_FMT_SHIFT\t\t\t22\n+#define CMDQ_WQE_HEADER_COMPLETE_REQ_SHIFT\t\t23\n+#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_SHIFT\t\t27\n+#define CMDQ_WQE_HEADER_CTRL_LEN_SHIFT\t\t\t29\n+#define CMDQ_WQE_HEADER_HW_BUSY_BIT_SHIFT\t\t31\n+\n+#define CMDQ_WQE_HEADER_BUFDESC_LEN_MASK\t\t0xFFU\n+#define CMDQ_WQE_HEADER_COMPLETE_FMT_MASK\t\t0x1U\n+#define CMDQ_WQE_HEADER_DATA_FMT_MASK\t\t\t0x1U\n+#define CMDQ_WQE_HEADER_COMPLETE_REQ_MASK\t\t0x1U\n+#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_MASK\t\t0x3U\n+#define CMDQ_WQE_HEADER_CTRL_LEN_MASK\t\t\t0x3U\n+#define CMDQ_WQE_HEADER_HW_BUSY_BIT_MASK\t\t0x1U\n+\n+#define CMDQ_WQE_HEADER_SET(val, member)\t\\\n+\t(((u32)(val) & CMDQ_WQE_HEADER_##member##_MASK) <<\t\\\n+\tCMDQ_WQE_HEADER_##member##_SHIFT)\n+\n+#define CMDQ_WQE_HEADER_GET(val, member)\t\\\n+\t(((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) &\t\\\n+\t\tCMDQ_WQE_HEADER_##member##_MASK)\n+\n #define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT\t\t0\n #define CMDQ_CTXT_EQ_ID_SHIFT\t\t\t\t53\n #define CMDQ_CTXT_CEQ_ARM_SHIFT\t\t\t\t61\n@@ -36,8 +101,523 @@\n #define CMDQ_CTXT_BLOCK_INFO_SET(val, member)\t\t\\\n \t(((u64)(val) & CMDQ_CTXT_##member##_MASK) << CMDQ_CTXT_##member##_SHIFT)\n \n+#define SAVED_DATA_ARM_SHIFT\t\t\t\t31\n+\n+#define SAVED_DATA_ARM_MASK\t\t\t\t0x1U\n+\n+#define SAVED_DATA_SET(val, member)\t\t\\\n+\t(((val) & SAVED_DATA_##member##_MASK) << SAVED_DATA_##member##_SHIFT)\n+\n+#define SAVED_DATA_CLEAR(val, member)\t\t\\\n+\t((val) & (~(SAVED_DATA_##member##_MASK << SAVED_DATA_##member##_SHIFT)))\n+\n+#define WQE_ERRCODE_VAL_SHIFT\t\t\t\t0\n+\n+#define WQE_ERRCODE_VAL_MASK\t\t\t\t0x7FFFFFFF\n+\n+#define WQE_ERRCODE_GET(val, member)\t\t\\\n+\t(((val) >> WQE_ERRCODE_##member##_SHIFT) & WQE_ERRCODE_##member##_MASK)\n+\n+#define WQE_COMPLETED(ctrl_info)\tCMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT)\n+\n+#define WQE_HEADER(wqe)\t\t        ((struct spnic_cmdq_header *)(wqe))\n+\n+#define CMDQ_DB_PI_OFF(pi)\t\t(((u16)LOWER_8_BITS(pi)) << 3)\n+\n+#define CMDQ_DB_ADDR(db_base, pi)\t(((u8 *)(db_base)) + CMDQ_DB_PI_OFF(pi))\n+\n+#define CMDQ_PFN(addr, page_size)\t((addr) >> (ilog2(page_size)))\n+\n+#define FIRST_DATA_TO_WRITE_LAST\tsizeof(u64)\n+\n+#define WQE_LCMD_SIZE\t\t64\n+#define WQE_SCMD_SIZE\t\t64\n+\n+#define COMPLETE_LEN\t\t3\n+\n+#define CMDQ_WQEBB_SIZE\t\t64\n+#define CMDQ_WQEBB_SHIFT\t6\n+\n+#define CMDQ_WQE_SIZE\t\t64\n+\n+#define SPNIC_CMDQ_WQ_BUF_SIZE\t4096\n+\n+#define WQE_NUM_WQEBBS(wqe_size, wq)\t\\\n+\t((u16)(RTE_ALIGN((u32)(wqe_size), (wq)->wqebb_size) / (wq)->wqebb_size))\n+\n+#define cmdq_to_cmdqs(cmdq)\tcontainer_of((cmdq) - (cmdq)->cmdq_type, \\\n+\t\t\t\t\t     struct spnic_cmdqs, cmdq[0])\n+\n #define WAIT_CMDQ_ENABLE_TIMEOUT\t300\n \n+static int spnic_cmdq_poll_msg(struct spnic_cmdq *cmdq, u32 timeout);\n+\n+bool spnic_cmdq_idle(struct spnic_cmdq *cmdq)\n+{\n+\tstruct spnic_wq *wq = cmdq->wq;\n+\n+\treturn (__atomic_load_n(&wq->delta, __ATOMIC_RELAXED) == wq->q_depth ?\n+\t\ttrue : false);\n+}\n+\n+struct spnic_cmd_buf *spnic_alloc_cmd_buf(void *hwdev)\n+{\n+\tstruct spnic_cmdqs *cmdqs = ((struct spnic_hwdev *)hwdev)->cmdqs;\n+\tstruct spnic_cmd_buf *cmd_buf;\n+\n+\tcmd_buf = rte_zmalloc(NULL, sizeof(*cmd_buf), 0);\n+\tif (!cmd_buf) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate cmd buffer failed\");\n+\t\treturn NULL;\n+\t}\n+\n+\tcmd_buf->mbuf = rte_pktmbuf_alloc(cmdqs->cmd_buf_pool);\n+\tif (!cmd_buf->mbuf) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate cmd from the pool failed\");\n+\t\tgoto alloc_pci_buf_err;\n+\t}\n+\n+\tcmd_buf->dma_addr = rte_mbuf_data_iova(cmd_buf->mbuf);\n+\tcmd_buf->buf = rte_pktmbuf_mtod(cmd_buf->mbuf, void *);\n+\n+\treturn cmd_buf;\n+\n+alloc_pci_buf_err:\n+\trte_free(cmd_buf);\n+\treturn NULL;\n+}\n+\n+void spnic_free_cmd_buf(struct spnic_cmd_buf *cmd_buf)\n+{\n+\trte_pktmbuf_free(cmd_buf->mbuf);\n+\n+\trte_free(cmd_buf);\n+}\n+\n+static u32 cmdq_wqe_size(enum cmdq_wqe_type wqe_type)\n+{\n+\tu32 wqe_size = 0;\n+\n+\tswitch (wqe_type) {\n+\tcase WQE_LCMD_TYPE:\n+\t\twqe_size = WQE_LCMD_SIZE;\n+\t\tbreak;\n+\tcase WQE_SCMD_TYPE:\n+\t\twqe_size = WQE_SCMD_SIZE;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn wqe_size;\n+}\n+\n+static int cmdq_get_wqe_size(enum bufdesc_len len)\n+{\n+\tint wqe_size = 0;\n+\n+\tswitch (len) {\n+\tcase BUFDESC_LCMD_LEN:\n+\t\twqe_size = WQE_LCMD_SIZE;\n+\t\tbreak;\n+\tcase BUFDESC_SCMD_LEN:\n+\t\twqe_size = WQE_SCMD_SIZE;\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn wqe_size;\n+}\n+\n+static void cmdq_set_completion(struct spnic_cmdq_completion *complete,\n+\t\t\t\tstruct spnic_cmd_buf *buf_out)\n+{\n+\tstruct spnic_sge_resp *sge_resp = &complete->sge_resp;\n+\n+\tspnic_set_sge(&sge_resp->sge, buf_out->dma_addr,\n+\t\t      SPNIC_CMDQ_BUF_SIZE);\n+}\n+\n+static void cmdq_set_lcmd_bufdesc(struct spnic_cmdq_wqe_lcmd *wqe,\n+\t\t\t\t  struct spnic_cmd_buf *buf_in)\n+{\n+\tspnic_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size);\n+}\n+\n+static void cmdq_set_db(struct spnic_cmdq *cmdq,\n+\t\t\tenum spnic_cmdq_type cmdq_type, u16 prod_idx)\n+{\n+\tu64 db = 0;\n+\n+\t/* Hardware will do endianness converting */\n+\tdb = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX);\n+\tdb = CMDQ_DB_INFO_UPPER_32(db) |\n+\t     CMDQ_DB_HEAD_SET(SPNIC_DB_CMDQ_TYPE, QUEUE_TYPE) |\n+\t     CMDQ_DB_HEAD_SET(cmdq_type, CMDQ_TYPE) |\n+\t     CMDQ_DB_HEAD_SET(SPNIC_DB_SRC_CMDQ_TYPE, SRC_TYPE);\n+\n+\trte_wmb(); /* Write all before the doorbell */\n+\n+\trte_write64(db, CMDQ_DB_ADDR(cmdq->db_base, prod_idx));\n+}\n+\n+static void cmdq_wqe_fill(void *dst, void *src)\n+{\n+\tmemcpy((u8 *)dst + FIRST_DATA_TO_WRITE_LAST,\n+\t       (u8 *)src + FIRST_DATA_TO_WRITE_LAST,\n+\t       CMDQ_WQE_SIZE - FIRST_DATA_TO_WRITE_LAST);\n+\n+\trte_wmb(); /* The first 8 bytes should be written last */\n+\n+\t*(u64 *)dst = *(u64 *)src;\n+}\n+\n+static void cmdq_prepare_wqe_ctrl(struct spnic_cmdq_wqe *wqe, int wrapped,\n+\t\t\t\t  enum spnic_mod_type mod, u8 cmd, u16 prod_idx,\n+\t\t\t\t  enum completion_format complete_format,\n+\t\t\t\t  enum data_format local_data_format,\n+\t\t\t\t  enum bufdesc_len buf_len)\n+{\n+\tstruct spnic_ctrl *ctrl = NULL;\n+\tenum ctrl_sect_len ctrl_len;\n+\tstruct spnic_cmdq_wqe_lcmd *wqe_lcmd = NULL;\n+\tstruct spnic_cmdq_wqe_scmd *wqe_scmd = NULL;\n+\tu32 saved_data = WQE_HEADER(wqe)->saved_data;\n+\n+\tif (local_data_format == DATA_SGE) {\n+\t\twqe_lcmd = &wqe->wqe_lcmd;\n+\n+\t\twqe_lcmd->status.status_info = 0;\n+\t\tctrl = &wqe_lcmd->ctrl;\n+\t\tctrl_len = CTRL_SECT_LEN;\n+\t} else {\n+\t\twqe_scmd = &wqe->inline_wqe.wqe_scmd;\n+\n+\t\twqe_scmd->status.status_info = 0;\n+\t\tctrl = &wqe_scmd->ctrl;\n+\t\tctrl_len = CTRL_DIRECT_SECT_LEN;\n+\t}\n+\n+\tctrl->ctrl_info = CMDQ_CTRL_SET(prod_idx, PI) |\n+\t\t\t  CMDQ_CTRL_SET(cmd, CMD) |\n+\t\t\t  CMDQ_CTRL_SET(mod, MOD) |\n+\t\t\t  CMDQ_CTRL_SET(SPNIC_ACK_TYPE_CMDQ, ACK_TYPE);\n+\n+\tWQE_HEADER(wqe)->header_info =\n+\t\tCMDQ_WQE_HEADER_SET(buf_len, BUFDESC_LEN) |\n+\t\tCMDQ_WQE_HEADER_SET(complete_format, COMPLETE_FMT) |\n+\t\tCMDQ_WQE_HEADER_SET(local_data_format, DATA_FMT) |\n+\t\tCMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ) |\n+\t\tCMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) |\n+\t\tCMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN) |\n+\t\tCMDQ_WQE_HEADER_SET((u32)wrapped, HW_BUSY_BIT);\n+\n+\tsaved_data &= SAVED_DATA_CLEAR(saved_data, ARM);\n+\tif (cmd == CMDQ_SET_ARM_CMD && mod == SPNIC_MOD_COMM)\n+\t\tWQE_HEADER(wqe)->saved_data = saved_data |\n+\t\t\t\t\t      SAVED_DATA_SET(1, ARM);\n+\telse\n+\t\tWQE_HEADER(wqe)->saved_data = saved_data;\n+}\n+\n+static void cmdq_set_lcmd_wqe(struct spnic_cmdq_wqe *wqe,\n+\t\t\t      enum cmdq_cmd_type cmd_type,\n+\t\t\t      struct spnic_cmd_buf *buf_in,\n+\t\t\t      struct spnic_cmd_buf *buf_out, int wrapped,\n+\t\t\t      enum spnic_mod_type mod, u8 cmd, u16 prod_idx)\n+{\n+\tstruct spnic_cmdq_wqe_lcmd *wqe_lcmd = &wqe->wqe_lcmd;\n+\tenum completion_format complete_format = COMPLETE_DIRECT;\n+\n+\tswitch (cmd_type) {\n+\tcase SYNC_CMD_DIRECT_RESP:\n+\t\tcomplete_format = COMPLETE_DIRECT;\n+\t\twqe_lcmd->completion.direct_resp = 0;\n+\t\tbreak;\n+\tcase SYNC_CMD_SGE_RESP:\n+\t\tif (buf_out) {\n+\t\t\tcomplete_format = COMPLETE_SGE;\n+\t\t\tcmdq_set_completion(&wqe_lcmd->completion, buf_out);\n+\t\t}\n+\t\tbreak;\n+\tcase ASYNC_CMD:\n+\t\tcomplete_format = COMPLETE_DIRECT;\n+\t\twqe_lcmd->completion.direct_resp = 0;\n+\t\twqe_lcmd->buf_desc.saved_async_buf = (u64)(buf_in);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\tcmdq_prepare_wqe_ctrl(wqe, wrapped, mod, cmd, prod_idx, complete_format,\n+\t\t\t\t  DATA_SGE, BUFDESC_LCMD_LEN);\n+\n+\tcmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in);\n+}\n+\n+static int cmdq_sync_cmd_direct_resp(struct spnic_cmdq *cmdq,\n+\t\t\t\t     enum spnic_mod_type mod, u8 cmd,\n+\t\t\t\t     struct spnic_cmd_buf *buf_in,\n+\t\t\t\t     u64 *out_param, u32 timeout)\n+{\n+\tstruct spnic_wq *wq = cmdq->wq;\n+\tstruct spnic_cmdq_wqe wqe;\n+\tstruct spnic_cmdq_wqe *curr_wqe = NULL;\n+\tstruct spnic_cmdq_wqe_lcmd *wqe_lcmd = NULL;\n+\tu16 curr_prod_idx, next_prod_idx, num_wqebbs;\n+\tint wrapped;\n+\tu32 timeo, wqe_size;\n+\tint err;\n+\n+\twqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);\n+\tnum_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);\n+\n+\t/* Keep wrapped and doorbell index correct */\n+\trte_spinlock_lock(&cmdq->cmdq_lock);\n+\n+\tcurr_wqe = spnic_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);\n+\tif (!curr_wqe) {\n+\t\terr = -EBUSY;\n+\t\tgoto cmdq_unlock;\n+\t}\n+\n+\tmemset(&wqe, 0, sizeof(wqe));\n+\twrapped = cmdq->wrapped;\n+\n+\tnext_prod_idx = curr_prod_idx + num_wqebbs;\n+\tif (next_prod_idx >= wq->q_depth) {\n+\t\tcmdq->wrapped = !cmdq->wrapped;\n+\t\tnext_prod_idx -= wq->q_depth;\n+\t}\n+\n+\tcmdq_set_lcmd_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, NULL,\n+\t\t\t  wrapped, mod, cmd, curr_prod_idx);\n+\n+\t/* Cmdq wqe is not shadow, therefore wqe will be written to wq */\n+\tcmdq_wqe_fill(curr_wqe, &wqe);\n+\n+\tcmdq->cmd_infos[curr_prod_idx].cmd_type = SPNIC_CMD_TYPE_DIRECT_RESP;\n+\n+\tcmdq_set_db(cmdq, SPNIC_CMDQ_SYNC, next_prod_idx);\n+\n+\ttimeo = msecs_to_jiffies(timeout ? timeout : CMDQ_CMD_TIMEOUT);\n+\terr = spnic_cmdq_poll_msg(cmdq, timeo);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Cmdq poll msg ack failed, prod idx: 0x%x\",\n+\t\t\t    curr_prod_idx);\n+\t\terr = -ETIMEDOUT;\n+\t\tgoto cmdq_unlock;\n+\t}\n+\n+\trte_smp_rmb(); /* Read error code after completion */\n+\n+\tif (out_param) {\n+\t\twqe_lcmd = &curr_wqe->wqe_lcmd;\n+\t\t*out_param = cpu_to_be64(wqe_lcmd->completion.direct_resp);\n+\t}\n+\n+\tif (cmdq->errcode[curr_prod_idx])\n+\t\terr = cmdq->errcode[curr_prod_idx];\n+\n+cmdq_unlock:\n+\trte_spinlock_unlock(&cmdq->cmdq_lock);\n+\n+\treturn err;\n+}\n+\n+static int cmdq_sync_cmd_detail_resp(struct spnic_cmdq *cmdq,\n+\t\t\t\t     enum spnic_mod_type mod, u8 cmd,\n+\t\t\t\t     struct spnic_cmd_buf *buf_in,\n+\t\t\t\t     struct spnic_cmd_buf *buf_out,\n+\t\t\t\t     u32 timeout)\n+{\n+\tstruct spnic_wq *wq = cmdq->wq;\n+\tstruct spnic_cmdq_wqe wqe;\n+\tstruct spnic_cmdq_wqe *curr_wqe = NULL;\n+\tu16 curr_prod_idx, next_prod_idx, num_wqebbs;\n+\tint wrapped;\n+\tu32 timeo, wqe_size;\n+\tint err;\n+\n+\twqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);\n+\tnum_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);\n+\n+\t/* Keep wrapped and doorbell index correct */\n+\trte_spinlock_lock(&cmdq->cmdq_lock);\n+\n+\tcurr_wqe = spnic_get_wqe(cmdq->wq, num_wqebbs, &curr_prod_idx);\n+\tif (!curr_wqe) {\n+\t\terr = -EBUSY;\n+\t\tgoto cmdq_unlock;\n+\t}\n+\n+\tmemset(&wqe, 0, sizeof(wqe));\n+\twrapped = cmdq->wrapped;\n+\n+\tnext_prod_idx = curr_prod_idx + num_wqebbs;\n+\tif (next_prod_idx >= wq->q_depth) {\n+\t\tcmdq->wrapped = !cmdq->wrapped;\n+\t\tnext_prod_idx -= wq->q_depth;\n+\t}\n+\n+\tcmdq_set_lcmd_wqe(&wqe, SYNC_CMD_SGE_RESP, buf_in, buf_out,\n+\t\t\t  wrapped, mod, cmd, curr_prod_idx);\n+\n+\t/* Cmdq wqe is not shadow, therefore wqe will be written to wq */\n+\tcmdq_wqe_fill(curr_wqe, &wqe);\n+\n+\tcmdq->cmd_infos[curr_prod_idx].cmd_type = SPNIC_CMD_TYPE_SGE_RESP;\n+\n+\tcmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx);\n+\n+\ttimeo = msecs_to_jiffies(timeout ? timeout : CMDQ_CMD_TIMEOUT);\n+\terr = spnic_cmdq_poll_msg(cmdq, timeo);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Cmdq poll msg ack failed, prod idx: 0x%x\",\n+\t\t\t    curr_prod_idx);\n+\t\terr = -ETIMEDOUT;\n+\t\tgoto cmdq_unlock;\n+\t}\n+\n+\trte_smp_rmb(); /* Read error code after completion */\n+\n+\tif (cmdq->errcode[curr_prod_idx])\n+\t\terr = cmdq->errcode[curr_prod_idx];\n+\n+cmdq_unlock:\n+\trte_spinlock_unlock(&cmdq->cmdq_lock);\n+\n+\treturn err;\n+}\n+\n+static int cmdq_params_valid(void *hwdev, struct spnic_cmd_buf *buf_in)\n+{\n+\tif (!buf_in || !hwdev) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid CMDQ buffer or hwdev is NULL\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (buf_in->size == 0 || buf_in->size > SPNIC_CMDQ_MAX_DATA_SIZE) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid CMDQ buffer size: 0x%x\",\n+\t\t\t    buf_in->size);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int wait_cmdqs_enable(struct spnic_cmdqs *cmdqs)\n+{\n+\tunsigned long end;\n+\n+\tend = jiffies + msecs_to_jiffies(WAIT_CMDQ_ENABLE_TIMEOUT);\n+\tdo {\n+\t\tif (cmdqs->status & SPNIC_CMDQ_ENABLE)\n+\t\t\treturn 0;\n+\t} while (time_before(jiffies, end));\n+\n+\treturn -EBUSY;\n+}\n+\n+int spnic_cmdq_direct_resp(void *hwdev, enum spnic_mod_type mod, u8 cmd,\n+\t\t\t   struct spnic_cmd_buf *buf_in, u64 *out_param,\n+\t\t\t   u32 timeout)\n+{\n+\tstruct spnic_cmdqs *cmdqs = ((struct spnic_hwdev *)hwdev)->cmdqs;\n+\tint err;\n+\n+\terr = cmdq_params_valid(hwdev, buf_in);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid cmdq parameters\");\n+\t\treturn err;\n+\t}\n+\n+\terr = wait_cmdqs_enable(cmdqs);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Cmdq is disabled\");\n+\t\treturn err;\n+\t}\n+\n+\treturn cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[SPNIC_CMDQ_SYNC],\n+\t\t\t\t\t mod, cmd, buf_in, out_param, timeout);\n+}\n+\n+int spnic_cmdq_detail_resp(void *hwdev, enum spnic_mod_type mod, u8 cmd,\n+\t\t\t   struct spnic_cmd_buf *buf_in,\n+\t\t\t   struct spnic_cmd_buf *buf_out, u32 timeout)\n+{\n+\tstruct spnic_cmdqs *cmdqs = ((struct spnic_hwdev *)hwdev)->cmdqs;\n+\tint err;\n+\n+\terr = cmdq_params_valid(hwdev, buf_in);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid cmdq parameters\");\n+\t\treturn err;\n+\t}\n+\n+\terr = wait_cmdqs_enable(cmdqs);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Cmdq is disabled\");\n+\t\treturn err;\n+\t}\n+\n+\treturn cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[SPNIC_CMDQ_SYNC],\n+\t\t\t\t\t mod, cmd, buf_in, buf_out, timeout);\n+}\n+\n+static void cmdq_update_errcode(struct spnic_cmdq *cmdq, u16 prod_idx,\n+\t\t\t\tint errcode)\n+{\n+\tcmdq->errcode[prod_idx] = errcode;\n+}\n+\n+static void clear_wqe_complete_bit(struct spnic_cmdq *cmdq,\n+\t\t\t\t   struct spnic_cmdq_wqe *wqe)\n+{\n+\tstruct spnic_ctrl *ctrl = NULL;\n+\tu32 header_info = WQE_HEADER(wqe)->header_info;\n+\tint buf_len = CMDQ_WQE_HEADER_GET(header_info, BUFDESC_LEN);\n+\tint wqe_size = cmdq_get_wqe_size(buf_len);\n+\tu16 num_wqebbs;\n+\n+\tif (wqe_size == WQE_LCMD_SIZE)\n+\t\tctrl = &wqe->wqe_lcmd.ctrl;\n+\telse\n+\t\tctrl = &wqe->inline_wqe.wqe_scmd.ctrl;\n+\n+\t/* Clear HW busy bit */\n+\tctrl->ctrl_info = 0;\n+\n+\trte_wmb(); /* Verify wqe is cleared */\n+\n+\tnum_wqebbs = WQE_NUM_WQEBBS(wqe_size, cmdq->wq);\n+\tspnic_put_wqe(cmdq->wq, num_wqebbs);\n+}\n+\n+static void cmdq_init_queue_ctxt(struct spnic_cmdq *cmdq,\n+\t\t\t\t struct spnic_cmdq_ctxt_info *ctxt_info)\n+{\n+\tstruct spnic_wq *wq = cmdq->wq;\n+\tu64 wq_first_page_paddr, pfn;\n+\n+\tu16 start_ci = (u16)(wq->cons_idx);\n+\n+\t/* The data in the HW is in Big Endian Format */\n+\twq_first_page_paddr = wq->queue_buf_paddr;\n+\n+\tpfn = CMDQ_PFN(wq_first_page_paddr, RTE_PGSIZE_4K);\n+\tctxt_info->curr_wqe_page_pfn =\n+\t\tCMDQ_CTXT_PAGE_INFO_SET(1, HW_BUSY_BIT) |\n+\t\tCMDQ_CTXT_PAGE_INFO_SET(0, CEQ_EN)\t|\n+\t\tCMDQ_CTXT_PAGE_INFO_SET(0, CEQ_ARM)\t|\n+\t\tCMDQ_CTXT_PAGE_INFO_SET(SPNIC_CEQ_ID_CMDQ, EQ_ID) |\n+\t\tCMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN);\n+\n+\tctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) |\n+\t\t\t\tCMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN);\n+}\n+\n static int init_cmdq(struct spnic_cmdq *cmdq, struct spnic_hwdev *hwdev,\n \t\t     struct spnic_wq *wq, enum spnic_cmdq_type q_type)\n {\n@@ -125,6 +705,14 @@ static int spnic_set_cmdq_ctxts(struct spnic_hwdev *hwdev)\n \n int spnic_reinit_cmdq_ctxts(struct spnic_hwdev *hwdev)\n {\n+\tstruct spnic_cmdqs *cmdqs = hwdev->cmdqs;\n+\tenum spnic_cmdq_type cmdq_type = SPNIC_CMDQ_SYNC;\n+\n+\tfor (; cmdq_type < SPNIC_MAX_CMDQ_TYPES; cmdq_type++) {\n+\t\tcmdqs->cmdq[cmdq_type].wrapped = 1;\n+\t\tspnic_wq_wqe_pg_clear(cmdqs->cmdq[cmdq_type].wq);\n+\t}\n+\n \treturn spnic_set_cmdq_ctxts(hwdev);\n }\n \n@@ -132,6 +720,7 @@ int spnic_cmdqs_init(struct spnic_hwdev *hwdev)\n {\n \tstruct spnic_cmdqs *cmdqs = NULL;\n \tenum spnic_cmdq_type type, cmdq_type;\n+\tsize_t saved_wqs_size;\n \tchar cmdq_pool_name[RTE_MEMPOOL_NAMESIZE];\n \tint err;\n \n@@ -142,6 +731,14 @@ int spnic_cmdqs_init(struct spnic_hwdev *hwdev)\n \thwdev->cmdqs = cmdqs;\n \tcmdqs->hwdev = hwdev;\n \n+\tsaved_wqs_size = SPNIC_MAX_CMDQ_TYPES * sizeof(struct spnic_wq);\n+\tcmdqs->saved_wqs = rte_zmalloc(NULL, saved_wqs_size, 0);\n+\tif (!cmdqs->saved_wqs) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate saved wqs failed\");\n+\t\terr = -ENOMEM;\n+\t\tgoto alloc_wqs_err;\n+\t}\n+\n \tmemset(cmdq_pool_name, 0, RTE_MEMPOOL_NAMESIZE);\n \tsnprintf(cmdq_pool_name, sizeof(cmdq_pool_name), \"spnic_cmdq_%u\",\n \t\t hwdev->port_id);\n@@ -155,6 +752,14 @@ int spnic_cmdqs_init(struct spnic_hwdev *hwdev)\n \t\tgoto pool_create_err;\n \t}\n \n+\terr = spnic_cmdq_alloc(cmdqs->saved_wqs, hwdev, SPNIC_MAX_CMDQ_TYPES,\n+\t\t\t       SPNIC_CMDQ_WQ_BUF_SIZE, CMDQ_WQEBB_SHIFT,\n+\t\t\t       SPNIC_CMDQ_DEPTH);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate cmdq failed\");\n+\t\tgoto cmdq_alloc_err;\n+\t}\n+\n \tcmdq_type = SPNIC_CMDQ_SYNC;\n \tfor (; cmdq_type < SPNIC_MAX_CMDQ_TYPES; cmdq_type++) {\n \t\terr = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev,\n@@ -163,6 +768,9 @@ int spnic_cmdqs_init(struct spnic_hwdev *hwdev)\n \t\t\tPMD_DRV_LOG(ERR, \"Initialize cmdq failed\");\n \t\t\tgoto init_cmdq_err;\n \t\t}\n+\n+\t\tcmdq_init_queue_ctxt(&cmdqs->cmdq[cmdq_type],\n+\t\t\t\t&cmdqs->cmdq[cmdq_type].cmdq_ctxt);\n \t}\n \n \terr = spnic_set_cmdq_ctxts(hwdev);\n@@ -176,9 +784,15 @@ int spnic_cmdqs_init(struct spnic_hwdev *hwdev)\n \tfor (; type < cmdq_type; type++)\n \t\tfree_cmdq(hwdev, &cmdqs->cmdq[type]);\n \n+\tspnic_cmdq_free(cmdqs->saved_wqs, SPNIC_MAX_CMDQ_TYPES);\n+\n+cmdq_alloc_err:\n \trte_mempool_free(cmdqs->cmd_buf_pool);\n \n pool_create_err:\n+\trte_free(cmdqs->saved_wqs);\n+\n+alloc_wqs_err:\n \trte_free(cmdqs);\n \n \treturn err;\n@@ -194,9 +808,68 @@ void spnic_cmdqs_free(struct spnic_hwdev *hwdev)\n \tfor (; cmdq_type < SPNIC_MAX_CMDQ_TYPES; cmdq_type++)\n \t\tfree_cmdq(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type]);\n \n+\tspnic_cmdq_free(cmdqs->saved_wqs, SPNIC_MAX_CMDQ_TYPES);\n+\n \trte_mempool_free(cmdqs->cmd_buf_pool);\n \n \trte_free(cmdqs->saved_wqs);\n \n \trte_free(cmdqs);\n }\n+\n+static int spnic_cmdq_poll_msg(struct spnic_cmdq *cmdq, u32 timeout)\n+{\n+\tstruct spnic_cmdq_wqe *wqe = NULL;\n+\tstruct spnic_cmdq_wqe_lcmd *wqe_lcmd = NULL;\n+\tstruct spnic_ctrl *ctrl = NULL;\n+\tstruct spnic_cmdq_cmd_info *cmd_info = NULL;\n+\tu32 status_info, ctrl_info;\n+\tu16 ci;\n+\tint errcode;\n+\tunsigned long end;\n+\tint done = 0;\n+\tint err = 0;\n+\n+\twqe = spnic_read_wqe(cmdq->wq, 1, &ci);\n+\tif (!wqe) {\n+\t\tPMD_DRV_LOG(ERR, \"No outstanding cmdq msg\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tcmd_info = &cmdq->cmd_infos[ci];\n+\tif (cmd_info->cmd_type == SPNIC_CMD_TYPE_NONE) {\n+\t\tPMD_DRV_LOG(ERR, \"Cmdq msg has not been filled and send to hw, \"\n+\t\t\t    \"or get TMO msg ack. cmdq ci: %u\", ci);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Only arm bit is using scmd wqe, the wqe is lcmd */\n+\twqe_lcmd = &wqe->wqe_lcmd;\n+\tctrl = &wqe_lcmd->ctrl;\n+\tend = jiffies + msecs_to_jiffies(timeout);\n+\tdo {\n+\t\tctrl_info = ctrl->ctrl_info;\n+\t\tif (WQE_COMPLETED(ctrl_info)) {\n+\t\t\tdone = 1;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\trte_delay_ms(1);\n+\t} while (time_before(jiffies, end));\n+\n+\tif (done) {\n+\t\tstatus_info = wqe_lcmd->status.status_info;\n+\t\terrcode = WQE_ERRCODE_GET(status_info, VAL);\n+\t\tcmdq_update_errcode(cmdq, ci, errcode);\n+\t\tclear_wqe_complete_bit(cmdq, wqe);\n+\t\terr = 0;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"Poll cmdq msg time out, ci: %u\", ci);\n+\t\terr = -ETIMEDOUT;\n+\t}\n+\n+\t/* Set this cmd invalid */\n+\tcmd_info->cmd_type = SPNIC_CMD_TYPE_NONE;\n+\n+\treturn err;\n+}\ndiff --git a/drivers/net/spnic/base/spnic_cmdq.h b/drivers/net/spnic/base/spnic_cmdq.h\nindex 49fc1b1684..9a08262860 100644\n--- a/drivers/net/spnic/base/spnic_cmdq.h\n+++ b/drivers/net/spnic/base/spnic_cmdq.h\n@@ -93,6 +93,7 @@ struct spnic_scmd_bufdesc {\n };\n \n struct spnic_lcmd_bufdesc {\n+\tstruct spnic_sge sge;\n \tu32 rsvd1;\n \tu64 saved_async_buf;\n \tu64 rsvd3;\n@@ -112,6 +113,7 @@ struct spnic_ctrl {\n };\n \n struct spnic_sge_resp {\n+\tstruct spnic_sge sge;\n \tu32 rsvd;\n };\n \n@@ -221,6 +223,24 @@ struct spnic_cmd_buf {\n \n int spnic_reinit_cmdq_ctxts(struct spnic_hwdev *hwdev);\n \n+bool spnic_cmdq_idle(struct spnic_cmdq *cmdq);\n+\n+struct spnic_cmd_buf *spnic_alloc_cmd_buf(void *hwdev);\n+\n+void spnic_free_cmd_buf(struct spnic_cmd_buf *cmd_buf);\n+\n+/*\n+ * PF/VF sends cmd to ucode by cmdq, and return 0 if success.\n+ * timeout=0, use default timeout.\n+ */\n+int spnic_cmdq_direct_resp(void *hwdev, enum spnic_mod_type mod, u8 cmd,\n+\t\t\t   struct spnic_cmd_buf *buf_in, u64 *out_param,\n+\t\t\t   u32 timeout);\n+\n+int spnic_cmdq_detail_resp(void *hwdev, enum spnic_mod_type mod, u8 cmd,\n+\t\t\t   struct spnic_cmd_buf *buf_in,\n+\t\t\t   struct spnic_cmd_buf *buf_out, u32 timeout);\n+\n int spnic_cmdqs_init(struct spnic_hwdev *hwdev);\n \n void spnic_cmdqs_free(struct spnic_hwdev *hwdev);\ndiff --git a/drivers/net/spnic/base/spnic_hw_comm.c b/drivers/net/spnic/base/spnic_hw_comm.c\nindex 7c58989c14..48730ce7fe 100644\n--- a/drivers/net/spnic/base/spnic_hw_comm.c\n+++ b/drivers/net/spnic/base/spnic_hw_comm.c\n@@ -11,6 +11,7 @@\n #include \"spnic_csr.h\"\n #include \"spnic_hwdev.h\"\n #include \"spnic_hwif.h\"\n+#include \"spnic_wq.h\"\n #include \"spnic_mgmt.h\"\n #include \"spnic_cmdq.h\"\n #include \"spnic_hw_comm.h\"\n@@ -28,6 +29,46 @@\n #define\tSPNIC_MSIX_CNT_PENDING_MASK\t\t\t0x1FU\n #define\tSPNIC_MSIX_CNT_RESEND_TIMER_MASK\t\t0x7U\n \n+#define DEFAULT_RX_BUF_SIZE\t((u16)0xB)\n+\n+enum spnic_rx_buf_size {\n+\tSPNIC_RX_BUF_SIZE_32B = 0x20,\n+\tSPNIC_RX_BUF_SIZE_64B = 0x40,\n+\tSPNIC_RX_BUF_SIZE_96B = 0x60,\n+\tSPNIC_RX_BUF_SIZE_128B = 0x80,\n+\tSPNIC_RX_BUF_SIZE_192B = 0xC0,\n+\tSPNIC_RX_BUF_SIZE_256B = 0x100,\n+\tSPNIC_RX_BUF_SIZE_384B = 0x180,\n+\tSPNIC_RX_BUF_SIZE_512B = 0x200,\n+\tSPNIC_RX_BUF_SIZE_768B = 0x300,\n+\tSPNIC_RX_BUF_SIZE_1K = 0x400,\n+\tSPNIC_RX_BUF_SIZE_1_5K = 0x600,\n+\tSPNIC_RX_BUF_SIZE_2K = 0x800,\n+\tSPNIC_RX_BUF_SIZE_3K = 0xC00,\n+\tSPNIC_RX_BUF_SIZE_4K = 0x1000,\n+\tSPNIC_RX_BUF_SIZE_8K = 0x2000,\n+\tSPNIC_RX_BUF_SIZE_16K = 0x4000,\n+};\n+\n+const u32 spnic_hw_rx_buf_size[] = {\n+\tSPNIC_RX_BUF_SIZE_32B,\n+\tSPNIC_RX_BUF_SIZE_64B,\n+\tSPNIC_RX_BUF_SIZE_96B,\n+\tSPNIC_RX_BUF_SIZE_128B,\n+\tSPNIC_RX_BUF_SIZE_192B,\n+\tSPNIC_RX_BUF_SIZE_256B,\n+\tSPNIC_RX_BUF_SIZE_384B,\n+\tSPNIC_RX_BUF_SIZE_512B,\n+\tSPNIC_RX_BUF_SIZE_768B,\n+\tSPNIC_RX_BUF_SIZE_1K,\n+\tSPNIC_RX_BUF_SIZE_1_5K,\n+\tSPNIC_RX_BUF_SIZE_2K,\n+\tSPNIC_RX_BUF_SIZE_3K,\n+\tSPNIC_RX_BUF_SIZE_4K,\n+\tSPNIC_RX_BUF_SIZE_8K,\n+\tSPNIC_RX_BUF_SIZE_16K,\n+};\n+\n int spnic_get_interrupt_cfg(void *dev, struct interrupt_info *info)\n {\n \tstruct spnic_hwdev *hwdev = dev;\ndiff --git a/drivers/net/spnic/base/spnic_hwdev.c b/drivers/net/spnic/base/spnic_hwdev.c\nindex 241f9d4e0b..7e348c3139 100644\n--- a/drivers/net/spnic/base/spnic_hwdev.c\n+++ b/drivers/net/spnic/base/spnic_hwdev.c\n@@ -9,6 +9,7 @@\n #include \"spnic_mgmt.h\"\n #include \"spnic_cmd.h\"\n #include \"spnic_mbox.h\"\n+#include \"spnic_wq.h\"\n #include \"spnic_cmdq.h\"\n #include \"spnic_hwdev.h\"\n #include \"spnic_hw_comm.h\"\n@@ -322,9 +323,6 @@ static void free_mgmt_channel(struct spnic_hwdev *hwdev)\n \tspnic_aeqs_free(hwdev);\n }\n \n-#define SPNIC_DEFAULT_WQ_PAGE_SIZE\t0x100000\n-#define SPNIC_HW_WQ_PAGE_SIZE\t\t0x1000\n-\n static int init_cmdqs_channel(struct spnic_hwdev *hwdev)\n {\n \tint err;\n@@ -394,6 +392,10 @@ static int spnic_init_comm_ch(struct spnic_hwdev *hwdev)\n static void spnic_uninit_comm_ch(struct spnic_hwdev *hwdev)\n {\n \tspnic_comm_cmdqs_free(hwdev);\n+\n+\tif (SPNIC_FUNC_TYPE(hwdev) != TYPE_VF)\n+\t\tspnic_set_wq_page_size(hwdev, spnic_global_func_id(hwdev),\n+\t\t\t\t\tSPNIC_HW_WQ_PAGE_SIZE);\n \tfree_mgmt_channel(hwdev);\n }\n \ndiff --git a/drivers/net/spnic/base/spnic_hwdev.h b/drivers/net/spnic/base/spnic_hwdev.h\nindex 48dba0934a..2f25c0d0d3 100644\n--- a/drivers/net/spnic/base/spnic_hwdev.h\n+++ b/drivers/net/spnic/base/spnic_hwdev.h\n@@ -13,6 +13,19 @@ struct spnic_aeqs;\n struct spnic_mbox;\n struct spnic_msg_pf_to_mgmt;\n \n+#define MGMT_VERSION_MAX_LEN\t\t32\n+\n+enum spnic_set_arm_type {\n+\tSPNIC_SET_ARM_CMDQ,\n+\tSPNIC_SET_ARM_SQ,\n+\tSPNIC_SET_ARM_TYPE_NUM\n+};\n+\n+struct spnic_page_addr {\n+\tvoid *virt_addr;\n+\tu64 phys_addr;\n+};\n+\n struct ffm_intr_info {\n \tu8 node_id;\n \t/* Error level of the interrupt source */\ndiff --git a/drivers/net/spnic/base/spnic_wq.c b/drivers/net/spnic/base/spnic_wq.c\nnew file mode 100644\nindex 0000000000..fced7eb0ab\n--- /dev/null\n+++ b/drivers/net/spnic/base/spnic_wq.c\n@@ -0,0 +1,139 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd\n+ */\n+\n+#include <rte_pci.h>\n+#include <rte_bus_pci.h>\n+#include <ethdev_pci.h>\n+#include <rte_mbuf.h>\n+#include <rte_malloc.h>\n+#include <rte_memcpy.h>\n+#include <rte_mempool.h>\n+#include <rte_errno.h>\n+#include <rte_ether.h>\n+\n+#include \"spnic_compat.h\"\n+#include \"spnic_hwdev.h\"\n+#include \"spnic_wq.h\"\n+\n+static void free_wq_pages(struct spnic_wq *wq)\n+{\n+\trte_memzone_free(wq->wq_mz);\n+\n+\twq->queue_buf_paddr = 0;\n+\twq->queue_buf_vaddr = 0;\n+}\n+\n+static int alloc_wq_pages(struct spnic_hwdev *hwdev, struct spnic_wq *wq,\n+\t\t\t  int qid)\n+{\n+\tconst struct rte_memzone *wq_mz;\n+\n+\twq_mz = rte_eth_dma_zone_reserve(hwdev->eth_dev, \"spnic_wq_mz\",\n+\t\t\t\t\t (uint16_t)qid, wq->wq_buf_size,\n+\t\t\t\t\t RTE_PGSIZE_256K, SOCKET_ID_ANY);\n+\tif (!wq_mz) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate wq[%d] rq_mz failed\", qid);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tmemset(wq_mz->addr, 0, wq->wq_buf_size);\n+\twq->wq_mz = wq_mz;\n+\twq->queue_buf_paddr = wq_mz->iova;\n+\twq->queue_buf_vaddr = (u64)(u64 *)wq_mz->addr;\n+\n+\treturn 0;\n+}\n+\n+void spnic_put_wqe(struct spnic_wq *wq, int num_wqebbs)\n+{\n+\twq->cons_idx += num_wqebbs;\n+\t__atomic_add_fetch(&wq->delta, num_wqebbs, __ATOMIC_RELAXED);\n+}\n+\n+void *spnic_read_wqe(struct spnic_wq *wq, int num_wqebbs, u16 *cons_idx)\n+{\n+\tu16 curr_cons_idx;\n+\n+\tif ((__atomic_load_n(&wq->delta, __ATOMIC_RELAXED) + num_wqebbs) > wq->q_depth)\n+\t\treturn NULL;\n+\n+\tcurr_cons_idx = (u16)(wq->cons_idx);\n+\n+\tcurr_cons_idx = MASKED_WQE_IDX(wq, curr_cons_idx);\n+\n+\t*cons_idx = curr_cons_idx;\n+\n+\treturn WQ_WQE_ADDR(wq, (u32)(*cons_idx));\n+}\n+\n+int spnic_cmdq_alloc(struct spnic_wq *wq, void *dev, int cmdq_blocks,\n+\t\t     u32 wq_buf_size, u32 wqebb_shift, u16 q_depth)\n+{\n+\tstruct spnic_hwdev *hwdev = (struct spnic_hwdev *)dev;\n+\tint i, j;\n+\tint err;\n+\n+\t/* Validate q_depth is power of 2 & wqebb_size is not 0 */\n+\tfor (i = 0; i < cmdq_blocks; i++) {\n+\t\twq[i].wqebb_size = 1 << wqebb_shift;\n+\t\twq[i].wqebb_shift = wqebb_shift;\n+\t\twq[i].wq_buf_size = wq_buf_size;\n+\t\twq[i].q_depth = q_depth;\n+\n+\t\terr = alloc_wq_pages(hwdev, &wq[i], i);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Failed to alloc CMDQ blocks\");\n+\t\t\tgoto cmdq_block_err;\n+\t\t}\n+\n+\t\twq[i].cons_idx = 0;\n+\t\twq[i].prod_idx = 0;\n+\t\t__atomic_store_n(&wq[i].delta, q_depth, __ATOMIC_RELAXED);\n+\n+\t\twq[i].mask = q_depth - 1;\n+\t}\n+\n+\treturn 0;\n+\n+cmdq_block_err:\n+\tfor (j = 0; j < i; j++)\n+\t\tfree_wq_pages(&wq[j]);\n+\n+\treturn err;\n+}\n+\n+void spnic_cmdq_free(struct spnic_wq *wq, int cmdq_blocks)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < cmdq_blocks; i++)\n+\t\tfree_wq_pages(&wq[i]);\n+}\n+\n+void spnic_wq_wqe_pg_clear(struct spnic_wq *wq)\n+{\n+\twq->cons_idx = 0;\n+\twq->prod_idx = 0;\n+\n+\tmemset((void *)wq->queue_buf_vaddr, 0, wq->wq_buf_size);\n+}\n+\n+void *spnic_get_wqe(struct spnic_wq *wq, int num_wqebbs, u16 *prod_idx)\n+{\n+\tu16 curr_prod_idx;\n+\n+\t__atomic_fetch_sub(&wq->delta, num_wqebbs, __ATOMIC_RELAXED);\n+\tcurr_prod_idx = wq->prod_idx;\n+\twq->prod_idx += num_wqebbs;\n+\t*prod_idx = MASKED_WQE_IDX(wq, curr_prod_idx);\n+\n+\treturn WQ_WQE_ADDR(wq, (u32)(*prod_idx));\n+}\n+\n+void spnic_set_sge(struct spnic_sge *sge, uint64_t addr, u32 len)\n+{\n+\tsge->hi_addr = upper_32_bits(addr);\n+\tsge->lo_addr = lower_32_bits(addr);\n+\tsge->len  = len;\n+}\ndiff --git a/drivers/net/spnic/base/spnic_wq.h b/drivers/net/spnic/base/spnic_wq.h\nindex 032d45e79e..19f604a79e 100644\n--- a/drivers/net/spnic/base/spnic_wq.h\n+++ b/drivers/net/spnic/base/spnic_wq.h\n@@ -9,11 +9,45 @@\n #define SPNIC_DEFAULT_WQ_PAGE_SIZE\t0x100000\n #define SPNIC_HW_WQ_PAGE_SIZE\t\t0x1000\n \n+#define WQS_BLOCKS_PER_PAGE\t\t4\n+\n+#define WQ_SIZE(wq)\t\t((u32)((u64)(wq)->q_depth * (wq)->wqebb_size))\n+\n+#define\tWQE_PAGE_NUM(wq, idx)\t(((idx) >> ((wq)->wqebbs_per_page_shift)) & \\\n+\t\t\t\t((wq)->num_q_pages - 1))\n+\n+#define\tWQE_PAGE_OFF(wq, idx)\t((u64)((wq)->wqebb_size) * \\\n+\t\t\t\t((idx) & ((wq)->num_wqebbs_per_page - 1)))\n+\n+#define WQ_PAGE_ADDR_SIZE\t\tsizeof(u64)\n+#define WQ_PAGE_ADDR_SIZE_SHIFT\t\t3\n+#define WQ_PAGE_ADDR(wq, idx)\t\t\\\n+\t\t((u8 *)(*(u64 *)((u64)((wq)->shadow_block_vaddr) + \\\n+\t\t(WQE_PAGE_NUM(wq, idx) << WQ_PAGE_ADDR_SIZE_SHIFT))))\n+\n+#define WQ_BLOCK_SIZE\t\t4096UL\n+#define WQS_PAGE_SIZE\t\t(WQS_BLOCKS_PER_PAGE * WQ_BLOCK_SIZE)\n+#define WQ_MAX_PAGES\t\t(WQ_BLOCK_SIZE >> WQ_PAGE_ADDR_SIZE_SHIFT)\n+\n #define CMDQ_BLOCKS_PER_PAGE\t\t8\n #define CMDQ_BLOCK_SIZE\t\t\t512UL\n #define CMDQ_PAGE_SIZE\t\t\tRTE_ALIGN((CMDQ_BLOCKS_PER_PAGE * \\\n \t\t\t\t\t\tCMDQ_BLOCK_SIZE), PAGE_SIZE)\n \n+#define ADDR_4K_ALIGNED(addr)\t\t(0 == ((addr) & 0xfff))\n+#define ADDR_256K_ALIGNED(addr)\t\t(0 == ((addr) & 0x3ffff))\n+\n+#define WQ_BASE_VADDR(wqs, wq)\t\t\\\n+\t\t((u64 *)(((u64)((wqs)->page_vaddr[(wq)->page_idx])) \\\n+\t\t\t\t+ (wq)->block_idx * WQ_BLOCK_SIZE))\n+\n+#define WQ_BASE_PADDR(wqs, wq)\t(((wqs)->page_paddr[(wq)->page_idx]) \\\n+\t\t\t\t+ (u64)(wq)->block_idx * WQ_BLOCK_SIZE)\n+\n+#define WQ_BASE_ADDR(wqs, wq)\t\t\\\n+\t\t((u64 *)(((u64)((wqs)->shadow_page_vaddr[(wq)->page_idx])) \\\n+\t\t\t\t+ (wq)->block_idx * WQ_BLOCK_SIZE))\n+\n #define CMDQ_BASE_VADDR(cmdq_pages, wq)\t\\\n \t\t\t((u64 *)(((u64)((cmdq_pages)->cmdq_page_vaddr)) \\\n \t\t\t\t+ (u64)((wq)->block_idx * CMDQ_BLOCK_SIZE)))\n@@ -28,16 +62,33 @@\n \n #define MASKED_WQE_IDX(wq, idx)\t((idx) & (wq)->mask)\n \n+#define WQE_SHADOW_PAGE(wq, wqe)\t\\\n+\t\t((u16)(((unsigned long)(wqe) - (unsigned long)(wq)->shadow_wqe) \\\n+\t\t/ (wq)->max_wqe_size))\n+\n+#define WQE_IN_RANGE(wqe, start, end)\t\\\n+\t\t(((unsigned long)(wqe) >= (unsigned long)(start)) && \\\n+\t\t((unsigned long)(wqe) < (unsigned long)(end)))\n+\n+#define WQ_NUM_PAGES(num_wqs)\t\\\n+\t(RTE_ALIGN((u32)(num_wqs), WQS_BLOCKS_PER_PAGE) / WQS_BLOCKS_PER_PAGE)\n+\n #define\tWQ_WQE_ADDR(wq, idx) ((void *)((u64)((wq)->queue_buf_vaddr) + \\\n \t\t\t      ((idx) << (wq)->wqebb_shift)))\n \n+struct spnic_sge {\n+\tu32 hi_addr;\n+\tu32 lo_addr;\n+\tu32 len;\n+};\n+\n struct spnic_wq {\n \t/* The addresses are 64 bit in the HW */\n \tu64 queue_buf_vaddr;\n \n \tu16 q_depth;\n \tu16 mask;\n-\trte_atomic32_t delta;\n+\tu32 delta;\n \n \tu32 cons_idx;\n \tu32 prod_idx;\n@@ -54,4 +105,19 @@ struct spnic_wq {\n \tu32 rsvd[5];\n };\n \n-#endif /* _SPNIC_WQ_H_ :*/\n+void spnic_wq_wqe_pg_clear(struct spnic_wq *wq);\n+\n+int spnic_cmdq_alloc(struct spnic_wq *wq, void *dev, int cmdq_blocks,\n+\t\t      u32 wq_buf_size, u32 wqebb_shift, u16 q_depth);\n+\n+void spnic_cmdq_free(struct spnic_wq *wq, int cmdq_blocks);\n+\n+void *spnic_get_wqe(struct spnic_wq *wq, int num_wqebbs, u16 *prod_idx);\n+\n+void spnic_put_wqe(struct spnic_wq *wq, int num_wqebbs);\n+\n+void *spnic_read_wqe(struct spnic_wq *wq, int num_wqebbs, u16 *cons_idx);\n+\n+void spnic_set_sge(struct spnic_sge *sge, uint64_t addr, u32 len);\n+\n+#endif /* _SPNIC_WQ_H_ */\n",
    "prefixes": [
        "v5",
        "07/26"
    ]
}