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 v3 2/5] net/enetfec: add UIO support
Date: Fri, 10 Sep 2021 02:13:11 +0530 [thread overview]
Message-ID: <20210909204314.1826-3-apeksha.gupta@nxp.com> (raw)
In-Reply-To: <20210909204314.1826-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 | 233 ++++++++++++++++++++++++++++++
drivers/net/enetfec/enet_ethdev.h | 2 +
drivers/net/enetfec/enet_regs.h | 108 ++++++++++++++
drivers/net/enetfec/enet_uio.c | 200 +++++++++++++++++++++++++
drivers/net/enetfec/enet_uio.h | 54 +++++++
drivers/net/enetfec/meson.build | 3 +-
6 files changed, 599 insertions(+), 1 deletion(-)
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 ee78f95cde..9e69fb1e0b 100644
--- a/drivers/net/enetfec/enet_ethdev.c
+++ b/drivers/net/enetfec/enet_ethdev.c
@@ -12,17 +12,222 @@
#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_VDEV_GEM_ID_ARG "intf"
#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,32 @@ 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_BUFDESC_EX
+ | QUIRK_RACC;
+
+ 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 b211c7a2c4..bff55a266a 100644
--- a/drivers/net/enetfec/enet_ethdev.h
+++ b/drivers/net/enetfec/enet_ethdev.h
@@ -156,5 +156,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..5665e19dd3
--- /dev/null
+++ b/drivers/net/enetfec/enet_regs.h
@@ -0,0 +1,108 @@
+/* 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)
+/* Controller has extended descriptor buffer */
+#define QUIRK_BUFDESC_EX (1 << 4)
+/* 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..10567839a6
--- /dev/null
+++ b/drivers/net/enetfec/enet_uio.c
@@ -0,0 +1,200 @@
+/* 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;
+int count;
+
+/*
+ * @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 (count > 0) {
+ printf("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) {
+ printf("US_UIO: Open Failed\n");
+ exit(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;
+
+ count++;
+
+ return 0;
+}
diff --git a/drivers/net/enetfec/enet_uio.h b/drivers/net/enetfec/enet_uio.h
new file mode 100644
index 0000000000..b220cae9dd
--- /dev/null
+++ b/drivers/net/enetfec/enet_uio.h
@@ -0,0 +1,54 @@
+/* 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"
+
+/* 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 config_enetfec_uio(struct enetfec_private *fep);
+void enetfec_uio_init(void);
+void enetfec_cleanup(void);
diff --git a/drivers/net/enetfec/meson.build b/drivers/net/enetfec/meson.build
index b0a0fc111b..25a6d73d57 100644
--- a/drivers/net/enetfec/meson.build
+++ b/drivers/net/enetfec/meson.build
@@ -8,4 +8,5 @@ endif
deps += ['common_dpaax']
-sources = files('enet_ethdev.c')
+sources = files('enet_ethdev.c',
+ 'enet_uio.c')
--
2.17.1
next prev parent reply other threads:[~2021-09-09 20:43 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-09 20:43 [dpdk-dev] [PATCH v3 0/5] drivers/net: add NXP ENETFEC driver Apeksha Gupta
2021-09-09 20:43 ` [dpdk-dev] [PATCH v3 1/5] net/enetfec: introduce " Apeksha Gupta
2021-09-23 10:09 ` Ferruh Yigit
2021-10-01 10:22 ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-10-01 14:45 ` Ferruh Yigit
2021-10-05 5:24 ` Apeksha Gupta
2021-10-05 9:29 ` Ferruh Yigit
2021-10-06 9:36 ` Apeksha Gupta
2021-09-09 20:43 ` Apeksha Gupta [this message]
2021-09-23 10:13 ` [dpdk-dev] [PATCH v3 2/5] net/enetfec: add UIO support Ferruh Yigit
2021-10-01 10:30 ` [dpdk-dev] [EXT] " Apeksha Gupta
2021-09-09 20:43 ` [dpdk-dev] [PATCH v3 3/5] net/enetfec: support queue configuration Apeksha Gupta
2021-09-09 20:43 ` [dpdk-dev] [PATCH v3 4/5] net/enetfec: add enqueue and dequeue support Apeksha Gupta
2021-09-09 20:43 ` [dpdk-dev] [PATCH v3 5/5] net/enetfec: add features 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=20210909204314.1826-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.