get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 63685,
    "url": "http://patches.dpdk.org/api/patches/63685/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20191209214656.27347-9-cardigliano@ntop.org/",
    "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": "<20191209214656.27347-9-cardigliano@ntop.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20191209214656.27347-9-cardigliano@ntop.org",
    "date": "2019-12-09T21:46:47",
    "name": "[v3,08/17] net/ionic: add adminq support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "5e403b2fff9a0be2adfaa3821c8e7fe6feacfa1a",
    "submitter": {
        "id": 1465,
        "url": "http://patches.dpdk.org/api/people/1465/?format=api",
        "name": "Alfredo Cardigliano",
        "email": "cardigliano@ntop.org"
    },
    "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/20191209214656.27347-9-cardigliano@ntop.org/mbox/",
    "series": [
        {
            "id": 7760,
            "url": "http://patches.dpdk.org/api/series/7760/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=7760",
            "date": "2019-12-09T21:46:39",
            "name": "Introduces net/ionic PMD",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/7760/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/63685/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/63685/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 2C2AEA04B3;\n\tMon,  9 Dec 2019 22:50:03 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 7B1F01BF93;\n\tMon,  9 Dec 2019 22:48:50 +0100 (CET)",
            "from mail.ntop.org (mail-digitalocean.ntop.org [167.99.215.164])\n by dpdk.org (Postfix) with ESMTP id 657AC5B3C\n for <dev@dpdk.org>; Mon,  9 Dec 2019 22:48:32 +0100 (CET)",
            "from devele.ntop.org (net-93-145-196-230.cust.vodafonedsl.it\n [93.145.196.230])\n by mail.ntop.org (Postfix) with ESMTPSA id 1EB0B41B73;\n Mon,  9 Dec 2019 22:48:32 +0100 (CET)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ntop.org; s=mail;\n t=1575928112; bh=y01dNvY2pah0NEmu+S7KWtIEQ1QrB749otfLSOzxLk8=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=sRw5UkFgb9wfLSnCaVNMFk4UQOIAuiNETF584zDWOywVkfH0C6ba+Xex7hlhf9UIs\n Pv08zHR7Drqi/KcanxBidIJI6rLpbw+TT1W15InCtDaYStAyUJTtNfPio3OeBASu0O\n pIT/z9lbF7vq/ccUQtEltwrkKvcZ7Ksyuo5kMFu0=",
        "From": "Alfredo Cardigliano <cardigliano@ntop.org>",
        "To": "Alfredo Cardigliano <cardigliano@ntop.org>",
        "Cc": "dev@dpdk.org",
        "Date": "Mon,  9 Dec 2019 22:46:47 +0100",
        "Message-Id": "<20191209214656.27347-9-cardigliano@ntop.org>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20191209214656.27347-1-cardigliano@ntop.org>",
        "References": "<20191209214656.27347-1-cardigliano@ntop.org>",
        "Subject": "[dpdk-dev] [PATCH v3 08/17] net/ionic: add adminq support",
        "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 <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add support for the admin queue, which is used for most\nof the NIC configurations.\n\nSigned-off-by: Alfredo Cardigliano <cardigliano@ntop.org>\nReviewed-by: Shannon Nelson <snelson@pensando.io>\n---\n drivers/net/ionic/ionic.h      |   3 +\n drivers/net/ionic/ionic_dev.c  | 255 +++++++++++++++++++++++\n drivers/net/ionic/ionic_dev.h  |  95 ++++++++-\n drivers/net/ionic/ionic_lif.c  | 356 +++++++++++++++++++++++++++++++++\n drivers/net/ionic/ionic_lif.h  |  36 ++++\n drivers/net/ionic/ionic_main.c | 186 +++++++++++++++++\n 6 files changed, 930 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/drivers/net/ionic/ionic.h b/drivers/net/ionic/ionic.h\nindex b6ef63161..7defb5fe0 100644\n--- a/drivers/net/ionic/ionic.h\n+++ b/drivers/net/ionic/ionic.h\n@@ -55,11 +55,14 @@ struct ionic_adapter {\n \tuint32_t max_ntxqs_per_lif;\n \tuint32_t max_nrxqs_per_lif;\n \tuint32_t nintrs;\n+\tbool intrs[IONIC_INTR_CTRL_REGS_MAX];\n \tbool is_mgmt_nic;\n \tstruct rte_pci_device *pci_dev;\n \tLIST_ENTRY(ionic_adapter) pci_adapters;\n };\n \n+int ionic_adminq_check_err(struct ionic_admin_ctx *ctx, bool timeout);\n+int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);\n int ionic_dev_cmd_wait_check(struct ionic_dev *idev, unsigned long max_wait);\n int ionic_setup(struct ionic_adapter *adapter);\n \ndiff --git a/drivers/net/ionic/ionic_dev.c b/drivers/net/ionic/ionic_dev.c\nindex 29f2720ae..1c5a4425b 100644\n--- a/drivers/net/ionic/ionic_dev.c\n+++ b/drivers/net/ionic/ionic_dev.c\n@@ -299,6 +299,12 @@ ionic_dev_cmd_lif_reset(struct ionic_dev *idev, uint16_t lif_index)\n \tionic_dev_cmd_go(idev, &cmd);\n }\n \n+struct ionic_doorbell *\n+ionic_db_map(struct ionic_lif *lif, struct ionic_queue *q)\n+{\n+\treturn lif->kern_dbpage + q->hw_type;\n+}\n+\n int\n ionic_db_page_num(struct ionic_lif *lif, int pid)\n {\n@@ -312,3 +318,252 @@ ionic_intr_init(struct ionic_dev *idev, struct ionic_intr_info *intr,\n \tionic_intr_clean(idev->intr_ctrl, index);\n \tintr->index = index;\n }\n+\n+void\n+ionic_dev_cmd_adminq_init(struct ionic_dev *idev,\n+\t\tstruct ionic_qcq *qcq,\n+\t\tuint16_t lif_index, uint16_t intr_index)\n+{\n+\tstruct ionic_queue *q = &qcq->q;\n+\tstruct ionic_cq *cq = &qcq->cq;\n+\n+\tunion ionic_dev_cmd cmd = {\n+\t\t.q_init.opcode = IONIC_CMD_Q_INIT,\n+\t\t.q_init.lif_index = lif_index,\n+\t\t.q_init.type = q->type,\n+\t\t.q_init.index = q->index,\n+\t\t.q_init.flags = IONIC_QINIT_F_ENA,\n+\t\t.q_init.pid = q->pid,\n+\t\t.q_init.intr_index = intr_index,\n+\t\t.q_init.ring_size = ilog2(q->num_descs),\n+\t\t.q_init.ring_base = q->base_pa,\n+\t\t.q_init.cq_ring_base = cq->base_pa,\n+\t};\n+\n+\tionic_dev_cmd_go(idev, &cmd);\n+}\n+\n+int\n+ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,\n+\t\tstruct ionic_intr_info *intr,\n+\t\tuint32_t num_descs, size_t desc_size)\n+{\n+\tif (desc_size == 0) {\n+\t\tIONIC_PRINT(ERR, \"Descriptor size is %zu\", desc_size);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!rte_is_power_of_2(num_descs) ||\n+\t    num_descs < IONIC_MIN_RING_DESC ||\n+\t    num_descs > IONIC_MAX_RING_DESC) {\n+\t\tIONIC_PRINT(ERR, \"%u descriptors (min: %u max: %u)\",\n+\t\t\tnum_descs, IONIC_MIN_RING_DESC, IONIC_MAX_RING_DESC);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tcq->lif = lif;\n+\tcq->bound_intr = intr;\n+\tcq->num_descs = num_descs;\n+\tcq->desc_size = desc_size;\n+\tcq->tail_idx = 0;\n+\tcq->done_color = 1;\n+\n+\treturn 0;\n+}\n+\n+void\n+ionic_cq_map(struct ionic_cq *cq, void *base, rte_iova_t base_pa)\n+{\n+\tcq->base = base;\n+\tcq->base_pa = base_pa;\n+}\n+\n+void\n+ionic_cq_bind(struct ionic_cq *cq, struct ionic_queue *q)\n+{\n+\tcq->bound_q = q;\n+\tq->bound_cq = cq;\n+}\n+\n+uint32_t\n+ionic_cq_service(struct ionic_cq *cq, uint32_t work_to_do,\n+\t\t ionic_cq_cb cb, void *cb_arg)\n+{\n+\tuint32_t work_done = 0;\n+\n+\tif (work_to_do == 0)\n+\t\treturn 0;\n+\n+\twhile (cb(cq, cq->tail_idx, cb_arg)) {\n+\t\tcq->tail_idx = (cq->tail_idx + 1) & (cq->num_descs - 1);\n+\t\tif (cq->tail_idx == 0)\n+\t\t\tcq->done_color = !cq->done_color;\n+\n+\t\tif (++work_done == work_to_do)\n+\t\t\tbreak;\n+\t}\n+\n+\treturn work_done;\n+}\n+\n+int\n+ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,\n+\t     struct ionic_queue *q, uint32_t index, uint32_t num_descs,\n+\t     size_t desc_size, size_t sg_desc_size, uint32_t pid)\n+{\n+\tuint32_t ring_size;\n+\n+\tif (desc_size == 0 || !rte_is_power_of_2(num_descs))\n+\t\treturn -EINVAL;\n+\n+\tring_size = ilog2(num_descs);\n+\n+\tif (ring_size < 2 || ring_size > 16)\n+\t\treturn -EINVAL;\n+\n+\tq->lif = lif;\n+\tq->idev = idev;\n+\tq->index = index;\n+\tq->num_descs = num_descs;\n+\tq->desc_size = desc_size;\n+\tq->sg_desc_size = sg_desc_size;\n+\tq->head_idx = 0;\n+\tq->tail_idx = 0;\n+\tq->pid = pid;\n+\n+\treturn 0;\n+}\n+\n+void\n+ionic_q_map(struct ionic_queue *q, void *base, rte_iova_t base_pa)\n+{\n+\tq->base = base;\n+\tq->base_pa = base_pa;\n+}\n+\n+void\n+ionic_q_sg_map(struct ionic_queue *q, void *base, rte_iova_t base_pa)\n+{\n+\tq->sg_base = base;\n+\tq->sg_base_pa = base_pa;\n+}\n+\n+void\n+ionic_q_flush(struct ionic_queue *q)\n+{\n+\twriteq(IONIC_DBELL_QID(q->hw_index) | q->head_idx, q->db);\n+}\n+\n+void\n+ionic_q_post(struct ionic_queue *q, bool ring_doorbell, desc_cb cb,\n+\t     void *cb_arg)\n+{\n+\tstruct ionic_desc_info *head = &q->info[q->head_idx];\n+\n+\thead->cb = cb;\n+\thead->cb_arg = cb_arg;\n+\n+\tq->head_idx = (q->head_idx + 1) & (q->num_descs - 1);\n+\n+\tif (ring_doorbell)\n+\t\tionic_q_flush(q);\n+}\n+\n+uint32_t\n+ionic_q_space_avail(struct ionic_queue *q)\n+{\n+\tuint32_t avail = q->tail_idx;\n+\n+\tif (q->head_idx >= avail)\n+\t\tavail += q->num_descs - q->head_idx - 1;\n+\telse\n+\t\tavail -= q->head_idx + 1;\n+\n+\treturn avail;\n+}\n+\n+bool\n+ionic_q_has_space(struct ionic_queue *q, uint32_t want)\n+{\n+\treturn ionic_q_space_avail(q) >= want;\n+}\n+\n+void\n+ionic_q_service(struct ionic_queue *q, uint32_t cq_desc_index,\n+\t\tuint32_t stop_index, void *service_cb_arg)\n+{\n+\tstruct ionic_desc_info *desc_info;\n+\tuint32_t curr_q_tail_idx;\n+\n+\tdo {\n+\t\tdesc_info = &q->info[q->tail_idx];\n+\n+\t\tif (desc_info->cb)\n+\t\t\tdesc_info->cb(q, q->tail_idx, cq_desc_index,\n+\t\t\t\tdesc_info->cb_arg, service_cb_arg);\n+\n+\t\tdesc_info->cb = NULL;\n+\t\tdesc_info->cb_arg = NULL;\n+\n+\t\tcurr_q_tail_idx = q->tail_idx;\n+\t\tq->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);\n+\n+\t} while (curr_q_tail_idx != stop_index);\n+}\n+\n+static void\n+ionic_adminq_cb(struct ionic_queue *q,\n+\t\tuint32_t q_desc_index, uint32_t cq_desc_index,\n+\t\tvoid *cb_arg, void *service_cb_arg __rte_unused)\n+{\n+\tstruct ionic_admin_ctx *ctx = cb_arg;\n+\tstruct ionic_admin_comp *cq_desc_base = q->bound_cq->base;\n+\tstruct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];\n+\n+\tif (unlikely(cq_desc->comp_index != q_desc_index)) {\n+\t\tIONIC_WARN_ON(cq_desc->comp_index != q_desc_index);\n+\t\treturn;\n+\t}\n+\n+\tmemcpy(&ctx->comp, cq_desc, sizeof(*cq_desc));\n+\n+\tctx->pending_work = false; /* done */\n+}\n+\n+/** ionic_adminq_post - Post an admin command.\n+ * @lif:\t\tHandle to lif.\n+ * @cmd_ctx:\t\tApi admin command context.\n+ *\n+ * Post the command to an admin queue in the ethernet driver.  If this command\n+ * succeeds, then the command has been posted, but that does not indicate a\n+ * completion.  If this command returns success, then the completion callback\n+ * will eventually be called.\n+ *\n+ * Return: zero or negative error status.\n+ */\n+int\n+ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)\n+{\n+\tstruct ionic_queue *adminq = &lif->adminqcq->q;\n+\tstruct ionic_admin_cmd *q_desc_base = adminq->base;\n+\tstruct ionic_admin_cmd *q_desc;\n+\tint err = 0;\n+\n+\trte_spinlock_lock(&lif->adminq_lock);\n+\n+\tif (!ionic_q_has_space(adminq, 1)) {\n+\t\terr = -ENOSPC;\n+\t\tgoto err_out;\n+\t}\n+\n+\tq_desc = &q_desc_base[adminq->head_idx];\n+\n+\tmemcpy(q_desc, &ctx->cmd, sizeof(ctx->cmd));\n+\n+\tionic_q_post(adminq, true, ionic_adminq_cb, ctx);\n+\n+err_out:\n+\trte_spinlock_unlock(&lif->adminq_lock);\n+\n+\treturn err;\n+}\ndiff --git a/drivers/net/ionic/ionic_dev.h b/drivers/net/ionic/ionic_dev.h\nindex ca9807a9b..a832ff405 100644\n--- a/drivers/net/ionic/ionic_dev.h\n+++ b/drivers/net/ionic/ionic_dev.h\n@@ -9,6 +9,9 @@\n #include \"ionic_if.h\"\n #include \"ionic_regs.h\"\n \n+#define IONIC_MAX_RING_DESC\t\t32768\n+#define IONIC_MIN_RING_DESC\t\t16\n+\n #define IONIC_LIFS_MAX\t\t\t1024\n \n #define IONIC_DEVCMD_TIMEOUT\t30 /* devcmd_timeout */\n@@ -121,6 +124,44 @@ struct ionic_dev {\n \tuint32_t port_info_sz;\n };\n \n+struct ionic_queue;\n+struct ionic_desc_info;\n+\n+typedef void (*desc_cb)(struct ionic_queue *q,\n+\tuint32_t q_desc_index,\n+\tuint32_t cq_desc_index,\n+\tvoid *cb_arg, void *service_cb_arg);\n+\n+struct ionic_desc_info {\n+\tdesc_cb cb;\n+\tvoid *cb_arg;\n+};\n+\n+struct ionic_queue {\n+\tstruct ionic_dev *idev;\n+\tstruct ionic_lif *lif;\n+\tstruct ionic_cq *bound_cq;\n+\tuint32_t index;\n+\tuint32_t type;\n+\tuint32_t hw_index;\n+\tuint32_t hw_type;\n+\tvoid *base;\n+\tvoid *sg_base;\n+\trte_iova_t base_pa;\n+\trte_iova_t sg_base_pa;\n+\tstruct ionic_desc_info *info;\n+\tuint32_t tail_idx;\n+\tuint32_t head_idx;\n+\tuint32_t num_descs;\n+\tuint32_t desc_size;\n+\tuint32_t sg_desc_size;\n+\tuint32_t pid;\n+\tuint32_t qid;\n+\tuint32_t qtype;\n+\tstruct ionic_doorbell __iomem *db;\n+\tvoid *nop_desc;\n+};\n+\n #define IONIC_INTR_INDEX_NOT_ASSIGNED\t(-1)\n #define IONIC_INTR_NAME_MAX_SZ\t\t(32)\n \n@@ -129,11 +170,34 @@ struct ionic_intr_info {\n \tint index;\n \tuint32_t vector;\n \tstruct ionic_intr __iomem *ctrl;\n-\tuint64_t rearm_count;\n+};\n+\n+struct ionic_cq {\n+\tstruct ionic_lif *lif;\n+\tstruct ionic_queue *bound_q;\n+\tuint32_t tail_idx;\n+\tuint32_t num_descs;\n+\tuint32_t desc_size;\n+\tbool done_color;\n+\tvoid *base;\n+\trte_iova_t base_pa;\n+\tstruct ionic_intr_info *bound_intr;\n+};\n+\n+/** ionic_admin_ctx - Admin command context.\n+ * @pending_work:\tFlag that indicates a completion.\n+ * @cmd:\t\tAdmin command (64B) to be copied to the queue.\n+ * @comp:\t\tAdmin completion (16B) copied from the queue.\n+ */\n+struct ionic_admin_ctx {\n+\tbool pending_work;\n+\tunion ionic_adminq_cmd cmd;\n+\tunion ionic_adminq_comp comp;\n };\n \n struct ionic_lif;\n struct ionic_adapter;\n+struct ionic_qcq;\n \n void ionic_intr_init(struct ionic_dev *idev, struct ionic_intr_info *intr,\n \tunsigned long index);\n@@ -166,7 +230,36 @@ void ionic_dev_cmd_lif_identify(struct ionic_dev *idev, uint8_t type,\n void ionic_dev_cmd_lif_init(struct ionic_dev *idev, uint16_t lif_index,\n \trte_iova_t addr);\n void ionic_dev_cmd_lif_reset(struct ionic_dev *idev, uint16_t lif_index);\n+void ionic_dev_cmd_adminq_init(struct ionic_dev *idev, struct ionic_qcq *qcq,\n+\tuint16_t lif_index, uint16_t intr_index);\n \n+struct ionic_doorbell __iomem *ionic_db_map(struct ionic_lif *lif,\n+\tstruct ionic_queue *q);\n int ionic_db_page_num(struct ionic_lif *lif, int pid);\n \n+int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,\n+\tstruct ionic_intr_info *intr, uint32_t num_descs,\n+\tsize_t desc_size);\n+void ionic_cq_map(struct ionic_cq *cq, void *base, rte_iova_t base_pa);\n+void ionic_cq_bind(struct ionic_cq *cq, struct ionic_queue *q);\n+typedef bool (*ionic_cq_cb)(struct ionic_cq *cq, uint32_t cq_desc_index,\n+\t\tvoid *cb_arg);\n+uint32_t ionic_cq_service(struct ionic_cq *cq, uint32_t work_to_do,\n+\tionic_cq_cb cb, void *cb_arg);\n+\n+int ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,\n+\tstruct ionic_queue *q, uint32_t index, uint32_t num_descs,\n+\tsize_t desc_size, size_t sg_desc_size, uint32_t pid);\n+void ionic_q_map(struct ionic_queue *q, void *base, rte_iova_t base_pa);\n+void ionic_q_sg_map(struct ionic_queue *q, void *base, rte_iova_t base_pa);\n+void ionic_q_flush(struct ionic_queue *q);\n+void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, desc_cb cb,\n+\tvoid *cb_arg);\n+uint32_t ionic_q_space_avail(struct ionic_queue *q);\n+bool ionic_q_has_space(struct ionic_queue *q, uint32_t want);\n+void ionic_q_service(struct ionic_queue *q, uint32_t cq_desc_index,\n+\tuint32_t stop_index, void *service_cb_arg);\n+\n+int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx);\n+\n #endif /* _IONIC_DEV_H_ */\ndiff --git a/drivers/net/ionic/ionic_lif.c b/drivers/net/ionic/ionic_lif.c\nindex 1cc130322..ec631b600 100644\n--- a/drivers/net/ionic/ionic_lif.c\n+++ b/drivers/net/ionic/ionic_lif.c\n@@ -10,6 +10,259 @@\n #include \"ionic_lif.h\"\n #include \"ionic_ethdev.h\"\n \n+int\n+ionic_qcq_enable(struct ionic_qcq *qcq)\n+{\n+\tstruct ionic_queue *q = &qcq->q;\n+\tstruct ionic_lif *lif = q->lif;\n+\tstruct ionic_dev *idev = &lif->adapter->idev;\n+\tstruct ionic_admin_ctx ctx = {\n+\t\t.pending_work = true,\n+\t\t.cmd.q_control = {\n+\t\t\t.opcode = IONIC_CMD_Q_CONTROL,\n+\t\t\t.lif_index = lif->index,\n+\t\t\t.type = q->type,\n+\t\t\t.index = q->index,\n+\t\t\t.oper = IONIC_Q_ENABLE,\n+\t\t},\n+\t};\n+\n+\tif (qcq->flags & IONIC_QCQ_F_INTR) {\n+\t\tionic_intr_mask(idev->intr_ctrl, qcq->intr.index,\n+\t\t\t\tIONIC_INTR_MASK_CLEAR);\n+\t}\n+\n+\treturn ionic_adminq_post_wait(lif, &ctx);\n+}\n+\n+int\n+ionic_qcq_disable(struct ionic_qcq *qcq)\n+{\n+\tstruct ionic_queue *q = &qcq->q;\n+\tstruct ionic_lif *lif = q->lif;\n+\tstruct ionic_dev *idev = &lif->adapter->idev;\n+\tstruct ionic_admin_ctx ctx = {\n+\t\t.pending_work = true,\n+\t\t.cmd.q_control = {\n+\t\t\t.opcode = IONIC_CMD_Q_CONTROL,\n+\t\t\t.lif_index = lif->index,\n+\t\t\t.type = q->type,\n+\t\t\t.index = q->index,\n+\t\t\t.oper = IONIC_Q_DISABLE,\n+\t\t},\n+\t};\n+\n+\tif (qcq->flags & IONIC_QCQ_F_INTR) {\n+\t\tionic_intr_mask(idev->intr_ctrl, qcq->intr.index,\n+\t\t\tIONIC_INTR_MASK_SET);\n+\t}\n+\n+\treturn ionic_adminq_post_wait(lif, &ctx);\n+}\n+\n+int\n+ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr)\n+{\n+\tstruct ionic_adapter *adapter = lif->adapter;\n+\tstruct ionic_dev *idev = &adapter->idev;\n+\tunsigned long index;\n+\n+\t/*\n+\t * Note: interrupt handler is called for index = 0 only\n+\t * (we use interrupts for the notifyq only anyway,\n+\t * which hash index = 0)\n+\t */\n+\n+\tfor (index = 0; index < adapter->nintrs; index++)\n+\t\tif (!adapter->intrs[index])\n+\t\t\tbreak;\n+\n+\tif (index == adapter->nintrs)\n+\t\treturn -ENOSPC;\n+\n+\tadapter->intrs[index] = true;\n+\n+\tionic_intr_init(idev, intr, index);\n+\n+\treturn 0;\n+}\n+\n+void\n+ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr)\n+{\n+\tif (intr->index != IONIC_INTR_INDEX_NOT_ASSIGNED)\n+\t\tlif->adapter->intrs[intr->index] = false;\n+}\n+\n+static int\n+ionic_qcq_alloc(struct ionic_lif *lif, uint8_t type,\n+\t\tuint32_t index,\n+\t\tconst char *base, uint32_t flags,\n+\t\tuint32_t num_descs,\n+\t\tuint32_t desc_size,\n+\t\tuint32_t cq_desc_size,\n+\t\tuint32_t sg_desc_size,\n+\t\tuint32_t pid, struct ionic_qcq **qcq)\n+{\n+\tstruct ionic_dev *idev = &lif->adapter->idev;\n+\tstruct ionic_qcq *new;\n+\tuint32_t q_size, cq_size, sg_size, total_size;\n+\tvoid *q_base, *cq_base, *sg_base;\n+\trte_iova_t q_base_pa = 0;\n+\trte_iova_t cq_base_pa = 0;\n+\trte_iova_t sg_base_pa = 0;\n+\tuint32_t socket_id = rte_socket_id();\n+\tint err;\n+\n+\t*qcq = NULL;\n+\n+\tq_size  = num_descs * desc_size;\n+\tcq_size = num_descs * cq_desc_size;\n+\tsg_size = num_descs * sg_desc_size;\n+\n+\ttotal_size = RTE_ALIGN(q_size, PAGE_SIZE) +\n+\t\tRTE_ALIGN(cq_size, PAGE_SIZE);\n+\t/*\n+\t * Note: aligning q_size/cq_size is not enough due to cq_base address\n+\t * aligning as q_base could be not aligned to the page.\n+\t * Adding PAGE_SIZE.\n+\t */\n+\ttotal_size += PAGE_SIZE;\n+\n+\tif (flags & IONIC_QCQ_F_SG) {\n+\t\ttotal_size += RTE_ALIGN(sg_size, PAGE_SIZE);\n+\t\ttotal_size += PAGE_SIZE;\n+\t}\n+\n+\tnew = rte_zmalloc(\"ionic\", sizeof(*new), 0);\n+\n+\tif (!new) {\n+\t\tIONIC_PRINT(ERR, \"Cannot allocate queue structure\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tnew->lif = lif;\n+\tnew->flags = flags;\n+\n+\tnew->q.info = rte_zmalloc(\"ionic\", sizeof(*new->q.info) * num_descs, 0);\n+\n+\tif (!new->q.info) {\n+\t\tIONIC_PRINT(ERR, \"Cannot allocate queue info\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tnew->q.type = type;\n+\n+\terr = ionic_q_init(lif, idev, &new->q, index, num_descs,\n+\t\tdesc_size, sg_desc_size, pid);\n+\n+\tif (err) {\n+\t\tIONIC_PRINT(ERR, \"Queue initialization failed\");\n+\t\treturn err;\n+\t}\n+\n+\tif (flags & IONIC_QCQ_F_INTR) {\n+\t\terr = ionic_intr_alloc(lif, &new->intr);\n+\t\tif (err)\n+\t\t\treturn err;\n+\n+\t\tionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,\n+\t\t\tIONIC_INTR_MASK_SET);\n+\t} else {\n+\t\tnew->intr.index = IONIC_INTR_INDEX_NOT_ASSIGNED;\n+\t}\n+\n+\terr = ionic_cq_init(lif, &new->cq, &new->intr,\n+\t\tnum_descs, cq_desc_size);\n+\tif (err) {\n+\t\tIONIC_PRINT(ERR, \"Completion queue initialization failed\");\n+\t\tgoto err_out_free_intr;\n+\t}\n+\n+\tnew->base_z = rte_eth_dma_zone_reserve(lif->eth_dev,\n+\t\tbase /* name */, index /* queue_idx */,\n+\t\ttotal_size, IONIC_ALIGN, socket_id);\n+\n+\tif (!new->base_z) {\n+\t\tIONIC_PRINT(ERR, \"Cannot reserve queue DMA memory\");\n+\t\terr = -ENOMEM;\n+\t\tgoto err_out_free_intr;\n+\t}\n+\n+\tnew->base = new->base_z->addr;\n+\tnew->base_pa = new->base_z->iova;\n+\tnew->total_size = total_size;\n+\n+\tq_base = new->base;\n+\tq_base_pa = new->base_pa;\n+\n+\tcq_base = (void *)RTE_ALIGN((uintptr_t)q_base + q_size, PAGE_SIZE);\n+\tcq_base_pa = RTE_ALIGN(q_base_pa + q_size, PAGE_SIZE);\n+\n+\tif (flags & IONIC_QCQ_F_SG) {\n+\t\tsg_base = (void *)RTE_ALIGN((uintptr_t)cq_base + cq_size,\n+\t\t\tPAGE_SIZE);\n+\t\tsg_base_pa = RTE_ALIGN(cq_base_pa + cq_size, PAGE_SIZE);\n+\t\tionic_q_sg_map(&new->q, sg_base, sg_base_pa);\n+\t}\n+\n+\tIONIC_PRINT(DEBUG, \"Q-Base-PA = %ju CQ-Base-PA = %ju \"\n+\t\t\"SG-base-PA = %ju\",\n+\t\tq_base_pa, cq_base_pa, sg_base_pa);\n+\n+\tionic_q_map(&new->q, q_base, q_base_pa);\n+\tionic_cq_map(&new->cq, cq_base, cq_base_pa);\n+\tionic_cq_bind(&new->cq, &new->q);\n+\n+\t*qcq = new;\n+\n+\treturn 0;\n+\n+err_out_free_intr:\n+\tif (flags & IONIC_QCQ_F_INTR)\n+\t\tionic_intr_free(lif, &new->intr);\n+\n+\treturn err;\n+}\n+\n+void\n+ionic_qcq_free(struct ionic_qcq *qcq)\n+{\n+\tif (qcq->base_z) {\n+\t\tqcq->base = NULL;\n+\t\tqcq->base_pa = 0;\n+\t\trte_memzone_free(qcq->base_z);\n+\t\tqcq->base_z = NULL;\n+\t}\n+\n+\tif (qcq->q.info) {\n+\t\trte_free(qcq->q.info);\n+\t\tqcq->q.info = NULL;\n+\t}\n+\n+\trte_free(qcq);\n+}\n+\n+static int\n+ionic_admin_qcq_alloc(struct ionic_lif *lif)\n+{\n+\tuint32_t flags;\n+\tint err = -ENOMEM;\n+\n+\tflags = 0;\n+\terr = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, \"admin\", flags,\n+\t\tIONIC_ADMINQ_LENGTH,\n+\t\tsizeof(struct ionic_admin_cmd),\n+\t\tsizeof(struct ionic_admin_comp),\n+\t\t0,\n+\t\tlif->kern_pid, &lif->adminqcq);\n+\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn 0;\n+}\n+\n static void *\n ionic_bus_map_dbpage(struct ionic_adapter *adapter, int page_num)\n {\n@@ -27,11 +280,15 @@ ionic_lif_alloc(struct ionic_lif *lif)\n \tstruct ionic_adapter *adapter = lif->adapter;\n \tuint32_t socket_id = rte_socket_id();\n \tint dbpage_num;\n+\tint err;\n \n \tsnprintf(lif->name, sizeof(lif->name), \"lif%u\", lif->index);\n \n \tIONIC_PRINT(DEBUG, \"Allocating Lif Info\");\n \n+\trte_spinlock_init(&lif->adminq_lock);\n+\trte_spinlock_init(&lif->adminq_service_lock);\n+\n \tlif->kern_pid = 0;\n \n \tdbpage_num = ionic_db_page_num(lif, 0);\n@@ -43,6 +300,17 @@ ionic_lif_alloc(struct ionic_lif *lif)\n \t\treturn -ENOMEM;\n \t}\n \n+\tIONIC_PRINT(DEBUG, \"Allocating Admin Queue\");\n+\n+\terr = ionic_admin_qcq_alloc(lif);\n+\n+\tif (err) {\n+\t\tIONIC_PRINT(ERR, \"Cannot allocate admin queue\");\n+\t\treturn err;\n+\t}\n+\n+\tIONIC_PRINT(DEBUG, \"Allocating Lif Info\");\n+\n \tlif->info_sz = RTE_ALIGN(sizeof(*lif->info), PAGE_SIZE);\n \n \tlif->info_z = rte_eth_dma_zone_reserve(lif->eth_dev,\n@@ -63,12 +331,93 @@ ionic_lif_alloc(struct ionic_lif *lif)\n void\n ionic_lif_free(struct ionic_lif *lif)\n {\n+\tif (lif->adminqcq) {\n+\t\tionic_qcq_free(lif->adminqcq);\n+\t\tlif->adminqcq = NULL;\n+\t}\n+\n \tif (lif->info) {\n \t\trte_memzone_free(lif->info_z);\n \t\tlif->info = NULL;\n \t}\n }\n \n+static void\n+ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)\n+{\n+\tstruct ionic_dev *idev = &lif->adapter->idev;\n+\n+\tif (!(qcq->flags & IONIC_QCQ_F_INITED))\n+\t\treturn;\n+\n+\tif (qcq->flags & IONIC_QCQ_F_INTR)\n+\t\tionic_intr_mask(idev->intr_ctrl, qcq->intr.index,\n+\t\t\tIONIC_INTR_MASK_SET);\n+\n+\tqcq->flags &= ~IONIC_QCQ_F_INITED;\n+}\n+\n+bool\n+ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,\n+\t\tvoid *cb_arg __rte_unused)\n+{\n+\tstruct ionic_admin_comp *cq_desc_base = cq->base;\n+\tstruct ionic_admin_comp *cq_desc = &cq_desc_base[cq_desc_index];\n+\n+\tif (!color_match(cq_desc->color, cq->done_color))\n+\t\treturn false;\n+\n+\tionic_q_service(cq->bound_q, cq_desc_index, cq_desc->comp_index, NULL);\n+\n+\treturn true;\n+}\n+\n+/* This acts like ionic_napi */\n+int\n+ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,\n+\t\tvoid *cb_arg)\n+{\n+\tstruct ionic_cq *cq = &qcq->cq;\n+\tuint32_t work_done;\n+\n+\twork_done = ionic_cq_service(cq, budget, cb, cb_arg);\n+\n+\treturn work_done;\n+}\n+\n+static int\n+ionic_lif_adminq_init(struct ionic_lif *lif)\n+{\n+\tstruct ionic_dev *idev = &lif->adapter->idev;\n+\tstruct ionic_qcq *qcq = lif->adminqcq;\n+\tstruct ionic_queue *q = &qcq->q;\n+\tstruct ionic_q_init_comp comp;\n+\tint err;\n+\n+\tionic_dev_cmd_adminq_init(idev, qcq, lif->index, qcq->intr.index);\n+\terr = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);\n+\tif (err)\n+\t\treturn err;\n+\n+\tionic_dev_cmd_comp(idev, &comp);\n+\n+\tq->hw_type = comp.hw_type;\n+\tq->hw_index = comp.hw_index;\n+\tq->db = ionic_db_map(lif, q);\n+\n+\tIONIC_PRINT(DEBUG, \"adminq->hw_type %d\", q->hw_type);\n+\tIONIC_PRINT(DEBUG, \"adminq->hw_index %d\", q->hw_index);\n+\tIONIC_PRINT(DEBUG, \"adminq->db %p\", q->db);\n+\n+\tif (qcq->flags & IONIC_QCQ_F_INTR)\n+\t\tionic_intr_mask(idev->intr_ctrl, qcq->intr.index,\n+\t\t\tIONIC_INTR_MASK_CLEAR);\n+\n+\tqcq->flags |= IONIC_QCQ_F_INITED;\n+\n+\treturn 0;\n+}\n+\n int\n ionic_lif_init(struct ionic_lif *lif)\n {\n@@ -84,6 +433,11 @@ ionic_lif_init(struct ionic_lif *lif)\n \n \tlif->hw_index = comp.hw_index;\n \n+\terr = ionic_lif_adminq_init(lif);\n+\n+\tif (err)\n+\t\treturn err;\n+\n \tlif->state |= IONIC_LIF_F_INITED;\n \n \treturn 0;\n@@ -95,6 +449,8 @@ ionic_lif_deinit(struct ionic_lif *lif)\n \tif (!(lif->state & IONIC_LIF_F_INITED))\n \t\treturn;\n \n+\tionic_lif_qcq_deinit(lif, lif->adminqcq);\n+\n \tlif->state &= ~IONIC_LIF_F_INITED;\n }\n \ndiff --git a/drivers/net/ionic/ionic_lif.h b/drivers/net/ionic/ionic_lif.h\nindex 6e3233d1d..96522c544 100644\n--- a/drivers/net/ionic/ionic_lif.h\n+++ b/drivers/net/ionic/ionic_lif.h\n@@ -13,6 +13,26 @@\n #include \"ionic_osdep.h\"\n #include \"ionic_dev.h\"\n \n+#define IONIC_ADMINQ_LENGTH\t16\t/* must be a power of two */\n+\n+#define IONIC_QCQ_F_INITED\tBIT(0)\n+#define IONIC_QCQ_F_SG\t\tBIT(1)\n+#define IONIC_QCQ_F_INTR\tBIT(2)\n+\n+/* Queue / Completion Queue */\n+struct ionic_qcq {\n+\tstruct ionic_queue q;        /**< Queue */\n+\tstruct ionic_cq cq;          /**< Completion Queue */\n+\tstruct ionic_lif *lif;       /**< LIF */\n+\tstruct rte_mempool *mb_pool; /**< mbuf pool to populate the RX ring */\n+\tconst struct rte_memzone *base_z;\n+\tvoid *base;\n+\trte_iova_t base_pa;\n+\tuint32_t total_size;\n+\tuint32_t flags;\n+\tstruct ionic_intr_info intr;\n+};\n+\n #define IONIC_LIF_F_INITED\t\tBIT(0)\n \n #define IONIC_LIF_NAME_MAX_SZ\t\t(32)\n@@ -25,6 +45,9 @@ struct ionic_lif {\n \tuint32_t hw_index;\n \tuint32_t state;\n \tuint32_t kern_pid;\n+\trte_spinlock_t adminq_lock;\n+\trte_spinlock_t adminq_service_lock;\n+\tstruct ionic_qcq *adminqcq;\n \tstruct ionic_doorbell __iomem *kern_dbpage;\n \tchar name[IONIC_LIF_NAME_MAX_SZ];\n \tuint32_t info_sz;\n@@ -47,4 +70,17 @@ int ionic_lif_start(struct ionic_lif *lif);\n int ionic_lif_configure(struct ionic_lif *lif);\n void ionic_lif_reset(struct ionic_lif *lif);\n \n+int ionic_intr_alloc(struct ionic_lif *lif, struct ionic_intr_info *intr);\n+void ionic_intr_free(struct ionic_lif *lif, struct ionic_intr_info *intr);\n+\n+bool ionic_adminq_service(struct ionic_cq *cq, uint32_t cq_desc_index,\n+\tvoid *cb_arg);\n+int ionic_qcq_service(struct ionic_qcq *qcq, int budget, ionic_cq_cb cb,\n+\tvoid *cb_arg);\n+\n+void ionic_qcq_free(struct ionic_qcq *qcq);\n+\n+int ionic_qcq_enable(struct ionic_qcq *qcq);\n+int ionic_qcq_disable(struct ionic_qcq *qcq);\n+\n #endif /* _IONIC_LIF_H_ */\ndiff --git a/drivers/net/ionic/ionic_main.c b/drivers/net/ionic/ionic_main.c\nindex da558cdce..0d7e27530 100644\n--- a/drivers/net/ionic/ionic_main.c\n+++ b/drivers/net/ionic/ionic_main.c\n@@ -5,6 +5,192 @@\n #include <rte_memzone.h>\n \n #include \"ionic.h\"\n+#include \"ionic_ethdev.h\"\n+#include \"ionic_lif.h\"\n+\n+static const char *\n+ionic_error_to_str(enum ionic_status_code code)\n+{\n+\tswitch (code) {\n+\tcase IONIC_RC_SUCCESS:\n+\t\treturn \"IONIC_RC_SUCCESS\";\n+\tcase IONIC_RC_EVERSION:\n+\t\treturn \"IONIC_RC_EVERSION\";\n+\tcase IONIC_RC_EOPCODE:\n+\t\treturn \"IONIC_RC_EOPCODE\";\n+\tcase IONIC_RC_EIO:\n+\t\treturn \"IONIC_RC_EIO\";\n+\tcase IONIC_RC_EPERM:\n+\t\treturn \"IONIC_RC_EPERM\";\n+\tcase IONIC_RC_EQID:\n+\t\treturn \"IONIC_RC_EQID\";\n+\tcase IONIC_RC_EQTYPE:\n+\t\treturn \"IONIC_RC_EQTYPE\";\n+\tcase IONIC_RC_ENOENT:\n+\t\treturn \"IONIC_RC_ENOENT\";\n+\tcase IONIC_RC_EINTR:\n+\t\treturn \"IONIC_RC_EINTR\";\n+\tcase IONIC_RC_EAGAIN:\n+\t\treturn \"IONIC_RC_EAGAIN\";\n+\tcase IONIC_RC_ENOMEM:\n+\t\treturn \"IONIC_RC_ENOMEM\";\n+\tcase IONIC_RC_EFAULT:\n+\t\treturn \"IONIC_RC_EFAULT\";\n+\tcase IONIC_RC_EBUSY:\n+\t\treturn \"IONIC_RC_EBUSY\";\n+\tcase IONIC_RC_EEXIST:\n+\t\treturn \"IONIC_RC_EEXIST\";\n+\tcase IONIC_RC_EINVAL:\n+\t\treturn \"IONIC_RC_EINVAL\";\n+\tcase IONIC_RC_ENOSPC:\n+\t\treturn \"IONIC_RC_ENOSPC\";\n+\tcase IONIC_RC_ERANGE:\n+\t\treturn \"IONIC_RC_ERANGE\";\n+\tcase IONIC_RC_BAD_ADDR:\n+\t\treturn \"IONIC_RC_BAD_ADDR\";\n+\tcase IONIC_RC_DEV_CMD:\n+\t\treturn \"IONIC_RC_DEV_CMD\";\n+\tcase IONIC_RC_ERROR:\n+\t\treturn \"IONIC_RC_ERROR\";\n+\tcase IONIC_RC_ERDMA:\n+\t\treturn \"IONIC_RC_ERDMA\";\n+\tdefault:\n+\t\treturn \"IONIC_RC_UNKNOWN\";\n+\t}\n+}\n+\n+static const char *\n+ionic_opcode_to_str(enum ionic_cmd_opcode opcode)\n+{\n+\tswitch (opcode) {\n+\tcase IONIC_CMD_NOP:\n+\t\treturn \"IONIC_CMD_NOP\";\n+\tcase IONIC_CMD_INIT:\n+\t\treturn \"IONIC_CMD_INIT\";\n+\tcase IONIC_CMD_RESET:\n+\t\treturn \"IONIC_CMD_RESET\";\n+\tcase IONIC_CMD_IDENTIFY:\n+\t\treturn \"IONIC_CMD_IDENTIFY\";\n+\tcase IONIC_CMD_GETATTR:\n+\t\treturn \"IONIC_CMD_GETATTR\";\n+\tcase IONIC_CMD_SETATTR:\n+\t\treturn \"IONIC_CMD_SETATTR\";\n+\tcase IONIC_CMD_PORT_IDENTIFY:\n+\t\treturn \"IONIC_CMD_PORT_IDENTIFY\";\n+\tcase IONIC_CMD_PORT_INIT:\n+\t\treturn \"IONIC_CMD_PORT_INIT\";\n+\tcase IONIC_CMD_PORT_RESET:\n+\t\treturn \"IONIC_CMD_PORT_RESET\";\n+\tcase IONIC_CMD_PORT_GETATTR:\n+\t\treturn \"IONIC_CMD_PORT_GETATTR\";\n+\tcase IONIC_CMD_PORT_SETATTR:\n+\t\treturn \"IONIC_CMD_PORT_SETATTR\";\n+\tcase IONIC_CMD_LIF_INIT:\n+\t\treturn \"IONIC_CMD_LIF_INIT\";\n+\tcase IONIC_CMD_LIF_RESET:\n+\t\treturn \"IONIC_CMD_LIF_RESET\";\n+\tcase IONIC_CMD_LIF_IDENTIFY:\n+\t\treturn \"IONIC_CMD_LIF_IDENTIFY\";\n+\tcase IONIC_CMD_LIF_SETATTR:\n+\t\treturn \"IONIC_CMD_LIF_SETATTR\";\n+\tcase IONIC_CMD_LIF_GETATTR:\n+\t\treturn \"IONIC_CMD_LIF_GETATTR\";\n+\tcase IONIC_CMD_RX_MODE_SET:\n+\t\treturn \"IONIC_CMD_RX_MODE_SET\";\n+\tcase IONIC_CMD_RX_FILTER_ADD:\n+\t\treturn \"IONIC_CMD_RX_FILTER_ADD\";\n+\tcase IONIC_CMD_RX_FILTER_DEL:\n+\t\treturn \"IONIC_CMD_RX_FILTER_DEL\";\n+\tcase IONIC_CMD_Q_INIT:\n+\t\treturn \"IONIC_CMD_Q_INIT\";\n+\tcase IONIC_CMD_Q_CONTROL:\n+\t\treturn \"IONIC_CMD_Q_CONTROL\";\n+\tcase IONIC_CMD_RDMA_RESET_LIF:\n+\t\treturn \"IONIC_CMD_RDMA_RESET_LIF\";\n+\tcase IONIC_CMD_RDMA_CREATE_EQ:\n+\t\treturn \"IONIC_CMD_RDMA_CREATE_EQ\";\n+\tcase IONIC_CMD_RDMA_CREATE_CQ:\n+\t\treturn \"IONIC_CMD_RDMA_CREATE_CQ\";\n+\tcase IONIC_CMD_RDMA_CREATE_ADMINQ:\n+\t\treturn \"IONIC_CMD_RDMA_CREATE_ADMINQ\";\n+\tdefault:\n+\t\treturn \"DEVCMD_UNKNOWN\";\n+\t}\n+}\n+\n+int\n+ionic_adminq_check_err(struct ionic_admin_ctx *ctx, bool timeout)\n+{\n+\tconst char *name;\n+\tconst char *status;\n+\n+\tif (ctx->comp.comp.status || timeout) {\n+\t\tname = ionic_opcode_to_str(ctx->cmd.cmd.opcode);\n+\t\tstatus = ionic_error_to_str(ctx->comp.comp.status);\n+\t\tIONIC_PRINT(ERR, \"%s (%d) failed: %s (%d)\",\n+\t\t\tname,\n+\t\t\tctx->cmd.cmd.opcode,\n+\t\t\ttimeout ? \"TIMEOUT\" : status,\n+\t\t\ttimeout ? -1 : ctx->comp.comp.status);\n+\t\treturn -EIO;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+ionic_wait_ctx_for_completion(struct ionic_lif *lif, struct ionic_qcq *qcq,\n+\t\tstruct ionic_admin_ctx *ctx, unsigned long max_wait)\n+{\n+\tunsigned long step_msec = 1;\n+\tunsigned int max_wait_msec = max_wait * 1000;\n+\tunsigned long elapsed_msec = 0;\n+\tint budget = 8;\n+\n+\twhile (ctx->pending_work && elapsed_msec < max_wait_msec) {\n+\t\t/*\n+\t\t * Locking here as adminq is served inline (this could be called\n+\t\t * from multiple places)\n+\t\t */\n+\t\trte_spinlock_lock(&lif->adminq_service_lock);\n+\n+\t\tionic_qcq_service(qcq, budget, ionic_adminq_service, NULL);\n+\n+\t\trte_spinlock_unlock(&lif->adminq_service_lock);\n+\n+\t\tmsec_delay(step_msec);\n+\t\telapsed_msec += step_msec;\n+\t}\n+\n+\treturn (!ctx->pending_work);\n+}\n+\n+int\n+ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)\n+{\n+\tstruct ionic_qcq *qcq = lif->adminqcq;\n+\tbool done;\n+\tint err;\n+\n+\tIONIC_PRINT(DEBUG, \"Sending %s to the admin queue\",\n+\t\tionic_opcode_to_str(ctx->cmd.cmd.opcode));\n+\n+\terr = ionic_adminq_post(lif, ctx);\n+\n+\tif (err) {\n+\t\tIONIC_PRINT(ERR, \"Failure posting to the admin queue %d (%d)\",\n+\t\t\tctx->cmd.cmd.opcode, err);\n+\n+\t\treturn err;\n+\t}\n+\n+\tdone = ionic_wait_ctx_for_completion(lif, qcq, ctx,\n+\t\tIONIC_DEVCMD_TIMEOUT);\n+\n+\terr = ionic_adminq_check_err(ctx, !done /* timed out */);\n+\n+\treturn err;\n+}\n \n static int\n ionic_dev_cmd_wait(struct ionic_dev *idev, unsigned long max_wait)\n",
    "prefixes": [
        "v3",
        "08/17"
    ]
}