get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 55012,
    "url": "http://patches.dpdk.org/api/patches/55012/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/482e7ca06281a4f7994344cfee14f3e12013781d.1560958308.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": "<482e7ca06281a4f7994344cfee14f3e12013781d.1560958308.git.xuanziyang2@huawei.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/482e7ca06281a4f7994344cfee14f3e12013781d.1560958308.git.xuanziyang2@huawei.com",
    "date": "2019-06-19T15:54:27",
    "name": "[v5,03/15] net/hinic/base: add api command channel code",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "51c490147fd907749a3f804da98892c8e70cc676",
    "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/482e7ca06281a4f7994344cfee14f3e12013781d.1560958308.git.xuanziyang2@huawei.com/mbox/",
    "series": [
        {
            "id": 5084,
            "url": "http://patches.dpdk.org/api/series/5084/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=5084",
            "date": "2019-06-19T15:45:20",
            "name": "A new net PMD - hinic",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/5084/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/55012/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/55012/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 6FE281D0D5;\n\tWed, 19 Jun 2019 17:42:48 +0200 (CEST)",
            "from huawei.com (szxga04-in.huawei.com [45.249.212.190])\n\tby dpdk.org (Postfix) with ESMTP id C2E101D0D1\n\tfor <dev@dpdk.org>; Wed, 19 Jun 2019 17:42:45 +0200 (CEST)",
            "from DGGEMS402-HUB.china.huawei.com (unknown [172.30.72.58])\n\tby Forcepoint Email with ESMTP id 88692FDF41D75F35A3F3\n\tfor <dev@dpdk.org>; Wed, 19 Jun 2019 23:42:35 +0800 (CST)",
            "from tester_149.localdomain (10.175.119.39) by\n\tDGGEMS402-HUB.china.huawei.com (10.3.19.202) with Microsoft SMTP\n\tServer id 14.3.439.0; Wed, 19 Jun 2019 23:42:25 +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<luoxianjun@huawei.com>, Ziyang Xuan <xuanziyang2@huawei.com>",
        "Date": "Wed, 19 Jun 2019 23:54:27 +0800",
        "Message-ID": "<482e7ca06281a4f7994344cfee14f3e12013781d.1560958308.git.xuanziyang2@huawei.com>",
        "X-Mailer": "git-send-email 2.18.0",
        "In-Reply-To": "<cover.1560958308.git.xuanziyang2@huawei.com>",
        "References": "<cover.1560958308.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 v5 03/15] net/hinic/base: add api command channel\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": "Api command channel is for communicating with mgmt module of chip.\nThis patch introduces data structures, initialization, interfaces,\nand commands sending functions of api command channel.\n\nSigned-off-by: Ziyang Xuan <xuanziyang2@huawei.com>\n---\n drivers/net/hinic/base/hinic_pmd_api_cmd.c | 1042 ++++++++++++++++++++\n drivers/net/hinic/base/hinic_pmd_api_cmd.h |  271 +++++\n 2 files changed, 1313 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",
    "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..1ea86fa92\n--- /dev/null\n+++ b/drivers/net/hinic/base/hinic_pmd_api_cmd.c\n@@ -0,0 +1,1042 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2017 Huawei Technologies Co., Ltd\n+ */\n+\n+#include \"hinic_compat.h\"\n+#include \"hinic_csr.h\"\n+#include \"hinic_pmd_hwdev.h\"\n+#include \"hinic_pmd_cmd.h\"\n+#include \"hinic_pmd_hwif.h\"\n+#include \"hinic_pmd_api_cmd.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;\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;\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;\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;\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;\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;\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..a48c831bb\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((((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 <<\t\\\n+\t\tHINIC_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((((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\tHINIC_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) &\t\\\n+\t\tHINIC_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\tHINIC_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\tHINIC_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\tHINIC_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+\t\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\tHINIC_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(((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((((val) >> HINIC_API_CMD_RESP_HEAD_STATUS_SHIFT) & \\\n+\t\tHINIC_API_CMD_RESP_HEAD_STATUS_MASK) ==\t\\\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(((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(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(((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(((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(((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_ */\n",
    "prefixes": [
        "v5",
        "03/15"
    ]
}