get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 104098,
    "url": "http://patches.dpdk.org/api/patches/104098/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20211110074829.16654-3-apeksha.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": "<20211110074829.16654-3-apeksha.gupta@nxp.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20211110074829.16654-3-apeksha.gupta@nxp.com",
    "date": "2021-11-10T07:48:26",
    "name": "[v9,2/5] net/enetfec: add UIO support",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "02f5003e7c502831af1458fb26180a7d6ddbbcdf",
    "submitter": {
        "id": 1570,
        "url": "http://patches.dpdk.org/api/people/1570/?format=api",
        "name": "Apeksha Gupta",
        "email": "apeksha.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/20211110074829.16654-3-apeksha.gupta@nxp.com/mbox/",
    "series": [
        {
            "id": 20445,
            "url": "http://patches.dpdk.org/api/series/20445/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=20445",
            "date": "2021-11-10T07:48:24",
            "name": "drivers/net: add NXP ENETFEC driver",
            "version": 9,
            "mbox": "http://patches.dpdk.org/series/20445/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/104098/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/104098/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 78214A034F;\n\tWed, 10 Nov 2021 08:48:44 +0100 (CET)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 966DF41103;\n\tWed, 10 Nov 2021 08:48:38 +0100 (CET)",
            "from inva020.nxp.com (inva020.nxp.com [92.121.34.13])\n by mails.dpdk.org (Postfix) with ESMTP id 16B4C410E0\n for <dev@dpdk.org>; Wed, 10 Nov 2021 08:48:35 +0100 (CET)",
            "from inva020.nxp.com (localhost [127.0.0.1])\n by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id E44961A0E61;\n Wed, 10 Nov 2021 08:48:34 +0100 (CET)",
            "from aprdc01srsp001v.ap-rdc01.nxp.com\n (aprdc01srsp001v.ap-rdc01.nxp.com [165.114.16.16])\n by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 82D881A0E93;\n Wed, 10 Nov 2021 08:48:34 +0100 (CET)",
            "from lsv03186.swis.in-blr01.nxp.com (lsv03186.swis.in-blr01.nxp.com\n [92.120.146.182])\n by aprdc01srsp001v.ap-rdc01.nxp.com (Postfix) with ESMTP id 7A0BA183AD05;\n Wed, 10 Nov 2021 15:48:33 +0800 (+08)"
        ],
        "From": "Apeksha Gupta <apeksha.gupta@nxp.com>",
        "To": "ferruh.yigit@intel.com, david.marchand@redhat.com,\n andrew.rybchenko@oktetlabs.ru",
        "Cc": "dev@dpdk.org, sachin.saxena@nxp.com, hemant.agrawal@nxp.com,\n Apeksha Gupta <apeksha.gupta@nxp.com>",
        "Date": "Wed, 10 Nov 2021 13:18:26 +0530",
        "Message-Id": "<20211110074829.16654-3-apeksha.gupta@nxp.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20211110074829.16654-1-apeksha.gupta@nxp.com>",
        "References": "<20211109113432.11876-6-apeksha.gupta@nxp.com>\n <20211110074829.16654-1-apeksha.gupta@nxp.com>",
        "X-Virus-Scanned": "ClamAV using ClamSMTP",
        "Subject": "[dpdk-dev] [PATCH v9 2/5] net/enetfec: add UIO support",
        "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",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Implemented the fec-uio driver in kernel. enetfec PMD uses\nUIO interface to interact with \"fec-uio\" driver implemented in\nkernel for PHY initialisation and for mapping the allocated memory\nof register & BD from kernel to DPDK which gives access to\nnon-cacheable memory for BD.\n\nSigned-off-by: Sachin Saxena <sachin.saxena@nxp.com>\nSigned-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>\n---\n drivers/net/enetfec/enet_ethdev.c | 209 ++++++++++++++++++++++\n drivers/net/enetfec/enet_ethdev.h |  11 ++\n drivers/net/enetfec/enet_regs.h   | 106 +++++++++++\n drivers/net/enetfec/enet_uio.c    | 284 ++++++++++++++++++++++++++++++\n drivers/net/enetfec/enet_uio.h    |  64 +++++++\n drivers/net/enetfec/meson.build   |   3 +-\n 6 files changed, 676 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/enetfec/enet_regs.h\n create mode 100644 drivers/net/enetfec/enet_uio.c\n create mode 100644 drivers/net/enetfec/enet_uio.h",
    "diff": "diff --git a/drivers/net/enetfec/enet_ethdev.c b/drivers/net/enetfec/enet_ethdev.c\nindex 50390f4ea4..fe6b5e539f 100644\n--- a/drivers/net/enetfec/enet_ethdev.c\n+++ b/drivers/net/enetfec/enet_ethdev.c\n@@ -13,14 +13,192 @@\n #include <rte_bus_vdev.h>\n #include <rte_dev.h>\n #include <rte_ether.h>\n+#include <rte_io.h>\n #include \"enet_pmd_logs.h\"\n #include \"enet_ethdev.h\"\n+#include \"enet_regs.h\"\n+#include \"enet_uio.h\"\n \n #define ENETFEC_NAME_PMD                net_enetfec\n \n+/* FEC receive acceleration */\n+#define ENETFEC_RACC_IPDIS\t\tRTE_BIT32(1)\n+#define ENETFEC_RACC_PRODIS\t\tRTE_BIT32(2)\n+#define ENETFEC_RACC_SHIFT16\t\tRTE_BIT32(7)\n+#define ENETFEC_RACC_OPTIONS\t\t(ENETFEC_RACC_IPDIS | \\\n+\t\t\t\t\t\tENETFEC_RACC_PRODIS)\n+\n+#define ENETFEC_PAUSE_FLAG_AUTONEG\t0x1\n+#define ENETFEC_PAUSE_FLAG_ENABLE\t0x2\n+\n+/* Pause frame field and FIFO threshold */\n+#define ENETFEC_FCE\t\t\tRTE_BIT32(5)\n+#define ENETFEC_RSEM_V\t\t\t0x84\n+#define ENETFEC_RSFL_V\t\t\t16\n+#define ENETFEC_RAEM_V\t\t\t0x8\n+#define ENETFEC_RAFL_V\t\t\t0x8\n+#define ENETFEC_OPD_V\t\t\t0xFFF0\n+\n+#define NUM_OF_BD_QUEUES\t\t6\n+\n+/*\n+ * This function is called to start or restart the ENETFEC during a link\n+ * change, transmit timeout, or to reconfigure the ENETFEC. The network\n+ * packet processing for this device must be stopped before this call.\n+ */\n+static void\n+enetfec_restart(struct rte_eth_dev *dev)\n+{\n+\tstruct enetfec_private *fep = dev->data->dev_private;\n+\tuint32_t rcntl = OPT_FRAME_SIZE | 0x04;\n+\tuint32_t ecntl = ENETFEC_ETHEREN;\n+\tuint32_t val;\n+\n+\t/* Clear any outstanding interrupt. */\n+\twritel(0xffffffff, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_EIR);\n+\n+\t/* Enable MII mode */\n+\tif (fep->full_duplex == FULL_DUPLEX) {\n+\t\t/* FD enable */\n+\t\trte_write32(rte_cpu_to_le_32(0x04),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_TCR);\n+\t} else {\n+\t/* No Rcv on Xmit */\n+\t\trcntl |= 0x02;\n+\t\trte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_TCR);\n+\t}\n+\n+\tif (fep->quirks & QUIRK_RACC) {\n+\t\tval = rte_read32((uint8_t *)fep->hw_baseaddr_v + ENETFEC_RACC);\n+\t\t/* align IP header */\n+\t\tval |= ENETFEC_RACC_SHIFT16;\n+\t\tval &= ~ENETFEC_RACC_OPTIONS;\n+\t\trte_write32(rte_cpu_to_le_32(val),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_RACC);\n+\t\trte_write32(rte_cpu_to_le_32(PKT_MAX_BUF_SIZE),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_FRAME_TRL);\n+\t}\n+\n+\t/*\n+\t * The phy interface and speed need to get configured\n+\t * differently on enet-mac.\n+\t */\n+\tif (fep->quirks & QUIRK_HAS_ENETFEC_MAC) {\n+\t\t/* Enable flow control and length check */\n+\t\trcntl |= 0x40000000 | 0x00000020;\n+\n+\t\t/* RGMII, RMII or MII */\n+\t\trcntl |= RTE_BIT32(6);\n+\t\tecntl |= RTE_BIT32(5);\n+\t}\n+\n+\t/* enable pause frame*/\n+\tif ((fep->flag_pause & ENETFEC_PAUSE_FLAG_ENABLE) ||\n+\t\t((fep->flag_pause & ENETFEC_PAUSE_FLAG_AUTONEG)\n+\t\t/*&& ndev->phydev && ndev->phydev->pause*/)) {\n+\t\trcntl |= ENETFEC_FCE;\n+\n+\t\t/* set FIFO threshold parameter to reduce overrun */\n+\t\trte_write32(rte_cpu_to_le_32(ENETFEC_RSEM_V),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_SEM);\n+\t\trte_write32(rte_cpu_to_le_32(ENETFEC_RSFL_V),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_SFL);\n+\t\trte_write32(rte_cpu_to_le_32(ENETFEC_RAEM_V),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_AEM);\n+\t\trte_write32(rte_cpu_to_le_32(ENETFEC_RAFL_V),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_AFL);\n+\n+\t\t/* OPD */\n+\t\trte_write32(rte_cpu_to_le_32(ENETFEC_OPD_V),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_OPD);\n+\t} else {\n+\t\trcntl &= ~ENETFEC_FCE;\n+\t}\n+\n+\trte_write32(rte_cpu_to_le_32(rcntl),\n+\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_RCR);\n+\n+\trte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_IAUR);\n+\trte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_IALR);\n+\n+\tif (fep->quirks & QUIRK_HAS_ENETFEC_MAC) {\n+\t\t/* enable ENETFEC endian swap */\n+\t\tecntl |= (1 << 8);\n+\t\t/* enable ENETFEC store and forward mode */\n+\t\trte_write32(rte_cpu_to_le_32(1 << 8),\n+\t\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_TFWR);\n+\t}\n+\tif (fep->bufdesc_ex)\n+\t\tecntl |= (1 << 4);\n+\tif (fep->quirks & QUIRK_SUPPORT_DELAYED_CLKS &&\n+\t\tfep->rgmii_txc_delay)\n+\t\tecntl |= ENETFEC_TXC_DLY;\n+\tif (fep->quirks & QUIRK_SUPPORT_DELAYED_CLKS &&\n+\t\tfep->rgmii_rxc_delay)\n+\t\tecntl |= ENETFEC_RXC_DLY;\n+\t/* Enable the MIB statistic event counters */\n+\trte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_MIBC);\n+\n+\tecntl |= 0x70000000;\n+\tfep->enetfec_e_cntl = ecntl;\n+\t/* And last, enable the transmit and receive processing */\n+\trte_write32(rte_cpu_to_le_32(ecntl),\n+\t\t(uint8_t *)fep->hw_baseaddr_v + ENETFEC_ECR);\n+\trte_delay_us(10);\n+}\n+\n+static int\n+enetfec_eth_configure(struct rte_eth_dev *dev)\n+{\n+\tif (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC)\n+\t\tENETFEC_PMD_ERR(\"PMD does not support KEEP_CRC offload\");\n+\n+\treturn 0;\n+}\n+\n+static int\n+enetfec_eth_start(struct rte_eth_dev *dev)\n+{\n+\tenetfec_restart(dev);\n+\n+\treturn 0;\n+}\n+\n+/* ENETFEC disable function.\n+ * @param[in] base      ENETFEC base address\n+ */\n+static void\n+enetfec_disable(struct enetfec_private *fep)\n+{\n+\trte_write32(rte_read32((uint8_t *)fep->hw_baseaddr_v + ENETFEC_ECR)\n+\t\t    & ~(fep->enetfec_e_cntl),\n+\t\t    (uint8_t *)fep->hw_baseaddr_v + ENETFEC_ECR);\n+}\n+\n+static int\n+enetfec_eth_stop(struct rte_eth_dev *dev)\n+{\n+\tstruct enetfec_private *fep = dev->data->dev_private;\n+\n+\tdev->data->dev_started = 0;\n+\tenetfec_disable(fep);\n+\n+\treturn 0;\n+}\n+\n+static const struct eth_dev_ops enetfec_ops = {\n+\t.dev_configure          = enetfec_eth_configure,\n+\t.dev_start              = enetfec_eth_start,\n+\t.dev_stop               = enetfec_eth_stop\n+};\n+\n static int\n enetfec_eth_init(struct rte_eth_dev *dev)\n {\n+\tstruct enetfec_private *fep = dev->data->dev_private;\n+\n+\tfep->full_duplex = FULL_DUPLEX;\n+\tdev->dev_ops = &enetfec_ops;\n \trte_eth_dev_probing_finish(dev);\n \treturn 0;\n }\n@@ -32,6 +210,8 @@ pmd_enetfec_probe(struct rte_vdev_device *vdev)\n \tstruct enetfec_private *fep;\n \tconst char *name;\n \tint rc;\n+\tint i;\n+\tunsigned int bdsize;\n \n \tname = rte_vdev_device_name(vdev);\n \tif (name == NULL)\n@@ -45,6 +225,35 @@ pmd_enetfec_probe(struct rte_vdev_device *vdev)\n \t/* setup board info structure */\n \tfep = dev->data->dev_private;\n \tfep->dev = dev;\n+\n+\tfep->max_rx_queues = ENETFEC_MAX_Q;\n+\tfep->max_tx_queues = ENETFEC_MAX_Q;\n+\tfep->quirks = QUIRK_HAS_ENETFEC_MAC | QUIRK_GBIT\n+\t\t| QUIRK_RACC;\n+\n+\trc = enetfec_configure();\n+\tif (rc != 0)\n+\t\treturn -ENOMEM;\n+\trc = config_enetfec_uio(fep);\n+\tif (rc != 0)\n+\t\treturn -ENOMEM;\n+\n+\t/* Get the BD size for distributing among six queues */\n+\tbdsize = (fep->bd_size) / NUM_OF_BD_QUEUES;\n+\n+\tfor (i = 0; i < fep->max_tx_queues; i++) {\n+\t\tfep->dma_baseaddr_t[i] = fep->bd_addr_v;\n+\t\tfep->bd_addr_p_t[i] = fep->bd_addr_p;\n+\t\tfep->bd_addr_v = (uint8_t *)fep->bd_addr_v + bdsize;\n+\t\tfep->bd_addr_p = fep->bd_addr_p + bdsize;\n+\t}\n+\tfor (i = 0; i < fep->max_rx_queues; i++) {\n+\t\tfep->dma_baseaddr_r[i] = fep->bd_addr_v;\n+\t\tfep->bd_addr_p_r[i] = fep->bd_addr_p;\n+\t\tfep->bd_addr_v = (uint8_t *)fep->bd_addr_v + bdsize;\n+\t\tfep->bd_addr_p = fep->bd_addr_p + bdsize;\n+\t}\n+\n \trc = enetfec_eth_init(dev);\n \tif (rc)\n \t\tgoto failed_init;\ndiff --git a/drivers/net/enetfec/enet_ethdev.h b/drivers/net/enetfec/enet_ethdev.h\nindex e6b55e1ae6..0f0684ab11 100644\n--- a/drivers/net/enetfec/enet_ethdev.h\n+++ b/drivers/net/enetfec/enet_ethdev.h\n@@ -5,12 +5,23 @@\n #ifndef __ENETFEC_ETHDEV_H__\n #define __ENETFEC_ETHDEV_H__\n \n+#include <rte_ethdev.h>\n+\n+/* full duplex */\n+#define FULL_DUPLEX             0x00\n+\n+#define PKT_MAX_BUF_SIZE        1984\n+#define OPT_FRAME_SIZE         (PKT_MAX_BUF_SIZE << 16)\n+\n /*\n  * ENETFEC can support 1 rx and tx queue..\n  */\n \n #define ENETFEC_MAX_Q\t\t1\n \n+#define writel(v, p) ({*(volatile unsigned int *)(p) = (v); })\n+#define readl(p) rte_read32(p)\n+\n struct enetfec_private {\n \tstruct rte_eth_dev\t*dev;\n \tstruct rte_eth_stats\tstats;\ndiff --git a/drivers/net/enetfec/enet_regs.h b/drivers/net/enetfec/enet_regs.h\nnew file mode 100644\nindex 0000000000..5415ed77ea\n--- /dev/null\n+++ b/drivers/net/enetfec/enet_regs.h\n@@ -0,0 +1,106 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2020 NXP\n+ */\n+\n+#ifndef __ENETFEC_REGS_H\n+#define __ENETFEC_REGS_H\n+\n+/* Ethernet receive use control and status of buffer descriptor\n+ */\n+#define RX_BD_TR\t((ushort)0x0001) /* Truncated */\n+#define RX_BD_OV\t((ushort)0x0002) /* Over-run */\n+#define RX_BD_CR\t((ushort)0x0004) /* CRC or Frame error */\n+#define RX_BD_SH\t((ushort)0x0008) /* Reserved */\n+#define RX_BD_NO\t((ushort)0x0010) /* Rcvd non-octet aligned frame */\n+#define RX_BD_LG\t((ushort)0x0020) /* Rcvd frame length voilation */\n+#define RX_BD_FIRST\t((ushort)0x0400) /* Reserved */\n+#define RX_BD_LAST\t((ushort)0x0800) /* last buffer in the frame */\n+#define RX_BD_INT\t0x00800000\n+#define RX_BD_ICE\t0x00000020\n+#define RX_BD_PCR\t0x00000010\n+\n+/*\n+ * 0 The next BD in consecutive location\n+ * 1 The next BD in ENETFECn_RDSR.\n+ */\n+#define RX_BD_WRAP\t((ushort)0x2000)\n+#define RX_BD_EMPTY\t((ushort)0x8000) /* BD is empty */\n+#define RX_BD_STATS\t((ushort)0x013f) /* All buffer descriptor status bits */\n+\n+/* Ethernet transmit use control and status of buffer descriptor */\n+#define TX_BD_TC\t((ushort)0x0400) /* Transmit CRC */\n+#define TX_BD_LAST\t((ushort)0x0800) /* Last in frame */\n+#define TX_BD_READY\t((ushort)0x8000) /* Data is ready */\n+#define TX_BD_STATS\t((ushort)0x0fff) /* All buffer descriptor status bits */\n+#define TX_BD_WRAP\t((ushort)0x2000)\n+\n+/* Ethernet transmit use control and status of enhanced buffer descriptor */\n+#define TX_BD_IINS\t\t0x08000000\n+#define TX_BD_PINS\t\t0x10000000\n+\n+#define ENETFEC_RD_START(X)\t(((X) == 1) ? ENETFEC_RD_START_1 : \\\n+\t\t\t\t(((X) == 2) ? \\\n+\t\t\t\t   ENETFEC_RD_START_2 : ENETFEC_RD_START_0))\n+#define ENETFEC_TD_START(X)\t(((X) == 1) ? ENETFEC_TD_START_1 : \\\n+\t\t\t\t(((X) == 2) ? \\\n+\t\t\t\t   ENETFEC_TD_START_2 : ENETFEC_TD_START_0))\n+#define ENETFEC_MRB_SIZE(X)\t(((X) == 1) ? ENETFEC_MRB_SIZE_1 : \\\n+\t\t\t\t(((X) == 2) ? \\\n+\t\t\t\t   ENETFEC_MRB_SIZE_2 : ENETFEC_MRB_SIZE_0))\n+\n+#define ENETFEC_ETHEREN\t\t((uint)0x00000002)\n+#define ENETFEC_TXC_DLY\t\t((uint)0x00010000)\n+#define ENETFEC_RXC_DLY\t\t((uint)0x00020000)\n+\n+/* ENETFEC MAC is in controller */\n+#define QUIRK_HAS_ENETFEC_MAC\t(1 << 0)\n+/* GBIT supported in controller */\n+#define QUIRK_GBIT\t\t(1 << 3)\n+/* RACC register supported by controller */\n+#define QUIRK_RACC\t\t(1 << 12)\n+/* i.MX8 ENETFEC IP version added the feature to generate the delayed TXC or\n+ * RXC. For its implementation, ENETFEC uses synchronized clocks (250MHz) for\n+ * generating delay of 2ns.\n+ */\n+#define QUIRK_SUPPORT_DELAYED_CLKS\t(1 << 18)\n+\n+#define ENETFEC_EIR\t0x004 /* Interrupt event register */\n+#define ENETFEC_EIMR\t0x008 /* Interrupt mask register */\n+#define ENETFEC_RDAR_0\t0x010 /* Receive descriptor active register ring0 */\n+#define ENETFEC_TDAR_0\t0x014 /* Transmit descriptor active register ring0 */\n+#define ENETFEC_ECR\t0x024 /* Ethernet control register */\n+#define ENETFEC_MSCR\t0x044 /* MII speed control register */\n+#define ENETFEC_MIBC\t0x064 /* MIB control and status register */\n+#define ENETFEC_RCR\t0x084 /* Receive control register */\n+#define ENETFEC_TCR\t0x0c4 /* Transmit Control register */\n+#define ENETFEC_PALR\t0x0e4 /* MAC address low 32 bits */\n+#define ENETFEC_PAUR\t0x0e8 /* MAC address high 16 bits */\n+#define ENETFEC_OPD\t0x0ec /* Opcode/Pause duration register */\n+#define ENETFEC_IAUR\t0x118 /* hash table 32 bits high */\n+#define ENETFEC_IALR\t0x11c /* hash table 32 bits low */\n+#define ENETFEC_GAUR\t0x120 /* grp hash table 32 bits high */\n+#define ENETFEC_GALR\t0x124 /* grp hash table 32 bits low */\n+#define ENETFEC_TFWR\t0x144 /* transmit FIFO water_mark */\n+#define ENETFEC_RACC\t0x1c4 /* Receive Accelerator function configuration*/\n+#define ENETFEC_DMA1CFG\t0x1d8 /* DMA class based configuration ring1 */\n+#define ENETFEC_DMA2CFG\t0x1dc /* DMA class based Configuration ring2 */\n+#define ENETFEC_RDAR_1\t0x1e0 /* Rx descriptor active register ring1 */\n+#define ENETFEC_TDAR_1\t0x1e4 /* Tx descriptor active register ring1 */\n+#define ENETFEC_RDAR_2\t0x1e8 /* Rx descriptor active register ring2 */\n+#define ENETFEC_TDAR_2\t0x1ec /* Tx descriptor active register ring2 */\n+#define ENETFEC_RD_START_1\t0x160 /* Receive descriptor ring1 start reg */\n+#define ENETFEC_TD_START_1\t0x164 /* Transmit descriptor ring1 start reg */\n+#define ENETFEC_MRB_SIZE_1\t0x168 /* Max receive buffer size reg ring1 */\n+#define ENETFEC_RD_START_2\t0x16c /* Receive descriptor ring2 start reg */\n+#define ENETFEC_TD_START_2\t0x170 /* Transmit descriptor ring2 start reg */\n+#define ENETFEC_MRB_SIZE_2\t0x174 /* Max receive buffer size reg ring2 */\n+#define ENETFEC_RD_START_0\t0x180 /* Receive descriptor ring0 start reg */\n+#define ENETFEC_TD_START_0\t0x184 /* Transmit descriptor ring0 start reg */\n+#define ENETFEC_MRB_SIZE_0\t0x188 /* Max receive buffer size reg ring0*/\n+#define ENETFEC_R_FIFO_SFL\t0x190 /* Rx FIFO full threshold */\n+#define ENETFEC_R_FIFO_SEM\t0x194 /* Rx FIFO empty threshold */\n+#define ENETFEC_R_FIFO_AEM\t0x198 /* Rx FIFO almost empty threshold */\n+#define ENETFEC_R_FIFO_AFL\t0x19c /* Rx FIFO almost full threshold */\n+#define ENETFEC_FRAME_TRL\t0x1b0 /* Frame truncation length */\n+\n+#endif /*__ENETFEC_REGS_H */\ndiff --git a/drivers/net/enetfec/enet_uio.c b/drivers/net/enetfec/enet_uio.c\nnew file mode 100644\nindex 0000000000..99e9dccf5a\n--- /dev/null\n+++ b/drivers/net/enetfec/enet_uio.c\n@@ -0,0 +1,284 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2021 NXP\n+ */\n+\n+#include <stdbool.h>\n+#include <stdint.h>\n+#include <stdio.h>\n+#include <unistd.h>\n+#include <stdlib.h>\n+#include <dirent.h>\n+#include <string.h>\n+#include <sys/mman.h>\n+#include <errno.h>\n+#include <fcntl.h>\n+\n+#include <rte_common.h>\n+#include <rte_malloc.h>\n+#include \"enet_pmd_logs.h\"\n+#include \"enet_uio.h\"\n+\n+static struct uio_job enetfec_uio_job;\n+static int enetfec_count;\n+\n+/** @brief Checks if a file name contains a certain substring.\n+ * This function assumes a filename format of: [text][number].\n+ * @param [in]  filename    File name\n+ * @param [in]  match       String to match in file name\n+ *\n+ * @retval true if file name matches the criteria\n+ * @retval false if file name does not match the criteria\n+ */\n+static bool\n+file_name_match_extract(const char filename[], const char match[])\n+{\n+\tchar *substr = NULL;\n+\n+\tsubstr = strstr(filename, match);\n+\tif (substr == NULL)\n+\t\treturn false;\n+\n+\treturn true;\n+}\n+\n+/*\n+ * @brief Reads first line from a file.\n+ * Composes file name as: root/subdir/filename\n+ *\n+ * @param [in]  root     Root path\n+ * @param [in]  subdir   Subdirectory name\n+ * @param [in]  filename File name\n+ * @param [out] line     The first line read from file.\n+ *\n+ * @retval 0 for success\n+ * @retval other value for error\n+ */\n+static int\n+file_read_first_line(const char root[], const char subdir[],\n+\t\t\tconst char filename[], char *line)\n+{\n+\tchar absolute_file_name[FEC_UIO_MAX_ATTR_FILE_NAME];\n+\tint fd = 0, ret = 0;\n+\n+\t/*compose the file name: root/subdir/filename */\n+\tmemset(absolute_file_name, 0, sizeof(absolute_file_name));\n+\tsnprintf(absolute_file_name, FEC_UIO_MAX_ATTR_FILE_NAME,\n+\t\t\"%s/%s/%s\", root, subdir, filename);\n+\n+\tfd = open(absolute_file_name, O_RDONLY);\n+\tif (fd <= 0)\n+\t\tENETFEC_PMD_ERR(\"Error opening file %s\", absolute_file_name);\n+\n+\t/* read UIO device name from first line in file */\n+\tret = read(fd, line, FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH);\n+\tif (ret <= 0) {\n+\t\tENETFEC_PMD_ERR(\"Error reading file %s\", absolute_file_name);\n+\t\treturn ret;\n+\t}\n+\tclose(fd);\n+\n+\t/* NULL-ify string */\n+\tline[ret] = '\\0';\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * @brief Maps rx-tx bd range assigned for a bd ring.\n+ *\n+ * @param [in] uio_device_fd    UIO device file descriptor\n+ * @param [in] uio_device_id    UIO device id\n+ * @param [in] uio_map_id       UIO allows maximum 5 different mapping for\n+\t\t\t\teach device. Maps start with id 0.\n+ * @param [out] map_size        Map size.\n+ * @param [out] map_addr\tMap physical address\n+ *\n+ * @retval  NULL if failed to map registers\n+ * @retval  Virtual address for mapped register address range\n+ */\n+static void *\n+uio_map_mem(int uio_device_fd, int uio_device_id,\n+\t\tint uio_map_id, int *map_size, uint64_t *map_addr)\n+{\n+\tvoid *mapped_address = NULL;\n+\tunsigned int uio_map_size = 0;\n+\tunsigned int uio_map_p_addr = 0;\n+\tchar uio_sys_root[FEC_UIO_MAX_ATTR_FILE_NAME];\n+\tchar uio_sys_map_subdir[FEC_UIO_MAX_ATTR_FILE_NAME];\n+\tchar uio_map_size_str[FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH + 1];\n+\tchar uio_map_p_addr_str[32];\n+\tint ret = 0;\n+\n+\t/* compose the file name: root/subdir/filename */\n+\tmemset(uio_sys_root, 0, sizeof(uio_sys_root));\n+\tmemset(uio_sys_map_subdir, 0, sizeof(uio_sys_map_subdir));\n+\tmemset(uio_map_size_str, 0, sizeof(uio_map_size_str));\n+\tmemset(uio_map_p_addr_str, 0, sizeof(uio_map_p_addr_str));\n+\n+\t/* Compose string: /sys/class/uio/uioX */\n+\tsnprintf(uio_sys_root, sizeof(uio_sys_root), \"%s/%s%d\",\n+\t\t\tFEC_UIO_DEVICE_SYS_ATTR_PATH, \"uio\", uio_device_id);\n+\t/* Compose string: maps/mapY */\n+\tsnprintf(uio_sys_map_subdir, sizeof(uio_sys_map_subdir), \"%s%d\",\n+\t\t\tFEC_UIO_DEVICE_SYS_MAP_ATTR, uio_map_id);\n+\n+\t/* Read first (and only) line from file\n+\t * /sys/class/uio/uioX/maps/mapY/size\n+\t */\n+\tret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,\n+\t\t\t\t\"size\", uio_map_size_str);\n+\tif (ret < 0) {\n+\t\tENETFEC_PMD_ERR(\"file_read_first_line() failed\");\n+\t\treturn NULL;\n+\t}\n+\tret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,\n+\t\t\t\t\"addr\", uio_map_p_addr_str);\n+\tif (ret < 0) {\n+\t\tENETFEC_PMD_ERR(\"file_read_first_line() failed\");\n+\t\treturn NULL;\n+\t}\n+\t/* Read mapping size and physical address expressed in hexa(base 16) */\n+\tuio_map_size = strtol(uio_map_size_str, NULL, 16);\n+\tuio_map_p_addr = strtol(uio_map_p_addr_str, NULL, 16);\n+\n+\tif (uio_map_id == 0) {\n+\t\t/* Map the register address in user space when map_id is 0 */\n+\t\tmapped_address = mmap(0 /*dynamically choose virtual address */,\n+\t\t\t\tuio_map_size, PROT_READ | PROT_WRITE,\n+\t\t\t\tMAP_SHARED, uio_device_fd, 0);\n+\t} else {\n+\t\t/* Map the BD memory in user space */\n+\t\tmapped_address = mmap(NULL, uio_map_size,\n+\t\t\t\tPROT_READ | PROT_WRITE,\n+\t\t\t\tMAP_SHARED, uio_device_fd, (1 * MAP_PAGE_SIZE));\n+\t}\n+\n+\tif (mapped_address == MAP_FAILED) {\n+\t\tENETFEC_PMD_ERR(\"Failed to map! errno = %d uio job fd = %d,\"\n+\t\t\t\"uio device id = %d, uio map id = %d\", errno,\n+\t\t\tuio_device_fd, uio_device_id, uio_map_id);\n+\t\treturn NULL;\n+\t}\n+\n+\t/* Save the map size to use it later on for munmap-ing */\n+\t*map_size = uio_map_size;\n+\t*map_addr = uio_map_p_addr;\n+\tENETFEC_PMD_INFO(\"UIO dev[%d] mapped region [id =%d] size 0x%x at %p\",\n+\t\tuio_device_id, uio_map_id, uio_map_size, mapped_address);\n+\n+\treturn mapped_address;\n+}\n+\n+int\n+config_enetfec_uio(struct enetfec_private *fep)\n+{\n+\tchar uio_device_file_name[32];\n+\tstruct uio_job *uio_job = NULL;\n+\n+\t/* Mapping is done only one time */\n+\tif (enetfec_count > 0) {\n+\t\tENETFEC_PMD_INFO(\"Mapped!\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tuio_job = &enetfec_uio_job;\n+\n+\t/* Find UIO device created by ENETFEC-UIO kernel driver */\n+\tmemset(uio_device_file_name, 0, sizeof(uio_device_file_name));\n+\tsnprintf(uio_device_file_name, sizeof(uio_device_file_name), \"%s%d\",\n+\t\t\tFEC_UIO_DEVICE_FILE_NAME, uio_job->uio_minor_number);\n+\n+\t/* Open device file */\n+\tuio_job->uio_fd = open(uio_device_file_name, O_RDWR);\n+\tif (uio_job->uio_fd < 0) {\n+\t\tENETFEC_PMD_WARN(\"Unable to open ENETFEC_UIO file\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tENETFEC_PMD_INFO(\"US_UIO: Open device(%s) file with uio_fd = %d\",\n+\t\t\tuio_device_file_name, uio_job->uio_fd);\n+\n+\tfep->hw_baseaddr_v = uio_map_mem(uio_job->uio_fd,\n+\t\tuio_job->uio_minor_number, FEC_UIO_REG_MAP_ID,\n+\t\t&uio_job->map_size, &uio_job->map_addr);\n+\tif (fep->hw_baseaddr_v == NULL)\n+\t\treturn -ENOMEM;\n+\tfep->hw_baseaddr_p = uio_job->map_addr;\n+\tfep->reg_size = uio_job->map_size;\n+\n+\tfep->bd_addr_v = uio_map_mem(uio_job->uio_fd,\n+\t\tuio_job->uio_minor_number, FEC_UIO_BD_MAP_ID,\n+\t\t&uio_job->map_size, &uio_job->map_addr);\n+\tif (fep->hw_baseaddr_v == NULL)\n+\t\treturn -ENOMEM;\n+\tfep->bd_addr_p = uio_job->map_addr;\n+\tfep->bd_size = uio_job->map_size;\n+\n+\tenetfec_count++;\n+\n+\treturn 0;\n+}\n+\n+int\n+enetfec_configure(void)\n+{\n+\tchar uio_name[32];\n+\tint uio_minor_number = -1;\n+\tint ret;\n+\tDIR *d = NULL;\n+\tstruct dirent *dir;\n+\n+\td = opendir(FEC_UIO_DEVICE_SYS_ATTR_PATH);\n+\tif (d == NULL) {\n+\t\tENETFEC_PMD_ERR(\"\\nError opening directory '%s': %s\\n\",\n+\t\t\tFEC_UIO_DEVICE_SYS_ATTR_PATH, strerror(errno));\n+\t\treturn -1;\n+\t}\n+\n+\t/* Iterate through all subdirs */\n+\twhile ((dir = readdir(d)) != NULL) {\n+\t\tif (!strncmp(dir->d_name, \".\", 1) ||\n+\t\t\t\t!strncmp(dir->d_name, \"..\", 2))\n+\t\t\tcontinue;\n+\n+\t\tif (file_name_match_extract(dir->d_name, \"uio\")) {\n+\t\t\t/*\n+\t\t\t * As substring <uio> was found in <d_name>\n+\t\t\t * read number following <uio> substring in <d_name>\n+\t\t\t */\n+\t\t\tret = sscanf(dir->d_name + strlen(\"uio\"), \"%d\",\n+\t\t\t\t\t\t\t&uio_minor_number);\n+\t\t\tif (ret < 0)\n+\t\t\t\tENETFEC_PMD_ERR(\"Error: not find minor number\\n\");\n+\t\t\t/*\n+\t\t\t * Open file uioX/name and read first line which\n+\t\t\t * contains the name for the device. Based on the\n+\t\t\t * name check if this UIO device is for enetfec.\n+\t\t\t */\n+\t\t\tmemset(uio_name, 0, sizeof(uio_name));\n+\t\t\tret = file_read_first_line(FEC_UIO_DEVICE_SYS_ATTR_PATH,\n+\t\t\t\t\tdir->d_name, \"name\", uio_name);\n+\t\t\tif (ret != 0) {\n+\t\t\t\tENETFEC_PMD_INFO(\"file_read_first_line failed\\n\");\n+\t\t\t\tclosedir(d);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n+\t\t\tif (file_name_match_extract(uio_name,\n+\t\t\t\t\t\tFEC_UIO_DEVICE_NAME)) {\n+\t\t\t\tenetfec_uio_job.uio_minor_number =\n+\t\t\t\t\t\t\tuio_minor_number;\n+\t\t\t\tENETFEC_PMD_INFO(\"enetfec device uio name: %s\",\n+\t\t\t\t\t\t uio_name);\n+\t\t\t}\n+\t\t}\n+\t}\n+\tclosedir(d);\n+\treturn 0;\n+}\n+\n+void\n+enetfec_cleanup(struct enetfec_private *fep)\n+{\n+\tmunmap(fep->hw_baseaddr_v, fep->cbus_size);\n+}\ndiff --git a/drivers/net/enetfec/enet_uio.h b/drivers/net/enetfec/enet_uio.h\nnew file mode 100644\nindex 0000000000..fec8ba6f95\n--- /dev/null\n+++ b/drivers/net/enetfec/enet_uio.h\n@@ -0,0 +1,64 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2021 NXP\n+ */\n+\n+#include \"enet_ethdev.h\"\n+\n+/* Prefix path to sysfs directory where UIO device attributes are exported.\n+ * Path for UIO device X is /sys/class/uio/uioX\n+ */\n+#define FEC_UIO_DEVICE_SYS_ATTR_PATH\t\"/sys/class/uio\"\n+\n+/* Subfolder in sysfs where mapping attributes are exported\n+ * for each UIO device. Path for mapping Y for device X is:\n+ * /sys/class/uio/uioX/maps/mapY\n+ */\n+#define FEC_UIO_DEVICE_SYS_MAP_ATTR\t\"maps/map\"\n+\n+/* Name of UIO device file prefix. Each UIO device will have a device file\n+ * /dev/uioX, where X is the minor device number.\n+ */\n+#define FEC_UIO_DEVICE_FILE_NAME\t\"/dev/uio\"\n+/*\n+ * Name of UIO device. User space FEC will have a corresponding\n+ * UIO device.\n+ * Maximum length is #FEC_UIO_MAX_DEVICE_NAME_LENGTH.\n+ *\n+ * @note  Must be kept in sync with FEC kernel driver\n+ * define #FEC_UIO_DEVICE_NAME !\n+ */\n+#define FEC_UIO_DEVICE_NAME     \"imx-fec-uio\"\n+\n+/* Maximum length for the name of an UIO device file.\n+ * Device file name format is: /dev/uioX.\n+ */\n+#define FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH\t30\n+\n+/* Maximum length for the name of an attribute file for an UIO device.\n+ * Attribute files are exported in sysfs and have the name formatted as:\n+ * /sys/class/uio/uioX/<attribute_file_name>\n+ */\n+#define FEC_UIO_MAX_ATTR_FILE_NAME\t100\n+\n+/* The id for the mapping used to export ENETFEC registers and BD memory to\n+ * user space through UIO device.\n+ */\n+#define FEC_UIO_REG_MAP_ID\t\t0\n+#define FEC_UIO_BD_MAP_ID\t\t1\n+\n+#define MAP_PAGE_SIZE\t\t\t4096\n+\n+struct uio_job {\n+\tuint32_t fec_id;\n+\tint uio_fd;\n+\tvoid *bd_start_addr;\n+\tvoid *register_base_addr;\n+\tint map_size;\n+\tuint64_t map_addr;\n+\tint uio_minor_number;\n+};\n+\n+int enetfec_configure(void);\n+int config_enetfec_uio(struct enetfec_private *fep);\n+void enetfec_uio_init(void);\n+void enetfec_cleanup(struct enetfec_private *fep);\ndiff --git a/drivers/net/enetfec/meson.build b/drivers/net/enetfec/meson.build\nindex 6d6c64c94b..57f316b8a5 100644\n--- a/drivers/net/enetfec/meson.build\n+++ b/drivers/net/enetfec/meson.build\n@@ -6,4 +6,5 @@ if not is_linux\n \treason = 'only supported on linux'\n endif\n \n-sources = files('enet_ethdev.c')\n+sources = files('enet_ethdev.c',\n+\t\t'enet_uio.c')\n",
    "prefixes": [
        "v9",
        "2/5"
    ]
}