get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 74048,
    "url": "http://patches.dpdk.org/api/patches/74048/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1594794114-16313-8-git-send-email-viacheslavo@mellanox.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": "<1594794114-16313-8-git-send-email-viacheslavo@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1594794114-16313-8-git-send-email-viacheslavo@mellanox.com",
    "date": "2020-07-15T06:21:44",
    "name": "[v2,07/17] net/mlx5: create Tx queues with DevX",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "f432c12cda548995c6c98310d7bf2b50c8204d01",
    "submitter": {
        "id": 1102,
        "url": "http://patches.dpdk.org/api/people/1102/?format=api",
        "name": "Slava Ovsiienko",
        "email": "viacheslavo@mellanox.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patches.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1594794114-16313-8-git-send-email-viacheslavo@mellanox.com/mbox/",
    "series": [
        {
            "id": 11032,
            "url": "http://patches.dpdk.org/api/series/11032/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11032",
            "date": "2020-07-15T06:21:37",
            "name": "net/mlx5: introduce accurate packet Tx scheduling",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/11032/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/74048/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/74048/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 9B330A0540;\n\tWed, 15 Jul 2020 08:23:06 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 0E5691C132;\n\tWed, 15 Jul 2020 08:22:17 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 860D11C129\n for <dev@dpdk.org>; Wed, 15 Jul 2020 08:22:12 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n viacheslavo@mellanox.com) with SMTP; 15 Jul 2020 09:22:11 +0300",
            "from pegasus12.mtr.labs.mlnx (pegasus12.mtr.labs.mlnx\n [10.210.17.40])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 06F6MBq8007035;\n Wed, 15 Jul 2020 09:22:11 +0300",
            "from pegasus12.mtr.labs.mlnx (localhost [127.0.0.1])\n by pegasus12.mtr.labs.mlnx (8.14.7/8.14.7) with ESMTP id 06F6MBGe016440;\n Wed, 15 Jul 2020 06:22:11 GMT",
            "(from viacheslavo@localhost)\n by pegasus12.mtr.labs.mlnx (8.14.7/8.14.7/Submit) id 06F6MBHx016439;\n Wed, 15 Jul 2020 06:22:11 GMT"
        ],
        "X-Authentication-Warning": "pegasus12.mtr.labs.mlnx: viacheslavo set sender to\n viacheslavo@mellanox.com using -f",
        "From": "Viacheslav Ovsiienko <viacheslavo@mellanox.com>",
        "To": "dev@dpdk.org",
        "Cc": "matan@mellanox.com, rasland@mellanox.com, olivier.matz@6wind.com,\n thomas@monjalon.net, ferruh.yigit@intel.com",
        "Date": "Wed, 15 Jul 2020 06:21:44 +0000",
        "Message-Id": "<1594794114-16313-8-git-send-email-viacheslavo@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1594794114-16313-1-git-send-email-viacheslavo@mellanox.com>",
        "References": "<1591771085-24959-1-git-send-email-viacheslavo@mellanox.com>\n <1594794114-16313-1-git-send-email-viacheslavo@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v2 07/17] net/mlx5: create Tx queues with DevX",
        "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": "To provide the packet send schedule on mbuf timestamp the Tx\nqueue must be attached to the same UAR as Clock Queue is.\nUAR is special hardware related resource mapped to the host\nmemory and provides doorbell registers, the assigning UAR\nto the queue being created is provided via DevX API only.\n\nSigned-off-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>\nAcked-by: Matan Azrad <matan@mellanox.com>\n---\n drivers/net/mlx5/mlx5_rxtx.c    | 108 +++++++++-----\n drivers/net/mlx5/mlx5_rxtx.h    |  14 ++\n drivers/net/mlx5/mlx5_trigger.c |   4 +-\n drivers/net/mlx5/mlx5_txq.c     | 306 +++++++++++++++++++++++++++++++++++++++-\n 4 files changed, 392 insertions(+), 40 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c\nindex 894f441..227289e 100644\n--- a/drivers/net/mlx5/mlx5_rxtx.c\n+++ b/drivers/net/mlx5/mlx5_rxtx.c\n@@ -944,43 +944,79 @@ enum mlx5_txcmp_code {\n \t\tstruct mlx5_txq_data *txq = (*priv->txqs)[sm->queue_id];\n \t\tstruct mlx5_txq_ctrl *txq_ctrl =\n \t\t\tcontainer_of(txq, struct mlx5_txq_ctrl, txq);\n-\t\tstruct ibv_qp_attr mod = {\n-\t\t\t.qp_state = IBV_QPS_RESET,\n-\t\t\t.port_num = (uint8_t)priv->dev_port,\n-\t\t};\n-\t\tstruct ibv_qp *qp = txq_ctrl->obj->qp;\n \n-\t\tret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);\n-\t\tif (ret) {\n-\t\t\tDRV_LOG(ERR, \"Cannot change the Tx QP state to RESET \"\n-\t\t\t\t\"%s\", strerror(errno));\n-\t\t\trte_errno = errno;\n-\t\t\treturn ret;\n-\t\t}\n-\t\tmod.qp_state = IBV_QPS_INIT;\n-\t\tret = mlx5_glue->modify_qp(qp, &mod,\n-\t\t\t\t\t   (IBV_QP_STATE | IBV_QP_PORT));\n-\t\tif (ret) {\n-\t\t\tDRV_LOG(ERR, \"Cannot change Tx QP state to INIT %s\",\n-\t\t\t\tstrerror(errno));\n-\t\t\trte_errno = errno;\n-\t\t\treturn ret;\n-\t\t}\n-\t\tmod.qp_state = IBV_QPS_RTR;\n-\t\tret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);\n-\t\tif (ret) {\n-\t\t\tDRV_LOG(ERR, \"Cannot change Tx QP state to RTR %s\",\n-\t\t\t\tstrerror(errno));\n-\t\t\trte_errno = errno;\n-\t\t\treturn ret;\n-\t\t}\n-\t\tmod.qp_state = IBV_QPS_RTS;\n-\t\tret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);\n-\t\tif (ret) {\n-\t\t\tDRV_LOG(ERR, \"Cannot change Tx QP state to RTS %s\",\n-\t\t\t\tstrerror(errno));\n-\t\t\trte_errno = errno;\n-\t\t\treturn ret;\n+\t\tif (txq_ctrl->obj->type == MLX5_TXQ_OBJ_TYPE_DEVX_SQ) {\n+\t\t\tstruct mlx5_devx_modify_sq_attr msq_attr = { 0 };\n+\n+\t\t\t/* Change queue state to reset. */\n+\t\t\tmsq_attr.sq_state = MLX5_SQC_STATE_ERR;\n+\t\t\tmsq_attr.state = MLX5_SQC_STATE_RST;\n+\t\t\tret = mlx5_devx_cmd_modify_sq(txq_ctrl->obj->sq_devx,\n+\t\t\t\t\t\t      &msq_attr);\n+\t\t\tif (ret) {\n+\t\t\t\tDRV_LOG(ERR, \"Cannot change the \"\n+\t\t\t\t\t\"Tx QP state to RESET %s\",\n+\t\t\t\t\tstrerror(errno));\n+\t\t\t\trte_errno = errno;\n+\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t\t/* Change queue state to ready. */\n+\t\t\tmsq_attr.sq_state = MLX5_SQC_STATE_RST;\n+\t\t\tmsq_attr.state = MLX5_SQC_STATE_RDY;\n+\t\t\tret = mlx5_devx_cmd_modify_sq(txq_ctrl->obj->sq_devx,\n+\t\t\t\t\t\t      &msq_attr);\n+\t\t\tif (ret) {\n+\t\t\t\tDRV_LOG(ERR, \"Cannot change the \"\n+\t\t\t\t\t\"Tx QP state to READY %s\",\n+\t\t\t\t\tstrerror(errno));\n+\t\t\t\trte_errno = errno;\n+\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tstruct ibv_qp_attr mod = {\n+\t\t\t\t.qp_state = IBV_QPS_RESET,\n+\t\t\t\t.port_num = (uint8_t)priv->dev_port,\n+\t\t\t};\n+\t\t\tstruct ibv_qp *qp = txq_ctrl->obj->qp;\n+\n+\t\t\tMLX5_ASSERT\n+\t\t\t\t(txq_ctrl->obj->type == MLX5_TXQ_OBJ_TYPE_IBV);\n+\n+\t\t\tret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);\n+\t\t\tif (ret) {\n+\t\t\t\tDRV_LOG(ERR, \"Cannot change the \"\n+\t\t\t\t\t\"Tx QP state to RESET %s\",\n+\t\t\t\t\tstrerror(errno));\n+\t\t\t\trte_errno = errno;\n+\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t\tmod.qp_state = IBV_QPS_INIT;\n+\t\t\tret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);\n+\t\t\tif (ret) {\n+\t\t\t\tDRV_LOG(ERR, \"Cannot change the \"\n+\t\t\t\t\t\"Tx QP state to INIT %s\",\n+\t\t\t\t\tstrerror(errno));\n+\t\t\t\trte_errno = errno;\n+\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t\tmod.qp_state = IBV_QPS_RTR;\n+\t\t\tret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);\n+\t\t\tif (ret) {\n+\t\t\t\tDRV_LOG(ERR, \"Cannot change the \"\n+\t\t\t\t\t\"Tx QP state to RTR %s\",\n+\t\t\t\t\tstrerror(errno));\n+\t\t\t\trte_errno = errno;\n+\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t\tmod.qp_state = IBV_QPS_RTS;\n+\t\t\tret = mlx5_glue->modify_qp(qp, &mod, IBV_QP_STATE);\n+\t\t\tif (ret) {\n+\t\t\t\tDRV_LOG(ERR, \"Cannot change the \"\n+\t\t\t\t\t\"Tx QP state to RTS %s\",\n+\t\t\t\t\tstrerror(errno));\n+\t\t\t\trte_errno = errno;\n+\t\t\t\treturn ret;\n+\t\t\t}\n \t\t}\n \t}\n \treturn 0;\ndiff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h\nindex 26621ff..1b797da 100644\n--- a/drivers/net/mlx5/mlx5_rxtx.h\n+++ b/drivers/net/mlx5/mlx5_rxtx.h\n@@ -323,6 +323,7 @@ struct mlx5_txq_data {\n \n enum mlx5_txq_obj_type {\n \tMLX5_TXQ_OBJ_TYPE_IBV,\t\t/* mlx5_txq_obj with ibv_wq. */\n+\tMLX5_TXQ_OBJ_TYPE_DEVX_SQ,\t/* mlx5_txq_obj with mlx5_devx_sq. */\n \tMLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN,\n \t/* mlx5_txq_obj with mlx5_devx_tq and hairpin support. */\n };\n@@ -349,6 +350,19 @@ struct mlx5_txq_obj {\n \t\t\t/* DevX object for Sx queue. */\n \t\t\tstruct mlx5_devx_obj *tis; /* The TIS object. */\n \t\t};\n+\t\tstruct {\n+\t\t\tstruct rte_eth_dev *dev;\n+\t\t\tstruct mlx5_devx_obj *cq_devx;\n+\t\t\tstruct mlx5dv_devx_umem *cq_umem;\n+\t\t\tvoid *cq_buf;\n+\t\t\tint64_t cq_dbrec_offset;\n+\t\t\tstruct mlx5_devx_dbr_page *cq_dbrec_page;\n+\t\t\tstruct mlx5_devx_obj *sq_devx;\n+\t\t\tstruct mlx5dv_devx_umem *sq_umem;\n+\t\t\tvoid *sq_buf;\n+\t\t\tint64_t sq_dbrec_offset;\n+\t\t\tstruct mlx5_devx_dbr_page *sq_dbrec_page;\n+\t\t};\n \t};\n };\n \ndiff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c\nindex ca25ad9..e324319 100644\n--- a/drivers/net/mlx5/mlx5_trigger.c\n+++ b/drivers/net/mlx5/mlx5_trigger.c\n@@ -59,7 +59,9 @@\n \t\t} else {\n \t\t\ttxq_alloc_elts(txq_ctrl);\n \t\t\ttxq_ctrl->obj = mlx5_txq_obj_new\n-\t\t\t\t(dev, i, MLX5_TXQ_OBJ_TYPE_IBV);\n+\t\t\t\t(dev, i, priv->txpp_en ?\n+\t\t\t\tMLX5_TXQ_OBJ_TYPE_DEVX_SQ :\n+\t\t\t\tMLX5_TXQ_OBJ_TYPE_IBV);\n \t\t}\n \t\tif (!txq_ctrl->obj) {\n \t\t\trte_errno = ENOMEM;\ndiff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c\nindex e1fa24e..f9ed504 100644\n--- a/drivers/net/mlx5/mlx5_txq.c\n+++ b/drivers/net/mlx5/mlx5_txq.c\n@@ -31,6 +31,7 @@\n #include <mlx5_devx_cmds.h>\n #include <mlx5_common.h>\n #include <mlx5_common_mr.h>\n+#include <mlx5_common_os.h>\n \n #include \"mlx5_defs.h\"\n #include \"mlx5_utils.h\"\n@@ -573,6 +574,297 @@\n }\n \n /**\n+ * Destroy the Tx queue DevX object.\n+ *\n+ * @param txq_obj\n+ *   Txq object to destroy\n+ */\n+static void\n+txq_release_sq_resources(struct mlx5_txq_obj *txq_obj)\n+{\n+\tMLX5_ASSERT(txq_obj->type == MLX5_TXQ_OBJ_TYPE_DEVX_SQ);\n+\n+\tif (txq_obj->sq_devx)\n+\t\tclaim_zero(mlx5_devx_cmd_destroy(txq_obj->sq_devx));\n+\tif (txq_obj->sq_dbrec_page)\n+\t\tclaim_zero(mlx5_release_dbr\n+\t\t\t\t(&txq_obj->txq_ctrl->priv->dbrpgs,\n+\t\t\t\tmlx5_os_get_umem_id\n+\t\t\t\t\t(txq_obj->sq_dbrec_page->umem),\n+\t\t\t\ttxq_obj->sq_dbrec_offset));\n+\tif (txq_obj->sq_umem)\n+\t\tclaim_zero(mlx5_glue->devx_umem_dereg(txq_obj->sq_umem));\n+\tif (txq_obj->sq_buf)\n+\t\trte_free(txq_obj->sq_buf);\n+\tif (txq_obj->cq_devx)\n+\t\tclaim_zero(mlx5_devx_cmd_destroy(txq_obj->cq_devx));\n+\tif (txq_obj->cq_dbrec_page)\n+\t\tclaim_zero(mlx5_release_dbr\n+\t\t\t\t(&txq_obj->txq_ctrl->priv->dbrpgs,\n+\t\t\t\tmlx5_os_get_umem_id\n+\t\t\t\t\t(txq_obj->cq_dbrec_page->umem),\n+\t\t\t\ttxq_obj->cq_dbrec_offset));\n+\tif (txq_obj->cq_umem)\n+\t\tclaim_zero(mlx5_glue->devx_umem_dereg(txq_obj->cq_umem));\n+\tif (txq_obj->cq_buf)\n+\t\trte_free(txq_obj->cq_buf);\n+}\n+\n+/**\n+ * Create the Tx queue DevX object.\n+ *\n+ * @param dev\n+ *   Pointer to Ethernet device.\n+ * @param idx\n+ *   Queue index in DPDK Tx queue array\n+ *\n+ * @return\n+ *   The DevX object initialised, NULL otherwise and rte_errno is set.\n+ */\n+static struct mlx5_txq_obj *\n+mlx5_txq_obj_devx_new(struct rte_eth_dev *dev, uint16_t idx)\n+{\n+#ifndef HAVE_MLX5DV_DEVX_UAR_OFFSET\n+\tDRV_LOG(ERR, \"port %u Tx queue %u cannot create with DevX, no UAR\",\n+\t\t     dev->data->port_id, idx);\n+\trte_errno = ENOMEM;\n+\treturn NULL;\n+#else\n+\tstruct mlx5_priv *priv = dev->data->dev_private;\n+\tstruct mlx5_dev_ctx_shared *sh = priv->sh;\n+\tstruct mlx5_txq_data *txq_data = (*priv->txqs)[idx];\n+\tstruct mlx5_txq_ctrl *txq_ctrl =\n+\t\tcontainer_of(txq_data, struct mlx5_txq_ctrl, txq);\n+\tstruct mlx5_devx_create_sq_attr sq_attr = { 0 };\n+\tstruct mlx5_devx_modify_sq_attr msq_attr = { 0 };\n+\tstruct mlx5_devx_cq_attr cq_attr = { 0 };\n+\tstruct mlx5_txq_obj *txq_obj = NULL;\n+\tsize_t page_size = sysconf(_SC_PAGESIZE);\n+\tstruct mlx5_cqe *cqe;\n+\tuint32_t i, nqe;\n+\tint ret = 0;\n+\n+\tMLX5_ASSERT(txq_data);\n+\tMLX5_ASSERT(!txq_ctrl->obj);\n+\ttxq_obj = rte_calloc_socket(__func__, 1,\n+\t\t\t\t    sizeof(struct mlx5_txq_obj), 0,\n+\t\t\t\t    txq_ctrl->socket);\n+\tif (!txq_obj) {\n+\t\tDRV_LOG(ERR,\n+\t\t\t\"port %u Tx queue %u cannot allocate memory resources\",\n+\t\t\tdev->data->port_id, txq_data->idx);\n+\t\trte_errno = ENOMEM;\n+\t\treturn NULL;\n+\t}\n+\ttxq_obj->type = MLX5_TXQ_OBJ_TYPE_DEVX_SQ;\n+\ttxq_obj->txq_ctrl = txq_ctrl;\n+\ttxq_obj->dev = dev;\n+\t/* Create the Completion Queue. */\n+\tnqe = (1UL << txq_data->elts_n) / MLX5_TX_COMP_THRESH +\n+\t       1 + MLX5_TX_COMP_THRESH_INLINE_DIV;\n+\tnqe = 1UL << log2above(nqe);\n+\tif (nqe > UINT16_MAX) {\n+\t\tDRV_LOG(ERR,\n+\t\t\t\"port %u Tx queue %u requests to many CQEs %u\",\n+\t\t\tdev->data->port_id, txq_data->idx, nqe);\n+\t\trte_errno = EINVAL;\n+\t\tgoto error;\n+\t}\n+\t/* Allocate memory buffer for CQEs. */\n+\ttxq_obj->cq_buf = rte_zmalloc_socket(__func__,\n+\t\t\t\t\t     nqe * sizeof(struct mlx5_cqe),\n+\t\t\t\t\t     MLX5_CQE_BUF_ALIGNMENT,\n+\t\t\t\t\t     sh->numa_node);\n+\tif (!txq_obj->cq_buf) {\n+\t\tDRV_LOG(ERR,\n+\t\t\t\"port %u Tx queue %u cannot allocate memory (CQ)\",\n+\t\t\tdev->data->port_id, txq_data->idx);\n+\t\trte_errno = ENOMEM;\n+\t\tgoto error;\n+\t}\n+\ttxq_data->cqe_n = log2above(nqe);\n+\ttxq_data->cqe_s = 1 << txq_data->cqe_n;\n+\ttxq_data->cqe_m = txq_data->cqe_s - 1;\n+\ttxq_data->cqes = (volatile struct mlx5_cqe *)txq_obj->cq_buf;\n+\ttxq_data->cq_ci = 0;\n+\ttxq_data->cq_pi = 0;\n+\t/* Register allocated buffer in user space with DevX. */\n+\ttxq_obj->cq_umem = mlx5_glue->devx_umem_reg\n+\t\t\t\t\t(sh->ctx,\n+\t\t\t\t\t (void *)txq_obj->cq_buf,\n+\t\t\t\t\t nqe * sizeof(struct mlx5_cqe),\n+\t\t\t\t\t IBV_ACCESS_LOCAL_WRITE);\n+\tif (!txq_obj->cq_umem) {\n+\t\trte_errno = errno;\n+\t\tDRV_LOG(ERR,\n+\t\t\t\"port %u Tx queue %u cannot register memory (CQ)\",\n+\t\t\tdev->data->port_id, txq_data->idx);\n+\t\tgoto error;\n+\t}\n+\t/* Allocate doorbell record for completion queue. */\n+\ttxq_obj->cq_dbrec_offset = mlx5_get_dbr(sh->ctx,\n+\t\t\t\t\t\t&priv->dbrpgs,\n+\t\t\t\t\t\t&txq_obj->cq_dbrec_page);\n+\tif (txq_obj->cq_dbrec_offset < 0)\n+\t\tgoto error;\n+\ttxq_data->cq_db = (volatile uint32_t *)(txq_obj->cq_dbrec_page->dbrs +\n+\t\t\t\t\t\ttxq_obj->cq_dbrec_offset);\n+\t*txq_data->cq_db = 0;\n+\t/* Create completion queue object with DevX. */\n+\tcq_attr.cqe_size = (sizeof(struct mlx5_cqe) == 128) ?\n+\t\t\t    MLX5_CQE_SIZE_128B : MLX5_CQE_SIZE_64B;\n+\tcq_attr.uar_page_id = sh->tx_uar->page_id;\n+\tcq_attr.eqn = sh->txpp.eqn;\n+\tcq_attr.q_umem_valid = 1;\n+\tcq_attr.q_umem_offset = (uintptr_t)txq_obj->cq_buf % page_size;\n+\tcq_attr.q_umem_id = txq_obj->cq_umem->umem_id;\n+\tcq_attr.db_umem_valid = 1;\n+\tcq_attr.db_umem_offset = txq_obj->cq_dbrec_offset;\n+\tcq_attr.db_umem_id = mlx5_os_get_umem_id(txq_obj->cq_dbrec_page->umem);\n+\tcq_attr.log_cq_size = rte_log2_u32(nqe);\n+\tcq_attr.log_page_size = rte_log2_u32(page_size);\n+\ttxq_obj->cq_devx = mlx5_devx_cmd_create_cq(sh->ctx, &cq_attr);\n+\tif (!txq_obj->cq_devx) {\n+\t\trte_errno = errno;\n+\t\tDRV_LOG(ERR, \"port %u Tx queue %u CQ creation failure\",\n+\t\t\tdev->data->port_id, idx);\n+\t\tgoto error;\n+\t}\n+\t/* Initial fill CQ buffer with invalid CQE opcode. */\n+\tcqe = (struct mlx5_cqe *)txq_obj->cq_buf;\n+\tfor (i = 0; i < txq_data->cqe_s; i++) {\n+\t\tcqe->op_own = (MLX5_CQE_INVALID << 4) | MLX5_CQE_OWNER_MASK;\n+\t\t++cqe;\n+\t}\n+\t/* Create the Work Queue. */\n+\tnqe = RTE_MIN(1UL << txq_data->elts_n,\n+\t\t      (uint32_t)sh->device_attr.max_qp_wr);\n+\ttxq_obj->sq_buf = rte_zmalloc_socket(__func__,\n+\t\t\t\t\t     nqe * sizeof(struct mlx5_wqe),\n+\t\t\t\t\t     page_size,\n+\t\t\t\t\t     sh->numa_node);\n+\tif (!txq_obj->sq_buf) {\n+\t\tDRV_LOG(ERR,\n+\t\t\t\"port %u Tx queue %u cannot allocate memory (SQ)\",\n+\t\t\tdev->data->port_id, txq_data->idx);\n+\t\trte_errno = ENOMEM;\n+\t\tgoto error;\n+\t}\n+\ttxq_data->wqe_n = log2above(nqe);\n+\ttxq_data->wqe_s = 1 << txq_data->wqe_n;\n+\ttxq_data->wqe_m = txq_data->wqe_s - 1;\n+\ttxq_data->wqes = (struct mlx5_wqe *)txq_obj->sq_buf;\n+\ttxq_data->wqes_end = txq_data->wqes + txq_data->wqe_s;\n+\ttxq_data->wqe_ci = 0;\n+\ttxq_data->wqe_pi = 0;\n+\ttxq_data->wqe_comp = 0;\n+\ttxq_data->wqe_thres = txq_data->wqe_s / MLX5_TX_COMP_THRESH_INLINE_DIV;\n+\t/* Register allocated buffer in user space with DevX. */\n+\ttxq_obj->sq_umem = mlx5_glue->devx_umem_reg\n+\t\t\t\t\t(sh->ctx,\n+\t\t\t\t\t (void *)txq_obj->sq_buf,\n+\t\t\t\t\t nqe * sizeof(struct mlx5_wqe),\n+\t\t\t\t\t IBV_ACCESS_LOCAL_WRITE);\n+\tif (!txq_obj->sq_umem) {\n+\t\trte_errno = errno;\n+\t\tDRV_LOG(ERR,\n+\t\t\t\"port %u Tx queue %u cannot register memory (SQ)\",\n+\t\t\tdev->data->port_id, txq_data->idx);\n+\t\tgoto error;\n+\t}\n+\t/* Allocate doorbell record for completion queue. */\n+\ttxq_obj->cq_dbrec_offset = mlx5_get_dbr(sh->ctx,\n+\t\t\t\t\t\t&priv->dbrpgs,\n+\t\t\t\t\t\t&txq_obj->sq_dbrec_page);\n+\tif (txq_obj->sq_dbrec_offset < 0)\n+\t\tgoto error;\n+\ttxq_data->qp_db = (volatile uint32_t *)\n+\t\t\t\t\t(txq_obj->sq_dbrec_page->dbrs +\n+\t\t\t\t\t txq_obj->sq_dbrec_offset +\n+\t\t\t\t\t MLX5_SND_DBR * sizeof(uint32_t));\n+\t*txq_data->qp_db = 0;\n+\t/* Create Send Queue object with DevX. */\n+\tsq_attr.tis_lst_sz = 1;\n+\tsq_attr.tis_num = sh->tis->id;\n+\tsq_attr.state = MLX5_SQC_STATE_RST;\n+\tsq_attr.cqn = txq_obj->cq_devx->id;\n+\tsq_attr.flush_in_error_en = 1;\n+\tsq_attr.allow_multi_pkt_send_wqe = !!priv->config.mps;\n+\tsq_attr.allow_swp = !!priv->config.swp;\n+\tsq_attr.min_wqe_inline_mode = priv->config.hca_attr.vport_inline_mode;\n+\tsq_attr.wq_attr.uar_page = sh->tx_uar->page_id;\n+\tsq_attr.wq_attr.wq_type = MLX5_WQ_TYPE_CYCLIC;\n+\tsq_attr.wq_attr.pd = sh->pdn;\n+\tsq_attr.wq_attr.log_wq_stride = rte_log2_u32(MLX5_WQE_SIZE);\n+\tsq_attr.wq_attr.log_wq_sz = txq_data->wqe_n;\n+\tsq_attr.wq_attr.dbr_umem_valid = 1;\n+\tsq_attr.wq_attr.dbr_addr = txq_obj->cq_dbrec_offset;\n+\tsq_attr.wq_attr.dbr_umem_id =\n+\t\t\tmlx5_os_get_umem_id(txq_obj->cq_dbrec_page->umem);\n+\tsq_attr.wq_attr.wq_umem_valid = 1;\n+\tsq_attr.wq_attr.wq_umem_id = txq_obj->sq_umem->umem_id;\n+\tsq_attr.wq_attr.wq_umem_offset = (uintptr_t)txq_obj->sq_buf % page_size;\n+\ttxq_obj->sq_devx = mlx5_devx_cmd_create_sq(sh->ctx, &sq_attr);\n+\tif (!txq_obj->sq_devx) {\n+\t\trte_errno = errno;\n+\t\tDRV_LOG(ERR, \"port %u Tx queue %u SQ creation failure\",\n+\t\t\tdev->data->port_id, idx);\n+\t\tgoto error;\n+\t}\n+\ttxq_data->qp_num_8s = txq_obj->sq_devx->id << 8;\n+\t/* Change Send Queue state to Ready-to-Send. */\n+\tmsq_attr.sq_state = MLX5_SQC_STATE_RST;\n+\tmsq_attr.state = MLX5_SQC_STATE_RDY;\n+\tret = mlx5_devx_cmd_modify_sq(txq_obj->sq_devx, &msq_attr);\n+\tif (ret) {\n+\t\trte_errno = errno;\n+\t\tDRV_LOG(ERR,\n+\t\t\t\"port %u Tx queue %u SP state to SQC_STATE_RDY failed\",\n+\t\t\tdev->data->port_id, idx);\n+\t\tgoto error;\n+\t}\n+\ttxq_data->fcqs = rte_calloc_socket(__func__,\n+\t\t\t\t\t   txq_data->cqe_s,\n+\t\t\t\t\t   sizeof(*txq_data->fcqs),\n+\t\t\t\t\t   RTE_CACHE_LINE_SIZE,\n+\t\t\t\t\t   txq_ctrl->socket);\n+\tif (!txq_data->fcqs) {\n+\t\tDRV_LOG(ERR, \"port %u Tx queue %u cannot allocate memory (FCQ)\",\n+\t\t\tdev->data->port_id, idx);\n+\t\trte_errno = ENOMEM;\n+\t\tgoto error;\n+\t}\n+#ifdef HAVE_IBV_FLOW_DV_SUPPORT\n+\t/*\n+\t * If using DevX need to query and store TIS transport domain value.\n+\t * This is done once per port.\n+\t * Will use this value on Rx, when creating matching TIR.\n+\t */\n+\tif (priv->config.devx && !priv->sh->tdn)\n+\t\tpriv->sh->tdn = priv->sh->td->id;\n+#endif\n+\tMLX5_ASSERT(sh->tx_uar);\n+\tMLX5_ASSERT(sh->tx_uar->reg_addr);\n+\ttxq_ctrl->bf_reg = sh->tx_uar->reg_addr;\n+\ttxq_ctrl->uar_mmap_offset = sh->tx_uar->mmap_off;\n+\trte_atomic32_set(&txq_obj->refcnt, 1);\n+\ttxq_uar_init(txq_ctrl);\n+\tLIST_INSERT_HEAD(&priv->txqsobj, txq_obj, next);\n+\treturn txq_obj;\n+error:\n+\tret = rte_errno; /* Save rte_errno before cleanup. */\n+\ttxq_release_sq_resources(txq_obj);\n+\tif (txq_data->fcqs) {\n+\t\trte_free(txq_data->fcqs);\n+\t\ttxq_data->fcqs = NULL;\n+\t}\n+\trte_free(txq_obj);\n+\trte_errno = ret; /* Restore rte_errno. */\n+\treturn NULL;\n+#endif\n+}\n+\n+/**\n  * Create the Tx queue Verbs object.\n  *\n  * @param dev\n@@ -609,6 +901,8 @@ struct mlx5_txq_obj *\n \n \tif (type == MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN)\n \t\treturn mlx5_txq_obj_hairpin_new(dev, idx);\n+\tif (type == MLX5_TXQ_OBJ_TYPE_DEVX_SQ)\n+\t\treturn mlx5_txq_obj_devx_new(dev, idx);\n #ifdef HAVE_IBV_FLOW_DV_SUPPORT\n \t/* If using DevX, need additional mask to read tisn value. */\n \tif (priv->config.devx && !priv->sh->tdn)\n@@ -817,8 +1111,10 @@ struct mlx5_txq_obj *\n \t\tclaim_zero(mlx5_glue->destroy_cq(tmpl.cq));\n \tif (tmpl.qp)\n \t\tclaim_zero(mlx5_glue->destroy_qp(tmpl.qp));\n-\tif (txq_data->fcqs)\n+\tif (txq_data && txq_data->fcqs) {\n \t\trte_free(txq_data->fcqs);\n+\t\ttxq_data->fcqs = NULL;\n+\t}\n \tif (txq_obj)\n \t\trte_free(txq_obj);\n \tpriv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_NONE;\n@@ -870,11 +1166,15 @@ struct mlx5_txq_obj *\n \t\tif (txq_obj->type == MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN) {\n \t\t\tif (txq_obj->tis)\n \t\t\t\tclaim_zero(mlx5_devx_cmd_destroy(txq_obj->tis));\n+\t\t} else if (txq_obj->type == MLX5_TXQ_OBJ_TYPE_DEVX_SQ) {\n+\t\t\ttxq_release_sq_resources(txq_obj);\n \t\t} else {\n \t\t\tclaim_zero(mlx5_glue->destroy_qp(txq_obj->qp));\n \t\t\tclaim_zero(mlx5_glue->destroy_cq(txq_obj->cq));\n-\t\t\t\tif (txq_obj->txq_ctrl->txq.fcqs)\n-\t\t\t\t\trte_free(txq_obj->txq_ctrl->txq.fcqs);\n+\t\t}\n+\t\tif (txq_obj->txq_ctrl->txq.fcqs) {\n+\t\t\trte_free(txq_obj->txq_ctrl->txq.fcqs);\n+\t\t\ttxq_obj->txq_ctrl->txq.fcqs = NULL;\n \t\t}\n \t\tLIST_REMOVE(txq_obj, next);\n \t\trte_free(txq_obj);\n",
    "prefixes": [
        "v2",
        "07/17"
    ]
}