get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 54475,
    "url": "http://patches.dpdk.org/api/patches/54475/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/d086edc78ecc2c4a5cd23ee280fe3ba9235e5a0b.1559818024.git.xuanziyang2@huawei.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": "<d086edc78ecc2c4a5cd23ee280fe3ba9235e5a0b.1559818024.git.xuanziyang2@huawei.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/d086edc78ecc2c4a5cd23ee280fe3ba9235e5a0b.1559818024.git.xuanziyang2@huawei.com",
    "date": "2019-06-06T11:14:40",
    "name": "[v4,02/11] net/hinic/base: add command channels code",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "8286dc0637253fb1a865f185485a5204ca6d56a3",
    "submitter": {
        "id": 1321,
        "url": "http://patches.dpdk.org/api/people/1321/?format=api",
        "name": "Ziyang Xuan",
        "email": "xuanziyang2@huawei.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/d086edc78ecc2c4a5cd23ee280fe3ba9235e5a0b.1559818024.git.xuanziyang2@huawei.com/mbox/",
    "series": [
        {
            "id": 4924,
            "url": "http://patches.dpdk.org/api/series/4924/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=4924",
            "date": "2019-06-06T11:04:33",
            "name": "A new net PMD - hinic",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/4924/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/54475/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/54475/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 157371B95D;\n\tThu,  6 Jun 2019 13:03:22 +0200 (CEST)",
            "from huawei.com (szxga05-in.huawei.com [45.249.212.191])\n\tby dpdk.org (Postfix) with ESMTP id AE8F81B946\n\tfor <dev@dpdk.org>; Thu,  6 Jun 2019 13:03:19 +0200 (CEST)",
            "from DGGEMS414-HUB.china.huawei.com (unknown [172.30.72.60])\n\tby Forcepoint Email with ESMTP id B67A38EDB64778B4AD63;\n\tThu,  6 Jun 2019 19:03:17 +0800 (CST)",
            "from tester_149.localdomain (10.175.119.39) by\n\tDGGEMS414-HUB.china.huawei.com (10.3.19.214) with Microsoft SMTP\n\tServer id 14.3.439.0; Thu, 6 Jun 2019 19:03:10 +0800"
        ],
        "From": "Ziyang Xuan <xuanziyang2@huawei.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<ferruh.yigit@intel.com>, <cloud.wangxiaoyun@huawei.com>,\n\t<zhouguoyang@huawei.com>, <shahar.belkar@huawei.com>,\n\t<stephen@networkplumber.org>, <luoxianjun@huawei.com>, Ziyang Xuan\n\t<xuanziyang2@huawei.com>",
        "Date": "Thu, 6 Jun 2019 19:14:40 +0800",
        "Message-ID": "<d086edc78ecc2c4a5cd23ee280fe3ba9235e5a0b.1559818024.git.xuanziyang2@huawei.com>",
        "X-Mailer": "git-send-email 2.18.0",
        "In-Reply-To": "<cover.1559818024.git.xuanziyang2@huawei.com>",
        "References": "<cover.1559818024.git.xuanziyang2@huawei.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.175.119.39]",
        "X-CFilter-Loop": "Reflected",
        "Subject": "[dpdk-dev] [PATCH v4 02/11] net/hinic/base: add command channels\n\tcode",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Admin channels include api channel and command queue,\nApi channel is for mgmt module. And command queue is\nfor ucode module.\n\nSigned-off-by: Ziyang Xuan <xuanziyang2@huawei.com>\n---\n drivers/net/hinic/base/hinic_pmd_api_cmd.c | 1037 ++++++++++++++++++++\n drivers/net/hinic/base/hinic_pmd_api_cmd.h |  271 +++++\n drivers/net/hinic/base/hinic_pmd_cmdq.c    |  901 +++++++++++++++++\n drivers/net/hinic/base/hinic_pmd_cmdq.h    |  190 ++++\n 4 files changed, 2399 insertions(+)\n create mode 100644 drivers/net/hinic/base/hinic_pmd_api_cmd.c\n create mode 100644 drivers/net/hinic/base/hinic_pmd_api_cmd.h\n create mode 100644 drivers/net/hinic/base/hinic_pmd_cmdq.c\n create mode 100644 drivers/net/hinic/base/hinic_pmd_cmdq.h",
    "diff": "diff --git a/drivers/net/hinic/base/hinic_pmd_api_cmd.c b/drivers/net/hinic/base/hinic_pmd_api_cmd.c\nnew file mode 100644\nindex 000000000..ecf635c28\n--- /dev/null\n+++ b/drivers/net/hinic/base/hinic_pmd_api_cmd.c\n@@ -0,0 +1,1037 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2017 Huawei Technologies Co., Ltd\n+ */\n+\n+#include \"hinic_pmd_dpdev.h\"\n+\n+#define API_CMD_CHAIN_CELL_SIZE_SHIFT\t6U\n+\n+#define API_CMD_CELL_DESC_SIZE\t\t8\n+#define API_CMD_CELL_DATA_ADDR_SIZE\t8\n+\n+#define API_CHAIN_NUM_CELLS\t\t32\n+#define API_CHAIN_CELL_SIZE\t\t128\n+#define API_CHAIN_RSP_DATA_SIZE\t\t128\n+\n+#define API_CHAIN_CELL_ALIGNMENT\t8\n+\n+#define API_CMD_TIMEOUT\t\t\t10000\n+\n+#define API_CMD_BUF_SIZE\t\t2048UL\n+\n+#define API_CMD_NODE_ALIGN_SIZE\t\t512UL\n+#define API_PAYLOAD_ALIGN_SIZE\t\t64\n+\n+#define API_CHAIN_RESP_ALIGNMENT\t64ULL\n+\n+#define COMPLETION_TIMEOUT_DEFAULT\t\t1000UL\n+#define POLLING_COMPLETION_TIMEOUT_DEFAULT\t1000U\n+\n+#define API_CMD_RESPONSE_DATA_PADDR(val)\tbe64_to_cpu(*((u64 *)(val)))\n+\n+#define READ_API_CMD_PRIV_DATA(id, token)\t(((id) << 16) + (token))\n+#define WRITE_API_CMD_PRIV_DATA(id)\t\t((id) << 16)\n+\n+#define MASKED_IDX(chain, idx)\t\t((idx) & ((chain)->num_cells - 1))\n+\n+#undef  SIZE_4BYTES\n+#undef  SIZE_8BYTES\n+#define SIZE_4BYTES(size)\t\t(ALIGN((u32)(size), 4U) >> 2)\n+#define SIZE_8BYTES(size)\t\t(ALIGN((u32)(size), 8U) >> 3)\n+\n+enum api_cmd_data_format {\n+\tSGL_DATA     = 1,\n+};\n+\n+enum api_cmd_type {\n+\tAPI_CMD_WRITE_TYPE = 0,\n+\tAPI_CMD_READ_TYPE = 1,\n+};\n+\n+enum api_cmd_bypass {\n+\tNOT_BYPASS = 0,\n+\tBYPASS = 1,\n+};\n+\n+enum api_cmd_resp_aeq {\n+\tNOT_TRIGGER = 0,\n+\tTRIGGER     = 1,\n+};\n+\n+static u8 xor_chksum_set(void *data)\n+{\n+\tint idx;\n+\tu8 checksum = 0;\n+\tu8 *val = (u8 *)data;\n+\n+\tfor (idx = 0; idx < 7; idx++)\n+\t\tchecksum ^= val[idx];\n+\n+\treturn checksum;\n+}\n+\n+static void set_prod_idx(struct hinic_api_cmd_chain *chain)\n+{\n+\tenum hinic_api_cmd_chain_type chain_type = chain->chain_type;\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tu32 hw_prod_idx_addr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain_type);\n+\tu32 prod_idx = chain->prod_idx;\n+\n+\thinic_hwif_write_reg(hwif, hw_prod_idx_addr, prod_idx);\n+}\n+\n+static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain)\n+{\n+\tu32 addr, val;\n+\n+\taddr = HINIC_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type);\n+\tval  = hinic_hwif_read_reg(chain->hwdev->hwif, addr);\n+\n+\treturn HINIC_API_CMD_STATUS_GET(val, CONS_IDX);\n+}\n+\n+static void dump_api_chain_reg(struct hinic_api_cmd_chain *chain)\n+{\n+\tu32 addr, val;\n+\n+\taddr = HINIC_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type);\n+\tval  = hinic_hwif_read_reg(chain->hwdev->hwif, addr);\n+\n+\tPMD_DRV_LOG(ERR, \"chain type: 0x%x\", chain->chain_type);\n+\tPMD_DRV_LOG(ERR, \"chain hw cpld error: 0x%x\",\n+\t\tHINIC_API_CMD_STATUS_GET(val, CPLD_ERR));\n+\tPMD_DRV_LOG(ERR, \"chain hw check error: 0x%x\",\n+\t\tHINIC_API_CMD_STATUS_GET(val, CHKSUM_ERR));\n+\tPMD_DRV_LOG(ERR, \"chain hw current fsm: 0x%x\",\n+\t\tHINIC_API_CMD_STATUS_GET(val, FSM));\n+\tPMD_DRV_LOG(ERR, \"chain hw current ci: 0x%x\",\n+\t\tHINIC_API_CMD_STATUS_GET(val, CONS_IDX));\n+\n+\taddr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain->chain_type);\n+\tval  = hinic_hwif_read_reg(chain->hwdev->hwif, addr);\n+\tPMD_DRV_LOG(ERR, \"Chain hw current pi: 0x%x\", val);\n+}\n+\n+/**\n+ * chain_busy - check if the chain is still processing last requests\n+ * @chain: chain to check\n+ **/\n+static int chain_busy(struct hinic_api_cmd_chain *chain)\n+{\n+\tswitch (chain->chain_type) {\n+\tcase HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:\n+\tcase HINIC_API_CMD_PMD_WRITE_TO_MGMT:\n+\t\tchain->cons_idx = get_hw_cons_idx(chain);\n+\t\tif (chain->cons_idx == MASKED_IDX(chain, chain->prod_idx + 1)) {\n+\t\t\tPMD_DRV_LOG(ERR, \"API CMD chain %d is busy, cons_idx: %d, prod_idx: %d\",\n+\t\t\t\tchain->chain_type, chain->cons_idx,\n+\t\t\t\tchain->prod_idx);\n+\t\t\tdump_api_chain_reg(chain);\n+\t\t\treturn -EBUSY;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"Unknown Chain type\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * get_cell_data_size - get the data size of specific cell type\n+ * @type: chain type\n+ **/\n+static u16 get_cell_data_size(enum hinic_api_cmd_chain_type type,\n+\t\t\t\t__rte_unused u16 cmd_size)\n+{\n+\tu16 cell_data_size = 0;\n+\n+\tswitch (type) {\n+\tcase HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:\n+\tcase HINIC_API_CMD_PMD_WRITE_TO_MGMT:\n+\t\tcell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE +\n+\t\t\t\t\tAPI_CMD_CELL_DATA_ADDR_SIZE,\n+\t\t\t\t\tAPI_CHAIN_CELL_ALIGNMENT);\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn cell_data_size;\n+}\n+\n+/**\n+ * prepare_cell_ctrl - prepare the ctrl of the cell for the command\n+ * @cell_ctrl: the control of the cell to set the control into it\n+ * @cell_len: the size of the cell\n+ **/\n+static void prepare_cell_ctrl(u64 *cell_ctrl, u16 cell_len)\n+{\n+\tu64 ctrl;\n+\tu8 chksum;\n+\n+\t/* Read Modify Write */\n+\tctrl = be64_to_cpu(*cell_ctrl);\n+\tctrl = HINIC_API_CMD_CELL_CTRL_CLEAR(ctrl, CELL_LEN) &\n+\t\tHINIC_API_CMD_CELL_CTRL_CLEAR(ctrl, RD_DMA_ATTR_OFF) &\n+\t\tHINIC_API_CMD_CELL_CTRL_CLEAR(ctrl, WR_DMA_ATTR_OFF) &\n+\t\tHINIC_API_CMD_CELL_CTRL_CLEAR(ctrl, XOR_CHKSUM);\n+\n+\tctrl |=  HINIC_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(cell_len), CELL_LEN) |\n+\t\tHINIC_API_CMD_CELL_CTRL_SET(0ULL, RD_DMA_ATTR_OFF) |\n+\t\tHINIC_API_CMD_CELL_CTRL_SET(0ULL, WR_DMA_ATTR_OFF);\n+\n+\tchksum = xor_chksum_set(&ctrl);\n+\n+\tctrl |= HINIC_API_CMD_CELL_CTRL_SET(chksum, XOR_CHKSUM);\n+\n+\t/* The data in the HW should be in Big Endian Format */\n+\t*cell_ctrl = cpu_to_be64(ctrl);\n+}\n+\n+/**\n+ * prepare_api_cmd - prepare API CMD command\n+ * @chain: chain for the command\n+ * @cell: the cell of the command\n+ * @dest: destination node on the card that will receive the command\n+ * @cmd: command data\n+ * @cmd_size: the command size\n+ **/\n+static void prepare_api_cmd(struct hinic_api_cmd_chain *chain,\n+\t\t\t\tstruct hinic_api_cmd_cell *cell,\n+\t\t\t\tenum hinic_node_id dest,\n+\t\t\t\tvoid *cmd, u16 cmd_size)\n+{\n+\tstruct hinic_api_cmd_cell_ctxt\t*cell_ctxt;\n+\tu32 priv;\n+\n+\tcell_ctxt = &chain->cell_ctxt[chain->prod_idx];\n+\n+\t/* Clear all the members before changes */\n+\tcell->desc = HINIC_API_CMD_DESC_CLEAR(cell->desc, API_TYPE) &\n+\t\t\tHINIC_API_CMD_DESC_CLEAR(cell->desc, RD_WR) &\n+\t\t\tHINIC_API_CMD_DESC_CLEAR(cell->desc, MGMT_BYPASS) &\n+\t\t\tHINIC_API_CMD_DESC_CLEAR(cell->desc, RESP_AEQE_EN) &\n+\t\t\tHINIC_API_CMD_DESC_CLEAR(cell->desc, DEST) &\n+\t\t\tHINIC_API_CMD_DESC_CLEAR(cell->desc, SIZE) &\n+\t\t\tHINIC_API_CMD_DESC_CLEAR(cell->desc, XOR_CHKSUM);\n+\n+\tswitch (chain->chain_type) {\n+\tcase HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:\n+\tcase HINIC_API_CMD_PMD_WRITE_TO_MGMT:\n+\t\tpriv =  WRITE_API_CMD_PRIV_DATA(chain->chain_type);\n+\t\tcell->desc = HINIC_API_CMD_DESC_SET(SGL_DATA, API_TYPE) |\n+\t\t\tHINIC_API_CMD_DESC_SET(API_CMD_WRITE_TYPE, RD_WR) |\n+\t\t\tHINIC_API_CMD_DESC_SET(NOT_BYPASS, MGMT_BYPASS) |\n+\t\t\tHINIC_API_CMD_DESC_SET(TRIGGER, RESP_AEQE_EN)\t|\n+\t\t\tHINIC_API_CMD_DESC_SET(priv, PRIV_DATA);\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"Unknown Chain type\");\n+\t\treturn;\n+\t}\n+\n+\tcell->desc |= HINIC_API_CMD_DESC_SET(dest, DEST)\t |\n+\t\t\tHINIC_API_CMD_DESC_SET(SIZE_4BYTES(cmd_size), SIZE);\n+\tcell->desc |= HINIC_API_CMD_DESC_SET(xor_chksum_set(&cell->desc),\n+\t\t\t\t\t\tXOR_CHKSUM);\n+\n+\t/* The data in the HW should be in Big Endian Format */\n+\tcell->desc = cpu_to_be64(cell->desc);\n+\n+\tmemcpy(cell_ctxt->api_cmd_vaddr, cmd, cmd_size);\n+}\n+\n+/**\n+ * prepare_cell - prepare cell ctrl and cmd in the current producer cell\n+ * @chain: chain for the command\n+ * @dest: destination node on the card that will receive the command\n+ * @cmd: command data\n+ * @cmd_size: the command size\n+ **/\n+static void prepare_cell(struct hinic_api_cmd_chain *chain,\n+\t\t\t enum  hinic_node_id dest,\n+\t\t\t void *cmd, u16 cmd_size)\n+{\n+\tstruct hinic_api_cmd_cell *curr_node;\n+\tu16 cell_size;\n+\n+\tcurr_node = chain->curr_node;\n+\n+\tcell_size = get_cell_data_size(chain->chain_type, cmd_size);\n+\n+\tprepare_cell_ctrl(&curr_node->ctrl, cell_size);\n+\tprepare_api_cmd(chain, curr_node, dest, cmd, cmd_size);\n+}\n+\n+static inline void cmd_chain_prod_idx_inc(struct hinic_api_cmd_chain *chain)\n+{\n+\tchain->prod_idx = MASKED_IDX(chain, chain->prod_idx + 1);\n+}\n+\n+static void issue_api_cmd(struct hinic_api_cmd_chain *chain)\n+{\n+\tset_prod_idx(chain);\n+}\n+\n+/**\n+ * api_cmd_status_update - update the status of the chain\n+ * @chain: chain to update\n+ **/\n+static void api_cmd_status_update(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_api_cmd_status *wb_status;\n+\tenum hinic_api_cmd_chain_type chain_type;\n+\tu64\tstatus_header;\n+\tu32\tbuf_desc;\n+\n+\twb_status = chain->wb_status;\n+\n+\tbuf_desc = be32_to_cpu(wb_status->buf_desc);\n+\tif (HINIC_API_CMD_STATUS_GET(buf_desc, CHKSUM_ERR)) {\n+\t\tPMD_DRV_LOG(ERR, \"API CMD status Xor check error\");\n+\t\treturn;\n+\t}\n+\n+\tstatus_header = be64_to_cpu(wb_status->header);\n+\tchain_type = HINIC_API_CMD_STATUS_HEADER_GET(status_header, CHAIN_ID);\n+\tif (chain_type >= HINIC_API_CMD_MAX)\n+\t\treturn;\n+\n+\tif (chain_type != chain->chain_type)\n+\t\treturn;\n+\n+\tchain->cons_idx = HINIC_API_CMD_STATUS_GET(buf_desc, CONS_IDX);\n+}\n+\n+/**\n+ * wait_for_status_poll - wait for write to mgmt command to complete\n+ * @chain: the chain of the command\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int wait_for_status_poll(struct hinic_api_cmd_chain *chain)\n+{\n+\tunsigned long end;\n+\tint err = -ETIMEDOUT;\n+\n+\tend = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);\n+\tdo {\n+\t\tapi_cmd_status_update(chain);\n+\n+\t\t/* SYNC API CMD cmd should start after prev cmd finished */\n+\t\tif (chain->cons_idx == chain->prod_idx) {\n+\t\t\terr = 0;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\trte_delay_us(10);\n+\t} while (time_before(jiffies, end));\n+\n+\treturn err;\n+}\n+\n+/**\n+ * wait_for_api_cmd_completion - wait for command to complete\n+ * @chain: chain for the command\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int wait_for_api_cmd_completion(struct hinic_api_cmd_chain *chain,\n+\t\t       __rte_unused struct hinic_api_cmd_cell_ctxt *ctxt,\n+\t\t       __rte_unused void *ack, __rte_unused u16 ack_size)\n+{\n+\tint err = 0;\n+\n+\t/* poll api cmd status for debug*/\n+\tswitch (chain->chain_type) {\n+\tcase HINIC_API_CMD_PMD_WRITE_TO_MGMT:\n+\t\terr = wait_for_status_poll(chain);\n+\t\tif (err)\n+\t\t\tPMD_DRV_LOG(ERR, \"API CMD poll status timeout\");\n+\t\tbreak;\n+\tcase HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"Unknown API CMD chain type\");\n+\t\terr = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+\tif (err)\n+\t\tdump_api_chain_reg(chain);\n+\n+\treturn err;\n+}\n+\n+static inline void update_api_cmd_ctxt(struct hinic_api_cmd_chain *chain,\n+\t\t\t\t       struct hinic_api_cmd_cell_ctxt *ctxt)\n+{\n+\tctxt->status = 1;\n+\tctxt->saved_prod_idx = chain->prod_idx;\n+}\n+\n+/**\n+ * api_cmd - API CMD command\n+ * @chain: chain for the command\n+ * @dest: destination node on the card that will receive the command\n+ * @cmd: command data\n+ * @cmd_size: the command size\n+ * @ack: pointer to messages to response\n+ * @ack_size: the size of ack message\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int api_cmd(struct hinic_api_cmd_chain *chain,\n+\t\t   enum hinic_node_id dest,\n+\t\t   void *cmd, u16 cmd_size, void *ack, u16 ack_size)\n+{\n+\tstruct hinic_api_cmd_cell_ctxt *ctxt;\n+\n+\tspin_lock(&chain->async_lock);\n+\n+\tctxt = &chain->cell_ctxt[chain->prod_idx];\n+\tif (chain_busy(chain)) {\n+\t\tspin_unlock(&chain->async_lock);\n+\t\treturn -EBUSY;\n+\t}\n+\tupdate_api_cmd_ctxt(chain, ctxt);\n+\n+\tprepare_cell(chain, dest, cmd, cmd_size);\n+\n+\tcmd_chain_prod_idx_inc(chain);\n+\n+\trte_wmb();/* issue the command */\n+\n+\tissue_api_cmd(chain);\n+\n+\t/* incremented prod idx, update ctxt */\n+\tchain->curr_node = chain->cell_ctxt[chain->prod_idx].cell_vaddr;\n+\n+\tspin_unlock(&chain->async_lock);\n+\n+\treturn wait_for_api_cmd_completion(chain, ctxt, ack, ack_size);\n+}\n+\n+/**\n+ * hinic_api_cmd_write - Write API CMD command\n+ * @chain: chain for write command\n+ * @dest: destination node on the card that will receive the command\n+ * @cmd: command data\n+ * @size: the command size\n+ * Return: 0 - success, negative - failure\n+ **/\n+int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain,\n+\t\t\tenum hinic_node_id dest, void *cmd, u16 size)\n+{\n+\t/* Verify the chain type */\n+\treturn api_cmd(chain, dest, cmd, size, NULL, 0);\n+}\n+\n+/**\n+ * api_cmd_hw_restart - restart the chain in the HW\n+ * @chain: the API CMD specific chain to restart\n+ **/\n+static int api_cmd_hw_restart(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tunsigned long end;\n+\tu32 reg_addr, val;\n+\tint err;\n+\n+\t/* Read Modify Write */\n+\treg_addr = HINIC_CSR_API_CMD_CHAIN_REQ_ADDR(chain->chain_type);\n+\tval = hinic_hwif_read_reg(hwif, reg_addr);\n+\n+\tval = HINIC_API_CMD_CHAIN_REQ_CLEAR(val, RESTART);\n+\tval |= HINIC_API_CMD_CHAIN_REQ_SET(1, RESTART);\n+\n+\thinic_hwif_write_reg(hwif, reg_addr, val);\n+\n+\tend = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);\n+\terr = -ETIMEDOUT;\n+\tdo {\n+\t\tval = hinic_hwif_read_reg(hwif, reg_addr);\n+\n+\t\tif (!HINIC_API_CMD_CHAIN_REQ_GET(val, RESTART)) {\n+\t\t\terr = 0;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\trte_delay_ms(1);\n+\t} while (time_before(jiffies, end));\n+\n+\treturn err;\n+}\n+\n+/**\n+ * api_cmd_ctrl_init - set the control register of a chain\n+ * @chain: the API CMD specific chain to set control register for\n+ **/\n+static void api_cmd_ctrl_init(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tu32 reg_addr, ctrl;\n+\tu32 cell_size;\n+\n+\t/* Read Modify Write */\n+\treg_addr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);\n+\n+\tcell_size = (u32)ilog2(chain->cell_size >>\n+\t\t\t       API_CMD_CHAIN_CELL_SIZE_SHIFT);\n+\n+\tctrl = hinic_hwif_read_reg(hwif, reg_addr);\n+\n+\tctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) &\n+\t\tHINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);\n+\n+\tctrl |= HINIC_API_CMD_CHAIN_CTRL_SET(0, AEQE_EN) |\n+\t\tHINIC_API_CMD_CHAIN_CTRL_SET(cell_size, CELL_SIZE);\n+\n+\thinic_hwif_write_reg(hwif, reg_addr, ctrl);\n+}\n+\n+/**\n+ * api_cmd_set_status_addr - set the status address of a chain in the HW\n+ * @chain: the API CMD specific chain to set status address for\n+ **/\n+static void api_cmd_set_status_addr(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tu32 addr, val;\n+\n+\taddr = HINIC_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type);\n+\tval = upper_32_bits(chain->wb_status_paddr);\n+\thinic_hwif_write_reg(hwif, addr, val);\n+\n+\taddr = HINIC_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type);\n+\tval = lower_32_bits(chain->wb_status_paddr);\n+\thinic_hwif_write_reg(hwif, addr, val);\n+}\n+\n+/**\n+ * api_cmd_set_num_cells - set the number cells of a chain in the HW\n+ * @chain: the API CMD specific chain to set the number of cells for\n+ **/\n+static void api_cmd_set_num_cells(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tu32 addr, val;\n+\n+\taddr = HINIC_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type);\n+\tval  = chain->num_cells;\n+\thinic_hwif_write_reg(hwif, addr, val);\n+}\n+\n+/**\n+ * api_cmd_head_init - set the head cell of a chain in the HW\n+ * @chain: the API CMD specific chain to set the head for\n+ **/\n+static void api_cmd_head_init(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tu32 addr, val;\n+\n+\taddr = HINIC_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type);\n+\tval = upper_32_bits(chain->head_cell_paddr);\n+\thinic_hwif_write_reg(hwif, addr, val);\n+\n+\taddr = HINIC_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type);\n+\tval = lower_32_bits(chain->head_cell_paddr);\n+\thinic_hwif_write_reg(hwif, addr, val);\n+}\n+\n+/**\n+ * wait_for_ready_chain - wait for the chain to be ready\n+ * @chain: the API CMD specific chain to wait for\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int wait_for_ready_chain(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tunsigned long end;\n+\tu32 addr, val;\n+\tu32 hw_cons_idx;\n+\tint err;\n+\n+\tend = jiffies + msecs_to_jiffies(API_CMD_TIMEOUT);\n+\n+\taddr = HINIC_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type);\n+\terr = -ETIMEDOUT;\n+\tdo {\n+\t\tval = hinic_hwif_read_reg(hwif, addr);\n+\t\thw_cons_idx = HINIC_API_CMD_STATUS_GET(val, CONS_IDX);\n+\n+\t\t/* Wait for HW cons idx to be updated */\n+\t\tif (hw_cons_idx == chain->cons_idx) {\n+\t\t\terr = 0;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\trte_delay_ms(1);\n+\t} while (time_before(jiffies, end));\n+\n+\treturn err;\n+}\n+\n+/**\n+ * api_cmd_chain_hw_clean - clean the HW\n+ * @chain: the API CMD specific chain\n+ **/\n+static void api_cmd_chain_hw_clean(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_hwif *hwif = chain->hwdev->hwif;\n+\tu32 addr, ctrl;\n+\n+\taddr = HINIC_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type);\n+\n+\tctrl = hinic_hwif_read_reg(hwif, addr);\n+\tctrl = HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_EN) &\n+\t       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR)    &\n+\t       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN)    &\n+\t       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) &\n+\t       HINIC_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE);\n+\n+\thinic_hwif_write_reg(hwif, addr, ctrl);\n+}\n+\n+/**\n+ * api_cmd_chain_hw_init - initialize the chain in the HW\n+ *(initialize API command csr)\n+ * @chain: the API CMD specific chain to initialize in HW\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int api_cmd_chain_hw_init(struct hinic_api_cmd_chain *chain)\n+{\n+\tapi_cmd_chain_hw_clean(chain);\n+\n+\tapi_cmd_set_status_addr(chain);\n+\n+\tif (api_cmd_hw_restart(chain)) {\n+\t\tPMD_DRV_LOG(ERR, \"Restart api_cmd_hw failed\");\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tapi_cmd_ctrl_init(chain);\n+\tapi_cmd_set_num_cells(chain);\n+\tapi_cmd_head_init(chain);\n+\n+\treturn wait_for_ready_chain(chain);\n+}\n+\n+/**\n+ * free_cmd_buf - free the dma buffer of API CMD command\n+ * @chain: the API CMD specific chain of the cmd\n+ * @cell_idx: the cell index of the cmd\n+ **/\n+static void free_cmd_buf(struct hinic_api_cmd_chain *chain, u32 cell_idx)\n+{\n+\tstruct hinic_api_cmd_cell_ctxt *cell_ctxt;\n+\tvoid *dev = chain->hwdev->dev_hdl;\n+\n+\tcell_ctxt = &chain->cell_ctxt[cell_idx];\n+\n+\tdma_free_coherent(dev, (API_CMD_BUF_SIZE + API_PAYLOAD_ALIGN_SIZE),\n+\t\t\t  cell_ctxt->api_cmd_vaddr_free,\n+\t\t\t  cell_ctxt->api_cmd_paddr_free);\n+}\n+\n+/**\n+ * alloc_cmd_buf - allocate a dma buffer for API CMD command\n+ * @chain: the API CMD specific chain for the cmd\n+ * @cell: the cell in the HW for the cmd\n+ * @cell_idx: the index of the cell\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain,\n+\t\t\t struct hinic_api_cmd_cell *cell, u32 cell_idx)\n+{\n+\tvoid *dev = chain->hwdev->dev_hdl;\n+\tstruct hinic_api_cmd_cell_ctxt *cell_ctxt;\n+\tdma_addr_t cmd_paddr = 0;\n+\tvoid *cmd_vaddr;\n+\tvoid *cmd_vaddr_alloc;\n+\tint err = 0;\n+\n+\tcmd_vaddr_alloc = dma_zalloc_coherent(dev, (API_CMD_BUF_SIZE +\n+\t\t\t\t\t      API_PAYLOAD_ALIGN_SIZE),\n+\t\t\t\t\t      &cmd_paddr, GFP_KERNEL);\n+\tif (!cmd_vaddr_alloc) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate API CMD dma memory failed\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tcell_ctxt = &chain->cell_ctxt[cell_idx];\n+\n+\tcell_ctxt->api_cmd_paddr_free = cmd_paddr;\n+\tcell_ctxt->api_cmd_vaddr_free = cmd_vaddr_alloc;\n+\tcmd_vaddr = PTR_ALIGN(cmd_vaddr_alloc, API_PAYLOAD_ALIGN_SIZE);\n+\tcmd_paddr = cmd_paddr + ((u64)cmd_vaddr - (u64)cmd_vaddr_alloc);\n+\n+\tcell_ctxt->api_cmd_vaddr = cmd_vaddr;\n+\tcell_ctxt->api_cmd_paddr = cmd_paddr;\n+\n+\t/* set the cmd DMA address in the cell */\n+\tswitch (chain->chain_type) {\n+\tcase HINIC_API_CMD_PMD_WRITE_TO_MGMT:\n+\tcase HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:\n+\t\tcell->write.hw_cmd_paddr = cpu_to_be64(cmd_paddr);\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"Unknown API CMD chain type\");\n+\t\tfree_cmd_buf(chain, cell_idx);\n+\t\terr = -EINVAL;\n+\t\tbreak;\n+\t}\n+\n+\treturn err;\n+}\n+\n+/**\n+ * api_cmd_create_cell - create API CMD cell of specific chain\n+ * @chain: the API CMD specific chain to create its cell\n+ * @cell_idx: the cell index to create\n+ * @pre_node: previous cell\n+ * @node_vaddr: the virt addr of the cell\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain,\n+\t\t\t       u32 cell_idx,\n+\t\t\t       struct hinic_api_cmd_cell *pre_node,\n+\t\t\t       struct hinic_api_cmd_cell **node_vaddr)\n+{\n+\tvoid *dev = chain->hwdev->dev_hdl;\n+\tstruct hinic_api_cmd_cell_ctxt *cell_ctxt;\n+\tstruct hinic_api_cmd_cell *node;\n+\tdma_addr_t node_paddr = 0;\n+\tvoid *node_vaddr_alloc;\n+\tint err = 0;\n+\n+\tnode_vaddr_alloc = dma_zalloc_coherent(dev, (chain->cell_size +\n+\t\t\t\t\t       API_CMD_NODE_ALIGN_SIZE),\n+\t\t\t\t\t       &node_paddr, GFP_KERNEL);\n+\tif (!node_vaddr_alloc) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate dma API CMD cell failed\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tcell_ctxt = &chain->cell_ctxt[cell_idx];\n+\n+\tcell_ctxt->cell_vaddr_free = node_vaddr_alloc;\n+\tcell_ctxt->cell_paddr_free = node_paddr;\n+\tnode = (struct hinic_api_cmd_cell *)PTR_ALIGN(node_vaddr_alloc,\n+\t\tAPI_CMD_NODE_ALIGN_SIZE);\n+\tnode_paddr = node_paddr + ((u64)node - (u64)node_vaddr_alloc);\n+\n+\tnode->read.hw_wb_resp_paddr = 0;\n+\n+\tcell_ctxt->cell_vaddr = node;\n+\tcell_ctxt->cell_paddr = node_paddr;\n+\n+\tif (!pre_node) {\n+\t\tchain->head_node = node;\n+\t\tchain->head_cell_paddr = node_paddr;\n+\t} else {\n+\t\t/* The data in the HW should be in Big Endian Format */\n+\t\tpre_node->next_cell_paddr = cpu_to_be64(node_paddr);\n+\t}\n+\n+\t/* Driver software should make sure that there is an empty\n+\t * API command cell at the end the chain\n+\t */\n+\tnode->next_cell_paddr = 0;\n+\n+\tswitch (chain->chain_type) {\n+\tcase HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:\n+\tcase HINIC_API_CMD_PMD_WRITE_TO_MGMT:\n+\t\terr = alloc_cmd_buf(chain, node, cell_idx);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Allocate cmd buffer failed\");\n+\t\t\tgoto alloc_cmd_buf_err;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tPMD_DRV_LOG(ERR, \"Unsupported API CMD chain type\");\n+\t\terr = -EINVAL;\n+\t\tgoto alloc_cmd_buf_err;\n+\t}\n+\n+\t*node_vaddr = node;\n+\n+\treturn 0;\n+\n+alloc_cmd_buf_err:\n+\tdma_free_coherent(dev, (chain->cell_size + API_CMD_NODE_ALIGN_SIZE),\n+\t\t\t  node_vaddr_alloc, cell_ctxt->cell_paddr_free);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * api_cmd_destroy_cell - destroy API CMD cell of specific chain\n+ * @chain: the API CMD specific chain to destroy its cell\n+ * @cell_idx: the cell to destroy\n+ **/\n+static void api_cmd_destroy_cell(struct hinic_api_cmd_chain *chain,\n+\t\t\t\t u32 cell_idx)\n+{\n+\tvoid *dev = chain->hwdev->dev_hdl;\n+\tstruct hinic_api_cmd_cell_ctxt *cell_ctxt;\n+\tstruct hinic_api_cmd_cell *node;\n+\tdma_addr_t node_paddr;\n+\n+\tcell_ctxt = &chain->cell_ctxt[cell_idx];\n+\n+\tnode = (struct hinic_api_cmd_cell *)(cell_ctxt->cell_vaddr_free);\n+\tnode_paddr = cell_ctxt->cell_paddr_free;\n+\n+\tif (cell_ctxt->api_cmd_vaddr) {\n+\t\tswitch (chain->chain_type) {\n+\t\tcase HINIC_API_CMD_PMD_WRITE_TO_MGMT:\n+\t\tcase HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU:\n+\t\t\tfree_cmd_buf(chain, cell_idx);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tdma_free_coherent(dev, (chain->cell_size +\n+\t\t\t\t  API_CMD_NODE_ALIGN_SIZE),\n+\t\t\t\t  node, node_paddr);\n+\t}\n+}\n+\n+/**\n+ * api_cmd_destroy_cells - destroy API CMD cells of specific chain\n+ * @chain: the API CMD specific chain to destroy its cells\n+ * @num_cells: number of cells to destroy\n+ **/\n+static void api_cmd_destroy_cells(struct hinic_api_cmd_chain *chain,\n+\t\t\t\t\t u32 num_cells)\n+{\n+\tu32 cell_idx;\n+\n+\tfor (cell_idx = 0; cell_idx < num_cells; cell_idx++)\n+\t\tapi_cmd_destroy_cell(chain, cell_idx);\n+}\n+\n+/**\n+ * api_cmd_create_cells - create API CMD cells for specific chain\n+ * @chain: the API CMD specific chain\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int api_cmd_create_cells(struct hinic_api_cmd_chain *chain)\n+{\n+\tstruct hinic_api_cmd_cell *node = NULL, *pre_node = NULL;\n+\tu32 cell_idx;\n+\tint err;\n+\n+\tfor (cell_idx = 0; cell_idx < chain->num_cells; cell_idx++) {\n+\t\terr = api_cmd_create_cell(chain, cell_idx, pre_node, &node);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Create API CMD cell failed\");\n+\t\t\tgoto create_cell_err;\n+\t\t}\n+\n+\t\tpre_node = node;\n+\t}\n+\n+\tif (!node) {\n+\t\terr = -EFAULT;\n+\t\tgoto create_cell_err;\n+\t}\n+\n+\t/* set the Final node to point on the start */\n+\tnode->next_cell_paddr = cpu_to_be64(chain->head_cell_paddr);\n+\n+\t/* set the current node to be the head */\n+\tchain->curr_node = chain->head_node;\n+\treturn 0;\n+\n+create_cell_err:\n+\tapi_cmd_destroy_cells(chain, cell_idx);\n+\treturn err;\n+}\n+\n+/**\n+ * api_chain_init - initialize API CMD specific chain\n+ * @chain: the API CMD specific chain to initialize\n+ * @attr: attributes to set in the chain\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int api_chain_init(struct hinic_api_cmd_chain *chain,\n+\t\t\t  struct hinic_api_cmd_chain_attr *attr)\n+{\n+\tvoid *dev = chain->hwdev->dev_hdl;\n+\tsize_t cell_ctxt_size;\n+\tint err;\n+\n+\tchain->chain_type  = attr->chain_type;\n+\tchain->num_cells = attr->num_cells;\n+\tchain->cell_size = attr->cell_size;\n+\tchain->rsp_size = attr->rsp_size;\n+\n+\tchain->prod_idx  = 0;\n+\tchain->cons_idx  = 0;\n+\n+\tspin_lock_init(&chain->async_lock);\n+\n+\tcell_ctxt_size = chain->num_cells * sizeof(*chain->cell_ctxt);\n+\tchain->cell_ctxt = kzalloc(cell_ctxt_size, GFP_KERNEL);\n+\tif (!chain->cell_ctxt) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate cell contexts for a chain failed\");\n+\t\terr = -ENOMEM;\n+\t\tgoto alloc_cell_ctxt_err;\n+\t}\n+\n+\tchain->wb_status = (struct hinic_api_cmd_status *)\n+\t\t\t   dma_zalloc_coherent(dev, sizeof(*chain->wb_status),\n+\t\t\t\t\t       &chain->wb_status_paddr,\n+\t\t\t\t\t       GFP_KERNEL);\n+\tif (!chain->wb_status) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate DMA wb status failed\");\n+\t\terr = -ENOMEM;\n+\t\tgoto alloc_wb_status_err;\n+\t}\n+\n+\treturn 0;\n+\n+alloc_wb_status_err:\n+\tkfree(chain->cell_ctxt);\n+\n+alloc_cell_ctxt_err:\n+\n+\treturn err;\n+}\n+\n+/**\n+ * api_chain_free - free API CMD specific chain\n+ * @chain: the API CMD specific chain to free\n+ **/\n+static void api_chain_free(struct hinic_api_cmd_chain *chain)\n+{\n+\tvoid *dev = chain->hwdev->dev_hdl;\n+\n+\tdma_free_coherent(dev, sizeof(*chain->wb_status),\n+\t\t\t  chain->wb_status, chain->wb_status_paddr);\n+\tkfree(chain->cell_ctxt);\n+}\n+\n+/**\n+ * api_cmd_create_chain - create API CMD specific chain\n+ * @cmd_chain: the API CMD specific chain to create\n+ * @attr: attributes to set in the chain\n+ * Return: 0 - success, negative - failure\n+ **/\n+static int api_cmd_create_chain(struct hinic_api_cmd_chain **cmd_chain,\n+\t\t\t\tstruct hinic_api_cmd_chain_attr *attr)\n+{\n+\tstruct hinic_hwdev *hwdev = attr->hwdev;\n+\tstruct hinic_api_cmd_chain *chain;\n+\tint err;\n+\n+\tif (attr->num_cells & (attr->num_cells - 1)) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid number of cells, must be power of 2\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tchain = kzalloc(sizeof(*chain), GFP_KERNEL);\n+\tif (!chain) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate memory for the chain failed\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tchain->hwdev = hwdev;\n+\n+\terr = api_chain_init(chain, attr);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Initialize chain failed\");\n+\t\tgoto chain_init_err;\n+\t}\n+\n+\terr = api_cmd_create_cells(chain);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Create cells for API CMD chain failed\");\n+\t\tgoto create_cells_err;\n+\t}\n+\n+\terr = api_cmd_chain_hw_init(chain);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Initialize chain hw info failed\");\n+\t\tgoto chain_hw_init_err;\n+\t}\n+\n+\t*cmd_chain = chain;\n+\treturn 0;\n+\n+chain_hw_init_err:\n+\tapi_cmd_destroy_cells(chain, chain->num_cells);\n+\n+create_cells_err:\n+\tapi_chain_free(chain);\n+\n+chain_init_err:\n+\tkfree(chain);\n+\treturn err;\n+}\n+\n+/**\n+ * api_cmd_destroy_chain - destroy API CMD specific chain\n+ * @chain: the API CMD specific chain to destroy\n+ **/\n+static void api_cmd_destroy_chain(struct hinic_api_cmd_chain *chain)\n+{\n+\tapi_cmd_destroy_cells(chain, chain->num_cells);\n+\tapi_chain_free(chain);\n+\tkfree(chain);\n+}\n+\n+/**\n+ * hinic_api_cmd_init - Initialize all the API CMD chains\n+ * @hwdev: the hardware interface of a pci function device\n+ * @chain: the API CMD chains that will be initialized\n+ * Return: 0 - success, negative - failure\n+ **/\n+int hinic_api_cmd_init(struct hinic_hwdev *hwdev,\n+\t\t       struct hinic_api_cmd_chain **chain)\n+{\n+\tstruct hinic_api_cmd_chain_attr attr;\n+\tenum hinic_api_cmd_chain_type chain_type, i;\n+\tint err;\n+\n+\tattr.hwdev = hwdev;\n+\tattr.num_cells  = API_CHAIN_NUM_CELLS;\n+\tattr.cell_size  = API_CHAIN_CELL_SIZE;\n+\tattr.rsp_size\t= API_CHAIN_RSP_DATA_SIZE;\n+\n+\tchain_type = HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU;\n+\tfor ( ; chain_type < HINIC_API_CMD_MAX; chain_type++) {\n+\t\tattr.chain_type = chain_type;\n+\t\terr = api_cmd_create_chain(&chain[chain_type], &attr);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Create chain %d failed\",\n+\t\t\t\tchain_type);\n+\t\t\tgoto create_chain_err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+\n+create_chain_err:\n+\ti = HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU;\n+\tfor (; i < chain_type; i++)\n+\t\tapi_cmd_destroy_chain(chain[i]);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * hinic_api_cmd_free - free the API CMD chains\n+ * @chain: the API CMD chains that will be freed\n+ **/\n+void hinic_api_cmd_free(struct hinic_api_cmd_chain **chain)\n+{\n+\tenum hinic_api_cmd_chain_type chain_type;\n+\n+\tchain_type = HINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU;\n+\tfor ( ; chain_type < HINIC_API_CMD_MAX; chain_type++)\n+\t\tapi_cmd_destroy_chain(chain[chain_type]);\n+}\ndiff --git a/drivers/net/hinic/base/hinic_pmd_api_cmd.h b/drivers/net/hinic/base/hinic_pmd_api_cmd.h\nnew file mode 100644\nindex 000000000..aff1f1391\n--- /dev/null\n+++ b/drivers/net/hinic/base/hinic_pmd_api_cmd.h\n@@ -0,0 +1,271 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2017 Huawei Technologies Co., Ltd\n+ */\n+\n+#ifndef _HINIC_PMD_API_CMD_H_\n+#define _HINIC_PMD_API_CMD_H_\n+\n+#define HINIC_API_CMD_CELL_CTRL_CELL_LEN_SHIFT\t\t\t0\n+#define HINIC_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_SHIFT\t\t16\n+#define HINIC_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_SHIFT\t\t24\n+#define HINIC_API_CMD_CELL_CTRL_XOR_CHKSUM_SHIFT\t\t56\n+\n+#define HINIC_API_CMD_CELL_CTRL_CELL_LEN_MASK\t\t\t0x3FU\n+#define HINIC_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_MASK\t\t0x3FU\n+#define HINIC_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_MASK\t\t0x3FU\n+#define HINIC_API_CMD_CELL_CTRL_XOR_CHKSUM_MASK\t\t\t0xFFU\n+\n+#define HINIC_API_CMD_CELL_CTRL_SET(val, member)\t\t\\\n+\t\t((((u64)val) & HINIC_API_CMD_CELL_CTRL_##member##_MASK) << \\\n+\t\tHINIC_API_CMD_CELL_CTRL_##member##_SHIFT)\n+\n+#define HINIC_API_CMD_CELL_CTRL_CLEAR(val, member)\t\t\\\n+\t((val) & (~((u64)HINIC_API_CMD_CELL_CTRL_##member##_MASK \\\n+\t\t<< HINIC_API_CMD_CELL_CTRL_##member##_SHIFT)))\n+\n+#define HINIC_API_CMD_DESC_API_TYPE_SHIFT\t\t\t0\n+#define HINIC_API_CMD_DESC_RD_WR_SHIFT\t\t\t\t1\n+#define HINIC_API_CMD_DESC_MGMT_BYPASS_SHIFT\t\t\t2\n+#define HINIC_API_CMD_DESC_RESP_AEQE_EN_SHIFT\t\t\t3\n+#define HINIC_API_CMD_DESC_PRIV_DATA_SHIFT\t\t\t8\n+#define HINIC_API_CMD_DESC_DEST_SHIFT\t\t\t\t32\n+#define HINIC_API_CMD_DESC_SIZE_SHIFT\t\t\t\t40\n+#define HINIC_API_CMD_DESC_XOR_CHKSUM_SHIFT\t\t\t56\n+\n+#define HINIC_API_CMD_DESC_API_TYPE_MASK\t\t\t0x1U\n+#define HINIC_API_CMD_DESC_RD_WR_MASK\t\t\t\t0x1U\n+#define HINIC_API_CMD_DESC_MGMT_BYPASS_MASK\t\t\t0x1U\n+#define HINIC_API_CMD_DESC_RESP_AEQE_EN_MASK\t\t\t0x1U\n+#define HINIC_API_CMD_DESC_DEST_MASK\t\t\t\t0x1FU\n+#define HINIC_API_CMD_DESC_SIZE_MASK\t\t\t\t0x7FFU\n+#define HINIC_API_CMD_DESC_XOR_CHKSUM_MASK\t\t\t0xFFU\n+#define HINIC_API_CMD_DESC_PRIV_DATA_MASK\t\t\t0xFFFFFFU\n+\n+#define HINIC_API_CMD_DESC_SET(val, member)\t\t\t\\\n+\t\t((((u64)val) & HINIC_API_CMD_DESC_##member##_MASK) << \\\n+\t\tHINIC_API_CMD_DESC_##member##_SHIFT)\n+\n+#define HINIC_API_CMD_DESC_CLEAR(val, member)\t\t\t\\\n+\t((val) & (~((u64)HINIC_API_CMD_DESC_##member##_MASK\t\\\n+\t\t<< HINIC_API_CMD_DESC_##member##_SHIFT)))\n+\n+#define HINIC_API_CMD_STATUS_HEADER_VALID_SHIFT\t\t\t0\n+#define HINIC_API_CMD_STATUS_HEADER_CHAIN_ID_SHIFT\t\t16\n+\n+#define HINIC_API_CMD_STATUS_HEADER_VALID_MASK\t\t\t0xFFU\n+#define HINIC_API_CMD_STATUS_HEADER_CHAIN_ID_MASK\t\t0xFFU\n+\n+#define HINIC_API_CMD_STATUS_VALID_CODE\t\t\t\t0xFF\n+\n+#define HINIC_API_CMD_STATUS_HEADER_GET(val, member)\t\t\\\n+\t      (((val) >> HINIC_API_CMD_STATUS_HEADER_##member##_SHIFT) & \\\n+\t      HINIC_API_CMD_STATUS_HEADER_##member##_MASK)\n+\n+#define HINIC_API_CMD_CHAIN_REQ_RESTART_SHIFT\t\t\t1\n+#define HINIC_API_CMD_CHAIN_REQ_WB_TRIGGER_SHIFT\t\t2\n+\n+#define HINIC_API_CMD_CHAIN_REQ_RESTART_MASK\t\t\t0x1U\n+#define HINIC_API_CMD_CHAIN_REQ_WB_TRIGGER_MASK\t\t\t0x1U\n+\n+#define HINIC_API_CMD_CHAIN_REQ_SET(val, member)\t\t\\\n+\t       (((val) & HINIC_API_CMD_CHAIN_REQ_##member##_MASK) << \\\n+\t       HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT)\n+\n+#define HINIC_API_CMD_CHAIN_REQ_GET(val, member)\t\t\\\n+\t      (((val) >> HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT) & \\\n+\t      HINIC_API_CMD_CHAIN_REQ_##member##_MASK)\n+\n+#define HINIC_API_CMD_CHAIN_REQ_CLEAR(val, member)\t\t\\\n+\t((val) & (~(HINIC_API_CMD_CHAIN_REQ_##member##_MASK\t\\\n+\t\t<< HINIC_API_CMD_CHAIN_REQ_##member##_SHIFT)))\n+\n+#define HINIC_API_CMD_CHAIN_CTRL_RESTART_EN_SHIFT\t\t1\n+#define HINIC_API_CMD_CHAIN_CTRL_XOR_ERR_SHIFT\t\t\t2\n+#define HINIC_API_CMD_CHAIN_CTRL_AEQE_EN_SHIFT\t\t\t4\n+#define HINIC_API_CMD_CHAIN_CTRL_AEQ_ID_SHIFT\t\t\t8\n+#define HINIC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_SHIFT\t\t28\n+#define HINIC_API_CMD_CHAIN_CTRL_CELL_SIZE_SHIFT\t\t30\n+\n+#define HINIC_API_CMD_CHAIN_CTRL_RESTART_EN_MASK\t\t0x1U\n+#define HINIC_API_CMD_CHAIN_CTRL_XOR_ERR_MASK\t\t\t0x1U\n+#define HINIC_API_CMD_CHAIN_CTRL_AEQE_EN_MASK\t\t\t0x1U\n+#define HINIC_API_CMD_CHAIN_CTRL_AEQ_ID_MASK\t\t\t0x3U\n+#define HINIC_API_CMD_CHAIN_CTRL_XOR_CHK_EN_MASK\t\t0x3U\n+#define HINIC_API_CMD_CHAIN_CTRL_CELL_SIZE_MASK\t\t\t0x3U\n+\n+#define HINIC_API_CMD_CHAIN_CTRL_SET(val, member)\t\t\\\n+\t(((val) & HINIC_API_CMD_CHAIN_CTRL_##member##_MASK) << \\\n+\tHINIC_API_CMD_CHAIN_CTRL_##member##_SHIFT)\n+\n+#define HINIC_API_CMD_CHAIN_CTRL_CLEAR(val, member)\t\t\\\n+\t((val) & (~(HINIC_API_CMD_CHAIN_CTRL_##member##_MASK\t\\\n+\t\t<< HINIC_API_CMD_CHAIN_CTRL_##member##_SHIFT)))\n+\n+#define HINIC_API_CMD_RESP_HEAD_VALID_MASK\t\t0xFF\n+#define HINIC_API_CMD_RESP_HEAD_VALID_CODE\t\t0xFF\n+\n+#define HINIC_API_CMD_RESP_HEADER_VALID(val)\t\\\n+\t\t(((val) & HINIC_API_CMD_RESP_HEAD_VALID_MASK) == \\\n+\t\tHINIC_API_CMD_RESP_HEAD_VALID_CODE)\n+\n+#define HINIC_API_CMD_RESP_HEAD_STATUS_SHIFT\t\t8\n+#define HINIC_API_CMD_RESP_HEAD_STATUS_MASK\t\t0xFFU\n+\n+#define HINIC_API_CMD_RESP_HEAD_ERR_CODE\t\t0x1\n+#define HINIC_API_CMD_RESP_HEAD_ERR(val)\t\\\n+\t\t((((val) >> HINIC_API_CMD_RESP_HEAD_STATUS_SHIFT) & \\\n+\t\tHINIC_API_CMD_RESP_HEAD_STATUS_MASK) == \\\n+\t\tHINIC_API_CMD_RESP_HEAD_ERR_CODE)\n+\n+#define HINIC_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT\t\t16\n+#define HINIC_API_CMD_RESP_HEAD_CHAIN_ID_MASK\t\t0xFF\n+\n+#define HINIC_API_CMD_RESP_RESERVED\t\t\t3\n+#define HINIC_API_CMD_RESP_HEAD_CHAIN_ID(val)\t\\\n+\t\t(((val) >> HINIC_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT) & \\\n+\t\tHINIC_API_CMD_RESP_HEAD_CHAIN_ID_MASK)\n+\n+#define HINIC_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT\t40\n+#define HINIC_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK\t0xFFFFFFU\n+\n+#define HINIC_API_CMD_RESP_HEAD_DRIVER_PRIV(val)\t\\\n+\t\t(u16)(((val) >> HINIC_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT) & \\\n+\t\tHINIC_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK)\n+\n+#define HINIC_API_CMD_STATUS_HEAD_VALID_MASK\t\t0xFFU\n+#define HINIC_API_CMD_STATUS_HEAD_VALID_SHIFT\t\t0\n+\n+#define HINIC_API_CMD_STATUS_HEAD_CHAIN_ID_MASK\t\t0xFFU\n+#define HINIC_API_CMD_STATUS_HEAD_CHAIN_ID_VALID_SHIFT\t16\n+\n+#define HINIC_API_CMD_STATUS_CONS_IDX_MASK\t\t0xFFFFFFU\n+#define HINIC_API_CMD_STATUS_CONS_IDX_SHIFT\t\t0\n+\n+#define HINIC_API_CMD_STATUS_FSM_MASK\t\t\t0xFU\n+#define HINIC_API_CMD_STATUS_FSM_SHIFT\t\t\t24\n+\n+#define HINIC_API_CMD_STATUS_CHKSUM_ERR_MASK\t\t0x3U\n+#define HINIC_API_CMD_STATUS_CHKSUM_ERR_SHIFT\t\t28\n+\n+#define HINIC_API_CMD_STATUS_CPLD_ERR_MASK\t\t0x1U\n+#define HINIC_API_CMD_STATUS_CPLD_ERR_SHIFT\t\t30\n+\n+#define HINIC_API_CMD_STATUS_CHAIN_ID(val) \\\n+\t\t(((val) >> HINIC_API_CMD_STATUS_HEAD_CHAIN_ID_VALID_SHIFT) & \\\n+\t\tHINIC_API_CMD_STATUS_HEAD_VALID_MASK)\n+\n+#define HINIC_API_CMD_STATUS_CONS_IDX(val) \\\n+\t\t((val) & HINIC_API_CMD_STATUS_CONS_IDX_MASK)\n+\n+#define HINIC_API_CMD_STATUS_CHKSUM_ERR(val) \\\n+\t\t(((val) >> HINIC_API_CMD_STATUS_CHKSUM_ERR_SHIFT) & \\\n+\t\tHINIC_API_CMD_STATUS_CHKSUM_ERR_MASK)\n+\n+#define HINIC_API_CMD_STATUS_GET(val, member)\t\t\t\\\n+\t\t(((val) >> HINIC_API_CMD_STATUS_##member##_SHIFT) & \\\n+\t\tHINIC_API_CMD_STATUS_##member##_MASK)\n+\n+enum hinic_api_cmd_chain_type {\n+\t/* read from mgmt cpu command with completion  */\n+\tHINIC_API_CMD_WRITE_ASYNC_TO_MGMT_CPU\t= 6,\n+\t/* PMD business api chain */\n+\tHINIC_API_CMD_PMD_WRITE_TO_MGMT         = 7,\n+\tHINIC_API_CMD_MAX\n+};\n+\n+enum hinic_node_id {\n+\tHINIC_NODE_ID_MGMT_HOST = 21,\n+};\n+\n+struct hinic_api_cmd_status {\n+\tu64 header;\n+\tu32 buf_desc;\n+\tu32 cell_addr_hi;\n+\tu32 cell_addr_lo;\n+\tu32 rsvd0;\n+\tu64 rsvd1;\n+};\n+\n+/* HW struct */\n+struct hinic_api_cmd_cell {\n+\tu64 ctrl;\n+\n+\t/* address is 64 bit in HW struct */\n+\tu64 next_cell_paddr;\n+\n+\tu64 desc;\n+\n+\t/* HW struct */\n+\tunion {\n+\t\tstruct {\n+\t\t\tu64 hw_cmd_paddr;\n+\t\t} write;\n+\n+\t\tstruct {\n+\t\t\tu64 hw_wb_resp_paddr;\n+\t\t\tu64 hw_cmd_paddr;\n+\t\t} read;\n+\t};\n+};\n+\n+struct hinic_api_cmd_cell_ctxt {\n+\tdma_addr_t\t\t\tcell_paddr;\n+\tstruct hinic_api_cmd_cell\t*cell_vaddr;\n+\n+\tdma_addr_t\t\t\tcell_paddr_free;\n+\tvoid\t\t\t\t*cell_vaddr_free;\n+\n+\tdma_addr_t\t\t\tapi_cmd_paddr;\n+\tvoid\t\t\t\t*api_cmd_vaddr;\n+\n+\tdma_addr_t\t\t\tapi_cmd_paddr_free;\n+\tvoid\t\t\t\t*api_cmd_vaddr_free;\n+\n+\tint\t\t\t\tstatus;\n+\n+\tu32\t\t\t\tsaved_prod_idx;\n+};\n+\n+struct hinic_api_cmd_chain_attr {\n+\tstruct hinic_hwdev\t\t*hwdev;\n+\tenum hinic_api_cmd_chain_type\tchain_type;\n+\n+\tu32\t\t\t\tnum_cells;\n+\tu16\t\t\t\trsp_size;\n+\tu16\t\t\t\tcell_size;\n+};\n+\n+struct hinic_api_cmd_chain {\n+\tstruct hinic_hwdev\t\t*hwdev;\n+\tenum hinic_api_cmd_chain_type\tchain_type;\n+\n+\tu32\t\t\t\tnum_cells;\n+\tu16\t\t\t\tcell_size;\n+\tu16\t\t\t\trsp_size;\n+\n+\t/* HW members is 24 bit format */\n+\tu32\t\t\t\tprod_idx;\n+\tu32\t\t\t\tcons_idx;\n+\n+\t/* Async cmd can not be scheduled */\n+\tspinlock_t\t\t\tasync_lock;\n+\n+\tdma_addr_t\t\t\twb_status_paddr;\n+\tstruct hinic_api_cmd_status\t*wb_status;\n+\n+\tdma_addr_t\t\t\thead_cell_paddr;\n+\tstruct hinic_api_cmd_cell\t*head_node;\n+\n+\tstruct hinic_api_cmd_cell_ctxt\t*cell_ctxt;\n+\tstruct hinic_api_cmd_cell\t*curr_node;\n+};\n+\n+int hinic_api_cmd_write(struct hinic_api_cmd_chain *chain,\n+\t\t\tenum hinic_node_id dest, void *cmd, u16 size);\n+\n+int hinic_api_cmd_init(struct hinic_hwdev *hwdev,\n+\t\t\t       struct hinic_api_cmd_chain **chain);\n+\n+void hinic_api_cmd_free(struct hinic_api_cmd_chain **chain);\n+\n+#endif /* _HINIC_PMD_API_CMD_H_ */\ndiff --git a/drivers/net/hinic/base/hinic_pmd_cmdq.c b/drivers/net/hinic/base/hinic_pmd_cmdq.c\nnew file mode 100644\nindex 000000000..824b8542a\n--- /dev/null\n+++ b/drivers/net/hinic/base/hinic_pmd_cmdq.c\n@@ -0,0 +1,901 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2017 Huawei Technologies Co., Ltd\n+ */\n+\n+#include \"hinic_pmd_dpdev.h\"\n+\n+#define CMDQ_CMD_TIMEOUT\t\t\t\t5000 /* 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_QUEUE_TYPE_SHIFT\t\t\t23\n+#define CMDQ_DB_INFO_CMDQ_TYPE_SHIFT\t\t\t24\n+#define CMDQ_DB_INFO_SRC_TYPE_SHIFT\t\t\t27\n+\n+#define CMDQ_DB_INFO_HI_PROD_IDX_MASK\t\t\t0xFFU\n+#define CMDQ_DB_INFO_QUEUE_TYPE_MASK\t\t\t0x1U\n+#define CMDQ_DB_INFO_CMDQ_TYPE_MASK\t\t\t0x7U\n+#define CMDQ_DB_INFO_SRC_TYPE_MASK\t\t\t0x1FU\n+\n+#define CMDQ_DB_INFO_SET(val, member)\t\t\t\\\n+\t\t\t\t(((val) & CMDQ_DB_INFO_##member##_MASK) \\\n+\t\t\t\t<< CMDQ_DB_INFO_##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\t\\\n+\t\t\t\t(((val) & CMDQ_CTRL_##member##_MASK) \\\n+\t\t\t\t\t<< CMDQ_CTRL_##member##_SHIFT)\n+\n+#define CMDQ_CTRL_GET(val, member)\t\t\t\\\n+\t\t\t\t(((val) >> CMDQ_CTRL_##member##_SHIFT) \\\n+\t\t\t\t\t& CMDQ_CTRL_##member##_MASK)\n+\n+#define CMDQ_CTRL_CLEAR(val, member)\t\t\t\\\n+\t\t\t\t((val) & (~(CMDQ_CTRL_##member##_MASK \\\n+\t\t\t\t\t<< CMDQ_CTRL_##member##_SHIFT)))\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\t\\\n+\t\t\t\t(((val) & CMDQ_WQE_HEADER_##member##_MASK) \\\n+\t\t\t\t\t<< CMDQ_WQE_HEADER_##member##_SHIFT)\n+\n+#define CMDQ_WQE_HEADER_GET(val, member)\t\t\\\n+\t\t\t\t(((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) \\\n+\t\t\t\t\t& CMDQ_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\t56\n+#define CMDQ_CTXT_CEQ_ARM_SHIFT\t\t\t\t61\n+#define CMDQ_CTXT_CEQ_EN_SHIFT\t\t\t\t62\n+#define CMDQ_CTXT_HW_BUSY_BIT_SHIFT\t\t\t63\n+\n+#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK\t\t0xFFFFFFFFFFFFF\n+#define CMDQ_CTXT_EQ_ID_MASK\t\t\t\t0x1F\n+#define CMDQ_CTXT_CEQ_ARM_MASK\t\t\t\t0x1\n+#define CMDQ_CTXT_CEQ_EN_MASK\t\t\t\t0x1\n+#define CMDQ_CTXT_HW_BUSY_BIT_MASK\t\t\t0x1\n+\n+#define CMDQ_CTXT_PAGE_INFO_SET(val, member)\t\t\\\n+\t\t\t\t(((u64)(val) & CMDQ_CTXT_##member##_MASK) \\\n+\t\t\t\t\t<< CMDQ_CTXT_##member##_SHIFT)\n+\n+#define CMDQ_CTXT_PAGE_INFO_CLEAR(val, member)\t\t\\\n+\t\t\t\t((val) & (~((u64)CMDQ_CTXT_##member##_MASK \\\n+\t\t\t\t\t<< CMDQ_CTXT_##member##_SHIFT)))\n+\n+#define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT\t\t\t0\n+#define CMDQ_CTXT_CI_SHIFT\t\t\t\t52\n+\n+#define CMDQ_CTXT_WQ_BLOCK_PFN_MASK\t\t\t0xFFFFFFFFFFFFF\n+#define CMDQ_CTXT_CI_MASK\t\t\t\t0xFFF\n+\n+#define CMDQ_CTXT_BLOCK_INFO_SET(val, member)\t\t\\\n+\t\t\t\t(((u64)(val) & CMDQ_CTXT_##member##_MASK) \\\n+\t\t\t\t\t<< CMDQ_CTXT_##member##_SHIFT)\n+\n+#define CMDQ_CTXT_BLOCK_INFO_CLEAR(val, member)\t\t\\\n+\t\t\t\t((val) & (~((u64)CMDQ_CTXT_##member##_MASK \\\n+\t\t\t\t\t<< CMDQ_CTXT_##member##_SHIFT)))\n+\n+#define SAVED_DATA_ARM_SHIFT\t\t\t31\n+\n+#define SAVED_DATA_ARM_MASK\t\t\t0x1U\n+\n+#define SAVED_DATA_SET(val, member)\t\t\\\n+\t\t\t\t(((val) & SAVED_DATA_##member##_MASK) \\\n+\t\t\t\t\t<< SAVED_DATA_##member##_SHIFT)\n+\n+#define SAVED_DATA_CLEAR(val, member)\t\t\\\n+\t\t\t\t((val) & (~(SAVED_DATA_##member##_MASK \\\n+\t\t\t\t\t<< SAVED_DATA_##member##_SHIFT)))\n+\n+#define WQE_ERRCODE_VAL_SHIFT\t\t\t20\n+\n+#define WQE_ERRCODE_VAL_MASK\t\t\t0xF\n+\n+#define WQE_ERRCODE_GET(val, member)\t\t\\\n+\t\t\t\t(((val) >> WQE_ERRCODE_##member##_SHIFT) \\\n+\t\t\t\t\t& 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 hinic_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\\\n+\t(((u8 *)(db_base) + HINIC_DB_OFF) + 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 HINIC_CMDQ_WQ_BUF_SIZE\t4096\n+\n+#define WQE_NUM_WQEBBS(wqe_size, wq)\t\\\n+\t\t((u16)(ALIGN((u32)(wqe_size),\t\\\n+\t\t(wq)->wqebb_size) / (wq)->wqebb_size))\n+\n+#define cmdq_to_cmdqs(cmdq)\tcontainer_of((cmdq) - (cmdq)->cmdq_type, \\\n+\t\t\t\tstruct hinic_cmdqs, cmdq[0])\n+\n+#define WAIT_CMDQ_ENABLE_TIMEOUT\t300\n+\n+enum cmdq_scmd_type {\n+\tCMDQ_SET_ARM_CMD = 2,\n+};\n+\n+enum cmdq_wqe_type {\n+\tWQE_LCMD_TYPE,\n+\tWQE_SCMD_TYPE,\n+};\n+\n+enum ctrl_sect_len {\n+\tCTRL_SECT_LEN = 1,\n+\tCTRL_DIRECT_SECT_LEN = 2,\n+};\n+\n+enum bufdesc_len {\n+\tBUFDESC_LCMD_LEN = 2,\n+\tBUFDESC_SCMD_LEN = 3,\n+};\n+\n+enum data_format {\n+\tDATA_SGE,\n+};\n+\n+enum completion_format {\n+\tCOMPLETE_DIRECT,\n+\tCOMPLETE_SGE,\n+};\n+\n+enum completion_request {\n+\tCEQ_SET = 1,\n+};\n+\n+enum cmdq_cmd_type {\n+\tSYNC_CMD_DIRECT_RESP,\n+\tSYNC_CMD_SGE_RESP,\n+\tASYNC_CMD,\n+};\n+\n+static int init_cmdq(struct hinic_cmdq *cmdq, struct hinic_hwdev *hwdev,\n+\t\t     struct hinic_wq *wq, enum hinic_cmdq_type q_type);\n+static void cmdq_init_queue_ctxt(struct hinic_cmdq *cmdq,\n+\t\t\t\t struct hinic_cmdq_ctxt *cmdq_ctxt);\n+static void free_cmdq(struct hinic_hwdev *hwdev, struct hinic_cmdq *cmdq);\n+static void hinic_cmdqs_free(struct hinic_hwdev *hwdev);\n+\n+bool hinic_cmdq_idle(struct hinic_cmdq *cmdq)\n+{\n+\tstruct hinic_wq *wq = cmdq->wq;\n+\n+\treturn ((wq->delta) == wq->q_depth ? true : false);\n+}\n+\n+struct hinic_cmd_buf *hinic_alloc_cmd_buf(void *hwdev)\n+{\n+\tstruct hinic_cmdqs *cmdqs = ((struct hinic_hwdev *)hwdev)->cmdqs;\n+\tstruct hinic_cmd_buf *cmd_buf;\n+\n+\tcmd_buf = kzalloc(sizeof(*cmd_buf), GFP_KERNEL);\n+\tif (!cmd_buf) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate cmd buffer failed\");\n+\t\treturn NULL;\n+\t}\n+\n+\tcmd_buf->buf = pci_pool_alloc(cmdqs->cmd_buf_pool, GFP_KERNEL,\n+\t\t\t\t      &cmd_buf->dma_addr);\n+\tif (!cmd_buf->buf) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate cmd from the pool failed\");\n+\t\tgoto alloc_pci_buf_err;\n+\t}\n+\n+\treturn cmd_buf;\n+\n+alloc_pci_buf_err:\n+\tkfree(cmd_buf);\n+\treturn NULL;\n+}\n+\n+void hinic_free_cmd_buf(void *hwdev, struct hinic_cmd_buf *cmd_buf)\n+{\n+\tstruct hinic_cmdqs *cmdqs = ((struct hinic_hwdev *)hwdev)->cmdqs;\n+\n+\tpci_pool_free(cmdqs->cmd_buf_pool, cmd_buf->buf, cmd_buf->dma_addr);\n+\tkfree(cmd_buf);\n+}\n+\n+static int cmdq_wqe_size(enum cmdq_wqe_type wqe_type)\n+{\n+\tint 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+\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+\t}\n+\n+\treturn wqe_size;\n+}\n+\n+static void cmdq_set_completion(struct hinic_cmdq_completion *complete,\n+\t\t\t\t\tstruct hinic_cmd_buf *buf_out)\n+{\n+\tstruct hinic_sge_resp *sge_resp = &complete->sge_resp;\n+\n+\thinic_set_sge(&sge_resp->sge, buf_out->dma_addr,\n+\t\t      HINIC_CMDQ_BUF_SIZE);\n+}\n+\n+static void cmdq_set_lcmd_bufdesc(struct hinic_cmdq_wqe_lcmd *wqe,\n+\t\t\t\t\tstruct hinic_cmd_buf *buf_in)\n+{\n+\thinic_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size);\n+}\n+\n+static void cmdq_fill_db(struct hinic_cmdq_db *db,\n+\t\t\tenum hinic_cmdq_type cmdq_type, u16 prod_idx)\n+{\n+\tdb->db_info = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX) |\n+\t\t\tCMDQ_DB_INFO_SET(HINIC_DB_CMDQ_TYPE, QUEUE_TYPE) |\n+\t\t\tCMDQ_DB_INFO_SET(cmdq_type, CMDQ_TYPE)\t\t|\n+\t\t\tCMDQ_DB_INFO_SET(HINIC_DB_SRC_CMDQ_TYPE, SRC_TYPE);\n+}\n+\n+static void cmdq_set_db(struct hinic_cmdq *cmdq,\n+\t\t\tenum hinic_cmdq_type cmdq_type, u16 prod_idx)\n+{\n+\tstruct hinic_cmdq_db db;\n+\n+\tcmdq_fill_db(&db, cmdq_type, prod_idx);\n+\n+\t/* The data that is written to HW should be in Big Endian Format */\n+\tdb.db_info = cpu_to_be32(db.db_info);\n+\n+\trte_wmb();\t/* write all before the doorbell */\n+\n+\twritel(db.db_info, 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 hinic_cmdq_wqe *wqe, int wrapped,\n+\t\t\t\t  enum hinic_ack_type ack_type,\n+\t\t\t\t  enum hinic_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 hinic_ctrl *ctrl;\n+\tenum ctrl_sect_len ctrl_len;\n+\tstruct hinic_cmdq_wqe_lcmd *wqe_lcmd;\n+\tstruct hinic_cmdq_wqe_scmd *wqe_scmd;\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)\t\t|\n+\t\t\tCMDQ_CTRL_SET(cmd, CMD)\t\t\t|\n+\t\t\tCMDQ_CTRL_SET(mod, MOD)\t\t\t|\n+\t\t\tCMDQ_CTRL_SET(ack_type, 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)\t|\n+\t\tCMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ)\t|\n+\t\tCMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) |\n+\t\tCMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN)\t\t|\n+\t\tCMDQ_WQE_HEADER_SET((u32)wrapped, HW_BUSY_BIT);\n+\n+\tif (cmd == CMDQ_SET_ARM_CMD && mod == HINIC_MOD_COMM) {\n+\t\tsaved_data &= SAVED_DATA_CLEAR(saved_data, ARM);\n+\t\tWQE_HEADER(wqe)->saved_data = saved_data |\n+\t\t\t\t\t\tSAVED_DATA_SET(1, ARM);\n+\t} else {\n+\t\tsaved_data &= SAVED_DATA_CLEAR(saved_data, ARM);\n+\t\tWQE_HEADER(wqe)->saved_data = saved_data;\n+\t}\n+}\n+\n+static void cmdq_set_lcmd_wqe(struct hinic_cmdq_wqe *wqe,\n+\t\t\t      enum cmdq_cmd_type cmd_type,\n+\t\t\t      struct hinic_cmd_buf *buf_in,\n+\t\t\t      struct hinic_cmd_buf *buf_out, int wrapped,\n+\t\t\t      enum hinic_ack_type ack_type,\n+\t\t\t      enum hinic_mod_type mod, u8 cmd, u16 prod_idx)\n+{\n+\tstruct hinic_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_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 SYNC_CMD_DIRECT_RESP:\n+\t\tcomplete_format = COMPLETE_DIRECT;\n+\t\twqe_lcmd->completion.direct_resp = 0;\n+\t\tbreak;\n+\tcase ASYNC_CMD:\n+\t\tcomplete_format = COMPLETE_DIRECT;\n+\t\twqe_lcmd->completion.direct_resp = 0;\n+\n+\t\twqe_lcmd->buf_desc.saved_async_buf = (u64)(buf_in);\n+\t\tbreak;\n+\t}\n+\n+\tcmdq_prepare_wqe_ctrl(wqe, wrapped, ack_type, mod, cmd,\n+\t\t\t      prod_idx, complete_format, DATA_SGE,\n+\t\t\t      BUFDESC_LCMD_LEN);\n+\n+\tcmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in);\n+}\n+\n+static int cmdq_params_valid(struct hinic_cmd_buf *buf_in)\n+{\n+\tif (buf_in->size > HINIC_CMDQ_MAX_DATA_SIZE) {\n+\t\tPMD_DRV_LOG(ERR, \"Invalid CMDQ buffer size\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int wait_cmdqs_enable(struct hinic_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 & HINIC_CMDQ_ENABLE)\n+\t\t\treturn 0;\n+\n+\t} while (time_before(jiffies, end));\n+\n+\treturn -EBUSY;\n+}\n+\n+static void cmdq_update_errcode(struct hinic_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 hinic_cmdq *cmdq,\n+\t\t\t\t   struct hinic_cmdq_wqe *wqe)\n+{\n+\tstruct hinic_cmdq_wqe_lcmd *wqe_lcmd;\n+\tstruct hinic_cmdq_inline_wqe *inline_wqe;\n+\tstruct hinic_cmdq_wqe_scmd *wqe_scmd;\n+\tstruct hinic_ctrl *ctrl;\n+\tu32 header_info = be32_to_cpu(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\twqe_lcmd = &wqe->wqe_lcmd;\n+\t\tctrl = &wqe_lcmd->ctrl;\n+\t} else {\n+\t\tinline_wqe = &wqe->inline_wqe;\n+\t\twqe_scmd = &inline_wqe->wqe_scmd;\n+\t\tctrl = &wqe_scmd->ctrl;\n+\t}\n+\n+\t/* clear HW busy bit */\n+\tctrl->ctrl_info = 0;\n+\n+\trte_wmb();\t/* verify wqe is clear */\n+\n+\tnum_wqebbs = WQE_NUM_WQEBBS(wqe_size, cmdq->wq);\n+\thinic_put_wqe(cmdq->wq, num_wqebbs);\n+}\n+\n+static int hinic_set_cmdq_ctxts(struct hinic_hwdev *hwdev)\n+{\n+\tstruct hinic_cmdqs *cmdqs = hwdev->cmdqs;\n+\tstruct hinic_cmdq_ctxt *cmdq_ctxt;\n+\tenum hinic_cmdq_type cmdq_type;\n+\tu16 in_size;\n+\tint err;\n+\n+\tcmdq_type = HINIC_CMDQ_SYNC;\n+\tfor (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {\n+\t\tcmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;\n+\t\tcmdq_ctxt->resp_aeq_num = HINIC_AEQ1;\n+\t\tin_size = sizeof(*cmdq_ctxt);\n+\t\terr = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,\n+\t\t\t\t\t     HINIC_MGMT_CMD_CMDQ_CTXT_SET,\n+\t\t\t\t\t     cmdq_ctxt, in_size, NULL,\n+\t\t\t\t\t     NULL, 0);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Set cmdq ctxt failed\");\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\t}\n+\n+\tcmdqs->status |= HINIC_CMDQ_ENABLE;\n+\n+\treturn 0;\n+}\n+\n+void hinic_comm_cmdqs_free(struct hinic_hwdev *hwdev)\n+{\n+\thinic_cmdqs_free(hwdev);\n+}\n+\n+int hinic_reinit_cmdq_ctxts(struct hinic_hwdev *hwdev)\n+{\n+\tstruct hinic_cmdqs *cmdqs = hwdev->cmdqs;\n+\tenum hinic_cmdq_type cmdq_type;\n+\n+\tcmdq_type = HINIC_CMDQ_SYNC;\n+\tfor (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {\n+\t\tcmdqs->cmdq[cmdq_type].wrapped = 1;\n+\t\thinic_wq_wqe_pg_clear(cmdqs->cmdq[cmdq_type].wq);\n+\t}\n+\n+\treturn hinic_set_cmdq_ctxts(hwdev);\n+}\n+\n+static int hinic_cmdqs_init(struct hinic_hwdev *hwdev)\n+{\n+\tstruct hinic_cmdqs *cmdqs;\n+\tstruct hinic_cmdq_ctxt *cmdq_ctxt;\n+\tenum hinic_cmdq_type type, cmdq_type;\n+\tsize_t saved_wqs_size;\n+\tint err;\n+\n+\tcmdqs = kzalloc(sizeof(*cmdqs), GFP_KERNEL);\n+\tif (!cmdqs)\n+\t\treturn -ENOMEM;\n+\n+\thwdev->cmdqs = cmdqs;\n+\tcmdqs->hwdev = hwdev;\n+\n+\tsaved_wqs_size = HINIC_MAX_CMDQ_TYPES * sizeof(struct hinic_wq);\n+\tcmdqs->saved_wqs = kzalloc(saved_wqs_size, GFP_KERNEL);\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+\tcmdqs->cmd_buf_pool = dma_pool_create(\"hinic_cmdq\", hwdev->dev_hdl,\n+\t\t\t\t\t      HINIC_CMDQ_BUF_SIZE,\n+\t\t\t\t\t      HINIC_CMDQ_BUF_SIZE, 0ULL);\n+\tif (!cmdqs->cmd_buf_pool) {\n+\t\tPMD_DRV_LOG(ERR, \"Create cmdq buffer pool failed\");\n+\t\terr = -ENOMEM;\n+\t\tgoto pool_create_err;\n+\t}\n+\n+\terr = hinic_cmdq_alloc(cmdqs->saved_wqs, hwdev->dev_hdl,\n+\t\t\t       HINIC_MAX_CMDQ_TYPES, HINIC_CMDQ_WQ_BUF_SIZE,\n+\t\t\t       CMDQ_WQEBB_SHIFT, HINIC_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 = HINIC_CMDQ_SYNC;\n+\tfor (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {\n+\t\terr = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev,\n+\t\t\t\t&cmdqs->saved_wqs[cmdq_type], cmdq_type);\n+\t\tif (err) {\n+\t\t\tPMD_DRV_LOG(ERR, \"Initialize cmdq failed\");\n+\t\t\tgoto init_cmdq_err;\n+\t\t}\n+\n+\t\tcmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;\n+\t\tcmdq_init_queue_ctxt(&cmdqs->cmdq[cmdq_type], cmdq_ctxt);\n+\t}\n+\n+\terr = hinic_set_cmdq_ctxts(hwdev);\n+\tif (err)\n+\t\tgoto init_cmdq_err;\n+\n+\treturn 0;\n+\n+init_cmdq_err:\n+\ttype = HINIC_CMDQ_SYNC;\n+\tfor ( ; type < cmdq_type; type++)\n+\t\tfree_cmdq(hwdev, &cmdqs->cmdq[type]);\n+\n+\thinic_cmdq_free(hwdev->dev_hdl, cmdqs->saved_wqs, HINIC_MAX_CMDQ_TYPES);\n+\n+cmdq_alloc_err:\n+\tdma_pool_destroy(cmdqs->cmd_buf_pool);\n+\n+pool_create_err:\n+\tkfree(cmdqs->saved_wqs);\n+\n+alloc_wqs_err:\n+\tkfree(cmdqs);\n+\n+\treturn err;\n+}\n+\n+static void hinic_cmdqs_free(struct hinic_hwdev *hwdev)\n+{\n+\tstruct hinic_cmdqs *cmdqs = hwdev->cmdqs;\n+\tenum hinic_cmdq_type cmdq_type = HINIC_CMDQ_SYNC;\n+\n+\tcmdqs->status &= ~HINIC_CMDQ_ENABLE;\n+\n+\tfor ( ; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++)\n+\t\tfree_cmdq(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type]);\n+\n+\thinic_cmdq_free(hwdev->dev_hdl, cmdqs->saved_wqs,\n+\t\t\tHINIC_MAX_CMDQ_TYPES);\n+\n+\tdma_pool_destroy(cmdqs->cmd_buf_pool);\n+\n+\tkfree(cmdqs->saved_wqs);\n+\n+\tkfree(cmdqs);\n+}\n+\n+static int hinic_set_cmdq_depth(struct hinic_hwdev *hwdev, u16 cmdq_depth)\n+{\n+\tstruct hinic_root_ctxt root_ctxt;\n+\n+\tmemset(&root_ctxt, 0, sizeof(root_ctxt));\n+\troot_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;\n+\troot_ctxt.func_idx = hinic_global_func_id(hwdev);\n+\troot_ctxt.ppf_idx = hinic_ppf_idx(hwdev);\n+\troot_ctxt.set_cmdq_depth = 1;\n+\troot_ctxt.cmdq_depth = (u8)ilog2(cmdq_depth);\n+\treturn hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,\n+\t\t\t\t      HINIC_MGMT_CMD_VAT_SET,\n+\t\t\t\t      &root_ctxt, sizeof(root_ctxt),\n+\t\t\t\t      NULL, NULL, 0);\n+}\n+\n+int hinic_comm_cmdqs_init(struct hinic_hwdev *hwdev)\n+{\n+\tint err;\n+\n+\terr = hinic_cmdqs_init(hwdev);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Init cmd queues failed\");\n+\t\treturn err;\n+\t}\n+\n+\terr = hinic_set_cmdq_depth(hwdev, HINIC_CMDQ_DEPTH);\n+\tif (err) {\n+\t\tPMD_DRV_LOG(ERR, \"Set cmdq depth failed\");\n+\t\tgoto set_cmdq_depth_err;\n+\t}\n+\n+\treturn 0;\n+\n+set_cmdq_depth_err:\n+\thinic_cmdqs_free(hwdev);\n+\n+\treturn err;\n+}\n+\n+static int init_cmdq(struct hinic_cmdq *cmdq, struct hinic_hwdev *hwdev,\n+\t\t     struct hinic_wq *wq, enum hinic_cmdq_type q_type)\n+{\n+\tvoid __iomem *db_base;\n+\tint err = 0;\n+\tsize_t errcode_size;\n+\tsize_t cmd_infos_size;\n+\n+\tcmdq->wq = wq;\n+\tcmdq->cmdq_type = q_type;\n+\tcmdq->wrapped = 1;\n+\n+\tspin_lock_init(&cmdq->cmdq_lock);\n+\n+\terrcode_size = wq->q_depth * sizeof(*cmdq->errcode);\n+\tcmdq->errcode = kzalloc(errcode_size, GFP_KERNEL);\n+\tif (!cmdq->errcode) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate errcode for cmdq failed\");\n+\t\tspin_lock_deinit(&cmdq->cmdq_lock);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tcmd_infos_size = wq->q_depth * sizeof(*cmdq->cmd_infos);\n+\tcmdq->cmd_infos = kzalloc(cmd_infos_size, GFP_KERNEL);\n+\tif (!cmdq->cmd_infos) {\n+\t\tPMD_DRV_LOG(ERR, \"Allocate errcode for cmdq failed\");\n+\t\terr = -ENOMEM;\n+\t\tgoto cmd_infos_err;\n+\t}\n+\n+\terr = hinic_alloc_db_addr(hwdev, &db_base, NULL);\n+\tif (err)\n+\t\tgoto alloc_db_err;\n+\n+\tcmdq->db_base = (u8 *)db_base;\n+\treturn 0;\n+\n+alloc_db_err:\n+\tkfree(cmdq->cmd_infos);\n+\n+cmd_infos_err:\n+\tkfree(cmdq->errcode);\n+\tspin_lock_deinit(&cmdq->cmdq_lock);\n+\n+\treturn err;\n+}\n+\n+static void free_cmdq(struct hinic_hwdev *hwdev, struct hinic_cmdq *cmdq)\n+{\n+\thinic_free_db_addr(hwdev, cmdq->db_base, NULL);\n+\tkfree(cmdq->cmd_infos);\n+\tkfree(cmdq->errcode);\n+\tspin_lock_deinit(&cmdq->cmdq_lock);\n+}\n+\n+static void cmdq_init_queue_ctxt(struct hinic_cmdq *cmdq,\n+\t\t\t\t struct hinic_cmdq_ctxt *cmdq_ctxt)\n+{\n+\tstruct hinic_cmdqs *cmdqs = (struct hinic_cmdqs *)cmdq_to_cmdqs(cmdq);\n+\tstruct hinic_hwdev *hwdev = cmdqs->hwdev;\n+\tstruct hinic_wq *wq = cmdq->wq;\n+\tstruct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info;\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, HINIC_PAGE_SIZE);\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(1, CEQ_EN)\t|\n+\t\tCMDQ_CTXT_PAGE_INFO_SET(0, CEQ_ARM)\t|\n+\t\tCMDQ_CTXT_PAGE_INFO_SET(HINIC_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+\tcmdq_ctxt->func_idx = HINIC_HWIF_GLOBAL_IDX(hwdev->hwif);\n+\tcmdq_ctxt->ppf_idx  = HINIC_HWIF_PPF_IDX(hwdev->hwif);\n+\tcmdq_ctxt->cmdq_id  = cmdq->cmdq_type;\n+}\n+\n+static int hinic_cmdq_poll_msg(struct hinic_cmdq *cmdq, u32 timeout)\n+{\n+\tstruct hinic_cmdq_wqe *wqe;\n+\tstruct hinic_cmdq_wqe_lcmd *wqe_lcmd;\n+\tstruct hinic_ctrl *ctrl;\n+\tstruct hinic_cmdq_cmd_info *cmd_info;\n+\tu32 status_info, ctrl_info;\n+\tu16 ci;\n+\tint errcode;\n+\tunsigned long end;\n+\tint done = 0;\n+\tint rc = 0;\n+\n+\twqe = (struct hinic_cmdq_wqe *)hinic_read_wqe(cmdq->wq, 1, &ci);\n+\tif (wqe == NULL) {\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+\t/* this cmd has not been filled and send to hw, or get TMO msg ack*/\n+\tif (cmd_info->cmd_type == HINIC_CMD_TYPE_NONE) {\n+\t\tPMD_DRV_LOG(ERR, \"Cmdq msg has not been filled and send to hw, or get TMO msg ack. cmdq ci: %u\",\n+\t\t\t    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+\n+\tdo {\n+\t\tctrl_info = be32_to_cpu((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 = be32_to_cpu(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\trc = 0;\n+\t} else {\n+\t\tPMD_DRV_LOG(ERR, \"Poll cmdq msg time out, ci: %u\", ci);\n+\t\trc = -ETIMEDOUT;\n+\t}\n+\n+\t/* set this cmd invalid */\n+\tcmd_info->cmd_type = HINIC_CMD_TYPE_NONE;\n+\n+\treturn rc;\n+}\n+\n+static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq,\n+\t\t\t\t     enum hinic_ack_type ack_type,\n+\t\t\t\t     enum hinic_mod_type mod, u8 cmd,\n+\t\t\t\t     struct hinic_cmd_buf *buf_in,\n+\t\t\t\t     u64 *out_param, u32 timeout)\n+{\n+\tstruct hinic_wq *wq = cmdq->wq;\n+\tstruct hinic_cmdq_wqe *curr_wqe, wqe;\n+\tstruct hinic_cmdq_wqe_lcmd *wqe_lcmd;\n+\tu16 curr_prod_idx, next_prod_idx, num_wqebbs;\n+\tint wrapped, wqe_size = cmdq_wqe_size(WQE_LCMD_TYPE);\n+\tu32 timeo;\n+\tint err;\n+\n+\tnum_wqebbs = WQE_NUM_WQEBBS(wqe_size, wq);\n+\n+\t/* Keep wrapped and doorbell index correct. */\n+\tspin_lock(&cmdq->cmdq_lock);\n+\n+\tcurr_wqe = (struct hinic_cmdq_wqe *)hinic_get_wqe(cmdq->wq, num_wqebbs,\n+\t\t\t\t\t\t\t  &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, ack_type, mod, cmd, curr_prod_idx);\n+\n+\t/* The data that is written to HW should be in Big Endian Format */\n+\thinic_cpu_to_be32(&wqe, wqe_size);\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 = HINIC_CMD_TYPE_NORMAL;\n+\n+\tcmdq_set_db(cmdq, HINIC_CMDQ_SYNC, next_prod_idx);\n+\n+\ttimeo = msecs_to_jiffies(timeout ? timeout : CMDQ_CMD_TIMEOUT);\n+\terr = hinic_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\tcurr_prod_idx);\n+\t\terr = -ETIMEDOUT;\n+\t\tgoto cmdq_unlock;\n+\t}\n+\n+\trte_smp_rmb();\t/* 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] > 1) {\n+\t\terr = cmdq->errcode[curr_prod_idx];\n+\t\tgoto cmdq_unlock;\n+\t}\n+\n+cmdq_unlock:\n+\tspin_unlock(&cmdq->cmdq_lock);\n+\n+\treturn err;\n+}\n+\n+int hinic_cmdq_direct_resp(void *hwdev, enum hinic_ack_type ack_type,\n+\t\t\t   enum hinic_mod_type mod, u8 cmd,\n+\t\t\t   struct hinic_cmd_buf *buf_in,\n+\t\t\t   u64 *out_param, u32 timeout)\n+{\n+\tstruct hinic_cmdqs *cmdqs = ((struct hinic_hwdev *)hwdev)->cmdqs;\n+\tint err = cmdq_params_valid(buf_in);\n+\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 disable\");\n+\t\treturn err;\n+\t}\n+\n+\treturn cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC_CMDQ_SYNC],\n+\t\t\t\t\t ack_type, mod, cmd, buf_in,\n+\t\t\t\t\t out_param, timeout);\n+}\ndiff --git a/drivers/net/hinic/base/hinic_pmd_cmdq.h b/drivers/net/hinic/base/hinic_pmd_cmdq.h\nnew file mode 100644\nindex 000000000..f4b74e711\n--- /dev/null\n+++ b/drivers/net/hinic/base/hinic_pmd_cmdq.h\n@@ -0,0 +1,190 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2017 Huawei Technologies Co., Ltd\n+ */\n+\n+#ifndef _HINIC_PMD_CMDQ_H_\n+#define _HINIC_PMD_CMDQ_H_\n+\n+#define HINIC_DB_OFF\t\t\t0x00000800\n+\n+#define HINIC_SCMD_DATA_LEN\t\t16\n+\n+/* hiovs pmd use 64, kernel l2nic use 4096 */\n+#define\tHINIC_CMDQ_DEPTH\t\t64\n+\n+#define\tHINIC_CMDQ_BUF_SIZE\t\t2048U\n+#define HINIC_CMDQ_BUF_HW_RSVD\t\t8\n+#define HINIC_CMDQ_MAX_DATA_SIZE\t(HINIC_CMDQ_BUF_SIZE\t\\\n+\t\t\t\t\t - HINIC_CMDQ_BUF_HW_RSVD)\n+\n+enum hinic_cmdq_type {\n+\tHINIC_CMDQ_SYNC,\n+\tHINIC_CMDQ_ASYNC,\n+\tHINIC_MAX_CMDQ_TYPES,\n+};\n+\n+enum hinic_db_src_type {\n+\tHINIC_DB_SRC_CMDQ_TYPE,\n+\tHINIC_DB_SRC_L2NIC_SQ_TYPE,\n+};\n+\n+enum hinic_cmdq_db_type {\n+\tHINIC_DB_SQ_RQ_TYPE,\n+\tHINIC_DB_CMDQ_TYPE,\n+};\n+\n+/* CMDQ WQE CTRLS */\n+struct hinic_cmdq_header {\n+\tu32\theader_info;\n+\tu32\tsaved_data;\n+};\n+\n+struct hinic_scmd_bufdesc {\n+\tu32\tbuf_len;\n+\tu32\trsvd;\n+\tu8\tdata[HINIC_SCMD_DATA_LEN];\n+};\n+\n+struct hinic_lcmd_bufdesc {\n+\tstruct hinic_sge\tsge;\n+\tu32\t\t\trsvd1;\n+\tu64\t\t\tsaved_async_buf;\n+\tu64\t\t\trsvd3;\n+};\n+\n+struct hinic_cmdq_db {\n+\tu32\tdb_info;\n+\tu32\trsvd;\n+};\n+\n+struct hinic_status {\n+\tu32 status_info;\n+};\n+\n+struct hinic_ctrl {\n+\tu32 ctrl_info;\n+};\n+\n+struct hinic_sge_resp {\n+\tstruct hinic_sge sge;\n+\tu32\t\trsvd;\n+};\n+\n+struct hinic_cmdq_completion {\n+\t/* HW Format */\n+\tunion {\n+\t\tstruct hinic_sge_resp\tsge_resp;\n+\t\tu64\t\t\tdirect_resp;\n+\t};\n+};\n+\n+struct hinic_cmdq_wqe_scmd {\n+\tstruct hinic_cmdq_header\theader;\n+\tstruct hinic_cmdq_db\t\tdb;\n+\tstruct hinic_status\t\tstatus;\n+\tstruct hinic_ctrl\t\tctrl;\n+\tstruct hinic_cmdq_completion\tcompletion;\n+\tstruct hinic_scmd_bufdesc\tbuf_desc;\n+};\n+\n+struct hinic_cmdq_wqe_lcmd {\n+\tstruct hinic_cmdq_header\theader;\n+\tstruct hinic_status\t\tstatus;\n+\tstruct hinic_ctrl\t\tctrl;\n+\tstruct hinic_cmdq_completion\tcompletion;\n+\tstruct hinic_lcmd_bufdesc\tbuf_desc;\n+};\n+\n+struct hinic_cmdq_inline_wqe {\n+\tstruct hinic_cmdq_wqe_scmd\twqe_scmd;\n+};\n+\n+struct hinic_cmdq_wqe {\n+\t/* HW Format */\n+\tunion{\n+\t\tstruct hinic_cmdq_inline_wqe\tinline_wqe;\n+\t\tstruct hinic_cmdq_wqe_lcmd\twqe_lcmd;\n+\t};\n+};\n+\n+struct hinic_cmdq_ctxt_info {\n+\tu64\tcurr_wqe_page_pfn;\n+\tu64\twq_block_pfn;\n+};\n+\n+/* New interface */\n+struct hinic_cmdq_ctxt {\n+\tu8\tstatus;\n+\tu8\tversion;\n+\tu8\tresp_aeq_num;\n+\tu8\trsvd0[5];\n+\n+\tu16\tfunc_idx;\n+\tu8\tcmdq_id;\n+\tu8\tppf_idx;\n+\n+\tu8\trsvd1[4];\n+\n+\tstruct hinic_cmdq_ctxt_info ctxt_info;\n+};\n+\n+enum hinic_cmdq_status {\n+\tHINIC_CMDQ_ENABLE = BIT(0),\n+};\n+\n+enum hinic_cmdq_cmd_type {\n+\tHINIC_CMD_TYPE_NONE,\n+\tHINIC_CMD_TYPE_SET_ARM,\n+\tHINIC_CMD_TYPE_NORMAL,\n+};\n+\n+struct hinic_cmdq_cmd_info {\n+\tenum hinic_cmdq_cmd_type cmd_type;\n+};\n+\n+struct hinic_cmdq {\n+\tstruct hinic_wq\t\t\t*wq;\n+\n+\tenum hinic_cmdq_type\t\tcmdq_type;\n+\tint\t\t\t\twrapped;\n+\n+\thinic_spinlock_t\t\tcmdq_lock;\n+\n+\tint\t\t\t\t*errcode;\n+\n+\t/* doorbell area */\n+\tu8 __iomem\t\t\t*db_base;\n+\n+\tstruct hinic_cmdq_ctxt\t\tcmdq_ctxt;\n+\n+\tstruct hinic_cmdq_cmd_info\t*cmd_infos;\n+};\n+\n+struct hinic_cmdqs {\n+\tstruct hinic_hwdev\t\t*hwdev;\n+\n+\tstruct pci_pool\t\t\t*cmd_buf_pool;\n+\n+\tstruct hinic_wq\t\t\t*saved_wqs;\n+\n+\tstruct hinic_cmdq\t\tcmdq[HINIC_MAX_CMDQ_TYPES];\n+\n+\tu32\t\t\t\tstatus;\n+};\n+\n+int hinic_reinit_cmdq_ctxts(struct hinic_hwdev *hwdev);\n+\n+bool hinic_cmdq_idle(struct hinic_cmdq *cmdq);\n+\n+struct hinic_cmd_buf *hinic_alloc_cmd_buf(void *hwdev);\n+void hinic_free_cmd_buf(void *hwdev, struct hinic_cmd_buf *buf);\n+\n+/* PF/VF send cmd to ucode by cmdq, and return if success.\n+ * timeout=0, use default timeout.\n+ */\n+int hinic_cmdq_direct_resp(void *hwdev, enum hinic_ack_type ack_type,\n+\t\t\t   enum hinic_mod_type mod, u8 cmd,\n+\t\t\t   struct hinic_cmd_buf *buf_in,\n+\t\t\t   u64 *out_param, u32 timeout);\n+\n+#endif /* _HINIC_PMD_CMDQ_H_ */\n",
    "prefixes": [
        "v4",
        "02/11"
    ]
}