@@ -949,9 +949,12 @@ F: doc/guides/nics/features/dpaa2.ini
NXP enetc
M: Gagandeep Singh <g.singh@nxp.com>
M: Sachin Saxena <sachin.saxena@oss.nxp.com>
+M: Vanshika Shukla <vanshika.shukla@nxp.com>
F: drivers/net/enetc/
F: doc/guides/nics/enetc.rst
+F: doc/guides/nics/enetc4.rst
F: doc/guides/nics/features/enetc.ini
+F: doc/guides/nics/features/enetc4.ini
NXP enetfec - EXPERIMENTAL
M: Apeksha Gupta <apeksha.gupta@nxp.com>
new file mode 100644
@@ -0,0 +1,17 @@
+[binaries]
+c = ['ccache', 'aarch64-linux-gnu-gcc']
+cpp = ['ccache', 'aarch64-linux-gnu-g++']
+ar = 'aarch64-linux-gnu-ar'
+as = 'aarch64-linux-gnu-as'
+strip = 'aarch64-linux-gnu-strip'
+pkgconfig = 'aarch64-linux-gnu-pkg-config'
+pcap-config = ''
+
+[host_machine]
+system = 'linux'
+cpu_family = 'aarch64'
+cpu = 'armv8.2-a'
+endian = 'little'
+
+[properties]
+platform = 'imx'
@@ -561,6 +561,18 @@ soc_hip10 = {
'numa': true
}
+soc_imx = {
+ 'description': 'NXP IMX',
+ 'implementer': '0x41',
+ 'part_number': '0xd05',
+ 'flags': [
+ ['RTE_MACHINE', '"armv8a"'],
+ ['RTE_MAX_LCORE', 6],
+ ['RTE_MAX_NUMA_NODES', 1],
+ ],
+ 'numa': false,
+}
+
soc_kunpeng920 = {
'description': 'HiSilicon Kunpeng 920',
'implementer': '0x48',
@@ -684,6 +696,7 @@ graviton2: AWS Graviton2
graviton3: AWS Graviton3
graviton4: AWS Graviton4
hip10: HiSilicon HIP10
+imx: NXP IMX
kunpeng920: HiSilicon Kunpeng 920
kunpeng930: HiSilicon Kunpeng 930
n1sdp: Arm Neoverse N1SDP
@@ -722,6 +735,7 @@ socs = {
'graviton3': soc_graviton3,
'graviton4': soc_graviton4,
'hip10': soc_hip10,
+ 'imx': soc_imx,
'kunpeng920': soc_kunpeng920,
'kunpeng930': soc_kunpeng930,
'n1sdp': soc_n1sdp,
new file mode 100644
@@ -0,0 +1,99 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright 2024 NXP
+
+ENETC4 Poll Mode Driver
+=======================
+
+The ENETC4 NIC PMD (**librte_net_enetc**) provides poll mode driver
+support for the inbuilt NIC found in the **NXP i.MX95** SoC.
+
+More information can be found at `NXP Official Website
+<https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/i-mx-applications-processors/i-mx-9-processors/i-mx-95-applications-processor-family-high-performance-safety-enabled-platform-with-eiq-neutron-npu:iMX95>`_.
+
+This section provides an overview of the NXP ENETC4
+and how it is integrated into the DPDK.
+
+Contents summary
+
+- ENETC4 overview
+- Supported ENETC4 SoCs
+- PCI bus driver
+- NIC driver
+- Prerequisites
+- Driver compilation and testing
+
+ENETC4 Overview
+---------------
+
+ENETC4 is a PCI Integrated End Point(IEP). IEP implements
+peripheral devices in an SoC such that software sees them as PCIe device.
+ENETC4 is an evolution of BDR(Buffer Descriptor Ring) based networking
+IPs.
+
+This infrastructure simplifies adding support for IEP and facilitates in following:
+
+- Device discovery and location
+- Resource requirement discovery and allocation (e.g. interrupt assignment,
+ device register address)
+- Event reporting
+
+Supported ENETC4 SoCs
+---------------------
+
+- i.MX95
+
+NIC Driver (PMD)
+----------------
+
+The ENETC4 PMD is a traditional DPDK PMD that bridges the RTE framework and
+ENETC4 internal drivers, supporting both Virtual Functions (VFs) and
+Physical Functions (PF). Key functionality includes:
+
+- Driver registration: The device vendor table is registered in the PCI subsystem.
+- Device discovery: The RTE framework scans the PCI bus for connected devices, triggering the ENETC4 driver's probe function.
+- Initialization: The probe function configures basic device registers and sets up Buffer Descriptor (BD) rings.
+- Receive processing: Upon packet reception, the BD Ring status bit is set, facilitating packet processing.
+- Transmission: Packet transmission precedes reception, ensuring efficient data transfer.
+
+Prerequisites
+-------------
+
+There are three main pre-requisites for executing ENETC4 PMD on ENETC4
+compatible boards:
+
+#. **ARM 64 Tool Chain**
+
+ For example, the `*aarch64* ARM Toolchain <https://developer.arm.com/-/media/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-aarch64-none-linux-gnu.tar.xz>`_.
+
+#. **Linux Kernel**
+
+ It can be obtained from `NXP's Github hosting <https://github.com/nxp-imx/linux-imx>`_.
+
+The following dependencies are not part of DPDK and must be installed
+separately:
+
+- **NXP Linux LF**
+
+ NXP Linux Factory (LF) includes support for family
+ of QorIQ® ARM-Architecture-based system on chip (SoC) processors
+ and corresponding boards.
+
+ It includes the Linux board support packages (BSPs) for NXP SoCs,
+ a fully operational tool chain, kernel and board specific modules.
+
+ i.MX LF release and related information can be obtained from: `LF <https://www.nxp.com/design/design-center/software/embedded-software/i-mx-software/embedded-linux-for-i-mx-applications-processors:IMXLINUX>`_
+ Refer section: Linux Current Release.
+
+- **kpage_ncache Kernel Module**
+
+ i.MX95 platform is a IO non-cache coherent platform and driver is dependent on
+ a kernel module kpage_ncache.ko to mark the hugepage memory to non-cacheable.
+
+ The module can be obtained from: `kpage_ncache <https://github.com/nxp-qoriq/dpdk-extras/tree/main/linux/kpage_ncache>`_
+
+Driver compilation and testing
+------------------------------
+
+Follow instructions available in the document
+:ref:`compiling and testing a PMD for a NIC <pmd_build_and_test>`
+to launch **testpmd**
new file mode 100644
@@ -0,0 +1,9 @@
+;
+; Supported features of the 'enetc4' network poll mode driver.
+;
+; Refer to default.ini for the full list of available PMD features.
+;
+[Features]
+Linux = Y
+ARMv8 = Y
+Usage doc = Y
@@ -27,6 +27,7 @@ Network Interface Controller Drivers
e1000em
ena
enetc
+ enetc4
enetfec
enic
fail_safe
@@ -139,6 +139,10 @@ New Features
* Added SR-IOV VF support.
* Added recent 1400/14000 and 15000 models to the supported list.
+* **Added ENETC4 PMD**
+
+ * Added ENETC4 PMD for NXP i.MX95 platform.
+
* **Updated Marvell cnxk net driver.**
* Added ethdev driver support for CN20K SoC.
new file mode 100644
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 NXP
+ *
+ * This header file defines the register offsets and bit fields
+ * of ENETC4 PF and VFs.
+ */
+
+#ifndef _ENETC4_HW_H_
+#define _ENETC4_HW_H_
+#include <rte_io.h>
+
+/* ENETC4 device IDs */
+#define ENETC4_DEV_ID 0xe101
+#define ENETC4_DEV_ID_VF 0xef00
+#define PCI_VENDOR_ID_NXP 0x1131
+
+/***************************ENETC port registers**************************/
+#define ENETC4_PMR 0x10
+#define ENETC4_PMR_EN (BIT(16) | BIT(17) | BIT(18))
+
+/* Port Station interface promiscuous MAC mode register */
+#define ENETC4_PSIPMMR 0x200
+#define PSIPMMR_SI0_MAC_UP BIT(0)
+#define PSIPMMR_SI_MAC_UP (BIT(0) | BIT(1) | BIT(2))
+#define PSIPMMR_SI0_MAC_MP BIT(16)
+#define PSIPMMR_SI_MAC_MP (BIT(16) | BIT(17) | BIT(18))
+
+/* Port Station interface a primary MAC address registers */
+#define ENETC4_PSIPMAR0(a) ((a) * 0x80 + 0x2000)
+#define ENETC4_PSIPMAR1(a) ((a) * 0x80 + 0x2004)
+
+/* Port MAC address register 0/1 */
+#define ENETC4_PMAR0 0x4020
+#define ENETC4_PMAR1 0x4024
+
+/* Port operational register */
+#define ENETC4_POR 0x4100
+
+/* Port traffic class a transmit maximum SDU register */
+#define ENETC4_PTCTMSDUR(a) ((a) * 0x20 + 0x4208)
+#define SDU_TYPE_MPDU BIT(16)
+
+#define ENETC4_PM_CMD_CFG(mac) (0x5008 + (mac) * 0x400)
+#define PM_CMD_CFG_TX_EN BIT(0)
+#define PM_CMD_CFG_RX_EN BIT(1)
+
+/* i.MX95 supports jumbo frame, but it is recommended to set the max frame
+ * size to 2000 bytes.
+ */
+#define ENETC4_MAC_MAXFRM_SIZE 2000
+
+/* Port MAC 0/1 Maximum Frame Length Register */
+#define ENETC4_PM_MAXFRM(mac) (0x5014 + (mac) * 0x400)
+
+/* Config register to reset counters */
+#define ENETC4_PM0_STAT_CONFIG 0x50e0
+/* Stats Reset Bit */
+#define ENETC4_CLEAR_STATS BIT(2)
+
+/* Port MAC 0/1 Receive Ethernet Octets Counter */
+#define ENETC4_PM_REOCT(mac) (0x5100 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Frame Error Counter */
+#define ENETC4_PM_RERR(mac) (0x5138 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Dropped Packets Counter */
+#define ENETC4_PM_RDRP(mac) (0x5158 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Packets Counter */
+#define ENETC4_PM_RPKT(mac) (0x5160 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Frame Error Counter */
+#define ENETC4_PM_TERR(mac) (0x5238 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Ethernet Octets Counter */
+#define ENETC4_PM_TEOCT(mac) (0x5200 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Packets Counter */
+#define ENETC4_PM_TPKT(mac) (0x5260 + (mac) * 0x400)
+
+/* Port MAC 0 Interface Mode Control Register */
+#define ENETC4_PM_IF_MODE(mac) (0x5300 + (mac) * 0x400)
+#define PM_IF_MODE_IFMODE (BIT(0) | BIT(1) | BIT(2))
+#define IFMODE_XGMII 0
+#define IFMODE_RMII 3
+#define IFMODE_RGMII 4
+#define IFMODE_SGMII 5
+#define PM_IF_MODE_ENA BIT(15)
+
+/* general register accessors */
+#define enetc4_rd_reg(reg) rte_read32((void *)(reg))
+#define enetc4_wr_reg(reg, val) rte_write32((val), (void *)(reg))
+
+#define enetc4_rd(hw, off) enetc4_rd_reg((size_t)(hw)->reg + (off))
+#define enetc4_wr(hw, off, val) enetc4_wr_reg((size_t)(hw)->reg + (off), val)
+/* port register accessors - PF only */
+#define enetc4_port_rd(hw, off) enetc4_rd_reg((size_t)(hw)->port + (off))
+#define enetc4_port_wr(hw, off, val) \
+ enetc4_wr_reg((size_t)(hw)->port + (off), val)
+/* BDR register accessors, see ENETC_BDR() */
+#define enetc4_bdr_rd(hw, t, n, off) \
+ enetc4_rd(hw, ENETC_BDR(t, n, off))
+#define enetc4_bdr_wr(hw, t, n, off, val) \
+ enetc4_wr(hw, ENETC_BDR(t, n, off), val)
+#define enetc4_txbdr_rd(hw, n, off) enetc4_bdr_rd(hw, TX, n, off)
+#define enetc4_rxbdr_rd(hw, n, off) enetc4_bdr_rd(hw, RX, n, off)
+#define enetc4_txbdr_wr(hw, n, off, val) \
+ enetc4_bdr_wr(hw, TX, n, off, val)
+#define enetc4_rxbdr_wr(hw, n, off, val) \
+ enetc4_bdr_wr(hw, RX, n, off, val)
+#endif
@@ -1,10 +1,11 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2024 NXP
*/
#ifndef _ENETC_HW_H_
#define _ENETC_HW_H_
#include <rte_io.h>
+#include <ethdev_pci.h>
#define BIT(x) ((uint64_t)1 << ((x)))
@@ -1,18 +1,21 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2019 NXP
+ * Copyright 2018-2019,2024 NXP
*/
#ifndef _ENETC_H_
#define _ENETC_H_
#include <rte_time.h>
+#include <ethdev_pci.h>
+#include "compat.h"
#include "base/enetc_hw.h"
+#include "enetc_logs.h"
#define PCI_VENDOR_ID_FREESCALE 0x1957
/* Max TX rings per ENETC. */
-#define MAX_TX_RINGS 2
+#define MAX_TX_RINGS 1
/* Max RX rings per ENTEC. */
#define MAX_RX_RINGS 1
@@ -33,21 +36,11 @@
#define ENETC_ETH_MAX_LEN (RTE_ETHER_MTU + \
RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)
-/*
- * upper_32_bits - return bits 32-63 of a number
- * @n: the number we're accessing
- *
- * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress
- * the "right shift count >= width of type" warning when that quantity is
- * 32-bits.
- */
-#define upper_32_bits(n) ((uint32_t)(((n) >> 16) >> 16))
+/* eth name size */
+#define ENETC_ETH_NAMESIZE 20
-/*
- * lower_32_bits - return bits 0-31 of a number
- * @n: the number we're accessing
- */
-#define lower_32_bits(n) ((uint32_t)(n))
+/* size for marking hugepage non-cacheable */
+#define SIZE_2MB 0x200000
#define ENETC_TXBD(BDR, i) (&(((struct enetc_tx_bd *)((BDR).bd_base))[i]))
#define ENETC_RXBD(BDR, i) (&(((union enetc_rx_bd *)((BDR).bd_base))[i]))
@@ -74,6 +67,7 @@ struct enetc_bdr {
};
struct rte_mempool *mb_pool; /* mbuf pool to populate RX ring. */
struct rte_eth_dev *ndev;
+ const struct rte_memzone *mz;
};
/*
@@ -96,6 +90,20 @@ struct enetc_eth_adapter {
#define ENETC_DEV_PRIVATE_TO_INTR(adapter) \
(&((struct enetc_eth_adapter *)adapter)->intr)
+/*
+ * ENETC4 function prototypes
+ */
+int enetc4_pci_remove(struct rte_pci_device *pci_dev);
+int enetc4_dev_configure(struct rte_eth_dev *dev);
+int enetc4_dev_close(struct rte_eth_dev *dev);
+int enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
+ struct rte_eth_dev_info *dev_info);
+
+/*
+ * enetc4_vf function prototype
+ */
+int enetc4_vf_dev_stop(struct rte_eth_dev *dev);
+
/*
* RX/TX ENETC function prototypes
*/
@@ -104,8 +112,9 @@ uint16_t enetc_xmit_pkts(void *txq, struct rte_mbuf **tx_pkts,
uint16_t enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
-
int enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt);
+void enetc4_dev_hw_init(struct rte_eth_dev *eth_dev);
+void print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr);
static inline int
enetc_bd_unused(struct enetc_bdr *bdr)
new file mode 100644
@@ -0,0 +1,309 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 NXP
+ */
+
+#include <stdbool.h>
+#include <rte_random.h>
+#include <dpaax_iova_table.h>
+
+#include "kpage_ncache_api.h"
+#include "base/enetc4_hw.h"
+#include "enetc_logs.h"
+#include "enetc.h"
+
+static int
+enetc4_dev_start(struct rte_eth_dev *dev)
+{
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct enetc_hw *enetc_hw = &hw->hw;
+ uint32_t val;
+
+ PMD_INIT_FUNC_TRACE();
+
+ val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(0));
+ enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(0),
+ val | PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN);
+
+ val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(1));
+ enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(1),
+ val | PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN);
+
+ /* Enable port */
+ val = enetc4_port_rd(enetc_hw, ENETC4_PMR);
+ enetc4_port_wr(enetc_hw, ENETC4_PMR, val | ENETC4_PMR_EN);
+
+ /* Enable port transmit/receive */
+ enetc4_port_wr(enetc_hw, ENETC4_POR, 0);
+
+ return 0;
+}
+
+static int
+enetc4_dev_stop(struct rte_eth_dev *dev)
+{
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct enetc_hw *enetc_hw = &hw->hw;
+ uint32_t val;
+
+ PMD_INIT_FUNC_TRACE();
+
+ /* Disable port */
+ val = enetc4_port_rd(enetc_hw, ENETC4_PMR);
+ enetc4_port_wr(enetc_hw, ENETC4_PMR, val & (~ENETC4_PMR_EN));
+
+ val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(0));
+ enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(0),
+ val & (~(PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN)));
+
+ val = enetc4_port_rd(enetc_hw, ENETC4_PM_CMD_CFG(1));
+ enetc4_port_wr(enetc_hw, ENETC4_PM_CMD_CFG(1),
+ val & (~(PM_CMD_CFG_TX_EN | PM_CMD_CFG_RX_EN)));
+
+ return 0;
+}
+
+static int
+enetc4_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
+{
+ uint32_t *mac = (uint32_t *)hw->mac.addr;
+ struct enetc_hw *enetc_hw = &hw->hw;
+ uint32_t high_mac = 0;
+ uint16_t low_mac = 0;
+ char eth_name[ENETC_ETH_NAMESIZE];
+
+ PMD_INIT_FUNC_TRACE();
+
+ /* Enabling Station Interface */
+ enetc4_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
+
+ *mac = (uint32_t)enetc4_port_rd(enetc_hw, ENETC4_PSIPMAR0(0));
+ high_mac = (uint32_t)*mac;
+ mac++;
+ *mac = (uint16_t)enetc4_port_rd(enetc_hw, ENETC4_PSIPMAR1(0));
+ low_mac = (uint16_t)*mac;
+
+ if ((high_mac | low_mac) == 0) {
+ char *first_byte;
+
+ ENETC_PMD_NOTICE("MAC is not available for this SI, "
+ "set random MAC");
+ mac = (uint32_t *)hw->mac.addr;
+ *mac = (uint32_t)rte_rand();
+ first_byte = (char *)mac;
+ *first_byte &= 0xfe; /* clear multicast bit */
+ *first_byte |= 0x02; /* set local assignment bit (IEEE802) */
+
+ enetc4_port_wr(enetc_hw, ENETC4_PMAR0, *mac);
+ mac++;
+ *mac = (uint16_t)rte_rand();
+ enetc4_port_wr(enetc_hw, ENETC4_PMAR1, *mac);
+ print_ethaddr("New address: ",
+ (const struct rte_ether_addr *)hw->mac.addr);
+ }
+
+ /* Allocate memory for storing MAC addresses */
+ snprintf(eth_name, sizeof(eth_name), "enetc4_eth_%d", eth_dev->data->port_id);
+ eth_dev->data->mac_addrs = rte_zmalloc(eth_name,
+ RTE_ETHER_ADDR_LEN, 0);
+ if (!eth_dev->data->mac_addrs) {
+ ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
+ "store MAC addresses",
+ RTE_ETHER_ADDR_LEN * 1);
+ return -ENOMEM;
+ }
+
+ /* Copy the permanent MAC address */
+ rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
+ ð_dev->data->mac_addrs[0]);
+
+ return 0;
+}
+
+int
+enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
+ struct rte_eth_dev_info *dev_info)
+{
+ PMD_INIT_FUNC_TRACE();
+ dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+ .nb_max = MAX_BD_COUNT,
+ .nb_min = MIN_BD_COUNT,
+ .nb_align = BD_ALIGN,
+ };
+ dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+ .nb_max = MAX_BD_COUNT,
+ .nb_min = MIN_BD_COUNT,
+ .nb_align = BD_ALIGN,
+ };
+ dev_info->max_rx_queues = MAX_RX_RINGS;
+ dev_info->max_tx_queues = MAX_TX_RINGS;
+ dev_info->max_rx_pktlen = ENETC4_MAC_MAXFRM_SIZE;
+
+ return 0;
+}
+
+int
+enetc4_dev_close(struct rte_eth_dev *dev)
+{
+ struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ int ret;
+
+ PMD_INIT_FUNC_TRACE();
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ if (hw->device_id == ENETC4_DEV_ID_VF)
+ ret = enetc4_vf_dev_stop(dev);
+ else
+ ret = enetc4_dev_stop(dev);
+
+ if (rte_eal_iova_mode() == RTE_IOVA_PA)
+ dpaax_iova_table_depopulate();
+
+ return ret;
+}
+
+int
+enetc4_dev_configure(struct rte_eth_dev *dev)
+{
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct enetc_hw *enetc_hw = &hw->hw;
+ uint32_t max_len;
+ uint32_t val;
+
+ PMD_INIT_FUNC_TRACE();
+
+ max_len = dev->data->dev_conf.rxmode.mtu + RTE_ETHER_HDR_LEN +
+ RTE_ETHER_CRC_LEN;
+ enetc4_port_wr(enetc_hw, ENETC4_PM_MAXFRM(0), ENETC_SET_MAXFRM(max_len));
+
+ val = ENETC4_MAC_MAXFRM_SIZE | SDU_TYPE_MPDU;
+ enetc4_port_wr(enetc_hw, ENETC4_PTCTMSDUR(0), val | SDU_TYPE_MPDU);
+
+ return 0;
+}
+
+
+
+/*
+ * The set of PCI devices this driver supports
+ */
+static const struct rte_pci_id pci_id_enetc4_map[] = {
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_NXP, ENETC4_DEV_ID) },
+ { .vendor_id = 0, /* sentinel */ },
+};
+
+/* Features supported by this driver */
+static const struct eth_dev_ops enetc4_ops = {
+ .dev_configure = enetc4_dev_configure,
+ .dev_start = enetc4_dev_start,
+ .dev_stop = enetc4_dev_stop,
+ .dev_close = enetc4_dev_close,
+ .dev_infos_get = enetc4_dev_infos_get,
+};
+
+/*
+ * Storing the HW base addresses
+ *
+ * @param eth_dev
+ * - Pointer to the structure rte_eth_dev
+ */
+void
+enetc4_dev_hw_init(struct rte_eth_dev *eth_dev)
+{
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+
+ eth_dev->rx_pkt_burst = &enetc_recv_pkts;
+ eth_dev->tx_pkt_burst = &enetc_xmit_pkts;
+
+ /* Retrieving and storing the HW base address of device */
+ hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
+ hw->device_id = pci_dev->id.device_id;
+
+ /* Calculating and storing the base HW addresses */
+ hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE);
+ hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE);
+}
+
+/**
+ * Initialisation of the enetc4 device
+ *
+ * @param eth_dev
+ * - Pointer to the structure rte_eth_dev
+ *
+ * @return
+ * - On success, zero.
+ * - On failure, negative value.
+ */
+
+static int
+enetc4_dev_init(struct rte_eth_dev *eth_dev)
+{
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ int error = 0;
+
+ PMD_INIT_FUNC_TRACE();
+ eth_dev->dev_ops = &enetc4_ops;
+ enetc4_dev_hw_init(eth_dev);
+
+ error = enetc4_mac_init(hw, eth_dev);
+ if (error != 0) {
+ ENETC_PMD_ERR("MAC initialization failed");
+ return -1;
+ }
+
+ /* Set MTU */
+ enetc_port_wr(&hw->hw, ENETC4_PM_MAXFRM(0),
+ ENETC_SET_MAXFRM(RTE_ETHER_MAX_LEN));
+ eth_dev->data->mtu = RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN -
+ RTE_ETHER_CRC_LEN;
+
+ if (rte_eal_iova_mode() == RTE_IOVA_PA)
+ dpaax_iova_table_populate();
+
+ ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
+ eth_dev->data->port_id, pci_dev->id.vendor_id,
+ pci_dev->id.device_id);
+ return 0;
+}
+
+static int
+enetc4_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ return enetc4_dev_close(eth_dev);
+}
+
+static int
+enetc4_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ return rte_eth_dev_pci_generic_probe(pci_dev,
+ sizeof(struct enetc_eth_adapter),
+ enetc4_dev_init);
+}
+
+int
+enetc4_pci_remove(struct rte_pci_device *pci_dev)
+{
+ return rte_eth_dev_pci_generic_remove(pci_dev, enetc4_dev_uninit);
+}
+
+static struct rte_pci_driver rte_enetc4_pmd = {
+ .id_table = pci_id_enetc4_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = enetc4_pci_probe,
+ .remove = enetc4_pci_remove,
+};
+
+RTE_PMD_REGISTER_PCI(net_enetc4, rte_enetc4_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_enetc4, pci_id_enetc4_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_enetc4, "* vfio-pci");
+RTE_LOG_REGISTER_DEFAULT(enetc4_logtype_pmd, NOTICE);
new file mode 100644
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 NXP
+ */
+
+#include <stdbool.h>
+#include <rte_random.h>
+#include <dpaax_iova_table.h>
+#include "base/enetc4_hw.h"
+#include "base/enetc_hw.h"
+#include "enetc_logs.h"
+#include "enetc.h"
+
+int
+enetc4_vf_dev_stop(struct rte_eth_dev *dev __rte_unused)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ return 0;
+}
+
+static int
+enetc4_vf_dev_start(struct rte_eth_dev *dev __rte_unused)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ return 0;
+}
+
+/*
+ * The set of PCI devices this driver supports
+ */
+static const struct rte_pci_id pci_vf_id_enetc4_map[] = {
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_NXP, ENETC4_DEV_ID_VF) },
+ { .vendor_id = 0, /* sentinel */ },
+};
+
+/* Features supported by this driver */
+static const struct eth_dev_ops enetc4_vf_ops = {
+ .dev_configure = enetc4_dev_configure,
+ .dev_start = enetc4_vf_dev_start,
+ .dev_stop = enetc4_vf_dev_stop,
+ .dev_close = enetc4_dev_close,
+ .dev_infos_get = enetc4_dev_infos_get,
+};
+
+static int
+enetc4_vf_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
+{
+ uint32_t *mac = (uint32_t *)hw->mac.addr;
+ struct enetc_hw *enetc_hw = &hw->hw;
+ uint32_t high_mac = 0;
+ uint16_t low_mac = 0;
+ char vf_eth_name[ENETC_ETH_NAMESIZE];
+
+ PMD_INIT_FUNC_TRACE();
+
+ /* Enabling Station Interface */
+ enetc4_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
+ *mac = (uint32_t)enetc_rd(enetc_hw, ENETC_SIPMAR0);
+ high_mac = (uint32_t)*mac;
+ mac++;
+ *mac = (uint16_t)enetc_rd(enetc_hw, ENETC_SIPMAR1);
+ low_mac = (uint16_t)*mac;
+
+ if ((high_mac | low_mac) == 0) {
+ char *first_byte;
+ ENETC_PMD_NOTICE("MAC is not available for this SI, "
+ "set random MAC");
+ mac = (uint32_t *)hw->mac.addr;
+ *mac = (uint32_t)rte_rand();
+ first_byte = (char *)mac;
+ *first_byte &= 0xfe; /* clear multicast bit */
+ *first_byte |= 0x02; /* set local assignment bit (IEEE802) */
+ enetc4_port_wr(enetc_hw, ENETC4_PMAR0, *mac);
+ mac++;
+ *mac = (uint16_t)rte_rand();
+ enetc4_port_wr(enetc_hw, ENETC4_PMAR1, *mac);
+ print_ethaddr("New address: ",
+ (const struct rte_ether_addr *)hw->mac.addr);
+ }
+
+ /* Allocate memory for storing MAC addresses */
+ snprintf(vf_eth_name, sizeof(vf_eth_name), "enetc4_vf_eth_%d", eth_dev->data->port_id);
+ eth_dev->data->mac_addrs = rte_zmalloc(vf_eth_name,
+ RTE_ETHER_ADDR_LEN, 0);
+ if (!eth_dev->data->mac_addrs) {
+ ENETC_PMD_ERR("Failed to allocate %d bytes needed to "
+ "store MAC addresses",
+ RTE_ETHER_ADDR_LEN * 1);
+ return -ENOMEM;
+ }
+
+ /* Copy the permanent MAC address */
+ rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
+ ð_dev->data->mac_addrs[0]);
+
+ return 0;
+}
+
+static int
+enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
+{
+ struct enetc_eth_hw *hw =
+ ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ int error = 0;
+
+ PMD_INIT_FUNC_TRACE();
+ eth_dev->dev_ops = &enetc4_vf_ops;
+ enetc4_dev_hw_init(eth_dev);
+
+ error = enetc4_vf_mac_init(hw, eth_dev);
+ if (error != 0) {
+ ENETC_PMD_ERR("MAC initialization failed!!");
+ return -1;
+ }
+
+ if (rte_eal_iova_mode() == RTE_IOVA_PA)
+ dpaax_iova_table_populate();
+
+ ENETC_PMD_DEBUG("port_id %d vendorID=0x%x deviceID=0x%x",
+ eth_dev->data->port_id, pci_dev->id.vendor_id,
+ pci_dev->id.device_id);
+ return 0;
+}
+
+static int
+enetc4_vf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ return rte_eth_dev_pci_generic_probe(pci_dev,
+ sizeof(struct enetc_eth_adapter),
+ enetc4_vf_dev_init);
+}
+
+static struct rte_pci_driver rte_enetc4_vf_pmd = {
+ .id_table = pci_vf_id_enetc4_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = enetc4_vf_pci_probe,
+ .remove = enetc4_pci_remove,
+};
+
+RTE_PMD_REGISTER_PCI(net_enetc4_vf, rte_enetc4_vf_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_enetc4_vf, pci_vf_id_enetc4_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_enetc4_vf, "* uio_pci_generic");
+RTE_LOG_REGISTER_DEFAULT(enetc4_vf_logtype_pmd, NOTICE);
@@ -1,9 +1,8 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2024 NXP
*/
#include <stdbool.h>
-#include <ethdev_pci.h>
#include <rte_random.h>
#include <dpaax_iova_table.h>
@@ -145,7 +144,7 @@ enetc_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
return rte_eth_linkstatus_set(dev, &link);
}
-static void
+void
print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
{
char buf[RTE_ETHER_ADDR_FMT_SIZE];
new file mode 100644
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
+ *
+ * Copyright 2022-2024 NXP
+ *
+ */
+
+#ifndef KPG_NC_MODULE_H
+#define KPG_NC_MODULE_H
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#include <rte_log.h>
+
+#include "enetc_logs.h"
+
+#define KPG_NC_DEVICE_NAME "page_ncache"
+#define KPG_NC_DEVICE_PATH "/dev/" KPG_NC_DEVICE_NAME
+
+/* IOCTL */
+#define KPG_NC_MAGIC_NUM 0xf0f0
+#define KPG_NC_IOCTL_UPDATE _IOWR(KPG_NC_MAGIC_NUM, 1, size_t)
+
+
+#define KNRM "\x1B[0m"
+#define KRED "\x1B[31m"
+#define KGRN "\x1B[32m"
+#define KYEL "\x1B[33m"
+#define KBLU "\x1B[34m"
+#define KMAG "\x1B[35m"
+#define KCYN "\x1B[36m"
+#define KWHT "\x1B[37m"
+
+#if defined(RTE_ARCH_ARM) && defined(RTE_ARCH_64)
+static inline void flush_tlb(void *p)
+{
+ asm volatile("dc civac, %0" ::"r"(p));
+ asm volatile("dsb ish");
+ asm volatile("isb");
+}
+#endif
+
+static inline void mark_kpage_ncache(uint64_t huge_page)
+{
+ int fd, ret;
+
+ fd = open(KPG_NC_DEVICE_PATH, O_RDONLY);
+ if (fd < 0) {
+ ENETC_PMD_ERR(KYEL "Error: " KNRM "Could not open: %s",
+ KPG_NC_DEVICE_PATH);
+ return;
+ }
+ ENETC_PMD_DEBUG(KCYN "%s: Huge_Page addr =" KNRM " 0x%" PRIX64,
+ __func__, huge_page);
+ ret = ioctl(fd, KPG_NC_IOCTL_UPDATE, (size_t)&huge_page);
+ if (ret) {
+ ENETC_PMD_ERR(KYEL "Error(%d): " KNRM "non-cachable set",
+ ret);
+ close(fd);
+ return;
+ }
+#if defined(RTE_ARCH_ARM) && defined(RTE_ARCH_64)
+ flush_tlb((void *)huge_page);
+#endif
+ ENETC_PMD_DEBUG(KYEL "Page should be non-cachable now" KNRM);
+
+ close(fd);
+}
+#endif /* KPG_NC_MODULE_H */
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: BSD-3-Clause
-# Copyright 2018 NXP
+# Copyright 2018,2024 NXP
if not is_linux
build = false
@@ -8,6 +8,8 @@ endif
deps += ['common_dpaax']
sources = files(
+ 'enetc4_ethdev.c',
+ 'enetc4_vf.c',
'enetc_ethdev.c',
'enetc_rxtx.c',
)