DPDK patches and discussions
 help / color / mirror / Atom feed
* [v1 00/12] ENETC4 PMD support
@ 2024-10-18  7:26 vanshika.shukla
  2024-10-18  7:26 ` [v1 01/12] net/enetc: Add initial ENETC4 PMD driver support vanshika.shukla
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev

From: Vanshika Shukla <vanshika.shukla@nxp.com>

This series introduces a new ENETC4 PMD driver for NXP's i.MX95
SoC, enabling basic network operations. 

Vanshika Shukla (12):
  net/enetc: Add initial ENETC4 PMD driver support
  net/enetc: Add RX and TX queue APIs for ENETC4 PMD
  net/enetc: Optimize ENETC4 data path
  net/enetc: Add TX checksum offload and RX checksum validation
  net/enetc: Add basic statistics
  net/enetc: Add packet type parsing support
  net/enetc: Add support for multiple queues with RSS
  net/enetc: Add VF to PF messaging support and primary MAC setup
  net/enetc: Add multicast and promiscuous mode support
  net/enetc: Add link speed and status support
  net/enetc: Add link status notification support
  net/enetc: Add MAC and VLAN filter support

 MAINTAINERS                            |    3 +
 config/arm/arm64_imx_linux_gcc         |   17 +
 config/arm/meson.build                 |   14 +
 doc/guides/nics/enetc4.rst             |   99 ++
 doc/guides/nics/features/enetc4.ini    |   22 +
 doc/guides/nics/index.rst              |    1 +
 doc/guides/rel_notes/release_24_11.rst |    4 +
 drivers/net/enetc/base/enetc4_hw.h     |  186 ++++
 drivers/net/enetc/base/enetc_hw.h      |   52 +-
 drivers/net/enetc/enetc.h              |  246 ++++-
 drivers/net/enetc/enetc4_ethdev.c      | 1051 ++++++++++++++++++
 drivers/net/enetc/enetc4_vf.c          | 1364 ++++++++++++++++++++++++
 drivers/net/enetc/enetc_cbdr.c         |  311 ++++++
 drivers/net/enetc/enetc_ethdev.c       |    5 +-
 drivers/net/enetc/enetc_rxtx.c         |  171 ++-
 drivers/net/enetc/kpage_ncache_api.h   |   70 ++
 drivers/net/enetc/meson.build          |    5 +-
 drivers/net/enetc/ntmp.h               |  110 ++
 18 files changed, 3690 insertions(+), 41 deletions(-)
 create mode 100644 config/arm/arm64_imx_linux_gcc
 create mode 100644 doc/guides/nics/enetc4.rst
 create mode 100644 doc/guides/nics/features/enetc4.ini
 create mode 100644 drivers/net/enetc/base/enetc4_hw.h
 create mode 100644 drivers/net/enetc/enetc4_ethdev.c
 create mode 100644 drivers/net/enetc/enetc4_vf.c
 create mode 100644 drivers/net/enetc/enetc_cbdr.c
 create mode 100644 drivers/net/enetc/kpage_ncache_api.h
 create mode 100644 drivers/net/enetc/ntmp.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 01/12] net/enetc: Add initial ENETC4 PMD driver support
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 02/12] net/enetc: Add RX and TX queue APIs for ENETC4 PMD vanshika.shukla
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Thomas Monjalon, Wathsala Vithanage, Bruce Richardson,
	Gagandeep Singh, Sachin Saxena, Vanshika Shukla, Anatoly Burakov
  Cc: Apeksha Gupta

From: Vanshika Shukla <vanshika.shukla@nxp.com>

This patch introduces a new ENETC4 PMD driver for NXP's i.MX95
SoC, enabling basic network operations. Key features include:

- Probe and teardown functions
- Hardware initialization for both Virtual Functions (VFs)
  and Physical Function (PF)

Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
---
 MAINTAINERS                            |   3 +
 config/arm/arm64_imx_linux_gcc         |  17 ++
 config/arm/meson.build                 |  14 ++
 doc/guides/nics/enetc4.rst             |  99 ++++++++
 doc/guides/nics/features/enetc4.ini    |   9 +
 doc/guides/nics/index.rst              |   1 +
 doc/guides/rel_notes/release_24_11.rst |   4 +
 drivers/net/enetc/base/enetc4_hw.h     | 111 +++++++++
 drivers/net/enetc/base/enetc_hw.h      |   3 +-
 drivers/net/enetc/enetc.h              |  43 ++--
 drivers/net/enetc/enetc4_ethdev.c      | 309 +++++++++++++++++++++++++
 drivers/net/enetc/enetc4_vf.c          | 146 ++++++++++++
 drivers/net/enetc/enetc_ethdev.c       |   5 +-
 drivers/net/enetc/kpage_ncache_api.h   |  70 ++++++
 drivers/net/enetc/meson.build          |   4 +-
 15 files changed, 816 insertions(+), 22 deletions(-)
 create mode 100644 config/arm/arm64_imx_linux_gcc
 create mode 100644 doc/guides/nics/enetc4.rst
 create mode 100644 doc/guides/nics/features/enetc4.ini
 create mode 100644 drivers/net/enetc/base/enetc4_hw.h
 create mode 100644 drivers/net/enetc/enetc4_ethdev.c
 create mode 100644 drivers/net/enetc/enetc4_vf.c
 create mode 100644 drivers/net/enetc/kpage_ncache_api.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f09cda04c8..b45524330c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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>
diff --git a/config/arm/arm64_imx_linux_gcc b/config/arm/arm64_imx_linux_gcc
new file mode 100644
index 0000000000..c876ae1d2b
--- /dev/null
+++ b/config/arm/arm64_imx_linux_gcc
@@ -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'
diff --git a/config/arm/meson.build b/config/arm/meson.build
index 55be7c8711..6112244f2c 100644
--- a/config/arm/meson.build
+++ b/config/arm/meson.build
@@ -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,
diff --git a/doc/guides/nics/enetc4.rst b/doc/guides/nics/enetc4.rst
new file mode 100644
index 0000000000..8ffdc53376
--- /dev/null
+++ b/doc/guides/nics/enetc4.rst
@@ -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**
diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
new file mode 100644
index 0000000000..ca3b9ae992
--- /dev/null
+++ b/doc/guides/nics/features/enetc4.ini
@@ -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
diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
index c14bc7988a..da2af04777 100644
--- a/doc/guides/nics/index.rst
+++ b/doc/guides/nics/index.rst
@@ -27,6 +27,7 @@ Network Interface Controller Drivers
     e1000em
     ena
     enetc
+    enetc4
     enetfec
     enic
     fail_safe
diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst
index d2301461ce..0f11dcbd8d 100644
--- a/doc/guides/rel_notes/release_24_11.rst
+++ b/doc/guides/rel_notes/release_24_11.rst
@@ -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.
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
new file mode 100644
index 0000000000..34a4ca3b02
--- /dev/null
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -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
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 66fad58e5e..2d63c54db6 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -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)))
 
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 7163633bce..87fc51b776 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -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)
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
new file mode 100644
index 0000000000..3fe14bd5a6
--- /dev/null
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -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,
+			&eth_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);
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
new file mode 100644
index 0000000000..7996d6decb
--- /dev/null
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -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,
+			     &eth_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);
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index ffbecc407c..d7cba1ba83 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -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];
diff --git a/drivers/net/enetc/kpage_ncache_api.h b/drivers/net/enetc/kpage_ncache_api.h
new file mode 100644
index 0000000000..01291b1d7f
--- /dev/null
+++ b/drivers/net/enetc/kpage_ncache_api.h
@@ -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 */
diff --git a/drivers/net/enetc/meson.build b/drivers/net/enetc/meson.build
index 966dc694fc..6e00758a36 100644
--- a/drivers/net/enetc/meson.build
+++ b/drivers/net/enetc/meson.build
@@ -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',
 )
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 02/12] net/enetc: Add RX and TX queue APIs for ENETC4 PMD
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
  2024-10-18  7:26 ` [v1 01/12] net/enetc: Add initial ENETC4 PMD driver support vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 03/12] net/enetc: Optimize ENETC4 data path vanshika.shukla
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla; +Cc: Apeksha Gupta

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Introduces queue setup, release, start, and stop
APIs for ENETC4 RX and TX queues, enabling:

- Queue configuration and initialization
- Queue resource management (setup, release)
- Queue operation control (start, stop)

Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |   1 +
 drivers/net/enetc/enetc.h           |  13 +
 drivers/net/enetc/enetc4_ethdev.c   | 434 ++++++++++++++++++++++++++++
 drivers/net/enetc/enetc4_vf.c       |   8 +
 drivers/net/enetc/enetc_rxtx.c      |  32 +-
 5 files changed, 485 insertions(+), 3 deletions(-)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index ca3b9ae992..37b548dcab 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Queue start/stop     = Y
 Linux                = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 87fc51b776..9901e434d9 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -98,6 +98,19 @@ 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);
+int enetc4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+			  uint16_t nb_rx_desc, unsigned int socket_id __rte_unused,
+			  const struct rte_eth_rxconf *rx_conf,
+			  struct rte_mempool *mb_pool);
+int enetc4_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx);
+int enetc4_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx);
+void enetc4_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
+int enetc4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
+			  uint16_t nb_desc, unsigned int socket_id __rte_unused,
+			  const struct rte_eth_txconf *tx_conf);
+int enetc4_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx);
+int enetc4_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx);
+void enetc4_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
 
 /*
  * enetc4_vf function prototype
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 3fe14bd5a6..4d05546308 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -143,10 +143,338 @@ enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
+static int
+mark_memory_ncache(struct enetc_bdr *bdr, const char *mz_name, unsigned int size)
+{
+	uint64_t huge_page;
+	const struct rte_memzone *mz;
+
+	mz = rte_memzone_reserve_aligned(mz_name,
+			size, SOCKET_ID_ANY,
+			RTE_MEMZONE_2MB, size);
+	if (mz) {
+		bdr->bd_base = mz->addr;
+	} else {
+		ENETC_PMD_ERR("Failed to allocate memzone!!,"
+			      " please reserve 2MB size pages");
+		return -ENOMEM;
+	}
+	if (mz->hugepage_sz != size)
+		ENETC_PMD_WARN("Hugepage size of queue memzone %" PRIx64,
+				mz->hugepage_sz);
+	bdr->mz = mz;
+
+	/* Mark memory NON-CACHEABLE */
+	huge_page =
+		(uint64_t)RTE_PTR_ALIGN_FLOOR(bdr->bd_base, size);
+	mark_kpage_ncache(huge_page);
+
+	return 0;
+}
+
+static int
+enetc4_alloc_txbdr(uint16_t port_id, struct enetc_bdr *txr, uint16_t nb_desc)
+{
+	char mz_name[RTE_MEMZONE_NAMESIZE];
+	int size;
+
+	size = nb_desc * sizeof(struct enetc_swbd);
+	txr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
+	if (txr->q_swbd == NULL)
+		return -ENOMEM;
+
+	snprintf(mz_name, sizeof(mz_name), "bdt_addr_%d", port_id);
+	if (mark_memory_ncache(txr, mz_name, SIZE_2MB)) {
+		ENETC_PMD_ERR("Failed to mark BD memory non-cacheable!");
+		rte_free(txr->q_swbd);
+		txr->q_swbd = NULL;
+		return -ENOMEM;
+	}
+	txr->bd_count = nb_desc;
+	txr->next_to_clean = 0;
+	txr->next_to_use = 0;
+
+	return 0;
+}
+
+static void
+enetc4_free_bdr(struct enetc_bdr *rxr)
+{
+	rte_memzone_free(rxr->mz);
+	rxr->mz = NULL;
+	rte_free(rxr->q_swbd);
+	rxr->q_swbd = NULL;
+	rxr->bd_base = NULL;
+}
+
+static void
+enetc4_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
+{
+	int idx = tx_ring->index;
+	phys_addr_t bd_address;
+
+	bd_address = (phys_addr_t)
+		     rte_mem_virt2iova((const void *)tx_ring->bd_base);
+	enetc4_txbdr_wr(hw, idx, ENETC_TBBAR0,
+		       lower_32_bits((uint64_t)bd_address));
+	enetc4_txbdr_wr(hw, idx, ENETC_TBBAR1,
+		       upper_32_bits((uint64_t)bd_address));
+	enetc4_txbdr_wr(hw, idx, ENETC_TBLENR,
+		       ENETC_RTBLENR_LEN(tx_ring->bd_count));
+
+	enetc4_txbdr_wr(hw, idx, ENETC_TBCIR, 0);
+	enetc4_txbdr_wr(hw, idx, ENETC_TBCISR, 0);
+	tx_ring->tcir = (void *)((size_t)hw->reg +
+			ENETC_BDR(TX, idx, ENETC_TBCIR));
+	tx_ring->tcisr = (void *)((size_t)hw->reg +
+			 ENETC_BDR(TX, idx, ENETC_TBCISR));
+}
+
+int
+enetc4_tx_queue_setup(struct rte_eth_dev *dev,
+		     uint16_t queue_idx,
+		     uint16_t nb_desc,
+		     unsigned int socket_id __rte_unused,
+		     const struct rte_eth_txconf *tx_conf)
+{
+	int err = 0;
+	struct enetc_bdr *tx_ring;
+	struct rte_eth_dev_data *data = dev->data;
+	struct enetc_eth_adapter *priv =
+			ENETC_DEV_PRIVATE(data->dev_private);
+
+	PMD_INIT_FUNC_TRACE();
+	if (nb_desc > MAX_BD_COUNT)
+		return -1;
+
+	tx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
+	if (tx_ring == NULL) {
+		ENETC_PMD_ERR("Failed to allocate TX ring memory");
+		err = -ENOMEM;
+		return -1;
+	}
+
+	tx_ring->index = queue_idx;
+	err = enetc4_alloc_txbdr(data->port_id, tx_ring, nb_desc);
+	if (err)
+		goto fail;
+
+	tx_ring->ndev = dev;
+	enetc4_setup_txbdr(&priv->hw.hw, tx_ring);
+	data->tx_queues[queue_idx] = tx_ring;
+	if (!tx_conf->tx_deferred_start) {
+		/* enable ring */
+		enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index,
+			       ENETC_TBMR, ENETC_TBMR_EN);
+		dev->data->tx_queue_state[tx_ring->index] =
+			       RTE_ETH_QUEUE_STATE_STARTED;
+	} else {
+		dev->data->tx_queue_state[tx_ring->index] =
+			       RTE_ETH_QUEUE_STATE_STOPPED;
+	}
+
+	return 0;
+fail:
+	rte_free(tx_ring);
+
+	return err;
+}
+
+void
+enetc4_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
+{
+	void *txq = dev->data->tx_queues[qid];
+
+	if (txq == NULL)
+		return;
+
+	struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq;
+	struct enetc_eth_hw *eth_hw =
+		ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
+	struct enetc_hw *hw;
+	struct enetc_swbd *tx_swbd;
+	int i;
+	uint32_t val;
+
+	/* Disable the ring */
+	hw = &eth_hw->hw;
+	val = enetc4_txbdr_rd(hw, tx_ring->index, ENETC_TBMR);
+	val &= (~ENETC_TBMR_EN);
+	enetc4_txbdr_wr(hw, tx_ring->index, ENETC_TBMR, val);
+
+	/* clean the ring*/
+	i = tx_ring->next_to_clean;
+	tx_swbd = &tx_ring->q_swbd[i];
+	while (tx_swbd->buffer_addr != NULL) {
+		rte_pktmbuf_free(tx_swbd->buffer_addr);
+		tx_swbd->buffer_addr = NULL;
+		tx_swbd++;
+		i++;
+		if (unlikely(i == tx_ring->bd_count)) {
+			i = 0;
+			tx_swbd = &tx_ring->q_swbd[i];
+		}
+	}
+
+	enetc4_free_bdr(tx_ring);
+	rte_free(tx_ring);
+}
+
+static int
+enetc4_alloc_rxbdr(uint16_t port_id, struct enetc_bdr *rxr,
+		  uint16_t nb_desc)
+{
+	char mz_name[RTE_MEMZONE_NAMESIZE];
+	int size;
+
+	size = nb_desc * sizeof(struct enetc_swbd);
+	rxr->q_swbd = rte_malloc(NULL, size, ENETC_BD_RING_ALIGN);
+	if (rxr->q_swbd == NULL)
+		return -ENOMEM;
+
+	snprintf(mz_name, sizeof(mz_name), "bdr_addr_%d", port_id);
+	if (mark_memory_ncache(rxr, mz_name, SIZE_2MB)) {
+		ENETC_PMD_ERR("Failed to mark BD memory non-cacheable!");
+		rte_free(rxr->q_swbd);
+		rxr->q_swbd = NULL;
+		return -ENOMEM;
+	}
+	rxr->bd_count = nb_desc;
+	rxr->next_to_clean = 0;
+	rxr->next_to_use = 0;
+	rxr->next_to_alloc = 0;
+
+	return 0;
+}
+
+static void
+enetc4_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
+		  struct rte_mempool *mb_pool)
+{
+	int idx = rx_ring->index;
+	uint16_t buf_size;
+	phys_addr_t bd_address;
+
+	bd_address = (phys_addr_t)
+		     rte_mem_virt2iova((const void *)rx_ring->bd_base);
+
+	enetc4_rxbdr_wr(hw, idx, ENETC_RBBAR0,
+		       lower_32_bits((uint64_t)bd_address));
+	enetc4_rxbdr_wr(hw, idx, ENETC_RBBAR1,
+		       upper_32_bits((uint64_t)bd_address));
+	enetc4_rxbdr_wr(hw, idx, ENETC_RBLENR,
+		       ENETC_RTBLENR_LEN(rx_ring->bd_count));
+
+	rx_ring->mb_pool = mb_pool;
+	rx_ring->rcir = (void *)((size_t)hw->reg +
+			ENETC_BDR(RX, idx, ENETC_RBCIR));
+	enetc_refill_rx_ring(rx_ring, (enetc_bd_unused(rx_ring)));
+	buf_size = (uint16_t)(rte_pktmbuf_data_room_size(rx_ring->mb_pool) -
+		   RTE_PKTMBUF_HEADROOM);
+	enetc4_rxbdr_wr(hw, idx, ENETC_RBBSR, buf_size);
+	enetc4_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
+}
+
+int
+enetc4_rx_queue_setup(struct rte_eth_dev *dev,
+		     uint16_t rx_queue_id,
+		     uint16_t nb_rx_desc,
+		     unsigned int socket_id __rte_unused,
+		     const struct rte_eth_rxconf *rx_conf,
+		     struct rte_mempool *mb_pool)
+{
+	int err = 0;
+	struct enetc_bdr *rx_ring;
+	struct rte_eth_dev_data *data =  dev->data;
+	struct enetc_eth_adapter *adapter =
+			ENETC_DEV_PRIVATE(data->dev_private);
+	uint64_t rx_offloads = data->dev_conf.rxmode.offloads;
+
+	PMD_INIT_FUNC_TRACE();
+	if (nb_rx_desc > MAX_BD_COUNT)
+		return -1;
+
+	rx_ring = rte_zmalloc(NULL, sizeof(struct enetc_bdr), 0);
+	if (rx_ring == NULL) {
+		ENETC_PMD_ERR("Failed to allocate RX ring memory");
+		err = -ENOMEM;
+		return err;
+	}
+
+	rx_ring->index = rx_queue_id;
+	err = enetc4_alloc_rxbdr(data->port_id, rx_ring, nb_rx_desc);
+	if (err)
+		goto fail;
+
+	rx_ring->ndev = dev;
+	enetc4_setup_rxbdr(&adapter->hw.hw, rx_ring, mb_pool);
+	data->rx_queues[rx_queue_id] = rx_ring;
+
+	if (!rx_conf->rx_deferred_start) {
+		/* enable ring */
+		enetc4_rxbdr_wr(&adapter->hw.hw, rx_ring->index, ENETC_RBMR,
+			       ENETC_RBMR_EN);
+		dev->data->rx_queue_state[rx_ring->index] =
+			       RTE_ETH_QUEUE_STATE_STARTED;
+	} else {
+		dev->data->rx_queue_state[rx_ring->index] =
+			       RTE_ETH_QUEUE_STATE_STOPPED;
+	}
+
+	rx_ring->crc_len = (uint8_t)((rx_offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) ?
+				     RTE_ETHER_CRC_LEN : 0);
+	return 0;
+fail:
+	rte_free(rx_ring);
+
+	return err;
+}
+
+void
+enetc4_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
+{
+	void *rxq = dev->data->rx_queues[qid];
+
+	if (rxq == NULL)
+		return;
+
+	struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
+	struct enetc_eth_hw *eth_hw =
+		ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
+	struct enetc_swbd *q_swbd;
+	struct enetc_hw *hw;
+	uint32_t val;
+	int i;
+
+	/* Disable the ring */
+	hw = &eth_hw->hw;
+	val = enetc4_rxbdr_rd(hw, rx_ring->index, ENETC_RBMR);
+	val &= (~ENETC_RBMR_EN);
+	enetc4_rxbdr_wr(hw, rx_ring->index, ENETC_RBMR, val);
+
+	/* Clean the ring */
+	i = rx_ring->next_to_clean;
+	q_swbd = &rx_ring->q_swbd[i];
+	while (i != rx_ring->next_to_use) {
+		rte_pktmbuf_free(q_swbd->buffer_addr);
+		q_swbd->buffer_addr = NULL;
+		q_swbd++;
+		i++;
+		if (unlikely(i == rx_ring->bd_count)) {
+			i = 0;
+			q_swbd = &rx_ring->q_swbd[i];
+		}
+	}
+
+	enetc4_free_bdr(rx_ring);
+	rte_free(rx_ring);
+}
+
 int
 enetc4_dev_close(struct rte_eth_dev *dev)
 {
 	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t i;
 	int ret;
 
 	PMD_INIT_FUNC_TRACE();
@@ -158,6 +486,18 @@ enetc4_dev_close(struct rte_eth_dev *dev)
 	else
 		ret = enetc4_dev_stop(dev);
 
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		enetc4_rx_queue_release(dev, i);
+		dev->data->rx_queues[i] = NULL;
+	}
+	dev->data->nb_rx_queues = 0;
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		enetc4_tx_queue_release(dev, i);
+		dev->data->tx_queues[i] = NULL;
+	}
+	dev->data->nb_tx_queues = 0;
+
 	if (rte_eal_iova_mode() == RTE_IOVA_PA)
 		dpaax_iova_table_depopulate();
 
@@ -185,7 +525,93 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
 	return 0;
 }
 
+int
+enetc4_rx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
+{
+	struct enetc_eth_adapter *priv =
+			ENETC_DEV_PRIVATE(dev->data->dev_private);
+	struct enetc_bdr *rx_ring;
+	uint32_t rx_data;
 
+	PMD_INIT_FUNC_TRACE();
+	rx_ring = dev->data->rx_queues[qidx];
+	if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
+		rx_data = enetc4_rxbdr_rd(&priv->hw.hw, rx_ring->index,
+					 ENETC_RBMR);
+		rx_data = rx_data | ENETC_RBMR_EN;
+		enetc4_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
+			       rx_data);
+		dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
+	}
+
+	return 0;
+}
+
+int
+enetc4_rx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
+{
+	struct enetc_eth_adapter *priv =
+			ENETC_DEV_PRIVATE(dev->data->dev_private);
+	struct enetc_bdr *rx_ring;
+	uint32_t rx_data;
+
+	PMD_INIT_FUNC_TRACE();
+	rx_ring = dev->data->rx_queues[qidx];
+	if (dev->data->rx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
+		rx_data = enetc4_rxbdr_rd(&priv->hw.hw, rx_ring->index,
+					 ENETC_RBMR);
+		rx_data = rx_data & (~ENETC_RBMR_EN);
+		enetc4_rxbdr_wr(&priv->hw.hw, rx_ring->index, ENETC_RBMR,
+			       rx_data);
+		dev->data->rx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
+	}
+
+	return 0;
+}
+
+int
+enetc4_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx)
+{
+	struct enetc_eth_adapter *priv =
+			ENETC_DEV_PRIVATE(dev->data->dev_private);
+	struct enetc_bdr *tx_ring;
+	uint32_t tx_data;
+
+	PMD_INIT_FUNC_TRACE();
+	tx_ring = dev->data->tx_queues[qidx];
+	if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STOPPED) {
+		tx_data = enetc4_txbdr_rd(&priv->hw.hw, tx_ring->index,
+					 ENETC_TBMR);
+		tx_data = tx_data | ENETC_TBMR_EN;
+		enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
+			       tx_data);
+		dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STARTED;
+	}
+
+	return 0;
+}
+
+int
+enetc4_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
+{
+	struct enetc_eth_adapter *priv =
+			ENETC_DEV_PRIVATE(dev->data->dev_private);
+	struct enetc_bdr *tx_ring;
+	uint32_t tx_data;
+
+	PMD_INIT_FUNC_TRACE();
+	tx_ring = dev->data->tx_queues[qidx];
+	if (dev->data->tx_queue_state[qidx] == RTE_ETH_QUEUE_STATE_STARTED) {
+		tx_data = enetc4_txbdr_rd(&priv->hw.hw, tx_ring->index,
+					 ENETC_TBMR);
+		tx_data = tx_data & (~ENETC_TBMR_EN);
+		enetc4_txbdr_wr(&priv->hw.hw, tx_ring->index, ENETC_TBMR,
+			       tx_data);
+		dev->data->tx_queue_state[qidx] = RTE_ETH_QUEUE_STATE_STOPPED;
+	}
+
+	return 0;
+}
 
 /*
  * The set of PCI devices this driver supports
@@ -202,6 +628,14 @@ static const struct eth_dev_ops enetc4_ops = {
 	.dev_stop             = enetc4_dev_stop,
 	.dev_close            = enetc4_dev_close,
 	.dev_infos_get        = enetc4_dev_infos_get,
+	.rx_queue_setup       = enetc4_rx_queue_setup,
+	.rx_queue_start       = enetc4_rx_queue_start,
+	.rx_queue_stop        = enetc4_rx_queue_stop,
+	.rx_queue_release     = enetc4_rx_queue_release,
+	.tx_queue_setup       = enetc4_tx_queue_setup,
+	.tx_queue_start       = enetc4_tx_queue_start,
+	.tx_queue_stop        = enetc4_tx_queue_stop,
+	.tx_queue_release     = enetc4_tx_queue_release,
 };
 
 /*
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 7996d6decb..0c68229a8d 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -41,6 +41,14 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.dev_stop             = enetc4_vf_dev_stop,
 	.dev_close            = enetc4_dev_close,
 	.dev_infos_get        = enetc4_dev_infos_get,
+	.rx_queue_setup       = enetc4_rx_queue_setup,
+	.rx_queue_start       = enetc4_rx_queue_start,
+	.rx_queue_stop        = enetc4_rx_queue_stop,
+	.rx_queue_release     = enetc4_rx_queue_release,
+	.tx_queue_setup       = enetc4_tx_queue_setup,
+	.tx_queue_start       = enetc4_tx_queue_start,
+	.tx_queue_stop        = enetc4_tx_queue_stop,
+	.tx_queue_release     = enetc4_tx_queue_release,
 };
 
 static int
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index ea64c9f682..1fc5f11339 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2024 NXP
  */
 
 #include <stdbool.h>
@@ -11,6 +11,7 @@
 #include "rte_memzone.h"
 
 #include "base/enetc_hw.h"
+#include "base/enetc4_hw.h"
 #include "enetc.h"
 #include "enetc_logs.h"
 
@@ -85,6 +86,12 @@ enetc_xmit_pkts(void *tx_queue,
 	int i, start, bds_to_use;
 	struct enetc_tx_bd *txbd;
 	struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
+	unsigned short buflen;
+	uint8_t *data;
+	int j;
+
+	struct enetc_eth_hw *hw =
+			ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
 
 	i = tx_ring->next_to_use;
 
@@ -95,6 +102,13 @@ enetc_xmit_pkts(void *tx_queue,
 	start = 0;
 	while (nb_pkts--) {
 		tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
+
+		if (hw->device_id == ENETC4_DEV_ID || hw->device_id == ENETC4_DEV_ID_VF) {
+			buflen = rte_pktmbuf_pkt_len(tx_ring->q_swbd[i].buffer_addr);
+			data = rte_pktmbuf_mtod(tx_ring->q_swbd[i].buffer_addr, void *);
+			for (j = 0; j <= buflen; j += RTE_CACHE_LINE_SIZE)
+				dcbf(data + j);
+		}
 		txbd = ENETC_TXBD(*tx_ring, i);
 		tx_swbd = &tx_ring->q_swbd[i];
 		txbd->frm_len = tx_pkts[start]->pkt_len;
@@ -326,6 +340,12 @@ enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 	int cleaned_cnt, i, bd_count;
 	struct enetc_swbd *rx_swbd;
 	union enetc_rx_bd *rxbd;
+	uint32_t bd_status;
+	uint8_t *data;
+	uint32_t j;
+	struct enetc_eth_hw *hw =
+			ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
+
 
 	/* next descriptor to process */
 	i = rx_ring->next_to_clean;
@@ -351,9 +371,8 @@ enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 
 	cleaned_cnt = enetc_bd_unused(rx_ring);
 	rx_swbd = &rx_ring->q_swbd[i];
-	while (likely(rx_frm_cnt < work_limit)) {
-		uint32_t bd_status;
 
+	while (likely(rx_frm_cnt < work_limit)) {
 		bd_status = rte_le_to_cpu_32(rxbd->r.lstatus);
 		if (!bd_status)
 			break;
@@ -366,6 +385,13 @@ enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 		rx_swbd->buffer_addr->ol_flags = 0;
 		enetc_dev_rx_parse(rx_swbd->buffer_addr,
 				   rxbd->r.parse_summary);
+
+		if (hw->device_id == ENETC4_DEV_ID || hw->device_id == ENETC4_DEV_ID_VF) {
+			data = rte_pktmbuf_mtod(rx_swbd->buffer_addr, void *);
+			for (j = 0; j <= rx_swbd->buffer_addr->pkt_len; j += RTE_CACHE_LINE_SIZE)
+				dccivac(data + j);
+		}
+
 		rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
 		cleaned_cnt++;
 		rx_swbd++;
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 03/12] net/enetc: Optimize ENETC4 data path
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
  2024-10-18  7:26 ` [v1 01/12] net/enetc: Add initial ENETC4 PMD driver support vanshika.shukla
  2024-10-18  7:26 ` [v1 02/12] net/enetc: Add RX and TX queue APIs for ENETC4 PMD vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 04/12] net/enetc: Add TX checksum offload and RX checksum validation vanshika.shukla
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla; +Cc: Apeksha Gupta

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Improves ENETC4 data path on i.MX95 Non-cache coherent platform by:

- Adding separate RX and TX functions.
- Reducing memory accesses

Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 drivers/net/enetc/base/enetc4_hw.h |   2 +
 drivers/net/enetc/enetc.h          |   5 +
 drivers/net/enetc/enetc4_ethdev.c  |   4 +-
 drivers/net/enetc/enetc_rxtx.c     | 153 ++++++++++++++++++++++++-----
 4 files changed, 138 insertions(+), 26 deletions(-)

diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index 34a4ca3b02..759cfaba28 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -14,6 +14,8 @@
 #define ENETC4_DEV_ID_VF	0xef00
 #define PCI_VENDOR_ID_NXP	0x1131
 
+#define ENETC4_TXBD_FLAGS_F		BIT(7)
+
 /***************************ENETC port registers**************************/
 #define ENETC4_PMR		0x10
 #define ENETC4_PMR_EN		(BIT(16) | BIT(17) | BIT(18))
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 9901e434d9..79c158513c 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -68,6 +68,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;
+	uint64_t ierrors;
 };
 
 /*
@@ -122,8 +123,12 @@ int enetc4_vf_dev_stop(struct rte_eth_dev *dev);
  */
 uint16_t enetc_xmit_pkts(void *txq, struct rte_mbuf **tx_pkts,
 		uint16_t nb_pkts);
+uint16_t enetc_xmit_pkts_nc(void *txq, struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts);
 uint16_t enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
 		uint16_t nb_pkts);
+uint16_t enetc_recv_pkts_nc(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);
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 4d05546308..290b90b9bc 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -651,8 +651,8 @@ enetc4_dev_hw_init(struct rte_eth_dev *eth_dev)
 		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;
+	eth_dev->rx_pkt_burst = &enetc_recv_pkts_nc;
+	eth_dev->tx_pkt_burst = &enetc_xmit_pkts_nc;
 
 	/* Retrieving and storing the HW base address of device */
 	hw->hw.reg = (void *)pci_dev->mem_resource[0].addr;
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index 1fc5f11339..d29b64ab56 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -86,12 +86,6 @@ enetc_xmit_pkts(void *tx_queue,
 	int i, start, bds_to_use;
 	struct enetc_tx_bd *txbd;
 	struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
-	unsigned short buflen;
-	uint8_t *data;
-	int j;
-
-	struct enetc_eth_hw *hw =
-			ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
 
 	i = tx_ring->next_to_use;
 
@@ -103,12 +97,6 @@ enetc_xmit_pkts(void *tx_queue,
 	while (nb_pkts--) {
 		tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
 
-		if (hw->device_id == ENETC4_DEV_ID || hw->device_id == ENETC4_DEV_ID_VF) {
-			buflen = rte_pktmbuf_pkt_len(tx_ring->q_swbd[i].buffer_addr);
-			data = rte_pktmbuf_mtod(tx_ring->q_swbd[i].buffer_addr, void *);
-			for (j = 0; j <= buflen; j += RTE_CACHE_LINE_SIZE)
-				dcbf(data + j);
-		}
 		txbd = ENETC_TXBD(*tx_ring, i);
 		tx_swbd = &tx_ring->q_swbd[i];
 		txbd->frm_len = tx_pkts[start]->pkt_len;
@@ -136,6 +124,61 @@ enetc_xmit_pkts(void *tx_queue,
 	return start;
 }
 
+uint16_t
+enetc_xmit_pkts_nc(void *tx_queue,
+		struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts)
+{
+	struct enetc_swbd *tx_swbd;
+	int i, start, bds_to_use;
+	struct enetc_tx_bd *txbd;
+	struct enetc_bdr *tx_ring = (struct enetc_bdr *)tx_queue;
+	unsigned int buflen, j;
+	uint8_t *data;
+
+	i = tx_ring->next_to_use;
+
+	bds_to_use = enetc_bd_unused(tx_ring);
+	if (bds_to_use < nb_pkts)
+		nb_pkts = bds_to_use;
+
+	start = 0;
+	while (nb_pkts--) {
+		tx_ring->q_swbd[i].buffer_addr = tx_pkts[start];
+
+		buflen = rte_pktmbuf_pkt_len(tx_ring->q_swbd[i].buffer_addr);
+		data = rte_pktmbuf_mtod(tx_ring->q_swbd[i].buffer_addr, void *);
+		for (j = 0; j <= buflen; j += RTE_CACHE_LINE_SIZE)
+			dcbf(data + j);
+
+		txbd = ENETC_TXBD(*tx_ring, i);
+		txbd->flags = rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_F);
+
+		tx_swbd = &tx_ring->q_swbd[i];
+		txbd->frm_len = buflen;
+		txbd->buf_len = txbd->frm_len;
+		txbd->addr = (uint64_t)(uintptr_t)
+		rte_cpu_to_le_64((size_t)tx_swbd->buffer_addr->buf_iova +
+				 tx_swbd->buffer_addr->data_off);
+		i++;
+		start++;
+		if (unlikely(i == tx_ring->bd_count))
+			i = 0;
+	}
+
+	/* we're only cleaning up the Tx ring here, on the assumption that
+	 * software is slower than hardware and hardware completed sending
+	 * older frames out by now.
+	 * We're also cleaning up the ring before kicking off Tx for the new
+	 * batch to minimize chances of contention on the Tx ring
+	 */
+	enetc_clean_tx_ring(tx_ring);
+
+	tx_ring->next_to_use = i;
+	enetc_wr_reg(tx_ring->tcir, i);
+	return start;
+}
+
 int
 enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
 {
@@ -171,7 +214,7 @@ enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
 		k++;
 		if (unlikely(i == rx_ring->bd_count)) {
 			i = 0;
-			rxbd = ENETC_RXBD(*rx_ring, 0);
+			rxbd = ENETC_RXBD(*rx_ring, i);
 			rx_swbd = &rx_ring->q_swbd[i];
 		}
 	}
@@ -341,11 +384,6 @@ enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 	struct enetc_swbd *rx_swbd;
 	union enetc_rx_bd *rxbd;
 	uint32_t bd_status;
-	uint8_t *data;
-	uint32_t j;
-	struct enetc_eth_hw *hw =
-			ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
-
 
 	/* next descriptor to process */
 	i = rx_ring->next_to_clean;
@@ -386,12 +424,6 @@ enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 		enetc_dev_rx_parse(rx_swbd->buffer_addr,
 				   rxbd->r.parse_summary);
 
-		if (hw->device_id == ENETC4_DEV_ID || hw->device_id == ENETC4_DEV_ID_VF) {
-			data = rte_pktmbuf_mtod(rx_swbd->buffer_addr, void *);
-			for (j = 0; j <= rx_swbd->buffer_addr->pkt_len; j += RTE_CACHE_LINE_SIZE)
-				dccivac(data + j);
-		}
-
 		rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
 		cleaned_cnt++;
 		rx_swbd++;
@@ -417,6 +449,79 @@ enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
 	return rx_frm_cnt;
 }
 
+static int
+enetc_clean_rx_ring_nc(struct enetc_bdr *rx_ring,
+		    struct rte_mbuf **rx_pkts,
+		    int work_limit)
+{
+	int rx_frm_cnt = 0;
+	int cleaned_cnt, i;
+	struct enetc_swbd *rx_swbd;
+	union enetc_rx_bd *rxbd, rxbd_temp;
+	uint32_t bd_status;
+	uint8_t *data;
+	uint32_t j;
+
+	/* next descriptor to process */
+	i = rx_ring->next_to_clean;
+	/* next descriptor to process */
+	rxbd = ENETC_RXBD(*rx_ring, i);
+
+	cleaned_cnt = enetc_bd_unused(rx_ring);
+	rx_swbd = &rx_ring->q_swbd[i];
+
+	while (likely(rx_frm_cnt < work_limit)) {
+#ifdef RTE_ARCH_32
+		rte_memcpy(&rxbd_temp, rxbd, 16);
+#else
+		__uint128_t *dst128 = (__uint128_t *)&rxbd_temp;
+		const __uint128_t *src128 = (const __uint128_t *)rxbd;
+		*dst128 = *src128;
+#endif
+		bd_status = rte_le_to_cpu_32(rxbd_temp.r.lstatus);
+		if (!bd_status)
+			break;
+		if (rxbd_temp.r.error)
+			rx_ring->ierrors++;
+
+		rx_swbd->buffer_addr->pkt_len = rxbd_temp.r.buf_len -
+						rx_ring->crc_len;
+		rx_swbd->buffer_addr->data_len = rx_swbd->buffer_addr->pkt_len;
+		rx_swbd->buffer_addr->hash.rss = rxbd_temp.r.rss_hash;
+		enetc_dev_rx_parse(rx_swbd->buffer_addr,
+				   rxbd_temp.r.parse_summary);
+
+		data = rte_pktmbuf_mtod(rx_swbd->buffer_addr, void *);
+		for (j = 0; j <= rx_swbd->buffer_addr->pkt_len; j += RTE_CACHE_LINE_SIZE)
+			dccivac(data + j);
+
+		rx_pkts[rx_frm_cnt] = rx_swbd->buffer_addr;
+		cleaned_cnt++;
+		rx_swbd++;
+		i++;
+		if (unlikely(i == rx_ring->bd_count)) {
+			i = 0;
+			rx_swbd = &rx_ring->q_swbd[i];
+		}
+		rxbd = ENETC_RXBD(*rx_ring, i);
+		rx_frm_cnt++;
+	}
+
+	rx_ring->next_to_clean = i;
+	enetc_refill_rx_ring(rx_ring, cleaned_cnt);
+
+	return rx_frm_cnt;
+}
+
+uint16_t
+enetc_recv_pkts_nc(void *rxq, struct rte_mbuf **rx_pkts,
+		uint16_t nb_pkts)
+{
+	struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
+
+	return enetc_clean_rx_ring_nc(rx_ring, rx_pkts, nb_pkts);
+}
+
 uint16_t
 enetc_recv_pkts(void *rxq, struct rte_mbuf **rx_pkts,
 		uint16_t nb_pkts)
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 04/12] net/enetc: Add TX checksum offload and RX checksum validation
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (2 preceding siblings ...)
  2024-10-18  7:26 ` [v1 03/12] net/enetc: Optimize ENETC4 data path vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 05/12] net/enetc: Add basic statistics vanshika.shukla
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla; +Cc: Apeksha Gupta

From: Vanshika Shukla <vanshika.shukla@nxp.com>

This patch add support for:

- L3 (IPv4, IPv6) TX checksum offload
- L4 (TCP, UDP) TX checksum offload
- RX checksum validation for IPv4, IPv6, TCP, UDP

Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |  2 ++
 drivers/net/enetc/base/enetc4_hw.h  | 14 ++++++++++
 drivers/net/enetc/base/enetc_hw.h   | 18 ++++++++++---
 drivers/net/enetc/enetc.h           |  5 ++++
 drivers/net/enetc/enetc4_ethdev.c   | 40 +++++++++++++++++++++++++++++
 drivers/net/enetc/enetc_rxtx.c      | 22 ++++++++++++++++
 6 files changed, 97 insertions(+), 4 deletions(-)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 37b548dcab..55b3b95953 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,8 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+L3 checksum offload  = Y
+L4 checksum offload  = Y
 Queue start/stop     = Y
 Linux                = Y
 ARMv8                = Y
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index 759cfaba28..114d27f34b 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -14,12 +14,26 @@
 #define ENETC4_DEV_ID_VF	0xef00
 #define PCI_VENDOR_ID_NXP	0x1131
 
+/* enetc4 txbd flags */
+#define ENETC4_TXBD_FLAGS_L4CS		BIT(0)
+#define ENETC4_TXBD_FLAGS_L_TX_CKSUM	BIT(3)
 #define ENETC4_TXBD_FLAGS_F		BIT(7)
+/* L4 type */
+#define ENETC4_TXBD_L4T_UDP		BIT(0)
+#define ENETC4_TXBD_L4T_TCP		BIT(1)
+/* L3 type is set to 0 for IPv4 and 1 for IPv6 */
+#define ENETC4_TXBD_L3T			0
+/* IPv4 checksum */
+#define ENETC4_TXBD_IPCS		1
 
 /***************************ENETC port registers**************************/
 #define ENETC4_PMR		0x10
 #define ENETC4_PMR_EN		(BIT(16) | BIT(17) | BIT(18))
 
+#define ENETC4_PARCSCR		0x9c
+#define L3_CKSUM		BIT(0)
+#define L4_CKSUM		BIT(1)
+
 /* Port Station interface promiscuous MAC mode register */
 #define ENETC4_PSIPMMR		0x200
 #define PSIPMMR_SI0_MAC_UP	BIT(0)
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 2d63c54db6..3cdfe23fc0 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -189,8 +189,7 @@ enum enetc_bdr_type {TX, RX};
 
 #define ENETC_TX_ADDR(txq, addr) ((void *)((txq)->enetc_txbdr + (addr)))
 
-#define ENETC_TXBD_FLAGS_IE		BIT(13)
-#define ENETC_TXBD_FLAGS_F		BIT(15)
+#define ENETC_TXBD_FLAGS_F		BIT(7)
 
 /* ENETC Parsed values (Little Endian) */
 #define ENETC_PARSE_ERROR		0x8000
@@ -249,8 +248,19 @@ struct enetc_tx_bd {
 	uint64_t addr;
 	uint16_t buf_len;
 	uint16_t frm_len;
-	uint16_t err_csum;
-	uint16_t flags;
+	union {
+		struct {
+			uint8_t l3_start:7;
+			uint8_t ipcs:1;
+			uint8_t l3_hdr_size:7;
+			uint8_t l3t:1;
+			uint8_t resv:5;
+			uint8_t l4t:3;
+			uint8_t flags;
+		};/* default layout */
+		uint32_t txstart;
+		uint32_t lstatus;
+	};
 };
 
 /* RX buffer descriptor */
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 79c158513c..c29353a89b 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -45,6 +45,11 @@
 #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]))
 
+#define ENETC4_MBUF_F_TX_IP_IPV4 (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_IPV4)
+#define ENETC4_TX_CKSUM_OFFLOAD_MASK (RTE_MBUF_F_TX_IP_CKSUM | \
+				    RTE_MBUF_F_TX_TCP_CKSUM | \
+				    RTE_MBUF_F_TX_UDP_CKSUM)
+
 struct enetc_swbd {
 	struct rte_mbuf *buffer_addr;
 };
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 290b90b9bc..02f048aa3c 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -11,6 +11,18 @@
 #include "enetc_logs.h"
 #include "enetc.h"
 
+/* Supported Rx offloads */
+static uint64_t dev_rx_offloads_sup =
+	RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
+	RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
+	RTE_ETH_RX_OFFLOAD_TCP_CKSUM;
+
+/* Supported Tx offloads */
+static uint64_t dev_tx_offloads_sup =
+	RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
+	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
+	RTE_ETH_TX_OFFLOAD_TCP_CKSUM;
+
 static int
 enetc4_dev_start(struct rte_eth_dev *dev)
 {
@@ -139,6 +151,8 @@ enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
 	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;
+	dev_info->rx_offload_capa = dev_rx_offloads_sup;
+	dev_info->tx_offload_capa = dev_tx_offloads_sup;
 
 	return 0;
 }
@@ -509,6 +523,10 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
 {
 	struct enetc_eth_hw *hw =
 		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_eth_conf *eth_conf = &dev->data->dev_conf;
+	uint64_t rx_offloads = eth_conf->rxmode.offloads;
+	uint64_t tx_offloads = eth_conf->txmode.offloads;
+	uint32_t checksum = L3_CKSUM | L4_CKSUM;
 	struct enetc_hw *enetc_hw = &hw->hw;
 	uint32_t max_len;
 	uint32_t val;
@@ -522,6 +540,28 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
 	val = ENETC4_MAC_MAXFRM_SIZE | SDU_TYPE_MPDU;
 	enetc4_port_wr(enetc_hw, ENETC4_PTCTMSDUR(0), val | SDU_TYPE_MPDU);
 
+	/* Rx offloads which are enabled by default */
+	if (dev_rx_offloads_sup & ~rx_offloads) {
+		ENETC_PMD_INFO("Some of rx offloads enabled by default"
+				" - requested 0x%" PRIx64 " fixed are 0x%" PRIx64,
+				rx_offloads, dev_rx_offloads_sup);
+	}
+
+	/* Tx offloads which are enabled by default */
+	if (dev_tx_offloads_sup & ~tx_offloads) {
+		ENETC_PMD_INFO("Some of tx offloads enabled by default"
+			       " - requested 0x%" PRIx64 " fixed are 0x%" PRIx64,
+			       tx_offloads, dev_tx_offloads_sup);
+	}
+
+	if (rx_offloads & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM)
+		checksum &= ~L3_CKSUM;
+
+	if (rx_offloads & (RTE_ETH_RX_OFFLOAD_UDP_CKSUM | RTE_ETH_RX_OFFLOAD_TCP_CKSUM))
+		checksum &= ~L4_CKSUM;
+
+	enetc4_port_wr(enetc_hw, ENETC4_PARCSCR, checksum);
+
 	return 0;
 }
 
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index d29b64ab56..963bd6fb31 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -124,6 +124,26 @@ enetc_xmit_pkts(void *tx_queue,
 	return start;
 }
 
+static void
+enetc4_tx_offload_checksum(struct rte_mbuf *mbuf, struct enetc_tx_bd *txbd)
+{
+	if ((mbuf->ol_flags & (RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_IPV4))
+						== ENETC4_MBUF_F_TX_IP_IPV4) {
+		txbd->l3t = ENETC4_TXBD_L3T;
+		txbd->ipcs = ENETC4_TXBD_IPCS;
+		txbd->l3_start = mbuf->l2_len;
+		txbd->l3_hdr_size = mbuf->l3_len / 4;
+		txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_L_TX_CKSUM);
+		if ((mbuf->ol_flags & RTE_MBUF_F_TX_UDP_CKSUM) == RTE_MBUF_F_TX_UDP_CKSUM) {
+			txbd->l4t = rte_cpu_to_le_16(ENETC4_TXBD_L4T_UDP);
+			txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_L4CS);
+		} else if ((mbuf->ol_flags & RTE_MBUF_F_TX_TCP_CKSUM) == RTE_MBUF_F_TX_TCP_CKSUM) {
+			txbd->l4t = rte_cpu_to_le_16(ENETC4_TXBD_L4T_TCP);
+			txbd->flags |= rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_L4CS);
+		}
+	}
+}
+
 uint16_t
 enetc_xmit_pkts_nc(void *tx_queue,
 		struct rte_mbuf **tx_pkts,
@@ -153,6 +173,8 @@ enetc_xmit_pkts_nc(void *tx_queue,
 
 		txbd = ENETC_TXBD(*tx_ring, i);
 		txbd->flags = rte_cpu_to_le_16(ENETC4_TXBD_FLAGS_F);
+		if (tx_ring->q_swbd[i].buffer_addr->ol_flags & ENETC4_TX_CKSUM_OFFLOAD_MASK)
+			enetc4_tx_offload_checksum(tx_ring->q_swbd[i].buffer_addr, txbd);
 
 		tx_swbd = &tx_ring->q_swbd[i];
 		txbd->frm_len = buflen;
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 05/12] net/enetc: Add basic statistics
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (3 preceding siblings ...)
  2024-10-18  7:26 ` [v1 04/12] net/enetc: Add TX checksum offload and RX checksum validation vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 06/12] net/enetc: Add packet type parsing support vanshika.shukla
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla; +Cc: Apeksha Gupta

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Introduces basic statistics collection for ENETC4 PMD, including:

- Packet transmit/receive counts
- Byte transmit/receive counts
- Error counters (TX/RX drops, errors)

Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |  1 +
 drivers/net/enetc/base/enetc4_hw.h  |  7 +++++
 drivers/net/enetc/base/enetc_hw.h   |  5 +++-
 drivers/net/enetc/enetc4_ethdev.c   | 42 +++++++++++++++++++++++++++++
 drivers/net/enetc/enetc4_vf.c       | 24 +++++++++++++++++
 5 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 55b3b95953..e814852d2d 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Basic stats          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Queue start/stop     = Y
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index 114d27f34b..874cdc4775 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -103,6 +103,13 @@
 #define IFMODE_SGMII			5
 #define PM_IF_MODE_ENA			BIT(15)
 
+/* Station interface statistics */
+#define ENETC4_SIROCT0           0x300
+#define ENETC4_SIRFRM0           0x308
+#define ENETC4_SITOCT0           0x320
+#define ENETC4_SITFRM0           0x328
+#define ENETC4_SITDFCR           0x340
+
 /* general register accessors */
 #define enetc4_rd_reg(reg)	rte_read32((void *)(reg))
 #define enetc4_wr_reg(reg, val)  rte_write32((val), (void *)(reg))
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 3cdfe23fc0..3208d91bc5 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -278,7 +278,10 @@ union enetc_rx_bd {
 		union {
 			struct {
 				uint16_t flags;
-				uint16_t error;
+				uint8_t error;
+				uint8_t resv:6;
+				uint8_t r:1;
+				uint8_t f:1;
 			};
 			uint32_t lstatus;
 		};
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 02f048aa3c..2db45ecf0c 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -484,6 +484,46 @@ enetc4_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
 	rte_free(rx_ring);
 }
 
+static
+int enetc4_stats_get(struct rte_eth_dev *dev,
+		    struct rte_eth_stats *stats)
+{
+	struct enetc_eth_hw *hw =
+		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+
+	/*
+	 * Total received packets, bad + good, if we want to get counters
+	 * of only good received packets then use ENETC4_PM_RFRM,
+	 * ENETC4_PM_TFRM registers.
+	 */
+	stats->ipackets = enetc4_port_rd(enetc_hw, ENETC4_PM_RPKT(0));
+	stats->opackets = enetc4_port_rd(enetc_hw, ENETC4_PM_TPKT(0));
+	stats->ibytes =  enetc4_port_rd(enetc_hw, ENETC4_PM_REOCT(0));
+	stats->obytes = enetc4_port_rd(enetc_hw, ENETC4_PM_TEOCT(0));
+	/*
+	 * Dropped + Truncated packets, use ENETC4_PM_RDRNTP(0) for without
+	 * truncated packets
+	 */
+	stats->imissed = enetc4_port_rd(enetc_hw, ENETC4_PM_RDRP(0));
+	stats->ierrors = enetc4_port_rd(enetc_hw, ENETC4_PM_RERR(0));
+	stats->oerrors = enetc4_port_rd(enetc_hw, ENETC4_PM_TERR(0));
+
+	return 0;
+}
+
+static int
+enetc4_stats_reset(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;
+
+	enetc4_port_wr(enetc_hw, ENETC4_PM0_STAT_CONFIG, ENETC4_CLEAR_STATS);
+
+	return 0;
+}
+
 int
 enetc4_dev_close(struct rte_eth_dev *dev)
 {
@@ -668,6 +708,8 @@ static const struct eth_dev_ops enetc4_ops = {
 	.dev_stop             = enetc4_dev_stop,
 	.dev_close            = enetc4_dev_close,
 	.dev_infos_get        = enetc4_dev_infos_get,
+	.stats_get            = enetc4_stats_get,
+	.stats_reset          = enetc4_stats_reset,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,
 	.rx_queue_stop        = enetc4_rx_queue_stop,
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 0c68229a8d..0d35fc2e1c 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -26,6 +26,29 @@ enetc4_vf_dev_start(struct rte_eth_dev *dev __rte_unused)
 	return 0;
 }
 
+static int
+enetc4_vf_stats_get(struct rte_eth_dev *dev,
+		    struct rte_eth_stats *stats)
+{
+	struct enetc_eth_hw *hw =
+		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_bdr *rx_ring;
+	uint8_t i;
+
+	PMD_INIT_FUNC_TRACE();
+	stats->ipackets = enetc4_rd(enetc_hw, ENETC4_SIRFRM0);
+	stats->opackets = enetc4_rd(enetc_hw, ENETC4_SITFRM0);
+	stats->ibytes = enetc4_rd(enetc_hw, ENETC4_SIROCT0);
+	stats->obytes = enetc4_rd(enetc_hw, ENETC4_SITOCT0);
+	stats->oerrors = enetc4_rd(enetc_hw, ENETC4_SITDFCR);
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		rx_ring = dev->data->rx_queues[i];
+		stats->ierrors += rx_ring->ierrors;
+	}
+	return 0;
+}
+
 /*
  * The set of PCI devices this driver supports
  */
@@ -41,6 +64,7 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.dev_stop             = enetc4_vf_dev_stop,
 	.dev_close            = enetc4_dev_close,
 	.dev_infos_get        = enetc4_dev_infos_get,
+	.stats_get            = enetc4_vf_stats_get,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,
 	.rx_queue_stop        = enetc4_rx_queue_stop,
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 06/12] net/enetc: Add packet type parsing support
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (4 preceding siblings ...)
  2024-10-18  7:26 ` [v1 05/12] net/enetc: Add basic statistics vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 07/12] net/enetc: Add support for multiple queues with RSS vanshika.shukla
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla; +Cc: Apeksha Gupta

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Introduces packet type parsing for ENETC4 PMD, supporting:

- RTE_PTYPE_L2_ETHER (Ethernet II)
- RTE_PTYPE_L3_IPV4 (IPv4)
- RTE_PTYPE_L3_IPV6 (IPv6)
- RTE_PTYPE_L4_TCP (TCP)
- RTE_PTYPE_L4_UDP (UDP)
- RTE_PTYPE_L4_SCTP (SCTP)
- RTE_PTYPE_L4_ICMP (ICMP)
- RTE_PTYPE_L4_FRAG (IPv4/IPv6 fragmentation)
- RTE_PTYPE_TUNNEL_ESP (ESP tunneling)

Signed-off-by: Apeksha Gupta <apeksha.gupta@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |  1 +
 drivers/net/enetc/base/enetc_hw.h   |  5 +++++
 drivers/net/enetc/enetc.h           |  2 ++
 drivers/net/enetc/enetc4_ethdev.c   | 23 +++++++++++++++++++++++
 drivers/net/enetc/enetc4_vf.c       |  1 +
 drivers/net/enetc/enetc_rxtx.c      | 10 ++++++++++
 6 files changed, 42 insertions(+)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index e814852d2d..3356475317 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Packet type parsing  = Y
 Basic stats          = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 3208d91bc5..10bd3c050c 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -196,6 +196,7 @@ enum enetc_bdr_type {TX, RX};
 #define ENETC_PKT_TYPE_ETHER            0x0060
 #define ENETC_PKT_TYPE_IPV4             0x0000
 #define ENETC_PKT_TYPE_IPV6             0x0020
+#define ENETC_PKT_TYPE_IPV6_EXT         0x0080
 #define ENETC_PKT_TYPE_IPV4_TCP \
 			(0x0010 | ENETC_PKT_TYPE_IPV4)
 #define ENETC_PKT_TYPE_IPV6_TCP \
@@ -208,6 +209,10 @@ enum enetc_bdr_type {TX, RX};
 			(0x0013 | ENETC_PKT_TYPE_IPV4)
 #define ENETC_PKT_TYPE_IPV6_SCTP \
 			(0x0013 | ENETC_PKT_TYPE_IPV6)
+#define ENETC_PKT_TYPE_IPV4_FRAG \
+			(0x0001 | ENETC_PKT_TYPE_IPV4)
+#define ENETC_PKT_TYPE_IPV6_FRAG \
+			(0x0001 | ENETC_PKT_TYPE_IPV6_EXT | ENETC_PKT_TYPE_IPV6)
 #define ENETC_PKT_TYPE_IPV4_ICMP \
 			(0x0003 | ENETC_PKT_TYPE_IPV4)
 #define ENETC_PKT_TYPE_IPV6_ICMP \
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index c29353a89b..8d4e432426 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -117,6 +117,8 @@ int enetc4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 int enetc4_tx_queue_start(struct rte_eth_dev *dev, uint16_t qidx);
 int enetc4_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx);
 void enetc4_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
+const uint32_t *enetc4_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+			size_t *no_of_elements);
 
 /*
  * enetc4_vf function prototype
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 2db45ecf0c..a57408fbe9 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -693,6 +693,28 @@ enetc4_tx_queue_stop(struct rte_eth_dev *dev, uint16_t qidx)
 	return 0;
 }
 
+const uint32_t *
+enetc4_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused,
+			    size_t *no_of_elements)
+{
+	PMD_INIT_FUNC_TRACE();
+	static const uint32_t ptypes[] = {
+		RTE_PTYPE_L2_ETHER,
+		RTE_PTYPE_L3_IPV4,
+		RTE_PTYPE_L3_IPV6,
+		RTE_PTYPE_L4_TCP,
+		RTE_PTYPE_L4_UDP,
+		RTE_PTYPE_L4_SCTP,
+		RTE_PTYPE_L4_ICMP,
+		RTE_PTYPE_L4_FRAG,
+		RTE_PTYPE_TUNNEL_ESP,
+		RTE_PTYPE_UNKNOWN
+	};
+
+	*no_of_elements = RTE_DIM(ptypes);
+	return ptypes;
+}
+
 /*
  * The set of PCI devices this driver supports
  */
@@ -718,6 +740,7 @@ static const struct eth_dev_ops enetc4_ops = {
 	.tx_queue_start       = enetc4_tx_queue_start,
 	.tx_queue_stop        = enetc4_tx_queue_stop,
 	.tx_queue_release     = enetc4_tx_queue_release,
+	.dev_supported_ptypes_get = enetc4_supported_ptypes_get,
 };
 
 /*
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 0d35fc2e1c..360bb0c710 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -73,6 +73,7 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.tx_queue_start       = enetc4_tx_queue_start,
 	.tx_queue_stop        = enetc4_tx_queue_stop,
 	.tx_queue_release     = enetc4_tx_queue_release,
+	.dev_supported_ptypes_get = enetc4_supported_ptypes_get,
 };
 
 static int
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index 963bd6fb31..65c79e508f 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -389,6 +389,16 @@ enetc_dev_rx_parse(struct rte_mbuf *m, uint16_t parse_results)
 				 RTE_PTYPE_L3_IPV6 |
 				 RTE_PTYPE_L4_ICMP;
 		return;
+	case ENETC_PKT_TYPE_IPV4_FRAG:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV4 |
+				 RTE_PTYPE_L4_FRAG;
+		return;
+	case ENETC_PKT_TYPE_IPV6_FRAG:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV6 |
+				 RTE_PTYPE_L4_FRAG;
+		return;
 	/* More switch cases can be added */
 	default:
 		enetc_slow_parsing(m, parse_results);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 07/12] net/enetc: Add support for multiple queues with RSS
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (5 preceding siblings ...)
  2024-10-18  7:26 ` [v1 06/12] net/enetc: Add packet type parsing support vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 08/12] net/enetc: Add VF to PF messaging support and primary MAC setup vanshika.shukla
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Introduces support for multiple transmit and receive queues in ENETC4
PMD, enabling scalable packet processing, improved throughput, and
latency. Packet distribution is handled through Receive Side Scaling
(RSS).

Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |   1 +
 drivers/net/enetc/base/enetc4_hw.h  |  11 +
 drivers/net/enetc/base/enetc_hw.h   |  21 +-
 drivers/net/enetc/enetc.h           |  37 +++-
 drivers/net/enetc/enetc4_ethdev.c   | 145 +++++++++++--
 drivers/net/enetc/enetc4_vf.c       |  10 +-
 drivers/net/enetc/enetc_cbdr.c      | 311 ++++++++++++++++++++++++++++
 drivers/net/enetc/meson.build       |   5 +-
 drivers/net/enetc/ntmp.h            | 110 ++++++++++
 9 files changed, 617 insertions(+), 34 deletions(-)
 create mode 100644 drivers/net/enetc/enetc_cbdr.c
 create mode 100644 drivers/net/enetc/ntmp.h

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 3356475317..79430d0018 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+RSS hash             = Y
 Packet type parsing  = Y
 Basic stats          = Y
 L3 checksum offload  = Y
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index 874cdc4775..49446f2cb4 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -110,6 +110,17 @@
 #define ENETC4_SITFRM0           0x328
 #define ENETC4_SITDFCR           0x340
 
+/* Control BDR regs */
+#define ENETC4_SICBDRMR		0x800
+#define ENETC4_SICBDRSR		0x804   /* RO */
+#define ENETC4_SICBDRBAR0	0x810
+#define ENETC4_SICBDRBAR1	0x814
+#define ENETC4_SICBDRPIR	0x818
+#define ENETC4_SICBDRCIR	0x81c
+#define ENETC4_SICBDRLENR	0x820
+#define ENETC4_SICTR0		0x18
+#define ENETC4_SICTR1		0x1c
+
 /* general register accessors */
 #define enetc4_rd_reg(reg)	rte_read32((void *)(reg))
 #define enetc4_wr_reg(reg, val)  rte_write32((val), (void *)(reg))
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 10bd3c050c..3cb56cd851 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -22,6 +22,10 @@
 /* SI regs, offset: 0h */
 #define ENETC_SIMR			0x0
 #define ENETC_SIMR_EN			BIT(31)
+#define ENETC_SIMR_RSSE			BIT(0)
+
+/* BDR grouping*/
+#define ENETC_SIRBGCR			0x38
 
 #define ENETC_SICAR0			0x40
 #define ENETC_SICAR0_COHERENT		0x2B2B6727
@@ -29,6 +33,7 @@
 #define ENETC_SIPMAR1			0x84
 
 #define ENETC_SICAPR0			0x900
+#define ENETC_SICAPR0_BDR_MASK		0xFF
 #define ENETC_SICAPR1			0x904
 
 #define ENETC_SIMSITRV(n)		(0xB00 + (n) * 0x4)
@@ -36,6 +41,11 @@
 
 #define ENETC_SICCAPR			0x1200
 
+#define ENETC_SIPCAPR0			0x20
+#define ENETC_SIPCAPR0_RSS		BIT(8)
+#define ENETC_SIRSSCAPR			0x1600
+#define ENETC_SIRSSCAPR_GET_NUM_RSS(val) (BIT((val) & 0xf) * 32)
+
 /* enum for BD type */
 enum enetc_bdr_type {TX, RX};
 
@@ -44,6 +54,7 @@ enum enetc_bdr_type {TX, RX};
 /* RX BDR reg offsets */
 #define ENETC_RBMR		0x0 /* RX BDR mode register*/
 #define ENETC_RBMR_EN		BIT(31)
+#define ENETC_BMR_RESET		0x0 /* BDR reset*/
 
 #define ENETC_RBSR		0x4  /* Rx BDR status register*/
 #define ENETC_RBBSR		0x8  /* Rx BDR buffer size register*/
@@ -231,15 +242,6 @@ struct enetc_eth_mac_info {
 	uint8_t get_link_status;
 };
 
-struct enetc_eth_hw {
-	struct rte_eth_dev *ndev;
-	struct enetc_hw hw;
-	uint16_t device_id;
-	uint16_t vendor_id;
-	uint8_t revision_id;
-	struct enetc_eth_mac_info mac;
-};
-
 /* Transmit Descriptor */
 struct enetc_tx_desc {
 	uint64_t addr;
@@ -292,5 +294,4 @@ union enetc_rx_bd {
 		};
 	} r;
 };
-
 #endif
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 8d4e432426..354cd761d7 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -10,7 +10,9 @@
 
 #include "compat.h"
 #include "base/enetc_hw.h"
+#include "base/enetc4_hw.h"
 #include "enetc_logs.h"
+#include "ntmp.h"
 
 #define PCI_VENDOR_ID_FREESCALE 0x1957
 
@@ -50,6 +52,18 @@
 				    RTE_MBUF_F_TX_TCP_CKSUM | \
 				    RTE_MBUF_F_TX_UDP_CKSUM)
 
+#define ENETC_CBD(R, i)	(&(((struct enetc_cbd *)((R).bd_base))[i]))
+#define ENETC_CBDR_TIMEOUT	1000 /* In multiple of ENETC_CBDR_DELAY */
+#define ENETC_CBDR_DELAY	100 /* usecs */
+#define ENETC_CBDR_SIZE		64
+#define ENETC_CBDR_ALIGN	128
+
+/* supported RSS */
+#define ENETC_RSS_OFFLOAD_ALL ( \
+	RTE_ETH_RSS_IP | \
+	RTE_ETH_RSS_UDP | \
+	RTE_ETH_RSS_TCP)
+
 struct enetc_swbd {
 	struct rte_mbuf *buffer_addr;
 };
@@ -76,6 +90,19 @@ struct enetc_bdr {
 	uint64_t ierrors;
 };
 
+struct enetc_eth_hw {
+	struct rte_eth_dev *ndev;
+	struct enetc_hw hw;
+	uint16_t device_id;
+	uint16_t vendor_id;
+	uint8_t revision_id;
+	struct enetc_eth_mac_info mac;
+	struct netc_cbdr cbdr;
+	uint32_t num_rss;
+	uint32_t max_rx_queues;
+	uint32_t max_tx_queues;
+};
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
@@ -102,7 +129,7 @@ struct enetc_eth_adapter {
 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,
+int enetc4_dev_infos_get(struct rte_eth_dev *dev,
 			 struct rte_eth_dev_info *dev_info);
 int enetc4_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
 			  uint16_t nb_rx_desc, unsigned int socket_id __rte_unused,
@@ -149,4 +176,12 @@ enetc_bd_unused(struct enetc_bdr *bdr)
 
 	return bdr->bd_count + bdr->next_to_clean - bdr->next_to_use - 1;
 }
+
+/* CBDR prototypes */
+int enetc4_setup_cbdr(struct rte_eth_dev *dev, struct enetc_hw *hw,
+			int bd_count, struct netc_cbdr *cbdr);
+void netc_free_cbdr(struct netc_cbdr *cbdr);
+int ntmp_rsst_query_or_update_entry(struct netc_cbdr *cbdr, uint32_t *table,
+			int count, bool query);
+
 #endif /* _ENETC_H_ */
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index a57408fbe9..075205a0e5 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -7,7 +7,6 @@
 #include <dpaax_iova_table.h>
 
 #include "kpage_ncache_api.h"
-#include "base/enetc4_hw.h"
 #include "enetc_logs.h"
 #include "enetc.h"
 
@@ -134,10 +133,14 @@ enetc4_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
 }
 
 int
-enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
+enetc4_dev_infos_get(struct rte_eth_dev *dev,
 		    struct rte_eth_dev_info *dev_info)
 {
+	struct enetc_eth_hw *hw =
+		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
 	PMD_INIT_FUNC_TRACE();
+
 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = MAX_BD_COUNT,
 		.nb_min = MIN_BD_COUNT,
@@ -148,11 +151,12 @@ enetc4_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
 		.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_queues = hw->max_rx_queues;
+	dev_info->max_tx_queues = hw->max_tx_queues;
 	dev_info->max_rx_pktlen = ENETC4_MAC_MAXFRM_SIZE;
 	dev_info->rx_offload_capa = dev_rx_offloads_sup;
 	dev_info->tx_offload_capa = dev_tx_offloads_sup;
+	dev_info->flow_type_rss_offloads = ENETC_RSS_OFFLOAD_ALL;
 
 	return 0;
 }
@@ -178,6 +182,11 @@ mark_memory_ncache(struct enetc_bdr *bdr, const char *mz_name, unsigned int size
 				mz->hugepage_sz);
 	bdr->mz = mz;
 
+	/* Double check memzone alignment and hugepage size */
+	if (!rte_is_aligned(bdr->bd_base, size))
+		ENETC_PMD_WARN("Memzone is not aligned to %x", size);
+
+	ENETC_PMD_DEBUG("Ring Hugepage start address = %p", bdr->bd_base);
 	/* Mark memory NON-CACHEABLE */
 	huge_page =
 		(uint64_t)RTE_PTR_ALIGN_FLOOR(bdr->bd_base, size);
@@ -197,7 +206,7 @@ enetc4_alloc_txbdr(uint16_t port_id, struct enetc_bdr *txr, uint16_t nb_desc)
 	if (txr->q_swbd == NULL)
 		return -ENOMEM;
 
-	snprintf(mz_name, sizeof(mz_name), "bdt_addr_%d", port_id);
+	snprintf(mz_name, sizeof(mz_name), "bdt_addr_%d_%d", port_id, txr->index);
 	if (mark_memory_ncache(txr, mz_name, SIZE_2MB)) {
 		ENETC_PMD_ERR("Failed to mark BD memory non-cacheable!");
 		rte_free(txr->q_swbd);
@@ -298,17 +307,20 @@ void
 enetc4_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
 {
 	void *txq = dev->data->tx_queues[qid];
+	struct enetc_hw *hw;
+	struct enetc_swbd *tx_swbd;
+	int i;
+	uint32_t val;
+	struct enetc_bdr *tx_ring;
+	struct enetc_eth_hw *eth_hw;
 
+	PMD_INIT_FUNC_TRACE();
 	if (txq == NULL)
 		return;
 
-	struct enetc_bdr *tx_ring = (struct enetc_bdr *)txq;
-	struct enetc_eth_hw *eth_hw =
+	tx_ring = (struct enetc_bdr *)txq;
+	eth_hw =
 		ENETC_DEV_PRIVATE_TO_HW(tx_ring->ndev->data->dev_private);
-	struct enetc_hw *hw;
-	struct enetc_swbd *tx_swbd;
-	int i;
-	uint32_t val;
 
 	/* Disable the ring */
 	hw = &eth_hw->hw;
@@ -346,7 +358,7 @@ enetc4_alloc_rxbdr(uint16_t port_id, struct enetc_bdr *rxr,
 	if (rxr->q_swbd == NULL)
 		return -ENOMEM;
 
-	snprintf(mz_name, sizeof(mz_name), "bdr_addr_%d", port_id);
+	snprintf(mz_name, sizeof(mz_name), "bdr_addr_%d_%d", port_id, rxr->index);
 	if (mark_memory_ncache(rxr, mz_name, SIZE_2MB)) {
 		ENETC_PMD_ERR("Failed to mark BD memory non-cacheable!");
 		rte_free(rxr->q_swbd);
@@ -448,17 +460,20 @@ void
 enetc4_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
 {
 	void *rxq = dev->data->rx_queues[qid];
+	struct enetc_swbd *q_swbd;
+	struct enetc_hw *hw;
+	uint32_t val;
+	int i;
+	struct enetc_bdr *rx_ring;
+	struct enetc_eth_hw *eth_hw;
 
+	PMD_INIT_FUNC_TRACE();
 	if (rxq == NULL)
 		return;
 
-	struct enetc_bdr *rx_ring = (struct enetc_bdr *)rxq;
-	struct enetc_eth_hw *eth_hw =
+	rx_ring = (struct enetc_bdr *)rxq;
+	eth_hw =
 		ENETC_DEV_PRIVATE_TO_HW(rx_ring->ndev->data->dev_private);
-	struct enetc_swbd *q_swbd;
-	struct enetc_hw *hw;
-	uint32_t val;
-	int i;
 
 	/* Disable the ring */
 	hw = &eth_hw->hw;
@@ -524,10 +539,22 @@ enetc4_stats_reset(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static void
+enetc4_rss_configure(struct enetc_hw *hw, int enable)
+{
+	uint32_t reg;
+
+	reg = enetc4_rd(hw, ENETC_SIMR);
+	reg &= ~ENETC_SIMR_RSSE;
+	reg |= (enable) ? ENETC_SIMR_RSSE : 0;
+	enetc4_wr(hw, ENETC_SIMR, reg);
+}
+
 int
 enetc4_dev_close(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;
 	uint16_t i;
 	int ret;
 
@@ -540,6 +567,13 @@ enetc4_dev_close(struct rte_eth_dev *dev)
 	else
 		ret = enetc4_dev_stop(dev);
 
+	if (dev->data->nb_rx_queues > 1) {
+		/* Disable RSS */
+		enetc4_rss_configure(enetc_hw, false);
+		/* Free CBDR */
+		netc_free_cbdr(&hw->cbdr);
+	}
+
 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		enetc4_rx_queue_release(dev, i);
 		dev->data->rx_queues[i] = NULL;
@@ -569,7 +603,9 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
 	uint32_t checksum = L3_CKSUM | L4_CKSUM;
 	struct enetc_hw *enetc_hw = &hw->hw;
 	uint32_t max_len;
-	uint32_t val;
+	uint32_t val, num_rss;
+	uint32_t ret = 0, i;
+	uint32_t *rss_table;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -602,6 +638,69 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
 
 	enetc4_port_wr(enetc_hw, ENETC4_PARCSCR, checksum);
 
+	/* Disable and reset RX and TX rings */
+	for (i = 0; i < dev->data->nb_rx_queues; i++)
+		enetc4_rxbdr_wr(enetc_hw, i, ENETC_RBMR, ENETC_BMR_RESET);
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++)
+		enetc4_rxbdr_wr(enetc_hw, i, ENETC_TBMR, ENETC_BMR_RESET);
+
+	if (dev->data->nb_rx_queues <= 1)
+		return 0;
+
+	/* Setup RSS */
+	/* Setup control BDR */
+	ret = enetc4_setup_cbdr(dev, enetc_hw, ENETC_CBDR_SIZE, &hw->cbdr);
+	if (ret) {
+		/* Disable RSS */
+		enetc4_rss_configure(enetc_hw, false);
+		return ret;
+	}
+
+	/* Reset CIR again after enable CBDR*/
+	rte_delay_us(ENETC_CBDR_DELAY);
+	ENETC_PMD_DEBUG("CIR %x after CBDR enable", rte_read32(hw->cbdr.regs.cir));
+	rte_write32(0, hw->cbdr.regs.cir);
+	ENETC_PMD_DEBUG("CIR %x after reset", rte_read32(hw->cbdr.regs.cir));
+
+	val = enetc_rd(enetc_hw, ENETC_SIPCAPR0);
+	if (val & ENETC_SIPCAPR0_RSS) {
+		num_rss = enetc_rd(enetc_hw, ENETC_SIRSSCAPR);
+		hw->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(num_rss);
+		ENETC_PMD_DEBUG("num_rss = %d", hw->num_rss);
+
+		/* Add number of BDR groups */
+		enetc4_wr(enetc_hw, ENETC_SIRBGCR, dev->data->nb_rx_queues);
+
+
+		/* Configuring indirecton table with default values
+		 * Hash algorithm and RSS secret key to be filled by PF
+		 */
+		rss_table = rte_malloc(NULL, hw->num_rss * sizeof(*rss_table), ENETC_CBDR_ALIGN);
+		if (!rss_table) {
+			enetc4_rss_configure(enetc_hw, false);
+			netc_free_cbdr(&hw->cbdr);
+			return -ENOMEM;
+		}
+
+		ENETC_PMD_DEBUG("Enabling RSS for port %s with queues = %d", dev->device->name,
+							dev->data->nb_rx_queues);
+		for (i = 0; i < hw->num_rss; i++)
+			rss_table[i] = i % dev->data->nb_rx_queues;
+
+		ret = ntmp_rsst_query_or_update_entry(&hw->cbdr, rss_table, hw->num_rss, false);
+		if (ret) {
+			ENETC_PMD_WARN("RSS indirection table update fails,"
+					"Scaling behaviour is undefined");
+			enetc4_rss_configure(enetc_hw, false);
+			netc_free_cbdr(&hw->cbdr);
+		}
+		rte_free(rss_table);
+
+		/* Enable RSS */
+		enetc4_rss_configure(enetc_hw, true);
+	}
+
 	return 0;
 }
 
@@ -786,11 +885,19 @@ enetc4_dev_init(struct rte_eth_dev *eth_dev)
 		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;
+	uint32_t si_cap;
+	struct enetc_hw *enetc_hw = &hw->hw;
 
 	PMD_INIT_FUNC_TRACE();
 	eth_dev->dev_ops = &enetc4_ops;
 	enetc4_dev_hw_init(eth_dev);
 
+	si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0);
+	hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK;
+	hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK;
+
+	ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d",
+			hw->max_rx_queues, hw->max_tx_queues);
 	error = enetc4_mac_init(hw, eth_dev);
 	if (error != 0) {
 		ENETC_PMD_ERR("MAC initialization failed");
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 360bb0c710..a9fb33c432 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -5,8 +5,6 @@
 #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"
 
@@ -137,11 +135,19 @@ enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
 			    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;
+	uint32_t si_cap;
+	struct enetc_hw *enetc_hw = &hw->hw;
 
 	PMD_INIT_FUNC_TRACE();
 	eth_dev->dev_ops = &enetc4_vf_ops;
 	enetc4_dev_hw_init(eth_dev);
 
+	si_cap = enetc_rd(enetc_hw, ENETC_SICAPR0);
+	hw->max_tx_queues = si_cap & ENETC_SICAPR0_BDR_MASK;
+	hw->max_rx_queues = (si_cap >> 16) & ENETC_SICAPR0_BDR_MASK;
+
+	ENETC_PMD_DEBUG("Max RX queues = %d Max TX queues = %d",
+			hw->max_rx_queues, hw->max_tx_queues);
 	error = enetc4_vf_mac_init(hw, eth_dev);
 	if (error != 0) {
 		ENETC_PMD_ERR("MAC initialization failed!!");
diff --git a/drivers/net/enetc/enetc_cbdr.c b/drivers/net/enetc/enetc_cbdr.c
new file mode 100644
index 0000000000..021090775f
--- /dev/null
+++ b/drivers/net/enetc/enetc_cbdr.c
@@ -0,0 +1,311 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 NXP
+ */
+
+#include <ethdev_pci.h>
+
+#include "enetc_logs.h"
+#include "enetc.h"
+
+#define NTMP_RSST_ID                    3
+
+/* Define NTMP Access Method */
+#define NTMP_AM_ENTRY_ID                0
+#define NTMP_AM_EXACT_KEY               1
+#define NTMP_AM_SEARCH                  2
+#define NTMP_AM_TERNARY_KEY             3
+
+/* Define NTMP Header Version */
+#define NTMP_HEADER_VERSION2            2
+
+#define NTMP_REQ_HDR_NPF                BIT(15)
+
+#define NTMP_RESP_LEN_MASK              GENMASK(19, 0)
+#define NTMP_REQ_LEN_MASK               GENMASK(31, 20)
+
+#define ENETC_NTMP_ENTRY_ID_SIZE        4
+
+#define ENETC_RSS_TABLE_ENTRY_NUM       64
+#define ENETC_RSS_CFGEU                 BIT(0)
+#define ENETC_RSS_STSEU                 BIT(1)
+#define ENETC_RSS_STSE_DATA_SIZE(n)     ((n) * 8)
+#define ENETC_RSS_CFGE_DATA_SIZE(n)     (n)
+
+#define NTMP_REQ_RESP_LEN(req, resp)    (((req) << 20 & NTMP_REQ_LEN_MASK) | \
+					((resp) & NTMP_RESP_LEN_MASK))
+
+static inline uint32_t
+netc_cbdr_read(void *reg)
+{
+	return rte_read32(reg);
+}
+
+static inline void
+netc_cbdr_write(void *reg, uint32_t val)
+{
+	rte_write32(val, reg);
+}
+
+static inline void
+ntmp_fill_request_headr(union netc_cbd *cbd, dma_addr_t dma,
+			int len, int table_id, int cmd,
+			int access_method)
+{
+	dma_addr_t dma_align;
+
+	memset(cbd, 0, sizeof(*cbd));
+	dma_align = dma;
+	cbd->ntmp_req_hdr.addr = dma_align;
+	cbd->ntmp_req_hdr.len = len;
+	cbd->ntmp_req_hdr.cmd = cmd;
+	cbd->ntmp_req_hdr.access_method = access_method;
+	cbd->ntmp_req_hdr.table_id = table_id;
+	cbd->ntmp_req_hdr.hdr_ver = NTMP_HEADER_VERSION2;
+	cbd->ntmp_req_hdr.cci = 0;
+	cbd->ntmp_req_hdr.rr = 0;       /* Must be set to 0 by SW. */
+	/* For NTMP version 2.0 or later version */
+	cbd->ntmp_req_hdr.npf = NTMP_REQ_HDR_NPF;
+}
+
+static inline int
+netc_get_free_cbd_num(struct netc_cbdr *cbdr)
+{
+	return (cbdr->next_to_clean - cbdr->next_to_use - 1 + cbdr->bd_num) %
+		cbdr->bd_num;
+}
+
+static inline union
+netc_cbd *netc_get_cbd(struct netc_cbdr *cbdr, int index)
+{
+	return &((union netc_cbd *)(cbdr->addr_base_align))[index];
+}
+
+static void
+netc_clean_cbdr(struct netc_cbdr *cbdr)
+{
+	union netc_cbd *cbd;
+	uint32_t i;
+
+	i = cbdr->next_to_clean;
+	while (netc_cbdr_read(cbdr->regs.cir) != i) {
+		cbd = netc_get_cbd(cbdr, i);
+		memset(cbd, 0, sizeof(*cbd));
+		dcbf(cbd);
+		i = (i + 1) % cbdr->bd_num;
+	}
+
+	cbdr->next_to_clean = i;
+}
+
+static int
+netc_xmit_ntmp_cmd(struct netc_cbdr *cbdr, union netc_cbd *cbd)
+{
+	union netc_cbd *ring_cbd;
+	uint32_t i, err = 0;
+	uint16_t status;
+	uint32_t timeout = cbdr->timeout;
+	uint32_t delay = cbdr->delay;
+
+	if (unlikely(!cbdr->addr_base))
+		return -EFAULT;
+
+	rte_spinlock_lock(&cbdr->ring_lock);
+
+	if (unlikely(!netc_get_free_cbd_num(cbdr)))
+		netc_clean_cbdr(cbdr);
+
+	i = cbdr->next_to_use;
+	ring_cbd = netc_get_cbd(cbdr, i);
+
+	/* Copy command BD to the ring */
+	*ring_cbd = *cbd;
+	/* Update producer index of both software and hardware */
+	i = (i + 1) % cbdr->bd_num;
+	dcbf(ring_cbd);
+	cbdr->next_to_use = i;
+	netc_cbdr_write(cbdr->regs.pir, i);
+	ENETC_PMD_DEBUG("Control msg sent PIR = %d, CIR = %d", netc_cbdr_read(cbdr->regs.pir),
+					netc_cbdr_read(cbdr->regs.cir));
+	do {
+		if (netc_cbdr_read(cbdr->regs.cir) == i) {
+			dccivac(ring_cbd);
+			ENETC_PMD_DEBUG("got response");
+			ENETC_PMD_DEBUG("Matched = %d, status = 0x%x",
+					ring_cbd->ntmp_resp_hdr.num_matched,
+					ring_cbd->ntmp_resp_hdr.error_rr);
+			break;
+		}
+		rte_delay_us(delay);
+	} while (timeout--);
+
+	if (timeout <= 0)
+		ENETC_PMD_ERR("no response of RSS configuration");
+
+	ENETC_PMD_DEBUG("CIR after receive = %d, SICBDRSR = 0x%x",
+					netc_cbdr_read(cbdr->regs.cir),
+					netc_cbdr_read(cbdr->regs.st));
+	/* Check the writeback error status */
+	status = ring_cbd->ntmp_resp_hdr.error_rr & NTMP_RESP_HDR_ERR;
+	if (unlikely(status)) {
+		ENETC_PMD_ERR("Command BD error: 0x%04x", status);
+		err = -EIO;
+	}
+
+	netc_clean_cbdr(cbdr);
+	rte_spinlock_unlock(&cbdr->ring_lock);
+
+	return err;
+}
+
+int
+ntmp_rsst_query_or_update_entry(struct netc_cbdr *cbdr, uint32_t *table,
+				int count, bool query)
+{
+	struct rsst_req_update *requ;
+	struct rsst_req_query *req;
+	union netc_cbd cbd;
+	uint32_t len, data_size;
+	dma_addr_t dma;
+	int err, i;
+	void *tmp;
+
+	if (count != ENETC_RSS_TABLE_ENTRY_NUM)
+		/* HW only takes in a full 64 entry table */
+		return -EINVAL;
+
+	if (query)
+		data_size = ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count) +
+			ENETC_RSS_CFGE_DATA_SIZE(count);
+	else
+		data_size = sizeof(*requ) + count * sizeof(uint8_t);
+
+	tmp = rte_malloc(NULL, data_size, ENETC_CBDR_ALIGN);
+	if (!tmp)
+		return -ENOMEM;
+
+	dma = rte_mem_virt2iova(tmp);
+	req = tmp;
+	/* Set the request data buffer */
+	if (query) {
+		len = NTMP_REQ_RESP_LEN(sizeof(*req), data_size);
+		ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID,
+					NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
+	} else {
+		requ = (struct rsst_req_update *)req;
+		requ->crd.update_act = (ENETC_RSS_CFGEU | ENETC_RSS_STSEU);
+		for (i = 0; i < count; i++)
+			requ->groups[i] = (uint8_t)(table[i]);
+
+		len = NTMP_REQ_RESP_LEN(data_size, 0);
+		ntmp_fill_request_headr(&cbd, dma, len, NTMP_RSST_ID,
+				NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
+		dcbf(requ);
+	}
+
+	err = netc_xmit_ntmp_cmd(cbdr, &cbd);
+	if (err) {
+		ENETC_PMD_ERR("%s RSS table entry failed (%d)!",
+				query ? "Query" : "Update", err);
+		goto end;
+	}
+
+	if (query) {
+		uint8_t *group = (uint8_t *)req;
+
+		group += ENETC_NTMP_ENTRY_ID_SIZE + ENETC_RSS_STSE_DATA_SIZE(count);
+		for (i = 0; i < count; i++)
+			table[i] = group[i];
+	}
+end:
+	rte_free(tmp);
+
+	return err;
+}
+
+static int
+netc_setup_cbdr(struct rte_eth_dev *dev, int cbd_num,
+		struct netc_cbdr_regs *regs,
+		struct netc_cbdr *cbdr)
+{
+	int size;
+
+	size = cbd_num * sizeof(union netc_cbd) +
+		NETC_CBDR_BASE_ADDR_ALIGN;
+
+	cbdr->addr_base = rte_malloc(NULL, size, ENETC_CBDR_ALIGN);
+	if (!cbdr->addr_base)
+		return -ENOMEM;
+
+	cbdr->dma_base = rte_mem_virt2iova(cbdr->addr_base);
+	cbdr->dma_size = size;
+	cbdr->bd_num = cbd_num;
+	cbdr->regs = *regs;
+	cbdr->dma_dev = dev;
+	cbdr->timeout = ENETC_CBDR_TIMEOUT;
+	cbdr->delay = ENETC_CBDR_DELAY;
+
+	if (getenv("ENETC4_CBDR_TIMEOUT"))
+		cbdr->timeout = atoi(getenv("ENETC4_CBDR_TIMEOUT"));
+
+	if (getenv("ENETC4_CBDR_DELAY"))
+		cbdr->delay = atoi(getenv("ENETC4_CBDR_DELAY"));
+
+
+	ENETC_PMD_DEBUG("CBDR timeout = %u and delay = %u", cbdr->timeout,
+						cbdr->delay);
+	/* The base address of the Control BD Ring must be 128 bytes aligned */
+	cbdr->dma_base_align =  cbdr->dma_base;
+	cbdr->addr_base_align = cbdr->addr_base;
+
+	cbdr->next_to_clean = 0;
+	cbdr->next_to_use = 0;
+	rte_spinlock_init(&cbdr->ring_lock);
+
+	netc_cbdr_write(cbdr->regs.mr, ~((uint32_t)NETC_CBDRMR_EN));
+	/* Step 1: Configure the base address of the Control BD Ring */
+	netc_cbdr_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
+	netc_cbdr_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align));
+
+	/* Step 2: Configure the producer index register */
+	netc_cbdr_write(cbdr->regs.pir, cbdr->next_to_clean);
+
+	/* Step 3: Configure the consumer index register */
+	netc_cbdr_write(cbdr->regs.cir, cbdr->next_to_use);
+	/* Step4: Configure the number of BDs of the Control BD Ring */
+	netc_cbdr_write(cbdr->regs.lenr, cbdr->bd_num);
+
+	/* Step 5: Enable the Control BD Ring */
+	netc_cbdr_write(cbdr->regs.mr, NETC_CBDRMR_EN);
+
+	return 0;
+}
+
+void
+netc_free_cbdr(struct netc_cbdr *cbdr)
+{
+	/* Disable the Control BD Ring */
+	if (cbdr->regs.mr != NULL) {
+		netc_cbdr_write(cbdr->regs.mr, 0);
+		rte_free(cbdr->addr_base);
+		memset(cbdr, 0, sizeof(*cbdr));
+	}
+}
+
+int
+enetc4_setup_cbdr(struct rte_eth_dev *dev, struct enetc_hw *hw,
+		  int bd_count, struct netc_cbdr *cbdr)
+{
+	struct netc_cbdr_regs regs;
+
+	regs.pir = (void *)((size_t)hw->reg + ENETC4_SICBDRPIR);
+	regs.cir = (void *)((size_t)hw->reg + ENETC4_SICBDRCIR);
+	regs.mr = (void *)((size_t)hw->reg + ENETC4_SICBDRMR);
+	regs.st = (void *)((size_t)hw->reg + ENETC4_SICBDRSR);
+	regs.bar0 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR0);
+	regs.bar1 = (void *)((size_t)hw->reg + ENETC4_SICBDRBAR1);
+	regs.lenr = (void *)((size_t)hw->reg + ENETC4_SICBDRLENR);
+	regs.sictr0 = (void *)((size_t)hw->reg + ENETC4_SICTR0);
+	regs.sictr1 = (void *)((size_t)hw->reg + ENETC4_SICTR1);
+
+	return netc_setup_cbdr(dev, bd_count, &regs, cbdr);
+}
diff --git a/drivers/net/enetc/meson.build b/drivers/net/enetc/meson.build
index 6e00758a36..fe8fdc07f3 100644
--- a/drivers/net/enetc/meson.build
+++ b/drivers/net/enetc/meson.build
@@ -8,10 +8,11 @@ endif
 
 deps += ['common_dpaax']
 sources = files(
-	'enetc4_ethdev.c',
-	'enetc4_vf.c',
+        'enetc4_ethdev.c',
+        'enetc4_vf.c',
         'enetc_ethdev.c',
         'enetc_rxtx.c',
+        'enetc_cbdr.c',
 )
 
 includes += include_directories('base')
diff --git a/drivers/net/enetc/ntmp.h b/drivers/net/enetc/ntmp.h
new file mode 100644
index 0000000000..0dbc006f26
--- /dev/null
+++ b/drivers/net/enetc/ntmp.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 NXP
+ */
+
+#ifndef ENETC_NTMP_H
+#define ENETC_NTMP_H
+
+#include "compat.h"
+#include <linux/types.h>
+
+#define BITS_PER_LONG   (__SIZEOF_LONG__ * 8)
+#define BITS_PER_LONG_LONG  (__SIZEOF_LONG_LONG__ * 8)
+#define GENMASK(h, l)       (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+/* define NTMP Operation Commands */
+#define NTMP_CMD_DELETE			BIT(0)
+#define NTMP_CMD_UPDATE			BIT(1)
+#define NTMP_CMD_QUERY			BIT(2)
+
+#define NETC_CBDR_TIMEOUT		1000 /* us */
+#define NETC_CBDR_BD_NUM		256
+#define NETC_CBDR_BASE_ADDR_ALIGN	128
+#define NETC_CBD_DATA_ADDR_ALIGN	16
+#define NETC_CBDRMR_EN			BIT(31)
+
+#define NTMP_RESP_HDR_ERR		GENMASK(11, 0)
+
+struct common_req_data {
+	uint16_t update_act;
+	uint8_t dbg_opt;
+	uint8_t query_act:4;
+	uint8_t tbl_ver:4;
+};
+
+/* RSS Table Request and Response Data Buffer Format */
+struct rsst_req_query {
+	struct common_req_data crd;
+	uint32_t entry_id;
+};
+
+/* struct for update operation */
+struct rsst_req_update {
+	struct common_req_data crd;
+	uint32_t entry_id;
+	uint8_t groups[];
+};
+
+/* The format of conctrol buffer descriptor */
+union netc_cbd {
+	struct {
+		uint64_t addr;
+		uint32_t len;
+		uint8_t cmd;
+		uint8_t resv1:4;
+		uint8_t access_method:4;
+		uint8_t table_id;
+		uint8_t hdr_ver:6;
+		uint8_t cci:1;
+		uint8_t rr:1;
+		uint32_t resv2[3];
+		uint32_t npf;
+	} ntmp_req_hdr;	/* NTMP Request Message Header Format */
+
+	struct {
+		uint32_t resv1[3];
+		uint16_t num_matched;
+		uint16_t error_rr; /* bit0~11: error, bit12~14: reserved, bit15: rr */
+		uint32_t resv3[4];
+	} ntmp_resp_hdr; /* NTMP Response Message Header Format */
+};
+
+struct netc_cbdr_regs {
+	void *pir;
+	void *cir;
+	void *mr;
+	void *st;
+
+	void *bar0;
+	void *bar1;
+	void *lenr;
+
+	/* station interface current time register */
+	void *sictr0;
+	void *sictr1;
+};
+
+struct netc_cbdr {
+	struct netc_cbdr_regs regs;
+
+	int bd_num;
+	int next_to_use;
+	int next_to_clean;
+
+	int dma_size;
+	void *addr_base;
+	void *addr_base_align;
+	dma_addr_t dma_base;
+	dma_addr_t dma_base_align;
+	struct rte_eth_dev *dma_dev;
+
+	rte_spinlock_t ring_lock; /* Avoid race condition */
+
+	/* bitmap of used words of SGCL table */
+	unsigned long *sgclt_used_words;
+	uint32_t sgclt_words_num;
+	uint32_t timeout;
+	uint32_t delay;
+};
+
+#endif /* ENETC_NTMP_H */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 08/12] net/enetc: Add VF to PF messaging support and primary MAC setup
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (6 preceding siblings ...)
  2024-10-18  7:26 ` [v1 07/12] net/enetc: Add support for multiple queues with RSS vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 09/12] net/enetc: Add multicast and promiscuous mode support vanshika.shukla
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Introduces Virtual Function (VF) to Physical Function (PF) messaging,
enabling VFs to communicate with the Linux PF driver for feature
enablement.

This patch also adds primary MAC address setup capability,
allowing VFs to configure their MAC addresses.

Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 drivers/net/enetc/base/enetc4_hw.h |  22 +++
 drivers/net/enetc/enetc.h          |  99 +++++++++++
 drivers/net/enetc/enetc4_vf.c      | 260 +++++++++++++++++++++++++++++
 3 files changed, 381 insertions(+)

diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index 49446f2cb4..f0b7563d22 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -14,6 +14,12 @@
 #define ENETC4_DEV_ID_VF	0xef00
 #define PCI_VENDOR_ID_NXP	0x1131
 
+struct enetc_msg_swbd {
+	void *vaddr;
+	uint64_t dma;
+	int size;
+};
+
 /* enetc4 txbd flags */
 #define ENETC4_TXBD_FLAGS_L4CS		BIT(0)
 #define ENETC4_TXBD_FLAGS_L_TX_CKSUM	BIT(3)
@@ -103,6 +109,9 @@
 #define IFMODE_SGMII			5
 #define PM_IF_MODE_ENA			BIT(15)
 
+#define ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE     100
+#define ENETC4_DEF_VSI_WAIT_DELAY_UPDATE       2000 /* us */
+
 /* Station interface statistics */
 #define ENETC4_SIROCT0           0x300
 #define ENETC4_SIRFRM0           0x308
@@ -110,6 +119,19 @@
 #define ENETC4_SITFRM0           0x328
 #define ENETC4_SITDFCR           0x340
 
+/* VSI MSG Registers */
+#define ENETC4_VSIMSGSR  0x204   /* RO */
+#define ENETC4_VSIMSGSR_MB       BIT(0)
+#define ENETC4_VSIMSGSR_MS       BIT(1)
+#define ENETC4_VSIMSGSNDAR0      0x210
+#define ENETC4_VSIMSGSNDAR1      0x214
+
+#define ENETC4_VSIMSGRR		 0x208
+#define ENETC4_VSIMSGRR_MR       BIT(0)
+
+#define ENETC_SIMSGSR_SET_MC(val) ((val) << 16)
+#define ENETC_SIMSGSR_GET_MC(val) ((val) >> 16)
+
 /* Control BDR regs */
 #define ENETC4_SICBDRMR		0x800
 #define ENETC4_SICBDRSR		0x804   /* RO */
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 354cd761d7..c0fba9d618 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -41,6 +41,11 @@
 /* eth name size */
 #define ENETC_ETH_NAMESIZE	20
 
+#define ENETC_DEFAULT_MSG_SIZE  1024    /* max size */
+
+/* Message length is in multiple of 32 bytes */
+#define ENETC_VSI_PSI_MSG_SIZE  32
+
 /* size for marking hugepage non-cacheable */
 #define SIZE_2MB	0x200000
 
@@ -123,6 +128,100 @@ struct enetc_eth_adapter {
 #define ENETC_DEV_PRIVATE_TO_INTR(adapter) \
 	(&((struct enetc_eth_adapter *)adapter)->intr)
 
+/* Class ID for PSI-TO-VSI messages */
+#define ENETC_MSG_CLASS_ID_CMD_SUCCESS          0x1
+#define ENETC_MSG_CLASS_ID_PERMISSION_DENY      0x2
+#define ENETC_MSG_CLASS_ID_CMD_NOT_SUPPORT      0x3
+#define ENETC_MSG_CLASS_ID_PSI_BUSY             0x4
+#define ENETC_MSG_CLASS_ID_CRC_ERROR            0x5
+#define ENETC_MSG_CLASS_ID_PROTO_NOT_SUPPORT    0x6
+#define ENETC_MSG_CLASS_ID_INVALID_MSG_LEN      0x7
+#define ENETC_MSG_CLASS_ID_CMD_TIMEOUT          0x8
+#define ENETC_MSG_CLASS_ID_CMD_DEFERED          0xf
+
+#define ENETC_PROMISC_DISABLE			0x41
+#define ENETC_PROMISC_ENABLE			0x43
+#define ENETC_ALLMULTI_PROMISC_DIS		0x81
+#define ENETC_ALLMULTI_PROMISC_EN		0x83
+
+
+/* Enum for class IDs */
+enum enetc_msg_cmd_class_id {
+	ENETC_CLASS_ID_MAC_FILTER = 0x20,
+};
+
+/* Enum for command IDs */
+enum enetc_msg_cmd_id {
+	ENETC_CMD_ID_SET_PRIMARY_MAC = 0,
+};
+
+enum mac_addr_status {
+	ENETC_INVALID_MAC_ADDR = 0x0,
+	ENETC_DUPLICATE_MAC_ADDR = 0X1,
+	ENETC_MAC_ADDR_NOT_FOUND = 0X2,
+};
+
+/* PSI-VSI command header format */
+struct enetc_msg_cmd_header {
+	uint16_t csum;		/* INET_CHECKSUM */
+	uint8_t class_id;       /* Command class type */
+	uint8_t cmd_id;         /* Denotes the specific required action */
+	uint8_t proto_ver;	/* Supported VSI-PSI command protocol version */
+	uint8_t len;		/* Extended message body length */
+	uint8_t reserved_1;
+	uint8_t cookie;	/* Control command execution asynchronously on PSI side */
+	uint64_t reserved_2;
+};
+
+/* VF-PF set primary MAC address message format */
+struct enetc_msg_cmd_set_primary_mac {
+	struct enetc_msg_cmd_header header;
+	uint8_t count;	/* number of MAC addresses */
+	uint8_t reserved_1;
+	uint16_t reserved_2;
+	struct rte_ether_addr addr;
+};
+
+struct enetc_msg_cmd_set_promisc {
+	struct enetc_msg_cmd_header header;
+	uint8_t op_type;
+};
+
+struct enetc_msg_cmd_get_link_status {
+	struct enetc_msg_cmd_header header;
+};
+
+struct enetc_msg_cmd_get_link_speed {
+	struct enetc_msg_cmd_header header;
+};
+
+struct enetc_msg_cmd_set_vlan_promisc {
+	struct enetc_msg_cmd_header header;
+	uint8_t op;
+	uint8_t reserved;
+};
+
+struct enetc_msg_vlan_exact_filter {
+	struct enetc_msg_cmd_header header;
+	uint8_t vlan_count;
+	uint8_t reserved_1;
+	uint16_t reserved_2;
+	uint16_t vlan_id;
+	uint8_t tpid;
+	uint8_t reserved2;
+};
+
+struct enetc_psi_reply_msg {
+	uint8_t class_id;
+	uint8_t status;
+};
+
+/* msg size encoding: default and max msg value of 1024B encoded as 0 */
+static inline uint32_t enetc_vsi_set_msize(uint32_t size)
+{
+	return size < ENETC_DEFAULT_MSG_SIZE ? size >> 5 : 0;
+}
+
 /*
  * ENETC4 function prototypes
  */
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index a9fb33c432..6bdd476f0a 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -8,6 +8,51 @@
 #include "enetc_logs.h"
 #include "enetc.h"
 
+#define ENETC_CRC_TABLE_SIZE		256
+#define ENETC_POLY			0x1021
+#define ENETC_CRC_INIT			0xffff
+#define ENETC_BYTE_SIZE			8
+#define ENETC_MSB_BIT			0x8000
+
+uint16_t enetc_crc_table[ENETC_CRC_TABLE_SIZE];
+bool enetc_crc_gen;
+
+static void
+enetc_gen_crc_table(void)
+{
+	uint16_t crc = 0;
+	uint16_t c;
+
+	for (int i = 0; i < ENETC_CRC_TABLE_SIZE; i++) {
+		crc = 0;
+		c = i << ENETC_BYTE_SIZE;
+		for (int j = 0; j < ENETC_BYTE_SIZE; j++) {
+			if ((crc ^ c) & ENETC_MSB_BIT)
+				crc = (crc << 1) ^ ENETC_POLY;
+			else
+				crc = crc << 1;
+			c = c << 1;
+		}
+
+		enetc_crc_table[i] = crc;
+	}
+
+	enetc_crc_gen = true;
+}
+
+static uint16_t
+enetc_crc_calc(uint16_t crc, const uint8_t *buffer, size_t len)
+{
+	uint8_t data;
+
+	while (len--) {
+		data = *buffer;
+		crc = (crc << 8) ^ enetc_crc_table[((crc >> 8) ^ data) & 0xff];
+		buffer++;
+	}
+	return crc;
+}
+
 int
 enetc4_vf_dev_stop(struct rte_eth_dev *dev __rte_unused)
 {
@@ -47,6 +92,217 @@ enetc4_vf_stats_get(struct rte_eth_dev *dev,
 	return 0;
 }
 
+
+static void
+enetc_msg_vf_fill_common_hdr(struct enetc_msg_swbd *msg,
+					uint8_t class_id, uint8_t cmd_id, uint8_t proto_ver,
+					uint8_t len, uint8_t cookie)
+{
+	struct enetc_msg_cmd_header *hdr = msg->vaddr;
+
+	hdr->class_id = class_id;
+	hdr->cmd_id = cmd_id;
+	hdr->proto_ver = proto_ver;
+	hdr->len = len;
+	hdr->cookie = cookie;
+	/* Incrementing msg 2 bytes ahead as the first two bytes are for CRC */
+	hdr->csum = rte_cpu_to_be_16(enetc_crc_calc(ENETC_CRC_INIT,
+				(uint8_t *)msg->vaddr + sizeof(uint16_t),
+				msg->size - sizeof(uint16_t)));
+
+	dcbf(hdr);
+}
+
+/* Messaging */
+static void
+enetc4_msg_vsi_write_msg(struct enetc_hw *hw,
+		struct enetc_msg_swbd *msg)
+{
+	uint32_t val;
+
+	val = enetc_vsi_set_msize(msg->size) | lower_32_bits(msg->dma);
+	enetc_wr(hw, ENETC4_VSIMSGSNDAR1, upper_32_bits(msg->dma));
+	enetc_wr(hw, ENETC4_VSIMSGSNDAR0, val);
+}
+
+static void
+enetc4_msg_vsi_reply_msg(struct enetc_hw *enetc_hw, struct enetc_psi_reply_msg *reply_msg)
+{
+	int vsimsgsr;
+	int8_t class_id = 0;
+	uint8_t status = 0;
+
+	vsimsgsr = enetc_rd(enetc_hw, ENETC4_VSIMSGSR);
+
+	/* Extracting 8 bits of message result in class_id */
+	class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 8) & 0xff);
+
+	/* Extracting 4 bits of message result in status */
+	status |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 4) & 0xf);
+
+	reply_msg->class_id = class_id;
+	reply_msg->status = status;
+}
+
+static int
+enetc4_msg_vsi_send(struct enetc_hw *enetc_hw, struct enetc_msg_swbd *msg)
+{
+	int timeout = ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE;
+	int delay_us = ENETC4_DEF_VSI_WAIT_DELAY_UPDATE;
+	uint8_t class_id = 0;
+	int err = 0;
+	int vsimsgsr;
+
+	enetc4_msg_vsi_write_msg(enetc_hw, msg);
+
+	do {
+		vsimsgsr = enetc_rd(enetc_hw, ENETC4_VSIMSGSR);
+		if (!(vsimsgsr & ENETC4_VSIMSGSR_MB))
+			break;
+		rte_delay_us(delay_us);
+	} while (--timeout);
+
+	if (!timeout) {
+		ENETC_PMD_ERR("Message not processed by PSI");
+		return -ETIMEDOUT;
+	}
+	/* check for message delivery error */
+	if (vsimsgsr & ENETC4_VSIMSGSR_MS) {
+		ENETC_PMD_ERR("Transfer error when copying the data");
+		return -EIO;
+	}
+
+	class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgsr) >> 8) & 0xff);
+
+	/* Check the user-defined completion status. */
+	if (class_id != ENETC_MSG_CLASS_ID_CMD_SUCCESS) {
+		switch (class_id) {
+		case ENETC_MSG_CLASS_ID_PERMISSION_DENY:
+			ENETC_PMD_ERR("Permission denied");
+			err = -EACCES;
+			break;
+		case ENETC_MSG_CLASS_ID_CMD_NOT_SUPPORT:
+			ENETC_PMD_ERR("Command not supported");
+			err = -EOPNOTSUPP;
+			break;
+		case ENETC_MSG_CLASS_ID_PSI_BUSY:
+			ENETC_PMD_ERR("PSI Busy");
+			err = -EBUSY;
+			break;
+		case ENETC_MSG_CLASS_ID_CMD_TIMEOUT:
+			ENETC_PMD_ERR("Command timeout");
+			err = -ETIME;
+			break;
+		case ENETC_MSG_CLASS_ID_CRC_ERROR:
+			ENETC_PMD_ERR("CRC error");
+			err = -EIO;
+			break;
+		case ENETC_MSG_CLASS_ID_PROTO_NOT_SUPPORT:
+			ENETC_PMD_ERR("Protocol Version not supported");
+			err = -EOPNOTSUPP;
+			break;
+		case ENETC_MSG_CLASS_ID_INVALID_MSG_LEN:
+			ENETC_PMD_ERR("Invalid message length");
+			err = -EINVAL;
+			break;
+		case ENETC_CLASS_ID_MAC_FILTER:
+			break;
+		default:
+			err = -EIO;
+		}
+	}
+
+	return err;
+}
+
+static int
+enetc4_vf_set_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_cmd_set_primary_mac *cmd;
+	struct enetc_msg_swbd *msg;
+	struct enetc_psi_reply_msg *reply_msg;
+	int msg_size;
+	int err = 0;
+
+	PMD_INIT_FUNC_TRACE();
+	reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
+	if (!reply_msg) {
+		ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
+		return -ENOMEM;
+	}
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		rte_free(reply_msg);
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac),
+				ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		rte_free(reply_msg);
+		return -ENOMEM;
+	}
+
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+
+	cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
+
+	cmd->count = 0;
+	memcpy(&cmd->addr.addr_bytes, addr, sizeof(struct rte_ether_addr));
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
+					ENETC_CMD_ID_SET_PRIMARY_MAC, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+	enetc4_msg_vsi_reply_msg(enetc_hw, reply_msg);
+
+	if (reply_msg->class_id == ENETC_CLASS_ID_MAC_FILTER) {
+		switch (reply_msg->status) {
+		case ENETC_INVALID_MAC_ADDR:
+			ENETC_PMD_ERR("Invalid MAC address");
+			err = -EINVAL;
+			break;
+		case ENETC_DUPLICATE_MAC_ADDR:
+			ENETC_PMD_ERR("Duplicate MAC address");
+			err = -EINVAL;
+			break;
+		default:
+			err = -EINVAL;
+			break;
+		}
+	}
+
+	if (err) {
+		ENETC_PMD_ERR("VSI command execute error!");
+		goto end;
+	}
+
+	rte_ether_addr_copy((struct rte_ether_addr *)&cmd->addr,
+			&dev->data->mac_addrs[0]);
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(reply_msg);
+	rte_free(msg);
+	return err;
+}
+
 /*
  * The set of PCI devices this driver supports
  */
@@ -63,6 +319,7 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.dev_close            = enetc4_dev_close,
 	.dev_infos_get        = enetc4_dev_infos_get,
 	.stats_get            = enetc4_vf_stats_get,
+	.mac_addr_set         = enetc4_vf_set_mac_addr,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,
 	.rx_queue_stop        = enetc4_rx_queue_stop,
@@ -121,6 +378,9 @@ enetc4_vf_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
 		return -ENOMEM;
 	}
 
+	if (!enetc_crc_gen)
+		enetc_gen_crc_table();
+
 	/* Copy the permanent MAC address */
 	rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr,
 			     &eth_dev->data->mac_addrs[0]);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 09/12] net/enetc: Add multicast and promiscuous mode support
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (7 preceding siblings ...)
  2024-10-18  7:26 ` [v1 08/12] net/enetc: Add VF to PF messaging support and primary MAC setup vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 10/12] net/enetc: Add link speed and status support vanshika.shukla
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Enables ENETC4 PMD to handle multicast and promiscuous modes.

Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |   2 +
 drivers/net/enetc/enetc.h           |   5 +
 drivers/net/enetc/enetc4_ethdev.c   |  40 +++++
 drivers/net/enetc/enetc4_vf.c       | 265 ++++++++++++++++++++++++++++
 4 files changed, 312 insertions(+)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 79430d0018..36d536d1f2 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,8 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Promiscuous mode     = Y
+Allmulticast mode    = Y
 RSS hash             = Y
 Packet type parsing  = Y
 Basic stats          = Y
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index c0fba9d618..902912f4fb 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -144,15 +144,20 @@ struct enetc_eth_adapter {
 #define ENETC_ALLMULTI_PROMISC_DIS		0x81
 #define ENETC_ALLMULTI_PROMISC_EN		0x83
 
+#define ENETC_PROMISC_VLAN_DISABLE		0x1
+#define ENETC_PROMISC_VLAN_ENABLE		0x3
 
 /* Enum for class IDs */
 enum enetc_msg_cmd_class_id {
 	ENETC_CLASS_ID_MAC_FILTER = 0x20,
+	ENETC_CLASS_ID_VLAN_FILTER = 0x21,
 };
 
 /* Enum for command IDs */
 enum enetc_msg_cmd_id {
 	ENETC_CMD_ID_SET_PRIMARY_MAC = 0,
+	ENETC_CMD_ID_SET_MAC_PROMISCUOUS = 5,
+	ENETC_CMD_ID_SET_VLAN_PROMISCUOUS = 4,
 };
 
 enum mac_addr_status {
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 075205a0e5..9df01b1e4d 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -592,6 +592,44 @@ enetc4_dev_close(struct rte_eth_dev *dev)
 	return ret;
 }
 
+static int
+enetc4_promiscuous_enable(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 psipmr = 0;
+
+	psipmr = enetc4_port_rd(enetc_hw, ENETC4_PSIPMMR);
+
+	/* Setting to enable promiscuous mode for all ports*/
+	psipmr |= PSIPMMR_SI_MAC_UP | PSIPMMR_SI_MAC_MP;
+
+	enetc4_port_wr(enetc_hw, ENETC4_PSIPMMR, psipmr);
+
+	return 0;
+}
+
+static int
+enetc4_promiscuous_disable(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 psipmr = 0;
+
+	/* Setting to disable promiscuous mode for SI0*/
+	psipmr = enetc4_port_rd(enetc_hw, ENETC4_PSIPMMR);
+	psipmr &= (~PSIPMMR_SI_MAC_UP);
+
+	if (dev->data->all_multicast == 0)
+		psipmr &= (~PSIPMMR_SI_MAC_MP);
+
+	enetc4_port_wr(enetc_hw, ENETC4_PSIPMMR, psipmr);
+
+	return 0;
+}
+
 int
 enetc4_dev_configure(struct rte_eth_dev *dev)
 {
@@ -831,6 +869,8 @@ static const struct eth_dev_ops enetc4_ops = {
 	.dev_infos_get        = enetc4_dev_infos_get,
 	.stats_get            = enetc4_stats_get,
 	.stats_reset          = enetc4_stats_reset,
+	.promiscuous_enable   = enetc4_promiscuous_enable,
+	.promiscuous_disable  = enetc4_promiscuous_disable,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,
 	.rx_queue_stop        = enetc4_rx_queue_stop,
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 6bdd476f0a..28cf83077c 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -303,6 +303,266 @@ enetc4_vf_set_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
 	return err;
 }
 
+static int
+enetc4_vf_promisc_send_message(struct rte_eth_dev *dev, bool promisc_en)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_cmd_set_promisc *cmd;
+	struct enetc_msg_swbd *msg;
+	int msg_size;
+	int err = 0;
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_promisc), ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		return -ENOMEM;
+	}
+
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+
+	cmd = (struct enetc_msg_cmd_set_promisc *)msg->vaddr;
+
+	/* op_type is based on the result of message format
+	 *    7  6      1       0
+	      type   promisc  flush
+	 */
+
+	if (promisc_en)
+		cmd->op_type = ENETC_PROMISC_ENABLE;
+	else
+		cmd->op_type = ENETC_PROMISC_DISABLE;
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
+				ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(msg);
+	return err;
+}
+
+static int
+enetc4_vf_allmulti_send_message(struct rte_eth_dev *dev, bool mc_promisc)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_cmd_set_promisc *cmd;
+	struct enetc_msg_swbd *msg;
+	int msg_size;
+	int err = 0;
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_promisc),
+				ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		return -ENOMEM;
+	}
+
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+
+	cmd = (struct enetc_msg_cmd_set_promisc *)msg->vaddr;
+
+	/* op_type is based on the result of message format
+	 *    7  6      1       0
+	      type   promisc  flush
+	 */
+
+	if (mc_promisc)
+		cmd->op_type = ENETC_ALLMULTI_PROMISC_EN;
+	else
+		cmd->op_type = ENETC_ALLMULTI_PROMISC_DIS;
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
+				ENETC_CMD_ID_SET_MAC_PROMISCUOUS, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(msg);
+	return err;
+}
+
+
+static int
+enetc4_vf_multicast_enable(struct rte_eth_dev *dev)
+{
+	int err;
+
+	PMD_INIT_FUNC_TRACE();
+	err = enetc4_vf_allmulti_send_message(dev, true);
+	if (err) {
+		ENETC_PMD_ERR("Failed to enable multicast promiscuous mode");
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+enetc4_vf_multicast_disable(struct rte_eth_dev *dev)
+{
+	int err;
+
+	PMD_INIT_FUNC_TRACE();
+	err = enetc4_vf_allmulti_send_message(dev, false);
+	if (err) {
+		ENETC_PMD_ERR("Failed to disable multicast promiscuous mode");
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+enetc4_vf_promisc_enable(struct rte_eth_dev *dev)
+{
+	int err;
+
+	PMD_INIT_FUNC_TRACE();
+	err = enetc4_vf_promisc_send_message(dev, true);
+	if (err) {
+		ENETC_PMD_ERR("Failed to enable promiscuous mode");
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+enetc4_vf_promisc_disable(struct rte_eth_dev *dev)
+{
+	int err;
+
+	PMD_INIT_FUNC_TRACE();
+	err = enetc4_vf_promisc_send_message(dev, false);
+	if (err) {
+		ENETC_PMD_ERR("Failed to disable promiscuous mode");
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_cmd_set_vlan_promisc *cmd;
+	struct enetc_msg_swbd *msg;
+	int msg_size;
+	int err = 0;
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_vlan_promisc),
+				ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		return -ENOMEM;
+	}
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+
+	cmd = (struct enetc_msg_cmd_set_vlan_promisc *)msg->vaddr;
+	/* op is based on the result of message format
+	 *	   1	  0
+	 *	promisc	flush
+	 */
+
+	if (promisc_en)
+		cmd->op = ENETC_PROMISC_VLAN_ENABLE;
+	else
+		cmd->op = ENETC_PROMISC_VLAN_DISABLE;
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
+				ENETC_CMD_ID_SET_VLAN_PROMISCUOUS, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(msg);
+	return err;
+}
+
+static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_unused)
+{
+	int err = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	if (dev->data->dev_conf.rxmode.offloads) {
+		ENETC_PMD_DEBUG("VLAN filter table entry inserted:"
+					"Disabling VLAN promisc mode");
+		err = enetc4_vf_vlan_promisc(dev, false);
+		if (err) {
+			ENETC_PMD_ERR("Added VLAN filter table entry:"
+					"Failed to disable promiscuous mode");
+			return err;
+		}
+	} else {
+		ENETC_PMD_DEBUG("Enabling VLAN promisc mode");
+		err = enetc4_vf_vlan_promisc(dev, true);
+		if (err) {
+			ENETC_PMD_ERR("Vlan filter table empty:"
+					"Failed to enable promiscuous mode");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * The set of PCI devices this driver supports
  */
@@ -320,6 +580,11 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.dev_infos_get        = enetc4_dev_infos_get,
 	.stats_get            = enetc4_vf_stats_get,
 	.mac_addr_set         = enetc4_vf_set_mac_addr,
+	.promiscuous_enable   = enetc4_vf_promisc_enable,
+	.promiscuous_disable  = enetc4_vf_promisc_disable,
+	.allmulticast_enable  = enetc4_vf_multicast_enable,
+	.allmulticast_disable = enetc4_vf_multicast_disable,
+	.vlan_offload_set     = enetc4_vf_vlan_offload_set,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,
 	.rx_queue_stop        = enetc4_rx_queue_stop,
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 10/12] net/enetc: Add link speed and status support
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (8 preceding siblings ...)
  2024-10-18  7:26 ` [v1 09/12] net/enetc: Add multicast and promiscuous mode support vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 11/12] net/enetc: Add link status notification support vanshika.shukla
  2024-10-18  7:26 ` [v1 12/12] net/enetc: Add MAC and VLAN filter support vanshika.shukla
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla

From: Vanshika Shukla <vanshika.shukla@nxp.com>

This patch add support for link update operation.

Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |   2 +
 drivers/net/enetc/base/enetc4_hw.h  |   9 ++
 drivers/net/enetc/enetc.h           |  25 ++++
 drivers/net/enetc/enetc4_ethdev.c   |  44 ++++++
 drivers/net/enetc/enetc4_vf.c       | 216 ++++++++++++++++++++++++++++
 5 files changed, 296 insertions(+)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 36d536d1f2..78b06e9841 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,8 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Speed capabilities   = Y
+Link status          = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 RSS hash             = Y
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index f0b7563d22..d899b82b9c 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -109,6 +109,15 @@ struct enetc_msg_swbd {
 #define IFMODE_SGMII			5
 #define PM_IF_MODE_ENA			BIT(15)
 
+/* Port MAC 0 Interface Status Register */
+#define ENETC4_PM_IF_STATUS(mac)	(0x5304 + (mac) * 0x400)
+#define ENETC4_LINK_MODE                 0x0000000000080000ULL
+#define ENETC4_LINK_STATUS               0x0000000000010000ULL
+#define ENETC4_LINK_SPEED_MASK           0x0000000000060000ULL
+#define ENETC4_LINK_SPEED_10M            0x0ULL
+#define ENETC4_LINK_SPEED_100M           0x0000000000020000ULL
+#define ENETC4_LINK_SPEED_1G             0x0000000000040000ULL
+
 #define ENETC4_DEF_VSI_WAIT_TIMEOUT_UPDATE     100
 #define ENETC4_DEF_VSI_WAIT_DELAY_UPDATE       2000 /* us */
 
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 902912f4fb..7f5329de33 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -151,6 +151,8 @@ struct enetc_eth_adapter {
 enum enetc_msg_cmd_class_id {
 	ENETC_CLASS_ID_MAC_FILTER = 0x20,
 	ENETC_CLASS_ID_VLAN_FILTER = 0x21,
+	ENETC_CLASS_ID_LINK_STATUS = 0x80,
+	ENETC_CLASS_ID_LINK_SPEED = 0x81
 };
 
 /* Enum for command IDs */
@@ -158,6 +160,8 @@ enum enetc_msg_cmd_id {
 	ENETC_CMD_ID_SET_PRIMARY_MAC = 0,
 	ENETC_CMD_ID_SET_MAC_PROMISCUOUS = 5,
 	ENETC_CMD_ID_SET_VLAN_PROMISCUOUS = 4,
+	ENETC_CMD_ID_GET_LINK_STATUS = 0,
+	ENETC_CMD_ID_GET_LINK_SPEED = 0
 };
 
 enum mac_addr_status {
@@ -166,6 +170,27 @@ enum mac_addr_status {
 	ENETC_MAC_ADDR_NOT_FOUND = 0X2,
 };
 
+enum link_status {
+	ENETC_LINK_UP = 0x0,
+	ENETC_LINK_DOWN = 0x1
+};
+
+enum speed {
+	ENETC_SPEED_UNKNOWN = 0x0,
+	ENETC_SPEED_10_HALF_DUPLEX = 0x1,
+	ENETC_SPEED_10_FULL_DUPLEX = 0x2,
+	ENETC_SPEED_100_HALF_DUPLEX = 0x3,
+	ENETC_SPEED_100_FULL_DUPLEX = 0x4,
+	ENETC_SPEED_1000 = 0x5,
+	ENETC_SPEED_2500 = 0x6,
+	ENETC_SPEED_5000 = 0x7,
+	ENETC_SPEED_10G = 0x8,
+	ENETC_SPEED_25G = 0x9,
+	ENETC_SPEED_50G = 0xA,
+	ENETC_SPEED_100G = 0xB,
+	ENETC_SPEED_NOT_SUPPORTED = 0xF
+};
+
 /* PSI-VSI command header format */
 struct enetc_msg_cmd_header {
 	uint16_t csum;		/* INET_CHECKSUM */
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 9df01b1e4d..29283f2d44 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -75,6 +75,49 @@ enetc4_dev_stop(struct rte_eth_dev *dev)
 	return 0;
 }
 
+/* return 0 means link status changed, -1 means not changed */
+static int
+enetc4_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	struct enetc_eth_hw *hw =
+		ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct rte_eth_link link;
+	uint32_t status;
+
+	PMD_INIT_FUNC_TRACE();
+
+	memset(&link, 0, sizeof(link));
+
+	status = enetc4_port_rd(enetc_hw, ENETC4_PM_IF_STATUS(0));
+
+	if (status & ENETC4_LINK_MODE)
+		link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+	else
+		link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+
+	if (status & ENETC4_LINK_STATUS)
+		link.link_status = RTE_ETH_LINK_UP;
+	else
+		link.link_status = RTE_ETH_LINK_DOWN;
+
+	switch (status & ENETC4_LINK_SPEED_MASK) {
+	case ENETC4_LINK_SPEED_1G:
+		link.link_speed = RTE_ETH_SPEED_NUM_1G;
+		break;
+
+	case ENETC4_LINK_SPEED_100M:
+		link.link_speed = RTE_ETH_SPEED_NUM_100M;
+		break;
+
+	default:
+	case ENETC4_LINK_SPEED_10M:
+		link.link_speed = RTE_ETH_SPEED_NUM_10M;
+	}
+
+	return rte_eth_linkstatus_set(dev, &link);
+}
+
 static int
 enetc4_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
 {
@@ -867,6 +910,7 @@ static const struct eth_dev_ops enetc4_ops = {
 	.dev_stop             = enetc4_dev_stop,
 	.dev_close            = enetc4_dev_close,
 	.dev_infos_get        = enetc4_dev_infos_get,
+	.link_update          = enetc4_link_update,
 	.stats_get            = enetc4_stats_get,
 	.stats_reset          = enetc4_stats_reset,
 	.promiscuous_enable   = enetc4_promiscuous_enable,
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 28cf83077c..307fabf2c6 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -206,6 +206,8 @@ enetc4_msg_vsi_send(struct enetc_hw *enetc_hw, struct enetc_msg_swbd *msg)
 			err = -EINVAL;
 			break;
 		case ENETC_CLASS_ID_MAC_FILTER:
+		case ENETC_CLASS_ID_LINK_STATUS:
+		case ENETC_CLASS_ID_LINK_SPEED:
 			break;
 		default:
 			err = -EIO;
@@ -479,6 +481,216 @@ enetc4_vf_promisc_disable(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static int
+enetc4_vf_get_link_status(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *reply_msg)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_swbd *msg;
+	int msg_size;
+	int err = 0;
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_status),
+			ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		return -ENOMEM;
+	}
+
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_STATUS,
+			ENETC_CMD_ID_GET_LINK_STATUS, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+	enetc4_msg_vsi_reply_msg(enetc_hw, reply_msg);
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(msg);
+	return err;
+}
+
+static int
+enetc4_vf_get_link_speed(struct rte_eth_dev *dev, struct enetc_psi_reply_msg *reply_msg)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_swbd *msg;
+	int msg_size;
+	int err = 0;
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_speed),
+				ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		return -ENOMEM;
+	}
+
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_SPEED,
+			ENETC_CMD_ID_GET_LINK_SPEED, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+	enetc4_msg_vsi_reply_msg(enetc_hw, reply_msg);
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(msg);
+	return err;
+}
+
+static int
+enetc4_vf_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
+{
+	struct enetc_psi_reply_msg *reply_msg;
+	struct rte_eth_link link;
+	int err;
+
+	PMD_INIT_FUNC_TRACE();
+	reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
+	if (!reply_msg) {
+		ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
+		return -ENOMEM;
+	}
+
+	memset(&link, 0, sizeof(struct rte_eth_link));
+
+	err = enetc4_vf_get_link_status(dev, reply_msg);
+	if (err) {
+		ENETC_PMD_ERR("Failed to get link status");
+		rte_free(reply_msg);
+		return err;
+	}
+
+	if (reply_msg->class_id == ENETC_CLASS_ID_LINK_STATUS) {
+		switch (reply_msg->status) {
+		case ENETC_LINK_UP:
+			link.link_status = RTE_ETH_LINK_UP;
+			break;
+		case ENETC_LINK_DOWN:
+			link.link_status = RTE_ETH_LINK_DOWN;
+			break;
+		default:
+			ENETC_PMD_ERR("Unknown link status");
+			break;
+		}
+	} else {
+		ENETC_PMD_ERR("Wrong reply message");
+		return -1;
+	}
+
+	err = enetc4_vf_get_link_speed(dev, reply_msg);
+	if (err) {
+		ENETC_PMD_ERR("Failed to get link speed");
+		rte_free(reply_msg);
+		return err;
+	}
+
+	if (reply_msg->class_id == ENETC_CLASS_ID_LINK_SPEED) {
+		switch (reply_msg->status) {
+		case ENETC_SPEED_UNKNOWN:
+			ENETC_PMD_DEBUG("Speed unknown");
+			link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+			break;
+		case ENETC_SPEED_10_HALF_DUPLEX:
+			link.link_speed = RTE_ETH_SPEED_NUM_10M;
+			link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+			break;
+		case ENETC_SPEED_10_FULL_DUPLEX:
+			link.link_speed = RTE_ETH_SPEED_NUM_10M;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_100_HALF_DUPLEX:
+			link.link_speed = RTE_ETH_SPEED_NUM_100M;
+			link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+			break;
+		case ENETC_SPEED_100_FULL_DUPLEX:
+			link.link_speed = RTE_ETH_SPEED_NUM_100M;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_1000:
+			link.link_speed = RTE_ETH_SPEED_NUM_1G;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_2500:
+			link.link_speed = RTE_ETH_SPEED_NUM_2_5G;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_5000:
+			link.link_speed = RTE_ETH_SPEED_NUM_5G;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_10G:
+			link.link_speed = RTE_ETH_SPEED_NUM_10G;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_25G:
+			link.link_speed = RTE_ETH_SPEED_NUM_25G;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_50G:
+			link.link_speed = RTE_ETH_SPEED_NUM_50G;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_100G:
+			link.link_speed = RTE_ETH_SPEED_NUM_100G;
+			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+			break;
+		case ENETC_SPEED_NOT_SUPPORTED:
+			ENETC_PMD_DEBUG("Speed not supported");
+			link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
+			break;
+		default:
+			ENETC_PMD_ERR("Unknown speed status");
+			break;
+		}
+	} else {
+		ENETC_PMD_ERR("Wrong reply message");
+		return -1;
+	}
+
+	link.link_autoneg = 1;
+
+	rte_eth_linkstatus_set(dev, &link);
+
+	rte_free(reply_msg);
+	return 0;
+}
+
 static int
 enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
 {
@@ -584,6 +796,7 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.promiscuous_disable  = enetc4_vf_promisc_disable,
 	.allmulticast_enable  = enetc4_vf_multicast_enable,
 	.allmulticast_disable = enetc4_vf_multicast_disable,
+	.link_update	      = enetc4_vf_link_update,
 	.vlan_offload_set     = enetc4_vf_vlan_offload_set,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,
@@ -685,6 +898,9 @@ enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
 	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);
+	/* update link */
+	enetc4_vf_link_update(eth_dev, 0);
+
 	return 0;
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 11/12] net/enetc: Add link status notification support
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (9 preceding siblings ...)
  2024-10-18  7:26 ` [v1 10/12] net/enetc: Add link speed and status support vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  2024-10-18  7:26 ` [v1 12/12] net/enetc: Add MAC and VLAN filter support vanshika.shukla
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla

From: Vanshika Shukla <vanshika.shukla@nxp.com>

This patch supports link event notifications for ENETC4 PMD, enabling:

- Link up/down event notifications
- Notification of link speed changes

Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |   1 +
 drivers/net/enetc/base/enetc4_hw.h  |   9 +-
 drivers/net/enetc/enetc.h           |   3 +
 drivers/net/enetc/enetc4_ethdev.c   |  16 ++-
 drivers/net/enetc/enetc4_vf.c       | 215 +++++++++++++++++++++++++++-
 5 files changed, 239 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 78b06e9841..31a1955215 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Link status event    = Y
 Speed capabilities   = Y
 Link status          = Y
 Promiscuous mode     = Y
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index d899b82b9c..2da779e351 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -128,7 +128,14 @@ struct enetc_msg_swbd {
 #define ENETC4_SITFRM0           0x328
 #define ENETC4_SITDFCR           0x340
 
-/* VSI MSG Registers */
+/* Station interface interrupts */
+#define ENETC4_SIMSIVR           0xA30
+#define ENETC4_VSIIER            0xA00
+#define ENETC4_VSIIDR            0xA08
+#define ENETC4_VSIIER_MRIE       BIT(9)
+#define ENETC4_SI_INT_IDX        0
+
+/* VSI Registers */
 #define ENETC4_VSIMSGSR  0x204   /* RO */
 #define ENETC4_VSIMSGSR_MB       BIT(0)
 #define ENETC4_VSIMSGSR_MS       BIT(1)
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 7f5329de33..6b37cd95dd 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -161,6 +161,8 @@ enum enetc_msg_cmd_id {
 	ENETC_CMD_ID_SET_MAC_PROMISCUOUS = 5,
 	ENETC_CMD_ID_SET_VLAN_PROMISCUOUS = 4,
 	ENETC_CMD_ID_GET_LINK_STATUS = 0,
+	ENETC_CMD_ID_REGISTER_LINK_NOTIF = 1,
+	ENETC_CMD_ID_UNREGISTER_LINK_NOTIF = 2,
 	ENETC_CMD_ID_GET_LINK_SPEED = 0
 };
 
@@ -280,6 +282,7 @@ const uint32_t *enetc4_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused
  * enetc4_vf function prototype
  */
 int enetc4_vf_dev_stop(struct rte_eth_dev *dev);
+int enetc4_vf_dev_intr(struct rte_eth_dev *eth_dev, bool enable);
 
 /*
  * RX/TX ENETC function prototypes
diff --git a/drivers/net/enetc/enetc4_ethdev.c b/drivers/net/enetc/enetc4_ethdev.c
index 29283f2d44..ab420aa301 100644
--- a/drivers/net/enetc/enetc4_ethdev.c
+++ b/drivers/net/enetc/enetc4_ethdev.c
@@ -605,10 +605,13 @@ enetc4_dev_close(struct rte_eth_dev *dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	if (hw->device_id == ENETC4_DEV_ID_VF)
+	if (hw->device_id == ENETC4_DEV_ID_VF) {
+		if (dev->data->dev_conf.intr_conf.lsc != 0)
+			enetc4_vf_dev_intr(dev, false);
 		ret = enetc4_vf_dev_stop(dev);
-	else
+	} else {
 		ret = enetc4_dev_stop(dev);
+	}
 
 	if (dev->data->nb_rx_queues > 1) {
 		/* Disable RSS */
@@ -719,6 +722,15 @@ enetc4_dev_configure(struct rte_eth_dev *dev)
 
 	enetc4_port_wr(enetc_hw, ENETC4_PARCSCR, checksum);
 
+	/* Enable interrupts */
+	if (hw->device_id == ENETC4_DEV_ID_VF) {
+		if (dev->data->dev_conf.intr_conf.lsc != 0) {
+			ret = enetc4_vf_dev_intr(dev, true);
+			if (ret)
+				ENETC_PMD_WARN("Failed to setup link interrupts");
+		}
+	}
+
 	/* Disable and reset RX and TX rings */
 	for (i = 0; i < dev->data->nb_rx_queues; i++)
 		enetc4_rxbdr_wr(enetc_hw, i, ENETC_RBMR, ENETC_BMR_RESET);
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 307fabf2c6..22266188ee 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -144,6 +144,69 @@ enetc4_msg_vsi_reply_msg(struct enetc_hw *enetc_hw, struct enetc_psi_reply_msg *
 	reply_msg->status = status;
 }
 
+static void
+enetc4_msg_get_psi_msg(struct enetc_hw *enetc_hw, struct enetc_psi_reply_msg *reply_msg)
+{
+	int vsimsgrr;
+	int8_t class_id = 0;
+	uint8_t status = 0;
+
+	vsimsgrr = enetc_rd(enetc_hw, ENETC4_VSIMSGRR);
+
+	/* Extracting 8 bits of message result in class_id */
+	class_id |= ((ENETC_SIMSGSR_GET_MC(vsimsgrr) >> 8) & 0xff);
+
+	/* Extracting 4 bits of message result in status */
+	status |= ((ENETC_SIMSGSR_GET_MC(vsimsgrr) >> 4) & 0xf);
+
+	reply_msg->class_id = class_id;
+	reply_msg->status = status;
+}
+
+static void
+enetc4_process_psi_msg(struct rte_eth_dev *eth_dev, struct enetc_hw *enetc_hw)
+{
+	struct enetc_psi_reply_msg *msg;
+	struct rte_eth_link link;
+	int ret = 0;
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		return;
+	}
+
+	rte_eth_linkstatus_get(eth_dev, &link);
+	enetc4_msg_get_psi_msg(enetc_hw, msg);
+
+	if (msg->class_id == ENETC_CLASS_ID_LINK_STATUS) {
+		switch (msg->status) {
+		case ENETC_LINK_UP:
+			ENETC_PMD_DEBUG("Link is up");
+			link.link_status = RTE_ETH_LINK_UP;
+			break;
+		case ENETC_LINK_DOWN:
+			ENETC_PMD_DEBUG("Link is down");
+			link.link_status = RTE_ETH_LINK_DOWN;
+			break;
+		default:
+			ENETC_PMD_ERR("Unknown link status 0x%x", msg->status);
+			break;
+		}
+		ret = rte_eth_linkstatus_set(eth_dev, &link);
+		if (!ret)
+			ENETC_PMD_DEBUG("Link status has been changed");
+
+		/* Process user registered callback */
+		rte_eth_dev_callback_process(eth_dev,
+			RTE_ETH_EVENT_INTR_LSC, NULL);
+	} else {
+		ENETC_PMD_ERR("Wrong message 0x%x", msg->class_id);
+	}
+
+	rte_free(msg);
+}
+
 static int
 enetc4_msg_vsi_send(struct enetc_hw *enetc_hw, struct enetc_msg_swbd *msg)
 {
@@ -775,6 +838,55 @@ static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_un
 	return 0;
 }
 
+static int
+enetc4_vf_link_register_notif(struct rte_eth_dev *dev, bool enable)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_swbd *msg;
+	struct rte_eth_link link;
+	int msg_size;
+	int err = 0;
+	uint8_t cmd;
+
+	PMD_INIT_FUNC_TRACE();
+	memset(&link, 0, sizeof(struct rte_eth_link));
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_get_link_status), ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		return -ENOMEM;
+	}
+
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+	if (enable)
+		cmd = ENETC_CMD_ID_REGISTER_LINK_NOTIF;
+	else
+		cmd = ENETC_CMD_ID_UNREGISTER_LINK_NOTIF;
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_LINK_STATUS,
+			cmd, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err)
+		ENETC_PMD_ERR("VSI msg error for link status notification");
+
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(msg);
+
+	return err;
+}
+
 /*
  * The set of PCI devices this driver supports
  */
@@ -866,6 +978,45 @@ enetc4_vf_mac_init(struct enetc_eth_hw *hw, struct rte_eth_dev *eth_dev)
 	return 0;
 }
 
+static void
+enetc_vf_enable_mr_int(struct enetc_hw *hw, bool en)
+{
+	uint32_t val;
+
+	val = enetc_rd(hw, ENETC4_VSIIER);
+	val &= ~ENETC4_VSIIER_MRIE;
+	val |= (en) ? ENETC4_VSIIER_MRIE : 0;
+	enetc_wr(hw, ENETC4_VSIIER, val);
+	ENETC_PMD_DEBUG("Interrupt enable status (VSIIER) = 0x%x", val);
+}
+
+static void
+enetc4_dev_interrupt_handler(void *param)
+{
+	struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param;
+	struct enetc_eth_hw *hw =
+		ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	uint32_t status;
+
+	/* Disable interrupts before process */
+	enetc_vf_enable_mr_int(enetc_hw, false);
+
+	status = enetc_rd(enetc_hw, ENETC4_VSIIDR);
+	ENETC_PMD_DEBUG("Got INTR VSIIDR status = 0x%0x", status);
+	/* Check for PSI to VSI message interrupt */
+	if (!(status & ENETC4_VSIIER_MRIE)) {
+		ENETC_PMD_ERR("Interrupt is not PSI to VSI");
+		goto intr_clear;
+	}
+
+	enetc4_process_psi_msg(eth_dev, enetc_hw);
+intr_clear:
+	/* Clear Interrupts */
+	enetc_wr(enetc_hw, ENETC4_VSIIDR, 0xffffffff);
+	enetc_vf_enable_mr_int(enetc_hw, true);
+}
+
 static int
 enetc4_vf_dev_init(struct rte_eth_dev *eth_dev)
 {
@@ -913,14 +1064,74 @@ enetc4_vf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 					     enetc4_vf_dev_init);
 }
 
+int
+enetc4_vf_dev_intr(struct rte_eth_dev *eth_dev, bool enable)
+{
+	struct enetc_eth_hw *hw =
+		ENETC_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	int ret = 0;
+
+	PMD_INIT_FUNC_TRACE();
+	if (!(intr_handle && rte_intr_fd_get(intr_handle))) {
+		ENETC_PMD_ERR("No INTR handle");
+		return -1;
+	}
+	if (enable) {
+		/* if the interrupts were configured on this devices*/
+		ret = rte_intr_callback_register(intr_handle,
+				enetc4_dev_interrupt_handler, eth_dev);
+		if (ret) {
+			ENETC_PMD_ERR("Failed to register INTR callback %d", ret);
+			return ret;
+		}
+		/* set one IRQ entry for PSI-to-VSI messaging */
+		/* Vector index 0 */
+		enetc_wr(enetc_hw, ENETC4_SIMSIVR, ENETC4_SI_INT_IDX);
+
+		/* enable uio/vfio intr/eventfd mapping */
+		ret = rte_intr_enable(intr_handle);
+		if (ret) {
+			ENETC_PMD_ERR("Failed to enable INTR %d", ret);
+			goto intr_enable_fail;
+		}
+
+		/* Enable message received interrupt */
+		enetc_vf_enable_mr_int(enetc_hw, true);
+		ret = enetc4_vf_link_register_notif(eth_dev, true);
+		if (ret) {
+			ENETC_PMD_ERR("Failed to register link notifications %d", ret);
+			goto disable;
+		}
+
+		return ret;
+	}
+
+	ret = enetc4_vf_link_register_notif(eth_dev, false);
+	if (ret)
+		ENETC_PMD_WARN("Failed to un-register link notification %d", ret);
+disable:
+	enetc_vf_enable_mr_int(enetc_hw, false);
+	ret = rte_intr_disable(intr_handle);
+	if (ret)
+		ENETC_PMD_WARN("Failed to disable INTR %d", ret);
+intr_enable_fail:
+	rte_intr_callback_unregister(intr_handle,
+			enetc4_dev_interrupt_handler, eth_dev);
+
+	return ret;
+}
+
 static struct rte_pci_driver rte_enetc4_vf_pmd = {
 	.id_table = pci_vf_id_enetc4_map,
-	.drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
 	.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_PMD_REGISTER_KMOD_DEP(net_enetc4_vf, "* igb_uio | uio_pci_generic");
 RTE_LOG_REGISTER_DEFAULT(enetc4_vf_logtype_pmd, NOTICE);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v1 12/12] net/enetc: Add MAC and VLAN filter support
  2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
                   ` (10 preceding siblings ...)
  2024-10-18  7:26 ` [v1 11/12] net/enetc: Add link status notification support vanshika.shukla
@ 2024-10-18  7:26 ` vanshika.shukla
  11 siblings, 0 replies; 13+ messages in thread
From: vanshika.shukla @ 2024-10-18  7:26 UTC (permalink / raw)
  To: dev, Gagandeep Singh, Sachin Saxena, Vanshika Shukla

From: Vanshika Shukla <vanshika.shukla@nxp.com>

Introduces support for:

- Up to 4 MAC addresses filtering
- Up to 4 VLAN filters

Enhances packet filtering capabilities for ENETC4 PMD.

Signed-off-by: Vanshika Shukla <vanshika.shukla@nxp.com>
Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc4.ini |   2 +
 drivers/net/enetc/base/enetc4_hw.h  |   3 +
 drivers/net/enetc/enetc.h           |  11 ++
 drivers/net/enetc/enetc4_vf.c       | 229 +++++++++++++++++++++++++++-
 4 files changed, 244 insertions(+), 1 deletion(-)

diff --git a/doc/guides/nics/features/enetc4.ini b/doc/guides/nics/features/enetc4.ini
index 31a1955215..87425f45c9 100644
--- a/doc/guides/nics/features/enetc4.ini
+++ b/doc/guides/nics/features/enetc4.ini
@@ -9,6 +9,8 @@ Speed capabilities   = Y
 Link status          = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
+Unicast MAC filter   = Y
+VLAN filter          = Y
 RSS hash             = Y
 Packet type parsing  = Y
 Basic stats          = Y
diff --git a/drivers/net/enetc/base/enetc4_hw.h b/drivers/net/enetc/base/enetc4_hw.h
index 2da779e351..e3eef6fe19 100644
--- a/drivers/net/enetc/base/enetc4_hw.h
+++ b/drivers/net/enetc/base/enetc4_hw.h
@@ -71,6 +71,9 @@ struct enetc_msg_swbd {
  */
 #define ENETC4_MAC_MAXFRM_SIZE  2000
 
+/* Number of MAC Address Filter table entries */
+#define ENETC4_MAC_ENTRIES      4
+
 /* Port MAC 0/1 Maximum Frame Length Register */
 #define ENETC4_PM_MAXFRM(mac)		(0x5014 + (mac) * 0x400)
 
diff --git a/drivers/net/enetc/enetc.h b/drivers/net/enetc/enetc.h
index 6b37cd95dd..e79a0bf0a9 100644
--- a/drivers/net/enetc/enetc.h
+++ b/drivers/net/enetc/enetc.h
@@ -158,7 +158,10 @@ enum enetc_msg_cmd_class_id {
 /* Enum for command IDs */
 enum enetc_msg_cmd_id {
 	ENETC_CMD_ID_SET_PRIMARY_MAC = 0,
+	ENETC_MSG_ADD_EXACT_MAC_ENTRIES = 1,
 	ENETC_CMD_ID_SET_MAC_PROMISCUOUS = 5,
+	ENETC_MSG_ADD_EXACT_VLAN_ENTRIES = 0,
+	ENETC_MSG_REMOVE_EXACT_VLAN_ENTRIES = 1,
 	ENETC_CMD_ID_SET_VLAN_PROMISCUOUS = 4,
 	ENETC_CMD_ID_GET_LINK_STATUS = 0,
 	ENETC_CMD_ID_REGISTER_LINK_NOTIF = 1,
@@ -170,6 +173,14 @@ enum mac_addr_status {
 	ENETC_INVALID_MAC_ADDR = 0x0,
 	ENETC_DUPLICATE_MAC_ADDR = 0X1,
 	ENETC_MAC_ADDR_NOT_FOUND = 0X2,
+	ENETC_MAC_FILTER_NO_RESOURCE = 0x3
+};
+
+enum vlan_status {
+	ENETC_INVALID_VLAN_ENTRY = 0x0,
+	ENETC_DUPLICATE_VLAN_ENTRY = 0X1,
+	ENETC_VLAN_ENTRY_NOT_FOUND = 0x2,
+	ENETC_VLAN_NO_RESOURCE = 0x3
 };
 
 enum link_status {
diff --git a/drivers/net/enetc/enetc4_vf.c b/drivers/net/enetc/enetc4_vf.c
index 22266188ee..fb27557378 100644
--- a/drivers/net/enetc/enetc4_vf.c
+++ b/drivers/net/enetc/enetc4_vf.c
@@ -17,6 +17,10 @@
 uint16_t enetc_crc_table[ENETC_CRC_TABLE_SIZE];
 bool enetc_crc_gen;
 
+/* Supported Rx offloads */
+static uint64_t dev_vf_rx_offloads_sup =
+	RTE_ETH_RX_OFFLOAD_VLAN_FILTER;
+
 static void
 enetc_gen_crc_table(void)
 {
@@ -53,6 +57,25 @@ enetc_crc_calc(uint16_t crc, const uint8_t *buffer, size_t len)
 	return crc;
 }
 
+static int
+enetc4_vf_dev_infos_get(struct rte_eth_dev *dev,
+			struct rte_eth_dev_info *dev_info)
+{
+	int ret = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	ret = enetc4_dev_infos_get(dev, dev_info);
+	if (ret)
+		return ret;
+
+	dev_info->max_mtu = dev_info->max_rx_pktlen - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN);
+	dev_info->max_mac_addrs = ENETC4_MAC_ENTRIES;
+	dev_info->rx_offload_capa |= dev_vf_rx_offloads_sup;
+
+	return 0;
+}
+
 int
 enetc4_vf_dev_stop(struct rte_eth_dev *dev __rte_unused)
 {
@@ -810,6 +833,201 @@ enetc4_vf_vlan_promisc(struct rte_eth_dev *dev, bool promisc_en)
 	return err;
 }
 
+static int
+enetc4_vf_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *addr,
+			uint32_t index __rte_unused, uint32_t pool __rte_unused)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_cmd_set_primary_mac *cmd;
+	struct enetc_msg_swbd *msg;
+	struct enetc_psi_reply_msg *reply_msg;
+	int msg_size;
+	int err = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	if (!rte_is_valid_assigned_ether_addr(addr))
+		return -EINVAL;
+
+	reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
+	if (!reply_msg) {
+		ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
+		return -ENOMEM;
+	}
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		rte_free(reply_msg);
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac),
+			ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		rte_free(reply_msg);
+		return -ENOMEM;
+	}
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+	cmd = (struct enetc_msg_cmd_set_primary_mac *)msg->vaddr;
+	memcpy(&cmd->addr.addr_bytes, addr, sizeof(struct rte_ether_addr));
+	cmd->count = 1;
+
+	enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_MAC_FILTER,
+			ENETC_MSG_ADD_EXACT_MAC_ENTRIES, 0, 0, 0);
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+	enetc4_msg_vsi_reply_msg(enetc_hw, reply_msg);
+
+	if (reply_msg->class_id == ENETC_CLASS_ID_MAC_FILTER) {
+		switch (reply_msg->status) {
+		case ENETC_INVALID_MAC_ADDR:
+			ENETC_PMD_ERR("Invalid MAC address");
+			err = -EINVAL;
+			break;
+		case ENETC_DUPLICATE_MAC_ADDR:
+			ENETC_PMD_ERR("Duplicate MAC address");
+			err = -EINVAL;
+			break;
+		case ENETC_MAC_FILTER_NO_RESOURCE:
+			ENETC_PMD_ERR("Not enough exact-match entries available");
+			err = -EINVAL;
+			break;
+		default:
+			err = -EINVAL;
+			break;
+		}
+	}
+
+	if (err) {
+		ENETC_PMD_ERR("VSI command execute error!");
+		goto end;
+	}
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(reply_msg);
+	rte_free(msg);
+	return err;
+}
+
+static int enetc4_vf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
+{
+	struct enetc_eth_hw *hw = ENETC_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct enetc_hw *enetc_hw = &hw->hw;
+	struct enetc_msg_vlan_exact_filter *cmd;
+	struct enetc_msg_swbd *msg;
+	struct enetc_psi_reply_msg *reply_msg;
+	int msg_size;
+	int err = 0;
+
+	PMD_INIT_FUNC_TRACE();
+
+	reply_msg = rte_zmalloc(NULL, sizeof(*reply_msg), RTE_CACHE_LINE_SIZE);
+	if (!reply_msg) {
+		ENETC_PMD_ERR("Failed to alloc memory for reply_msg");
+		return -ENOMEM;
+	}
+
+	msg = rte_zmalloc(NULL, sizeof(*msg), RTE_CACHE_LINE_SIZE);
+	if (!msg) {
+		ENETC_PMD_ERR("Failed to alloc msg");
+		err = -ENOMEM;
+		rte_free(reply_msg);
+		return err;
+	}
+
+	msg_size = RTE_ALIGN(sizeof(struct enetc_msg_vlan_exact_filter),
+			ENETC_VSI_PSI_MSG_SIZE);
+	msg->vaddr = rte_zmalloc(NULL, msg_size, 0);
+	if (!msg->vaddr) {
+		ENETC_PMD_ERR("Failed to alloc memory for msg");
+		rte_free(msg);
+		rte_free(reply_msg);
+		return -ENOMEM;
+	}
+	msg->dma = rte_mem_virt2iova((const void *)msg->vaddr);
+	msg->size = msg_size;
+	cmd = (struct enetc_msg_vlan_exact_filter *)msg->vaddr;
+	cmd->vlan_count = 1;
+	cmd->vlan_id = vlan_id;
+
+	/* TPID 2-bit encoding value is taken from the H/W block guide:
+	 *	00b Standard C-VLAN 0x8100
+	 *	01b Standard S-VLAN 0x88A8
+	 *	10b Custom VLAN as defined by CVLANR1[ETYPE]
+	 *	11b Custom VLAN as defined by CVLANR2[ETYPE]
+	 * Currently Standard C-VLAN is supported. To support others in future.
+	 */
+	cmd->tpid = 0;
+
+	if (on) {
+		enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
+				ENETC_MSG_ADD_EXACT_VLAN_ENTRIES, 0, 0, 0);
+	} else {
+		enetc_msg_vf_fill_common_hdr(msg, ENETC_CLASS_ID_VLAN_FILTER,
+				ENETC_MSG_REMOVE_EXACT_VLAN_ENTRIES, 0, 0, 0);
+	}
+
+	/* send the command and wait */
+	err = enetc4_msg_vsi_send(enetc_hw, msg);
+	if (err) {
+		ENETC_PMD_ERR("VSI message send error");
+		goto end;
+	}
+
+	enetc4_msg_vsi_reply_msg(enetc_hw, reply_msg);
+
+	if (reply_msg->class_id == ENETC_CLASS_ID_VLAN_FILTER) {
+		switch (reply_msg->status) {
+		case ENETC_INVALID_VLAN_ENTRY:
+			ENETC_PMD_ERR("VLAN entry not valid");
+			err = -EINVAL;
+			break;
+		case ENETC_DUPLICATE_VLAN_ENTRY:
+			ENETC_PMD_ERR("Duplicated VLAN entry");
+			err = -EINVAL;
+			break;
+		case ENETC_VLAN_ENTRY_NOT_FOUND:
+			ENETC_PMD_ERR("VLAN entry not found");
+			err = -EINVAL;
+			break;
+		case ENETC_VLAN_NO_RESOURCE:
+			ENETC_PMD_ERR("Not enough exact-match entries available");
+			err = -EINVAL;
+			break;
+		default:
+			err = -EINVAL;
+			break;
+		}
+	}
+
+	if (err) {
+		ENETC_PMD_ERR("VSI command execute error!");
+		goto end;
+	}
+
+end:
+	/* free memory no longer required */
+	rte_free(msg->vaddr);
+	rte_free(reply_msg);
+	rte_free(msg);
+	return err;
+}
+
 static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_unused)
 {
 	int err = 0;
@@ -838,6 +1056,12 @@ static int enetc4_vf_vlan_offload_set(struct rte_eth_dev *dev, int mask __rte_un
 	return 0;
 }
 
+static int
+enetc4_vf_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
+{
+	return 0;
+}
+
 static int
 enetc4_vf_link_register_notif(struct rte_eth_dev *dev, bool enable)
 {
@@ -901,14 +1125,17 @@ static const struct eth_dev_ops enetc4_vf_ops = {
 	.dev_start            = enetc4_vf_dev_start,
 	.dev_stop             = enetc4_vf_dev_stop,
 	.dev_close            = enetc4_dev_close,
-	.dev_infos_get        = enetc4_dev_infos_get,
 	.stats_get            = enetc4_vf_stats_get,
+	.dev_infos_get        = enetc4_vf_dev_infos_get,
+	.mtu_set              = enetc4_vf_mtu_set,
 	.mac_addr_set         = enetc4_vf_set_mac_addr,
+	.mac_addr_add	      = enetc4_vf_mac_addr_add,
 	.promiscuous_enable   = enetc4_vf_promisc_enable,
 	.promiscuous_disable  = enetc4_vf_promisc_disable,
 	.allmulticast_enable  = enetc4_vf_multicast_enable,
 	.allmulticast_disable = enetc4_vf_multicast_disable,
 	.link_update	      = enetc4_vf_link_update,
+	.vlan_filter_set      = enetc4_vf_vlan_filter_set,
 	.vlan_offload_set     = enetc4_vf_vlan_offload_set,
 	.rx_queue_setup       = enetc4_rx_queue_setup,
 	.rx_queue_start       = enetc4_rx_queue_start,
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-10-18  7:28 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-18  7:26 [v1 00/12] ENETC4 PMD support vanshika.shukla
2024-10-18  7:26 ` [v1 01/12] net/enetc: Add initial ENETC4 PMD driver support vanshika.shukla
2024-10-18  7:26 ` [v1 02/12] net/enetc: Add RX and TX queue APIs for ENETC4 PMD vanshika.shukla
2024-10-18  7:26 ` [v1 03/12] net/enetc: Optimize ENETC4 data path vanshika.shukla
2024-10-18  7:26 ` [v1 04/12] net/enetc: Add TX checksum offload and RX checksum validation vanshika.shukla
2024-10-18  7:26 ` [v1 05/12] net/enetc: Add basic statistics vanshika.shukla
2024-10-18  7:26 ` [v1 06/12] net/enetc: Add packet type parsing support vanshika.shukla
2024-10-18  7:26 ` [v1 07/12] net/enetc: Add support for multiple queues with RSS vanshika.shukla
2024-10-18  7:26 ` [v1 08/12] net/enetc: Add VF to PF messaging support and primary MAC setup vanshika.shukla
2024-10-18  7:26 ` [v1 09/12] net/enetc: Add multicast and promiscuous mode support vanshika.shukla
2024-10-18  7:26 ` [v1 10/12] net/enetc: Add link speed and status support vanshika.shukla
2024-10-18  7:26 ` [v1 11/12] net/enetc: Add link status notification support vanshika.shukla
2024-10-18  7:26 ` [v1 12/12] net/enetc: Add MAC and VLAN filter support vanshika.shukla

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).