All of lore.kernel.org
 help / color / mirror / Atom feed
From: Apeksha Gupta <apeksha.gupta@nxp.com>
To: david.marchand@redhat.com, andrew.rybchenko@oktetlabs.ru,
	ferruh.yigit@intel.com
Cc: dev@dpdk.org, sachin.saxena@nxp.com, hemant.agrawal@nxp.com,
	Apeksha Gupta <apeksha.gupta@nxp.com>
Subject: [dpdk-dev] [PATCH v6 2/5] net/enetfec: add UIO support
Date: Thu, 21 Oct 2021 10:16:57 +0530	[thread overview]
Message-ID: <20211021044700.12370-3-apeksha.gupta@nxp.com> (raw)
In-Reply-To: <20211021044700.12370-1-apeksha.gupta@nxp.com>

Implemented the fec-uio driver in kernel. enetfec PMD uses
UIO interface to interact with "fec-uio" driver implemented in
kernel for PHY initialisation and for mapping the allocated memory
of register & BD from kernel to DPDK which gives access to
non-cacheable memory for BD.

Signed-off-by: Sachin Saxena <sachin.saxena@nxp.com>
Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
---
 drivers/net/enetfec/enet_ethdev.c | 236 +++++++++++++++++++++++++
 drivers/net/enetfec/enet_ethdev.h |   2 +
 drivers/net/enetfec/enet_regs.h   | 106 ++++++++++++
 drivers/net/enetfec/enet_uio.c    | 278 ++++++++++++++++++++++++++++++
 drivers/net/enetfec/enet_uio.h    |  64 +++++++
 5 files changed, 686 insertions(+)
 create mode 100644 drivers/net/enetfec/enet_regs.h
 create mode 100644 drivers/net/enetfec/enet_uio.c
 create mode 100644 drivers/net/enetfec/enet_uio.h

diff --git a/drivers/net/enetfec/enet_ethdev.c b/drivers/net/enetfec/enet_ethdev.c
index 8a74fb5bf2..406a8db7f3 100644
--- a/drivers/net/enetfec/enet_ethdev.c
+++ b/drivers/net/enetfec/enet_ethdev.c
@@ -13,16 +13,221 @@
 #include <rte_bus_vdev.h>
 #include <rte_dev.h>
 #include <rte_ether.h>
+#include <rte_io.h>
 #include "enet_ethdev.h"
 #include "enet_pmd_logs.h"
+#include "enet_regs.h"
+#include "enet_uio.h"
 
 #define ENETFEC_NAME_PMD                net_enetfec
 #define ENETFEC_CDEV_INVALID_FD         -1
+#define BIT(nr)				(1u << (nr))
+
+/* FEC receive acceleration */
+#define ENETFEC_RACC_IPDIS		BIT(1)
+#define ENETFEC_RACC_PRODIS		BIT(2)
+#define ENETFEC_RACC_SHIFT16		BIT(7)
+#define ENETFEC_RACC_OPTIONS		(ENETFEC_RACC_IPDIS | \
+						ENETFEC_RACC_PRODIS)
+
+#define ENETFEC_PAUSE_FLAG_AUTONEG	0x1
+#define ENETFEC_PAUSE_FLAG_ENABLE	0x2
+
+/* Pause frame field and FIFO threshold */
+#define ENETFEC_FCE			BIT(5)
+#define ENETFEC_RSEM_V			0x84
+#define ENETFEC_RSFL_V			16
+#define ENETFEC_RAEM_V			0x8
+#define ENETFEC_RAFL_V			0x8
+#define ENETFEC_OPD_V			0xFFF0
+
+#define NUM_OF_QUEUES			6
+
+uint32_t e_cntl;
+
+/*
+ * This function is called to start or restart the ENETFEC during a link
+ * change, transmit timeout, or to reconfigure the ENETFEC. The network
+ * packet processing for this device must be stopped before this call.
+ */
+static void
+enetfec_restart(struct rte_eth_dev *dev)
+{
+	struct enetfec_private *fep = dev->data->dev_private;
+	uint32_t temp_mac[2];
+	uint32_t rcntl = OPT_FRAME_SIZE | 0x04;
+	uint32_t ecntl = ENETFEC_ETHEREN;
+
+	/* default mac address */
+	struct rte_ether_addr addr = {
+		.addr_bytes = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6} };
+	uint32_t val;
+
+	/*
+	 * enet-mac reset will reset mac address registers too,
+	 * so need to reconfigure it.
+	 */
+	memcpy(&temp_mac, addr.addr_bytes, ETH_ALEN);
+	rte_write32(rte_cpu_to_be_32(temp_mac[0]),
+		(uint8_t *)fep->hw_baseaddr_v + ENETFEC_PALR);
+	rte_write32(rte_cpu_to_be_32(temp_mac[1]),
+		(uint8_t *)fep->hw_baseaddr_v + ENETFEC_PAUR);
+
+	/* Clear any outstanding interrupt. */
+	writel(0xffffffff, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_EIR);
+
+	/* Enable MII mode */
+	if (fep->full_duplex == FULL_DUPLEX) {
+		/* FD enable */
+		rte_write32(rte_cpu_to_le_32(0x04),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_TCR);
+	} else {
+	/* No Rcv on Xmit */
+		rcntl |= 0x02;
+		rte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_TCR);
+	}
+
+	if (fep->quirks & QUIRK_RACC) {
+		val = rte_read32((uint8_t *)fep->hw_baseaddr_v + ENETFEC_RACC);
+		/* align IP header */
+		val |= ENETFEC_RACC_SHIFT16;
+		val &= ~ENETFEC_RACC_OPTIONS;
+		rte_write32(rte_cpu_to_le_32(val),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_RACC);
+		rte_write32(rte_cpu_to_le_32(PKT_MAX_BUF_SIZE),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_FRAME_TRL);
+	}
+
+	/*
+	 * The phy interface and speed need to get configured
+	 * differently on enet-mac.
+	 */
+	if (fep->quirks & QUIRK_HAS_ENETFEC_MAC) {
+		/* Enable flow control and length check */
+		rcntl |= 0x40000000 | 0x00000020;
+
+		/* RGMII, RMII or MII */
+		rcntl |= BIT(6);
+		ecntl |= BIT(5);
+	}
+
+	/* enable pause frame*/
+	if ((fep->flag_pause & ENETFEC_PAUSE_FLAG_ENABLE) ||
+		((fep->flag_pause & ENETFEC_PAUSE_FLAG_AUTONEG)
+		/*&& ndev->phydev && ndev->phydev->pause*/)) {
+		rcntl |= ENETFEC_FCE;
+
+		/* set FIFO threshold parameter to reduce overrun */
+		rte_write32(rte_cpu_to_le_32(ENETFEC_RSEM_V),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_SEM);
+		rte_write32(rte_cpu_to_le_32(ENETFEC_RSFL_V),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_SFL);
+		rte_write32(rte_cpu_to_le_32(ENETFEC_RAEM_V),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_AEM);
+		rte_write32(rte_cpu_to_le_32(ENETFEC_RAFL_V),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_R_FIFO_AFL);
+
+		/* OPD */
+		rte_write32(rte_cpu_to_le_32(ENETFEC_OPD_V),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_OPD);
+	} else {
+		rcntl &= ~ENETFEC_FCE;
+	}
+
+	rte_write32(rte_cpu_to_le_32(rcntl),
+		(uint8_t *)fep->hw_baseaddr_v + ENETFEC_RCR);
+
+	rte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_IAUR);
+	rte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_IALR);
+
+	if (fep->quirks & QUIRK_HAS_ENETFEC_MAC) {
+		/* enable ENETFEC endian swap */
+		ecntl |= (1 << 8);
+		/* enable ENETFEC store and forward mode */
+		rte_write32(rte_cpu_to_le_32(1 << 8),
+			(uint8_t *)fep->hw_baseaddr_v + ENETFEC_TFWR);
+	}
+	if (fep->bufdesc_ex)
+		ecntl |= (1 << 4);
+	if (fep->quirks & QUIRK_SUPPORT_DELAYED_CLKS &&
+		fep->rgmii_txc_delay)
+		ecntl |= ENETFEC_TXC_DLY;
+	if (fep->quirks & QUIRK_SUPPORT_DELAYED_CLKS &&
+		fep->rgmii_rxc_delay)
+		ecntl |= ENETFEC_RXC_DLY;
+	/* Enable the MIB statistic event counters */
+	rte_write32(0, (uint8_t *)fep->hw_baseaddr_v + ENETFEC_MIBC);
+
+	ecntl |= 0x70000000;
+	e_cntl = ecntl;
+	/* And last, enable the transmit and receive processing */
+	rte_write32(rte_cpu_to_le_32(ecntl),
+		(uint8_t *)fep->hw_baseaddr_v + ENETFEC_ECR);
+	rte_delay_us(10);
+}
+
+static int
+enetfec_eth_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC)
+		ENETFEC_PMD_ERR("PMD does not support KEEP_CRC offload");
+
+	return 0;
+}
+
+static int
+enetfec_eth_start(struct rte_eth_dev *dev)
+{
+	enetfec_restart(dev);
+
+	return 0;
+}
+/* ENETFEC enable function.
+ * @param[in] base      ENETFEC base address
+ */
+void
+enetfec_enable(void *base)
+{
+	rte_write32(rte_read32((uint8_t *)base + ENETFEC_ECR) | e_cntl,
+					(uint8_t *)base + ENETFEC_ECR);
+}
+
+/* ENETFEC disable function.
+ * @param[in] base      ENETFEC base address
+ */
+void
+enetfec_disable(void *base)
+{
+	rte_write32(rte_read32((uint8_t *)base + ENETFEC_ECR) & ~e_cntl,
+					(uint8_t *)base + ENETFEC_ECR);
+}
+
+static int
+enetfec_eth_stop(__rte_unused struct rte_eth_dev *dev)
+{
+	struct enetfec_private *fep = dev->data->dev_private;
+
+	dev->data->dev_started = 0;
+	enetfec_disable(fep->hw_baseaddr_v);
+
+	return 0;
+}
+
+static const struct eth_dev_ops enetfec_ops = {
+	.dev_configure          = enetfec_eth_configure,
+	.dev_start              = enetfec_eth_start,
+	.dev_stop               = enetfec_eth_stop
+};
 
 static int
 enetfec_eth_init(struct rte_eth_dev *dev)
 {
+	struct enetfec_private *fep = dev->data->dev_private;
+
+	fep->full_duplex = FULL_DUPLEX;
+	dev->dev_ops = &enetfec_ops;
 	rte_eth_dev_probing_finish(dev);
+
 	return 0;
 }
 
@@ -33,6 +238,8 @@ pmd_enetfec_probe(struct rte_vdev_device *vdev)
 	struct enetfec_private *fep;
 	const char *name;
 	int rc;
+	int i;
+	unsigned int bdsize;
 
 	name = rte_vdev_device_name(vdev);
 	if (name == NULL)
@@ -46,6 +253,35 @@ pmd_enetfec_probe(struct rte_vdev_device *vdev)
 	/* setup board info structure */
 	fep = dev->data->dev_private;
 	fep->dev = dev;
+
+	fep->max_rx_queues = ENETFEC_MAX_Q;
+	fep->max_tx_queues = ENETFEC_MAX_Q;
+	fep->quirks = QUIRK_HAS_ENETFEC_MAC | QUIRK_GBIT
+		| QUIRK_RACC;
+
+	rc = enetfec_configure();
+	if (rc != 0)
+		return -ENOMEM;
+	rc = config_enetfec_uio(fep);
+	if (rc != 0)
+		return -ENOMEM;
+
+	/* Get the BD size for distributing among six queues */
+	bdsize = (fep->bd_size) / NUM_OF_QUEUES;
+
+	for (i = 0; i < fep->max_tx_queues; i++) {
+		fep->dma_baseaddr_t[i] = fep->bd_addr_v;
+		fep->bd_addr_p_t[i] = fep->bd_addr_p;
+		fep->bd_addr_v = (uint8_t *)fep->bd_addr_v + bdsize;
+		fep->bd_addr_p = fep->bd_addr_p + bdsize;
+	}
+	for (i = 0; i < fep->max_rx_queues; i++) {
+		fep->dma_baseaddr_r[i] = fep->bd_addr_v;
+		fep->bd_addr_p_r[i] = fep->bd_addr_p;
+		fep->bd_addr_v = (uint8_t *)fep->bd_addr_v + bdsize;
+		fep->bd_addr_p = fep->bd_addr_p + bdsize;
+	}
+
 	rc = enetfec_eth_init(dev);
 	if (rc)
 		goto failed_init;
diff --git a/drivers/net/enetfec/enet_ethdev.h b/drivers/net/enetfec/enet_ethdev.h
index c674dfc782..312e0424e5 100644
--- a/drivers/net/enetfec/enet_ethdev.h
+++ b/drivers/net/enetfec/enet_ethdev.h
@@ -175,5 +175,7 @@ struct bufdesc *enet_get_nextdesc(struct bufdesc *bdp,
 		struct bufdesc_prop *bd);
 int enet_new_rxbdp(struct enetfec_private *fep, struct bufdesc *bdp,
 		struct rte_mbuf *mbuf);
+void enetfec_enable(void *base);
+void enetfec_disable(void *base);
 
 #endif /*__ENETFEC_ETHDEV_H__*/
diff --git a/drivers/net/enetfec/enet_regs.h b/drivers/net/enetfec/enet_regs.h
new file mode 100644
index 0000000000..5415ed77ea
--- /dev/null
+++ b/drivers/net/enetfec/enet_regs.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2020 NXP
+ */
+
+#ifndef __ENETFEC_REGS_H
+#define __ENETFEC_REGS_H
+
+/* Ethernet receive use control and status of buffer descriptor
+ */
+#define RX_BD_TR	((ushort)0x0001) /* Truncated */
+#define RX_BD_OV	((ushort)0x0002) /* Over-run */
+#define RX_BD_CR	((ushort)0x0004) /* CRC or Frame error */
+#define RX_BD_SH	((ushort)0x0008) /* Reserved */
+#define RX_BD_NO	((ushort)0x0010) /* Rcvd non-octet aligned frame */
+#define RX_BD_LG	((ushort)0x0020) /* Rcvd frame length voilation */
+#define RX_BD_FIRST	((ushort)0x0400) /* Reserved */
+#define RX_BD_LAST	((ushort)0x0800) /* last buffer in the frame */
+#define RX_BD_INT	0x00800000
+#define RX_BD_ICE	0x00000020
+#define RX_BD_PCR	0x00000010
+
+/*
+ * 0 The next BD in consecutive location
+ * 1 The next BD in ENETFECn_RDSR.
+ */
+#define RX_BD_WRAP	((ushort)0x2000)
+#define RX_BD_EMPTY	((ushort)0x8000) /* BD is empty */
+#define RX_BD_STATS	((ushort)0x013f) /* All buffer descriptor status bits */
+
+/* Ethernet transmit use control and status of buffer descriptor */
+#define TX_BD_TC	((ushort)0x0400) /* Transmit CRC */
+#define TX_BD_LAST	((ushort)0x0800) /* Last in frame */
+#define TX_BD_READY	((ushort)0x8000) /* Data is ready */
+#define TX_BD_STATS	((ushort)0x0fff) /* All buffer descriptor status bits */
+#define TX_BD_WRAP	((ushort)0x2000)
+
+/* Ethernet transmit use control and status of enhanced buffer descriptor */
+#define TX_BD_IINS		0x08000000
+#define TX_BD_PINS		0x10000000
+
+#define ENETFEC_RD_START(X)	(((X) == 1) ? ENETFEC_RD_START_1 : \
+				(((X) == 2) ? \
+				   ENETFEC_RD_START_2 : ENETFEC_RD_START_0))
+#define ENETFEC_TD_START(X)	(((X) == 1) ? ENETFEC_TD_START_1 : \
+				(((X) == 2) ? \
+				   ENETFEC_TD_START_2 : ENETFEC_TD_START_0))
+#define ENETFEC_MRB_SIZE(X)	(((X) == 1) ? ENETFEC_MRB_SIZE_1 : \
+				(((X) == 2) ? \
+				   ENETFEC_MRB_SIZE_2 : ENETFEC_MRB_SIZE_0))
+
+#define ENETFEC_ETHEREN		((uint)0x00000002)
+#define ENETFEC_TXC_DLY		((uint)0x00010000)
+#define ENETFEC_RXC_DLY		((uint)0x00020000)
+
+/* ENETFEC MAC is in controller */
+#define QUIRK_HAS_ENETFEC_MAC	(1 << 0)
+/* GBIT supported in controller */
+#define QUIRK_GBIT		(1 << 3)
+/* RACC register supported by controller */
+#define QUIRK_RACC		(1 << 12)
+/* i.MX8 ENETFEC IP version added the feature to generate the delayed TXC or
+ * RXC. For its implementation, ENETFEC uses synchronized clocks (250MHz) for
+ * generating delay of 2ns.
+ */
+#define QUIRK_SUPPORT_DELAYED_CLKS	(1 << 18)
+
+#define ENETFEC_EIR	0x004 /* Interrupt event register */
+#define ENETFEC_EIMR	0x008 /* Interrupt mask register */
+#define ENETFEC_RDAR_0	0x010 /* Receive descriptor active register ring0 */
+#define ENETFEC_TDAR_0	0x014 /* Transmit descriptor active register ring0 */
+#define ENETFEC_ECR	0x024 /* Ethernet control register */
+#define ENETFEC_MSCR	0x044 /* MII speed control register */
+#define ENETFEC_MIBC	0x064 /* MIB control and status register */
+#define ENETFEC_RCR	0x084 /* Receive control register */
+#define ENETFEC_TCR	0x0c4 /* Transmit Control register */
+#define ENETFEC_PALR	0x0e4 /* MAC address low 32 bits */
+#define ENETFEC_PAUR	0x0e8 /* MAC address high 16 bits */
+#define ENETFEC_OPD	0x0ec /* Opcode/Pause duration register */
+#define ENETFEC_IAUR	0x118 /* hash table 32 bits high */
+#define ENETFEC_IALR	0x11c /* hash table 32 bits low */
+#define ENETFEC_GAUR	0x120 /* grp hash table 32 bits high */
+#define ENETFEC_GALR	0x124 /* grp hash table 32 bits low */
+#define ENETFEC_TFWR	0x144 /* transmit FIFO water_mark */
+#define ENETFEC_RACC	0x1c4 /* Receive Accelerator function configuration*/
+#define ENETFEC_DMA1CFG	0x1d8 /* DMA class based configuration ring1 */
+#define ENETFEC_DMA2CFG	0x1dc /* DMA class based Configuration ring2 */
+#define ENETFEC_RDAR_1	0x1e0 /* Rx descriptor active register ring1 */
+#define ENETFEC_TDAR_1	0x1e4 /* Tx descriptor active register ring1 */
+#define ENETFEC_RDAR_2	0x1e8 /* Rx descriptor active register ring2 */
+#define ENETFEC_TDAR_2	0x1ec /* Tx descriptor active register ring2 */
+#define ENETFEC_RD_START_1	0x160 /* Receive descriptor ring1 start reg */
+#define ENETFEC_TD_START_1	0x164 /* Transmit descriptor ring1 start reg */
+#define ENETFEC_MRB_SIZE_1	0x168 /* Max receive buffer size reg ring1 */
+#define ENETFEC_RD_START_2	0x16c /* Receive descriptor ring2 start reg */
+#define ENETFEC_TD_START_2	0x170 /* Transmit descriptor ring2 start reg */
+#define ENETFEC_MRB_SIZE_2	0x174 /* Max receive buffer size reg ring2 */
+#define ENETFEC_RD_START_0	0x180 /* Receive descriptor ring0 start reg */
+#define ENETFEC_TD_START_0	0x184 /* Transmit descriptor ring0 start reg */
+#define ENETFEC_MRB_SIZE_0	0x188 /* Max receive buffer size reg ring0*/
+#define ENETFEC_R_FIFO_SFL	0x190 /* Rx FIFO full threshold */
+#define ENETFEC_R_FIFO_SEM	0x194 /* Rx FIFO empty threshold */
+#define ENETFEC_R_FIFO_AEM	0x198 /* Rx FIFO almost empty threshold */
+#define ENETFEC_R_FIFO_AFL	0x19c /* Rx FIFO almost full threshold */
+#define ENETFEC_FRAME_TRL	0x1b0 /* Frame truncation length */
+
+#endif /*__ENETFEC_REGS_H */
diff --git a/drivers/net/enetfec/enet_uio.c b/drivers/net/enetfec/enet_uio.c
new file mode 100644
index 0000000000..c939b4736b
--- /dev/null
+++ b/drivers/net/enetfec/enet_uio.c
@@ -0,0 +1,278 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 NXP
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include "enet_pmd_logs.h"
+#include "enet_uio.h"
+
+static struct uio_job enetfec_uio_job;
+static int enetfec_count;
+
+/** @brief Checks if a file name contains a certain substring.
+ * This function assumes a filename format of: [text][number].
+ * @param [in]  filename    File name
+ * @param [in]  match       String to match in file name
+ *
+ * @retval true if file name matches the criteria
+ * @retval false if file name does not match the criteria
+ */
+static bool
+file_name_match_extract(const char filename[], const char match[])
+{
+	char *substr = NULL;
+
+	substr = strstr(filename, match);
+	if (substr == NULL)
+		return false;
+
+	return true;
+}
+
+/*
+ * @brief Reads first line from a file.
+ * Composes file name as: root/subdir/filename
+ *
+ * @param [in]  root     Root path
+ * @param [in]  subdir   Subdirectory name
+ * @param [in]  filename File name
+ * @param [out] line     The first line read from file.
+ *
+ * @retval 0 for success
+ * @retval other value for error
+ */
+static int
+file_read_first_line(const char root[], const char subdir[],
+			const char filename[], char *line)
+{
+	char absolute_file_name[FEC_UIO_MAX_ATTR_FILE_NAME];
+	int fd = 0, ret = 0;
+
+	/*compose the file name: root/subdir/filename */
+	memset(absolute_file_name, 0, sizeof(absolute_file_name));
+	snprintf(absolute_file_name, FEC_UIO_MAX_ATTR_FILE_NAME,
+		"%s/%s/%s", root, subdir, filename);
+
+	fd = open(absolute_file_name, O_RDONLY);
+	if (fd <= 0)
+		ENETFEC_PMD_ERR("Error opening file %s", absolute_file_name);
+
+	/* read UIO device name from first line in file */
+	ret = read(fd, line, FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH);
+	if (ret <= 0) {
+		ENETFEC_PMD_ERR("Error reading file %s", absolute_file_name);
+		return ret;
+	}
+	close(fd);
+
+	/* NULL-ify string */
+	line[ret] = '\0';
+
+	return 0;
+}
+
+/*
+ * @brief Maps rx-tx bd range assigned for a bd ring.
+ *
+ * @param [in] uio_device_fd    UIO device file descriptor
+ * @param [in] uio_device_id    UIO device id
+ * @param [in] uio_map_id       UIO allows maximum 5 different mapping for
+				each device. Maps start with id 0.
+ * @param [out] map_size        Map size.
+ * @param [out] map_addr	Map physical address
+ *
+ * @retval  NULL if failed to map registers
+ * @retval  Virtual address for mapped register address range
+ */
+static void *
+uio_map_mem(int uio_device_fd, int uio_device_id,
+		int uio_map_id, int *map_size, uint64_t *map_addr)
+{
+	void *mapped_address = NULL;
+	unsigned int uio_map_size = 0;
+	unsigned int uio_map_p_addr = 0;
+	char uio_sys_root[FEC_UIO_MAX_ATTR_FILE_NAME];
+	char uio_sys_map_subdir[FEC_UIO_MAX_ATTR_FILE_NAME];
+	char uio_map_size_str[FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH + 1];
+	char uio_map_p_addr_str[32];
+	int ret = 0;
+
+	/* compose the file name: root/subdir/filename */
+	memset(uio_sys_root, 0, sizeof(uio_sys_root));
+	memset(uio_sys_map_subdir, 0, sizeof(uio_sys_map_subdir));
+	memset(uio_map_size_str, 0, sizeof(uio_map_size_str));
+	memset(uio_map_p_addr_str, 0, sizeof(uio_map_p_addr_str));
+
+	/* Compose string: /sys/class/uio/uioX */
+	snprintf(uio_sys_root, sizeof(uio_sys_root), "%s/%s%d",
+			FEC_UIO_DEVICE_SYS_ATTR_PATH, "uio", uio_device_id);
+	/* Compose string: maps/mapY */
+	snprintf(uio_sys_map_subdir, sizeof(uio_sys_map_subdir), "%s%d",
+			FEC_UIO_DEVICE_SYS_MAP_ATTR, uio_map_id);
+
+	/* Read first (and only) line from file
+	 * /sys/class/uio/uioX/maps/mapY/size
+	 */
+	ret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,
+				"size", uio_map_size_str);
+	if (ret < 0) {
+		ENETFEC_PMD_ERR("file_read_first_line() failed");
+		return NULL;
+	}
+	ret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,
+				"addr", uio_map_p_addr_str);
+	if (ret < 0) {
+		ENETFEC_PMD_ERR("file_read_first_line() failed");
+		return NULL;
+	}
+	/* Read mapping size and physical address expressed in hexa(base 16) */
+	uio_map_size = strtol(uio_map_size_str, NULL, 16);
+	uio_map_p_addr = strtol(uio_map_p_addr_str, NULL, 16);
+
+	if (uio_map_id == 0) {
+		/* Map the register address in user space when map_id is 0 */
+		mapped_address = mmap(0 /*dynamically choose virtual address */,
+				uio_map_size, PROT_READ | PROT_WRITE,
+				MAP_SHARED, uio_device_fd, 0);
+	} else {
+		/* Map the BD memory in user space */
+		mapped_address = mmap(NULL, uio_map_size,
+				PROT_READ | PROT_WRITE,
+				MAP_SHARED, uio_device_fd, (1 * MAP_PAGE_SIZE));
+	}
+
+	if (mapped_address == MAP_FAILED) {
+		ENETFEC_PMD_ERR("Failed to map! errno = %d uio job fd = %d,"
+			"uio device id = %d, uio map id = %d", errno,
+			uio_device_fd, uio_device_id, uio_map_id);
+		return NULL;
+	}
+
+	/* Save the map size to use it later on for munmap-ing */
+	*map_size = uio_map_size;
+	*map_addr = uio_map_p_addr;
+	ENETFEC_PMD_INFO("UIO dev[%d] mapped region [id =%d] size 0x%x at %p",
+		uio_device_id, uio_map_id, uio_map_size, mapped_address);
+
+	return mapped_address;
+}
+
+int
+config_enetfec_uio(struct enetfec_private *fep)
+{
+	char uio_device_file_name[32];
+	struct uio_job *uio_job = NULL;
+
+	/* Mapping is done only one time */
+	if (enetfec_count > 0) {
+		ENETFEC_PMD_INFO("Mapped!\n");
+		return 0;
+	}
+
+	uio_job = &enetfec_uio_job;
+
+	/* Find UIO device created by ENETFEC-UIO kernel driver */
+	memset(uio_device_file_name, 0, sizeof(uio_device_file_name));
+	snprintf(uio_device_file_name, sizeof(uio_device_file_name), "%s%d",
+			FEC_UIO_DEVICE_FILE_NAME, uio_job->uio_minor_number);
+
+	/* Open device file */
+	uio_job->uio_fd = open(uio_device_file_name, O_RDWR);
+	if (uio_job->uio_fd < 0) {
+		ENETFEC_PMD_WARN("Unable to open ENETFEC_UIO file\n");
+		return -1;
+	}
+
+	ENETFEC_PMD_INFO("US_UIO: Open device(%s) file with uio_fd = %d",
+			uio_device_file_name, uio_job->uio_fd);
+
+	fep->hw_baseaddr_v = uio_map_mem(uio_job->uio_fd,
+		uio_job->uio_minor_number, FEC_UIO_REG_MAP_ID,
+		&uio_job->map_size, &uio_job->map_addr);
+	if (fep->hw_baseaddr_v == NULL)
+		return -ENOMEM;
+	fep->hw_baseaddr_p = uio_job->map_addr;
+	fep->reg_size = uio_job->map_size;
+
+	fep->bd_addr_v = uio_map_mem(uio_job->uio_fd,
+		uio_job->uio_minor_number, FEC_UIO_BD_MAP_ID,
+		&uio_job->map_size, &uio_job->map_addr);
+	if (fep->hw_baseaddr_v == NULL)
+		return -ENOMEM;
+	fep->bd_addr_p = uio_job->map_addr;
+	fep->bd_size = uio_job->map_size;
+
+	enetfec_count++;
+
+	return 0;
+}
+
+int
+enetfec_configure(void)
+{
+	char uio_name[32];
+	int uio_minor_number = -1;
+	int ret;
+	DIR *d = NULL;
+	struct dirent *dir;
+
+	d = opendir(FEC_UIO_DEVICE_SYS_ATTR_PATH);
+	if (d == NULL) {
+		ENETFEC_PMD_ERR("\nError opening directory '%s': %s\n",
+			FEC_UIO_DEVICE_SYS_ATTR_PATH, strerror(errno));
+		return -1;
+	}
+
+	/* Iterate through all subdirs */
+	while ((dir = readdir(d)) != NULL) {
+		if (!strncmp(dir->d_name, ".", 1) ||
+				!strncmp(dir->d_name, "..", 2))
+			continue;
+
+		if (file_name_match_extract(dir->d_name, "uio")) {
+			/*
+			 * As substring <uio> was found in <d_name>
+			 * read number following <uio> substring in <d_name>
+			 */
+			ret = sscanf(dir->d_name + strlen("uio"), "%d",
+							&uio_minor_number);
+			if (ret < 0)
+				ENETFEC_PMD_ERR("Error: not find minor number\n");
+			/*
+			 * Open file uioX/name and read first line which
+			 * contains the name for the device. Based on the
+			 * name check if this UIO device is for enetfec.
+			 */
+			memset(uio_name, 0, sizeof(uio_name));
+			ret = file_read_first_line(FEC_UIO_DEVICE_SYS_ATTR_PATH,
+					dir->d_name, "name", uio_name);
+			if (ret != 0) {
+				ENETFEC_PMD_INFO("file_read_first_line failed\n");
+				closedir(d);
+				return -1;
+			}
+
+			if (file_name_match_extract(uio_name,
+						FEC_UIO_DEVICE_NAME)) {
+				enetfec_uio_job.uio_minor_number =
+							uio_minor_number;
+				ENETFEC_PMD_INFO("enetfec device uio name: %s",
+						 uio_name);
+			}
+		}
+	}
+	closedir(d);
+	return 0;
+}
diff --git a/drivers/net/enetfec/enet_uio.h b/drivers/net/enetfec/enet_uio.h
new file mode 100644
index 0000000000..4a031d3f46
--- /dev/null
+++ b/drivers/net/enetfec/enet_uio.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 NXP
+ */
+
+#include "enet_ethdev.h"
+
+/* Prefix path to sysfs directory where UIO device attributes are exported.
+ * Path for UIO device X is /sys/class/uio/uioX
+ */
+#define FEC_UIO_DEVICE_SYS_ATTR_PATH	"/sys/class/uio"
+
+/* Subfolder in sysfs where mapping attributes are exported
+ * for each UIO device. Path for mapping Y for device X is:
+ * /sys/class/uio/uioX/maps/mapY
+ */
+#define FEC_UIO_DEVICE_SYS_MAP_ATTR	"maps/map"
+
+/* Name of UIO device file prefix. Each UIO device will have a device file
+ * /dev/uioX, where X is the minor device number.
+ */
+#define FEC_UIO_DEVICE_FILE_NAME	"/dev/uio"
+/*
+ * Name of UIO device. User space FEC will have a corresponding
+ * UIO device.
+ * Maximum length is #FEC_UIO_MAX_DEVICE_NAME_LENGTH.
+ *
+ * @note  Must be kept in sync with FEC kernel driver
+ * define #FEC_UIO_DEVICE_NAME !
+ */
+#define FEC_UIO_DEVICE_NAME     "imx-fec-uio"
+
+/* Maximum length for the name of an UIO device file.
+ * Device file name format is: /dev/uioX.
+ */
+#define FEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH	30
+
+/* Maximum length for the name of an attribute file for an UIO device.
+ * Attribute files are exported in sysfs and have the name formatted as:
+ * /sys/class/uio/uioX/<attribute_file_name>
+ */
+#define FEC_UIO_MAX_ATTR_FILE_NAME	100
+
+/* The id for the mapping used to export ENETFEC registers and BD memory to
+ * user space through UIO device.
+ */
+#define FEC_UIO_REG_MAP_ID		0
+#define FEC_UIO_BD_MAP_ID		1
+
+#define MAP_PAGE_SIZE			4096
+
+struct uio_job {
+	uint32_t fec_id;
+	int uio_fd;
+	void *bd_start_addr;
+	void *register_base_addr;
+	int map_size;
+	uint64_t map_addr;
+	int uio_minor_number;
+};
+
+int enetfec_configure(void);
+int config_enetfec_uio(struct enetfec_private *fep);
+void enetfec_uio_init(void);
+void enetfec_cleanup(void);
-- 
2.17.1


  parent reply	other threads:[~2021-10-21  4:47 UTC|newest]

Thread overview: 91+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-01 11:42 [dpdk-dev] [PATCH v4 0/5] drivers/net: add NXP ENETFEC driver Apeksha Gupta
2021-10-01 11:42 ` [dpdk-dev] [PATCH v4 1/5] net/enetfec: introduce " Apeksha Gupta
2021-10-19 18:39   ` [dpdk-dev] [PATCH v5 0/5] drivers/net: add " Apeksha Gupta
2021-10-19 18:39     ` [dpdk-dev] [PATCH v5 1/5] net/enetfec: introduce " Apeksha Gupta
2021-10-21  4:46       ` [dpdk-dev] [PATCH v6 0/5] drivers/net: add " Apeksha Gupta
2021-10-21  4:46         ` [dpdk-dev] [PATCH v6 1/5] net/enetfec: introduce " Apeksha Gupta
2021-10-21  5:24           ` Hemant Agrawal
2021-10-27 14:18           ` Ferruh Yigit
2021-11-08 18:42             ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-11-03 19:20           ` [dpdk-dev] [PATCH v7 0/5] drivers/net: add " Apeksha Gupta
2021-11-03 19:20             ` [dpdk-dev] [PATCH v7 1/5] net/enetfec: introduce " Apeksha Gupta
2021-11-03 23:27               ` Ferruh Yigit
2021-11-04 18:24               ` Ferruh Yigit
2021-11-08 19:13                 ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-11-09 11:34               ` [dpdk-dev] [PATCH v8 0/5] drivers/net: add " Apeksha Gupta
2021-11-09 11:34                 ` [dpdk-dev] [PATCH v8 1/5] net/enetfec: introduce " Apeksha Gupta
2021-11-09 11:34                 ` [dpdk-dev] [PATCH v8 2/5] net/enetfec: add UIO support Apeksha Gupta
2021-11-09 11:34                 ` [dpdk-dev] [PATCH v8 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-11-09 11:34                 ` [dpdk-dev] [PATCH v8 4/5] net/enetfec: add Rx/Tx support Apeksha Gupta
2021-11-09 11:34                 ` [dpdk-dev] [PATCH v8 5/5] net/enetfec: add features Apeksha Gupta
2021-11-10  7:48                   ` [dpdk-dev] [PATCH v9 0/5] drivers/net: add NXP ENETFEC driver Apeksha Gupta
2021-11-10  7:48                     ` [dpdk-dev] [PATCH v9 1/5] net/enetfec: introduce " Apeksha Gupta
2021-11-10 13:53                       ` Ferruh Yigit
2021-11-13  4:31                       ` [PATCH v10 0/5] drivers/net: add " Apeksha Gupta
2021-11-13  4:31                         ` [PATCH v10 1/5] net/enetfec: introduce " Apeksha Gupta
2021-11-15  7:19                           ` [PATCH v11 0/5] drivers/net: add " Apeksha Gupta
2021-11-15  7:19                             ` [PATCH v11 1/5] net/enetfec: introduce " Apeksha Gupta
2021-11-15 10:07                               ` Ferruh Yigit
2023-03-21 18:03                               ` Ferruh Yigit
2023-03-23  6:00                                 ` Sachin Saxena (OSS)
2023-03-23 11:07                                   ` Ferruh Yigit
2023-03-23 11:09                                     ` Sachin Saxena (OSS)
2021-11-15  7:19                             ` [PATCH v11 2/5] net/enetfec: add UIO support Apeksha Gupta
2021-11-15  7:19                             ` [PATCH v11 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-11-15 10:11                               ` Ferruh Yigit
2021-11-15 10:24                                 ` Ferruh Yigit
2021-11-15 11:15                                   ` Ferruh Yigit
2021-11-15  7:19                             ` [PATCH v11 4/5] net/enetfec: add Rx/Tx support Apeksha Gupta
2021-11-15  7:19                             ` [PATCH v11 5/5] net/enetfec: add features Apeksha Gupta
2021-11-15  9:44                             ` [PATCH v11 0/5] drivers/net: add NXP ENETFEC driver Ferruh Yigit
2021-11-15 15:05                             ` Ferruh Yigit
2021-11-25 16:52                               ` Ferruh Yigit
2021-11-13  4:31                         ` [PATCH v10 2/5] net/enetfec: add UIO support Apeksha Gupta
2021-11-13  4:31                         ` [PATCH v10 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-11-13 17:11                           ` Stephen Hemminger
2021-11-13  4:31                         ` [PATCH v10 4/5] net/enetfec: add Rx/Tx support Apeksha Gupta
2021-11-13 17:10                           ` Stephen Hemminger
2021-11-13  4:31                         ` [PATCH v10 5/5] net/enetfec: add features Apeksha Gupta
2021-11-10  7:48                     ` [dpdk-dev] [PATCH v9 2/5] net/enetfec: add UIO support Apeksha Gupta
2021-11-10  7:48                     ` [dpdk-dev] [PATCH v9 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-11-10 13:54                       ` Ferruh Yigit
2021-11-13  5:00                         ` [EXT] " Apeksha Gupta
2021-11-15 10:06                         ` Ferruh Yigit
2021-11-15 10:23                           ` Ferruh Yigit
2021-11-15 10:29                             ` Ferruh Yigit
2021-11-10  7:48                     ` [dpdk-dev] [PATCH v9 4/5] net/enetfec: add Rx/Tx support Apeksha Gupta
2021-11-10 13:56                       ` Ferruh Yigit
2021-11-10  7:48                     ` [dpdk-dev] [PATCH v9 5/5] net/enetfec: add features Apeksha Gupta
2021-11-10 13:57                       ` Ferruh Yigit
2021-11-03 19:20             ` [dpdk-dev] [PATCH v7 2/5] net/enetfec: add UIO support Apeksha Gupta
2021-11-04 18:25               ` Ferruh Yigit
2021-11-08 20:24                 ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-11-08 21:51                   ` Ferruh Yigit
2021-11-03 19:20             ` [dpdk-dev] [PATCH v7 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-11-04 18:26               ` Ferruh Yigit
2021-11-03 19:20             ` [dpdk-dev] [PATCH v7 4/5] net/enetfec: add Rx/Tx support Apeksha Gupta
2021-11-04 18:28               ` Ferruh Yigit
2021-11-09 16:20                 ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-11-03 19:20             ` [dpdk-dev] [PATCH v7 5/5] net/enetfec: add features Apeksha Gupta
2021-11-04 18:31             ` [dpdk-dev] [PATCH v7 0/5] drivers/net: add NXP ENETFEC driver Ferruh Yigit
2021-10-21  4:46         ` Apeksha Gupta [this message]
2021-10-27 14:21           ` [dpdk-dev] [PATCH v6 2/5] net/enetfec: add UIO support Ferruh Yigit
2021-11-08 18:44             ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-10-21  4:46         ` [dpdk-dev] [PATCH v6 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-10-27 14:23           ` Ferruh Yigit
2021-11-08 18:45             ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-10-21  4:46         ` [dpdk-dev] [PATCH v6 4/5] net/enetfec: add enqueue and dequeue support Apeksha Gupta
2021-10-27 14:25           ` Ferruh Yigit
2021-11-08 18:47             ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-10-21  4:47         ` [dpdk-dev] [PATCH v6 5/5] net/enetfec: add features Apeksha Gupta
2021-10-27 14:26           ` Ferruh Yigit
2021-10-27 14:15         ` [dpdk-dev] [PATCH v6 0/5] drivers/net: add NXP ENETFEC driver Ferruh Yigit
2021-10-19 18:40     ` [dpdk-dev] [PATCH v5 2/5] net/enetfec: add UIO support Apeksha Gupta
2021-10-19 18:40     ` [dpdk-dev] [PATCH v5 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-10-19 18:40     ` [dpdk-dev] [PATCH v5 4/5] net/enetfec: add enqueue and dequeue support Apeksha Gupta
2021-10-19 18:40     ` [dpdk-dev] [PATCH v5 5/5] net/enetfec: add features Apeksha Gupta
2021-10-01 11:42 ` [dpdk-dev] [PATCH v4 2/5] net/enetfec: add UIO support Apeksha Gupta
2021-10-01 11:42 ` [dpdk-dev] [PATCH v4 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-10-01 11:42 ` [dpdk-dev] [PATCH v4 4/5] net/enetfec: add enqueue and dequeue support Apeksha Gupta
2021-10-01 11:42 ` [dpdk-dev] [PATCH v4 5/5] net/enetfec: add features Apeksha Gupta
2021-10-17 10:49 ` [dpdk-dev] [PATCH v4 0/5] drivers/net: add NXP ENETFEC driver Apeksha Gupta

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211021044700.12370-3-apeksha.gupta@nxp.com \
    --to=apeksha.gupta@nxp.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=hemant.agrawal@nxp.com \
    --cc=sachin.saxena@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.