get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 112830,
    "url": "http://patches.dpdk.org/api/patches/112830/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1655348434-7096-4-git-send-email-wei.huang@intel.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": "<1655348434-7096-4-git-send-email-wei.huang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1655348434-7096-4-git-send-email-wei.huang@intel.com",
    "date": "2022-06-16T03:00:32",
    "name": "[v8,3/5] raw/ifpga: add HE-LPBK AFU driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "995061d9be8b33aace4bf42282e8e437dc8315b2",
    "submitter": {
        "id": 2033,
        "url": "http://patches.dpdk.org/api/people/2033/?format=api",
        "name": "Wei Huang",
        "email": "wei.huang@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1655348434-7096-4-git-send-email-wei.huang@intel.com/mbox/",
    "series": [
        {
            "id": 23549,
            "url": "http://patches.dpdk.org/api/series/23549/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=23549",
            "date": "2022-06-16T03:00:29",
            "name": "introduce AFU PMD driver of FPGA",
            "version": 8,
            "mbox": "http://patches.dpdk.org/series/23549/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/112830/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/112830/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 26A82A0547;\n\tThu, 16 Jun 2022 04:53:11 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 81DC842BE8;\n\tThu, 16 Jun 2022 04:52:56 +0200 (CEST)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n by mails.dpdk.org (Postfix) with ESMTP id 1EBDB40141;\n Thu, 16 Jun 2022 04:52:53 +0200 (CEST)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 15 Jun 2022 19:52:53 -0700",
            "from unknown (HELO zj-fpga-amt.sh.intel.com) ([10.238.175.102])\n by FMSMGA003.fm.intel.com with ESMTP; 15 Jun 2022 19:52:51 -0700"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1655347975; x=1686883975;\n h=from:to:cc:subject:date:message-id:in-reply-to: references;\n bh=iXcSODCI/G4vTS5RraJmlWCW39BwE7m3AjHJonT/wYw=;\n b=dXIbAY8Zvh/6NzRdxkIs+ikoYPk9HdbnzRjp5enZW4ZcfyyyQLLg8rmi\n 6N5RCa2hyp3WjAngUHVjgdZLJuozXTQlXdk+oYcB7JThFYSP4o/jbCyX7\n XlTaj/YpLwbU4EkcoWzy46SsCMSiafvCwlZRUpnJ4qbVKrM3ypjJNENeU\n c27wVZ98sQUo9dqPvo3Q4ITFdFbxN3HN8d7DNBCbrqCGDHhrfqD4dCAoa\n 2nEI87aC4qG15khpi3E3zEbAfoY6idq+ynW0PsqKBeMxxfEDF5CCRSten\n cB/g6M34rkdDr441PY+XuAPfQhWLDSeoMu64eDX15GgdtetIxwkD0XmSL w==;",
        "X-IronPort-AV": [
            "E=McAfee;i=\"6400,9594,10379\"; a=\"276725742\"",
            "E=Sophos;i=\"5.91,302,1647327600\"; d=\"scan'208\";a=\"276725742\"",
            "E=Sophos;i=\"5.91,302,1647327600\"; d=\"scan'208\";a=\"674824698\""
        ],
        "X-ExtLoop1": "1",
        "From": "Wei Huang <wei.huang@intel.com>",
        "To": "dev@dpdk.org, thomas@monjalon.net, nipun.gupta@nxp.com,\n hemant.agrawal@nxp.com",
        "Cc": "stable@dpdk.org, rosen.xu@intel.com, tianfei.zhang@intel.com,\n qi.z.zhang@intel.com, Wei Huang <wei.huang@intel.com>",
        "Subject": "[PATCH v8 3/5] raw/ifpga: add HE-LPBK AFU driver",
        "Date": "Wed, 15 Jun 2022 23:00:32 -0400",
        "Message-Id": "<1655348434-7096-4-git-send-email-wei.huang@intel.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1655348434-7096-1-git-send-email-wei.huang@intel.com>",
        "References": "<1654760242-7832-1-git-send-email-wei.huang@intel.com>\n <1655348434-7096-1-git-send-email-wei.huang@intel.com>",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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"
    },
    "content": "HE-LPBK and HE-MEM-LPBK are host exerciser modules in OFS FPGA,\nHE-LPBK is used to test PCI bus and HE-MEM-LPBK is used to test\nlocal memory.\nThis driver initialize the modules and report test result.\n\nSigned-off-by: Wei Huang <wei.huang@intel.com>\nAcked-by: Tianfei Zhang <tianfei.zhang@intel.com>\nReviewed-by: Rosen Xu <rosen.xu@intel.com>\n---\nv2: move source files to ifpga and rename, refine code\n---\n drivers/raw/ifpga/afu_pmd_he_lpbk.c | 436 ++++++++++++++++++++++++++++++++++++\n drivers/raw/ifpga/afu_pmd_he_lpbk.h | 126 +++++++++++\n drivers/raw/ifpga/meson.build       |   2 +-\n drivers/raw/ifpga/rte_pmd_afu.h     |  14 ++\n 4 files changed, 577 insertions(+), 1 deletion(-)\n create mode 100644 drivers/raw/ifpga/afu_pmd_he_lpbk.c\n create mode 100644 drivers/raw/ifpga/afu_pmd_he_lpbk.h",
    "diff": "diff --git a/drivers/raw/ifpga/afu_pmd_he_lpbk.c b/drivers/raw/ifpga/afu_pmd_he_lpbk.c\nnew file mode 100644\nindex 0000000..8b2c85b\n--- /dev/null\n+++ b/drivers/raw/ifpga/afu_pmd_he_lpbk.c\n@@ -0,0 +1,436 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2022 Intel Corporation\n+ */\n+\n+#include <errno.h>\n+#include <stdio.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <inttypes.h>\n+#include <unistd.h>\n+#include <fcntl.h>\n+#include <poll.h>\n+#include <sys/eventfd.h>\n+#include <sys/ioctl.h>\n+\n+#include <rte_eal.h>\n+#include <rte_malloc.h>\n+#include <rte_memcpy.h>\n+#include <rte_io.h>\n+#include <rte_vfio.h>\n+#include <rte_bus_pci.h>\n+#include <rte_bus_ifpga.h>\n+#include <rte_rawdev.h>\n+\n+#include \"afu_pmd_core.h\"\n+#include \"afu_pmd_he_lpbk.h\"\n+\n+static int he_lpbk_afu_config(struct afu_rawdev *dev)\n+{\n+\tstruct he_lpbk_priv *priv = NULL;\n+\tstruct rte_pmd_afu_he_lpbk_cfg *cfg = NULL;\n+\tstruct he_lpbk_csr_cfg v;\n+\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tpriv = (struct he_lpbk_priv *)dev->priv;\n+\tif (!priv)\n+\t\treturn -ENOENT;\n+\n+\tcfg = &priv->he_lpbk_cfg;\n+\n+\tv.csr = 0;\n+\n+\tif (cfg->cont)\n+\t\tv.cont = 1;\n+\n+\tv.mode = cfg->mode;\n+\tv.trput_interleave = cfg->trput_interleave;\n+\tif (cfg->multi_cl == 4)\n+\t\tv.multicl_len = 2;\n+\telse\n+\t\tv.multicl_len = cfg->multi_cl - 1;\n+\n+\tIFPGA_RAWDEV_PMD_DEBUG(\"cfg: 0x%08x\", v.csr);\n+\trte_write32(v.csr, priv->he_lpbk_ctx.addr + CSR_CFG);\n+\n+\treturn 0;\n+}\n+\n+static void he_lpbk_report(struct afu_rawdev *dev, uint32_t cl)\n+{\n+\tstruct he_lpbk_priv *priv = NULL;\n+\tstruct rte_pmd_afu_he_lpbk_cfg *cfg = NULL;\n+\tstruct he_lpbk_ctx *ctx = NULL;\n+\tstruct he_lpbk_dsm_status *stat = NULL;\n+\tstruct he_lpbk_status0 stat0;\n+\tstruct he_lpbk_status1 stat1;\n+\tuint64_t swtest_msg = 0;\n+\tuint64_t ticks = 0;\n+\tuint64_t info = 0;\n+\tdouble num, rd_bw, wr_bw;\n+\n+\tif (!dev || !dev->priv)\n+\t\treturn;\n+\n+\tpriv = (struct he_lpbk_priv *)dev->priv;\n+\tcfg = &priv->he_lpbk_cfg;\n+\tctx = &priv->he_lpbk_ctx;\n+\n+\tstat = ctx->status_ptr;\n+\n+\tswtest_msg = rte_read64(ctx->addr + CSR_SWTEST_MSG);\n+\tstat0.csr = rte_read64(ctx->addr + CSR_STATUS0);\n+\tstat1.csr = rte_read64(ctx->addr + CSR_STATUS1);\n+\n+\tif (cfg->cont)\n+\t\tticks = stat->num_clocks - stat->start_overhead;\n+\telse\n+\t\tticks = stat->num_clocks -\n+\t\t\t(stat->start_overhead + stat->end_overhead);\n+\n+\tif (cfg->freq_mhz == 0) {\n+\t\tinfo = rte_read64(ctx->addr + CSR_HE_INFO0);\n+\t\tIFPGA_RAWDEV_PMD_INFO(\"API version: %\"PRIx64, info >> 16);\n+\t\tcfg->freq_mhz = info & 0xffff;\n+\t\tif (cfg->freq_mhz == 0) {\n+\t\t\tIFPGA_RAWDEV_PMD_INFO(\"Frequency of AFU clock is unknown.\"\n+\t\t\t\t\" Assuming 350 MHz.\");\n+\t\t\tcfg->freq_mhz = 350;\n+\t\t}\n+\t}\n+\n+\tnum = (double)stat0.num_reads;\n+\trd_bw = (num * CLS_TO_SIZE(1) * MHZ(cfg->freq_mhz)) / ticks;\n+\tnum = (double)stat0.num_writes;\n+\twr_bw = (num * CLS_TO_SIZE(1) * MHZ(cfg->freq_mhz)) / ticks;\n+\n+\tprintf(\"Cachelines  Read_Count Write_Count Pend_Read Pend_Write \"\n+\t\t\"Clocks@%uMHz   Rd_Bandwidth   Wr_Bandwidth\\n\",\n+\t\tcfg->freq_mhz);\n+\tprintf(\"%10u  %10u %10u %10u %10u  %12\"PRIu64\n+\t\t\"   %7.3f GB/s   %7.3f GB/s\\n\",\n+\t\tcl, stat0.num_reads, stat0.num_writes,\n+\t\tstat1.num_pend_reads, stat1.num_pend_writes,\n+\t\tticks, rd_bw / 1e9, wr_bw / 1e9);\n+\tprintf(\"Test Message: 0x%\"PRIx64\"\\n\", swtest_msg);\n+}\n+\n+static int he_lpbk_test(struct afu_rawdev *dev)\n+{\n+\tstruct he_lpbk_priv *priv = NULL;\n+\tstruct rte_pmd_afu_he_lpbk_cfg *cfg = NULL;\n+\tstruct he_lpbk_ctx *ctx = NULL;\n+\tstruct he_lpbk_csr_ctl ctl;\n+\tuint32_t *ptr = NULL;\n+\tuint32_t i, j, cl, val = 0;\n+\tuint64_t sval = 0;\n+\tint ret = 0;\n+\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tpriv = (struct he_lpbk_priv *)dev->priv;\n+\tif (!priv)\n+\t\treturn -ENOENT;\n+\n+\tcfg = &priv->he_lpbk_cfg;\n+\tctx = &priv->he_lpbk_ctx;\n+\n+\tctl.csr = 0;\n+\trte_write32(ctl.csr, ctx->addr + CSR_CTL);\n+\trte_delay_us(1000);\n+\tctl.reset = 1;\n+\trte_write32(ctl.csr, ctx->addr + CSR_CTL);\n+\n+\t/* initialize DMA addresses */\n+\tIFPGA_RAWDEV_PMD_DEBUG(\"src_addr: 0x%\"PRIx64, ctx->src_iova);\n+\trte_write64(SIZE_TO_CLS(ctx->src_iova), ctx->addr + CSR_SRC_ADDR);\n+\n+\tIFPGA_RAWDEV_PMD_DEBUG(\"dst_addr: 0x%\"PRIx64, ctx->dest_iova);\n+\trte_write64(SIZE_TO_CLS(ctx->dest_iova), ctx->addr + CSR_DST_ADDR);\n+\n+\tIFPGA_RAWDEV_PMD_DEBUG(\"dsm_addr: 0x%\"PRIx64, ctx->dsm_iova);\n+\trte_write32(SIZE_TO_CLS(ctx->dsm_iova), ctx->addr + CSR_AFU_DSM_BASEL);\n+\trte_write32(SIZE_TO_CLS(ctx->dsm_iova) >> 32,\n+\t\tctx->addr + CSR_AFU_DSM_BASEH);\n+\n+\tret = he_lpbk_afu_config(dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* initialize src data */\n+\tptr = (uint32_t *)ctx->src_ptr;\n+\tj = CLS_TO_SIZE(cfg->end) >> 2;\n+\tfor (i = 0; i < j; i++)\n+\t\t*ptr++ = i;\n+\n+\t/* start test */\n+\tfor (cl = cfg->begin; cl <= cfg->end; cl += cfg->multi_cl) {\n+\t\tmemset(ctx->dest_ptr, 0, CLS_TO_SIZE(cl));\n+\t\tmemset(ctx->dsm_ptr, 0, DSM_SIZE);\n+\n+\t\tctl.csr = 0;\n+\t\trte_write32(ctl.csr, ctx->addr + CSR_CTL);\n+\t\trte_delay_us(1000);\n+\t\tctl.reset = 1;\n+\t\trte_write32(ctl.csr, ctx->addr + CSR_CTL);\n+\n+\t\trte_write32(cl - 1, ctx->addr + CSR_NUM_LINES);\n+\n+\t\tctl.start = 1;\n+\t\trte_write32(ctl.csr, ctx->addr + CSR_CTL);\n+\n+\t\tif (cfg->cont) {\n+\t\t\trte_delay_ms(cfg->timeout * 1000);\n+\t\t\tctl.force_completion = 1;\n+\t\t\trte_write32(ctl.csr, ctx->addr + CSR_CTL);\n+\t\t\tret = dsm_poll_timeout(&ctx->status_ptr->test_complete,\n+\t\t\t\tval, (val & 0x1) == 1, DSM_POLL_INTERVAL,\n+\t\t\t\tDSM_TIMEOUT);\n+\t\t\tif (ret) {\n+\t\t\t\tprintf(\"DSM poll timeout\\n\");\n+\t\t\t\tgoto end;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tret = dsm_poll_timeout(&ctx->status_ptr->test_complete,\n+\t\t\t\tval, (val & 0x1) == 1, DSM_POLL_INTERVAL,\n+\t\t\t\tDSM_TIMEOUT);\n+\t\t\tif (ret) {\n+\t\t\t\tprintf(\"DSM poll timeout\\n\");\n+\t\t\t\tgoto end;\n+\t\t\t}\n+\t\t\tctl.force_completion = 1;\n+\t\t\trte_write32(ctl.csr, ctx->addr + CSR_CTL);\n+\t\t}\n+\n+\t\the_lpbk_report(dev, cl);\n+\n+\t\ti = 0;\n+\t\twhile (i++ < 100) {\n+\t\t\tsval = rte_read64(ctx->addr + CSR_STATUS1);\n+\t\t\tif (sval == 0)\n+\t\t\t\tbreak;\n+\t\t\trte_delay_us(1000);\n+\t\t}\n+\n+\t\tif (cfg->mode == NLB_MODE_LPBK) {\n+\t\t\tptr = (uint32_t *)ctx->dest_ptr;\n+\t\t\tj = CLS_TO_SIZE(cl) >> 2;\n+\t\t\tfor (i = 0; i < j; i++) {\n+\t\t\t\tif (*ptr++ != i) {\n+\t\t\t\t\tIFPGA_RAWDEV_PMD_ERR(\"Data mismatch @ %u\", i);\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+end:\n+\treturn 0;\n+}\n+\n+static int he_lpbk_ctx_release(struct afu_rawdev *dev)\n+{\n+\tstruct he_lpbk_priv *priv = NULL;\n+\tstruct he_lpbk_ctx *ctx = NULL;\n+\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tpriv = (struct he_lpbk_priv *)dev->priv;\n+\tif (!priv)\n+\t\treturn -ENOENT;\n+\n+\tctx = &priv->he_lpbk_ctx;\n+\n+\trte_free(ctx->dsm_ptr);\n+\tctx->dsm_ptr = NULL;\n+\tctx->status_ptr = NULL;\n+\n+\trte_free(ctx->src_ptr);\n+\tctx->src_ptr = NULL;\n+\n+\trte_free(ctx->dest_ptr);\n+\tctx->dest_ptr = NULL;\n+\n+\treturn 0;\n+}\n+\n+static int he_lpbk_ctx_init(struct afu_rawdev *dev)\n+{\n+\tstruct he_lpbk_priv *priv = NULL;\n+\tstruct he_lpbk_ctx *ctx = NULL;\n+\tint ret = 0;\n+\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tpriv = (struct he_lpbk_priv *)dev->priv;\n+\tif (!priv)\n+\t\treturn -ENOENT;\n+\n+\tctx = &priv->he_lpbk_ctx;\n+\tctx->addr = (uint8_t *)dev->addr;\n+\n+\tctx->dsm_ptr = (uint8_t *)rte_zmalloc(NULL, DSM_SIZE, TEST_MEM_ALIGN);\n+\tif (!ctx->dsm_ptr)\n+\t\treturn -ENOMEM;\n+\tctx->dsm_iova = rte_malloc_virt2iova(ctx->dsm_ptr);\n+\tif (ctx->dsm_iova == RTE_BAD_IOVA) {\n+\t\tret = -ENOMEM;\n+\t\tgoto release_dsm;\n+\t}\n+\n+\tctx->src_ptr = (uint8_t *)rte_zmalloc(NULL, NLB_BUF_SIZE,\n+\t\tTEST_MEM_ALIGN);\n+\tif (!ctx->src_ptr) {\n+\t\tret = -ENOMEM;\n+\t\tgoto release_dsm;\n+\t}\n+\tctx->src_iova = rte_malloc_virt2iova(ctx->src_ptr);\n+\tif (ctx->src_iova == RTE_BAD_IOVA) {\n+\t\tret = -ENOMEM;\n+\t\tgoto release_src;\n+\t}\n+\n+\tctx->dest_ptr = (uint8_t *)rte_zmalloc(NULL, NLB_BUF_SIZE,\n+\t\tTEST_MEM_ALIGN);\n+\tif (!ctx->dest_ptr) {\n+\t\tret = -ENOMEM;\n+\t\tgoto release_src;\n+\t}\n+\tctx->dest_iova = rte_malloc_virt2iova(ctx->dest_ptr);\n+\tif (ctx->dest_iova == RTE_BAD_IOVA) {\n+\t\tret = -ENOMEM;\n+\t\tgoto release_dest;\n+\t}\n+\n+\tctx->status_ptr = (struct he_lpbk_dsm_status *)ctx->dsm_ptr;\n+\treturn 0;\n+\n+release_dest:\n+\trte_free(ctx->dest_ptr);\n+\tctx->dest_ptr = NULL;\n+release_src:\n+\trte_free(ctx->src_ptr);\n+\tctx->src_ptr = NULL;\n+release_dsm:\n+\trte_free(ctx->dsm_ptr);\n+\tctx->dsm_ptr = NULL;\n+\treturn ret;\n+}\n+\n+static int he_lpbk_init(struct afu_rawdev *dev)\n+{\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tif (!dev->priv) {\n+\t\tdev->priv = rte_zmalloc(NULL, sizeof(struct he_lpbk_priv), 0);\n+\t\tif (!dev->priv)\n+\t\t\treturn -ENOMEM;\n+\t}\n+\n+\treturn he_lpbk_ctx_init(dev);\n+}\n+\n+static int he_lpbk_config(struct afu_rawdev *dev, void *config,\n+\tsize_t config_size)\n+{\n+\tstruct he_lpbk_priv *priv = NULL;\n+\tstruct rte_pmd_afu_he_lpbk_cfg *cfg = NULL;\n+\n+\tif (!dev || !config || !config_size)\n+\t\treturn -EINVAL;\n+\n+\tpriv = (struct he_lpbk_priv *)dev->priv;\n+\tif (!priv)\n+\t\treturn -ENOENT;\n+\n+\tif (config_size != sizeof(struct rte_pmd_afu_he_lpbk_cfg))\n+\t\treturn -EINVAL;\n+\n+\tcfg = (struct rte_pmd_afu_he_lpbk_cfg *)config;\n+\tif (cfg->mode > NLB_MODE_TRPUT)\n+\t\treturn -EINVAL;\n+\tif ((cfg->multi_cl != 1) && (cfg->multi_cl != 2) &&\n+\t\t(cfg->multi_cl != 4))\n+\t\treturn -EINVAL;\n+\tif ((cfg->begin < MIN_CACHE_LINES) || (cfg->begin > MAX_CACHE_LINES))\n+\t\treturn -EINVAL;\n+\tif ((cfg->end < cfg->begin) || (cfg->end > MAX_CACHE_LINES))\n+\t\treturn -EINVAL;\n+\n+\trte_memcpy(&priv->he_lpbk_cfg, cfg, sizeof(priv->he_lpbk_cfg));\n+\n+\treturn 0;\n+}\n+\n+static int he_lpbk_close(struct afu_rawdev *dev)\n+{\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\the_lpbk_ctx_release(dev);\n+\n+\trte_free(dev->priv);\n+\tdev->priv = NULL;\n+\n+\treturn 0;\n+}\n+\n+static int he_lpbk_dump(struct afu_rawdev *dev, FILE *f)\n+{\n+\tstruct he_lpbk_priv *priv = NULL;\n+\tstruct he_lpbk_ctx *ctx = NULL;\n+\n+\tif (!dev)\n+\t\treturn -EINVAL;\n+\n+\tpriv = (struct he_lpbk_priv *)dev->priv;\n+\tif (!priv)\n+\t\treturn -ENOENT;\n+\n+\tif (!f)\n+\t\tf = stdout;\n+\n+\tctx = &priv->he_lpbk_ctx;\n+\n+\tfprintf(f, \"addr:\\t\\t%p\\n\", (void *)ctx->addr);\n+\tfprintf(f, \"dsm_ptr:\\t%p\\n\", (void *)ctx->dsm_ptr);\n+\tfprintf(f, \"dsm_iova:\\t0x%\"PRIx64\"\\n\", ctx->dsm_iova);\n+\tfprintf(f, \"src_ptr:\\t%p\\n\", (void *)ctx->src_ptr);\n+\tfprintf(f, \"src_iova:\\t0x%\"PRIx64\"\\n\", ctx->src_iova);\n+\tfprintf(f, \"dest_ptr:\\t%p\\n\", (void *)ctx->dest_ptr);\n+\tfprintf(f, \"dest_iova:\\t0x%\"PRIx64\"\\n\", ctx->dest_iova);\n+\tfprintf(f, \"status_ptr:\\t%p\\n\", (void *)ctx->status_ptr);\n+\n+\treturn 0;\n+}\n+\n+static struct afu_ops he_lpbk_ops = {\n+\t.init = he_lpbk_init,\n+\t.config = he_lpbk_config,\n+\t.start = NULL,\n+\t.stop = NULL,\n+\t.test = he_lpbk_test,\n+\t.close = he_lpbk_close,\n+\t.dump = he_lpbk_dump,\n+\t.reset = NULL\n+};\n+\n+struct afu_rawdev_drv he_lpbk_drv = {\n+\t.uuid = { HE_LPBK_UUID_L, HE_LPBK_UUID_H },\n+\t.ops = &he_lpbk_ops\n+};\n+\n+AFU_PMD_REGISTER(he_lpbk_drv);\n+\n+struct afu_rawdev_drv he_mem_lpbk_drv = {\n+\t.uuid = { HE_MEM_LPBK_UUID_L, HE_MEM_LPBK_UUID_H },\n+\t.ops = &he_lpbk_ops\n+};\n+\n+AFU_PMD_REGISTER(he_mem_lpbk_drv);\ndiff --git a/drivers/raw/ifpga/afu_pmd_he_lpbk.h b/drivers/raw/ifpga/afu_pmd_he_lpbk.h\nnew file mode 100644\nindex 0000000..5ad6aa8\n--- /dev/null\n+++ b/drivers/raw/ifpga/afu_pmd_he_lpbk.h\n@@ -0,0 +1,126 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2022 Intel Corporation\n+ */\n+\n+#ifndef _AFU_PMD_HE_LPBK_H_\n+#define _AFU_PMD_HE_LPBK_H_\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include \"afu_pmd_core.h\"\n+#include \"rte_pmd_afu.h\"\n+\n+#define HE_LPBK_UUID_L     0xb94b12284c31e02b\n+#define HE_LPBK_UUID_H     0x56e203e9864f49a7\n+#define HE_MEM_LPBK_UUID_L 0xbb652a578330a8eb\n+#define HE_MEM_LPBK_UUID_H 0x8568ab4e6ba54616\n+\n+/* HE-LBK & HE-MEM-LBK registers definition */\n+#define CSR_SCRATCHPAD0    0x100\n+#define CSR_SCRATCHPAD1    0x108\n+#define CSR_AFU_DSM_BASEL  0x110\n+#define CSR_AFU_DSM_BASEH  0x114\n+#define CSR_SRC_ADDR       0x120\n+#define CSR_DST_ADDR       0x128\n+#define CSR_NUM_LINES      0x130\n+#define CSR_CTL            0x138\n+#define CSR_CFG            0x140\n+#define CSR_INACT_THRESH   0x148\n+#define CSR_INTERRUPT0     0x150\n+#define CSR_SWTEST_MSG     0x158\n+#define CSR_STATUS0        0x160\n+#define CSR_STATUS1        0x168\n+#define CSR_ERROR          0x170\n+#define CSR_STRIDE         0x178\n+#define CSR_HE_INFO0       0x180\n+\n+#define DSM_SIZE           0x200000\n+#define DSM_POLL_INTERVAL  5  /* ms */\n+#define DSM_TIMEOUT        1000  /* ms */\n+\n+#define NLB_BUF_SIZE  0x400000\n+#define TEST_MEM_ALIGN  1024\n+\n+struct he_lpbk_csr_ctl {\n+\tunion {\n+\t\tuint32_t csr;\n+\t\tstruct {\n+\t\t\tuint32_t reset:1;\n+\t\t\tuint32_t start:1;\n+\t\t\tuint32_t force_completion:1;\n+\t\t\tuint32_t reserved:29;\n+\t\t};\n+\t};\n+};\n+\n+struct he_lpbk_csr_cfg {\n+\tunion {\n+\t\tuint32_t csr;\n+\t\tstruct {\n+\t\t\tuint32_t rsvd1:1;\n+\t\t\tuint32_t cont:1;\n+\t\t\tuint32_t mode:3;\n+\t\t\tuint32_t multicl_len:2;\n+\t\t\tuint32_t rsvd2:13;\n+\t\t\tuint32_t trput_interleave:3;\n+\t\t\tuint32_t test_cfg:5;\n+\t\t\tuint32_t interrupt_on_error:1;\n+\t\t\tuint32_t interrupt_testmode:1;\n+\t\t\tuint32_t rsvd3:2;\n+\t\t};\n+\t};\n+};\n+\n+struct he_lpbk_status0 {\n+\tunion {\n+\t\tuint64_t csr;\n+\t\tstruct {\n+\t\t\tuint32_t num_writes;\n+\t\t\tuint32_t num_reads;\n+\t\t};\n+\t};\n+};\n+\n+struct he_lpbk_status1 {\n+\tunion {\n+\t\tuint64_t csr;\n+\t\tstruct {\n+\t\t\tuint32_t num_pend_writes;\n+\t\t\tuint32_t num_pend_reads;\n+\t\t};\n+\t};\n+};\n+\n+struct he_lpbk_dsm_status {\n+\tuint32_t test_complete;\n+\tuint32_t test_error;\n+\tuint64_t num_clocks;\n+\tuint32_t num_reads;\n+\tuint32_t num_writes;\n+\tuint32_t start_overhead;\n+\tuint32_t end_overhead;\n+};\n+\n+struct he_lpbk_ctx {\n+\tuint8_t *addr;\n+\tuint8_t *dsm_ptr;\n+\tuint64_t dsm_iova;\n+\tuint8_t *src_ptr;\n+\tuint64_t src_iova;\n+\tuint8_t *dest_ptr;\n+\tuint64_t dest_iova;\n+\tstruct he_lpbk_dsm_status *status_ptr;\n+};\n+\n+struct he_lpbk_priv {\n+\tstruct rte_pmd_afu_he_lpbk_cfg he_lpbk_cfg;\n+\tstruct he_lpbk_ctx he_lpbk_ctx;\n+};\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _AFU_PMD_HE_LPBK_H_ */\ndiff --git a/drivers/raw/ifpga/meson.build b/drivers/raw/ifpga/meson.build\nindex 2294ab5..629ff8a 100644\n--- a/drivers/raw/ifpga/meson.build\n+++ b/drivers/raw/ifpga/meson.build\n@@ -14,7 +14,7 @@ deps += ['ethdev', 'rawdev', 'pci', 'bus_pci', 'kvargs',\n     'bus_vdev', 'bus_ifpga', 'net', 'net_i40e', 'net_ipn3ke']\n \n sources = files('ifpga_rawdev.c', 'rte_pmd_ifpga.c', 'afu_pmd_core.c',\n-    'afu_pmd_n3000.c')\n+    'afu_pmd_n3000.c', 'afu_pmd_he_lpbk.c')\n \n includes += include_directories('base')\n includes += include_directories('../../net/ipn3ke')\ndiff --git a/drivers/raw/ifpga/rte_pmd_afu.h b/drivers/raw/ifpga/rte_pmd_afu.h\nindex f14a053..19b3902 100644\n--- a/drivers/raw/ifpga/rte_pmd_afu.h\n+++ b/drivers/raw/ifpga/rte_pmd_afu.h\n@@ -90,6 +90,20 @@ struct rte_pmd_afu_n3000_cfg {\n \t};\n };\n \n+/**\n+ * HE-LPBK & HE-MEM-LPBK AFU configuration data structure.\n+ */\n+struct rte_pmd_afu_he_lpbk_cfg {\n+\tuint32_t mode;\n+\tuint32_t begin;\n+\tuint32_t end;\n+\tuint32_t multi_cl;\n+\tuint32_t cont;\n+\tuint32_t timeout;\n+\tuint32_t trput_interleave;\n+\tuint32_t freq_mhz;\n+};\n+\n #ifdef __cplusplus\n }\n #endif\n",
    "prefixes": [
        "v8",
        "3/5"
    ]
}