get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 105445,
    "url": "http://patches.dpdk.org/api/patches/105445/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20211227161645.24359-11-nipun.gupta@nxp.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": "<20211227161645.24359-11-nipun.gupta@nxp.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20211227161645.24359-11-nipun.gupta@nxp.com",
    "date": "2021-12-27T16:16:39",
    "name": "[v2,10/16] net/dpaa2: support recycle loopback port",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "726bba8f9136fe5c1f21ac6e737944959a73cf66",
    "submitter": {
        "id": 471,
        "url": "http://patches.dpdk.org/api/people/471/?format=api",
        "name": "Nipun Gupta",
        "email": "nipun.gupta@nxp.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20211227161645.24359-11-nipun.gupta@nxp.com/mbox/",
    "series": [
        {
            "id": 21030,
            "url": "http://patches.dpdk.org/api/series/21030/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=21030",
            "date": "2021-12-27T16:16:29",
            "name": "features and fixes on NXP eth devices",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/21030/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/105445/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/105445/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 9BDFFA04A5;\n\tMon, 27 Dec 2021 17:17:50 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id B63674117A;\n\tMon, 27 Dec 2021 17:17:05 +0100 (CET)",
            "from inva021.nxp.com (inva021.nxp.com [92.121.34.21])\n by mails.dpdk.org (Postfix) with ESMTP id 89DBE410FC\n for <dev@dpdk.org>; Mon, 27 Dec 2021 17:16:52 +0100 (CET)",
            "from inva021.nxp.com (localhost [127.0.0.1])\n by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 62832201BC6;\n Mon, 27 Dec 2021 17:16:52 +0100 (CET)",
            "from aprdc01srsp001v.ap-rdc01.nxp.com\n (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16])\n by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id F351020155C;\n Mon, 27 Dec 2021 17:16:51 +0100 (CET)",
            "from lsv03274.swis.in-blr01.nxp.com (lsv03274.swis.in-blr01.nxp.com\n [92.120.147.114])\n by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 657C8183AD05;\n Tue, 28 Dec 2021 00:16:51 +0800 (+08)"
        ],
        "From": "nipun.gupta@nxp.com",
        "To": "dev@dpdk.org",
        "Cc": "thomas@monjalon.net, ferruh.yigit@intel.com, hemant.agrawal@nxp.com,\n Jun Yang <jun.yang@nxp.com>",
        "Subject": "[PATCH v2 10/16] net/dpaa2: support recycle loopback port",
        "Date": "Mon, 27 Dec 2021 21:46:39 +0530",
        "Message-Id": "<20211227161645.24359-11-nipun.gupta@nxp.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20211227161645.24359-1-nipun.gupta@nxp.com>",
        "References": "<20211206121824.3493-1-nipun.gupta@nxp.com>\n <20211227161645.24359-1-nipun.gupta@nxp.com>",
        "X-Virus-Scanned": "ClamAV using ClamSMTP",
        "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": "From: Jun Yang <jun.yang@nxp.com>\n\nDPAA2 recycle port is used for configuring the device\nin the loopback mode. Loopback configuration can be at\ndpni level or at serdes level.\n\nSigned-off-by: Jun Yang <jun.yang@nxp.com>\n---\n drivers/bus/fslmc/portal/dpaa2_hw_pvt.h |   3 +-\n drivers/net/dpaa2/dpaa2_ethdev.c        |  32 +-\n drivers/net/dpaa2/dpaa2_ethdev.h        |  23 +\n drivers/net/dpaa2/dpaa2_recycle.c       | 780 ++++++++++++++++++++++++\n drivers/net/dpaa2/mc/dpni.c             |  32 +\n drivers/net/dpaa2/mc/fsl_dpni_cmd.h     |   1 +\n drivers/net/dpaa2/meson.build           |   1 +\n 7 files changed, 870 insertions(+), 2 deletions(-)\n create mode 100644 drivers/net/dpaa2/dpaa2_recycle.c",
    "diff": "diff --git a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h\nindex 8cb4d404aa..4d0f7e4b5d 100644\n--- a/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h\n+++ b/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h\n@@ -1,7 +1,7 @@\n /* SPDX-License-Identifier: BSD-3-Clause\n  *\n  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.\n- *   Copyright 2016-2020 NXP\n+ *   Copyright 2016-2021 NXP\n  *\n  */\n \n@@ -176,6 +176,7 @@ struct dpaa2_queue {\n \tuint16_t nb_desc;\n \tuint16_t resv;\n \tuint64_t offloads;\n+\tuint64_t lpbk_cntx;\n } __rte_cache_aligned;\n \n struct swp_active_dqs {\ndiff --git a/drivers/net/dpaa2/dpaa2_ethdev.c b/drivers/net/dpaa2/dpaa2_ethdev.c\nindex a45beed75f..d81f8cb07a 100644\n--- a/drivers/net/dpaa2/dpaa2_ethdev.c\n+++ b/drivers/net/dpaa2/dpaa2_ethdev.c\n@@ -668,6 +668,30 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev)\n \tif (rx_offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER)\n \t\tdpaa2_vlan_offload_set(dev, RTE_ETH_VLAN_FILTER_MASK);\n \n+\tif (eth_conf->lpbk_mode) {\n+\t\tret = dpaa2_dev_recycle_config(dev);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"Error to configure %s to recycle port.\",\n+\t\t\t\tdev->data->name);\n+\n+\t\t\treturn ret;\n+\t\t}\n+\t} else {\n+\t\t/** User may disable loopback mode by calling\n+\t\t * \"dev_configure\" with lpbk_mode cleared.\n+\t\t * No matter the port was configured recycle or not,\n+\t\t * recycle de-configure is called here.\n+\t\t * If port is not recycled, the de-configure will return directly.\n+\t\t */\n+\t\tret = dpaa2_dev_recycle_deconfig(dev);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"Error to de-configure recycle port %s.\",\n+\t\t\t\tdev->data->name);\n+\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n \tdpaa2_tm_init(dev);\n \n \treturn 0;\n@@ -2601,6 +2625,9 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)\n \t\treturn -1;\n \t}\n \n+\tif (eth_dev->data->dev_conf.lpbk_mode)\n+\t\tdpaa2_dev_recycle_deconfig(eth_dev);\n+\n \t/* Clean the device first */\n \tret = dpni_reset(dpni_dev, CMD_PRI_LOW, priv->token);\n \tif (ret) {\n@@ -2624,6 +2651,7 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)\n \tpriv->dist_queues = attr.num_queues;\n \tpriv->num_channels = attr.num_channels;\n \tpriv->channel_inuse = 0;\n+\trte_spinlock_init(&priv->lpbk_qp_lock);\n \n \t/* only if the custom CG is enabled */\n \tif (attr.options & DPNI_OPT_CUSTOM_CG)\n@@ -2808,7 +2836,9 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)\n \t\t\treturn ret;\n \t\t}\n \t}\n-\tRTE_LOG(INFO, PMD, \"%s: netdev created\\n\", eth_dev->data->name);\n+\tRTE_LOG(INFO, PMD, \"%s: netdev created, connected to %s\\n\",\n+\t\teth_dev->data->name, dpaa2_dev->ep_name);\n+\n \treturn 0;\n init_err:\n \tdpaa2_dev_close(eth_dev);\ndiff --git a/drivers/net/dpaa2/dpaa2_ethdev.h b/drivers/net/dpaa2/dpaa2_ethdev.h\nindex bd33a22a8e..b032da9eff 100644\n--- a/drivers/net/dpaa2/dpaa2_ethdev.h\n+++ b/drivers/net/dpaa2/dpaa2_ethdev.h\n@@ -11,6 +11,7 @@\n #include <rte_event_eth_rx_adapter.h>\n #include <rte_pmd_dpaa2.h>\n \n+#include <rte_fslmc.h>\n #include <dpaa2_hw_pvt.h>\n #include \"dpaa2_tm.h\"\n \n@@ -65,6 +66,18 @@\n /* Tx confirmation enabled */\n #define DPAA2_TX_CONF_ENABLE\t0x06\n \n+/* HW loopback the egress traffic to self ingress*/\n+#define DPAA2_TX_MAC_LOOPBACK_MODE 0x20\n+\n+#define DPAA2_TX_SERDES_LOOPBACK_MODE 0x40\n+\n+#define DPAA2_TX_DPNI_LOOPBACK_MODE 0x80\n+\n+#define DPAA2_TX_LOOPBACK_MODE \\\n+\t(DPAA2_TX_MAC_LOOPBACK_MODE | \\\n+\tDPAA2_TX_SERDES_LOOPBACK_MODE | \\\n+\tDPAA2_TX_DPNI_LOOPBACK_MODE)\n+\n #define DPAA2_RSS_OFFLOAD_ALL ( \\\n \tRTE_ETH_RSS_L2_PAYLOAD | \\\n \tRTE_ETH_RSS_IP | \\\n@@ -192,6 +205,7 @@ struct dpaa2_dev_priv {\n \tstruct dpaa2_queue *next_tx_conf_queue;\n \n \tstruct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */\n+\trte_spinlock_t lpbk_qp_lock;\n \n \tuint8_t channel_inuse;\n \tLIST_HEAD(, rte_flow) flows; /**< Configured flow rule handles. */\n@@ -268,4 +282,13 @@ int dpaa2_timesync_read_rx_timestamp(struct rte_eth_dev *dev,\n \t\t\t\t\t\tuint32_t flags __rte_unused);\n int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev,\n \t\t\t\t\t  struct timespec *timestamp);\n+\n+int dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev);\n+int dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev);\n+int dpaa2_dev_recycle_qp_setup(struct rte_dpaa2_device *dpaa2_dev,\n+\tuint16_t qidx, uint64_t cntx,\n+\teth_rx_burst_t tx_lpbk, eth_tx_burst_t rx_lpbk,\n+\tstruct dpaa2_queue **txq,\n+\tstruct dpaa2_queue **rxq);\n+\n #endif /* _DPAA2_ETHDEV_H */\ndiff --git a/drivers/net/dpaa2/dpaa2_recycle.c b/drivers/net/dpaa2/dpaa2_recycle.c\nnew file mode 100644\nindex 0000000000..e274d24ead\n--- /dev/null\n+++ b/drivers/net/dpaa2/dpaa2_recycle.c\n@@ -0,0 +1,780 @@\n+/* * SPDX-License-Identifier: BSD-3-Clause\n+ *\n+ *   Copyright 2019-2021 NXP\n+ *\n+ */\n+\n+#include <time.h>\n+#include <net/if.h>\n+\n+#include <rte_mbuf.h>\n+#include <ethdev_driver.h>\n+#include <rte_malloc.h>\n+#include <rte_memcpy.h>\n+#include <rte_string_fns.h>\n+#include <rte_cycles.h>\n+#include <rte_kvargs.h>\n+#include <rte_dev.h>\n+#include <rte_fslmc.h>\n+#include <rte_flow_driver.h>\n+\n+#include \"dpaa2_pmd_logs.h\"\n+#include <fslmc_vfio.h>\n+#include <dpaa2_hw_pvt.h>\n+#include <dpaa2_hw_mempool.h>\n+#include <dpaa2_hw_dpio.h>\n+#include <mc/fsl_dpmng.h>\n+#include \"dpaa2_ethdev.h\"\n+#include \"dpaa2_sparser.h\"\n+#include <fsl_qbman_debug.h>\n+\n+#include <rte_io.h>\n+#include <unistd.h>\n+#include <sys/mman.h>\n+\n+#define PAGE_SIZE\t\t\t(sysconf(_SC_PAGESIZE))\n+#define PAGE_MASK\t\t\t(~(PAGE_SIZE - 1))\n+\n+#define LSX_SERDES_LAN_NB\t\t8\n+#define LSX_SERDES_REG_BASE\t\t0x1ea0000\n+#define LSX_LB_EN_BIT\t\t\t0x10000000\n+\n+#define CONFIG_SYS_IMMR\t\t\t0x01000000\n+\n+#define CONFIG_SYS_FSL_GUTS_ADDR\t(CONFIG_SYS_IMMR + 0x00E00000)\n+#define CONFIG_SYS_FSL_SERDES_ADDR\t(CONFIG_SYS_IMMR + 0xEA0000)\n+\n+#define FSL_LX_SRDS1_PRTCL_SHIFT\t16\n+#define FSL_LX_SRDS2_PRTCL_SHIFT\t21\n+#define FSL_LX_SRDS3_PRTCL_SHIFT\t26\n+\n+#define FSL_LS_SRDS1_PRTCL_SHIFT\t16\n+#define FSL_LS_SRDS2_PRTCL_SHIFT\t0\n+\n+#define FSL_LX_SRDS1_REGSR\t\t29\n+#define FSL_LX_SRDS2_REGSR\t\t29\n+#define FSL_LX_SRDS3_REGSR\t\t29\n+\n+#define FSL_LS_SRDS1_REGSR\t\t29\n+#define FSL_LS_SRDS2_REGSR\t\t30\n+\n+#define FSL_LX_SRDS1_PRTCL_MASK\t\t0x001F0000\n+#define FSL_LX_SRDS2_PRTCL_MASK\t\t0x03E00000\n+#define FSL_LX_SRDS3_PRTCL_MASK\t\t0x7C000000\n+\n+#define FSL_LS_SRDS1_PRTCL_MASK\t\t0xFFFF0000\n+#define FSL_LS_SRDS2_PRTCL_MASK\t\t0x0000FFFF\n+\n+struct ccsr_lx_serdes_lan {\n+\tuint8_t unused1[0xa0];\n+\tuint32_t lnatcsr0;\n+\tuint8_t unused2[0x100 - 0xa4];\n+} __rte_packed;\n+\n+struct ccsr_lx_serdes {\n+\tuint8_t unused0[0x800];\n+\tstruct ccsr_lx_serdes_lan lane[LSX_SERDES_LAN_NB];\n+} __rte_packed;\n+\n+struct ccsr_ls_serdes {\n+\tuint8_t unused[0x800];\n+\tstruct serdes_lane {\n+\t\tuint32_t gcr0;   /* General Control Register 0 */\n+\t\tuint32_t gcr1;   /* General Control Register 1 */\n+\t\tuint32_t gcr2;   /* General Control Register 2 */\n+\t\tuint32_t ssc0;   /* Speed Switch Control 0 */\n+\t\tuint32_t rec0;   /* Receive Equalization Control 0 */\n+\t\tuint32_t rec1;   /* Receive Equalization Control 1 */\n+\t\tuint32_t tec0;   /* Transmit Equalization Control 0 */\n+\t\tuint32_t ssc1;   /* Speed Switch Control 1 */\n+\t\tuint32_t ttlc;\n+\t\tuint32_t rev[6];\n+\t\tuint32_t tsc3;\n+\t} lane[LSX_SERDES_LAN_NB];\n+\tuint8_t res5[0x19fc - 0xa00];\n+} __rte_packed;\n+\n+struct ccsr_gur {\n+\tuint32_t\tporsr1;\t\t/* POR status 1 */\n+\tuint32_t\tporsr2;\t\t/* POR status 2 */\n+\tuint8_t\tres_008[0x20 - 0x8];\n+\tuint32_t\tgpporcr1; /* General-purpose POR configuration */\n+\tuint32_t\tgpporcr2; /* General-purpose POR configuration 2 */\n+\tuint32_t\tgpporcr3;\n+\tuint32_t\tgpporcr4;\n+\tuint8_t\tres_030[0x60 - 0x30];\n+\tuint32_t\tdcfg_fusesr;\t/* Fuse status register */\n+\tuint8_t\tres_064[0x70 - 0x64];\n+\tuint32_t\tdevdisr;\t/* Device disable control 1 */\n+\tuint32_t\tdevdisr2;\t/* Device disable control 2 */\n+\tuint32_t\tdevdisr3;\t/* Device disable control 3 */\n+\tuint32_t\tdevdisr4;\t/* Device disable control 4 */\n+\tuint32_t\tdevdisr5;\t/* Device disable control 5 */\n+\tuint32_t\tdevdisr6;\t/* Device disable control 6 */\n+\tuint8_t\tres_088[0x94 - 0x88];\n+\tuint32_t\tcoredisr;\t/* Device disable control 7 */\n+\tuint8_t\tres_098[0xa0 - 0x98];\n+\tuint32_t\tpvr;\t\t/* Processor version */\n+\tuint32_t\tsvr;\t\t/* System version */\n+\tuint8_t\tres_0a8[0x100 - 0xa8];\n+\tuint32_t\trcwsr[30];\t/* Reset control word status */\n+\n+\tuint8_t\tres_178[0x200 - 0x178];\n+\tuint32_t\tscratchrw[16];\t/* Scratch Read/Write */\n+\tuint8_t\tres_240[0x300 - 0x240];\n+\tuint32_t\tscratchw1r[4];\t/* Scratch Read (Write once) */\n+\tuint8_t\tres_310[0x400 - 0x310];\n+\tuint32_t\tbootlocptrl; /* Boot location pointer low-order addr */\n+\tuint32_t\tbootlocptrh; /* Boot location pointer high-order addr */\n+\tuint8_t\tres_408[0x520 - 0x408];\n+\tuint32_t\tusb1_amqr;\n+\tuint32_t\tusb2_amqr;\n+\tuint8_t\tres_528[0x530 - 0x528];\t/* add more registers when needed */\n+\tuint32_t\tsdmm1_amqr;\n+\tuint32_t\tsdmm2_amqr;\n+\tuint8_t\tres_538[0x550 - 0x538];\t/* add more registers when needed */\n+\tuint32_t\tsata1_amqr;\n+\tuint32_t\tsata2_amqr;\n+\tuint32_t\tsata3_amqr;\n+\tuint32_t\tsata4_amqr;\n+\tuint8_t\tres_560[0x570 - 0x560];\t/* add more registers when needed */\n+\tuint32_t\tmisc1_amqr;\n+\tuint8_t\tres_574[0x590 - 0x574];\t/* add more registers when needed */\n+\tuint32_t\tspare1_amqr;\n+\tuint32_t\tspare2_amqr;\n+\tuint32_t\tspare3_amqr;\n+\tuint8_t\tres_59c[0x620 - 0x59c];\t/* add more registers when needed */\n+\tuint32_t\tgencr[7];\t/* General Control Registers */\n+\tuint8_t\tres_63c[0x640 - 0x63c];\t/* add more registers when needed */\n+\tuint32_t\tcgensr1;\t/* Core General Status Register */\n+\tuint8_t\tres_644[0x660 - 0x644];\t/* add more registers when needed */\n+\tuint32_t\tcgencr1;\t/* Core General Control Register */\n+\tuint8_t\tres_664[0x740 - 0x664];\t/* add more registers when needed */\n+\tuint32_t\ttp_ityp[64];\t/* Topology Initiator Type Register */\n+\tstruct {\n+\t\tuint32_t\tupper;\n+\t\tuint32_t\tlower;\n+\t} tp_cluster[4];\t/* Core cluster n Topology Register */\n+\tuint8_t\tres_864[0x920 - 0x864];\t/* add more registers when needed */\n+\tuint32_t ioqoscr[8];\t/*I/O Quality of Services Register */\n+\tuint32_t uccr;\n+\tuint8_t\tres_944[0x960 - 0x944];\t/* add more registers when needed */\n+\tuint32_t ftmcr;\n+\tuint8_t\tres_964[0x990 - 0x964];\t/* add more registers when needed */\n+\tuint32_t coredisablesr;\n+\tuint8_t\tres_994[0xa00 - 0x994];\t/* add more registers when needed */\n+\tuint32_t sdbgcr; /*Secure Debug Confifuration Register */\n+\tuint8_t\tres_a04[0xbf8 - 0xa04];\t/* add more registers when needed */\n+\tuint32_t ipbrr1;\n+\tuint32_t ipbrr2;\n+\tuint8_t\tres_858[0x1000 - 0xc00];\n+} __rte_packed;\n+\n+static void *lsx_ccsr_map_region(uint64_t addr, size_t len)\n+{\n+\tint fd;\n+\tvoid *tmp;\n+\tuint64_t start;\n+\tuint64_t offset;\n+\n+\tfd = open(\"/dev/mem\", O_RDWR);\n+\tif (fd < 0) {\n+\t\tDPAA2_PMD_ERR(\"Fail to open /dev/mem\");\n+\t\treturn NULL;\n+\t}\n+\n+\tstart = addr & PAGE_MASK;\n+\toffset = addr - start;\n+\tlen = len & PAGE_MASK;\n+\tif (len < (size_t)PAGE_SIZE)\n+\t\tlen = PAGE_SIZE;\n+\n+\ttmp = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start);\n+\n+\tclose(fd);\n+\n+\tif (tmp != MAP_FAILED)\n+\t\treturn (uint8_t *)tmp + offset;\n+\telse\n+\t\treturn NULL;\n+}\n+\n+static const uint8_t ls_sd1_prot_idx_map[] = {\n+\t0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0e,\n+\t0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c,\n+\t0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a,\n+\t0x2b, 0x2d, 0x2e, 0x30, 0x32, 0x33, 0x35,\n+\t0x37, 0x39, 0x3b, 0x4b, 0x4c, 0x4d, 0x58\n+};\n+\n+static const uint8_t ls_sd2_prot_idx_map[] = {\n+\t0x07, 0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x12,\n+\t0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20,\n+\t0x22, 0x24, 0x3d, 0x3f, 0x41, 0x43, 0x45,\n+\t0x47, 0x49, 0x4f, 0x50, 0x51, 0x52, 0x53,\n+\t0x54, 0x55, 0x56, 0x57\n+};\n+\n+static const uint8_t ls_sd1_eth_loopback_support[][LSX_SERDES_LAN_NB] = {\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x03*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x05*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x07*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x09*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0a*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0c*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0e*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x10*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x12*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x14*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x16*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x18*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1a*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1c*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1e*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x20*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x22*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x24*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x26*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x28*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x2a*/\n+\n+\t{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2b*/\n+\t{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2d*/\n+\t{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x2e*/\n+\t{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x30*/\n+\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x32*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x33*/\n+\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x35*/\n+\t{1, 1, 0, 0, 0, 0, 0, 0}, /* 0x37*/\n+\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x39*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x3b*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x4b*/\n+\t{0, 0, 0, 0, 1, 1, 1, 1}, /* 0x4c*/\n+\t{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x4d*/\n+\t{0, 0, 0, 0, 0, 0, 1, 1}  /* 0x58*/\n+};\n+\n+static const uint8_t ls_sd2_eth_loopback_support[][LSX_SERDES_LAN_NB] = {\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x07*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x09*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0a*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0c*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x0e*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x10*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x12*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x14*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x16*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x18*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1a*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1c*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x1e*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x20*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x22*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 0x24*/\n+\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x3d*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x3f*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x41*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x43*/\n+\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x45*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x47*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x49*/\n+\n+\t{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x4f*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x50*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0x51*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 0x52*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x53*/\n+\t{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x54*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 0x55*/\n+\t{0, 0, 1, 1, 0, 0, 1, 1}, /* 0x56*/\n+\t{0, 0, 0, 0, 0, 0, 1, 1}  /* 0x57*/\n+};\n+\n+enum lsx_serdes_id {\n+\tLSX_SERDES_1 = 1,\n+\tLSX_SERDES_2 = 2\n+};\n+\n+static const uint8_t lx_sd1_loopback_support[][LSX_SERDES_LAN_NB] = {\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 1 prot*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 2 prot*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 3 prot*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 4 prot*/\n+\t{0, 0, 0, 0, 1, 1, 1, 1}, /* 5 prot*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 6 prot*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 7 prot*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 8 prot*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 9 prot*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 10 prot*/\n+\t{0, 0, 1, 1, 0, 0, 1, 1}, /* 11 prot*/\n+\t{0, 0, 0, 0, 0, 0, 1, 1}, /* 12 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 13 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 14 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 15 prot*/\n+\t{0, 0, 1, 1, 0, 0, 0, 0}, /* 16 prot*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 17 prot*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 18 prot*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 19 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 20 prot*/\n+\t{1, 1, 1, 1, 0, 0, 1, 1}, /* 21 prot*/\n+\t{1, 1, 1, 1, 0, 0, 1, 1}  /* 22 prot*/\n+};\n+\n+static const uint8_t lx_sd2_loopback_support[][LSX_SERDES_LAN_NB] = {\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 0 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 1 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 2 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 3 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 4 prot*/\n+\t{0, 0, 0, 0, 0, 0, 0, 0}, /* 5 prot*/\n+\t{0, 0, 0, 0, 1, 1, 1, 1}, /* 6 prot*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 7 prot*/\n+\t{0, 0, 0, 0, 0, 0, 1, 1}, /* 8 prot*/\n+\t{1, 1, 1, 1, 1, 1, 1, 1}, /* 9 prot*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 10 prot*/\n+\t{0, 1, 1, 1, 0, 1, 1, 1}, /* 11 prot*/\n+\t{1, 1, 1, 1, 0, 0, 0, 0}, /* 12 prot*/\n+\t{0, 0, 0, 0, 0, 0, 1, 1}, /* 13 prot*/\n+\t{0, 0, 1, 1, 0, 0, 1, 1}  /* 14 prot*/\n+};\n+\n+static inline int\n+ls_mac_to_serdes_id(uint8_t mac_id)\n+{\n+\tif (mac_id >= 1 && mac_id <= 8)\n+\t\treturn LSX_SERDES_1;\n+\tif (mac_id >= 9 && mac_id <= 16)\n+\t\treturn LSX_SERDES_2;\n+\n+\treturn -1;\n+}\n+\n+static inline int\n+lx_mac_to_serdes_id(uint8_t mac_id)\n+{\n+\tif (mac_id >= 1 && mac_id <= 10)\n+\t\treturn LSX_SERDES_1;\n+\tif (mac_id >= 11 && mac_id <= 18)\n+\t\treturn LSX_SERDES_2;\n+\n+\treturn -1;\n+}\n+\n+static inline int\n+ls_serdes_cfg_to_idx(uint8_t sd_cfg, int sd_id)\n+{\n+\tint i;\n+\n+\tif (sd_id == LSX_SERDES_1) {\n+\t\tfor (i = 0; i < (int)sizeof(ls_sd1_prot_idx_map); i++) {\n+\t\t\tif (ls_sd1_prot_idx_map[i] == sd_cfg)\n+\t\t\t\treturn i;\n+\t\t}\n+\t} else if (sd_id == LSX_SERDES_2) {\n+\t\tfor (i = 0; i < (int)sizeof(ls_sd2_prot_idx_map); i++) {\n+\t\t\tif (ls_sd2_prot_idx_map[i] == sd_cfg)\n+\t\t\t\treturn i;\n+\t\t}\n+\t}\n+\n+\treturn -1;\n+}\n+\n+static inline int\n+lx_serdes_cfg_to_idx(uint8_t sd_cfg, int sd_id __rte_unused)\n+{\n+\treturn sd_cfg;\n+}\n+\n+static inline int\n+ls_mac_serdes_lpbk_support(uint16_t mac_id,\n+\tuint16_t *serdes_id, uint16_t *lan_id)\n+{\n+\tstruct ccsr_gur *gur_base =\n+\t\tlsx_ccsr_map_region(CONFIG_SYS_FSL_GUTS_ADDR,\n+\t\t\tsizeof(struct ccsr_gur) / 64 * 64 + 64);\n+\tuint32_t sd_cfg;\n+\tint sd_id, sd_idx;\n+\tuint16_t lan_id_tmp = 0;\n+\tconst uint8_t *ls_sd_loopback_support;\n+\n+\tsd_id = ls_mac_to_serdes_id(mac_id);\n+\n+\tif (sd_id == LSX_SERDES_1) {\n+\t\tsd_cfg = rte_read32(&gur_base->rcwsr[FSL_LS_SRDS1_REGSR - 1]) &\n+\t\t\t\tFSL_LS_SRDS1_PRTCL_MASK;\n+\t\tsd_cfg >>= FSL_LS_SRDS1_PRTCL_SHIFT;\n+\t} else if (sd_id == LSX_SERDES_2) {\n+\t\tsd_cfg = rte_read32(&gur_base->rcwsr[FSL_LS_SRDS2_REGSR - 1]) &\n+\t\t\t\tFSL_LS_SRDS2_PRTCL_MASK;\n+\t\tsd_cfg >>= FSL_LS_SRDS2_PRTCL_SHIFT;\n+\t} else {\n+\t\treturn false;\n+\t}\n+\tsd_cfg = sd_cfg & 0xff;\n+\n+\tsd_idx = ls_serdes_cfg_to_idx(sd_cfg, sd_id);\n+\tif (sd_idx < 0) {\n+\t\tDPAA2_PMD_ERR(\"Serdes protocol(0x%02x) does not exist\\n\",\n+\t\t\tsd_cfg);\n+\t\treturn false;\n+\t}\n+\n+\tif (sd_id == LSX_SERDES_1) {\n+\t\tls_sd_loopback_support =\n+\t\t\t&ls_sd1_eth_loopback_support[sd_idx][0];\n+\t} else {\n+\t\tls_sd_loopback_support =\n+\t\t\t&ls_sd2_eth_loopback_support[sd_idx][0];\n+\t}\n+\n+\tif (sd_id == LSX_SERDES_1)\n+\t\tlan_id_tmp = (mac_id - 1);\n+\telse\n+\t\tlan_id_tmp = (mac_id - 9);\n+\n+\tif (lan_id_tmp >= LSX_SERDES_LAN_NB) {\n+\t\tDPAA2_PMD_ERR(\"Invalid serdes lan(%d).\", lan_id_tmp);\n+\t\treturn false;\n+\t}\n+\n+\tif (!ls_sd_loopback_support[lan_id_tmp])\n+\t\treturn false;\n+\n+\tif (lan_id)\n+\t\t*lan_id = lan_id_tmp;\n+\tif (serdes_id)\n+\t\t*serdes_id = sd_id;\n+\n+\treturn true;\n+}\n+\n+static inline int\n+lx_mac_serdes_lpbk_support(uint16_t mac_id,\n+\tuint16_t *serdes_id, uint16_t *lan_id)\n+{\n+\tstruct ccsr_gur *gur_base =\n+\t\tlsx_ccsr_map_region(CONFIG_SYS_FSL_GUTS_ADDR,\n+\t\t\tsizeof(struct ccsr_gur) / 64 * 64 + 64);\n+\tuint32_t sd_cfg;\n+\tint sd_id, sd_idx;\n+\tuint16_t lan_id_tmp = 0;\n+\tconst uint8_t *lx_sd_loopback_support;\n+\n+\tsd_id = lx_mac_to_serdes_id(mac_id);\n+\n+\tif (sd_id == LSX_SERDES_1) {\n+\t\tsd_cfg = rte_read32(&gur_base->rcwsr[FSL_LX_SRDS1_REGSR - 1]) &\n+\t\t\t\tFSL_LX_SRDS1_PRTCL_MASK;\n+\t\tsd_cfg >>= FSL_LX_SRDS1_PRTCL_SHIFT;\n+\t} else if (sd_id == LSX_SERDES_2) {\n+\t\tsd_cfg = rte_read32(&gur_base->rcwsr[FSL_LX_SRDS2_REGSR - 1]) &\n+\t\t\t\tFSL_LX_SRDS2_PRTCL_MASK;\n+\t\tsd_cfg >>= FSL_LX_SRDS2_PRTCL_SHIFT;\n+\t} else {\n+\t\treturn false;\n+\t}\n+\tsd_cfg = sd_cfg & 0xff;\n+\n+\tsd_idx = lx_serdes_cfg_to_idx(sd_cfg, sd_id);\n+\tif (sd_idx < 0)\n+\t\treturn false;\n+\n+\tif (sd_id == LSX_SERDES_1)\n+\t\tlx_sd_loopback_support = &lx_sd1_loopback_support[sd_idx][0];\n+\telse\n+\t\tlx_sd_loopback_support = &lx_sd2_loopback_support[sd_idx][0];\n+\n+\tif (sd_id == LSX_SERDES_1) {\n+\t\tif (mac_id == 1)\n+\t\t\tlan_id_tmp = 0;\n+\t\telse if (mac_id == 2)\n+\t\t\tlan_id_tmp = 4;\n+\t\telse\n+\t\t\tlan_id_tmp = (mac_id - 3);\n+\t} else {\n+\t\tif (mac_id == 11)\n+\t\t\tlan_id_tmp = 0;\n+\t\telse if (mac_id == 12)\n+\t\t\tlan_id_tmp = 1;\n+\t\telse if (mac_id == 13)\n+\t\t\tlan_id_tmp = 6;\n+\t\telse if (mac_id == 14)\n+\t\t\tlan_id_tmp = 7;\n+\t\telse if (mac_id == 15)\n+\t\t\tlan_id_tmp = 4;\n+\t\telse if (mac_id == 16)\n+\t\t\tlan_id_tmp = 5;\n+\t\telse if (mac_id == 17)\n+\t\t\tlan_id_tmp = 2;\n+\t\telse if (mac_id == 18)\n+\t\t\tlan_id_tmp = 3;\n+\t\telse\n+\t\t\treturn false;\n+\t}\n+\n+\tif (lan_id_tmp >= LSX_SERDES_LAN_NB)\n+\t\treturn false;\n+\n+\tif (!lx_sd_loopback_support[lan_id_tmp])\n+\t\treturn false;\n+\n+\tif (lan_id)\n+\t\t*lan_id = lan_id_tmp;\n+\tif (serdes_id)\n+\t\t*serdes_id = sd_id;\n+\n+\treturn true;\n+}\n+\n+static inline int\n+ls_serdes_eth_lpbk(uint16_t mac_id, int en)\n+{\n+\tuint16_t serdes_id, lan_id;\n+\tint ret;\n+\tuint32_t data;\n+\tstruct ccsr_ls_serdes *serdes_base;\n+\tvoid *reg = 0;\n+\n+\tret = ls_mac_serdes_lpbk_support(mac_id, &serdes_id, &lan_id);\n+\tif (!ret)\n+\t\treturn -ENOTSUP;\n+\n+\tserdes_base = lsx_ccsr_map_region(CONFIG_SYS_FSL_SERDES_ADDR +\n+\t\t\t\t(serdes_id - LSX_SERDES_1) * 0x10000,\n+\t\t\t\tsizeof(struct ccsr_ls_serdes) / 64 * 64 + 64);\n+\tif (!serdes_base) {\n+\t\tDPAA2_PMD_ERR(\"Serdes register map failed\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tif (serdes_id == LSX_SERDES_1)\n+\t\tlan_id = LSX_SERDES_LAN_NB - lan_id - 1;\n+\n+\treg = &serdes_base->lane[lan_id].tsc3;\n+\n+\tdata = rte_read32(reg);\n+\tif (en)\n+\t\trte_write32(data | LSX_LB_EN_BIT, reg);\n+\telse\n+\t\trte_write32(data & (~LSX_LB_EN_BIT), reg);\n+\n+\treturn 0;\n+}\n+\n+static inline int\n+lx_serdes_eth_lpbk(uint16_t mac_id, int en)\n+{\n+\tuint16_t serdes_id = 0xffff, lan_id = 0xffff;\n+\tint ret;\n+\tuint32_t data;\n+\tstruct ccsr_lx_serdes *serdes_base;\n+\tvoid *reg = 0;\n+\n+\tret = lx_mac_serdes_lpbk_support(mac_id, &serdes_id, &lan_id);\n+\tif (!ret)\n+\t\treturn -ENOTSUP;\n+\n+\tserdes_base = lsx_ccsr_map_region(CONFIG_SYS_FSL_SERDES_ADDR +\n+\t\t\t\t\t(serdes_id - LSX_SERDES_1) * 0x10000,\n+\t\t\t\t\tsizeof(struct ccsr_lx_serdes) / 64 * 64 + 64);\n+\tif (!serdes_base) {\n+\t\tDPAA2_PMD_ERR(\"Serdes register map failed\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\tif (serdes_id == LSX_SERDES_1)\n+\t\tlan_id = LSX_SERDES_LAN_NB - lan_id - 1;\n+\n+\treg = &serdes_base->lane[lan_id].lnatcsr0;\n+\n+\tdata = rte_read32(reg);\n+\tif (en)\n+\t\trte_write32(data | LSX_LB_EN_BIT, reg);\n+\telse\n+\t\trte_write32(data & (~LSX_LB_EN_BIT), reg);\n+\n+\treturn 0;\n+}\n+\n+/* Configure dpaa2 port as recycle port */\n+int\n+dpaa2_dev_recycle_config(struct rte_eth_dev *eth_dev)\n+{\n+\tstruct rte_device *dev = eth_dev->device;\n+\tstruct dpaa2_dev_priv *priv = eth_dev->data->dev_private;\n+\tstruct rte_dpaa2_device *dpaa2_dev =\n+\t\t\tcontainer_of(dev, struct rte_dpaa2_device, device);\n+\tstruct fsl_mc_io *dpni_dev = eth_dev->process_private;\n+\tstruct dpni_port_cfg port_cfg;\n+\tint ret;\n+\n+\tif (priv->flags & DPAA2_TX_LOOPBACK_MODE) {\n+\t\tDPAA2_PMD_INFO(\"%s has been configured recycle device.\",\n+\t\t\teth_dev->data->name);\n+\n+\t\treturn 0;\n+\t}\n+\n+\tif (dpaa2_dev->ep_dev_type == DPAA2_MAC) {\n+\t\t/** For dpmac-dpni connection,\n+\t\t * try setting serdes loopback as recycle device at first.\n+\t\t */\n+\t\tif (dpaa2_svr_family == SVR_LS2088A) {\n+\t\t\tret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1);\n+\t\t\tif (!ret) {\n+\t\t\t\tpriv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE;\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t} else if (dpaa2_svr_family == SVR_LX2160A) {\n+\t\t\tret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 1);\n+\t\t\tif (!ret) {\n+\t\t\t\tpriv->flags |= DPAA2_TX_SERDES_LOOPBACK_MODE;\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tDPAA2_PMD_DEBUG(\"Serdes loopback not support SoC(0x%08x)\",\n+\t\t\t\tdpaa2_svr_family);\n+\t\t}\n+\n+\t\t/** If serdes loopback is not supported for this mac,\n+\t\t * trying set mac loopback.\n+\t\t */\n+\n+\t\tport_cfg.loopback_en = 1;\n+\t\tret = dpni_set_port_cfg(dpni_dev, CMD_PRI_LOW,\n+\t\t\t\tpriv->token,\n+\t\t\t\tDPNI_PORT_CFG_LOOPBACK,\n+\t\t\t\t&port_cfg);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"Error(%d) to enable loopback\", ret);\n+\t\t\treturn -ENOTSUP;\n+\t\t}\n+\n+\t\tpriv->flags |= DPAA2_TX_MAC_LOOPBACK_MODE;\n+\n+\t\treturn 0;\n+\t}\n+\n+\tif (dpaa2_dev->ep_dev_type == DPAA2_ETH &&\n+\t\tdpaa2_dev->object_id == dpaa2_dev->ep_object_id) {\n+\t\tpriv->flags |= DPAA2_TX_DPNI_LOOPBACK_MODE;\n+\n+\t\treturn 0;\n+\t}\n+\n+\treturn -ENOTSUP;\n+}\n+\n+int\n+dpaa2_dev_recycle_deconfig(struct rte_eth_dev *eth_dev)\n+{\n+\tstruct rte_device *dev = eth_dev->device;\n+\tstruct dpaa2_dev_priv *priv = eth_dev->data->dev_private;\n+\tstruct rte_dpaa2_device *dpaa2_dev =\n+\t\t\tcontainer_of(dev, struct rte_dpaa2_device, device);\n+\tstruct fsl_mc_io *dpni_dev = eth_dev->process_private;\n+\tstruct dpni_port_cfg port_cfg;\n+\tint ret = 0;\n+\n+\tif (!(priv->flags & DPAA2_TX_LOOPBACK_MODE))\n+\t\treturn 0;\n+\n+\tif (priv->flags & DPAA2_TX_SERDES_LOOPBACK_MODE) {\n+\t\tif (dpaa2_svr_family == SVR_LS2088A) {\n+\t\t\tret = ls_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_WARN(\"Error(%d) to disable Serdes loopback\",\n+\t\t\t\t\tret);\n+\t\t\t} else {\n+\t\t\t\tpriv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE;\n+\t\t\t}\n+\t\t} else if (dpaa2_svr_family == SVR_LX2160A) {\n+\t\t\tret = lx_serdes_eth_lpbk(dpaa2_dev->ep_object_id, 0);\n+\t\t\tif (ret) {\n+\t\t\t\tDPAA2_PMD_WARN(\"Error(%d) to disable Serdes loopback\",\n+\t\t\t\t\tret);\n+\t\t\t} else {\n+\t\t\t\tpriv->flags &= ~DPAA2_TX_SERDES_LOOPBACK_MODE;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tDPAA2_PMD_DEBUG(\"Serdes loopback not support SoC(0x%08x)\",\n+\t\t\t\tdpaa2_svr_family);\n+\t\t}\n+\t}\n+\n+\tif (priv->flags & DPAA2_TX_MAC_LOOPBACK_MODE) {\n+\t\tport_cfg.loopback_en = 0;\n+\t\tret = dpni_set_port_cfg(dpni_dev, CMD_PRI_LOW,\n+\t\t\t\tpriv->token,\n+\t\t\t\tDPNI_PORT_CFG_LOOPBACK,\n+\t\t\t\t&port_cfg);\n+\t\tif (ret) {\n+\t\t\tDPAA2_PMD_ERR(\"Error(%d) to disable TX mac loopback\",\n+\t\t\t\tret);\n+\t\t} else {\n+\t\t\tpriv->flags &= ~DPAA2_TX_MAC_LOOPBACK_MODE;\n+\t\t}\n+\t}\n+\n+\tif (priv->flags & DPAA2_TX_DPNI_LOOPBACK_MODE)\n+\t\tpriv->flags &= ~DPAA2_TX_DPNI_LOOPBACK_MODE;\n+\n+\treturn ret;\n+}\n+\n+int\n+dpaa2_dev_recycle_qp_setup(struct rte_dpaa2_device *dpaa2_dev,\n+\tuint16_t qidx, uint64_t cntx,\n+\teth_rx_burst_t tx_lpbk, eth_tx_burst_t rx_lpbk,\n+\tstruct dpaa2_queue **txq,\n+\tstruct dpaa2_queue **rxq)\n+{\n+\tstruct rte_eth_dev *dev;\n+\tstruct rte_eth_dev_data *data;\n+\tstruct dpaa2_queue *txq_tmp;\n+\tstruct dpaa2_queue *rxq_tmp;\n+\tstruct dpaa2_dev_priv *priv;\n+\n+\tdev = dpaa2_dev->eth_dev;\n+\tdata = dev->data;\n+\tpriv = data->dev_private;\n+\n+\tif (!(priv->flags & DPAA2_TX_LOOPBACK_MODE) &&\n+\t\t(tx_lpbk || rx_lpbk)) {\n+\t\tDPAA2_PMD_ERR(\"%s is NOT recycle device!\", data->name);\n+\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (qidx >= data->nb_rx_queues || qidx >= data->nb_tx_queues)\n+\t\treturn -EINVAL;\n+\n+\trte_spinlock_lock(&priv->lpbk_qp_lock);\n+\n+\tif (tx_lpbk)\n+\t\tdev->tx_pkt_burst = tx_lpbk;\n+\n+\tif (rx_lpbk)\n+\t\tdev->rx_pkt_burst = rx_lpbk;\n+\n+\ttxq_tmp = data->tx_queues[qidx];\n+\ttxq_tmp->lpbk_cntx = cntx;\n+\trxq_tmp = data->rx_queues[qidx];\n+\trxq_tmp->lpbk_cntx = cntx;\n+\n+\tif (txq)\n+\t\t*txq = txq_tmp;\n+\tif (rxq)\n+\t\t*rxq = rxq_tmp;\n+\n+\trte_spinlock_unlock(&priv->lpbk_qp_lock);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c\nindex b7a65cb637..7a2bc15eb4 100644\n--- a/drivers/net/dpaa2/mc/dpni.c\n+++ b/drivers/net/dpaa2/mc/dpni.c\n@@ -3087,3 +3087,35 @@ int dpni_get_custom_tpid(struct fsl_mc_io *mc_io, uint32_t cmd_flags,\n \treturn err;\n }\n \n+/**\n+ * dpni_set_port_cfg() - performs configurations at physical port connected on\n+ *\t\tthis dpni. The command have effect only if dpni is connected to\n+ *\t\tanother dpni object\n+ * @mc_io:\tPointer to MC portal's I/O object\n+ * @cmd_flags:\tCommand flags; one or more of 'MC_CMD_FLAG_'\n+ * @token:\tToken of DPNI object\n+ * @flags:\tValid fields from port_cfg structure\n+ * @port_cfg: Configuration data; one or more of DPNI_PORT_CFG_\n+ * The command can be called only when dpni is connected to a dpmac object. If\n+ * the dpni is unconnected or the endpoint is not a dpni it will return error.\n+ * If dpmac endpoint is disconnected the settings will be lost\n+ */\n+int dpni_set_port_cfg(struct fsl_mc_io *mc_io, uint32_t cmd_flags,\n+\t\tuint16_t token, uint32_t flags, struct dpni_port_cfg *port_cfg)\n+{\n+\tstruct dpni_cmd_set_port_cfg *cmd_params;\n+\tstruct mc_command cmd = { 0 };\n+\n+\t/* prepare command */\n+\tcmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PORT_CFG,\n+\t\t\tcmd_flags, token);\n+\n+\tcmd_params = (struct dpni_cmd_set_port_cfg *)cmd.params;\n+\tcmd_params->flags = cpu_to_le32(flags);\n+\tdpni_set_field(cmd_params->bit_params,\tPORT_LOOPBACK_EN,\n+\t\t\t!!port_cfg->loopback_en);\n+\n+\t/* send command to MC */\n+\treturn mc_send_command(mc_io, &cmd);\n+}\n+\ndiff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h\nindex ed0bd7615a..b7bd7556af 100644\n--- a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h\n+++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h\n@@ -119,6 +119,7 @@\n #define DPNI_CMDID_REMOVE_CUSTOM_TPID\t\tDPNI_CMD(0x276)\n #define DPNI_CMDID_GET_CUSTOM_TPID\t\tDPNI_CMD(0x277)\n #define DPNI_CMDID_GET_LINK_CFG\t\t\tDPNI_CMD(0x278)\n+#define DPNI_CMDID_SET_PORT_CFG\t\t\tDPNI_CMD(0x27B)\n \n /* Macros for accessing command fields smaller than 1byte */\n #define DPNI_MASK(field)\t\\\ndiff --git a/drivers/net/dpaa2/meson.build b/drivers/net/dpaa2/meson.build\nindex 21b827a259..51598c048c 100644\n--- a/drivers/net/dpaa2/meson.build\n+++ b/drivers/net/dpaa2/meson.build\n@@ -14,6 +14,7 @@ sources = files(\n         'dpaa2_mux.c',\n         'dpaa2_ethdev.c',\n         'dpaa2_flow.c',\n+        'dpaa2_recycle.c',\n         'dpaa2_rxtx.c',\n         'dpaa2_sparser.c',\n         'dpaa2_ptp.c',\n",
    "prefixes": [
        "v2",
        "10/16"
    ]
}