get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 14329,
    "url": "http://patches.dpdk.org/api/patches/14329/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1466758261-25986-18-git-send-email-nelio.laranjeiro@6wind.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": "<1466758261-25986-18-git-send-email-nelio.laranjeiro@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1466758261-25986-18-git-send-email-nelio.laranjeiro@6wind.com",
    "date": "2016-06-24T08:50:53",
    "name": "[dpdk-dev,v6,17/25] mlx5: add support for inline send",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": true,
    "hash": "b9667e6947448a2245756949c818e73e2af77669",
    "submitter": {
        "id": 243,
        "url": "http://patches.dpdk.org/api/people/243/?format=api",
        "name": "Nélio Laranjeiro",
        "email": "nelio.laranjeiro@6wind.com"
    },
    "delegate": {
        "id": 10,
        "url": "http://patches.dpdk.org/api/users/10/?format=api",
        "username": "bruce",
        "first_name": "Bruce",
        "last_name": "Richardson",
        "email": "bruce.richardson@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1466758261-25986-18-git-send-email-nelio.laranjeiro@6wind.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/14329/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/14329/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 [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 78977C714;\n\tFri, 24 Jun 2016 10:53:55 +0200 (CEST)",
            "from mail-wm0-f51.google.com (mail-wm0-f51.google.com\n\t[74.125.82.51]) by dpdk.org (Postfix) with ESMTP id EE406C68E\n\tfor <dev@dpdk.org>; Fri, 24 Jun 2016 10:53:45 +0200 (CEST)",
            "by mail-wm0-f51.google.com with SMTP id a66so16019414wme.0\n\tfor <dev@dpdk.org>; Fri, 24 Jun 2016 01:53:45 -0700 (PDT)",
            "from ping.vm.6wind.com (guy78-3-82-239-227-177.fbx.proxad.net.\n\t[82.239.227.177]) by smtp.gmail.com with ESMTPSA id\n\tt188sm2060584wma.8.2016.06.24.01.53.44\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tFri, 24 Jun 2016 01:53:44 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=6g1UYPO7JYBhkBGsZYCeMpv3qmPV+CYPDtYEPSCjPKM=;\n\tb=JbN5pe5YrpdlKO5jbvFKaS2ijQckk6SPte5xkzsxWTMT+TJ7hDOegSwZiLT2Jq9bhw\n\tqwK7tBtytqQdN0WmXwxOmnGmhd886U8/Yz6/8Q/1u8LIUowuvuNGmz3YxWdAn4gWQPAm\n\tnj68UISq/4wivfk69DjkF47uyzPKLOCSu0ItOJgLibEMhWwtGivnLEwnfHW8J8LGsOzx\n\t/f4o1TwkJv5FgFozyLOsLJwjHMm/Dovx50mBaMW+Gd1xnxiHHwIWAGcfKtX3XDwgbFTV\n\tfIzbrx589LtAzKjO4xJ81VYrXh7HulowH01cOSpiQST53kb6R3ybYsxQYvC3k83YS3vy\n\thYpg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=6g1UYPO7JYBhkBGsZYCeMpv3qmPV+CYPDtYEPSCjPKM=;\n\tb=cCCHS1oJOVhkYKEFX91h/AfZ4Xgb7Z/nPqGvUAMpri7e1NKSJMs/RoojtKtk4si5b2\n\t5lRNSU1aOpG/0IPuM86KZbbot7gBnAFZKcFZZh2IAZ0wHVdA6UIj/tg1kzMz6kbKPtV/\n\tV1dsLsNjrobs8tzi+IJztb82O/XyvQ7EIBHDC5KwQlE6Z2+9isy+pkTI05HYDXON6Cb+\n\tR5D8d+zbMaCtUJuPTSuSudpMTSIlZg5HLCOUaju6m6/EUJKOs9n/knz75ja276gCoPxN\n\tcama2hxMN+hI5uDpUmoDLAVIyEaYmQEgL50/BdZ3J/PME7JW4u2mozYzvb0Qn5BQ6how\n\tahRw==",
        "X-Gm-Message-State": "ALyK8tKsnhl2sVE1DRGmHlbksk7IfcsE+vCa8pMsRAzs4mo4U4qodhHEeftgfrMyfaTcLyvt",
        "X-Received": "by 10.28.95.196 with SMTP id t187mr17976209wmb.89.1466758425388; \n\tFri, 24 Jun 2016 01:53:45 -0700 (PDT)",
        "From": "Nelio Laranjeiro <nelio.laranjeiro@6wind.com>",
        "To": "dev@dpdk.org",
        "Cc": "Bruce Richardson <bruce.richardson@intel.com>,\n\tFerruh Yigit <ferruh.yigit@intel.com>,\n\tYaacov Hazan <yaacovh@mellanox.com>, \n\tAdrien Mazarguil <adrien.mazarguil@6wind.com>",
        "Date": "Fri, 24 Jun 2016 10:50:53 +0200",
        "Message-Id": "<1466758261-25986-18-git-send-email-nelio.laranjeiro@6wind.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": "<1466758261-25986-1-git-send-email-nelio.laranjeiro@6wind.com>",
        "References": "<1466700801-10383-1-git-send-email-nelio.laranjeiro@6wind.com>\n\t<1466758261-25986-1-git-send-email-nelio.laranjeiro@6wind.com>",
        "Subject": "[dpdk-dev] [PATCH v6 17/25] mlx5: add support for inline send",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Yaacov Hazan <yaacovh@mellanox.com>\n\nImplement send inline feature which copies packet data directly into WQEs\nfor improved latency. The maximum packet size and the minimum number of Tx\nqueues to qualify for inline send are user-configurable.\n\nThis feature is effective when HW causes a performance bottleneck.\n\nSigned-off-by: Yaacov Hazan <yaacovh@mellanox.com>\nSigned-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>\nSigned-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>\n---\n doc/guides/nics/mlx5.rst       |  17 +++\n drivers/net/mlx5/mlx5.c        |  15 +++\n drivers/net/mlx5/mlx5.h        |   2 +\n drivers/net/mlx5/mlx5_ethdev.c |   5 +\n drivers/net/mlx5/mlx5_rxtx.c   | 273 +++++++++++++++++++++++++++++++++++++++++\n drivers/net/mlx5/mlx5_rxtx.h   |   2 +\n drivers/net/mlx5/mlx5_txq.c    |   4 +\n 7 files changed, 318 insertions(+)",
    "diff": "diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst\nindex 756153b..9ada221 100644\n--- a/doc/guides/nics/mlx5.rst\n+++ b/doc/guides/nics/mlx5.rst\n@@ -154,6 +154,23 @@ Run-time configuration\n   allows to save PCI bandwidth and improve performance at the cost of a\n   slightly higher CPU usage.  Enabled by default.\n \n+- ``txq_inline`` parameter [int]\n+\n+  Amount of data to be inlined during TX operations. Improves latency.\n+  Can improve PPS performance when PCI back pressure is detected and may be\n+  useful for scenarios involving heavy traffic on many queues.\n+\n+  It is not enabled by default (set to 0) since the additional software\n+  logic necessary to handle this mode can lower performance when back\n+  pressure is not expected.\n+\n+- ``txqs_min_inline`` parameter [int]\n+\n+  Enable inline send only when the number of TX queues is greater or equal\n+  to this value.\n+\n+  This option should be used in combination with ``txq_inline`` above.\n+\n Prerequisites\n -------------\n \ndiff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 0257d34..2d63a48 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -72,6 +72,15 @@\n /* Device parameter to enable RX completion queue compression. */\n #define MLX5_RXQ_CQE_COMP_EN \"rxq_cqe_comp_en\"\n \n+/* Device parameter to configure inline send. */\n+#define MLX5_TXQ_INLINE \"txq_inline\"\n+\n+/*\n+ * Device parameter to configure the number of TX queues threshold for\n+ * enabling inline send.\n+ */\n+#define MLX5_TXQS_MIN_INLINE \"txqs_min_inline\"\n+\n /**\n  * Retrieve integer value from environment variable.\n  *\n@@ -269,6 +278,10 @@ mlx5_args_check(const char *key, const char *val, void *opaque)\n \t}\n \tif (strcmp(MLX5_RXQ_CQE_COMP_EN, key) == 0) {\n \t\tpriv->cqe_comp = !!tmp;\n+\t} else if (strcmp(MLX5_TXQ_INLINE, key) == 0) {\n+\t\tpriv->txq_inline = tmp;\n+\t} else if (strcmp(MLX5_TXQS_MIN_INLINE, key) == 0) {\n+\t\tpriv->txqs_inline = tmp;\n \t} else {\n \t\tWARN(\"%s: unknown parameter\", key);\n \t\treturn -EINVAL;\n@@ -292,6 +305,8 @@ mlx5_args(struct priv *priv, struct rte_devargs *devargs)\n {\n \tconst char **params = (const char *[]){\n \t\tMLX5_RXQ_CQE_COMP_EN,\n+\t\tMLX5_TXQ_INLINE,\n+\t\tMLX5_TXQS_MIN_INLINE,\n \t};\n \tstruct rte_kvargs *kvlist;\n \tint ret = 0;\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 8f5a6df..3a86609 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -113,6 +113,8 @@ struct priv {\n \tunsigned int mps:1; /* Whether multi-packet send is supported. */\n \tunsigned int cqe_comp:1; /* Whether CQE compression is enabled. */\n \tunsigned int pending_alarm:1; /* An alarm is pending. */\n+\tunsigned int txq_inline; /* Maximum packet size for inlining. */\n+\tunsigned int txqs_inline; /* Queue number threshold for inlining. */\n \t/* RX/TX queues. */\n \tunsigned int rxqs_n; /* RX queues array size. */\n \tunsigned int txqs_n; /* TX queues array size. */\ndiff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c\nindex 47e64b2..aeea4ff 100644\n--- a/drivers/net/mlx5/mlx5_ethdev.c\n+++ b/drivers/net/mlx5/mlx5_ethdev.c\n@@ -1318,6 +1318,11 @@ void\n priv_select_tx_function(struct priv *priv)\n {\n \tpriv->dev->tx_pkt_burst = mlx5_tx_burst;\n+\tif (priv->txq_inline && (priv->txqs_n >= priv->txqs_inline)) {\n+\t\tpriv->dev->tx_pkt_burst = mlx5_tx_burst_inline;\n+\t\tDEBUG(\"selected inline TX function (%u >= %u queues)\",\n+\t\t      priv->txqs_n, priv->txqs_inline);\n+\t}\n }\n \n /**\ndiff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c\nindex 9d992c3..daa22d9 100644\n--- a/drivers/net/mlx5/mlx5_rxtx.c\n+++ b/drivers/net/mlx5/mlx5_rxtx.c\n@@ -376,6 +376,139 @@ mlx5_wqe_write_vlan(struct txq *txq, volatile union mlx5_wqe *wqe,\n }\n \n /**\n+ * Write a inline WQE.\n+ *\n+ * @param txq\n+ *   Pointer to TX queue structure.\n+ * @param wqe\n+ *   Pointer to the WQE to fill.\n+ * @param addr\n+ *   Buffer data address.\n+ * @param length\n+ *   Packet length.\n+ * @param lkey\n+ *   Memory region lkey.\n+ */\n+static inline void\n+mlx5_wqe_write_inline(struct txq *txq, volatile union mlx5_wqe *wqe,\n+\t\t      uintptr_t addr, uint32_t length)\n+{\n+\tuint32_t size;\n+\tuint16_t wqe_cnt = txq->wqe_n - 1;\n+\tuint16_t wqe_ci = txq->wqe_ci + 1;\n+\n+\t/* Copy the first 16 bytes into inline header. */\n+\trte_memcpy((void *)(uintptr_t)wqe->inl.eseg.inline_hdr_start,\n+\t\t   (void *)(uintptr_t)addr,\n+\t\t   MLX5_ETH_INLINE_HEADER_SIZE);\n+\taddr += MLX5_ETH_INLINE_HEADER_SIZE;\n+\tlength -= MLX5_ETH_INLINE_HEADER_SIZE;\n+\tsize = 3 + ((4 + length + 15) / 16);\n+\twqe->inl.byte_cnt = htonl(length | MLX5_INLINE_SEG);\n+\trte_memcpy((void *)(uintptr_t)&wqe->inl.data[0],\n+\t\t   (void *)addr, MLX5_WQE64_INL_DATA);\n+\taddr += MLX5_WQE64_INL_DATA;\n+\tlength -= MLX5_WQE64_INL_DATA;\n+\twhile (length) {\n+\t\tvolatile union mlx5_wqe *wqe_next =\n+\t\t\t&(*txq->wqes)[wqe_ci & wqe_cnt];\n+\t\tuint32_t copy_bytes = (length > sizeof(*wqe)) ?\n+\t\t\t\t      sizeof(*wqe) :\n+\t\t\t\t      length;\n+\n+\t\trte_mov64((uint8_t *)(uintptr_t)&wqe_next->data[0],\n+\t\t\t  (uint8_t *)addr);\n+\t\taddr += copy_bytes;\n+\t\tlength -= copy_bytes;\n+\t\t++wqe_ci;\n+\t}\n+\tassert(size < 64);\n+\twqe->inl.ctrl.data[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);\n+\twqe->inl.ctrl.data[1] = htonl(txq->qp_num_8s | size);\n+\twqe->inl.ctrl.data[3] = 0;\n+\twqe->inl.eseg.rsvd0 = 0;\n+\twqe->inl.eseg.rsvd1 = 0;\n+\twqe->inl.eseg.mss = 0;\n+\twqe->inl.eseg.rsvd2 = 0;\n+\twqe->inl.eseg.inline_hdr_sz = htons(MLX5_ETH_INLINE_HEADER_SIZE);\n+\t/* Increment consumer index. */\n+\ttxq->wqe_ci = wqe_ci;\n+}\n+\n+/**\n+ * Write a inline WQE with VLAN.\n+ *\n+ * @param txq\n+ *   Pointer to TX queue structure.\n+ * @param wqe\n+ *   Pointer to the WQE to fill.\n+ * @param addr\n+ *   Buffer data address.\n+ * @param length\n+ *   Packet length.\n+ * @param lkey\n+ *   Memory region lkey.\n+ * @param vlan_tci\n+ *   VLAN field to insert in packet.\n+ */\n+static inline void\n+mlx5_wqe_write_inline_vlan(struct txq *txq, volatile union mlx5_wqe *wqe,\n+\t\t\t   uintptr_t addr, uint32_t length, uint16_t vlan_tci)\n+{\n+\tuint32_t size;\n+\tuint32_t wqe_cnt = txq->wqe_n - 1;\n+\tuint16_t wqe_ci = txq->wqe_ci + 1;\n+\tuint32_t vlan = htonl(0x81000000 | vlan_tci);\n+\n+\t/*\n+\t * Copy 12 bytes of source & destination MAC address.\n+\t * Copy 4 bytes of VLAN.\n+\t * Copy 2 bytes of Ether type.\n+\t */\n+\trte_memcpy((uint8_t *)(uintptr_t)wqe->inl.eseg.inline_hdr_start,\n+\t\t   (uint8_t *)addr, 12);\n+\trte_memcpy((uint8_t *)(uintptr_t)wqe->inl.eseg.inline_hdr_start + 12,\n+\t\t   &vlan, sizeof(vlan));\n+\trte_memcpy((uint8_t *)(uintptr_t)wqe->inl.eseg.inline_hdr_start + 16,\n+\t\t   ((uint8_t *)addr + 12), 2);\n+\taddr += MLX5_ETH_VLAN_INLINE_HEADER_SIZE - sizeof(vlan);\n+\tlength -= MLX5_ETH_VLAN_INLINE_HEADER_SIZE - sizeof(vlan);\n+\tsize = (sizeof(wqe->inl.ctrl.ctrl) +\n+\t\tsizeof(wqe->inl.eseg) +\n+\t\tsizeof(wqe->inl.byte_cnt) +\n+\t\tlength + 15) / 16;\n+\twqe->inl.byte_cnt = htonl(length | MLX5_INLINE_SEG);\n+\trte_memcpy((void *)(uintptr_t)&wqe->inl.data[0],\n+\t\t   (void *)addr, MLX5_WQE64_INL_DATA);\n+\taddr += MLX5_WQE64_INL_DATA;\n+\tlength -= MLX5_WQE64_INL_DATA;\n+\twhile (length) {\n+\t\tvolatile union mlx5_wqe *wqe_next =\n+\t\t\t&(*txq->wqes)[wqe_ci & wqe_cnt];\n+\t\tuint32_t copy_bytes = (length > sizeof(*wqe)) ?\n+\t\t\t\t      sizeof(*wqe) :\n+\t\t\t\t      length;\n+\n+\t\trte_mov64((uint8_t *)(uintptr_t)&wqe_next->data[0],\n+\t\t\t  (uint8_t *)addr);\n+\t\taddr += copy_bytes;\n+\t\tlength -= copy_bytes;\n+\t\t++wqe_ci;\n+\t}\n+\tassert(size < 64);\n+\twqe->inl.ctrl.data[0] = htonl((txq->wqe_ci << 8) | MLX5_OPCODE_SEND);\n+\twqe->inl.ctrl.data[1] = htonl(txq->qp_num_8s | size);\n+\twqe->inl.ctrl.data[3] = 0;\n+\twqe->inl.eseg.rsvd0 = 0;\n+\twqe->inl.eseg.rsvd1 = 0;\n+\twqe->inl.eseg.mss = 0;\n+\twqe->inl.eseg.rsvd2 = 0;\n+\twqe->inl.eseg.inline_hdr_sz = htons(MLX5_ETH_VLAN_INLINE_HEADER_SIZE);\n+\t/* Increment consumer index. */\n+\ttxq->wqe_ci = wqe_ci;\n+}\n+\n+/**\n  * Ring TX queue doorbell.\n  *\n  * @param txq\n@@ -417,6 +550,23 @@ tx_prefetch_cqe(struct txq *txq, uint16_t ci)\n }\n \n /**\n+ * Prefetch a WQE.\n+ *\n+ * @param txq\n+ *   Pointer to TX queue structure.\n+ * @param  wqe_ci\n+ *   WQE consumer index.\n+ */\n+static inline void\n+tx_prefetch_wqe(struct txq *txq, uint16_t ci)\n+{\n+\tvolatile union mlx5_wqe *wqe;\n+\n+\twqe = &(*txq->wqes)[ci & (txq->wqe_n - 1)];\n+\trte_prefetch0(wqe);\n+}\n+\n+/**\n  * DPDK callback for TX.\n  *\n  * @param dpdk_txq\n@@ -529,6 +679,129 @@ mlx5_tx_burst(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)\n }\n \n /**\n+ * DPDK callback for TX with inline support.\n+ *\n+ * @param dpdk_txq\n+ *   Generic pointer to TX queue structure.\n+ * @param[in] pkts\n+ *   Packets to transmit.\n+ * @param pkts_n\n+ *   Number of packets in array.\n+ *\n+ * @return\n+ *   Number of packets successfully transmitted (<= pkts_n).\n+ */\n+uint16_t\n+mlx5_tx_burst_inline(void *dpdk_txq, struct rte_mbuf **pkts, uint16_t pkts_n)\n+{\n+\tstruct txq *txq = (struct txq *)dpdk_txq;\n+\tuint16_t elts_head = txq->elts_head;\n+\tconst unsigned int elts_n = txq->elts_n;\n+\tunsigned int i;\n+\tunsigned int max;\n+\tunsigned int comp;\n+\tvolatile union mlx5_wqe *wqe;\n+\tstruct rte_mbuf *buf;\n+\tunsigned int max_inline = txq->max_inline;\n+\n+\tif (unlikely(!pkts_n))\n+\t\treturn 0;\n+\tbuf = pkts[0];\n+\t/* Prefetch first packet cacheline. */\n+\ttx_prefetch_cqe(txq, txq->cq_ci);\n+\ttx_prefetch_cqe(txq, txq->cq_ci + 1);\n+\trte_prefetch0(buf);\n+\t/* Start processing. */\n+\ttxq_complete(txq);\n+\tmax = (elts_n - (elts_head - txq->elts_tail));\n+\tif (max > elts_n)\n+\t\tmax -= elts_n;\n+\tassert(max >= 1);\n+\tassert(max <= elts_n);\n+\t/* Always leave one free entry in the ring. */\n+\t--max;\n+\tif (max == 0)\n+\t\treturn 0;\n+\tif (max > pkts_n)\n+\t\tmax = pkts_n;\n+\tfor (i = 0; (i != max); ++i) {\n+\t\tunsigned int elts_head_next = (elts_head + 1) & (elts_n - 1);\n+\t\tuintptr_t addr;\n+\t\tuint32_t length;\n+\t\tuint32_t lkey;\n+\n+\t\twqe = &(*txq->wqes)[txq->wqe_ci & (txq->wqe_n - 1)];\n+\t\ttx_prefetch_wqe(txq, txq->wqe_ci);\n+\t\ttx_prefetch_wqe(txq, txq->wqe_ci + 1);\n+\t\tif (i + 1 < max)\n+\t\t\trte_prefetch0(pkts[i + 1]);\n+\t\t/* Should we enable HW CKSUM offload */\n+\t\tif (buf->ol_flags &\n+\t\t    (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM)) {\n+\t\t\twqe->inl.eseg.cs_flags =\n+\t\t\t\tMLX5_ETH_WQE_L3_CSUM |\n+\t\t\t\tMLX5_ETH_WQE_L4_CSUM;\n+\t\t} else {\n+\t\t\twqe->inl.eseg.cs_flags = 0;\n+\t\t}\n+\t\t/* Retrieve buffer information. */\n+\t\taddr = rte_pktmbuf_mtod(buf, uintptr_t);\n+\t\tlength = DATA_LEN(buf);\n+\t\t/* Update element. */\n+\t\t(*txq->elts)[elts_head] = buf;\n+\t\t/* Prefetch next buffer data. */\n+\t\tif (i + 1 < max)\n+\t\t\trte_prefetch0(rte_pktmbuf_mtod(pkts[i + 1],\n+\t\t\t\t\t\t       volatile void *));\n+\t\tif (length <= max_inline) {\n+\t\t\tif (buf->ol_flags & PKT_TX_VLAN_PKT)\n+\t\t\t\tmlx5_wqe_write_inline_vlan(txq, wqe,\n+\t\t\t\t\t\t\t   addr, length,\n+\t\t\t\t\t\t\t   buf->vlan_tci);\n+\t\t\telse\n+\t\t\t\tmlx5_wqe_write_inline(txq, wqe, addr, length);\n+\t\t} else {\n+\t\t\t/* Retrieve Memory Region key for this memory pool. */\n+\t\t\tlkey = txq_mp2mr(txq, txq_mb2mp(buf));\n+\t\t\tif (buf->ol_flags & PKT_TX_VLAN_PKT)\n+\t\t\t\tmlx5_wqe_write_vlan(txq, wqe, addr, length,\n+\t\t\t\t\t\t    lkey, buf->vlan_tci);\n+\t\t\telse\n+\t\t\t\tmlx5_wqe_write(txq, wqe, addr, length, lkey);\n+\t\t}\n+\t\twqe->inl.ctrl.data[2] = 0;\n+\t\telts_head = elts_head_next;\n+\t\tbuf = pkts[i + 1];\n+#ifdef MLX5_PMD_SOFT_COUNTERS\n+\t\t/* Increment sent bytes counter. */\n+\t\ttxq->stats.obytes += length;\n+#endif\n+\t}\n+\t/* Take a shortcut if nothing must be sent. */\n+\tif (unlikely(i == 0))\n+\t\treturn 0;\n+\t/* Check whether completion threshold has been reached. */\n+\tcomp = txq->elts_comp + i;\n+\tif (comp >= MLX5_TX_COMP_THRESH) {\n+\t\t/* Request completion on last WQE. */\n+\t\twqe->inl.ctrl.data[2] = htonl(8);\n+\t\t/* Save elts_head in unused \"immediate\" field of WQE. */\n+\t\twqe->inl.ctrl.data[3] = elts_head;\n+\t\ttxq->elts_comp = 0;\n+\t} else {\n+\t\ttxq->elts_comp = comp;\n+\t}\n+#ifdef MLX5_PMD_SOFT_COUNTERS\n+\t/* Increment sent packets counter. */\n+\ttxq->stats.opackets += i;\n+#endif\n+\t/* Ring QP doorbell. */\n+\tmlx5_tx_dbrec(txq);\n+\ttxq->elts_head = elts_head;\n+\treturn i;\n+}\n+\n+/**\n  * Translate RX completion flags to packet type.\n  *\n  * @param[in] cqe\ndiff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h\nindex f900e65..3c83148 100644\n--- a/drivers/net/mlx5/mlx5_rxtx.h\n+++ b/drivers/net/mlx5/mlx5_rxtx.h\n@@ -246,6 +246,7 @@ struct txq {\n \tuint16_t wqe_n; /* Number of WQ elements. */\n \tuint16_t bf_offset; /* Blueflame offset. */\n \tuint16_t bf_buf_size; /* Blueflame size. */\n+\tuint16_t max_inline; /* Maximum size to inline in a WQE. */\n \tuint32_t qp_num_8s; /* QP number shifted by 8. */\n \tvolatile struct mlx5_cqe (*cqes)[]; /* Completion queue. */\n \tvolatile union mlx5_wqe (*wqes)[]; /* Work queue. */\n@@ -310,6 +311,7 @@ uint16_t mlx5_tx_burst_secondary_setup(void *, struct rte_mbuf **, uint16_t);\n /* mlx5_rxtx.c */\n \n uint16_t mlx5_tx_burst(void *, struct rte_mbuf **, uint16_t);\n+uint16_t mlx5_tx_burst_inline(void *, struct rte_mbuf **, uint16_t);\n uint16_t mlx5_rx_burst(void *, struct rte_mbuf **, uint16_t);\n uint16_t removed_tx_burst(void *, struct rte_mbuf **, uint16_t);\n uint16_t removed_rx_burst(void *, struct rte_mbuf **, uint16_t);\ndiff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c\nindex 7b2dc7c..6a4a96e 100644\n--- a/drivers/net/mlx5/mlx5_txq.c\n+++ b/drivers/net/mlx5/mlx5_txq.c\n@@ -332,6 +332,10 @@ txq_ctrl_setup(struct rte_eth_dev *dev, struct txq_ctrl *txq_ctrl,\n \t\t.comp_mask = (IBV_EXP_QP_INIT_ATTR_PD |\n \t\t\t      IBV_EXP_QP_INIT_ATTR_RES_DOMAIN),\n \t};\n+\tif (priv->txq_inline && priv->txqs_n >= priv->txqs_inline) {\n+\t\ttmpl.txq.max_inline = priv->txq_inline;\n+\t\tattr.init.cap.max_inline_data = tmpl.txq.max_inline;\n+\t}\n \ttmpl.qp = ibv_exp_create_qp(priv->ctx, &attr.init);\n \tif (tmpl.qp == NULL) {\n \t\tret = (errno ? errno : EINVAL);\n",
    "prefixes": [
        "dpdk-dev",
        "v6",
        "17/25"
    ]
}