RE: [PATCH] net: Explicitly include correct DT includes

2023-07-16 Thread Wei Fang
> -Original Message-
> From: Rob Herring 
> Sent: 2023年7月15日 1:48
> To: Dario Binacchi ; Wolfgang
> Grandegger ; Marc Kleine-Budde
> ; David S. Miller ; Eric
> Dumazet ; Jakub Kicinski ; Paolo
> Abeni ; Chandrasekar Ramakrishnan
> ; Chen-Yu Tsai ; Jernej Skrabec
> ; Samuel Holland ; Florian
> Fainelli ; Andrew Lunn ;
> Vladimir Oltean ; Kurt Kanzenbach ;
> Woojung Huh ;
> unglinuxdri...@microchip.com; Arınç ÜNAL ;
> Daniel Golle ; Landen Chao
> ; DENG Qingfang ; Sean
> Wang ; Matthias Brugger
> ; AngeloGioacchino Del Regno
> ; Claudiu Manoil
> ; Alexandre Belloni
> ; Linus Walleij ;
> Alvin Šipraga ; George McCollister
> ; Andreas Larsson ;
> Iyappan Subramanian ; Keyur Chudgar
> ; Chris Snook ;
> Nicolas Ferre ; Claudiu Beznea
> ; Madalin Bucur ;
> Wei Fang ; Shenwei Wang ;
> Clark Wang ; dl-linux-imx ;
> Sean Anderson ; Pantelis Antoniou
> ; Leo Li ; Yisen Zhuang
> ; Salil Mehta ;
> Douglas Miller ; Marcin Wojtas
> ; Russell King ; Tara s Chornyi
> ; Mirko Lindner ;
> Stephen Hemminger ; Felix Fietkau
> ; John Crispin ; Mark Lee
> ; Lorenzo Bianconi ;
> Horatiu Vultur ; Timur Tabi
> ; Sergey Shtylyov ; Steve Glendinning
> ; Kunihiko Hayashi
> ; Giuseppe Cavallaro
> ; Alexandre Torgue ;
> Jose Abreu ; Maxime Coquelin
> ; Shawn Guo ; Sascha
> Hauer ; Pengutronix Kernel Team
> ; Fabio Estevam ; Neil
> Armstrong ; Kevin Hilman
> ; Jerome Brunet ; Martin
> Blumenstingl ; Vinod Ko ul
> ; Bhupesh Sharma ; Emil
> Renner Berthing ; Samin Guo
> ; Thierry Reding ;
> Jonathan Hunter ; Nobuhiro Iwamatsu
> ; Grygorii Strashko
> ; Kevin Brace
> ; Francois Romieu
> ; Michal Simek ; Radhey
> Shyam Pandey ; Alexander Aring
> ; Stefan Schmidt ;
> Miquel Raynal ; Alex Elder ;
> Clément Léger ; Heiner Kallweit
> ; SkyLake Huang ;
> Kalle Valo ; Loic Poulain ; Ryder
> Lee ; Shayne Chen ;
> Jérôme Pouille r ; Richard Cochran
> 
> Cc: devicet...@vger.kernel.org; linux-...@vger.kernel.org;
> net...@vger.kernel.org; linux-ker...@vger.kernel.org;
> linux-arm-ker...@lists.infradead.org; linux-su...@lists.linux.dev;
> linux-media...@lists.infradead.org; linuxppc-dev@lists.ozlabs.org;
> linux-renesas-...@vger.kernel.org;
> linux-st...@st-md-mailman.stormreply.com;
> linux-amlo...@lists.infradead.org; linux-ox...@groups.io;
> linux-te...@vger.kernel.org; linux-o...@vger.kernel.org;
> linux-w...@vger.kernel.org; ath...@lists.infradead.org;
> linux-wirel...@vger.kernel.org; ath...@lists.infradead.org;
> wcn3...@lists.infradead.org
> Subject: [PATCH] net: Explicitly include correct DT includes
> 
> The DT of_device.h and of_platform.h date back to the separate
> of_platform_bus_type before it as merged into the regular platform bus.
> As part of that merge prepping Arm DT support 13 years ago, they
> "temporarily" include each other. They also include platform_device.h and 
> of.h.
> As a result, there's a pretty much random mix of those include files used
> throughout the tree. In order to detangle these headers and replace the
> implicit includes with struct declarations, users need to explicitly include 
> the
> correct includes.
> 
> Signed-off-by: Rob Herring 
> ---
> diff --git a/drivers/net/ethernet/freescale/fec_ptp.c
> b/drivers/net/ethernet/freescale/fec_ptp.c
> index ab86bb8562ef..9428a06b6a87 100644
> --- a/drivers/net/ethernet/freescale/fec_ptp.c
> +++ b/drivers/net/ethernet/freescale/fec_ptp.c
> @@ -30,7 +30,6 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  #include 
>  #include 
> 
Thanks!
Reviewed-by: Wei Fang 



RE: [PATCH] net: Use of_property_read_bool() for boolean properties

2023-03-13 Thread Wei Fang
> -Original Message-
> From: Rob Herring 
> Sent: 2023年3月10日 22:47
> To: Wolfgang Grandegger ; Marc Kleine-Budde
> ; David S. Miller ; Eric
> Dumazet ; Jakub Kicinski ; Paolo
> Abeni ; Nicolas Ferre ;
> Claudiu Beznea ; Wei Fang
> ; Shenwei Wang ; Clark Wang
> ; dl-linux-imx ; Claudiu
> Manoil ; Giuseppe Cavallaro
> ; Alexandre Torgue ;
> Jose Abreu ; Shawn Guo ;
> Sascha Hauer ; Pengutronix Kernel Team
> ; Fabio Estevam ; Maxime
> Coquelin ; Grygorii Strashko
> ; Francois Romieu ; Michal
> Simek ; Qiang Zhao ; Kalle
> Valo ; Samuel Mendoza-Jonas 
> Cc: devicet...@vger.kernel.org; linux-...@vger.kernel.org;
> net...@vger.kernel.org; linux-ker...@vger.kernel.org;
> linux-st...@st-md-mailman.stormreply.com;
> linux-arm-ker...@lists.infradead.org; linux-o...@vger.kernel.org;
> linuxppc-dev@lists.ozlabs.org; linux-wirel...@vger.kernel.org
> Subject: [PATCH] net: Use of_property_read_bool() for boolean properties
> 
> It is preferred to use typed property access functions (i.e.
> of_property_read_ functions) rather than low-level
> of_get_property/of_find_property functions for reading properties.
> Convert reading boolean properties to to of_property_read_bool().
> 
> Signed-off-by: Rob Herring 
> ---
>  drivers/net/ethernet/freescale/fec_main.c   |  2 +-

Reviewed-by: Wei Fang 




[PATCH net] net: enetc: add missing static descriptor and inline keyword

2024-10-10 Thread Wei Fang
Fix the build warnings when CONFIG_FSL_ENETC_MDIO is not enabled.
The detailed warnings are shown as follows.

include/linux/fsl/enetc_mdio.h:62:18: warning: no previous prototype for 
function 'enetc_hw_alloc' [-Wmissing-prototypes]
  62 | struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem 
*port_regs)
 |  ^
include/linux/fsl/enetc_mdio.h:62:1: note: declare 'static' if the function is 
not intended to be used outside of this translation unit
  62 | struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem 
*port_regs)
 | ^
 | static
8 warnings generated.

Fixes: 6517798dd343 ("enetc: Make MDIO accessors more generic and export to 
include/linux/fsl")
Cc: sta...@vger.kernel.org
Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202410102136.jqhzocs4-...@intel.com/
Signed-off-by: Wei Fang 
---
 include/linux/fsl/enetc_mdio.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/fsl/enetc_mdio.h b/include/linux/fsl/enetc_mdio.h
index df25fffdc0ae..623ccfcbf39c 100644
--- a/include/linux/fsl/enetc_mdio.h
+++ b/include/linux/fsl/enetc_mdio.h
@@ -59,7 +59,8 @@ static inline int enetc_mdio_read_c45(struct mii_bus *bus, 
int phy_id,
 static inline int enetc_mdio_write_c45(struct mii_bus *bus, int phy_id,
   int devad, int regnum, u16 value)
 { return -EINVAL; }
-struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
+static inline struct enetc_hw *enetc_hw_alloc(struct device *dev,
+ void __iomem *port_regs)
 { return ERR_PTR(-EINVAL); }
 
 #endif
-- 
2.34.1




RE: [PATCH net-next 05/13] net: enetc: add debugfs interface to dump MAC filter

2025-01-05 Thread Wei Fang
> Subject: Re: [PATCH net-next 05/13] net: enetc: add debugfs interface to dump
> MAC filter
> 
> On Fri, Jan 03, 2025 at 02:06:01PM +0800, Wei Fang wrote:
> > ENETC's MAC filter consists of hash MAC filter and exact MAC filter. Hash
> > MAC filter is a 64-entry hash table consisting of two 32-bit registers.
> > Exact MAC filter is implemented by configuring MAC address filter table
> > through command BD ring. The table is stored in ENETC's internal memory
> > and needs to be read through command BD ring. In order to facilitate
> > debugging, added a debugfs interface to get the relevant information
> > about MAC filter.
> 
> How do other drivers do this?

I don't know about other vendor's hardware, but IMO, if the configuration is
done through registers, we only need to debug through some tools that read
and write registers, such as devmem2. I also saw some drivers added debugfs
interface, such as Intel, Huawei, Marvell, etc. I think they also added it to
facilitate obtaining some debugging information.

> 
> You should only use debugfs if there is no standard way to accomplish
> something. And if there is no standard way, you should be thinking is
> this a common feature other drivers will need, and if so, add a
> standard mechanism.
> 
> You will get pushback for using debugfs as a bumping ground without
> adding some justification that debugfs is the only possible solution.
> 

IMO, standard methods are only suitable for extracting common
information, but each vendor's implementation is not uniform, and the
specific details are also different. It is impossible to obtain every detail
information through standard methods. The purpose of adding debugfs
is just to facilitate debugging, so we need to obtain all the detailed
information, so I think the debugfs interface is good, which allows us to
obtain every specific information in all NETC tables.




[PATCH net-next 04/13] net: enetc: add MAC filter for i.MX95 ENETC PF

2025-01-02 Thread Wei Fang
The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bits hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.

For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.

Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 411 +-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  11 +
 5 files changed, 437 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 9380d3e8ca01..4dba91408e3d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -316,6 +316,8 @@ struct enetc_si {
const struct enetc_si_ops *ops;
 
struct enetc_mac_filter mac_filter[MADDR_TYPE];
+   struct workqueue_struct *workqueue;
+   struct work_struct rx_mode_task;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
 #define ENETC4_PSICFGR2(a) ((a) * 0x80 + 0x2018)
 #define  PSICFGR2_NUM_MSIX GENMASK(5, 0)
 
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a)((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a)((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index b957e92e3a00..6ec849949267 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
 
 #define ENETC_SI_MAX_RING_NUM  8
 
+#define ENETC_MAC_FILTER_TYPE_UC   BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC   BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL  (ENETC_MAC_FILTER_TYPE_UC | \
+ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+   u8 addr[ETH_ALEN];
+};
+
 static void enetc4_get_port_caps(struct enetc_pf *pf)
 {
struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 
val = enetc_port_rd(hw, ENETC4_PMCAPR);
pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+   val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+   pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
 }
 
 static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -71,9 +83,33 @@ static int enetc4_pf_struct_init(struct enetc_si *si)
 
enetc4_get_port_caps(pf);
 
+   INIT_HLIST_HEAD(&pf->mac_list);
+   mutex_init(&pf->mac_list_lock);
+
return 0;
 }
 
+static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
+{
+   struct enetc_mac_list_entry *entry;
+   struct hlist_node *tmp;
+
+   scoped_guard(mutex, &pf->mac_list_lock) {
+   hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
+   hlist_del(&entry->node);
+   kfree(entry);
+   }
+
+   pf->num_mfe = 0;
+   }
+}
+
+static void enetc4_pf_struct_free(struct enetc_pf *pf)
+{
+   enetc4_pf_destroy_mac_list(pf);
+   mutex_destroy(&pf->mac_list_lock);
+}
+

[PATCH net-next 02/13] net: enetc: add command BD ring support for i.MX95 ENETC

2025-01-02 Thread Wei Fang
The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).

Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. In order to
ensure driver compatibility, struct enetc_si_ops is introduced. This
structure defines some hooks shared by VSI and PSI. Different hardware
driver will register different hooks, For example, setup_cbdr() is used
to initialize the command BD ring, and teardown_cbdr() is used to free
the command BD ring.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  | 27 --
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 47 -
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 51 ---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 13 +++--
 .../net/ethernet/freescale/enetc/enetc_vf.c   | 13 +++--
 5 files changed, 132 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..4ff0957e69be 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -266,6 +267,19 @@ struct enetc_platform_info {
const struct enetc_drvdata *data;
 };
 
+struct enetc_si;
+
+/*
+ * This structure defines the some common hooks for ENETC PSI and VSI.
+ * In addition, since VSI only uses the struct enetc_si as its private
+ * driver data, so this structure also define some hooks specifically
+ * for VSI. For VSI-specific hooks, the format is ???vf_*()???.
+ */
+struct enetc_si_ops {
+   int (*setup_cbdr)(struct enetc_si *si);
+   void (*teardown_cbdr)(struct enetc_si *si);
+};
+
 /* PCI IEP device data */
 struct enetc_si {
struct pci_dev *pdev;
@@ -274,7 +288,10 @@ struct enetc_si {
 
struct net_device *ndev; /* back ref. */
 
-   struct enetc_cbdr cbd_ring;
+   union {
+   struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+   struct ntmp_priv ntmp; /* ENETC 4.1 and later */
+   };
 
int num_rx_rings; /* how many rings are available in the SI */
int num_tx_rings;
@@ -284,6 +301,7 @@ struct enetc_si {
u16 revision;
int hw_features;
const struct enetc_drvdata *drvdata;
+   const struct enetc_si_ops *ops;
 };
 
 #define ENETC_SI_ALIGN 32
@@ -490,9 +508,10 @@ void enetc_mm_link_state_update(struct enetc_ndev_priv 
*priv, bool link);
 void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
 
 /* control buffer descriptor ring (CBDR) */
-int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
-struct enetc_cbdr *cbdr);
-void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc_setup_cbdr(struct enetc_si *si);
+void enetc_teardown_cbdr(struct enetc_si *si);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index fc41078c4f5d..b957e92e3a00 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,23 @@ static void enetc4_configure_port(struct enetc_pf *pf)
enetc4_enable_trx(pf);
 }
 
+static int enetc4_init_ntmp_priv(struct enetc_si *si)
+{
+   struct ntmp_priv *ntmp = &si->ntmp;
+
+   ntmp->dev_type = NETC_DEV_ENETC;
+
+   /* For ENETC 4.1, all table versions are 0 */
+   memset(&ntmp->cbdrs.tbl, 0, sizeof(ntmp->cbdrs.tbl));
+
+   return si->ops->setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_priv(struct enetc_si *si)
+{
+   si->ops->teardown_cbdr(si);
+}
+
 static int enetc4_pf_init(struct enetc_pf *pf)
 {
struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +289,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
return err;
}
 
+   err = enetc4_init_ntmp_priv(pf->si);
+   if (err) {
+   dev_err(dev, "Failed to init CBDR\n");
+   return err;
+   }
+
enetc4_configure_port(pf);
 
return 0;
 }
 
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+   enetc4_free_ntmp_priv(pf->si);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -688,6 +716,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
free_netdev

[PATCH net-next 05/13] net: enetc: add debugfs interface to dump MAC filter

2025-01-02 Thread Wei Fang
ENETC's MAC filter consists of hash MAC filter and exact MAC filter. Hash
MAC filter is a 64-entry hash table consisting of two 32-bit registers.
Exact MAC filter is implemented by configuring MAC address filter table
through command BD ring. The table is stored in ENETC's internal memory
and needs to be read through command BD ring. In order to facilitate
debugging, added a debugfs interface to get the relevant information
about MAC filter.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/Makefile |  1 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 +
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 93 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h | 20 
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  4 +
 5 files changed, 119 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h

diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
 nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4dba91408e3d..ca1bc85c0ac9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -318,6 +318,7 @@ struct enetc_si {
struct enetc_mac_filter mac_filter[MADDR_TYPE];
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
+   struct dentry *debugfs_root;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index ..3a660c80344a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include 
+#include 
+#include 
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+#define is_en(x)   (x) ? "Enabled" : "Disabled"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   u32 hash_h, hash_l;
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+   seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+   seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+   struct maft_entry_data maft_data;
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   struct maft_keye_data *keye;
+   struct enetc_pf *pf;
+   int i, err, num_si;
+   u32 val;
+
+   pf = enetc_si_priv(si);
+   num_si = pf->caps.num_vsi + 1;
+
+   val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+   for (i = 0; i < num_si; i++) {
+   seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n",
+  i, is_en(PSIPMMR_SI_MAC_UP(i) & val));
+   seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n",
+  i, is_en(PSIPMMR_SI_MAC_MP(i) & val));
+   }
+
+   /* MAC hash filter table */
+   for (i = 0; i < num_si; i++)
+   enetc_show_si_mac_hash_filter(s, i);
+
+   if (!pf->num_mfe)
+   return 0;
+
+   /* MAC address filter table */
+   seq_puts(s, "Show MAC address filter table\n");
+   for (i = 0; i < pf->num_mfe; i++) {
+   memset(&maft_data, 0, sizeof(maft_data));
+   err = ntmp_maft_query_entry(&si->ntmp.cbdrs, i, &maft_data);
+   if (err)
+   return err;
+
+   keye = &maft_data.keye;
+   seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+  keye->mac_addr, 
le16_to_cpu(maft_data.cfge.si_bitmap));
+   }
+
+   return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
+
+void enetc_create_debugfs(struct enetc_si *si)
+{
+   struct net_device *ndev = si->ndev;
+   struct dentry *root;
+
+   root = debugfs_create_dir(netdev_name(n

[PATCH net-next 03/13] net: enetc: move generic MAC filterng interfaces to enetc-core

2025-01-02 Thread Wei Fang
Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.

Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. At the same time, the struct enetc_mac_filter is
moved from enetc_pf to enetc_si, because enetc_si is a structure shared by
PF and VFs. This lays the basis for i.MX95 ENETC PF and VFs to support
MAC address filtering.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 36 ++
 drivers/net/ethernet/freescale/enetc/enetc.h  | 17 +++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 49 +++
 .../net/ethernet/freescale/enetc/enetc_pf.h   | 14 --
 4 files changed, 60 insertions(+), 56 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 6a6fc819dfde..6d21c133e418 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct 
enetc_ndev_priv *priv,
enetc_mm_commit_preemptible_tcs(priv);
 }
 
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+   u64 mask = 0;
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 8; i++)
+   mask |= BIT_ULL(i * 6);
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+   return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+   int idx = enetc_mac_addr_hash_idx(addr);
+
+   /* add hash table entry */
+   __set_bit(idx, filter->mac_hash_table);
+   filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+   filter->mac_addr_cnt = 0;
+
+   bitmap_zero(filter->mac_hash_table,
+   ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ff0957e69be..9380d3e8ca01 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
 
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
+#define ENETC_MADDR_HASH_TBL_SZ64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+   union {
+   char mac_addr[ETH_ALEN];
+   DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+   };
+   int mac_addr_cnt;
+};
+
 struct enetc_tx_swbd {
union {
struct sk_buff *skb;
@@ -302,6 +314,8 @@ struct enetc_si {
int hw_features;
const struct enetc_drvdata *drvdata;
const struct enetc_si_ops *ops;
+
+   struct enetc_mac_filter mac_filter[MADDR_TYPE];
 };
 
 #define ENETC_SI_ALIGN 32
@@ -484,6 +498,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
 int enetc_configure_si(struct enetc_ndev_priv *priv);
 int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index a214749a4af6..cc3e52bd3096 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, 
u16 vlan, u8 qos)
enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
 }
 
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
-   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
-   u64 mask = 0;
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 8; i++)
-   mask |= BIT_ULL(i * 6);
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
-   filter->mac_addr_cnt = 0;
-
-   bitmap_zero(filte

[PATCH net-next 01/13] net: enetc: add initial netc-lib driver to support NTMP

2025-01-02 Thread Wei Fang
Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.

For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.

It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/Kconfig  |  11 +
 drivers/net/ethernet/freescale/enetc/Makefile |   3 +
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 468 ++
 .../ethernet/freescale/enetc/ntmp_formats.h   |  61 +++
 include/linux/fsl/ntmp.h  | 178 +++
 5 files changed, 721 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_formats.h
 create mode 100644 include/linux/fsl/ntmp.h

diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig 
b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..94db8e8d0eb3 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,16 @@ config NXP_ENETC_PF_COMMON
 
  If compiled as module (M), the module name is nxp-enetc-pf-common.
 
+config NXP_NETC_LIB
+   tristate "NETC Library"
+   help
+ This module provides common functionalities for both ENETC and NETC
+ Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+ flower and debugfs interfaces and so on.
+
+ If compiled as module (M), the module name is nxp-netc-lib.
+
+
 config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI_MSI
@@ -40,6 +50,7 @@ config NXP_ENETC4
select FSL_ENETC_CORE
select FSL_ENETC_MDIO
select NXP_ENETC_PF_COMMON
+   select NXP_NETC_LIB
select PHYLINK
select DIMLIB
help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
 obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
 nxp-enetc-pf-common-y := enetc_pf_common.o
 
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
 fsl-enetc-y := enetc_pf.o
 fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c 
b/drivers/net/ethernet/freescale/enetc/ntmp.c
new file mode 100644
index ..bcbccede9644
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NETC NTMP (NETC Table Management Protocol) 2.0 Library
+ * Copyright 2025 NXP
+ */
+
+#include 
+#include 
+#include 
+
+#include "ntmp_formats.h"
+
+#define NETC_CBDR_TIMEOUT  1000 /* us */
+#define NETC_CBDR_MR_ENBIT(31)
+
+#define NTMP_BASE_ADDR_ALIGN   128
+#define NTMP_DATA_ADDR_ALIGN   32
+
+/* Define NTMP Table ID */
+#define NTMP_MAFT_ID   1
+#define NTMP_RSST_ID   3
+
+/* Generic Update Actions for most tables */
+#define NTMP_GEN_UA_CFGEU  BIT(0)
+#define NTMP_GEN_UA_STSEU  BIT(1)
+
+#define NTMP_ENTRY_ID_SIZE 4
+#define RSST_ENTRY_NUM 64
+#define RSST_STSE_DATA_SIZE(n) ((n) * 8)
+#define RSST_CFGE_DATA_SIZE(n) (n)
+
+#define NTMP_FILL_CRD(crd, tblv, qa, ua) \
+({ \
+   typeof(crd) _crd = (crd); \
+   (_crd)->update_act = cpu_to_le16(ua); \
+   (_crd)->tblv_qact = NTMP_TBLV_QACT(tblv, qa); \
+})
+
+#define NTMP_FILL_CRD_EID(req, tblv, qa, ua, eid) \
+({ \
+   typeof(req) _req = (req); \
+   NTMP_FILL_CRD(&(_req)->crd, tblv, qa, ua); \
+   (_req)->entry_id = cpu_to_le32(eid); \
+})
+
+int n

[PATCH net-next 10/13] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c

2025-01-02 Thread Wei Fang
Since the VLAN hash filter of ENETC v1 and v4 is the basically same, the
only difference is the offset of the VLAN hash filter registers. So, the
.set_si_vlan_hash_filter() hook is added to struct enetc_pf_ops to set
the registers of the corresponding platform. In addition, the common VLAN
hash filter functions enetc_vlan_rx_add_vid() and enetc_vlan_rx_del_vid()
are moved to enetc_pf_common.c.

Signed-off-by: Wei Fang 
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 34 ++-
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  1 +
 .../freescale/enetc/enetc_pf_common.c | 34 +++
 .../freescale/enetc/enetc_pf_common.h |  2 ++
 4 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c0aaf6349b0b..d9c1ebd180db 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -215,43 +215,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-unsigned long hash)
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx, u64 hash)
 {
enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_si *si = priv->si;
-   struct enetc_hw *hw = &si->hw;
-   int idx;
-
-   __set_bit(vid, si->active_vlans);
-
-   idx = enetc_vid_hash_idx(vid);
-   if (!__test_and_set_bit(idx, si->vlan_ht_filter))
-   enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-
-   return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_si *si = priv->si;
-   struct enetc_hw *hw = &si->hw;
-
-   if (__test_and_clear_bit(vid, si->active_vlans)) {
-   enetc_refresh_vlan_ht_filter(si);
-   enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-   }
-
-   return 0;
-}
-
 static void enetc_set_loopback(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -971,6 +940,7 @@ static const struct enetc_pf_ops enetc_pf_ops = {
.enable_psfp = enetc_psfp_enable,
.set_rss_key = enetc_set_rss_key,
.get_rss_key = enetc_get_rss_key,
+   .set_si_vlan_hash_filter = enetc_set_vlan_ht_filter,
 };
 
 static int enetc_pf_probe(struct pci_dev *pdev,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index d56b381b9da9..7a0fa5fba8bf 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -39,6 +39,7 @@ struct enetc_pf_ops {
int (*enable_psfp)(struct enetc_ndev_priv *priv);
void (*set_rss_key)(struct enetc_hw *hw, const u8 *key);
void (*get_rss_key)(struct enetc_hw *hw, u8 *key);
+   void (*set_si_vlan_hash_filter)(struct enetc_hw *hw, int si, u64 hash);
 };
 
 struct enetc_pf {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a737a7f8c79e..9f812c1af7a3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -343,5 +343,39 @@ void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
 }
 EXPORT_SYMBOL_GPL(enetc_phylink_destroy);
 
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
+   int idx;
+
+   __set_bit(vid, si->active_vlans);
+
+   idx = enetc_vid_hash_idx(vid);
+   if (!__test_and_set_bit(idx, si->vlan_ht_filter))
+   pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
+
+   if (__test_and_clear_bit(vid, si->active_vlans)) {
+   enetc_refresh_vlan_ht_filter(si);
+   pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+   }
+
+   return 0;

[PATCH net-next 09/13] net: enetc: move generic VLAN filter interfaces to enetc-core

2025-01-02 Thread Wei Fang
For ENETC, each SI has a corresponding VLAN hash table. That is to say,
both PF and VFs can support VLAN filter. However, currently only ENETC v1
PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
VF drivers also support VLAN filter, some related macros are moved from
enetc_pf.h to enetc.h, and the related structure variables are moved from
enetc_pf to enetc_si.

Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
so that it can be shared by PF and VF drivers. This will make it easier
to add VLAN filter support for i.MX95 ENETC later.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 25 ++
 drivers/net/ethernet/freescale/enetc/enetc.h  |  6 +++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 46 +--
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  4 --
 4 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index e27b031c4f46..8b4a004f51a4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -72,6 +72,31 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter 
*filter)
 }
 EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
 
+int enetc_vid_hash_idx(unsigned int vid)
+{
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+   return res;
+}
+EXPORT_SYMBOL_GPL(enetc_vid_hash_idx);
+
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si)
+{
+   int i;
+
+   bitmap_zero(si->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, si->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
+
+   __set_bit(hidx, si->vlan_ht_filter);
+   }
+}
+EXPORT_SYMBOL_GPL(enetc_refresh_vlan_ht_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 2b0d27ed924d..0ecec9da6148 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -24,6 +24,7 @@
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
 #define ENETC_MADDR_HASH_TBL_SZ64
+#define ENETC_VLAN_HT_SIZE 64
 
 enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
 
@@ -321,6 +322,9 @@ struct enetc_si {
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
struct dentry *debugfs_root;
+
+   DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   DECLARE_BITMAP(active_vlans, VLAN_N_VID);
 };
 
 #define ENETC_SI_ALIGN 32
@@ -506,6 +510,8 @@ int enetc_get_driver_data(struct enetc_si *si);
 void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
  const unsigned char *addr);
 void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
+int enetc_vid_hash_idx(unsigned int vid);
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 59039d087695..c0aaf6349b0b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -222,45 +222,18 @@ static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, 
int si_idx,
enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vid_hash_idx(unsigned int vid)
-{
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
-{
-   int i;
-
-   if (rehash) {
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
-   }
-
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-}
-
 static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int idx;
 
-   __set_bit(vid, pf->active_vlans);
+   __set_bit(vid, si->active_vlans);
 
idx = enetc_vid_hash_idx(vid);
-   if (!__test_and_set_bit(idx

[PATCH net-next 07/13] net: enetc: add RSS support for i.MX95 ENETC PF

2025-01-02 Thread Wei Fang
Add Receive side scaling (RSS) support for i.MX95 ENETC PF to improve the
network performance and balance the CPU loading. In addition, since both
ENETC v1 and ENETC v4 only support the toeplitz algorithm, so a check for
hfunc was added.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  |  7 +---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  4 ++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 37 +++
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 14 +++
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 33 -
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  2 +
 .../freescale/enetc/enetc_pf_common.c |  6 +--
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  2 +
 8 files changed, 87 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 6d21c133e418..233f58e57a20 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2363,7 +2363,7 @@ static int enetc_setup_default_rss_table(struct enetc_si 
*si, int num_groups)
for (i = 0; i < si->num_rss; i++)
rss_table[i] = i % num_groups;
 
-   enetc_set_rss_table(si, rss_table, si->num_rss);
+   si->ops->set_rss_table(si, rss_table, si->num_rss);
 
kfree(rss_table);
 
@@ -2394,10 +2394,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
if (si->hw_features & ENETC_SI_F_LSO)
enetc_set_lso_flags_mask(hw);
 
-   /* TODO: RSS support for i.MX95 will be supported later, and the
-* is_enetc_rev1() condition will be removed
-*/
-   if (si->num_rss && is_enetc_rev1(si)) {
+   if (si->num_rss) {
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index fb53fb961364..2b0d27ed924d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -290,6 +290,8 @@ struct enetc_si;
 struct enetc_si_ops {
int (*setup_cbdr)(struct enetc_si *si);
void (*teardown_cbdr)(struct enetc_si *si);
+   int (*get_rss_table)(struct enetc_si *si, u32 *table, int count);
+   int (*set_rss_table)(struct enetc_si *si, const u32 *table, int count);
 };
 
 /* PCI IEP device data */
@@ -540,6 +542,8 @@ int enetc_set_fs_entry(struct enetc_si *si, struct 
enetc_cmd_rfse *rfse,
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 
 static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
 struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 6de571b5b425..4cd0931baea0 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -69,9 +69,27 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw 
*hw, int si,
put_unaligned_le16(lower, addr + 4);
 }
 
+static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *key)
+{
+   int i;
+
+   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)key)[i]);
+}
+
+static void enetc4_get_rss_key(struct enetc_hw *hw, u8 *key)
+{
+   int i;
+
+   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+   ((u32 *)key)[i] = enetc_port_rd(hw, ENETC4_PRSSKR(i));
+}
+
 static const struct enetc_pf_ops enetc4_pf_ops = {
.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
+   .set_rss_key = enetc4_set_rss_key,
+   .get_rss_key = enetc4_get_rss_key,
 };
 
 static int enetc4_pf_struct_init(struct enetc_si *si)
@@ -263,14 +281,6 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
enetc4_pf_reset_tc_msdu(&si->hw);
 }
 
-static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-   int i;
-
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
-}
-
 static void enetc4_set_default_rss_key(struct enetc_pf *pf)
 {
u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
@@ -691,6 +701,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static int enetc4_pf_set_features(struct net_device

[PATCH net-next 11/13] net: enetc: add VLAN filtering support for i.MX95 ENETC PF

2025-01-02 Thread Wei Fang
Add VLAN hash filter support for i.MX95 ENETC PF. If VLAN filtering is
disabled, then VLAN promiscuous mode will be enabled, which means that
PF qualifies for reception of all VLAN tags.

Signed-off-by: Wei Fang 
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  4 
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 20 +++
 .../freescale/enetc/enetc_pf_common.c |  2 +-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 826359004850..aa25b445d301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -107,6 +107,10 @@
 #define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
 #define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
 
+/* Port station interface a VLAN hash filter register 0/1 */
+#define ENETC4_PSIVHFR0(a) ((a) * 0x80 + 0x2060)
+#define ENETC4_PSIVHFR1(a) ((a) * 0x80 + 0x2064)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 4cd0931baea0..e2eca28eec06 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -85,11 +85,19 @@ static void enetc4_get_rss_key(struct enetc_hw *hw, u8 *key)
((u32 *)key)[i] = enetc_port_rd(hw, ENETC4_PRSSKR(i));
 }
 
+static void enetc4_pf_set_si_vlan_hash_filter(struct enetc_hw *hw,
+ int si, u64 hash)
+{
+   enetc_port_wr(hw, ENETC4_PSIVHFR0(si), lower_32_bits(hash));
+   enetc_port_wr(hw, ENETC4_PSIVHFR1(si), upper_32_bits(hash));
+}
+
 static const struct enetc_pf_ops enetc4_pf_ops = {
.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
.set_rss_key = enetc4_set_rss_key,
.get_rss_key = enetc4_get_rss_key,
+   .set_si_vlan_hash_filter = enetc4_pf_set_si_vlan_hash_filter,
 };
 
 static int enetc4_pf_struct_init(struct enetc_si *si)
@@ -704,6 +712,16 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 static int enetc4_pf_set_features(struct net_device *ndev,
  netdev_features_t features)
 {
+   netdev_features_t changed = ndev->features ^ features;
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+
+   if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+   bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+
+   enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+   }
+
enetc_set_features(ndev, features);
 
return 0;
@@ -717,6 +735,8 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_set_mac_address= enetc_pf_set_mac_addr,
.ndo_set_rx_mode= enetc4_pf_set_rx_mode,
.ndo_set_features   = enetc4_pf_set_features,
+   .ndo_vlan_rx_add_vid= enetc_vlan_rx_add_vid,
+   .ndo_vlan_rx_kill_vid   = enetc_vlan_rx_del_vid,
 };
 
 static struct phylink_pcs *
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 9f812c1af7a3..3f7ccc482301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -135,7 +135,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | 
NETIF_F_LOOPBACK);
+   ndev->hw_features &= ~NETIF_F_LOOPBACK;
goto end;
}
 
-- 
2.34.1




[PATCH net-next 12/13] net: enetc: add loopback support for i.MX95 ENETC PF

2025-01-02 Thread Wei Fang
Add internal loopback support for i.MX95 ENETC PF, the default loopback
mode is MAC level loopback, the MAC Tx data is looped back onto the Rx.
The MAC interface runs at a fixed 1:8 ratio of NETC clock in MAC-level
loopback mode, with no dependency on Tx clock.

Signed-off-by: Wei Fang 
---
 .../net/ethernet/freescale/enetc/enetc4_pf.c   | 18 ++
 .../ethernet/freescale/enetc/enetc_pf_common.c |  4 +---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index e2eca28eec06..d460d75647f7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -709,6 +709,21 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_si *si = priv->si;
+   u32 val;
+
+   val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+   val = u32_replace_bits(val, en ? 1 : 0, PM_CMD_CFG_LOOP_EN);
+   /* Default to select MAC level loopback mode if loopback is enabled. */
+   val = u32_replace_bits(val, en ? LPBCK_MODE_MAC_LEVEL : 0,
+  PM_CMD_CFG_LPBK_MODE);
+
+   enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
 static int enetc4_pf_set_features(struct net_device *ndev,
  netdev_features_t features)
 {
@@ -722,6 +737,9 @@ static int enetc4_pf_set_features(struct net_device *ndev,
enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
}
 
+   if (changed & NETIF_F_LOOPBACK)
+   enetc4_pf_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
enetc_set_features(ndev, features);
 
return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3f7ccc482301..0a2b8769a175 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -134,10 +134,8 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
}
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
-   if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~NETIF_F_LOOPBACK;
+   if (!is_enetc_rev1(si))
goto end;
-   }
 
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-- 
2.34.1




[PATCH net-next 06/13] net: enetc: make enetc_set_rxfh() and enetc_get_rxfh() reusable

2025-01-02 Thread Wei Fang
Both ENETC v1 and v4 support Receive Side Scaling (RSS), but the offset
of the RSS key registers is different. In order to make enetc_get_rxfh()
and enetc_set_rxfh() be reused by ENETC v4, the .set_rss_key() and
.get_rss_key() interfaces are added to enect_pf_ops.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 -
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 42 +--
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 18 
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  2 +
 4 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index ca1bc85c0ac9..fb53fb961364 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -537,7 +537,6 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
 int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
   int index);
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 
b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index bf34b5bb1e35..56ba82830279 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -4,7 +4,8 @@
 #include 
 #include 
 #include 
-#include "enetc.h"
+
+#include "enetc_pf.h"
 
 static const u32 enetc_si_regs[] = {
ENETC_SIMR, ENETC_SIPMAR0, ENETC_SIPMAR1, ENETC_SICBDRMR,
@@ -681,51 +682,46 @@ static int enetc_get_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
-   int err = 0, i;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
+   int err = 0;
 
/* return hash function */
rxfh->hfunc = ETH_RSS_HASH_TOP;
 
/* return hash key */
-   if (rxfh->key && hw->port)
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   ((u32 *)rxfh->key)[i] = enetc_port_rd(hw,
- ENETC_PRSSK(i));
+   if (rxfh->key && enetc_si_is_pf(si)) {
+   struct enetc_pf *pf = enetc_si_priv(si);
+
+   pf->ops->get_rss_key(hw, rxfh->key);
+   }
 
/* return RSS table */
if (rxfh->indir)
-   err = enetc_get_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = enetc_get_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
 
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-   int i;
-
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
-}
-EXPORT_SYMBOL_GPL(enetc_set_rss_key);
-
 static int enetc_set_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh,
  struct netlink_ext_ack *extack)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int err = 0;
 
/* set hash key, if PF */
-   if (rxfh->key && hw->port)
-   enetc_set_rss_key(hw, rxfh->key);
+   if (rxfh->key && enetc_si_is_pf(si)) {
+   struct enetc_pf *pf = enetc_si_priv(si);
+
+   pf->ops->set_rss_key(hw, rxfh->key);
+   }
 
/* set RSS table */
if (rxfh->indir)
-   err = enetc_set_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = enetc_set_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index cc3e52bd3096..f050cf039733 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -512,6 +512,22 @@ static void enetc_mac_enable(struct enetc_si *si, bool en)
enetc_port_mac_wr(si, ENETC_PM0_CMD_CFG, val);
 }
 
+static void enetc_set_rss_key(struct enetc_hw *hw, const u8 *key)
+{
+   int i;
+
+   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+   enetc_port_wr(hw, ENETC_PRSSK(i), ((u

[PATCH net-next 08/13] net: enetc: enable RSS feature by default

2025-01-02 Thread Wei Fang
Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 35 ++-
 .../freescale/enetc/enetc_pf_common.c |  4 ++-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 233f58e57a20..e27b031c4f46 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2378,6 +2378,22 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
 }
 
+static int enetc_set_rss(struct net_device *ndev, int en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+   u32 reg;
+
+   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+   reg = enetc_rd(hw, ENETC_SIMR);
+   reg &= ~ENETC_SIMR_RSSE;
+   reg |= (en) ? ENETC_SIMR_RSSE : 0;
+   enetc_wr(hw, ENETC_SIMR, reg);
+
+   return 0;
+}
+
 int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
struct enetc_si *si = priv->si;
@@ -2398,6 +2414,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
+
+   if (priv->ndev->features & NETIF_F_RXHASH)
+   enetc_set_rss(priv->ndev, true);
}
 
return 0;
@@ -3190,22 +3209,6 @@ struct net_device_stats *enetc_get_stats(struct 
net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static int enetc_set_rss(struct net_device *ndev, int en)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
-   u32 reg;
-
-   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
-   reg = enetc_rd(hw, ENETC_SIMR);
-   reg &= ~ENETC_SIMR_RSSE;
-   reg |= (en) ? ENETC_SIMR_RSSE : 0;
-   enetc_wr(hw, ENETC_SIMR, reg);
-
-   return 0;
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index c346e0e3ad37..a737a7f8c79e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
if (si->hw_features & ENETC_SI_F_LSO)
priv->active_offloads |= ENETC_F_LSO;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 072e5b40a199..3372a9a779a6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, 
struct net_device *ndev,
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
  NETIF_F_TSO | NETIF_F_TSO6;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* pick up primary MAC address from SI */
enetc_load_primary_mac_addr(&si->hw, ndev);
-- 
2.34.1




[PATCH net-next 00/13] Add more feautues for ENETC v4 - round 2

2025-01-02 Thread Wei Fang
This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.

Wei Fang (13):
  net: enetc: add initial netc-lib driver to support NTMP
  net: enetc: add command BD ring support for i.MX95 ENETC
  net: enetc: move generic MAC filterng interfaces to enetc-core
  net: enetc: add MAC filter for i.MX95 ENETC PF
  net: enetc: add debugfs interface to dump MAC filter
  net: enetc: make enetc_set_rxfh() and enetc_get_rxfh() reusable
  net: enetc: add RSS support for i.MX95 ENETC PF
  net: enetc: enable RSS feature by default
  net: enetc: move generic VLAN filter interfaces to enetc-core
  net: enetc: move generic VLAN hash filter functions to
enetc_pf_common.c
  net: enetc: add VLAN filtering support for i.MX95 ENETC PF
  net: enetc: add loopback support for i.MX95 ENETC PF
  MAINTAINERS: add new file ntmp.h to ENETC driver

 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |  11 +
 drivers/net/ethernet/freescale/enetc/Makefile |   4 +
 drivers/net/ethernet/freescale/enetc/enetc.c  | 103 +++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  58 +-
 .../ethernet/freescale/enetc/enetc4_debugfs.c |  93 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h |  20 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  12 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 537 +-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c |  65 ++-
 .../ethernet/freescale/enetc/enetc_ethtool.c  |  71 ++-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 140 ++---
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  32 +-
 .../freescale/enetc/enetc_pf_common.c |  46 +-
 .../freescale/enetc/enetc_pf_common.h |   2 +
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  19 +-
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 468 +++
 .../ethernet/freescale/enetc/ntmp_formats.h   |  61 ++
 include/linux/fsl/ntmp.h  | 178 ++
 20 files changed, 1731 insertions(+), 196 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_formats.h
 create mode 100644 include/linux/fsl/ntmp.h

-- 
2.34.1




[PATCH net-next 13/13] MAINTAINERS: add new file ntmp.h to ENETC driver

2025-01-02 Thread Wei Fang
Add new file ntmp.h. to ENETC driver.

Signed-off-by: Wei Fang 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1579124ef426..ac28154f7eb5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9099,6 +9099,7 @@ F:
Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
 F: drivers/net/ethernet/freescale/enetc/
 F: include/linux/fsl/enetc_mdio.h
 F: include/linux/fsl/netc_global.h
+F: include/linux/fsl/ntmp.h
 
 FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 M: Claudiu Manoil 
-- 
2.34.1




RE: [PATCH net-next 01/13] net: enetc: add initial netc-lib driver to support NTMP

2025-01-05 Thread Wei Fang
> > +#define NTMP_FILL_CRD(crd, tblv, qa, ua) \
> > +({ \
> > +   typeof(crd) _crd = (crd); \
> > +   (_crd)->update_act = cpu_to_le16(ua); \
> > +   (_crd)->tblv_qact = NTMP_TBLV_QACT(tblv, qa); \
> > +})
> > +
> > +#define NTMP_FILL_CRD_EID(req, tblv, qa, ua, eid) \
> > +({ \
> > +   typeof(req) _req = (req); \
> > +   NTMP_FILL_CRD(&(_req)->crd, tblv, qa, ua); \
> > +   (_req)->entry_id = cpu_to_le32(eid); \
> > +})
> 
> 
> These are pretty complex for #defines. Can they be made into
> functions? That will get you type checking, finding bugs where
> parameters are swapped.

The problem is that different tables have different types of 'req'
parameters. Of course, since the headers of these request data
are the same, we can force these pointers to be converted to
common type pointers, but I think the forced conversion has made
this pointless.

> 
> > +int netc_setup_cbdr(struct device *dev, int cbd_num,
> > +   struct netc_cbdr_regs *regs,
> > +   struct netc_cbdr *cbdr)
> > +{
> > +   int size;
> > +
> > +   size = cbd_num * sizeof(union netc_cbd) + NTMP_BASE_ADDR_ALIGN;
> > +
> > +   cbdr->addr_base = dma_alloc_coherent(dev, size, &cbdr->dma_base,
> > +GFP_KERNEL);
> > +   if (!cbdr->addr_base)
> > +   return -ENOMEM;
> > +
> > +   cbdr->dma_size = size;
> > +   cbdr->bd_num = cbd_num;
> > +   cbdr->regs = *regs;
> > +
> > +   /* The base address of the Control BD Ring must be 128 bytes aligned */
> > +   cbdr->dma_base_align =  ALIGN(cbdr->dma_base,
> NTMP_BASE_ADDR_ALIGN);
> > +   cbdr->addr_base_align = PTR_ALIGN(cbdr->addr_base,
> > + NTMP_BASE_ADDR_ALIGN);
> > +
> > +   cbdr->next_to_clean = 0;
> > +   cbdr->next_to_use = 0;
> > +   spin_lock_init(&cbdr->ring_lock);
> > +
> > +   /* Step 1: Configure the base address of the Control BD Ring */
> > +   netc_write(cbdr->regs.bar0, lower_32_bits(cbdr->dma_base_align));
> > +   netc_write(cbdr->regs.bar1, upper_32_bits(cbdr->dma_base_align));
> > +
> > +   /* Step 2: Configure the producer index register */
> > +   netc_write(cbdr->regs.pir, cbdr->next_to_clean);
> > +
> > +   /* Step 3: Configure the consumer index register */
> > +   netc_write(cbdr->regs.cir, cbdr->next_to_use);
> > +
> > +   /* Step4: Configure the number of BDs of the Control BD Ring */
> > +   netc_write(cbdr->regs.lenr, cbdr->bd_num);
> > +
> > +   /* Step 5: Enable the Control BD Ring */
> > +   netc_write(cbdr->regs.mr, NETC_CBDR_MR_EN);
> > +
> > +   return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(netc_setup_cbdr);
> 
> I assume there is a version 3 in development, which will need a
> different library, or at least different symbols. Maybe you should
> think about the naming issues now?

I think that version 3 will not exist for a long time or will never exist.
The reason for developing NTMP 2.0 is that NTMP 1.0 cannot be
extended, so its table format is fixed, but for NTMP 2.0, its table
format supports extension. For the same table, multiple versions
can be expanded.

> 
> > diff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h
> > new file mode 100644
> > index ..7cf322a1c8e3
> > --- /dev/null
> > +++ b/include/linux/fsl/ntmp.h
> > @@ -0,0 +1,178 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> > +/* Copyright 2025 NXP */
> > +#ifndef __NETC_NTMP_H
> > +#define __NETC_NTMP_H
> 
> Does this header need to be global? What else will use it outside of
> drivers/net/ethernet/freescale/enetc?
> 
Yes, this library will be used by NETC Switch driver, although there is
no NETC switch driver in the upstream yet, this is already in the plan.




[PATCH v2 net-next 04/13] net: enetc: add MAC filter for i.MX95 ENETC PF

2025-01-13 Thread Wei Fang
The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bits hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.

For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.

Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.

Signed-off-by: Wei Fang 
---
v2 changes:
Fix the compile warning.
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |   2 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 411 +-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  11 +
 5 files changed, 437 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 9380d3e8ca01..4dba91408e3d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -316,6 +316,8 @@ struct enetc_si {
const struct enetc_si_ops *ops;
 
struct enetc_mac_filter mac_filter[MADDR_TYPE];
+   struct workqueue_struct *workqueue;
+   struct work_struct rx_mode_task;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
 #define ENETC4_PSICFGR2(a) ((a) * 0x80 + 0x2018)
 #define  PSICFGR2_NUM_MSIX GENMASK(5, 0)
 
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a)((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a)((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index b957e92e3a00..7e69c9be36a8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
 
 #define ENETC_SI_MAX_RING_NUM  8
 
+#define ENETC_MAC_FILTER_TYPE_UC   BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC   BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL  (ENETC_MAC_FILTER_TYPE_UC | \
+ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+   u8 addr[ETH_ALEN];
+};
+
 static void enetc4_get_port_caps(struct enetc_pf *pf)
 {
struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 
val = enetc_port_rd(hw, ENETC4_PMCAPR);
pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+   val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+   pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
 }
 
 static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -71,9 +83,33 @@ static int enetc4_pf_struct_init(struct enetc_si *si)
 
enetc4_get_port_caps(pf);
 
+   INIT_HLIST_HEAD(&pf->mac_list);
+   mutex_init(&pf->mac_list_lock);
+
return 0;
 }
 
+static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
+{
+   struct enetc_mac_list_entry *entry;
+   struct hlist_node *tmp;
+
+   scoped_guard(mutex, &pf->mac_list_lock) {
+   hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
+   hlist_del(&entry->node);
+   kfree(entry);
+   }
+
+   pf->num_mfe = 0;
+   }
+}
+
+static void enetc4_pf_struct_free(struct enetc_pf *pf)
+{
+   enetc4_pf_destroy_mac_list(pf

[PATCH v2 net-next 05/13] net: enetc: add debugfs interface to dump MAC filter

2025-01-13 Thread Wei Fang
ENETC's MAC filter consists of hash MAC filter and exact MAC filter. Hash
MAC filter is a 64-entry hash table consisting of two 32-bit registers.
Exact MAC filter is implemented by configuring MAC address filter table
through command BD ring. The table is stored in ENETC's internal memory
and needs to be read through command BD ring. In order to facilitate
debugging, added a debugfs interface to get the relevant information
about MAC filter.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/Makefile |  1 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 +
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 93 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h | 20 
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  4 +
 5 files changed, 119 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h

diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
 nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4dba91408e3d..ca1bc85c0ac9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -318,6 +318,7 @@ struct enetc_si {
struct enetc_mac_filter mac_filter[MADDR_TYPE];
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
+   struct dentry *debugfs_root;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index ..3a660c80344a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include 
+#include 
+#include 
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+#define is_en(x)   (x) ? "Enabled" : "Disabled"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   u32 hash_h, hash_l;
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+   seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+   seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+   struct maft_entry_data maft_data;
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   struct maft_keye_data *keye;
+   struct enetc_pf *pf;
+   int i, err, num_si;
+   u32 val;
+
+   pf = enetc_si_priv(si);
+   num_si = pf->caps.num_vsi + 1;
+
+   val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+   for (i = 0; i < num_si; i++) {
+   seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n",
+  i, is_en(PSIPMMR_SI_MAC_UP(i) & val));
+   seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n",
+  i, is_en(PSIPMMR_SI_MAC_MP(i) & val));
+   }
+
+   /* MAC hash filter table */
+   for (i = 0; i < num_si; i++)
+   enetc_show_si_mac_hash_filter(s, i);
+
+   if (!pf->num_mfe)
+   return 0;
+
+   /* MAC address filter table */
+   seq_puts(s, "Show MAC address filter table\n");
+   for (i = 0; i < pf->num_mfe; i++) {
+   memset(&maft_data, 0, sizeof(maft_data));
+   err = ntmp_maft_query_entry(&si->ntmp.cbdrs, i, &maft_data);
+   if (err)
+   return err;
+
+   keye = &maft_data.keye;
+   seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+  keye->mac_addr, 
le16_to_cpu(maft_data.cfge.si_bitmap));
+   }
+
+   return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
+
+void enetc_create_debugfs(struct enetc_si *si)
+{
+   struct net_device *ndev = si->ndev;
+   struct dentry *root;
+
+   root = debugfs_create_dir(netdev_name(n

[PATCH v2 net-next 03/13] net: enetc: move generic MAC filterng interfaces to enetc-core

2025-01-13 Thread Wei Fang
Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.

Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. At the same time, the struct enetc_mac_filter is
moved from enetc_pf to enetc_si, because enetc_si is a structure shared by
PF and VFs. This lays the basis for i.MX95 ENETC PF and VFs to support
MAC address filtering.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 36 ++
 drivers/net/ethernet/freescale/enetc/enetc.h  | 17 +++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 49 +++
 .../net/ethernet/freescale/enetc/enetc_pf.h   | 14 --
 4 files changed, 60 insertions(+), 56 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 6a6fc819dfde..6d21c133e418 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct 
enetc_ndev_priv *priv,
enetc_mm_commit_preemptible_tcs(priv);
 }
 
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+   u64 mask = 0;
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 8; i++)
+   mask |= BIT_ULL(i * 6);
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+   return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+   int idx = enetc_mac_addr_hash_idx(addr);
+
+   /* add hash table entry */
+   __set_bit(idx, filter->mac_hash_table);
+   filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+   filter->mac_addr_cnt = 0;
+
+   bitmap_zero(filter->mac_hash_table,
+   ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ff0957e69be..9380d3e8ca01 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
 
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
+#define ENETC_MADDR_HASH_TBL_SZ64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+   union {
+   char mac_addr[ETH_ALEN];
+   DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+   };
+   int mac_addr_cnt;
+};
+
 struct enetc_tx_swbd {
union {
struct sk_buff *skb;
@@ -302,6 +314,8 @@ struct enetc_si {
int hw_features;
const struct enetc_drvdata *drvdata;
const struct enetc_si_ops *ops;
+
+   struct enetc_mac_filter mac_filter[MADDR_TYPE];
 };
 
 #define ENETC_SI_ALIGN 32
@@ -484,6 +498,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
 int enetc_configure_si(struct enetc_ndev_priv *priv);
 int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index a214749a4af6..cc3e52bd3096 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, 
u16 vlan, u8 qos)
enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
 }
 
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
-   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
-   u64 mask = 0;
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 8; i++)
-   mask |= BIT_ULL(i * 6);
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
-   filter->mac_addr_cnt = 0;
-
-   bitmap_zero(filte

[PATCH v2 net-next 01/13] net: enetc: add initial netc-lib driver to support NTMP

2025-01-13 Thread Wei Fang
Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.

For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.

It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.

Signed-off-by: Wei Fang 
---
v2 changes:
Change NTMP_FILL_CRD() and NTMP_FILL_CRD_EID to functions.
---
 drivers/net/ethernet/freescale/enetc/Kconfig  |  11 +
 drivers/net/ethernet/freescale/enetc/Makefile |   3 +
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 468 ++
 .../ethernet/freescale/enetc/ntmp_formats.h   |  59 +++
 include/linux/fsl/ntmp.h  | 178 +++
 5 files changed, 719 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_formats.h
 create mode 100644 include/linux/fsl/ntmp.h

diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig 
b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..94db8e8d0eb3 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,16 @@ config NXP_ENETC_PF_COMMON
 
  If compiled as module (M), the module name is nxp-enetc-pf-common.
 
+config NXP_NETC_LIB
+   tristate "NETC Library"
+   help
+ This module provides common functionalities for both ENETC and NETC
+ Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+ flower and debugfs interfaces and so on.
+
+ If compiled as module (M), the module name is nxp-netc-lib.
+
+
 config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI_MSI
@@ -40,6 +50,7 @@ config NXP_ENETC4
select FSL_ENETC_CORE
select FSL_ENETC_MDIO
select NXP_ENETC_PF_COMMON
+   select NXP_NETC_LIB
select PHYLINK
select DIMLIB
help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
 obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
 nxp-enetc-pf-common-y := enetc_pf_common.o
 
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
 fsl-enetc-y := enetc_pf.o
 fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c 
b/drivers/net/ethernet/freescale/enetc/ntmp.c
new file mode 100644
index ..ba8a2ac9d4b4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NETC NTMP (NETC Table Management Protocol) 2.0 Library
+ * Copyright 2025 NXP
+ */
+
+#include 
+#include 
+#include 
+
+#include "ntmp_formats.h"
+
+#define NETC_CBDR_TIMEOUT  1000 /* us */
+#define NETC_CBDR_MR_ENBIT(31)
+
+#define NTMP_BASE_ADDR_ALIGN   128
+#define NTMP_DATA_ADDR_ALIGN   32
+
+/* Define NTMP Table ID */
+#define NTMP_MAFT_ID   1
+#define NTMP_RSST_ID   3
+
+/* Generic Update Actions for most tables */
+#define NTMP_GEN_UA_CFGEU  BIT(0)
+#define NTMP_GEN_UA_STSEU  BIT(1)
+
+#define NTMP_ENTRY_ID_SIZE 4
+#define RSST_ENTRY_NUM 64
+#define RSST_STSE_DATA_SIZE(n) ((n) * 8)
+#define RSST_CFGE_DATA_SIZE(n) (n)
+
+int netc_setup_cbdr(struct device *dev, int cbd_num,
+   struct netc_cbdr_regs *regs,
+   struct netc_cbdr *cbdr)
+{
+   int size;
+
+   size = cbd_num * sizeof(union netc_cbd) + NTMP_BASE_ADDR_ALIGN;
+
+   cbdr->addr_base = dma_alloc_coherent(dev, size, &cbdr->dma_base,
+  

[PATCH v2 net-next 02/13] net: enetc: add command BD ring support for i.MX95 ENETC

2025-01-13 Thread Wei Fang
The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).

Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. In order to
ensure driver compatibility, struct enetc_si_ops is introduced. This
structure defines some hooks shared by VSI and PSI. Different hardware
driver will register different hooks, For example, setup_cbdr() is used
to initialize the command BD ring, and teardown_cbdr() is used to free
the command BD ring.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  | 27 --
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 47 -
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 51 ---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 13 +++--
 .../net/ethernet/freescale/enetc/enetc_vf.c   | 13 +++--
 5 files changed, 132 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..4ff0957e69be 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -266,6 +267,19 @@ struct enetc_platform_info {
const struct enetc_drvdata *data;
 };
 
+struct enetc_si;
+
+/*
+ * This structure defines the some common hooks for ENETC PSI and VSI.
+ * In addition, since VSI only uses the struct enetc_si as its private
+ * driver data, so this structure also define some hooks specifically
+ * for VSI. For VSI-specific hooks, the format is ???vf_*()???.
+ */
+struct enetc_si_ops {
+   int (*setup_cbdr)(struct enetc_si *si);
+   void (*teardown_cbdr)(struct enetc_si *si);
+};
+
 /* PCI IEP device data */
 struct enetc_si {
struct pci_dev *pdev;
@@ -274,7 +288,10 @@ struct enetc_si {
 
struct net_device *ndev; /* back ref. */
 
-   struct enetc_cbdr cbd_ring;
+   union {
+   struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+   struct ntmp_priv ntmp; /* ENETC 4.1 and later */
+   };
 
int num_rx_rings; /* how many rings are available in the SI */
int num_tx_rings;
@@ -284,6 +301,7 @@ struct enetc_si {
u16 revision;
int hw_features;
const struct enetc_drvdata *drvdata;
+   const struct enetc_si_ops *ops;
 };
 
 #define ENETC_SI_ALIGN 32
@@ -490,9 +508,10 @@ void enetc_mm_link_state_update(struct enetc_ndev_priv 
*priv, bool link);
 void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
 
 /* control buffer descriptor ring (CBDR) */
-int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
-struct enetc_cbdr *cbdr);
-void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc_setup_cbdr(struct enetc_si *si);
+void enetc_teardown_cbdr(struct enetc_si *si);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index fc41078c4f5d..b957e92e3a00 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,23 @@ static void enetc4_configure_port(struct enetc_pf *pf)
enetc4_enable_trx(pf);
 }
 
+static int enetc4_init_ntmp_priv(struct enetc_si *si)
+{
+   struct ntmp_priv *ntmp = &si->ntmp;
+
+   ntmp->dev_type = NETC_DEV_ENETC;
+
+   /* For ENETC 4.1, all table versions are 0 */
+   memset(&ntmp->cbdrs.tbl, 0, sizeof(ntmp->cbdrs.tbl));
+
+   return si->ops->setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_priv(struct enetc_si *si)
+{
+   si->ops->teardown_cbdr(si);
+}
+
 static int enetc4_pf_init(struct enetc_pf *pf)
 {
struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +289,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
return err;
}
 
+   err = enetc4_init_ntmp_priv(pf->si);
+   if (err) {
+   dev_err(dev, "Failed to init CBDR\n");
+   return err;
+   }
+
enetc4_configure_port(pf);
 
return 0;
 }
 
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+   enetc4_free_ntmp_priv(pf->si);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -688,6 +716,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
free_netdev

[PATCH v2 net-next 00/13] Add more feautues for ENETC v4 - round 2

2025-01-13 Thread Wei Fang
This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.

---
v1 Link: https://lore.kernel.org/imx/20250103060610.2233908-1-wei.f...@nxp.com/
---

Wei Fang (13):
  net: enetc: add initial netc-lib driver to support NTMP
  net: enetc: add command BD ring support for i.MX95 ENETC
  net: enetc: move generic MAC filterng interfaces to enetc-core
  net: enetc: add MAC filter for i.MX95 ENETC PF
  net: enetc: add debugfs interface to dump MAC filter
  net: enetc: make enetc_set_rxfh() and enetc_get_rxfh() reusable
  net: enetc: add RSS support for i.MX95 ENETC PF
  net: enetc: enable RSS feature by default
  net: enetc: move generic VLAN filter interfaces to enetc-core
  net: enetc: move generic VLAN hash filter functions to
enetc_pf_common.c
  net: enetc: add VLAN filtering support for i.MX95 ENETC PF
  net: enetc: add loopback support for i.MX95 ENETC PF
  MAINTAINERS: add new file ntmp.h to ENETC driver

 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |  11 +
 drivers/net/ethernet/freescale/enetc/Makefile |   4 +
 drivers/net/ethernet/freescale/enetc/enetc.c  | 103 +++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  58 +-
 .../ethernet/freescale/enetc/enetc4_debugfs.c |  93 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h |  20 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  12 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 537 +-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c |  65 ++-
 .../ethernet/freescale/enetc/enetc_ethtool.c  |  71 ++-
 .../net/ethernet/freescale/enetc/enetc_hw.h   |   6 +
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 140 ++---
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  32 +-
 .../freescale/enetc/enetc_pf_common.c |  46 +-
 .../freescale/enetc/enetc_pf_common.h |   2 +
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  19 +-
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 468 +++
 .../ethernet/freescale/enetc/ntmp_formats.h   |  59 ++
 include/linux/fsl/ntmp.h  | 178 ++
 20 files changed, 1729 insertions(+), 196 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_formats.h
 create mode 100644 include/linux/fsl/ntmp.h

-- 
2.34.1




[PATCH v2 net-next 08/13] net: enetc: enable RSS feature by default

2025-01-13 Thread Wei Fang
Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 35 ++-
 .../freescale/enetc/enetc_pf_common.c |  4 ++-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
 3 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 233f58e57a20..e27b031c4f46 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2378,6 +2378,22 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
 }
 
+static int enetc_set_rss(struct net_device *ndev, int en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+   u32 reg;
+
+   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+   reg = enetc_rd(hw, ENETC_SIMR);
+   reg &= ~ENETC_SIMR_RSSE;
+   reg |= (en) ? ENETC_SIMR_RSSE : 0;
+   enetc_wr(hw, ENETC_SIMR, reg);
+
+   return 0;
+}
+
 int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
struct enetc_si *si = priv->si;
@@ -2398,6 +2414,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
+
+   if (priv->ndev->features & NETIF_F_RXHASH)
+   enetc_set_rss(priv->ndev, true);
}
 
return 0;
@@ -3190,22 +3209,6 @@ struct net_device_stats *enetc_get_stats(struct 
net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static int enetc_set_rss(struct net_device *ndev, int en)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
-   u32 reg;
-
-   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
-   reg = enetc_rd(hw, ENETC_SIMR);
-   reg &= ~ENETC_SIMR_RSSE;
-   reg |= (en) ? ENETC_SIMR_RSSE : 0;
-   enetc_wr(hw, ENETC_SIMR, reg);
-
-   return 0;
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index c346e0e3ad37..a737a7f8c79e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
if (si->hw_features & ENETC_SI_F_LSO)
priv->active_offloads |= ENETC_F_LSO;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 072e5b40a199..3372a9a779a6 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, 
struct net_device *ndev,
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
  NETIF_F_TSO | NETIF_F_TSO6;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* pick up primary MAC address from SI */
enetc_load_primary_mac_addr(&si->hw, ndev);
-- 
2.34.1




[PATCH v2 net-next 10/13] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c

2025-01-13 Thread Wei Fang
Since the VLAN hash filter of ENETC v1 and v4 is the basically same, the
only difference is the offset of the VLAN hash filter registers. So, the
.set_si_vlan_hash_filter() hook is added to struct enetc_pf_ops to set
the registers of the corresponding platform. In addition, the common VLAN
hash filter functions enetc_vlan_rx_add_vid() and enetc_vlan_rx_del_vid()
are moved to enetc_pf_common.c.

Signed-off-by: Wei Fang 
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 34 ++-
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  1 +
 .../freescale/enetc/enetc_pf_common.c | 34 +++
 .../freescale/enetc/enetc_pf_common.h |  2 ++
 4 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c0aaf6349b0b..d9c1ebd180db 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -215,43 +215,12 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-unsigned long hash)
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx, u64 hash)
 {
enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_si *si = priv->si;
-   struct enetc_hw *hw = &si->hw;
-   int idx;
-
-   __set_bit(vid, si->active_vlans);
-
-   idx = enetc_vid_hash_idx(vid);
-   if (!__test_and_set_bit(idx, si->vlan_ht_filter))
-   enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-
-   return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_si *si = priv->si;
-   struct enetc_hw *hw = &si->hw;
-
-   if (__test_and_clear_bit(vid, si->active_vlans)) {
-   enetc_refresh_vlan_ht_filter(si);
-   enetc_set_vlan_ht_filter(hw, 0, *si->vlan_ht_filter);
-   }
-
-   return 0;
-}
-
 static void enetc_set_loopback(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -971,6 +940,7 @@ static const struct enetc_pf_ops enetc_pf_ops = {
.enable_psfp = enetc_psfp_enable,
.set_rss_key = enetc_set_rss_key,
.get_rss_key = enetc_get_rss_key,
+   .set_si_vlan_hash_filter = enetc_set_vlan_ht_filter,
 };
 
 static int enetc_pf_probe(struct pci_dev *pdev,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
index d56b381b9da9..7a0fa5fba8bf 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
@@ -39,6 +39,7 @@ struct enetc_pf_ops {
int (*enable_psfp)(struct enetc_ndev_priv *priv);
void (*set_rss_key)(struct enetc_hw *hw, const u8 *key);
void (*get_rss_key)(struct enetc_hw *hw, u8 *key);
+   void (*set_si_vlan_hash_filter)(struct enetc_hw *hw, int si, u64 hash);
 };
 
 struct enetc_pf {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a737a7f8c79e..9f812c1af7a3 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -343,5 +343,39 @@ void enetc_phylink_destroy(struct enetc_ndev_priv *priv)
 }
 EXPORT_SYMBOL_GPL(enetc_phylink_destroy);
 
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
+   int idx;
+
+   __set_bit(vid, si->active_vlans);
+
+   idx = enetc_vid_hash_idx(vid);
+   if (!__test_and_set_bit(idx, si->vlan_ht_filter))
+   pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
+
+   if (__test_and_clear_bit(vid, si->active_vlans)) {
+   enetc_refresh_vlan_ht_filter(si);
+   pf->ops->set_si_vlan_hash_filter(hw, 0, *si->vlan_ht_filter);
+   }
+
+   return 0;

[PATCH v2 net-next 11/13] net: enetc: add VLAN filtering support for i.MX95 ENETC PF

2025-01-13 Thread Wei Fang
Add VLAN hash filter support for i.MX95 ENETC PF. If VLAN filtering is
disabled, then VLAN promiscuous mode will be enabled, which means that
PF qualifies for reception of all VLAN tags.

Signed-off-by: Wei Fang 
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  4 
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 20 +++
 .../freescale/enetc/enetc_pf_common.c |  2 +-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 826359004850..aa25b445d301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -107,6 +107,10 @@
 #define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
 #define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
 
+/* Port station interface a VLAN hash filter register 0/1 */
+#define ENETC4_PSIVHFR0(a) ((a) * 0x80 + 0x2060)
+#define ENETC4_PSIVHFR1(a) ((a) * 0x80 + 0x2064)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index adb5819c091f..65e6e3742ada 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -85,11 +85,19 @@ static void enetc4_get_rss_key(struct enetc_hw *hw, u8 *key)
((u32 *)key)[i] = enetc_port_rd(hw, ENETC4_PRSSKR(i));
 }
 
+static void enetc4_pf_set_si_vlan_hash_filter(struct enetc_hw *hw,
+ int si, u64 hash)
+{
+   enetc_port_wr(hw, ENETC4_PSIVHFR0(si), lower_32_bits(hash));
+   enetc_port_wr(hw, ENETC4_PSIVHFR1(si), upper_32_bits(hash));
+}
+
 static const struct enetc_pf_ops enetc4_pf_ops = {
.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
.set_rss_key = enetc4_set_rss_key,
.get_rss_key = enetc4_get_rss_key,
+   .set_si_vlan_hash_filter = enetc4_pf_set_si_vlan_hash_filter,
 };
 
 static int enetc4_pf_struct_init(struct enetc_si *si)
@@ -704,6 +712,16 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 static int enetc4_pf_set_features(struct net_device *ndev,
  netdev_features_t features)
 {
+   netdev_features_t changed = ndev->features ^ features;
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+
+   if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+   bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+
+   enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+   }
+
enetc_set_features(ndev, features);
 
return 0;
@@ -717,6 +735,8 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_set_mac_address= enetc_pf_set_mac_addr,
.ndo_set_rx_mode= enetc4_pf_set_rx_mode,
.ndo_set_features   = enetc4_pf_set_features,
+   .ndo_vlan_rx_add_vid= enetc_vlan_rx_add_vid,
+   .ndo_vlan_rx_kill_vid   = enetc_vlan_rx_del_vid,
 };
 
 static struct phylink_pcs *
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 9f812c1af7a3..3f7ccc482301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -135,7 +135,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | 
NETIF_F_LOOPBACK);
+   ndev->hw_features &= ~NETIF_F_LOOPBACK;
goto end;
}
 
-- 
2.34.1




[PATCH v2 net-next 12/13] net: enetc: add loopback support for i.MX95 ENETC PF

2025-01-13 Thread Wei Fang
Add internal loopback support for i.MX95 ENETC PF, the default loopback
mode is MAC level loopback, the MAC Tx data is looped back onto the Rx.
The MAC interface runs at a fixed 1:8 ratio of NETC clock in MAC-level
loopback mode, with no dependency on Tx clock.

Signed-off-by: Wei Fang 
---
 .../net/ethernet/freescale/enetc/enetc4_pf.c   | 18 ++
 .../ethernet/freescale/enetc/enetc_pf_common.c |  4 +---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 65e6e3742ada..948d2f796bfb 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -709,6 +709,21 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_si *si = priv->si;
+   u32 val;
+
+   val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+   val = u32_replace_bits(val, en ? 1 : 0, PM_CMD_CFG_LOOP_EN);
+   /* Default to select MAC level loopback mode if loopback is enabled. */
+   val = u32_replace_bits(val, en ? LPBCK_MODE_MAC_LEVEL : 0,
+  PM_CMD_CFG_LPBK_MODE);
+
+   enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
 static int enetc4_pf_set_features(struct net_device *ndev,
  netdev_features_t features)
 {
@@ -722,6 +737,9 @@ static int enetc4_pf_set_features(struct net_device *ndev,
enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
}
 
+   if (changed & NETIF_F_LOOPBACK)
+   enetc4_pf_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
enetc_set_features(ndev, features);
 
return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 3f7ccc482301..0a2b8769a175 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -134,10 +134,8 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
}
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
-   if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~NETIF_F_LOOPBACK;
+   if (!is_enetc_rev1(si))
goto end;
-   }
 
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-- 
2.34.1




[PATCH v2 net-next 07/13] net: enetc: add RSS support for i.MX95 ENETC PF

2025-01-13 Thread Wei Fang
Add Receive side scaling (RSS) support for i.MX95 ENETC PF to improve the
network performance and balance the CPU loading. In addition, since both
ENETC v1 and ENETC v4 only support the toeplitz algorithm, so a check for
hfunc was added.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  |  7 +---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  4 ++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 37 +++
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 14 +++
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 33 -
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  2 +
 .../freescale/enetc/enetc_pf_common.c |  6 +--
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  2 +
 8 files changed, 87 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 6d21c133e418..233f58e57a20 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2363,7 +2363,7 @@ static int enetc_setup_default_rss_table(struct enetc_si 
*si, int num_groups)
for (i = 0; i < si->num_rss; i++)
rss_table[i] = i % num_groups;
 
-   enetc_set_rss_table(si, rss_table, si->num_rss);
+   si->ops->set_rss_table(si, rss_table, si->num_rss);
 
kfree(rss_table);
 
@@ -2394,10 +2394,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
if (si->hw_features & ENETC_SI_F_LSO)
enetc_set_lso_flags_mask(hw);
 
-   /* TODO: RSS support for i.MX95 will be supported later, and the
-* is_enetc_rev1() condition will be removed
-*/
-   if (si->num_rss && is_enetc_rev1(si)) {
+   if (si->num_rss) {
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index fb53fb961364..2b0d27ed924d 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -290,6 +290,8 @@ struct enetc_si;
 struct enetc_si_ops {
int (*setup_cbdr)(struct enetc_si *si);
void (*teardown_cbdr)(struct enetc_si *si);
+   int (*get_rss_table)(struct enetc_si *si, u32 *table, int count);
+   int (*set_rss_table)(struct enetc_si *si, const u32 *table, int count);
 };
 
 /* PCI IEP device data */
@@ -540,6 +542,8 @@ int enetc_set_fs_entry(struct enetc_si *si, struct 
enetc_cmd_rfse *rfse,
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 
 static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
 struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 798c69e83c8f..adb5819c091f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -69,9 +69,27 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw 
*hw, int si,
put_unaligned_le16(lower, addr + 4);
 }
 
+static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *key)
+{
+   int i;
+
+   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)key)[i]);
+}
+
+static void enetc4_get_rss_key(struct enetc_hw *hw, u8 *key)
+{
+   int i;
+
+   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+   ((u32 *)key)[i] = enetc_port_rd(hw, ENETC4_PRSSKR(i));
+}
+
 static const struct enetc_pf_ops enetc4_pf_ops = {
.set_si_primary_mac = enetc4_pf_set_si_primary_mac,
.get_si_primary_mac = enetc4_pf_get_si_primary_mac,
+   .set_rss_key = enetc4_set_rss_key,
+   .get_rss_key = enetc4_get_rss_key,
 };
 
 static int enetc4_pf_struct_init(struct enetc_si *si)
@@ -263,14 +281,6 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
enetc4_pf_reset_tc_msdu(&si->hw);
 }
 
-static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-   int i;
-
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
-}
-
 static void enetc4_set_default_rss_key(struct enetc_pf *pf)
 {
u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
@@ -691,6 +701,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static int enetc4_pf_set_features(struct net_device

[PATCH v2 net-next 09/13] net: enetc: move generic VLAN filter interfaces to enetc-core

2025-01-13 Thread Wei Fang
For ENETC, each SI has a corresponding VLAN hash table. That is to say,
both PF and VFs can support VLAN filter. However, currently only ENETC v1
PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
VF drivers also support VLAN filter, some related macros are moved from
enetc_pf.h to enetc.h, and the related structure variables are moved from
enetc_pf to enetc_si.

Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
so that it can be shared by PF and VF drivers. This will make it easier
to add VLAN filter support for i.MX95 ENETC later.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 25 ++
 drivers/net/ethernet/freescale/enetc/enetc.h  |  6 +++
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 46 +--
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  4 --
 4 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index e27b031c4f46..8b4a004f51a4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -72,6 +72,31 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter 
*filter)
 }
 EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
 
+int enetc_vid_hash_idx(unsigned int vid)
+{
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+   return res;
+}
+EXPORT_SYMBOL_GPL(enetc_vid_hash_idx);
+
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si)
+{
+   int i;
+
+   bitmap_zero(si->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, si->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
+
+   __set_bit(hidx, si->vlan_ht_filter);
+   }
+}
+EXPORT_SYMBOL_GPL(enetc_refresh_vlan_ht_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 2b0d27ed924d..0ecec9da6148 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -24,6 +24,7 @@
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
 #define ENETC_MADDR_HASH_TBL_SZ64
+#define ENETC_VLAN_HT_SIZE 64
 
 enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
 
@@ -321,6 +322,9 @@ struct enetc_si {
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
struct dentry *debugfs_root;
+
+   DECLARE_BITMAP(vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   DECLARE_BITMAP(active_vlans, VLAN_N_VID);
 };
 
 #define ENETC_SI_ALIGN 32
@@ -506,6 +510,8 @@ int enetc_get_driver_data(struct enetc_si *si);
 void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
  const unsigned char *addr);
 void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
+int enetc_vid_hash_idx(unsigned int vid);
+void enetc_refresh_vlan_ht_filter(struct enetc_si *si);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 59039d087695..c0aaf6349b0b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -222,45 +222,18 @@ static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, 
int si_idx,
enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
 }
 
-static int enetc_vid_hash_idx(unsigned int vid)
-{
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
-{
-   int i;
-
-   if (rehash) {
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
-   }
-
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-}
-
 static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int idx;
 
-   __set_bit(vid, pf->active_vlans);
+   __set_bit(vid, si->active_vlans);
 
idx = enetc_vid_hash_idx(vid);
-   if (!__test_and_set_bit(idx

[PATCH v2 net-next 06/13] net: enetc: make enetc_set_rxfh() and enetc_get_rxfh() reusable

2025-01-13 Thread Wei Fang
Both ENETC v1 and v4 support Receive Side Scaling (RSS), but the offset
of the RSS key registers is different. In order to make enetc_get_rxfh()
and enetc_set_rxfh() be reused by ENETC v4, the .set_rss_key() and
.get_rss_key() interfaces are added to enect_pf_ops.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 -
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 42 +--
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 18 
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  2 +
 4 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index ca1bc85c0ac9..fb53fb961364 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -537,7 +537,6 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
 int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
   int index);
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 
b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index bf34b5bb1e35..56ba82830279 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -4,7 +4,8 @@
 #include 
 #include 
 #include 
-#include "enetc.h"
+
+#include "enetc_pf.h"
 
 static const u32 enetc_si_regs[] = {
ENETC_SIMR, ENETC_SIPMAR0, ENETC_SIPMAR1, ENETC_SICBDRMR,
@@ -681,51 +682,46 @@ static int enetc_get_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
-   int err = 0, i;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
+   int err = 0;
 
/* return hash function */
rxfh->hfunc = ETH_RSS_HASH_TOP;
 
/* return hash key */
-   if (rxfh->key && hw->port)
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   ((u32 *)rxfh->key)[i] = enetc_port_rd(hw,
- ENETC_PRSSK(i));
+   if (rxfh->key && enetc_si_is_pf(si)) {
+   struct enetc_pf *pf = enetc_si_priv(si);
+
+   pf->ops->get_rss_key(hw, rxfh->key);
+   }
 
/* return RSS table */
if (rxfh->indir)
-   err = enetc_get_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = enetc_get_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
 
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-   int i;
-
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
-}
-EXPORT_SYMBOL_GPL(enetc_set_rss_key);
-
 static int enetc_set_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh,
  struct netlink_ext_ack *extack)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int err = 0;
 
/* set hash key, if PF */
-   if (rxfh->key && hw->port)
-   enetc_set_rss_key(hw, rxfh->key);
+   if (rxfh->key && enetc_si_is_pf(si)) {
+   struct enetc_pf *pf = enetc_si_priv(si);
+
+   pf->ops->set_rss_key(hw, rxfh->key);
+   }
 
/* set RSS table */
if (rxfh->indir)
-   err = enetc_set_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = enetc_set_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index cc3e52bd3096..f050cf039733 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -512,6 +512,22 @@ static void enetc_mac_enable(struct enetc_si *si, bool en)
enetc_port_mac_wr(si, ENETC_PM0_CMD_CFG, val);
 }
 
+static void enetc_set_rss_key(struct enetc_hw *hw, const u8 *key)
+{
+   int i;
+
+   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
+   enetc_port_wr(hw, ENETC_PRSSK(i), ((u

[PATCH v2 net-next 13/13] MAINTAINERS: add new file ntmp.h to ENETC driver

2025-01-13 Thread Wei Fang
Add new file ntmp.h. to ENETC driver.

Signed-off-by: Wei Fang 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1579124ef426..ac28154f7eb5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9099,6 +9099,7 @@ F:
Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
 F: drivers/net/ethernet/freescale/enetc/
 F: include/linux/fsl/enetc_mdio.h
 F: include/linux/fsl/netc_global.h
+F: include/linux/fsl/ntmp.h
 
 FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 M: Claudiu Manoil 
-- 
2.34.1




RE: [PATCH v2 net-next 07/13] net: enetc: add RSS support for i.MX95 ENETC PF

2025-01-15 Thread Wei Fang
> -Original Message-
> From: Jakub Kicinski 
> Sent: 2025年1月16日 10:41
> To: Wei Fang 
> Cc: Claudiu Manoil ; Vladimir Oltean
> ; Clark Wang ;
> andrew+net...@lunn.ch; da...@davemloft.net; eduma...@google.com;
> pab...@redhat.com; christophe.le...@csgroup.eu; net...@vger.kernel.org;
> linux-ker...@vger.kernel.org; linuxppc-dev@lists.ozlabs.org;
> linux-arm-ker...@lists.infradead.org; i...@lists.linux.dev
> Subject: Re: [PATCH v2 net-next 07/13] net: enetc: add RSS support for i.MX95
> ENETC PF
> 
> On Thu, 16 Jan 2025 02:24:10 + Wei Fang wrote:
> > > Why create full ops for something this trivial?
> >
> > We add enetc_pf_hw_ops to implement different hardware ops
> > for different chips. So that they can be called in common functions.
> > Although the change is minor, it is consistent with the original
> > intention of adding enetc_pf_hw_ops.
> 
> In other words you prefer ops.
> 
> Now imagine you have to refactor such piece of code in 10 drivers
> and each of them has 2 layers of indirect ops like you do.
> Unnecessary complexity.

Okay, I will remove them from ops.



RE: [PATCH v2 net-next 07/13] net: enetc: add RSS support for i.MX95 ENETC PF

2025-01-15 Thread Wei Fang
> On Mon, 13 Jan 2025 16:22:39 +0800 Wei Fang wrote:
> > Add Receive side scaling (RSS) support for i.MX95 ENETC PF to improve the
> > network performance and balance the CPU loading. In addition, since both
> > ENETC v1 and ENETC v4 only support the toeplitz algorithm, so a check for
> > hfunc was added.
> 
> This and previous commits are a bi hard to follow. You plumb some
> stuff thru in the previous commit. In this one you reshuffle things,
> again. Try to separate code movement / restructuring in one commit.
> And new additions more clearly in the next.

Okay, I will.

> 
> > +static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *key)
> > +{
> > +   int i;
> > +
> > +   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> > +   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)key)[i]);
> > +}
> > +
> > +static void enetc4_get_rss_key(struct enetc_hw *hw, u8 *key)
> > +{
> > +   int i;
> > +
> > +   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> > +   ((u32 *)key)[i] = enetc_port_rd(hw, ENETC4_PRSSKR(i));
> > +}
> 
> Isn't the only difference between the chips the register offset?
Yes.

> Why create full ops for something this trivial?

We add enetc_pf_hw_ops to implement different hardware ops
for different chips. So that they can be called in common functions.
Although the change is minor, it is consistent with the original
intention of adding enetc_pf_hw_ops.

> 
> > +static int enetc4_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc
> *rxnfc,
> > +   u32 *rule_locs)
> > +{
> > +   struct enetc_ndev_priv *priv = netdev_priv(ndev);
> > +
> > +   switch (rxnfc->cmd) {
> > +   case ETHTOOL_GRXRINGS:
> > +   rxnfc->data = priv->num_rx_rings;
> > +   break;
> > +   case ETHTOOL_GRXFH:
> > +   return enetc_get_rsshash(rxnfc);
> > +   default:
> > +   return -EOPNOTSUPP;
> > +   }
> > +
> > +   return 0;
> > +}
> 
> Why add a new function instead of returning EOPNOTSUPP for new chips
> in the existing one?

We will add ETHTOOL_G/SRXCLSXXX in the future, but both the hardware and
software implementation of ENETC4 are different from ENETC1, and we don't
want to mix them in one function, which would look a bit messy.

> 
> > @@ -712,6 +730,12 @@ static int enetc_set_rxfh(struct net_device *ndev,
> > struct enetc_hw *hw = &si->hw;
> > int err = 0;
> >
> > +   if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
> > +   rxfh->hfunc != ETH_RSS_HASH_TOP) {
> > +   netdev_err(ndev, "Only toeplitz hash function is supported\n");
> > +   return -EOPNOTSUPP;
> 
> Should be a separate commit.
> --
> pw-bot: cr



RE: [PATCH v3 net-next 04/13] net: enetc: add MAC filter for i.MX95 ENETC PF

2025-03-15 Thread Wei Fang
> On 3/4/25 8:21 AM, Wei Fang wrote:
> > +static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16
> si_bit,
> > +  struct enetc_mac_addr *mac,
> > +  int mac_cnt)
> > +{
> > +   struct enetc_mac_list_entry *entry;
> > +   int i;
> > +
> > +   for (i = 0; i < mac_cnt; i++) {
> > +   entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> > +   if (entry) {
> > +   entry->si_bitmap &= ~si_bit;
> > +   if (!entry->si_bitmap) {
> 
> 
> Minor nit: here and elsewhere you could reduce the level of indentation
> restructoring the code as:

Okay, I will improve it, thanks.
> 
>   if (!entry)
>   continue;
> 
>   entry->si_bitmap &= ~si_bit;
>   if (entry->si_bitmap)
>   continue;
> /P



RE: [PATCH v4 net-next 11/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c

2025-03-18 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:27PM +0800, Wei Fang wrote:
> > Since the VLAN hash filter of ENETC v1 and v4 is the basically same, the
> > only difference is the offset of the VLAN hash filter registers. So, the
> > .set_si_vlan_hash_filter() hook is added to struct enetc_pf_ops to set
> > the registers of the corresponding platform.
> 
> For the RSS hash key register, you added a function which retrieves the
> register base. For the VLAN hash filter, you add ops. Same problem,
> different solutions?

I thought it was a bit different, because we have a 'si' parameter, anyway,
I think it is fine to remove this ops and use the same way as RSS.




RE: [PATCH v4 net-next 03/14] net: enetc: move generic MAC filterng interfaces to enetc-core

2025-03-17 Thread Wei Fang
> title: s/filterng/filtering/
> 
> On Tue, Mar 11, 2025 at 01:38:19PM +0800, Wei Fang wrote:
> > Although only ENETC PF can access the MAC address filter table, the table
> > entries can specify MAC address filtering for one or more SIs based on
> > SI_BITMAP, which means that the table also supports MAC address filtering
> > for VFs.
> >
> > Currently, only the ENETC v1 PF driver supports MAC address filtering. In
> > order to add the MAC address filtering support for the ENETC v4 PF driver
> > and VF driver in the future, the relevant generic interfaces are moved to
> > the enetc-core driver. At the same time, the struct enetc_mac_filter is
> > moved from enetc_pf to enetc_si, because enetc_si is a structure shared by
> > PF and VFs. This lays the basis for i.MX95 ENETC PF and VFs to support
> > MAC address filtering.
> >
> > Signed-off-by: Wei Fang 
> > ---
> 
> For this series I don't see any VF implementation of ndo_set_rx_mode().
> I don't think you have to move struct enetc_mac_filter from struct enetc_pf
> to struct enetc_si, so please don't do that until there is a justification
> for it that is contained in the same patch set, and the two can be
> evaluated together.

Okay, I will keep them in "struct enetc_pf". :)
> 
> Moving enetc_add_mac_addr_ht_filter() and enetc_reset_mac_addr_filter()
> to enetc.c seems fine.




RE: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-03-17 Thread Wei Fang
> On Fri, Mar 14, 2025 at 03:48:21PM +0200, Wei Fang wrote:
> > > I mean, I was just suggesting to group the macros with the macros, and
> > > the struct fields with the struct fields. Mixing them together looks a
> > > bit messy to me. Even worse in the definition of "union netc_cbd" which
> > > IMO needs to be reconsidered a bit (a hint given below).
> >
> > I think this is a matter of personal preference. I was inspired by some
> > of Intel's structure definitions. I think this method allows me to quickly
> > understand what fields the member consists of and what bits each field
> > occupies.
> (...)
> > Thanks, but we have added fully NTMP support in downstream, it's a great
> > challenge for me to convert it to the 'packing' method. I don't think I have
> > too much time to do this conversion. And I also need some time to figure
> > out how to use it and whether it is worth doing so.
> 
> Ok, I'm not forcing you to use pack_fields(), but given the fact that
> bit field overlap is now something that has to be manually checked, and
> a bug of this kind already exists in this set, you will have to wait for
> me, or other reviewers, to go through the bit field definitions from the
> entire set.
> 
> > > And I agree with you, I also don't want ntmp_private.h to be exposed to
> > > the NTMP API consumers, and I wasn't suggesting that. I just want the
> > > NTMP API to spare consumer drivers of the gory details, like for example
> > > the buffer layout of a MAC filtering entry, reserved fields, things like
> > > that. What I was saying is to keep the buffer layout private to
> > > ntmp_private.h, and expose a more abstract data structure to API
> > > consumers.
> >
> > Sorry, I don't fully understand, for example, if we place the definition
> > of "struct maft_keye_data" in ntmp_private.h, how does the debugfs
> > get the information from "struct maft_keye_data"? Add a helper function
> > in the NTMP driver and export it to enetc driver? And how does
> > enetc4_pf_add_si_mac_exact_filter() to set the mac address to "struct
> > maft_keye_data", add another helper? If so, I think it is more complicated.
> 
> Well, my complaint, which has to do with style and personal preference,
> is that exposing packed data structures to NTMP API clients puts an
> unnecessary burden on them. For example, NTMP users have to call
> cpu_to_le16()
> to populate data.cfge.si_bitmap. A bug in the packed layout will
> potentially have to be fixed in multiple places. The two options for a
> more high-level NTMP API that I see are:
> - You expose pointers to the packed data structures, but API functions
>   provide getters and setters, and the exact buffer layout is only known
>   to the NTMP layer.
> - The API functions expose "unpacked" data structures, which are more
>   abstract and don't contain reserved fields and are in CPU native
>   endianness, and the NTMP layer packs them to buffers, either using
>   pack_fields() or manually.
> 

Actually I did this is the original version, I mean in downstream kernel 6.6
tree. I add a "ntmp_mfe" in ntmp.h like below

struct ntmp_mfe {
u8 mac[ETH_ALEN];
u16 si_bitmap;
};

And the conversion was done by the NTMP driver. But then I found that this was
very troublesome. We get data from kernel "struct A,B,C", then the enetc driver
converts them to "struct D", and finally the ntmp driver converts it to "struct 
E".
So I thought why don't we convert "struct A,B,C" to "struct E" from the 
beginning?
After all, these data structures are only used by enetc and netc switch 
drivers, so
in kernel 6.12, I changed it to the current way.

> Claudiu, what do you think? I can withdraw the request to hide packed
> MAFT (and other) struct definitions from include/linux/fsl/ntmp.h if you
> think they're fine there.
> 
> > > Thank you for posting the downstream layout of struct ntmp_priv which I
> > > was already aware of. What I was saying is that the word "private" means
> > > an aspect of the implementation which is hidden from other code layers.
> > > There's nothing "private" here if the NTMP layer has access to the
> > > definition of this structure. I was asking whether you agree that it's
> > > more adequate to name this structure "ntmp_client", since it represents
> > > the data associated with a consumer of the NTMP API - a NETC SI or (in
> > > the future) the switch. Or some other name. But the word "private" seems
> > > misused.
> >
> > Okay, it seems to make you feel confused, let me rename it later, how about
> > "ntmp_user"?
> 
> "ntmp_user" works for me better than "ntmp_priv", thanks. Are you also
> going to make the API functions from include/linux/fsl/ntmp.h take
> "struct ntmp_user *" as first argument, rather than "struct netc_cbdrs *"?

I think we do not need to keep "struct netc_cbdrs", it can be integrated into
"struct ntmp_user".




RE: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95 ENETC PF

2025-03-18 Thread Wei Fang
> > +
> > +static void enetc4_pf_set_si_mac_hash_filter(struct enetc_hw *hw, int si,
> > +int type, u64 hash)
> > +{
> > +   if (type == UC) {
> > +   enetc_port_wr(hw, ENETC4_PSIUMHFR0(si), lower_32_bits(hash));
> > +   enetc_port_wr(hw, ENETC4_PSIUMHFR1(si), upper_32_bits(hash));
> > +   } else { /* MC */
> > +   enetc_port_wr(hw, ENETC4_PSIMMHFR0(si), lower_32_bits(hash));
> > +   enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
> > +   }
> > +}
> 
> Please split into separate functions for unicast and for multicast.
> The implementations don't share any code, and the callers are not in
> common code either.
> 

Just copied from enetc_set_mac_ht_flt (), I can split into two separate
functions.

> > +
> > +static void enetc4_pf_destroy_mac_list(struct enetc_pf *pf)
> > +{
> > +   struct enetc_mac_list_entry *entry;
> > +   struct hlist_node *tmp;
> > +
> > +   mutex_lock(&pf->mac_list_lock);
> 
> The mutex_lock() usage here should raise serious questions. This is
> running right before mutex_destroy(). So if there were any concurrent
> attempt to acquire this lock, that concurrent code would have been broken
> any time it would have lost arbitration, by the fact that it would
> attempt to acquire a destroyed mutex.
> 
> But there's no such concurrent thread, because we run after
> destroy_workqueue()
> which flushes those concurrent calls and prevents new ones. So the mutex
> usage here is not necessary.
> 

You are right, but I'm afraid of the Coverity will report an issue, because the
pf->mac_list and pf->num_mfe are protected by the mac_list_lock in other
functions. And enetc4_pf_destroy_mac_list() will be called in other function
in the subsequent patches. I don't think it is unnecessary.

> [ same thing with mutex_init() immediately followed by mutex_lock().
>   It is an incorrect pattern most of the time. ]
> 
> > +
> > +   hlist_for_each_entry_safe(entry, tmp, &pf->mac_list, node) {
> > +   hlist_del(&entry->node);
> > +   kfree(entry);
> > +   }
> > +
> > +   pf->num_mfe = 0;
> > +
> > +   mutex_unlock(&pf->mac_list_lock);
> > +}
> > +
> > +static bool enetc_mac_filter_type_check(int type, const u8 *addr)
> > +{
> > +   if (type == ENETC_MAC_FILTER_TYPE_UC)
> > +   return !is_multicast_ether_addr(addr);
> > +   else if (type == ENETC_MAC_FILTER_TYPE_MC)
> > +   return is_multicast_ether_addr(addr);
> > +   else
> > +   return true;
> > +}
> > +
> > +static struct enetc_mac_list_entry *
> > +enetc_mac_list_lookup_entry(struct enetc_pf *pf, const unsigned char
> *addr)
> > +{
> > +   struct enetc_mac_list_entry *entry;
> > +
> > +   hlist_for_each_entry(entry, &pf->mac_list, node)
> > +   if (ether_addr_equal(entry->mac, addr))
> > +   return entry;
> > +
> > +   return NULL;
> > +}
> > +
> > +static void enetc_mac_list_add_entry(struct enetc_pf *pf,
> > +struct enetc_mac_list_entry *entry)
> > +{
> > +   hlist_add_head(&entry->node, &pf->mac_list);
> > +}
> > +
> > +static void enetc_mac_list_del_entry(struct enetc_mac_list_entry *entry)
> > +{
> > +   hlist_del(&entry->node);
> > +   kfree(entry);
> > +}
> > +
> > +static void enetc_mac_list_del_matched_entries(struct enetc_pf *pf, u16
> si_bit,
> > +  struct enetc_mac_addr *mac,
> > +  int mac_cnt)
> > +{
> > +   struct enetc_mac_list_entry *entry;
> > +   int i;
> > +
> > +   for (i = 0; i < mac_cnt; i++) {
> > +   entry = enetc_mac_list_lookup_entry(pf, mac[i].addr);
> > +   if (!entry)
> > +   continue;
> > +
> > +   entry->si_bitmap &= ~si_bit;
> > +   if (entry->si_bitmap)
> > +   continue;
> > +
> > +   enetc_mac_list_del_entry(entry);
> > +   pf->num_mfe--;
> > +   }
> > +}
> > +
> > +static bool enetc_mac_list_is_available(struct enetc_pf *pf,
> > +   struct enetc_mac_addr *mac,
> > +   int mac_cnt)
> > +{
> > +   int max_num_mfe = pf->caps.mac_filter_num;
> > +   struct enetc_mac_list_entry *entry;
> > +   int cur_num_mfe = pf->num_mfe;
> > +   int i, new_mac_cnt = 0;
> > +
> > +   if (mac_cnt > max_num_mfe)
> > +   return false;
> > +
> > +   /* Check MAC filter table whether has enough available entries */
> > +   hlist_for_each_entry(entry, &pf->mac_list, node) {
> > +   for (i = 0; i < mac_cnt; i++) {
> > +   if (ether_addr_equal(entry->mac, mac[i].addr))
> > +   break;
> > +   }
> > +
> > +   if (i == mac_cnt)
> > +   new_mac_cnt++;
> > +
> > +   if ((cur_num_mfe + new_mac_cnt) > max_num_mfe)
> > +   return false;
> > +   }
> > +
> > +   return true;
> > +}
> > +
> > +static int enetc4_pf_add_si_mac_exact_filter(struct enetc

RE: [PATCH v4 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF

2025-03-18 Thread Wei Fang
> On Tue, Mar 18, 2025 at 06:47:11AM +0200, Wei Fang wrote:
> > > These rxnfc commands seem implemented identically to the corresponding
> > > subset from enetc_get_rxnfc(). Rather than duplicating those, could you
> > > rather return -EOPNOTSUPP for the unsupported ones on NETC v4, and
> reuse
> > > enetc_get_rxnfc()?
> > >
> >
> > I have explained it to Jakub in v2:
> >
> https://lore.kernel.org/imx/PAXPR04MB8510B52B7D27640C557680B4881A2
> @PAXPR04MB8510.eurprd04.prod.outlook.com/
> >
> > So I don't want to reuse it for ENETC v4 PF.
> 
> A detail of the review process, written in
> Documentation/process/6.Followthrough.rst,
> is that "Andrew Morton has suggested that every review comment which does
> not result in a code change should result in an additional code comment
> instead; that can help future reviewers avoid the questions which came
> up the first time around."
> 
> [ personal mention: it doesn't have to be a code comment but can also be
>   a sentence in the commit message ]
> 
> I believe that it would be good if you could apply that suggestion for
> future submissions (not only for this particular comment).

Okay, good to know this info, I will add a comments here.




RE: [PATCH v4 net-next 04/14] net: enetc: add MAC filter for i.MX95 ENETC PF

2025-03-18 Thread Wei Fang
> On Tue, Mar 18, 2025 at 05:19:51AM +0200, Wei Fang wrote:
> > You are right, but I'm afraid of the Coverity will report an issue, because 
> > the
> > pf->mac_list and pf->num_mfe are protected by the mac_list_lock in other
> > functions. And enetc4_pf_destroy_mac_list() will be called in other function
> > in the subsequent patches. I don't think it is unnecessary.
> 
> Sorry, but I can only take the presented code at face value. If the
> Coverity tool signals an issue, you can still triage it and explain why
> it is a false positive. Or, if it is a real issue, you can add locking
> and provide a good justification for it. But the justification is
> missing now.
> 
> > So for your question about Rx packet loss, although it is a very corner
> > case, the solution I can think of is that we can use temporary MAC hash
> > filters before deleting MAFT entries and delete them after adding the
> > MAFT entries. Can you accept this proposal?
> 
> That sounds good. I'm thinking, for each MAC address filter, maybe you
> need an information whether it is programmed to hardware as an exact
> match filter or a hash filter, and make use of that functionality here:
> temporarily make all filters be hash-based ones, and then see how many
> you can convert to exact matches. With something like this, it should
> also be easier to maximize the use of the exact match table. Currently,
> AFAIU, if you have 5 MAC address filters, they will all be stored as hash
> filters, even if 4 of them could have been exact matches. Maybe that can
> also be improved with such extra information.
> 

Currently, I don't want to make the driver too complicated, I think if the 
number
of MACs exceeds the MAFT's capability, we just use hash filter. Otherwise, we
use MAFT.

> > > > +static int enetc4_pf_set_mac_exact_filter(struct enetc_pf *pf, int 
> > > > type)
> > > > +{
> > > > +   int max_num_mfe = pf->caps.mac_filter_num;
> > > > +   struct net_device *ndev = pf->si->ndev;
> > > > +   struct enetc_mac_addr *mac_tbl;
> > > > +   struct netdev_hw_addr *ha;
> > > > +   u8 si_mac[ETH_ALEN];
> > > > +   int mac_cnt = 0;
> > > > +   int err;
> > > > +
> > > > +   mac_tbl = kcalloc(max_num_mfe, sizeof(*mac_tbl), GFP_KERNEL);
> > >
> > > Can't you know ahead of time, based on netdev_uc_count(), whether you
> > > will have space for exact match filters, and avoid unnecessary
> > > allocations if not? enetc_mac_list_is_available() seems way too late.
> >
> > I can add a check before alloc mac_tbl, but enetc_mac_list_is_available()
> > is still needed, because enetc4_pf_add_si_mac_exact_filter() is a common
> > function for all Sis, not only for PSI.
> 
> From the way in which the discussion is progressing in the replies
> above, it sounds to me like maybe this logic will change a bit more.
> 
> > > > +static int enetc4_pf_wq_task_init(struct enetc_si *si)
> > > > +{
> > > > +   char wq_name[24];
> > > > +
> > > > +   INIT_WORK(&si->rx_mode_task, enetc4_pf_do_set_rx_mode);
> > > > +   snprintf(wq_name, sizeof(wq_name), "enetc-%s",
> pci_name(si->pdev));
> > > > +   si->workqueue = create_singlethread_workqueue(wq_name);
> > > > +   if (!si->workqueue)
> > > > +   return -ENOMEM;
> > > > +
> > > > +   return 0;
> > > > +}
> > >
> > > Naming scheme is inconsistent here: the function is called "pf" but
> > > takes "si" as argument. Same for enetc4_pf_do_set_rx_mode() where the
> > > rx_mode_task is part of the station interface structure.
> >
> > So change 'pf' to 'psi'?
> 
> Sounds better.
> 
> > > > +   struct hlist_head mac_list; /* MAC address filter table */
> > >
> > > One thing I don't understand is why, given this implementation and
> > > final effect, you even bother to keep the mac_list persistently in
> > > struct enetc_pf. You have:
> > >
> > > enetc4_pf_do_set_rx_mode()
> > > -> enetc4_pf_flush_si_mac_exact_filter(ENETC_MAC_FILTER_TYPE_ALL)
> > >-> hlist_for_each_entry_safe(&pf->mac_list)
> > >   -> enetc_mac_list_del_entry()
> > >
> > > which practically deletes all &pf->mac_list elements every time.
> > > So why even store them persistently in the first place? Why not just
> > 

RE: [PATCH v4 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC

2025-03-13 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:18PM +0800, Wei Fang wrote:
> > The command BD ring is used to configure functionality where the
> > underlying resources may be shared between different entities or being
> > too large to configure using direct registers (such as lookup tables).
> >
> > Because the command BD and table formats of i.MX95 and LS1028A are very
> > different, the software processing logic is also different. In order to
> > ensure driver compatibility, struct enetc_si_ops is introduced. This
> > structure defines some hooks shared by VSI and PSI. Different hardware
> > driver will register different hooks, For example, setup_cbdr() is used
> > to initialize the command BD ring, and teardown_cbdr() is used to free
> > the command BD ring.
> >
> > Signed-off-by: Wei Fang 
> > ---
> >  drivers/net/ethernet/freescale/enetc/enetc.h  | 27 +++--
> >  .../net/ethernet/freescale/enetc/enetc4_pf.c  | 47 +++-
> >  .../net/ethernet/freescale/enetc/enetc_cbdr.c | 55 +--
> >  .../net/ethernet/freescale/enetc/enetc_pf.c   | 13 +++--
> >  .../net/ethernet/freescale/enetc/enetc_vf.c   | 13 +++--
> >  5 files changed, 136 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h
> b/drivers/net/ethernet/freescale/enetc/enetc.h
> > index 4ad4eb5c5a74..4ff0957e69be 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc.h
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
> > @@ -8,6 +8,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -266,6 +267,19 @@ struct enetc_platform_info {
> > const struct enetc_drvdata *data;
> >  };
> >
> > +struct enetc_si;
> > +
> > +/*
> > + * This structure defines the some common hooks for ENETC PSI and VSI.
> > + * In addition, since VSI only uses the struct enetc_si as its private
> > + * driver data, so this structure also define some hooks specifically
> > + * for VSI. For VSI-specific hooks, the format is ‘vf_*()’.
> > + */
> > +struct enetc_si_ops {
> > +   int (*setup_cbdr)(struct enetc_si *si);
> > +   void (*teardown_cbdr)(struct enetc_si *si);
> > +};
> 
> I don't understand the need for si->ops->setup_cbdr() and
> si->ops->teardown_cbdr()?
> Doesn't every call site know which kind of SI it is dealing with, and thus it 
> can
> appropriately call the direct symbol?
> - the v1 PSI and the VSI call enetc_setup_cbdr() and enetc_teardown_cbdr()
> - the v4 PSI calls enetc4_setup_cbdr() and enetc4_teardown_cbdr()

Yes, for PSI we can use directly call these functions because they are different
drivers, but for VSI, v1 and v4 will use the same driver. I just want the PSI 
and
VSI to be consistent. If you don't like this, I can remove these interfaces from
the patch set, and add vf_setup_cbdr and vf_teardown_cbdr in the future when
I add the VF support for ENETC v4.

> What benefit is there to making an indirect function call?
> 
> At least that's what the current code does, I'm not sure if that is the 
> intention.




RE: [PATCH v4 net-next 14/14] MAINTAINERS: add new file ntmp.h to ENETC driver

2025-03-17 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:30PM +0800, Wei Fang wrote:
> > Add new file ntmp.h. to ENETC driver.
> >
> > Signed-off-by: Wei Fang 
> > ---
> >  MAINTAINERS | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > 7078199fcebf..e259b659eadb 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -9174,6 +9174,7 @@ F:
>   Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
> >  F: drivers/net/ethernet/freescale/enetc/
> >  F: include/linux/fsl/enetc_mdio.h
> >  F: include/linux/fsl/netc_global.h
> > +F: include/linux/fsl/ntmp.h
> >
> >  FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
> >  M: Claudiu Manoil 
> > --
> > 2.34.1
> >
> 
> This should be squashed with the patch that adds the initial NTMP support.
> We don't split out patches to the MAINTAINERS file.

Okay, I will squashed it to the NTMP patch.




RE: [PATCH v4 net-next 09/14] net: enetc: enable RSS feature by default

2025-03-17 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:25PM +0800, Wei Fang wrote:
> > Receive side scaling (RSS) is a network driver technology that enables
> > the efficient distribution of network receive processing across
> > multiple CPUs in multiprocessor systems. Therefore, it is better to
> > enable RSS by default so that the CPU load can be balanced and network
> > performance can be improved when then network is enabled.
> 
> s/then network/the network/
> 
> >
> > Signed-off-by: Wei Fang 
> > ---
> >  drivers/net/ethernet/freescale/enetc/enetc.c  | 35 ++-
> >  .../freescale/enetc/enetc_pf_common.c |  4 ++-
> >  .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
> >  3 files changed, 25 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c
> > b/drivers/net/ethernet/freescale/enetc/enetc.c
> > index 5b5e65ac8fab..8583ac9f7b9e 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc.c
> > @@ -2420,6 +2420,22 @@ static void enetc_set_lso_flags_mask(struct
> enetc_hw *hw)
> > enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
> >  }
> >
> > +static int enetc_set_rss(struct net_device *ndev, int en)
> 
> Can you please add a preliminary patch which converts this function's 
> prototype
> to:

Okay, I can add such a patch in this patch set.
> 
> static void enetc_set_rss(struct net_device *ndev, bool en) ?
> 
> After you do that please feel free to add my tag and keep it in future patch
> submissions:
> 
> Acked-by: Vladimir Oltean 
> 
> I don't see downsides to enabling RX hashing by default.



RE: [PATCH v4 net-next 06/14] net: enetc: add set/get_rss_table() to enetc_si_ops

2025-03-17 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:22PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> > index d7d9a720069b..072e5b40a199 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
> > @@ -165,6 +165,8 @@ static void enetc_vf_netdev_setup(struct enetc_si *si,
> struct net_device *ndev,
> >  static const struct enetc_si_ops enetc_vsi_ops = {
> > .setup_cbdr = enetc_setup_cbdr,
> > .teardown_cbdr = enetc_teardown_cbdr,
> > +   .get_rss_table = enetc_get_rss_table,
> > +   .set_rss_table = enetc_set_rss_table,
> >  };
> 
> Are the CBDR-based enetc_get_rss_table() and enetc_set_rss_table()
> the correct implementations for NETC v4 VSIs? (I guess not). Does
> the driver/hardware fail in a civilized way, or does it crash?

We have not added ENETC v4 VSI support yet, the current VSI driver
is only applicable to v1. I will add enetc4_vsi_ops when supporting
v4 VSI.




RE: [PATCH v4 net-next 10/14] net: enetc: move generic VLAN filter interfaces to enetc-core

2025-03-17 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:26PM +0800, Wei Fang wrote:
> > For ENETC, each SI has a corresponding VLAN hash table. That is to say,
> > both PF and VFs can support VLAN filter. However, currently only ENETC v1
> > PF driver supports VLAN filter. In order to make i.MX95 ENETC (v4) PF and
> > VF drivers also support VLAN filter, some related macros are moved from
> > enetc_pf.h to enetc.h, and the related structure variables are moved from
> > enetc_pf to enetc_si.
> >
> > Besides, enetc_vid_hash_idx() as a generic function is moved to enetc.c.
> > Extract enetc_refresh_vlan_ht_filter() from enetc_sync_vlan_ht_filter()
> > so that it can be shared by PF and VF drivers. This will make it easier
> > to add VLAN filter support for i.MX95 ENETC later.
> >
> > Signed-off-by: Wei Fang 
> > ---
> 
> In this and the next patch, can you please separate the code movement
> from the logical changes? It makes review much more difficult. With the
> similar observation that, as in the case of MAC filtering, VSIs don't
> yet support VLAN filtering, so the movement of the hash table structures
> from per-PF to per-SI is currently premature. So I expect to see that
> part removed from the next revision.

Okay, I will keep vlan_ht_filter in struct enetc_pf, and move common
interfaces to enetc_pf_common.c.




RE: [PATCH v4 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter

2025-03-17 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:21PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> > b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> > new file mode 100644
> > index ..3a660c80344a
> > --- /dev/null
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> > @@ -0,0 +1,93 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/* Copyright 2025 NXP */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "enetc_pf.h"
> > +#include "enetc4_debugfs.h"
> > +
> > +#define is_en(x)   (x) ? "Enabled" : "Disabled"
> 
> str_enabled_disabled()

Oh, good, I wondered if there was a general implementation in
the kernel, but I did not find one due to my limited knowledge.
Thanks!

> 
> > +
> > +static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
> > +{
> > +   struct enetc_si *si = s->private;
> > +   struct enetc_hw *hw = &si->hw;
> > +   u32 hash_h, hash_l;
> > +
> > +   hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
> > +   hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
> > +   seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
> > +  i, hash_h, hash_l);
> 
> Maybe the ":" separator between the high and low 32 bits is clearer than "x".

I want it to be presented as a full 64-bit entry. If it is in the format
of "%08x:%08x", it may be difficult to understand which is the high
32-bit and which is the low 32-bit.

> 
> > +
> > +   hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
> > +   hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
> > +   seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
> > +  i, hash_h, hash_l);
> > +}
> > +
> > +static int enetc_mac_filter_show(struct seq_file *s, void *data) {
> > +   struct maft_entry_data maft_data;
> > +   struct enetc_si *si = s->private;
> > +   struct enetc_hw *hw = &si->hw;
> > +   struct maft_keye_data *keye;
> > +   struct enetc_pf *pf;
> > +   int i, err, num_si;
> > +   u32 val;
> > +
> > +   pf = enetc_si_priv(si);
> > +   num_si = pf->caps.num_vsi + 1;
> > +
> > +   val = enetc_port_rd(hw, ENETC4_PSIPMMR);
> > +   for (i = 0; i < num_si; i++) {
> > +   seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n",
> > +  i, is_en(PSIPMMR_SI_MAC_UP(i) & val));
> > +   seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n",
> > +  i, is_en(PSIPMMR_SI_MAC_MP(i) & val));
> > +   }
> > +
> > +   /* MAC hash filter table */
> > +   for (i = 0; i < num_si; i++)
> > +   enetc_show_si_mac_hash_filter(s, i);
> > +
> > +   if (!pf->num_mfe)
> > +   return 0;
> > +
> > +   /* MAC address filter table */
> > +   seq_puts(s, "Show MAC address filter table\n");
> 
> The word "show" seems superfluous.

Okay, will remove it.

> 
> > +   for (i = 0; i < pf->num_mfe; i++) {
> > +   memset(&maft_data, 0, sizeof(maft_data));
> > +   err = ntmp_maft_query_entry(&si->ntmp.cbdrs, i, &maft_data);
> > +   if (err)
> > +   return err;
> > +
> > +   keye = &maft_data.keye;
> > +   seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
> > +  keye->mac_addr, 
> > le16_to_cpu(maft_data.cfge.si_bitmap));
> > +   }
> > +
> > +   return 0;
> > +}
> > +DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);



RE: [PATCH v4 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF

2025-03-17 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:24PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h
> b/drivers/net/ethernet/freescale/enetc/enetc.h
> > index a3ce324c716c..ecf79338cd79 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc.h
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc.h
> > @@ -543,6 +543,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8
> *bytes);
> >  int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
> >  int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
> >  int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
> > +int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
> > +int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
> >
> >  static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
> >  struct enetc_cbd *cbd,
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > index f991e1aae85c..53dbd5d71859 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > @@ -693,6 +693,14 @@ static void enetc4_pf_set_rx_mode(struct
> net_device *ndev)
> > queue_work(si->workqueue, &si->rx_mode_task);
> >  }
> >
> > +static int enetc4_pf_set_features(struct net_device *ndev,
> > + netdev_features_t features)
> > +{
> > +   enetc_set_features(ndev, features);
> > +
> > +   return 0;
> > +}
> > +
> >  static const struct net_device_ops enetc4_ndev_ops = {
> > .ndo_open   = enetc_open,
> > .ndo_stop   = enetc_close,
> > @@ -700,6 +708,7 @@ static const struct net_device_ops enetc4_ndev_ops
> = {
> > .ndo_get_stats  = enetc_get_stats,
> > .ndo_set_mac_address= enetc_pf_set_mac_addr,
> > .ndo_set_rx_mode= enetc4_pf_set_rx_mode,
> > +   .ndo_set_features   = enetc4_pf_set_features,
> >  };
> >
> >  static struct phylink_pcs *
> > @@ -1108,6 +1117,8 @@ static void enetc4_pf_netdev_destroy(struct
> enetc_si *si)
> >  static const struct enetc_si_ops enetc4_psi_ops = {
> > .setup_cbdr = enetc4_setup_cbdr,
> > .teardown_cbdr = enetc4_teardown_cbdr,
> > +   .get_rss_table = enetc4_get_rss_table,
> > +   .set_rss_table = enetc4_set_rss_table,
> >  };
> >
> >  static int enetc4_pf_wq_task_init(struct enetc_si *si)
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > index 4e5125331d7b..1a74b93f1fd3 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > @@ -299,3 +299,17 @@ int enetc_set_rss_table(struct enetc_si *si, const
> u32 *table, int count)
> > return enetc_cmd_rss_table(si, (u32 *)table, count, false);
> >  }
> >  EXPORT_SYMBOL_GPL(enetc_set_rss_table);
> > +
> > +int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
> > +{
> > +   return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
> > +  table, count, true);
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_get_rss_table);
> > +
> > +int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count)
> > +{
> > +   return ntmp_rsst_query_or_update_entry(&si->ntmp.cbdrs,
> > +  (u32 *)table, count, false);
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_set_rss_table);
> 
> I don't understand the logic for placing enetc4_get_rss_table() and
> enetc4_set_rss_table() in enetc_cbdr.c (built as part of fsl-enetc-core-y)?
> It's not core code, it's used only by NETC v4.

The ENETC v4 VF will reuse the driver of ENETC v1, and it also supports
RSS, so I think these functions are fine to be placed in enetc-core.

> 
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> > index 1a8fae3c406b..bc65135925b8 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
> > @@ -625,6 +625,24 @@ static int enetc_get_rxnfc(struct net_device *ndev,
> struct ethtool_rxnfc *rxnfc,
> > return 0;
> >  }
> >
> > +static int enetc4_get_rxnfc(struct net_device *ndev, struct ethtool_rxnfc
> *rxnfc,
> > + 

RE: [PATCH v4 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable

2025-03-17 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:23PM +0800, Wei Fang wrote:
> > Since the offset of the RSS key registers of i.MX95 ENETC is different
> > from that of LS1028A, so add enetc_get_rss_key_base() to get the base
> > offset for the different chips, so that enetc_set_rss_key() can be
> > reused for this trivial.
> 
> for this trivial... ? task?

Sorry, it should be trivial thing.
> 
> >
> > Signed-off-by: Wei Fang 
> > ---
> >  drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
> > .../net/ethernet/freescale/enetc/enetc4_pf.c  | 11 +--
> > .../ethernet/freescale/enetc/enetc_ethtool.c  | 19 ++-
> >  .../net/ethernet/freescale/enetc/enetc_pf.c   |  2 +-
> >  4 files changed, 17 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > index a98ed059a83f..f991e1aae85c 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> > @@ -583,22 +583,13 @@ static void enetc4_set_trx_frame_size(struct
> enetc_pf *pf)
> > enetc4_pf_reset_tc_msdu(&si->hw);
> >  }
> >
> > -static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
> > -{
> > -   int i;
> > -
> > -   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
> > -   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
> > -}
> > -
> >  static void enetc4_set_default_rss_key(struct enetc_pf *pf)  {
> > u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
> > -   struct enetc_hw *hw = &pf->si->hw;
> >
> > /* set up hash key */
> > get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
> > -   enetc4_set_rss_key(hw, hash_key);
> > +   enetc_set_rss_key(pf->si, hash_key);
> >  }
> 
> The entire enetc4_set_default_rss_key() seems reusable as
> enetc_set_default_rss_key(). enetc_configure_port() has the same logic.
> 

Yes, I can add enetc_set_default_rss_key() to enetc_pf_common.c

> >
> >  static void enetc4_enable_trx(struct enetc_pf *pf)



RE: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-03-17 Thread Wei Fang
> On Mon, Mar 17, 2025 at 11:55:26AM +0200, Wei Fang wrote:
> > Actually I did this is the original version, I mean in downstream kernel 6.6
> > tree. I add a "ntmp_mfe" in ntmp.h like below
> >
> > struct ntmp_mfe {
> > u8 mac[ETH_ALEN];
> > u16 si_bitmap;
> > };
> >
> > And the conversion was done by the NTMP driver. But then I found that this
> was
> > very troublesome. We get data from kernel "struct A,B,C", then the enetc
> driver
> > converts them to "struct D", and finally the ntmp driver converts it to 
> > "struct
> E".
> > So I thought why don't we convert "struct A,B,C" to "struct E" from the
> beginning?
> > After all, these data structures are only used by enetc and netc switch 
> > drivers,
> so
> > in kernel 6.12, I changed it to the current way.
> 
> I understand. With pack_fields(), "struct E" (the packed representation
> of "struct D") doesn't explicitly exist, just an abstract type
> representing the u8 *buffer, and the struct packed_field_u8 array[]
> which is hidden inside the NTMP layer.

Yes, "struct E" will not exist, but we need to pack every member in
"struct D" to convert them to the hardware structure, so there are
still two conversions ("struct A,B,C" -> "struct "D" --> hardware
structure).




RE: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-03-14 Thread Wei Fang



Best Regards,
Wei Fang

> -Original Message-
> From: Vladimir Oltean 
> On Fri, Mar 14, 2025 at 05:38:18AM +0200, Wei Fang wrote:
> > > > +   __le16 update_act;
> > > > +   u8 dbg_opt;
> > > > +   u8 tblv_qact;
> > > > +#define NTMP_QUERY_ACT GENMASK(3, 0)
> > > > +#define NTMP_TBL_VER   GENMASK(7, 0)
> > > > +#define NTMP_TBLV_QACT(v, a)   (FIELD_PREP(NTMP_TBL_VER, (v)) | \
> > > > +((a) & NTMP_QUERY_ACT))
> > >
> > > Can you please move #define macros out of structure definitions?
> >
> > No, I think these macros in the structure can better reflect the specific
> > meaning of these members. We can intuitively see what the bits of
> > these members represent, rather than finding the definition of these
> > bits in RM or elsewhere.
> 
> I mean, I was just suggesting to group the macros with the macros, and
> the struct fields with the struct fields. Mixing them together looks a
> bit messy to me. Even worse in the definition of "union netc_cbd" which
> IMO needs to be reconsidered a bit (a hint given below).

I think this is a matter of personal preference. I was inspired by some
of Intel's structure definitions. I think this method allows me to quickly
understand what fields the member consists of and what bits each field
occupies.

> 
> But you mention "intuitive" definitions without having to go to the RM.
> If I look just at the definitions, I see that NTMP_QUERY_ACT and
> NTMP_TBL_VER
> overlap, and that NTMP_TBLV_QACT() just ORs them together. How does that
> work?
> Shouldn't NTMP_TBL_VER() have been GENMASK(7, 4)? If I do open the RM

I must admit that it is my fault, so yes, NTMP_TBL_VER should be GENMASK(7, 4).
I will fix it, thanks for pointing this.

> and go to the "Generic NTMP Request Data Buffer Format" section, that
> table does seem to agree with me.
> 
> The "normal" way to give more meaning to struct fields is to define them
> as enum values. That doesn't work with "packed" field definitions as you
> have here, which I agree is a challenge. But it is one of the reasons
> why I tried to develop an API together with Jacob Keller which tries to
> address this, by allowing you to define the structures in an "unpacked"
> format, and have a separate data structure which informs the CPU how
> that structure maps over the buffer layout.
> 
> Below is an example to illustrate this for the case of NTMP request buffers.
> Note that the example is incomplete and doesn't even compile, because I
> haven't even converted all ntmp_fill_crd_eid() callers - I don't want to
> waste too much time doing that in case you disagree, but it's still
> enough to show what I'm talking about. Disclaimer: I didn't even _try_
> to compile it - it may contain bugs.
> 
> -- >8 --
> diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig
> b/drivers/net/ethernet/freescale/enetc/Kconfig
> index c8efbb6f2055..35d5cf21f6f4 100644
> --- a/drivers/net/ethernet/freescale/enetc/Kconfig
> +++ b/drivers/net/ethernet/freescale/enetc/Kconfig
> @@ -17,6 +17,7 @@ config NXP_ENETC_PF_COMMON
> 
>  config NXP_NETC_LIB
>   tristate
> + select PACKING
>   help
> This module provides common functionalities for both ENETC and NETC
> Switch, such as NETC Table Management Protocol (NTMP) 2.0,
> common tc
> diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c
> b/drivers/net/ethernet/freescale/enetc/ntmp.c
> index df10f2f310c1..f96cfca92a1c 100644
> --- a/drivers/net/ethernet/freescale/enetc/ntmp.c
> +++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
> @@ -180,7 +180,7 @@ static int netc_xmit_ntmp_cmd(struct netc_cbdrs
> *cbdrs, union netc_cbd *cbd)
>   return err;
>  }
> 
> -static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void
> **buf_align)
> +static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data,
> ntmp_common_req_msg_data_buf *buf_align)
>  {
>   void *buf;
> 
> @@ -221,18 +221,24 @@ static void ntmp_fill_request_headr(union netc_cbd
> *cbd, dma_addr_t dma,
>   cbd->req_hdr.npf = cpu_to_le32(NTMP_NPF);
>  }
> 
> -static void ntmp_fill_crd(struct common_req_data *crd,
> -   u8 tblv, u8 qa, u16 ua)
> +static const struct packed_field_u8 ntmp_common_req_fields[] = {
> + PACKED_FIELD(31, 28, struct ntmp_common_req_data, table_version),
> + PACKED_FIELD(27, 24, struct ntmp_common_req_data, query_actions),
> + PACKED_FIELD(15, 0, struct ntmp_common_req_data, update_actions),
> +};
> +
> +static void ntmp_

RE: [PATCH v4 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC

2025-03-14 Thread Wei Fang
> On Fri, Mar 14, 2025 at 06:51:06AM +0200, Wei Fang wrote:
> > > I don't understand the need for si->ops->setup_cbdr() and
> > > si->ops->teardown_cbdr()?
> > > Doesn't every call site know which kind of SI it is dealing with, and 
> > > thus it
> can
> > > appropriately call the direct symbol?
> > > - the v1 PSI and the VSI call enetc_setup_cbdr() and enetc_teardown_cbdr()
> > > - the v4 PSI calls enetc4_setup_cbdr() and enetc4_teardown_cbdr()
> >
> > Yes, for PSI we can use directly call these functions because they are 
> > different
> > drivers, but for VSI, v1 and v4 will use the same driver. I just want the 
> > PSI and
> > VSI to be consistent. If you don't like this, I can remove these interfaces 
> > from
> > the patch set, and add vf_setup_cbdr and vf_teardown_cbdr in the future
> when
> > I add the VF support for ENETC v4.
> 
> It's not that I don't like them, the point is rather simple: as far as
> this patch set is concerned, converting direct function calls to
> indirect ones is an unfinished idea. It needs to be evaluated in full
> context, which is not present here - as you say, v4 VSIs need to be
> further modified to call a different set of operations - but right now,
> they call a single set of CBDR functions. Changes which require
> subsequent patch sets in order to make any sense at all are discouraged.
> 
> Given the fact that the PSI code paths still don't benefit from an
> indirect function call in any way, I would in principle recommend to
> keep calling their CBDR methods directly. For VSIs I don't know which is
> preferable (if-else vs function pointer), I need to see that code first.

Okay, let's keep directly calls in v1 and v4 PSI drivers. Regarding to the
VSI, some people don't like if-else because they think we may have v5,
v6, v7 in the future which may use different version of command BD ring,
so they prefer function pointer. But for trivial, like different register 
offsets
for different ENETC versions. I think if-else is enough.




RE: [PATCH v4 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-03-13 Thread Wei Fang
> On Tue, Mar 11, 2025 at 01:38:17PM +0800, Wei Fang wrote:
> > +int ntmp_rsst_query_or_update_entry(struct netc_cbdrs *cbdrs, u32 *table,
> > +   int count, bool query)
> > +{
> > +   struct ntmp_dma_buf data = {.dev = cbdrs->dma_dev};
> > +   struct rsst_req_update *requ;
> > +   struct ntmp_req_by_eid *req;
> > +   union netc_cbd cbd;
> > +   int err, i;
> > +   u32 len;
> > +
> > +   if (count != RSST_ENTRY_NUM)
> > +   /* HW only takes in a full 64 entry table */
> > +   return -EINVAL;
> > +
> > +   if (query)
> > +   data.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +
> > +   RSST_CFGE_DATA_SIZE(count);
> > +   else
> > +   data.size = struct_size(requ, groups, count);
> > +
> > +   err = ntmp_alloc_data_mem(&data, (void **)&req);
> > +   if (err)
> > +   return err;
> > +
> > +   /* Set the request data buffer */
> > +   if (query) {
> > +   ntmp_fill_crd_eid(req, cbdrs->tbl.rsst_ver, 0, 0, 0);
> > +   len = NTMP_LEN(sizeof(*req), data.size);
> > +   ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
> > +   NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);
> 
> Please either use a commonly accepted abbreviation such as "hdr", or
> preferably,
> just spell "header" as such. This reminded me of Kevin Malone's quote
> "Why waste time say lot word when few word do trick?" :)
> 

Sure, I will fix it.

> > +   } else {
> > +   requ = (struct rsst_req_update *)req;
> > +   ntmp_fill_crd_eid(&requ->rbe, cbdrs->tbl.rsst_ver, 0,
> > + NTMP_GEN_UA_CFGEU | NTMP_GEN_UA_STSEU, 0);
> > +   for (i = 0; i < count; i++)
> > +   requ->groups[i] = (u8)(table[i]);
> > +
> > +   len = NTMP_LEN(data.size, 0);
> > +   ntmp_fill_request_headr(&cbd, data.dma, len, NTMP_RSST_ID,
> > +   NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);
> > +   }
> > +
> > +   err = netc_xmit_ntmp_cmd(cbdrs, &cbd);
> > +   if (err) {
> > +   dev_err(cbdrs->dma_dev, "%s RSS table entry failed (%d)",
> > +   query ? "Query" : "Update", err);
> > +   goto end;
> > +   }
> > +
> > +   if (query) {
> > +   u8 *group = (u8 *)req;
> > +
> > +   group += NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count);
> > +   for (i = 0; i < count; i++)
> > +   table[i] = group[i];
> > +   }
> > +
> > +end:
> > +   ntmp_free_data_mem(&data);
> > +
> > +   return err;
> > +}
> > +EXPORT_SYMBOL_GPL(ntmp_rsst_query_or_update_entry);
> 
> Instead of exporting "query_or_update" mixed semantics, can you please
> export two separate functions, one for "query" and the other for "update"?
> For query=false, you can make the "table" argument const.
> 
> Also, from the looks of their implementation, there isn't much that is
> common anyway.
> 

Okay, accept, I will split it into two functions.

> > +static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void
> **buf_align)
> > +{
> > +   void *buf;
> > +
> > +   buf = dma_alloc_coherent(data->dev, data->size +
> NTMP_DATA_ADDR_ALIGN,
> > +&data->dma, GFP_ATOMIC);
> 
> Is there any call site that can't use sleeping allocations (GFP_KERNEL)?
> 

The initial reason was that we called ntmp_maft_add_entry() directly when
implementing ndo_set_rx_mode(), so we changed it to GFP_ATOMIC. Later,
we implemented ndo_set_rx_mode() using workqueue, so for the current
patch, we can change it back to GFP_KERNEL.

> > +   if (!buf)
> > +   return -ENOMEM;
> > +
> > +   data->buf = buf;
> > +   *buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);
> > +
> > +   return 0;
> > +}
> > +
> > diff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> > new file mode 100644
> > index ..45e4d083ab0a
> > --- /dev/null
> > +++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h
> > @@ -0,0 +1,63 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
> > +/*
> > + * NTMP table request and response data buffer formats
> > + * Copyright 2025 NXP

[PATCH v5 net-next 00/14] Add more features for ENETC v4 - round 2

2025-04-11 Thread Wei Fang
This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.

---
v1 Link: https://lore.kernel.org/imx/20250103060610.2233908-1-wei.f...@nxp.com/
v2 Link: https://lore.kernel.org/imx/20250113082245.2332775-1-wei.f...@nxp.com/
v3 Link: https://lore.kernel.org/imx/20250304072201.1332603-1-wei.f...@nxp.com/
v4 Link: https://lore.kernel.org/imx/20250311053830.1516523-1-wei.f...@nxp.com/
---

Wei Fang (14):
  net: enetc: add initial netc-lib driver to support NTMP
  net: enetc: add command BD ring support for i.MX95 ENETC
  net: enetc: move generic MAC filtering interfaces to enetc-core
  net: enetc: add MAC filtering for i.MX95 ENETC PF
  net: enetc: add debugfs interface to dump MAC filter
  net: enetc: add set/get_rss_table() hooks to enetc_si_ops
  net: enetc: make enetc_set_rss_key() reusable
  net: enetc: add RSS support for i.MX95 ENETC PF
  net: enetc: change enetc_set_rss() to void type
  net: enetc: enable RSS feature by default
  net: enetc: extract enetc_refresh_vlan_ht_filter()
  net: enetc: move generic VLAN hash filter functions to
enetc_pf_common.c
  net: enetc: add VLAN filtering support for i.MX95 ENETC PF
  net: enetc: add loopback support for i.MX95 ENETC PF

 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   4 +
 drivers/net/ethernet/freescale/enetc/enetc.c  |  76 ++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  45 +-
 .../ethernet/freescale/enetc/enetc4_debugfs.c |  90 
 .../ethernet/freescale/enetc/enetc4_debugfs.h |  20 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  12 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 359 +-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c |  51 ++
 .../ethernet/freescale/enetc/enetc_ethtool.c  |  74 ++-
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 105 +
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  14 +-
 .../freescale/enetc/enetc_pf_common.c |  93 +++-
 .../freescale/enetc/enetc_pf_common.h |   3 +
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  10 +-
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 442 ++
 .../ethernet/freescale/enetc/ntmp_private.h   | 106 +
 include/linux/fsl/ntmp.h  | 126 +
 19 files changed, 1464 insertions(+), 175 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

-- 
2.34.1




[PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC

2025-04-11 Thread Wei Fang
The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).

Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. So add
enetc4_setup_cbdr() and enetc4_teardown_cbdr() for ENETC v4 drivers.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Remove setup_cbdr() and teardown_cbdr() hooks
2. Rename enetc4_init_ntmp_priv() to enetc4_init_ntmp_user()
3. Modify the commit message
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  9 -
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 39 ++-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 39 +++
 3 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..384e0bded87f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,7 +275,10 @@ struct enetc_si {
 
struct net_device *ndev; /* back ref. */
 
-   struct enetc_cbdr cbd_ring;
+   union {
+   struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+   struct ntmp_user ntmp_user; /* ENETC 4.1 and later */
+   };
 
int num_rx_rings; /* how many rings are available in the SI */
int num_tx_rings;
@@ -284,6 +288,7 @@ struct enetc_si {
u16 revision;
int hw_features;
const struct enetc_drvdata *drvdata;
+   const struct enetc_si_ops *ops;
 };
 
 #define ENETC_SI_ALIGN 32
@@ -493,6 +498,8 @@ void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv 
*priv);
 int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
 struct enetc_cbdr *cbdr);
 void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 73ac8c6afb3a..175eebadde76 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,21 @@ static void enetc4_configure_port(struct enetc_pf *pf)
enetc4_enable_trx(pf);
 }
 
+static int enetc4_init_ntmp_user(struct enetc_si *si)
+{
+   struct ntmp_user *user = &si->ntmp_user;
+
+   /* For ENETC 4.1, all table versions are 0 */
+   memset(&user->tbl, 0, sizeof(user->tbl));
+
+   return enetc4_setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_user(struct enetc_si *si)
+{
+   enetc4_teardown_cbdr(si);
+}
+
 static int enetc4_pf_init(struct enetc_pf *pf)
 {
struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +287,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
return err;
}
 
+   err = enetc4_init_ntmp_user(pf->si);
+   if (err) {
+   dev_err(dev, "Failed to init CBDR\n");
+   return err;
+   }
+
enetc4_configure_port(pf);
 
return 0;
 }
 
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+   enetc4_free_ntmp_user(pf->si);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -728,14 +754,25 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 
enetc_get_si_caps(si);
 
-   return enetc4_pf_netdev_create(si);
+   err = enetc4_pf_netdev_create(si);
+   if (err)
+   goto err_netdev_create;
+
+   return 0;
+
+err_netdev_create:
+   enetc4_pf_free(pf);
+
+   return err;
 }
 
 static void enetc4_pf_remove(struct pci_dev *pdev)
 {
struct enetc_si *si = pci_get_drvdata(pdev);
+   struct enetc_pf *pf = enetc_si_priv(si);
 
enetc4_pf_netdev_destroy(si);
+   enetc4_pf_free(pf);
 }
 
 static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c 
b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 20bfdf7fb4b4..ecb571e5ea50 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -60,6 +60,45 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
 }
 EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
 
+int enetc4_setup_cbdr(struct enetc_si *si)
+{
+   struct ntmp_user *user = &si->ntmp_user;
+   struct device *dev = &si->pdev->dev;
+   struct enetc_hw *hw = &si-&g

[PATCH v5 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core

2025-04-11 Thread Wei Fang
Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.

Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. This lays the basis for i.MX95 ENETC PF and VFs to
support MAC address filtering.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Keep mac_filter in struct enetc_pf
2. Modify the commit message
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 36 +++
 drivers/net/ethernet/freescale/enetc/enetc.h  | 15 
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 34 --
 .../net/ethernet/freescale/enetc/enetc_pf.h   | 11 --
 4 files changed, 51 insertions(+), 45 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 2106861463e4..3832d2cd91ba 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct 
enetc_ndev_priv *priv,
enetc_mm_commit_preemptible_tcs(priv);
 }
 
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+   u64 mask = 0;
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 8; i++)
+   mask |= BIT_ULL(i * 6);
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+   return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+   int idx = enetc_mac_addr_hash_idx(addr);
+
+   /* add hash table entry */
+   __set_bit(idx, filter->mac_hash_table);
+   filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+   filter->mac_addr_cnt = 0;
+
+   bitmap_zero(filter->mac_hash_table,
+   ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 384e0bded87f..c3ebb32ce50c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
 
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
+#define ENETC_MADDR_HASH_TBL_SZ64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+   union {
+   char mac_addr[ETH_ALEN];
+   DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+   };
+   int mac_addr_cnt;
+};
+
 struct enetc_tx_swbd {
union {
struct sk_buff *skb;
@@ -471,6 +483,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
 int enetc_configure_si(struct enetc_ndev_priv *priv);
 int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 203862ec1114..f76403f7aee8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, 
u16 vlan, u8 qos)
enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
 }
 
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
-   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
-   u64 mask = 0;
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 8; i++)
-   mask |= BIT_ULL(i * 6);
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
-   filter->mac_addr_cnt = 0;
-
-   bitmap_zero(filter->mac_hash_table,
-   ENETC_MADDR_HASH_TBL_SZ);
-}
-
 static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
 const unsigned char *addr)
 {
@@ -104,16 +80,6 @@ static void enetc_add_mac_addr_em_filte

[PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-04-11 Thread Wei Fang
Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.

For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.

It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Add the change of MAINTAINERS to this patch
2. Rename ntmp_fill_request_headr() to ntmp_fill_request_hdr()
3. Split ntmp_rsst_query_or_update_entry() into
ntmp_rsst_query_or_update_entry() and ntmp_rsst_query_entry()
4. Add "ntmp_" prefix to struct cmn_resp_query and cmn_req_data.
5. Remove struct common_resp_nq and netc_dev_type
6. Correct the definition of NTMP_TBL_VER
7. Remove struct netc_cbdrs and rename ntmp_priv to ntmp_user
8. Improve the error log
9. Remove NTMP_NULL_ENTRY_ID check from ntmp_delete_entry_by_id()
10. Remove netc_select_cbdr()
11. Move union netc_cbd from ntmp.h to ntmp_private.h
---
 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   3 +
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 442 ++
 .../ethernet/freescale/enetc/ntmp_private.h   | 106 +
 include/linux/fsl/ntmp.h  | 126 +
 6 files changed, 686 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 4c5c2e2c1278..2ae3fb3a0297 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9374,6 +9374,7 @@ F:
Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
 F: drivers/net/ethernet/freescale/enetc/
 F: include/linux/fsl/enetc_mdio.h
 F: include/linux/fsl/netc_global.h
+F: include/linux/fsl/ntmp.h
 
 FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 M: Claudiu Manoil 
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig 
b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..c8efbb6f2055 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,13 @@ config NXP_ENETC_PF_COMMON
 
  If compiled as module (M), the module name is nxp-enetc-pf-common.
 
+config NXP_NETC_LIB
+   tristate
+   help
+ This module provides common functionalities for both ENETC and NETC
+ Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+ flower and debugfs interfaces and so on.
+
 config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI_MSI
@@ -40,6 +47,7 @@ config NXP_ENETC4
select FSL_ENETC_CORE
select FSL_ENETC_MDIO
select NXP_ENETC_PF_COMMON
+   select NXP_NETC_LIB
select PHYLINK
select DIMLIB
help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
 obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
 nxp-enetc-pf-common-y := enetc_pf_common.o
 
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
 fsl-enetc-y := enetc_pf.o
 fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c 
b/drivers/net/ethernet/freescale/enetc/ntmp.c
new file mode 100644
index ..07cf88968d5e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NETC NTMP (NETC Table Management Protocol) 2.0 Library
+ * Copyright 2025 NXP
+ */
+
+#include 
+#include 
+#include 
+
+#include "ntmp_private.h"
+
+#define NETC_CBDR_TIMEOUT  1000 /* 

[PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF

2025-04-11 Thread Wei Fang
The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bit hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.

For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.

Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Refactor enetc4_pf_set_si_mac_promisc()
2. Split enetc4_pf_set_si_mac_hash_filter() into
enetc4_pf_set_si_uc_hash_filter() and enetc4_pf_set_si_mc_hash_filter()
3. Rename enetc4_pf_wq_task_init() to enetc4_psi_wq_task_init()
4. Rename enetc4_pf_do_set_rx_mode() to enetc4_psi_do_set_rx_mode()
5. Remove mac_list_lock and mac_list related functions
6. Add enetc4_pf_clear_maft_entries() and enetc4_pf_add_maft_entries()
7. Refactor enetc4_pf_set_mac_exact_filter() and rename it to
enetc4_pf_set_uc_exact_filter()
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |   3 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 251 +-
 .../net/ethernet/freescale/enetc/enetc_pf.h   |   3 +
 4 files changed, 264 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index c3ebb32ce50c..1573ff06fcf4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -301,6 +301,9 @@ struct enetc_si {
int hw_features;
const struct enetc_drvdata *drvdata;
const struct enetc_si_ops *ops;
+
+   struct workqueue_struct *workqueue;
+   struct work_struct rx_mode_task;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
 #define ENETC4_PSICFGR2(a) ((a) * 0x80 + 0x2018)
 #define  PSICFGR2_NUM_MSIX GENMASK(5, 0)
 
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a)((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a)((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 175eebadde76..4c2d944d6b05 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
 
 #define ENETC_SI_MAX_RING_NUM  8
 
+#define ENETC_MAC_FILTER_TYPE_UC   BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC   BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL  (ENETC_MAC_FILTER_TYPE_UC | \
+ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+   u8 addr[ETH_ALEN];
+};
+
 static void enetc4_get_port_caps(struct enetc_pf *pf)
 {
struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 
val = enetc_port_rd(hw, ENETC4_PMCAPR);
pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+   val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+   pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
 }
 
 static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -56,6 +68,180 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw 
*hw, int si,
put_unaligned_le16(lower, addr + 4);
 }
 
+static void enetc4_pf_set_si_mac_promisc(struct enetc_hw *hw, int si,
+bool uc_promisc, bool mc_promisc)
+{
+   u32 val = enetc_port_rd(hw, ENETC

[PATCH v5 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter

2025-04-11 Thread Wei Fang
ENETC's MAC filter consists of hash MAC filter and exact MAC filter.
Hash MAC filter is a 64-bit entry hash table consisting of two 32-bit
registers. Exact MAC filter is implemented by configuring MAC address
filter table through command BD ring. The table is stored in ENETC's
internal memory and needs to be read through command BD ring. In order
to facilitate debugging, added a debugfs interface to get the relevant
information about MAC filter.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Replace is_en() with str_enabled_disabled()
2. Remove superfluous "Show" in the debug log
3. Remove keye variable from enetc_mac_filter_show()
---
 drivers/net/ethernet/freescale/enetc/Makefile |  1 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 +
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 90 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h | 20 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  4 +
 5 files changed, 116 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h

diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
 nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 1573ff06fcf4..b53ecc882a90 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -304,6 +304,7 @@ struct enetc_si {
 
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
+   struct dentry *debugfs_root;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index ..3479c0abe9e6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   u32 hash_h, hash_l;
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+   seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+   seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   struct maft_entry_data maft;
+   struct enetc_pf *pf;
+   int i, err, num_si;
+   u32 val;
+
+   pf = enetc_si_priv(si);
+   num_si = pf->caps.num_vsi + 1;
+
+   val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+   for (i = 0; i < num_si; i++) {
+   seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n", i,
+  str_enabled_disabled(PSIPMMR_SI_MAC_UP(i) & val));
+   seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n", i,
+  str_enabled_disabled(PSIPMMR_SI_MAC_MP(i) & val));
+   }
+
+   /* MAC hash filter table */
+   for (i = 0; i < num_si; i++)
+   enetc_show_si_mac_hash_filter(s, i);
+
+   if (!pf->num_mfe)
+   return 0;
+
+   /* MAC address filter table */
+   seq_puts(s, "MAC address filter table\n");
+   for (i = 0; i < pf->num_mfe; i++) {
+   memset(&maft, 0, sizeof(maft));
+   err = ntmp_maft_query_entry(&si->ntmp_user, i, &maft);
+   if (err)
+   return err;
+
+   seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+  maft.keye.mac_addr, 
le16_to_cpu(maft.cfge.si_bitmap));
+   }
+
+   return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
+
+void enetc_create_debugfs(struct enetc_si *si)
+{
+   struct net_device *ndev = si->ndev;
+   struct dentry *root;
+
+   root = debugfs_create_dir(netdev_name(ndev), NULL);
+   if (IS_ER

[PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops

2025-04-11 Thread Wei Fang
Since i.MX95 ENETC (v4) uses NTMP 2.0 to manage the RSS table, which is
different from LS1028A ENETC (v1). In order to reuse some functions
related to the RSS table, so add .get_rss_table() and .set_rss_table()
hooks to enetc_si_ops.

Signed-off-by: Wei Fang 
---
v5 changes:
Add enetc_set_default_rss_key() to enetc_pf_common.c and use it in both
enetc v1 and v4 drivers
---
 drivers/net/ethernet/freescale/enetc/enetc.c|  2 +-
 drivers/net/ethernet/freescale/enetc/enetc.h| 13 +
 .../net/ethernet/freescale/enetc/enetc_ethtool.c| 12 ++--
 drivers/net/ethernet/freescale/enetc/enetc_pf.c |  6 ++
 drivers/net/ethernet/freescale/enetc/enetc_vf.c |  6 ++
 5 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 3832d2cd91ba..2a8fa455e96b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2405,7 +2405,7 @@ static int enetc_setup_default_rss_table(struct enetc_si 
*si, int num_groups)
for (i = 0; i < si->num_rss; i++)
rss_table[i] = i % num_groups;
 
-   enetc_set_rss_table(si, rss_table, si->num_rss);
+   si->ops->set_rss_table(si, rss_table, si->num_rss);
 
kfree(rss_table);
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index b53ecc882a90..786042029b1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -279,6 +279,19 @@ struct enetc_platform_info {
const struct enetc_drvdata *data;
 };
 
+struct enetc_si;
+
+/*
+ * This structure defines the some common hooks for ENETC PSI and VSI.
+ * In addition, since VSI only uses the struct enetc_si as its private
+ * driver data, so this structure also define some hooks specifically
+ * for VSI. For VSI-specific hooks, the format is ???vf_*()???.
+ */
+struct enetc_si_ops {
+   int (*get_rss_table)(struct enetc_si *si, u32 *table, int count);
+   int (*set_rss_table)(struct enetc_si *si, const u32 *table, int count);
+};
+
 /* PCI IEP device data */
 struct enetc_si {
struct pci_dev *pdev;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 
b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index ece3ae28ba82..d14182401d81 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -681,7 +681,8 @@ static int enetc_get_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int err = 0, i;
 
/* return hash function */
@@ -695,8 +696,7 @@ static int enetc_get_rxfh(struct net_device *ndev,
 
/* return RSS table */
if (rxfh->indir)
-   err = enetc_get_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = si->ops->get_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
@@ -715,7 +715,8 @@ static int enetc_set_rxfh(struct net_device *ndev,
  struct netlink_ext_ack *extack)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int err = 0;
 
/* set hash key, if PF */
@@ -724,8 +725,7 @@ static int enetc_set_rxfh(struct net_device *ndev,
 
/* set RSS table */
if (rxfh->indir)
-   err = enetc_set_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = si->ops->set_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index f76403f7aee8..8dabb80ec04c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -905,6 +905,11 @@ static int enetc_pf_register_with_ierb(struct pci_dev 
*pdev)
return enetc_ierb_register_pf(ierb_pdev, pdev);
 }
 
+static const struct enetc_si_ops enetc_psi_ops = {
+   .get_rss_table = enetc_get_rss_table,
+   .set_rss_table = enetc_set_rss_table,
+};
+
 static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 {
struct enetc_si *si;
@@ -924,6 +929,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev 
*pdev)
}
 
si->revision = enetc_get_ip_revision(&si->hw);
+   si->ops = &enetc_psi_ops;
err = enetc_get_dr

[PATCH v5 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable

2025-04-11 Thread Wei Fang
Since the offset of the RSS key registers of i.MX95 ENETC is different
from that of LS1028A, so add enetc_get_rss_key_base() to get the base
offset for the different chips, so that enetc_set_rss_key() can be
reused for this trivial thing.

Signed-off-by: Wei Fang 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 20 +--
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 19 +-
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  4 +---
 .../freescale/enetc/enetc_pf_common.c | 10 ++
 .../freescale/enetc/enetc_pf_common.h |  1 +
 6 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 786042029b1e..e49c1626e7e5 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -537,7 +537,7 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
 int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
   int index);
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index bbe16c140875..b72a365625d2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -413,24 +413,6 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
enetc4_pf_reset_tc_msdu(&si->hw);
 }
 
-static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-   int i;
-
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
-}
-
-static void enetc4_set_default_rss_key(struct enetc_pf *pf)
-{
-   u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
-   struct enetc_hw *hw = &pf->si->hw;
-
-   /* set up hash key */
-   get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
-   enetc4_set_rss_key(hw, hash_key);
-}
-
 static void enetc4_enable_trx(struct enetc_pf *pf)
 {
struct enetc_hw *hw = &pf->si->hw;
@@ -443,7 +425,7 @@ static void enetc4_configure_port(struct enetc_pf *pf)
 {
enetc4_configure_port_si(pf);
enetc4_set_trx_frame_size(pf);
-   enetc4_set_default_rss_key(pf);
+   enetc_set_default_rss_key(pf);
enetc4_enable_trx(pf);
 }
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 
b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index d14182401d81..1a8fae3c406b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -677,6 +677,14 @@ static u32 enetc_get_rxfh_indir_size(struct net_device 
*ndev)
return priv->si->num_rss;
 }
 
+static int enetc_get_rss_key_base(struct enetc_si *si)
+{
+   if (is_enetc_rev1(si))
+   return ENETC_PRSSK(0);
+
+   return ENETC4_PRSSKR(0);
+}
+
 static int enetc_get_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh)
 {
@@ -701,12 +709,14 @@ static int enetc_get_rxfh(struct net_device *ndev,
return err;
 }
 
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes)
 {
+   int base = enetc_get_rss_key_base(si);
+   struct enetc_hw *hw = &si->hw;
int i;
 
for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
+   enetc_port_wr(hw, base + i * 4, ((u32 *)bytes)[i]);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_key);
 
@@ -716,12 +726,11 @@ static int enetc_set_rxfh(struct net_device *ndev,
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_si *si = priv->si;
-   struct enetc_hw *hw = &si->hw;
int err = 0;
 
/* set hash key, if PF */
-   if (rxfh->key && hw->port)
-   enetc_set_rss_key(hw, rxfh->key);
+   if (rxfh->key && enetc_si_is_pf(si))
+   enetc_set_rss_key(si, rxfh->key);
 
/* set RSS table */
if (rxfh->indir)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8dabb80ec04c..8f2616fd83d2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -515,7 +515,6 @@ static void enetc_mac_enable(struct enetc_si *si

[PATCH v5 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF

2025-04-11 Thread Wei Fang
Compared with LS1028A, there are two main differences: first, i.MX95
ENETC uses NTMP 2.0 to manage the RSS table, and second, the offset
of the RSS Key registers is different. Some modifications have been
made in the previous patches based on these differences to ensure that
the relevant interfaces are compatible with i.MX95. So it's time to
add RSS support to i.MX95 ENETC PF.

Signed-off-by: Wei Fang 
---
1. Add comments for enetc4_get_rxnfc()
2. Modify enetc4_set_rss_table() and enetc4_get_rss_table()
---
 drivers/net/ethernet/freescale/enetc/enetc.c  |  5 +-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 15 ++
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 12 +
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 47 ---
 .../freescale/enetc/enetc_pf_common.c |  6 +--
 6 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 2a8fa455e96b..5b5e65ac8fab 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2436,10 +2436,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
if (si->hw_features & ENETC_SI_F_LSO)
enetc_set_lso_flags_mask(hw);
 
-   /* TODO: RSS support for i.MX95 will be supported later, and the
-* is_enetc_rev1() condition will be removed
-*/
-   if (si->num_rss && is_enetc_rev1(si)) {
+   if (si->num_rss) {
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index e49c1626e7e5..7b24f1a5969a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -541,6 +541,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8 
*bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 
 static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
 struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index b72a365625d2..e164e1a3f44b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -514,6 +514,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static int enetc4_pf_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+   enetc_set_features(ndev, features);
+
+   return 0;
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -521,6 +529,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_get_stats  = enetc_get_stats,
.ndo_set_mac_address= enetc_pf_set_mac_addr,
.ndo_set_rx_mode= enetc4_pf_set_rx_mode,
+   .ndo_set_features   = enetc4_pf_set_features,
 };
 
 static struct phylink_pcs *
@@ -926,6 +935,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
free_netdev(ndev);
 }
 
+static const struct enetc_si_ops enetc4_psi_ops = {
+   .get_rss_table = enetc4_get_rss_table,
+   .set_rss_table = enetc4_set_rss_table,
+};
+
 static int enetc4_psi_wq_task_init(struct enetc_si *si)
 {
char wq_name[24];
@@ -963,6 +977,7 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 "Couldn't map PF only space\n");
 
si->revision = enetc_get_ip_revision(&si->hw);
+   si->ops = &enetc4_psi_ops;
err = enetc_get_driver_data(si);
if (err)
return dev_err_probe(dev, err,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c 
b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index ecb571e5ea50..fcfff908f7c1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -295,3 +295,15 @@ int enetc_set_rss_table(struct enetc_si *si, const u32 
*table, int count)
return enetc_cmd_rss_table(si, (u32 *)table, count, false);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_table);
+
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
+{
+   return ntmp_rsst_query_entry(&si->ntmp_user, table, count);
+}
+EXPORT_SYM

[PATCH v5 net-next 10/14] net: enetc: enable RSS feature by default

2025-04-11 Thread Wei Fang
Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.

Signed-off-by: Wei Fang 
---
v5 changes:
Just rebase it based on patch 9.
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 31 ++-
 .../freescale/enetc/enetc_pf_common.c |  4 ++-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
 3 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index a389d5089734..d686baeb1aa8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2420,6 +2420,20 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
 }
 
+static void enetc_set_rss(struct net_device *ndev, int en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+   u32 reg;
+
+   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+   reg = enetc_rd(hw, ENETC_SIMR);
+   reg &= ~ENETC_SIMR_RSSE;
+   reg |= (en) ? ENETC_SIMR_RSSE : 0;
+   enetc_wr(hw, ENETC_SIMR, reg);
+}
+
 int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
struct enetc_si *si = priv->si;
@@ -2440,6 +2454,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
+
+   if (priv->ndev->features & NETIF_F_RXHASH)
+   enetc_set_rss(priv->ndev, true);
}
 
return 0;
@@ -3232,20 +3249,6 @@ struct net_device_stats *enetc_get_stats(struct 
net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static void enetc_set_rss(struct net_device *ndev, int en)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
-   u32 reg;
-
-   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
-   reg = enetc_rd(hw, ENETC_SIMR);
-   reg &= ~ENETC_SIMR_RSSE;
-   reg |= (en) ? ENETC_SIMR_RSSE : 0;
-   enetc_wr(hw, ENETC_SIMR, reg);
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a302477c4de4..a751862a70b1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
if (si->hw_features & ENETC_SI_F_LSO)
priv->active_offloads |= ENETC_F_LSO;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 4fafe4e18a37..f6aed0a1ad1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, 
struct net_device *ndev,
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
  NETIF_F_TSO | NETIF_F_TSO6;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* pick up primary MAC address from SI */
enetc_load_primary_mac_addr(&si->hw, ndev);
-- 
2.34.1




[PATCH v5 net-next 11/14] net: enetc: extract enetc_refresh_vlan_ht_filter()

2025-04-11 Thread Wei Fang
Extract the common function enetc_refresh_vlan_ht_filter() from
enetc_sync_vlan_ht_filter() so that it can be reused by the ENETC
v4 PF and VF drivers in the future.

Signed-off-by: Wei Fang 
---
v5 changes
New patch
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 20 ---
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8f2616fd83d2..ae2dbd159ab4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -234,21 +234,16 @@ static int enetc_vid_hash_idx(unsigned int vid)
return res;
 }
 
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
 {
int i;
 
-   if (rehash) {
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
 
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
+   __set_bit(hidx, pf->vlan_ht_filter);
}
-
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 }
 
 static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
@@ -261,7 +256,7 @@ static int enetc_vlan_rx_add_vid(struct net_device *ndev, 
__be16 prot, u16 vid)
 
idx = enetc_vid_hash_idx(vid);
if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_sync_vlan_ht_filter(pf, false);
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 
return 0;
 }
@@ -272,7 +267,8 @@ static int enetc_vlan_rx_del_vid(struct net_device *ndev, 
__be16 prot, u16 vid)
struct enetc_pf *pf = enetc_si_priv(priv->si);
 
__clear_bit(vid, pf->active_vlans);
-   enetc_sync_vlan_ht_filter(pf, true);
+   enetc_refresh_vlan_ht_filter(pf);
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 
return 0;
 }
-- 
2.34.1




[PATCH v5 net-next 09/14] net: enetc: change enetc_set_rss() to void type

2025-04-11 Thread Wei Fang
Actually enetc_set_rss() does not need a return value, so change its
type to void.

Signed-off-by: Wei Fang 
Acked-by: Vladimir Oltean 
---
v5 changes:
New patch, suggested by Vladimir
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 5b5e65ac8fab..a389d5089734 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -3232,7 +3232,7 @@ struct net_device_stats *enetc_get_stats(struct 
net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static int enetc_set_rss(struct net_device *ndev, int en)
+static void enetc_set_rss(struct net_device *ndev, int en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
@@ -3244,8 +3244,6 @@ static int enetc_set_rss(struct net_device *ndev, int en)
reg &= ~ENETC_SIMR_RSSE;
reg |= (en) ? ENETC_SIMR_RSSE : 0;
enetc_wr(hw, ENETC_SIMR, reg);
-
-   return 0;
 }
 
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
-- 
2.34.1




[PATCH v5 net-next 12/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c

2025-04-11 Thread Wei Fang
The VLAN hash filters of ENETC v1 and v4 are basically the same, the only
difference is that the offset of the VLAN hash filter registers has been
changed in ENETC v4. So some functions like enetc_vlan_rx_add_vid() and
enetc_vlan_rx_del_vid() only need to be slightly modified to be reused
by ENETC v4. Currently, we just move these functions from enetc_pf.c to
enetc_pf_common.c. Appropriate modifications will be made for ENETC4 in
a subsequent patch.

Signed-off-by: Wei Fang 
---
v5 changes
Remove set_si_vlan_hash_filter() hook
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 57 --
 .../freescale/enetc/enetc_pf_common.c | 60 +++
 .../freescale/enetc/enetc_pf_common.h |  2 +
 3 files changed, 62 insertions(+), 57 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index ae2dbd159ab4..6560bdbff287 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -216,63 +216,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-unsigned long hash)
-{
-   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
-   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
-}
-
-static int enetc_vid_hash_idx(unsigned int vid)
-{
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
-{
-   int i;
-
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
-}
-
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
-   int idx;
-
-   __set_bit(vid, pf->active_vlans);
-
-   idx = enetc_vid_hash_idx(vid);
-   if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
-   return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
-
-   __clear_bit(vid, pf->active_vlans);
-   enetc_refresh_vlan_ht_filter(pf);
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
-   return 0;
-}
-
 static void enetc_set_loopback(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a751862a70b1..ed8afd174c9e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -353,5 +353,65 @@ void enetc_set_default_rss_key(struct enetc_pf *pf)
 }
 EXPORT_SYMBOL_GPL(enetc_set_default_rss_key);
 
+static int enetc_vid_hash_idx(unsigned int vid)
+{
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+   return res;
+}
+
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
+{
+   int i;
+
+   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
+
+   __set_bit(hidx, pf->vlan_ht_filter);
+   }
+}
+
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
+unsigned long hash)
+{
+   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
+   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
+}
+
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   int idx;
+
+   __set_bit(vid, pf->active_vlans);
+
+   idx = enetc_vid_hash_idx(vid);
+   if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(nde

[PATCH v5 net-next 14/14] net: enetc: add loopback support for i.MX95 ENETC PF

2025-04-11 Thread Wei Fang
Add internal loopback support for i.MX95 ENETC PF, the default loopback
mode is MAC level loopback, the MAC Tx data is looped back onto the Rx.
The MAC interface runs at a fixed 1:8 ratio of NETC clock in MAC-level
loopback mode, with no dependency on Tx clock.

Signed-off-by: Wei Fang 
---
v5: no changes
---
 .../net/ethernet/freescale/enetc/enetc4_pf.c   | 18 ++
 .../ethernet/freescale/enetc/enetc_pf_common.c |  4 +---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 421378212a73..711047f7074b 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -101,6 +101,21 @@ static void enetc4_pf_set_si_mc_hash_filter(struct 
enetc_hw *hw, int si,
enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
 }
 
+static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_si *si = priv->si;
+   u32 val;
+
+   val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+   val = u32_replace_bits(val, en ? 1 : 0, PM_CMD_CFG_LOOP_EN);
+   /* Default to select MAC level loopback mode if loopback is enabled. */
+   val = u32_replace_bits(val, en ? LPBCK_MODE_MAC_LEVEL : 0,
+  PM_CMD_CFG_LPBK_MODE);
+
+   enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
 static void enetc4_pf_clear_maft_entries(struct enetc_pf *pf)
 {
int i;
@@ -527,6 +542,9 @@ static int enetc4_pf_set_features(struct net_device *ndev,
enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
}
 
+   if (changed & NETIF_F_LOOPBACK)
+   enetc4_pf_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
enetc_set_features(ndev, features);
 
return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 8c563e552021..edf14a95cab7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -134,10 +134,8 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
}
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
-   if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~NETIF_F_LOOPBACK;
+   if (!is_enetc_rev1(si))
goto end;
-   }
 
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-- 
2.34.1




[PATCH v5 net-next 13/14] net: enetc: add VLAN filtering support for i.MX95 ENETC PF

2025-04-11 Thread Wei Fang
Since the offsets of the VLAN hash filter registers of ENETC v4 are
different from ENETC v1. Therefore, enetc_set_si_vlan_ht_filter() is
added to set the correct VLAN hash filter based on the SI ID and ENETC
revision, so that ENETC v4 PF driver can reuse enetc_vlan_rx_add_vid()
and enetc_vlan_rx_del_vid(). In addition, the VLAN promiscuous mode will
be enabled if VLAN filtering is disabled, which means that PF qualifies
for reception of all VLAN tags.

Signed-off-by: Wei Fang 
---
v5 changes
1. Remove set_si_vlan_hash_filter() hook
2. Refator enetc_set_vlan_ht_filter() and rename it to
enetc_set_si_vlan_ht_filter()
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  4 +++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 12 +
 .../freescale/enetc/enetc_pf_common.c | 25 +--
 3 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 826359004850..aa25b445d301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -107,6 +107,10 @@
 #define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
 #define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
 
+/* Port station interface a VLAN hash filter register 0/1 */
+#define ENETC4_PSIVHFR0(a) ((a) * 0x80 + 0x2060)
+#define ENETC4_PSIVHFR1(a) ((a) * 0x80 + 0x2064)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index e164e1a3f44b..421378212a73 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -517,6 +517,16 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 static int enetc4_pf_set_features(struct net_device *ndev,
  netdev_features_t features)
 {
+   netdev_features_t changed = ndev->features ^ features;
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+
+   if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+   bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+
+   enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+   }
+
enetc_set_features(ndev, features);
 
return 0;
@@ -530,6 +540,8 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_set_mac_address= enetc_pf_set_mac_addr,
.ndo_set_rx_mode= enetc4_pf_set_rx_mode,
.ndo_set_features   = enetc4_pf_set_features,
+   .ndo_vlan_rx_add_vid= enetc_vlan_rx_add_vid,
+   .ndo_vlan_rx_kill_vid   = enetc_vlan_rx_del_vid,
 };
 
 static struct phylink_pcs *
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index ed8afd174c9e..8c563e552021 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -135,7 +135,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | 
NETIF_F_LOOPBACK);
+   ndev->hw_features &= ~NETIF_F_LOOPBACK;
goto end;
}
 
@@ -376,11 +376,22 @@ static void enetc_refresh_vlan_ht_filter(struct enetc_pf 
*pf)
}
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-unsigned long hash)
+static void enetc_set_si_vlan_ht_filter(struct enetc_si *si,
+   int si_id, u64 hash)
 {
-   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
-   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
+   struct enetc_hw *hw = &si->hw;
+   int high_reg_off, low_reg_off;
+
+   if (is_enetc_rev1(si)) {
+   low_reg_off = ENETC_PSIVHFR0(si_id);
+   high_reg_off = ENETC_PSIVHFR1(si_id);
+   } else {
+   low_reg_off = ENETC4_PSIVHFR0(si_id);
+   high_reg_off = ENETC4_PSIVHFR1(si_id);
+   }
+
+   enetc_port_wr(hw, low_reg_off, lower_32_bits(hash));
+   enetc_port_wr(hw, high_reg_off, upper_32_bits(hash));
 }
 
 int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
@@ -393,7 +404,7 @@ int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 
prot, u16 vid)
 
idx = enetc_vid_hash_idx(vid);
if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filt

RE: [PATCH v5 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC

2025-04-18 Thread Wei Fang
> -Original Message-
> From: Vladimir Oltean 
> Sent: 2025年4月18日 21:25
> To: Wei Fang 
> Cc: Claudiu Manoil ; Vladimir Oltean
> ; Clark Wang ;
> andrew+net...@lunn.ch; da...@davemloft.net; eduma...@google.com;
> k...@kernel.org; pab...@redhat.com; christophe.le...@csgroup.eu;
> net...@vger.kernel.org; linux-ker...@vger.kernel.org; i...@lists.linux.dev;
> linuxppc-dev@lists.ozlabs.org; linux-arm-ker...@lists.infradead.org
> Subject: Re: [PATCH v5 net-next 02/14] net: enetc: add command BD ring
> support for i.MX95 ENETC
> 
> On Fri, Apr 11, 2025 at 05:57:40PM +0800, Wei Fang wrote:
> > diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > index 20bfdf7fb4b4..ecb571e5ea50 100644
> > --- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > +++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
> > @@ -60,6 +60,45 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
> >  }
> >  EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
> >
> > +int enetc4_setup_cbdr(struct enetc_si *si)
> > +{
> > +   struct ntmp_user *user = &si->ntmp_user;
> > +   struct device *dev = &si->pdev->dev;
> > +   struct enetc_hw *hw = &si->hw;
> > +   struct netc_cbdr_regs regs;
> > +
> > +   user->cbdr_num = 1;
> > +   user->cbdr_size = NETC_CBDR_BD_NUM;
> > +   user->dev = dev;
> > +   user->ring = devm_kcalloc(dev, user->cbdr_num,
> > + sizeof(struct netc_cbdr), GFP_KERNEL);
> > +   if (!user->ring)
> > +   return -ENOMEM;
> > +
> > +   /* set CBDR cache attributes */
> > +   enetc_wr(hw, ENETC_SICAR2,
> > +ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
> > +
> > +   regs.pir = hw->reg + ENETC_SICBDRPIR;
> > +   regs.cir = hw->reg + ENETC_SICBDRCIR;
> > +   regs.mr = hw->reg + ENETC_SICBDRMR;
> > +   regs.bar0 = hw->reg + ENETC_SICBDRBAR0;
> > +   regs.bar1 = hw->reg + ENETC_SICBDRBAR1;
> > +   regs.lenr = hw->reg + ENETC_SICBDRLENR;
> > +
> > +   return netc_setup_cbdr(dev, user->cbdr_size, ®s, user->ring);
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_setup_cbdr);
> > +
> > +void enetc4_teardown_cbdr(struct enetc_si *si)
> > +{
> > +   struct ntmp_user *user = &si->ntmp_user;
> > +
> > +   netc_teardown_cbdr(user->dev, user->ring);
> > +   user->dev = NULL;
> > +}
> > +EXPORT_SYMBOL_GPL(enetc4_teardown_cbdr);
> 
> I wanted to ask why isn't netc_setup_cbdr() merged into enetc4_setup_cbdr()
> (and likewise for teardown_cbdr), because they sound very similar, and
> they operate on the same data - one is literally a continuation of the
> other. Then I looked downstream where the netc_switch is another API
> user of netc_setup_cbdr() and netc_teardown_cbdr().
> 
> Do you think you could rename netc_setup_cbdr() into something like below:

Sure, I will rename them.

> 
> struct ntmp_user *ntmp_user_create(struct device *dev, size_t num_cbdr,
>  const struct netc_cbdr_regs *regs);
> void ntmp_user_destroy(struct ntmp_user *user);
> 
> From a data encapsulation perspective, it would be great if the outside
> world only worked with an opaque struct ntmp_user * pointer.
> 
> Hide NETC_CBDR_BD_NUM from include/linux/fsl/ntmp.h if API users don't
> need to customize it, and let ntmp_user_create() set it.
> 

Do we need to retain cbdr_size in struct ntmp_user? Or just remove it in
next version?



RE: [PATCH v5 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-04-18 Thread Wei Fang
> I see this is "Changes requested", so here are some more nitpicks from me.
> 
> On Fri, Apr 11, 2025 at 05:57:39PM +0800, Wei Fang wrote:
> > Some NETC functionality is controlled using control messages sent to the
> > hardware using BD ring interface with 32B descriptor similar to transmit
> > BD ring used on ENETC. This BD ring interface is referred to as command
> > BD ring. It is used to configure functionality where the underlying
> > resources may be shared between different entities or being too large to
> > configure using direct registers. Therefore, a messaging protocol called
> > NETC Table Management Protocol (NTMP) is provided for exchanging
> > configuration and management information between the software and the
> > hardware using the command BD ring interface.
> >
> > For i.MX95, NTMP has been upgraded to version 2.0, which is incompatible
> > with LS1028A, because the message formats have been changed.
> 
> Can you please add one more sentence clarifying that the LS1028A
> management protocol has been retroactively named NTMP 1.0 and its
> implementation is in enetc_cbdr.c and enetc_tsn.c? The driver, like new
> NETC documentation, refers to NTMP 2.0 as simply "NTMP".
> 

Okay, but enetc_tsn.c is only existed in downstream, so it will not be
added here.




RE: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF

2025-04-20 Thread Wei Fang
> On Fri, Apr 11, 2025 at 05:57:42PM +0800, Wei Fang wrote:
> >  static const struct enetc_pf_ops enetc4_pf_ops = {
> > .set_si_primary_mac = enetc4_pf_set_si_primary_mac,
> > .get_si_primary_mac = enetc4_pf_get_si_primary_mac,
> > @@ -303,12 +489,55 @@ static void enetc4_pf_free(struct enetc_pf *pf)
> > enetc4_free_ntmp_user(pf->si);
> >  }
> >
> > +static void enetc4_psi_do_set_rx_mode(struct work_struct *work)
> > +{
> > +   struct enetc_si *si = container_of(work, struct enetc_si, rx_mode_task);
> > +   struct enetc_pf *pf = enetc_si_priv(si);
> > +   struct net_device *ndev = si->ndev;
> > +   struct enetc_hw *hw = &si->hw;
> > +   bool uc_promisc = false;
> > +   bool mc_promisc = false;
> > +   int type = 0;
> > +
> > +   if (ndev->flags & IFF_PROMISC) {
> > +   uc_promisc = true;
> > +   mc_promisc = true;
> > +   } else if (ndev->flags & IFF_ALLMULTI) {
> 
> enetc4_psi_do_set_rx_mode() runs unlocked relative to changes made
> to ndev->flags, so could you at least read it just once to avoid
> inconsistencies?
> 
> Speaking of running unlocked: if I'm not mistaken, this code design
> might lose consecutive updates to ndev->flags, as well as to the address
> lists, if queue_work() is executed while si->rx_mode_task is still
> running. There is a difference between statically allocating and
> continuously queuing the same work item, vs allocating one work item
> per each ndo_set_rx_mode() call.
> 
> In practice it might be hard to trigger an actual issue, because the
> call sites serialize under rtnl_lock() which is so bulky that
> si->rx_mode_task should have time to finish by the time ndo_set_rx_mode()
> has a chance to be called again.
> 
> I can't tell you exactly how, but my gut feeling is that the combination
> of these 2 things is going to be problematic.

I think we can add rtnl_lock() to enetc4_psi_do_set_rx_mode() to keep
consistency, as shown below.

--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -497,6 +497,8 @@ static void enetc4_psi_do_set_rx_mode(struct work_struct 
*work)
bool mc_promisc = false;
int type = 0;

+   rtnl_lock();
+
if (ndev->flags & IFF_PROMISC) {
uc_promisc = true;
mc_promisc = true;
@@ -519,6 +521,8 @@ static void enetc4_psi_do_set_rx_mode(struct work_struct 
*work)

/* Set new MAC filter */
enetc4_pf_set_mac_filter(pf, type);
+
+   rtnl_unlock();
 }



RE: [PATCH v6 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter

2025-04-29 Thread Wei Fang
> [Some people who received this message don't often get email from
> ti...@kernel.org. Learn why this is important at
> https://aka.ms/LearnAboutSenderIdentification ]
> 
> On Mon, Apr 28, 2025 at 6:19 AM Wei Fang  wrote:
> > +void enetc_remove_debugfs(struct enetc_si *si)
> > +{
> > +   debugfs_remove_recursive(si->debugfs_root);
> 
> You can just call debugfs_remove() here.  debugfs_remove_recursive()
> is deprecated:
> 
> void debugfs_remove(struct dentry *dentry);
> #define debugfs_remove_recursive debugfs_remove

Okay, I will replace it with debugfs_remove(), thanks



RE: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF

2025-04-15 Thread Wei Fang
> -Original Message-
> From: Jakub Kicinski 
> Sent: 2025年4月16日 11:43
> To: Wei Fang 
> Cc: Claudiu Manoil ; Vladimir Oltean
> ; Clark Wang ;
> andrew+net...@lunn.ch; da...@davemloft.net; eduma...@google.com;
> pab...@redhat.com; christophe.le...@csgroup.eu; net...@vger.kernel.org;
> linux-ker...@vger.kernel.org; i...@lists.linux.dev; 
> linuxppc-dev@lists.ozlabs.org;
> linux-arm-ker...@lists.infradead.org
> Subject: Re: [PATCH v5 net-next 04/14] net: enetc: add MAC filtering for 
> i.MX95
> ENETC PF
> 
> On Fri, 11 Apr 2025 17:57:42 +0800 Wei Fang wrote:
> > enetc4_pf_netdev_destroy(si);
> > enetc4_pf_free(pf);
> > +   destroy_workqueue(si->workqueue);
> 
> I think that you need to flush or cancel the work after unregistering
> the netdev but before freeing it? The work may access netdev after its
> freed.

Yes, you are right, I will improve it. thanks.


[PATCH v7 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF

2025-05-06 Thread Wei Fang
The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bit hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.

For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.

Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |   3 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 260 ++
 .../net/ethernet/freescale/enetc/enetc_pf.h   |   3 +
 4 files changed, 274 insertions(+)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index c3ebb32ce50c..1573ff06fcf4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -301,6 +301,9 @@ struct enetc_si {
int hw_features;
const struct enetc_drvdata *drvdata;
const struct enetc_si_ops *ops;
+
+   struct workqueue_struct *workqueue;
+   struct work_struct rx_mode_task;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
 #define ENETC4_PSICFGR2(a) ((a) * 0x80 + 0x2018)
 #define  PSICFGR2_NUM_MSIX GENMASK(5, 0)
 
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a)((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a)((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 175eebadde76..7b801f6e9a31 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
 
 #define ENETC_SI_MAX_RING_NUM  8
 
+#define ENETC_MAC_FILTER_TYPE_UC   BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC   BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL  (ENETC_MAC_FILTER_TYPE_UC | \
+ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+   u8 addr[ETH_ALEN];
+};
+
 static void enetc4_get_port_caps(struct enetc_pf *pf)
 {
struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 
val = enetc_port_rd(hw, ENETC4_PMCAPR);
pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+   val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+   pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
 }
 
 static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -56,6 +68,185 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw 
*hw, int si,
put_unaligned_le16(lower, addr + 4);
 }
 
+static void enetc4_pf_set_si_mac_promisc(struct enetc_hw *hw, int si,
+bool uc_promisc, bool mc_promisc)
+{
+   u32 val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+
+   if (uc_promisc)
+   val |= PSIPMMR_SI_MAC_UP(si);
+   else
+   val &= ~PSIPMMR_SI_MAC_UP(si);
+
+   if (mc_promisc)
+   val |= PSIPMMR_SI_MAC_MP(si);
+   else
+   val &= ~PSIPMMR_SI_MAC_MP(si);
+
+   enetc_port_wr(hw, ENETC4_PSIPMMR, val);
+}
+
+static void enetc4_pf_set_si_uc_hash_filter(struct enetc_hw *hw, int si,
+   u64 hash)
+{
+   enetc_port_wr(hw, ENETC4_P

[PATCH v7 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF

2025-05-06 Thread Wei Fang
Compared with LS1028A, there are two main differences: first, i.MX95
ENETC uses NTMP 2.0 to manage the RSS table, and second, the offset
of the RSS Key registers is different. Some modifications have been
made in the previous patches based on these differences to ensure that
the relevant interfaces are compatible with i.MX95. So it's time to
add RSS support to i.MX95 ENETC PF.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  |  5 +-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 15 ++
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 12 +
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 47 ---
 .../freescale/enetc/enetc_pf_common.c |  6 +--
 6 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 494f8f77bf4c..08762772c045 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2446,10 +2446,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
if (si->hw_features & ENETC_SI_F_LSO)
enetc_set_lso_flags_mask(hw);
 
-   /* TODO: RSS support for i.MX95 will be supported later, and the
-* is_enetc_rev1() condition will be removed
-*/
-   if (si->num_rss && is_enetc_rev1(si)) {
+   if (si->num_rss) {
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index e49c1626e7e5..7b24f1a5969a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -541,6 +541,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8 
*bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 
 static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
 struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index d2a414c28c21..2d890f7bcc95 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -523,6 +523,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static int enetc4_pf_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+   enetc_set_features(ndev, features);
+
+   return 0;
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -530,6 +538,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_get_stats  = enetc_get_stats,
.ndo_set_mac_address= enetc_pf_set_mac_addr,
.ndo_set_rx_mode= enetc4_pf_set_rx_mode,
+   .ndo_set_features   = enetc4_pf_set_features,
 };
 
 static struct phylink_pcs *
@@ -957,6 +966,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
free_netdev(ndev);
 }
 
+static const struct enetc_si_ops enetc4_psi_ops = {
+   .get_rss_table = enetc4_get_rss_table,
+   .set_rss_table = enetc4_set_rss_table,
+};
+
 static int enetc4_pf_probe(struct pci_dev *pdev,
   const struct pci_device_id *ent)
 {
@@ -981,6 +995,7 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 "Couldn't map PF only space\n");
 
si->revision = enetc_get_ip_revision(&si->hw);
+   si->ops = &enetc4_psi_ops;
err = enetc_get_driver_data(si);
if (err)
return dev_err_probe(dev, err,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c 
b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 71e4da530028..3d5f31879d5c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -294,3 +294,15 @@ int enetc_set_rss_table(struct enetc_si *si, const u32 
*table, int count)
return enetc_cmd_rss_table(si, (u32 *)table, count, false);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_table);
+
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
+{
+   return ntmp_rsst_query_entry(&si->ntmp_user, table, count);
+}
+EXPORT_SYMBOL_GPL(enetc4_get_rss_table);
+
+int enetc4_set

[PATCH v7 net-next 10/14] net: enetc: enable RSS feature by default

2025-05-06 Thread Wei Fang
Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.

Signed-off-by: Wei Fang 
Acked-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 31 ++-
 .../freescale/enetc/enetc_pf_common.c |  4 ++-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
 3 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index daea85cbf043..7e92dc0a9a49 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2430,6 +2430,20 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
 }
 
+static void enetc_set_rss(struct net_device *ndev, int en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+   u32 reg;
+
+   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+   reg = enetc_rd(hw, ENETC_SIMR);
+   reg &= ~ENETC_SIMR_RSSE;
+   reg |= (en) ? ENETC_SIMR_RSSE : 0;
+   enetc_wr(hw, ENETC_SIMR, reg);
+}
+
 int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
struct enetc_si *si = priv->si;
@@ -2450,6 +2464,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
+
+   if (priv->ndev->features & NETIF_F_RXHASH)
+   enetc_set_rss(priv->ndev, true);
}
 
return 0;
@@ -3242,20 +3259,6 @@ struct net_device_stats *enetc_get_stats(struct 
net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static void enetc_set_rss(struct net_device *ndev, int en)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
-   u32 reg;
-
-   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
-   reg = enetc_rd(hw, ENETC_SIMR);
-   reg &= ~ENETC_SIMR_RSSE;
-   reg |= (en) ? ENETC_SIMR_RSSE : 0;
-   enetc_wr(hw, ENETC_SIMR, reg);
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a302477c4de4..a751862a70b1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
if (si->hw_features & ENETC_SI_F_LSO)
priv->active_offloads |= ENETC_F_LSO;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 4fafe4e18a37..f6aed0a1ad1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, 
struct net_device *ndev,
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
  NETIF_F_TSO | NETIF_F_TSO6;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* pick up primary MAC address from SI */
enetc_load_primary_mac_addr(&si->hw, ndev);
-- 
2.34.1




[PATCH v7 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter

2025-05-06 Thread Wei Fang
ENETC's MAC filter consists of hash MAC filter and exact MAC filter.
Hash MAC filter is a 64-bit entry hash table consisting of two 32-bit
registers. Exact MAC filter is implemented by configuring MAC address
filter table through command BD ring. The table is stored in ENETC's
internal memory and needs to be read through command BD ring. In order
to facilitate debugging, added a debugfs interface to get the relevant
information about MAC filter.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/Makefile |  1 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 +
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 90 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h | 20 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  4 +
 5 files changed, 116 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h

diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
 nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 1573ff06fcf4..b53ecc882a90 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -304,6 +304,7 @@ struct enetc_si {
 
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
+   struct dentry *debugfs_root;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index ..1b1591dce73d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   u32 hash_h, hash_l;
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+   seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+   seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   struct maft_entry_data maft;
+   struct enetc_pf *pf;
+   int i, err, num_si;
+   u32 val;
+
+   pf = enetc_si_priv(si);
+   num_si = pf->caps.num_vsi + 1;
+
+   val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+   for (i = 0; i < num_si; i++) {
+   seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n", i,
+  str_enabled_disabled(PSIPMMR_SI_MAC_UP(i) & val));
+   seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n", i,
+  str_enabled_disabled(PSIPMMR_SI_MAC_MP(i) & val));
+   }
+
+   /* MAC hash filter table */
+   for (i = 0; i < num_si; i++)
+   enetc_show_si_mac_hash_filter(s, i);
+
+   if (!pf->num_mfe)
+   return 0;
+
+   /* MAC address filter table */
+   seq_puts(s, "MAC address filter table\n");
+   for (i = 0; i < pf->num_mfe; i++) {
+   memset(&maft, 0, sizeof(maft));
+   err = ntmp_maft_query_entry(&si->ntmp_user, i, &maft);
+   if (err)
+   return err;
+
+   seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+  maft.keye.mac_addr, 
le16_to_cpu(maft.cfge.si_bitmap));
+   }
+
+   return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
+
+void enetc_create_debugfs(struct enetc_si *si)
+{
+   struct net_device *ndev = si->ndev;
+   struct dentry *root;
+
+   root = debugfs_create_dir(netdev_name(ndev), NULL);
+   if (IS_ERR(root))
+   return;
+
+   si->debugfs_root = root;
+
+   debugfs_create_file("mac_filter", 0444, root, si, 
&a

[PATCH v7 net-next 07/14] net: enetc: make enetc_set_rss_key() reusable

2025-05-06 Thread Wei Fang
Since the offset of the RSS key registers of i.MX95 ENETC is different
from that of LS1028A, so add enetc_get_rss_key_base() to get the base
offset for the different chips, so that enetc_set_rss_key() can be
reused for this trivial thing.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +-
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 20 +--
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 19 +-
 .../net/ethernet/freescale/enetc/enetc_pf.c   |  4 +---
 .../freescale/enetc/enetc_pf_common.c | 10 ++
 .../freescale/enetc/enetc_pf_common.h |  1 +
 6 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 786042029b1e..e49c1626e7e5 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -537,7 +537,7 @@ int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
 int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse,
   int index);
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes);
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index db60354ea8d1..d2a414c28c21 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -418,24 +418,6 @@ static void enetc4_set_trx_frame_size(struct enetc_pf *pf)
enetc4_pf_reset_tc_msdu(&si->hw);
 }
 
-static void enetc4_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
-{
-   int i;
-
-   for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC4_PRSSKR(i), ((u32 *)bytes)[i]);
-}
-
-static void enetc4_set_default_rss_key(struct enetc_pf *pf)
-{
-   u8 hash_key[ENETC_RSSHASH_KEY_SIZE] = {0};
-   struct enetc_hw *hw = &pf->si->hw;
-
-   /* set up hash key */
-   get_random_bytes(hash_key, ENETC_RSSHASH_KEY_SIZE);
-   enetc4_set_rss_key(hw, hash_key);
-}
-
 static void enetc4_enable_trx(struct enetc_pf *pf)
 {
struct enetc_hw *hw = &pf->si->hw;
@@ -448,7 +430,7 @@ static void enetc4_configure_port(struct enetc_pf *pf)
 {
enetc4_configure_port_si(pf);
enetc4_set_trx_frame_size(pf);
-   enetc4_set_default_rss_key(pf);
+   enetc_set_default_rss_key(pf);
enetc4_enable_trx(pf);
 }
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 
b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 5c51cf7ea439..33a91babb0b2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -677,6 +677,14 @@ static u32 enetc_get_rxfh_indir_size(struct net_device 
*ndev)
return priv->si->num_rss;
 }
 
+static int enetc_get_rss_key_base(struct enetc_si *si)
+{
+   if (is_enetc_rev1(si))
+   return ENETC_PRSSK(0);
+
+   return ENETC4_PRSSKR(0);
+}
+
 static int enetc_get_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh)
 {
@@ -701,12 +709,14 @@ static int enetc_get_rxfh(struct net_device *ndev,
return err;
 }
 
-void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes)
+void enetc_set_rss_key(struct enetc_si *si, const u8 *bytes)
 {
+   int base = enetc_get_rss_key_base(si);
+   struct enetc_hw *hw = &si->hw;
int i;
 
for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / 4; i++)
-   enetc_port_wr(hw, ENETC_PRSSK(i), ((u32 *)bytes)[i]);
+   enetc_port_wr(hw, base + i * 4, ((u32 *)bytes)[i]);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_key);
 
@@ -716,12 +726,11 @@ static int enetc_set_rxfh(struct net_device *ndev,
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_si *si = priv->si;
-   struct enetc_hw *hw = &si->hw;
int err = 0;
 
/* set hash key, if PF */
-   if (rxfh->key && hw->port)
-   enetc_set_rss_key(hw, rxfh->key);
+   if (rxfh->key && enetc_si_is_pf(si))
+   enetc_set_rss_key(si, rxfh->key);
 
/* set RSS table */
if (rxfh->indir)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8dabb80ec04c..8f2616fd83d2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -515,7 +515,6 @@ static void enetc_mac_en

[PATCH v7 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core

2025-05-06 Thread Wei Fang
Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.

Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. This lays the basis for i.MX95 ENETC PF and VFs to
support MAC address filtering.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 36 +++
 drivers/net/ethernet/freescale/enetc/enetc.h  | 15 
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 34 --
 .../net/ethernet/freescale/enetc/enetc_pf.h   | 11 --
 4 files changed, 51 insertions(+), 45 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 3ee52f4b1166..5a7af44e4594 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct 
enetc_ndev_priv *priv,
enetc_mm_commit_preemptible_tcs(priv);
 }
 
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+   u64 mask = 0;
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 8; i++)
+   mask |= BIT_ULL(i * 6);
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+   return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+   int idx = enetc_mac_addr_hash_idx(addr);
+
+   /* add hash table entry */
+   __set_bit(idx, filter->mac_hash_table);
+   filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+   filter->mac_addr_cnt = 0;
+
+   bitmap_zero(filter->mac_hash_table,
+   ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 384e0bded87f..c3ebb32ce50c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
 
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
+#define ENETC_MADDR_HASH_TBL_SZ64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+   union {
+   char mac_addr[ETH_ALEN];
+   DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+   };
+   int mac_addr_cnt;
+};
+
 struct enetc_tx_swbd {
union {
struct sk_buff *skb;
@@ -471,6 +483,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
 int enetc_configure_si(struct enetc_ndev_priv *priv);
 int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 203862ec1114..f76403f7aee8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, 
u16 vlan, u8 qos)
enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
 }
 
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
-   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
-   u64 mask = 0;
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 8; i++)
-   mask |= BIT_ULL(i * 6);
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
-   filter->mac_addr_cnt = 0;
-
-   bitmap_zero(filter->mac_hash_table,
-   ENETC_MADDR_HASH_TBL_SZ);
-}
-
 static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
 const unsigned char *addr)
 {
@@ -104,16 +80,6 @@ static void enetc_add_mac_addr_em_filter(struct 
enetc_mac_filter *filter,
filter->mac_ad

[PATCH v7 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops

2025-05-06 Thread Wei Fang
Since i.MX95 ENETC (v4) uses NTMP 2.0 to manage the RSS table, which is
different from LS1028A ENETC (v1). In order to reuse some functions
related to the RSS table, so add .get_rss_table() and .set_rss_table()
hooks to enetc_si_ops.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.c|  2 +-
 drivers/net/ethernet/freescale/enetc/enetc.h| 13 +
 .../net/ethernet/freescale/enetc/enetc_ethtool.c| 12 ++--
 drivers/net/ethernet/freescale/enetc/enetc_pf.c |  6 ++
 drivers/net/ethernet/freescale/enetc/enetc_vf.c |  6 ++
 5 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 5a7af44e4594..494f8f77bf4c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2415,7 +2415,7 @@ static int enetc_setup_default_rss_table(struct enetc_si 
*si, int num_groups)
for (i = 0; i < si->num_rss; i++)
rss_table[i] = i % num_groups;
 
-   enetc_set_rss_table(si, rss_table, si->num_rss);
+   si->ops->set_rss_table(si, rss_table, si->num_rss);
 
kfree(rss_table);
 
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index b53ecc882a90..786042029b1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -279,6 +279,19 @@ struct enetc_platform_info {
const struct enetc_drvdata *data;
 };
 
+struct enetc_si;
+
+/*
+ * This structure defines the some common hooks for ENETC PSI and VSI.
+ * In addition, since VSI only uses the struct enetc_si as its private
+ * driver data, so this structure also define some hooks specifically
+ * for VSI. For VSI-specific hooks, the format is ???vf_*()???.
+ */
+struct enetc_si_ops {
+   int (*get_rss_table)(struct enetc_si *si, u32 *table, int count);
+   int (*set_rss_table)(struct enetc_si *si, const u32 *table, int count);
+};
+
 /* PCI IEP device data */
 struct enetc_si {
struct pci_dev *pdev;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 
b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index f47c8b6cc511..5c51cf7ea439 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -681,7 +681,8 @@ static int enetc_get_rxfh(struct net_device *ndev,
  struct ethtool_rxfh_param *rxfh)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int err = 0, i;
 
/* return hash function */
@@ -695,8 +696,7 @@ static int enetc_get_rxfh(struct net_device *ndev,
 
/* return RSS table */
if (rxfh->indir)
-   err = enetc_get_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = si->ops->get_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
@@ -715,7 +715,8 @@ static int enetc_set_rxfh(struct net_device *ndev,
  struct netlink_ext_ack *extack)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
+   struct enetc_si *si = priv->si;
+   struct enetc_hw *hw = &si->hw;
int err = 0;
 
/* set hash key, if PF */
@@ -724,8 +725,7 @@ static int enetc_set_rxfh(struct net_device *ndev,
 
/* set RSS table */
if (rxfh->indir)
-   err = enetc_set_rss_table(priv->si, rxfh->indir,
- priv->si->num_rss);
+   err = si->ops->set_rss_table(si, rxfh->indir, si->num_rss);
 
return err;
 }
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index f76403f7aee8..8dabb80ec04c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -905,6 +905,11 @@ static int enetc_pf_register_with_ierb(struct pci_dev 
*pdev)
return enetc_ierb_register_pf(ierb_pdev, pdev);
 }
 
+static const struct enetc_si_ops enetc_psi_ops = {
+   .get_rss_table = enetc_get_rss_table,
+   .set_rss_table = enetc_set_rss_table,
+};
+
 static struct enetc_si *enetc_psi_create(struct pci_dev *pdev)
 {
struct enetc_si *si;
@@ -924,6 +929,7 @@ static struct enetc_si *enetc_psi_create(struct pci_dev 
*pdev)
}
 
si->revision = enetc_get_ip_revision(&si->hw);
+   si->ops = &enetc_psi_ops;
err = enetc_get_driver_data(si);
if (err) {
dev_err(&pdev->dev, "Coul

[PATCH v7 net-next 09/14] net: enetc: change enetc_set_rss() to void type

2025-05-06 Thread Wei Fang
Actually enetc_set_rss() does not need a return value, so change its
type to void.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 08762772c045..daea85cbf043 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -3242,7 +3242,7 @@ struct net_device_stats *enetc_get_stats(struct 
net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static int enetc_set_rss(struct net_device *ndev, int en)
+static void enetc_set_rss(struct net_device *ndev, int en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_hw *hw = &priv->si->hw;
@@ -3254,8 +3254,6 @@ static int enetc_set_rss(struct net_device *ndev, int en)
reg &= ~ENETC_SIMR_RSSE;
reg |= (en) ? ENETC_SIMR_RSSE : 0;
enetc_wr(hw, ENETC_SIMR, reg);
-
-   return 0;
 }
 
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
-- 
2.34.1




[PATCH v7 net-next 00/14] Add more features for ENETC v4 - round 2

2025-05-06 Thread Wei Fang
This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.

---
v1 Link: https://lore.kernel.org/imx/20250103060610.2233908-1-wei.f...@nxp.com/
v2 Link: https://lore.kernel.org/imx/20250113082245.2332775-1-wei.f...@nxp.com/
v3 Link: https://lore.kernel.org/imx/20250304072201.1332603-1-wei.f...@nxp.com/
v4 Link: https://lore.kernel.org/imx/20250311053830.1516523-1-wei.f...@nxp.com/
v5 Link: https://lore.kernel.org/imx/20250411095752.3072696-1-wei.f...@nxp.com/
v6 Link: https://lore.kernel.org/imx/20250428105657.3283130-1-wei.f...@nxp.com/ 
v7 changes:
1. Replace debugfs_remove_recursive() with debugfs_remove()
2. Collect tags
---

Wei Fang (14):
  net: enetc: add initial netc-lib driver to support NTMP
  net: enetc: add command BD ring support for i.MX95 ENETC
  net: enetc: move generic MAC filtering interfaces to enetc-core
  net: enetc: add MAC filtering for i.MX95 ENETC PF
  net: enetc: add debugfs interface to dump MAC filter
  net: enetc: add set/get_rss_table() hooks to enetc_si_ops
  net: enetc: make enetc_set_rss_key() reusable
  net: enetc: add RSS support for i.MX95 ENETC PF
  net: enetc: change enetc_set_rss() to void type
  net: enetc: enable RSS feature by default
  net: enetc: extract enetc_refresh_vlan_ht_filter()
  net: enetc: move generic VLAN hash filter functions to
enetc_pf_common.c
  net: enetc: add VLAN filtering support for i.MX95 ENETC PF
  net: enetc: add loopback support for i.MX95 ENETC PF

 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   4 +
 drivers/net/ethernet/freescale/enetc/enetc.c  |  76 ++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  45 +-
 .../ethernet/freescale/enetc/enetc4_debugfs.c |  90 
 .../ethernet/freescale/enetc/enetc4_debugfs.h |  20 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  12 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 368 +-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c |  50 ++
 .../ethernet/freescale/enetc/enetc_ethtool.c  |  74 ++-
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 105 +---
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  14 +-
 .../freescale/enetc/enetc_pf_common.c |  93 +++-
 .../freescale/enetc/enetc_pf_common.h |   3 +
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  10 +-
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 462 ++
 .../ethernet/freescale/enetc/ntmp_private.h   | 103 
 include/linux/fsl/ntmp.h  | 121 +
 19 files changed, 1485 insertions(+), 174 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

-- 
2.34.1




[PATCH v7 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-05-06 Thread Wei Fang
Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.

For the management protocol of LS1028A has been retroactively named NTMP
1.0, and its implementation is in enetc_cbdr.c and enetc_qos.c. However,
NTMP of i.MX95 has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.

It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   3 +
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 462 ++
 .../ethernet/freescale/enetc/ntmp_private.h   | 103 
 include/linux/fsl/ntmp.h  | 121 +
 6 files changed, 698 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5c31814c9687..b69988a9f965 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9376,6 +9376,7 @@ F:
Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
 F: drivers/net/ethernet/freescale/enetc/
 F: include/linux/fsl/enetc_mdio.h
 F: include/linux/fsl/netc_global.h
+F: include/linux/fsl/ntmp.h
 
 FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 M: Claudiu Manoil 
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig 
b/drivers/net/ethernet/freescale/enetc/Kconfig
index 7250d3bbf6bb..616ea22ceabc 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,13 @@ config NXP_ENETC_PF_COMMON
 
  If compiled as module (M), the module name is nxp-enetc-pf-common.
 
+config NXP_NETC_LIB
+   tristate
+   help
+ This module provides common functionalities for both ENETC and NETC
+ Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+ flower and debugfs interfaces and so on.
+
 config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI_MSI
@@ -40,6 +47,7 @@ config NXP_ENETC4
select FSL_ENETC_CORE
select FSL_ENETC_MDIO
select NXP_ENETC_PF_COMMON
+   select NXP_NETC_LIB
select PHYLINK
select DIMLIB
help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
 obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
 nxp-enetc-pf-common-y := enetc_pf_common.o
 
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
 fsl-enetc-y := enetc_pf.o
 fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o
diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c 
b/drivers/net/ethernet/freescale/enetc/ntmp.c
new file mode 100644
index ..ba32c1bbd9e1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * NETC NTMP (NETC Table Management Protocol) 2.0 Library
+ * Copyright 2025 NXP
+ */
+
+#include 
+#include 
+#include 
+
+#include "ntmp_private.h"
+
+#define NETC_CBDR_TIMEOUT  1000 /* us */
+#define NETC_CBDR_DELAY_US 10
+#define NETC_CBDR_MR_ENBIT(31)
+
+#define NTMP_BASE_ADDR_ALIGN   128
+#define NTMP_DATA_ADDR_ALIGN   32
+
+/* Define NTMP Table ID */
+#define NTMP_MAFT_ID   1
+#define NTMP_RSST_ID   3
+
+/* Generic Update Actions for most tables */
+#define NTMP_GEN_UA_CFGEU  BIT(0)
+#define NTMP_GEN_UA_STSEU  BIT(1)
+
+#defin

[PATCH v7 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC

2025-05-06 Thread Wei Fang
The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).

Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. So add
enetc4_setup_cbdr() and enetc4_teardown_cbdr() for ENETC v4 drivers.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  9 -
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 39 ++-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 38 ++
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..384e0bded87f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,7 +275,10 @@ struct enetc_si {
 
struct net_device *ndev; /* back ref. */
 
-   struct enetc_cbdr cbd_ring;
+   union {
+   struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+   struct ntmp_user ntmp_user; /* ENETC 4.1 and later */
+   };
 
int num_rx_rings; /* how many rings are available in the SI */
int num_tx_rings;
@@ -284,6 +288,7 @@ struct enetc_si {
u16 revision;
int hw_features;
const struct enetc_drvdata *drvdata;
+   const struct enetc_si_ops *ops;
 };
 
 #define ENETC_SI_ALIGN 32
@@ -493,6 +498,8 @@ void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv 
*priv);
 int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
 struct enetc_cbdr *cbdr);
 void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 73ac8c6afb3a..175eebadde76 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,21 @@ static void enetc4_configure_port(struct enetc_pf *pf)
enetc4_enable_trx(pf);
 }
 
+static int enetc4_init_ntmp_user(struct enetc_si *si)
+{
+   struct ntmp_user *user = &si->ntmp_user;
+
+   /* For ENETC 4.1, all table versions are 0 */
+   memset(&user->tbl, 0, sizeof(user->tbl));
+
+   return enetc4_setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_user(struct enetc_si *si)
+{
+   enetc4_teardown_cbdr(si);
+}
+
 static int enetc4_pf_init(struct enetc_pf *pf)
 {
struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +287,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
return err;
}
 
+   err = enetc4_init_ntmp_user(pf->si);
+   if (err) {
+   dev_err(dev, "Failed to init CBDR\n");
+   return err;
+   }
+
enetc4_configure_port(pf);
 
return 0;
 }
 
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+   enetc4_free_ntmp_user(pf->si);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -728,14 +754,25 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 
enetc_get_si_caps(si);
 
-   return enetc4_pf_netdev_create(si);
+   err = enetc4_pf_netdev_create(si);
+   if (err)
+   goto err_netdev_create;
+
+   return 0;
+
+err_netdev_create:
+   enetc4_pf_free(pf);
+
+   return err;
 }
 
 static void enetc4_pf_remove(struct pci_dev *pdev)
 {
struct enetc_si *si = pci_get_drvdata(pdev);
+   struct enetc_pf *pf = enetc_si_priv(si);
 
enetc4_pf_netdev_destroy(si);
+   enetc4_pf_free(pf);
 }
 
 static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c 
b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 20bfdf7fb4b4..71e4da530028 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -60,6 +60,44 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
 }
 EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
 
+int enetc4_setup_cbdr(struct enetc_si *si)
+{
+   struct ntmp_user *user = &si->ntmp_user;
+   struct device *dev = &si->pdev->dev;
+   struct enetc_hw *hw = &si->hw;
+   struct netc_cbdr_regs regs;
+
+   user->cbdr_num = 1;
+   user->dev = dev;
+   user->ri

[PATCH v7 net-next 13/14] net: enetc: add VLAN filtering support for i.MX95 ENETC PF

2025-05-06 Thread Wei Fang
Since the offsets of the VLAN hash filter registers of ENETC v4 are
different from ENETC v1. Therefore, enetc_set_si_vlan_ht_filter() is
added to set the correct VLAN hash filter based on the SI ID and ENETC
revision, so that ENETC v4 PF driver can reuse enetc_vlan_rx_add_vid()
and enetc_vlan_rx_del_vid(). In addition, the VLAN promiscuous mode will
be enabled if VLAN filtering is disabled, which means that PF qualifies
for reception of all VLAN tags.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  4 +++
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 12 +
 .../freescale/enetc/enetc_pf_common.c | 25 +--
 3 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 826359004850..aa25b445d301 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -107,6 +107,10 @@
 #define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
 #define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
 
+/* Port station interface a VLAN hash filter register 0/1 */
+#define ENETC4_PSIVHFR0(a) ((a) * 0x80 + 0x2060)
+#define ENETC4_PSIVHFR1(a) ((a) * 0x80 + 0x2064)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 2d890f7bcc95..1f6500f12bbb 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -526,6 +526,16 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
 static int enetc4_pf_set_features(struct net_device *ndev,
  netdev_features_t features)
 {
+   netdev_features_t changed = ndev->features ^ features;
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+
+   if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+   bool promisc_en = !(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+
+   enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
+   }
+
enetc_set_features(ndev, features);
 
return 0;
@@ -539,6 +549,8 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_set_mac_address= enetc_pf_set_mac_addr,
.ndo_set_rx_mode= enetc4_pf_set_rx_mode,
.ndo_set_features   = enetc4_pf_set_features,
+   .ndo_vlan_rx_add_vid= enetc_vlan_rx_add_vid,
+   .ndo_vlan_rx_kill_vid   = enetc_vlan_rx_del_vid,
 };
 
 static struct phylink_pcs *
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index ed8afd174c9e..8c563e552021 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -135,7 +135,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | 
NETIF_F_LOOPBACK);
+   ndev->hw_features &= ~NETIF_F_LOOPBACK;
goto end;
}
 
@@ -376,11 +376,22 @@ static void enetc_refresh_vlan_ht_filter(struct enetc_pf 
*pf)
}
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-unsigned long hash)
+static void enetc_set_si_vlan_ht_filter(struct enetc_si *si,
+   int si_id, u64 hash)
 {
-   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
-   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
+   struct enetc_hw *hw = &si->hw;
+   int high_reg_off, low_reg_off;
+
+   if (is_enetc_rev1(si)) {
+   low_reg_off = ENETC_PSIVHFR0(si_id);
+   high_reg_off = ENETC_PSIVHFR1(si_id);
+   } else {
+   low_reg_off = ENETC4_PSIVHFR0(si_id);
+   high_reg_off = ENETC4_PSIVHFR1(si_id);
+   }
+
+   enetc_port_wr(hw, low_reg_off, lower_32_bits(hash));
+   enetc_port_wr(hw, high_reg_off, upper_32_bits(hash));
 }
 
 int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
@@ -393,7 +404,7 @@ int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 
prot, u16 vid)
 
idx = enetc_vid_hash_idx(vid);
if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+   enetc_set_si_vlan_ht_filter(pf->si, 0, *pf->vlan_ht_filter);
 
return 0;
 }

[PATCH v7 net-next 14/14] net: enetc: add loopback support for i.MX95 ENETC PF

2025-05-06 Thread Wei Fang
Add internal loopback support for i.MX95 ENETC PF, the default loopback
mode is MAC level loopback, the MAC Tx data is looped back onto the Rx.
The MAC interface runs at a fixed 1:8 ratio of NETC clock in MAC-level
loopback mode, with no dependency on Tx clock.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 .../net/ethernet/freescale/enetc/enetc4_pf.c   | 18 ++
 .../ethernet/freescale/enetc/enetc_pf_common.c |  4 +---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 1f6500f12bbb..c16378eb50bc 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -101,6 +101,21 @@ static void enetc4_pf_set_si_mc_hash_filter(struct 
enetc_hw *hw, int si,
enetc_port_wr(hw, ENETC4_PSIMMHFR1(si), upper_32_bits(hash));
 }
 
+static void enetc4_pf_set_loopback(struct net_device *ndev, bool en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_si *si = priv->si;
+   u32 val;
+
+   val = enetc_port_mac_rd(si, ENETC4_PM_CMD_CFG(0));
+   val = u32_replace_bits(val, en ? 1 : 0, PM_CMD_CFG_LOOP_EN);
+   /* Default to select MAC level loopback mode if loopback is enabled. */
+   val = u32_replace_bits(val, en ? LPBCK_MODE_MAC_LEVEL : 0,
+  PM_CMD_CFG_LPBK_MODE);
+
+   enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
+}
+
 static void enetc4_pf_clear_maft_entries(struct enetc_pf *pf)
 {
int i;
@@ -536,6 +551,9 @@ static int enetc4_pf_set_features(struct net_device *ndev,
enetc4_pf_set_si_vlan_promisc(hw, 0, promisc_en);
}
 
+   if (changed & NETIF_F_LOOPBACK)
+   enetc4_pf_set_loopback(ndev, !!(features & NETIF_F_LOOPBACK));
+
enetc_set_features(ndev, features);
 
return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 8c563e552021..edf14a95cab7 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -134,10 +134,8 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
}
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
-   if (!is_enetc_rev1(si)) {
-   ndev->hw_features &= ~NETIF_F_LOOPBACK;
+   if (!is_enetc_rev1(si))
goto end;
-   }
 
ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
 NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-- 
2.34.1




[PATCH v7 net-next 12/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c

2025-05-06 Thread Wei Fang
The VLAN hash filters of ENETC v1 and v4 are basically the same, the only
difference is that the offset of the VLAN hash filter registers has been
changed in ENETC v4. So some functions like enetc_vlan_rx_add_vid() and
enetc_vlan_rx_del_vid() only need to be slightly modified to be reused
by ENETC v4. Currently, we just move these functions from enetc_pf.c to
enetc_pf_common.c. Appropriate modifications will be made for ENETC4 in
a subsequent patch.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 57 --
 .../freescale/enetc/enetc_pf_common.c | 60 +++
 .../freescale/enetc/enetc_pf_common.h |  2 +
 3 files changed, 62 insertions(+), 57 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index ae2dbd159ab4..6560bdbff287 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -216,63 +216,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-unsigned long hash)
-{
-   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
-   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
-}
-
-static int enetc_vid_hash_idx(unsigned int vid)
-{
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
-{
-   int i;
-
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
-}
-
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
-   int idx;
-
-   __set_bit(vid, pf->active_vlans);
-
-   idx = enetc_vid_hash_idx(vid);
-   if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
-   return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
-
-   __clear_bit(vid, pf->active_vlans);
-   enetc_refresh_vlan_ht_filter(pf);
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
-   return 0;
-}
-
 static void enetc_set_loopback(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a751862a70b1..ed8afd174c9e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -353,5 +353,65 @@ void enetc_set_default_rss_key(struct enetc_pf *pf)
 }
 EXPORT_SYMBOL_GPL(enetc_set_default_rss_key);
 
+static int enetc_vid_hash_idx(unsigned int vid)
+{
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+   return res;
+}
+
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
+{
+   int i;
+
+   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
+
+   __set_bit(hidx, pf->vlan_ht_filter);
+   }
+}
+
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
+unsigned long hash)
+{
+   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
+   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
+}
+
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   int idx;
+
+   __set_bit(vid, pf->active_vlans);
+
+   idx = enetc_vid_hash_idx(vid);
+   if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv

[PATCH v7 net-next 11/14] net: enetc: extract enetc_refresh_vlan_ht_filter()

2025-05-06 Thread Wei Fang
Extract the common function enetc_refresh_vlan_ht_filter() from
enetc_sync_vlan_ht_filter() so that it can be reused by the ENETC
v4 PF and VF drivers in the future.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 20 ---
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8f2616fd83d2..ae2dbd159ab4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -234,21 +234,16 @@ static int enetc_vid_hash_idx(unsigned int vid)
return res;
 }
 
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
 {
int i;
 
-   if (rehash) {
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
 
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
+   __set_bit(hidx, pf->vlan_ht_filter);
}
-
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 }
 
 static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
@@ -261,7 +256,7 @@ static int enetc_vlan_rx_add_vid(struct net_device *ndev, 
__be16 prot, u16 vid)
 
idx = enetc_vid_hash_idx(vid);
if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_sync_vlan_ht_filter(pf, false);
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 
return 0;
 }
@@ -272,7 +267,8 @@ static int enetc_vlan_rx_del_vid(struct net_device *ndev, 
__be16 prot, u16 vid)
struct enetc_pf *pf = enetc_si_priv(priv->si);
 
__clear_bit(vid, pf->active_vlans);
-   enetc_sync_vlan_ht_filter(pf, true);
+   enetc_refresh_vlan_ht_filter(pf);
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 
return 0;
 }
-- 
2.34.1




RE: [PATCH v5 net-next 06/14] net: enetc: add set/get_rss_table() hooks to enetc_si_ops

2025-04-15 Thread Wei Fang
> On 4/11/25 11:57 AM, Wei Fang wrote:
> > Since i.MX95 ENETC (v4) uses NTMP 2.0 to manage the RSS table, which
> > is different from LS1028A ENETC (v1). In order to reuse some functions
> > related to the RSS table, so add .get_rss_table() and .set_rss_table()
> > hooks to enetc_si_ops.
> >
> > Signed-off-by: Wei Fang 
> > ---
> > v5 changes:
> > Add enetc_set_default_rss_key() to enetc_pf_common.c and use it in
> > both enetc v1 and v4 drivers
> 
> Note for the reviewers: this changelog actually applies to the next
> (07/14) patch.
> 
> /P

Thanks for pointing out this mistake of changelog.




[PATCH v6 net-next 01/14] net: enetc: add initial netc-lib driver to support NTMP

2025-04-28 Thread Wei Fang
Some NETC functionality is controlled using control messages sent to the
hardware using BD ring interface with 32B descriptor similar to transmit
BD ring used on ENETC. This BD ring interface is referred to as command
BD ring. It is used to configure functionality where the underlying
resources may be shared between different entities or being too large to
configure using direct registers. Therefore, a messaging protocol called
NETC Table Management Protocol (NTMP) is provided for exchanging
configuration and management information between the software and the
hardware using the command BD ring interface.

For the management protocol of LS1028A has been retroactively named NTMP
1.0, and its implementation is in enetc_cbdr.c and enetc_qos.c. However,
NTMP of i.MX95 has been upgraded to version 2.0, which is incompatible
with LS1028A, because the message formats have been changed. Therefore,
add the netc-lib driver to support NTMP 2.0 to operate various tables.
Note that, only MAC address filter table and RSS table are supported at
the moment. More tables will be supported in subsequent patches.

It is worth mentioning that the purpose of the netc-lib driver is to
provide some NTMP-based generic interfaces for ENETC and NETC Switch
drivers. Currently, it only supports the configurations of some tables.
Interfaces such as tc flower and debugfs will be added in the future.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Add the change of MAINTAINERS to this patch
2. Rename ntmp_fill_request_headr() to ntmp_fill_request_hdr()
3. Split ntmp_rsst_query_or_update_entry() into
ntmp_rsst_query_or_update_entry() and ntmp_rsst_query_entry()
4. Add "ntmp_" prefix to struct cmn_resp_query and cmn_req_data.
5. Remove struct common_resp_nq and netc_dev_type
6. Correct the definition of NTMP_TBL_VER
7. Remove struct netc_cbdrs and rename ntmp_priv to ntmp_user
8. Improve the error log
9. Remove NTMP_NULL_ENTRY_ID check from ntmp_delete_entry_by_id()
10. Remove netc_select_cbdr()
11. Move union netc_cbd from ntmp.h to ntmp_private.h
v6 changes:
1. Add the description of NTMP 1.0 in commit message
2. Add NETC_CBDR_DELAY_US
3. Add ntmp_table_name() and change the error log
4. Optimize the initialization of struct ntmp_dma_buf data
5. Rename netc_setup_cbdr() and netc_teardown_cbdr() to ntmp_init_cbdr()
   and ntmp_free_cbdr()
6. Remove cbdr_size for struct ntmp_user and move NETC_CBDR_BD_NUM from
   ntmp.h to ntmp_private.h
7. Remove some unused macros
---
 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   3 +
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 462 ++
 .../ethernet/freescale/enetc/ntmp_private.h   | 103 
 include/linux/fsl/ntmp.h  | 121 +
 6 files changed, 698 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a7545b5abef9..56a8bb9ea4af 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9375,6 +9375,7 @@ F:
Documentation/devicetree/bindings/net/nxp,netc-blk-ctrl.yaml
 F: drivers/net/ethernet/freescale/enetc/
 F: include/linux/fsl/enetc_mdio.h
 F: include/linux/fsl/netc_global.h
+F: include/linux/fsl/ntmp.h
 
 FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 M: Claudiu Manoil 
diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig 
b/drivers/net/ethernet/freescale/enetc/Kconfig
index 6c2779047dcd..c8efbb6f2055 100644
--- a/drivers/net/ethernet/freescale/enetc/Kconfig
+++ b/drivers/net/ethernet/freescale/enetc/Kconfig
@@ -15,6 +15,13 @@ config NXP_ENETC_PF_COMMON
 
  If compiled as module (M), the module name is nxp-enetc-pf-common.
 
+config NXP_NETC_LIB
+   tristate
+   help
+ This module provides common functionalities for both ENETC and NETC
+ Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc
+ flower and debugfs interfaces and so on.
+
 config FSL_ENETC
tristate "ENETC PF driver"
depends on PCI_MSI
@@ -40,6 +47,7 @@ config NXP_ENETC4
select FSL_ENETC_CORE
select FSL_ENETC_MDIO
select NXP_ENETC_PF_COMMON
+   select NXP_NETC_LIB
select PHYLINK
select DIMLIB
help
diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 6fd27ee4fcd1..707a68e26971 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -6,6 +6,9 @@ fsl-enetc-core-y := enetc.o enetc_cbdr.o enetc_ethtool.o
 obj-$(CONFIG_NXP_ENETC_PF_COMMON) += nxp-enetc-pf-common.o
 nxp-enetc-pf-common-y := enetc_pf_common.o
 
+obj-$(CONFIG_NXP_NETC_LIB) += nxp-netc-lib.o
+nxp-netc-lib-y := ntmp.o
+
 obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o
 fsl-enetc-

[PATCH v6 net-next 00/14] Add more features for ENETC v4 - round 2

2025-04-28 Thread Wei Fang
This patch set adds the following features.
1. Compared with ENETC v1, the formats of tables and command BD of ENETC
v4 have changed significantly, and the two are not compatible. Therefore,
in order to support the NETC Table Management Protocol (NTMP) v2.0, we
introduced the netc-lib driver and added support for MAC address filter
table and RSS table.
2. Add MAC filter and VLAN filter support for i.MX95 ENETC PF.
3. Add RSS support for i.MX95 ENETC PF.
4. Add loopback support for i.MX95 ENETC PF.

---
v1 Link: https://lore.kernel.org/imx/20250103060610.2233908-1-wei.f...@nxp.com/
v2 Link: https://lore.kernel.org/imx/20250113082245.2332775-1-wei.f...@nxp.com/
v3 Link: https://lore.kernel.org/imx/20250304072201.1332603-1-wei.f...@nxp.com/
v4 Link: https://lore.kernel.org/imx/20250311053830.1516523-1-wei.f...@nxp.com/
v5 Link: https://lore.kernel.org/imx/20250411095752.3072696-1-wei.f...@nxp.com/
---

Wei Fang (14):
  net: enetc: add initial netc-lib driver to support NTMP
  net: enetc: add command BD ring support for i.MX95 ENETC
  net: enetc: move generic MAC filtering interfaces to enetc-core
  net: enetc: add MAC filtering for i.MX95 ENETC PF
  net: enetc: add debugfs interface to dump MAC filter
  net: enetc: add set/get_rss_table() hooks to enetc_si_ops
  net: enetc: make enetc_set_rss_key() reusable
  net: enetc: add RSS support for i.MX95 ENETC PF
  net: enetc: change enetc_set_rss() to void type
  net: enetc: enable RSS feature by default
  net: enetc: extract enetc_refresh_vlan_ht_filter()
  net: enetc: move generic VLAN hash filter functions to
enetc_pf_common.c
  net: enetc: add VLAN filtering support for i.MX95 ENETC PF
  net: enetc: add loopback support for i.MX95 ENETC PF

 MAINTAINERS   |   1 +
 drivers/net/ethernet/freescale/enetc/Kconfig  |   8 +
 drivers/net/ethernet/freescale/enetc/Makefile |   4 +
 drivers/net/ethernet/freescale/enetc/enetc.c  |  76 ++-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  45 +-
 .../ethernet/freescale/enetc/enetc4_debugfs.c |  90 
 .../ethernet/freescale/enetc/enetc4_debugfs.h |  20 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |  12 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 368 +-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c |  50 ++
 .../ethernet/freescale/enetc/enetc_ethtool.c  |  74 ++-
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 105 +---
 .../net/ethernet/freescale/enetc/enetc_pf.h   |  14 +-
 .../freescale/enetc/enetc_pf_common.c |  93 +++-
 .../freescale/enetc/enetc_pf_common.h |   3 +
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  10 +-
 drivers/net/ethernet/freescale/enetc/ntmp.c   | 462 ++
 .../ethernet/freescale/enetc/ntmp_private.h   | 103 
 include/linux/fsl/ntmp.h  | 121 +
 19 files changed, 1485 insertions(+), 174 deletions(-)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/ntmp_private.h
 create mode 100644 include/linux/fsl/ntmp.h

-- 
2.34.1




[PATCH v6 net-next 04/14] net: enetc: add MAC filtering for i.MX95 ENETC PF

2025-04-28 Thread Wei Fang
The i.MX95 ENETC supports both MAC hash filter and MAC exact filter. MAC
hash filter is implenented through a 64-bit hash table to match against
the hashed addresses, PF and VFs each have two MAC hash tables, one is
for unicast and the other one is for multicast. But MAC exact filter is
shared between SIs (PF and VFs), each table entry contains a MAC address
that may be unicast or multicast and the entry also contains an SI bitmap
field that indicates for which SIs the entry is valid.

For i.MX95 ENETC, MAC exact filter only has 4 entries. According to the
observation of the system default network configuration, the MAC filter
will be configured with multiple multicast addresses, so MAC exact filter
does not have enough entries to implement multicast filtering. Therefore,
the current MAC exact filter is only used for unicast filtering. If the
number of unicast addresses exceeds 4, then MAC hash filter is used.

Note that both MAC hash filter and MAC exact filter can only be accessed
by PF, VFs can notify PF to set its corresponding MAC filter through the
mailbox mechanism of ENETC. But currently MAC filter is only added for
i.MX95 ENETC PF. The MAC filter support of ENETC VFs will be supported in
subsequent patches.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Refactor enetc4_pf_set_si_mac_promisc()
2. Split enetc4_pf_set_si_mac_hash_filter() into
enetc4_pf_set_si_uc_hash_filter() and enetc4_pf_set_si_mc_hash_filter()
3. Rename enetc4_pf_wq_task_init() to enetc4_psi_wq_task_init()
4. Rename enetc4_pf_do_set_rx_mode() to enetc4_psi_do_set_rx_mode()
5. Remove mac_list_lock and mac_list related functions
6. Add enetc4_pf_clear_maft_entries() and enetc4_pf_add_maft_entries()
7. Refactor enetc4_pf_set_mac_exact_filter() and rename it to
enetc4_pf_set_uc_exact_filter()
v6 changes:
1. Add rtnl_lock() to enetc4_psi_do_set_rx_mode()
2. Move enetc4_psi_wq_task_init() to enetc4_pf_netdev_create(), and add
   cancel_work() and destroy_workqueue() to enetc4_pf_netdev_destroy()
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |   3 +
 .../net/ethernet/freescale/enetc/enetc4_hw.h  |   8 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 260 ++
 .../net/ethernet/freescale/enetc/enetc_pf.h   |   3 +
 4 files changed, 274 insertions(+)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index c3ebb32ce50c..1573ff06fcf4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -301,6 +301,9 @@ struct enetc_si {
int hw_features;
const struct enetc_drvdata *drvdata;
const struct enetc_si_ops *ops;
+
+   struct workqueue_struct *workqueue;
+   struct work_struct rx_mode_task;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h 
b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 695cb07c74bc..826359004850 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -99,6 +99,14 @@
 #define ENETC4_PSICFGR2(a) ((a) * 0x80 + 0x2018)
 #define  PSICFGR2_NUM_MSIX GENMASK(5, 0)
 
+/* Port station interface a unicast MAC hash filter register 0/1 */
+#define ENETC4_PSIUMHFR0(a)((a) * 0x80 + 0x2050)
+#define ENETC4_PSIUMHFR1(a)((a) * 0x80 + 0x2054)
+
+/* Port station interface a multicast MAC hash filter register 0/1 */
+#define ENETC4_PSIMMHFR0(a)((a) * 0x80 + 0x2058)
+#define ENETC4_PSIMMHFR1(a)((a) * 0x80 + 0x205c)
+
 #define ENETC4_PMCAPR  0x4004
 #define  PMCAPR_HD BIT(8)
 #define  PMCAPR_FP GENMASK(10, 9)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 175eebadde76..7b801f6e9a31 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -11,6 +11,15 @@
 
 #define ENETC_SI_MAX_RING_NUM  8
 
+#define ENETC_MAC_FILTER_TYPE_UC   BIT(0)
+#define ENETC_MAC_FILTER_TYPE_MC   BIT(1)
+#define ENETC_MAC_FILTER_TYPE_ALL  (ENETC_MAC_FILTER_TYPE_UC | \
+ENETC_MAC_FILTER_TYPE_MC)
+
+struct enetc_mac_addr {
+   u8 addr[ETH_ALEN];
+};
+
 static void enetc4_get_port_caps(struct enetc_pf *pf)
 {
struct enetc_hw *hw = &pf->si->hw;
@@ -26,6 +35,9 @@ static void enetc4_get_port_caps(struct enetc_pf *pf)
 
val = enetc_port_rd(hw, ENETC4_PMCAPR);
pf->caps.half_duplex = (val & PMCAPR_HD) ? 1 : 0;
+
+   val = enetc_port_rd(hw, ENETC4_PSIMAFCAPR);
+   pf->caps.mac_filter_num = val & PSIMAFCAPR_NUM_MAC_AFTE;
 }
 
 static void enetc4_pf_set_si_primary_mac(struct enetc_hw *hw, int si,
@@ -56,6 +68,185 @@ static void enetc4_pf_get_si_primary_mac(struct enetc_hw 
*hw, int si,
put_unaligned_le16(lower, addr

[PATCH v6 net-next 02/14] net: enetc: add command BD ring support for i.MX95 ENETC

2025-04-28 Thread Wei Fang
The command BD ring is used to configure functionality where the
underlying resources may be shared between different entities or being
too large to configure using direct registers (such as lookup tables).

Because the command BD and table formats of i.MX95 and LS1028A are very
different, the software processing logic is also different. So add
enetc4_setup_cbdr() and enetc4_teardown_cbdr() for ENETC v4 drivers.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Remove setup_cbdr() and teardown_cbdr() hooks
2. Rename enetc4_init_ntmp_priv() to enetc4_init_ntmp_user()
3. Modify the commit message
v6 changs:
Rebase the patch due to the changes of patch 1
---
 drivers/net/ethernet/freescale/enetc/enetc.h  |  9 -
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 39 ++-
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 38 ++
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 4ad4eb5c5a74..384e0bded87f 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,7 +275,10 @@ struct enetc_si {
 
struct net_device *ndev; /* back ref. */
 
-   struct enetc_cbdr cbd_ring;
+   union {
+   struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
+   struct ntmp_user ntmp_user; /* ENETC 4.1 and later */
+   };
 
int num_rx_rings; /* how many rings are available in the SI */
int num_tx_rings;
@@ -284,6 +288,7 @@ struct enetc_si {
u16 revision;
int hw_features;
const struct enetc_drvdata *drvdata;
+   const struct enetc_si_ops *ops;
 };
 
 #define ENETC_SI_ALIGN 32
@@ -493,6 +498,8 @@ void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv 
*priv);
 int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
 struct enetc_cbdr *cbdr);
 void enetc_teardown_cbdr(struct enetc_cbdr *cbdr);
+int enetc4_setup_cbdr(struct enetc_si *si);
+void enetc4_teardown_cbdr(struct enetc_si *si);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index 73ac8c6afb3a..175eebadde76 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -260,6 +260,21 @@ static void enetc4_configure_port(struct enetc_pf *pf)
enetc4_enable_trx(pf);
 }
 
+static int enetc4_init_ntmp_user(struct enetc_si *si)
+{
+   struct ntmp_user *user = &si->ntmp_user;
+
+   /* For ENETC 4.1, all table versions are 0 */
+   memset(&user->tbl, 0, sizeof(user->tbl));
+
+   return enetc4_setup_cbdr(si);
+}
+
+static void enetc4_free_ntmp_user(struct enetc_si *si)
+{
+   enetc4_teardown_cbdr(si);
+}
+
 static int enetc4_pf_init(struct enetc_pf *pf)
 {
struct device *dev = &pf->si->pdev->dev;
@@ -272,11 +287,22 @@ static int enetc4_pf_init(struct enetc_pf *pf)
return err;
}
 
+   err = enetc4_init_ntmp_user(pf->si);
+   if (err) {
+   dev_err(dev, "Failed to init CBDR\n");
+   return err;
+   }
+
enetc4_configure_port(pf);
 
return 0;
 }
 
+static void enetc4_pf_free(struct enetc_pf *pf)
+{
+   enetc4_free_ntmp_user(pf->si);
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -728,14 +754,25 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 
enetc_get_si_caps(si);
 
-   return enetc4_pf_netdev_create(si);
+   err = enetc4_pf_netdev_create(si);
+   if (err)
+   goto err_netdev_create;
+
+   return 0;
+
+err_netdev_create:
+   enetc4_pf_free(pf);
+
+   return err;
 }
 
 static void enetc4_pf_remove(struct pci_dev *pdev)
 {
struct enetc_si *si = pci_get_drvdata(pdev);
+   struct enetc_pf *pf = enetc_si_priv(si);
 
enetc4_pf_netdev_destroy(si);
+   enetc4_pf_free(pf);
 }
 
 static const struct pci_device_id enetc4_pf_id_table[] = {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c 
b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 20bfdf7fb4b4..71e4da530028 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -60,6 +60,44 @@ void enetc_teardown_cbdr(struct enetc_cbdr *cbdr)
 }
 EXPORT_SYMBOL_GPL(enetc_teardown_cbdr);
 
+int enetc4_setup_cbdr(struct enetc_si *si)
+{
+   struct ntmp_user *user = &si->ntmp_user;
+   struct device *dev = 

[PATCH v6 net-next 03/14] net: enetc: move generic MAC filtering interfaces to enetc-core

2025-04-28 Thread Wei Fang
Although only ENETC PF can access the MAC address filter table, the table
entries can specify MAC address filtering for one or more SIs based on
SI_BITMAP, which means that the table also supports MAC address filtering
for VFs.

Currently, only the ENETC v1 PF driver supports MAC address filtering. In
order to add the MAC address filtering support for the ENETC v4 PF driver
and VF driver in the future, the relevant generic interfaces are moved to
the enetc-core driver. This lays the basis for i.MX95 ENETC PF and VFs to
support MAC address filtering.

Signed-off-by: Wei Fang 
Reviewed-by: Vladimir Oltean 
---
v5 changes:
1. Keep mac_filter in struct enetc_pf
2. Modify the commit message
v6 changes:
No changes, only collect Reviewed-by tag
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 36 +++
 drivers/net/ethernet/freescale/enetc/enetc.h  | 15 
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 34 --
 .../net/ethernet/freescale/enetc/enetc_pf.h   | 11 --
 4 files changed, 51 insertions(+), 45 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 3ee52f4b1166..5a7af44e4594 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -36,6 +36,42 @@ static void enetc_change_preemptible_tcs(struct 
enetc_ndev_priv *priv,
enetc_mm_commit_preemptible_tcs(priv);
 }
 
+static int enetc_mac_addr_hash_idx(const u8 *addr)
+{
+   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
+   u64 mask = 0;
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 8; i++)
+   mask |= BIT_ULL(i * 6);
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
+
+   return res;
+}
+
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr)
+{
+   int idx = enetc_mac_addr_hash_idx(addr);
+
+   /* add hash table entry */
+   __set_bit(idx, filter->mac_hash_table);
+   filter->mac_addr_cnt++;
+}
+EXPORT_SYMBOL_GPL(enetc_add_mac_addr_ht_filter);
+
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
+{
+   filter->mac_addr_cnt = 0;
+
+   bitmap_zero(filter->mac_hash_table,
+   ENETC_MADDR_HASH_TBL_SZ);
+}
+EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+
 static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
 {
int num_tx_rings = priv->num_tx_rings;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 384e0bded87f..c3ebb32ce50c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -23,6 +23,18 @@
 
 #define ENETC_CBD_DATA_MEM_ALIGN 64
 
+#define ENETC_MADDR_HASH_TBL_SZ64
+
+enum enetc_mac_addr_type {UC, MC, MADDR_TYPE};
+
+struct enetc_mac_filter {
+   union {
+   char mac_addr[ETH_ALEN];
+   DECLARE_BITMAP(mac_hash_table, ENETC_MADDR_HASH_TBL_SZ);
+   };
+   int mac_addr_cnt;
+};
+
 struct enetc_tx_swbd {
union {
struct sk_buff *skb;
@@ -471,6 +483,9 @@ int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
 int enetc_configure_si(struct enetc_ndev_priv *priv);
 int enetc_get_driver_data(struct enetc_si *si);
+void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
+ const unsigned char *addr);
+void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 203862ec1114..f76403f7aee8 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -72,30 +72,6 @@ static void enetc_set_isol_vlan(struct enetc_hw *hw, int si, 
u16 vlan, u8 qos)
enetc_port_wr(hw, ENETC_PSIVLANR(si), val);
 }
 
-static int enetc_mac_addr_hash_idx(const u8 *addr)
-{
-   u64 fold = __swab64(ether_addr_to_u64(addr)) >> 16;
-   u64 mask = 0;
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 8; i++)
-   mask |= BIT_ULL(i * 6);
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight64(fold & (mask << i)) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
-{
-   filter->mac_addr_cnt = 0;
-
-   bitmap_zero(filter->mac_hash_table,
-   ENETC_MADDR_HASH_TBL_SZ);
-}
-
 static void enetc_add_mac_addr_em_filter(struct enetc_mac_filter *filter,
 const unsigned char *addr)
 {

[PATCH v6 net-next 05/14] net: enetc: add debugfs interface to dump MAC filter

2025-04-28 Thread Wei Fang
ENETC's MAC filter consists of hash MAC filter and exact MAC filter.
Hash MAC filter is a 64-bit entry hash table consisting of two 32-bit
registers. Exact MAC filter is implemented by configuring MAC address
filter table through command BD ring. The table is stored in ENETC's
internal memory and needs to be read through command BD ring. In order
to facilitate debugging, added a debugfs interface to get the relevant
information about MAC filter.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Replace is_en() with str_enabled_disabled()
2. Remove superfluous "Show" in the debug log
3. Remove keye variable from enetc_mac_filter_show()
v6: no changes
---
 drivers/net/ethernet/freescale/enetc/Makefile |  1 +
 drivers/net/ethernet/freescale/enetc/enetc.h  |  1 +
 .../ethernet/freescale/enetc/enetc4_debugfs.c | 90 +++
 .../ethernet/freescale/enetc/enetc4_debugfs.h | 20 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  |  4 +
 5 files changed, 116 insertions(+)
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
 create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_debugfs.h

diff --git a/drivers/net/ethernet/freescale/enetc/Makefile 
b/drivers/net/ethernet/freescale/enetc/Makefile
index 707a68e26971..f1c5ad45fd76 100644
--- a/drivers/net/ethernet/freescale/enetc/Makefile
+++ b/drivers/net/ethernet/freescale/enetc/Makefile
@@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o
 
 obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o
 nxp-enetc4-y := enetc4_pf.o
+nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o
 
 obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o
 fsl-enetc-vf-y := enetc_vf.o
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index 1573ff06fcf4..b53ecc882a90 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -304,6 +304,7 @@ struct enetc_si {
 
struct workqueue_struct *workqueue;
struct work_struct rx_mode_task;
+   struct dentry *debugfs_root;
 };
 
 #define ENETC_SI_ALIGN 32
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
new file mode 100644
index ..3479c0abe9e6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright 2025 NXP */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "enetc_pf.h"
+#include "enetc4_debugfs.h"
+
+static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   u32 hash_h, hash_l;
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIUMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIUMHFR1(i));
+   seq_printf(s, "SI %d unicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+
+   hash_l = enetc_port_rd(hw, ENETC4_PSIMMHFR0(i));
+   hash_h = enetc_port_rd(hw, ENETC4_PSIMMHFR1(i));
+   seq_printf(s, "SI %d multicast MAC hash filter: 0x%08x%08x\n",
+  i, hash_h, hash_l);
+}
+
+static int enetc_mac_filter_show(struct seq_file *s, void *data)
+{
+   struct enetc_si *si = s->private;
+   struct enetc_hw *hw = &si->hw;
+   struct maft_entry_data maft;
+   struct enetc_pf *pf;
+   int i, err, num_si;
+   u32 val;
+
+   pf = enetc_si_priv(si);
+   num_si = pf->caps.num_vsi + 1;
+
+   val = enetc_port_rd(hw, ENETC4_PSIPMMR);
+   for (i = 0; i < num_si; i++) {
+   seq_printf(s, "SI %d Unicast Promiscuous mode: %s\n", i,
+  str_enabled_disabled(PSIPMMR_SI_MAC_UP(i) & val));
+   seq_printf(s, "SI %d Multicast Promiscuous mode: %s\n", i,
+  str_enabled_disabled(PSIPMMR_SI_MAC_MP(i) & val));
+   }
+
+   /* MAC hash filter table */
+   for (i = 0; i < num_si; i++)
+   enetc_show_si_mac_hash_filter(s, i);
+
+   if (!pf->num_mfe)
+   return 0;
+
+   /* MAC address filter table */
+   seq_puts(s, "MAC address filter table\n");
+   for (i = 0; i < pf->num_mfe; i++) {
+   memset(&maft, 0, sizeof(maft));
+   err = ntmp_maft_query_entry(&si->ntmp_user, i, &maft);
+   if (err)
+   return err;
+
+   seq_printf(s, "Entry %d, MAC: %pM, SI bitmap: 0x%04x\n", i,
+  maft.keye.mac_addr, 
le16_to_cpu(maft.cfge.si_bitmap));
+   }
+
+   return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(enetc_mac_filter);
+
+void enetc_create_debugfs(struct enetc_si *si)
+{
+   struct net_device *ndev = si->ndev;
+   struct dentry *root;
+
+   root = debugfs_create_dir(netdev_name(ndev), NULL);
+   

[PATCH v6 net-next 12/14] net: enetc: move generic VLAN hash filter functions to enetc_pf_common.c

2025-04-28 Thread Wei Fang
The VLAN hash filters of ENETC v1 and v4 are basically the same, the only
difference is that the offset of the VLAN hash filter registers has been
changed in ENETC v4. So some functions like enetc_vlan_rx_add_vid() and
enetc_vlan_rx_del_vid() only need to be slightly modified to be reused
by ENETC v4. Currently, we just move these functions from enetc_pf.c to
enetc_pf_common.c. Appropriate modifications will be made for ENETC4 in
a subsequent patch.

Signed-off-by: Wei Fang 
---
v5 changes
Remove set_si_vlan_hash_filter() hook
v6: no changes
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 57 --
 .../freescale/enetc/enetc_pf_common.c | 60 +++
 .../freescale/enetc/enetc_pf_common.h |  2 +
 3 files changed, 62 insertions(+), 57 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index ae2dbd159ab4..6560bdbff287 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -216,63 +216,6 @@ static void enetc_pf_set_rx_mode(struct net_device *ndev)
enetc_port_wr(hw, ENETC_PSIPMR, psipmr);
 }
 
-static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
-unsigned long hash)
-{
-   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
-   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
-}
-
-static int enetc_vid_hash_idx(unsigned int vid)
-{
-   int res = 0;
-   int i;
-
-   for (i = 0; i < 6; i++)
-   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
-
-   return res;
-}
-
-static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
-{
-   int i;
-
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
-}
-
-static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
-   int idx;
-
-   __set_bit(vid, pf->active_vlans);
-
-   idx = enetc_vid_hash_idx(vid);
-   if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
-   return 0;
-}
-
-static int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_pf *pf = enetc_si_priv(priv->si);
-
-   __clear_bit(vid, pf->active_vlans);
-   enetc_refresh_vlan_ht_filter(pf);
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
-
-   return 0;
-}
-
 static void enetc_set_loopback(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a751862a70b1..ed8afd174c9e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -353,5 +353,65 @@ void enetc_set_default_rss_key(struct enetc_pf *pf)
 }
 EXPORT_SYMBOL_GPL(enetc_set_default_rss_key);
 
+static int enetc_vid_hash_idx(unsigned int vid)
+{
+   int res = 0;
+   int i;
+
+   for (i = 0; i < 6; i++)
+   res |= (hweight8(vid & (BIT(i) | BIT(i + 6))) & 0x1) << i;
+
+   return res;
+}
+
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
+{
+   int i;
+
+   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
+
+   __set_bit(hidx, pf->vlan_ht_filter);
+   }
+}
+
+static void enetc_set_vlan_ht_filter(struct enetc_hw *hw, int si_idx,
+unsigned long hash)
+{
+   enetc_port_wr(hw, ENETC_PSIVHFR0(si_idx), lower_32_bits(hash));
+   enetc_port_wr(hw, ENETC_PSIVHFR1(si_idx), upper_32_bits(hash));
+}
+
+int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_pf *pf = enetc_si_priv(priv->si);
+   int idx;
+
+   __set_bit(vid, pf->active_vlans);
+
+   idx = enetc_vid_hash_idx(vid);
+   if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(enetc_vlan_rx_add_vid);
+
+int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(nde

[PATCH v6 net-next 10/14] net: enetc: enable RSS feature by default

2025-04-28 Thread Wei Fang
Receive side scaling (RSS) is a network driver technology that enables
the efficient distribution of network receive processing across multiple
CPUs in multiprocessor systems. Therefore, it is better to enable RSS by
default so that the CPU load can be balanced and network performance can
be improved when then network is enabled.

Signed-off-by: Wei Fang 
---
v5 changes:
Just rebase it based on patch 9.
v6: no changes
---
 drivers/net/ethernet/freescale/enetc/enetc.c  | 31 ++-
 .../freescale/enetc/enetc_pf_common.c |  4 ++-
 .../net/ethernet/freescale/enetc/enetc_vf.c   |  4 ++-
 3 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index daea85cbf043..7e92dc0a9a49 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2430,6 +2430,20 @@ static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
 }
 
+static void enetc_set_rss(struct net_device *ndev, int en)
+{
+   struct enetc_ndev_priv *priv = netdev_priv(ndev);
+   struct enetc_hw *hw = &priv->si->hw;
+   u32 reg;
+
+   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
+
+   reg = enetc_rd(hw, ENETC_SIMR);
+   reg &= ~ENETC_SIMR_RSSE;
+   reg |= (en) ? ENETC_SIMR_RSSE : 0;
+   enetc_wr(hw, ENETC_SIMR, reg);
+}
+
 int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
struct enetc_si *si = priv->si;
@@ -2450,6 +2464,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
+
+   if (priv->ndev->features & NETIF_F_RXHASH)
+   enetc_set_rss(priv->ndev, true);
}
 
return 0;
@@ -3242,20 +3259,6 @@ struct net_device_stats *enetc_get_stats(struct 
net_device *ndev)
 }
 EXPORT_SYMBOL_GPL(enetc_get_stats);
 
-static void enetc_set_rss(struct net_device *ndev, int en)
-{
-   struct enetc_ndev_priv *priv = netdev_priv(ndev);
-   struct enetc_hw *hw = &priv->si->hw;
-   u32 reg;
-
-   enetc_wr(hw, ENETC_SIRBGCR, priv->num_rx_rings);
-
-   reg = enetc_rd(hw, ENETC_SIMR);
-   reg &= ~ENETC_SIMR_RSSE;
-   reg |= (en) ? ENETC_SIMR_RSSE : 0;
-   enetc_wr(hw, ENETC_SIMR, reg);
-}
-
 static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
 {
struct enetc_ndev_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index a302477c4de4..a751862a70b1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -128,8 +128,10 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct 
net_device *ndev,
if (si->hw_features & ENETC_SI_F_LSO)
priv->active_offloads |= ENETC_F_LSO;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* TODO: currently, i.MX95 ENETC driver does not support advanced 
features */
if (!is_enetc_rev1(si)) {
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index 4fafe4e18a37..f6aed0a1ad1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -155,8 +155,10 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, 
struct net_device *ndev,
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
  NETIF_F_TSO | NETIF_F_TSO6;
 
-   if (si->num_rss)
+   if (si->num_rss) {
ndev->hw_features |= NETIF_F_RXHASH;
+   ndev->features |= NETIF_F_RXHASH;
+   }
 
/* pick up primary MAC address from SI */
enetc_load_primary_mac_addr(&si->hw, ndev);
-- 
2.34.1




[PATCH v6 net-next 11/14] net: enetc: extract enetc_refresh_vlan_ht_filter()

2025-04-28 Thread Wei Fang
Extract the common function enetc_refresh_vlan_ht_filter() from
enetc_sync_vlan_ht_filter() so that it can be reused by the ENETC
v4 PF and VF drivers in the future.

Signed-off-by: Wei Fang 
---
v5: New patch
v6: no changes
---
 .../net/ethernet/freescale/enetc/enetc_pf.c   | 20 ---
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index 8f2616fd83d2..ae2dbd159ab4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -234,21 +234,16 @@ static int enetc_vid_hash_idx(unsigned int vid)
return res;
 }
 
-static void enetc_sync_vlan_ht_filter(struct enetc_pf *pf, bool rehash)
+static void enetc_refresh_vlan_ht_filter(struct enetc_pf *pf)
 {
int i;
 
-   if (rehash) {
-   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   bitmap_zero(pf->vlan_ht_filter, ENETC_VLAN_HT_SIZE);
+   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
+   int hidx = enetc_vid_hash_idx(i);
 
-   for_each_set_bit(i, pf->active_vlans, VLAN_N_VID) {
-   int hidx = enetc_vid_hash_idx(i);
-
-   __set_bit(hidx, pf->vlan_ht_filter);
-   }
+   __set_bit(hidx, pf->vlan_ht_filter);
}
-
-   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 }
 
 static int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid)
@@ -261,7 +256,7 @@ static int enetc_vlan_rx_add_vid(struct net_device *ndev, 
__be16 prot, u16 vid)
 
idx = enetc_vid_hash_idx(vid);
if (!__test_and_set_bit(idx, pf->vlan_ht_filter))
-   enetc_sync_vlan_ht_filter(pf, false);
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 
return 0;
 }
@@ -272,7 +267,8 @@ static int enetc_vlan_rx_del_vid(struct net_device *ndev, 
__be16 prot, u16 vid)
struct enetc_pf *pf = enetc_si_priv(priv->si);
 
__clear_bit(vid, pf->active_vlans);
-   enetc_sync_vlan_ht_filter(pf, true);
+   enetc_refresh_vlan_ht_filter(pf);
+   enetc_set_vlan_ht_filter(&pf->si->hw, 0, *pf->vlan_ht_filter);
 
return 0;
 }
-- 
2.34.1




[PATCH v6 net-next 08/14] net: enetc: add RSS support for i.MX95 ENETC PF

2025-04-28 Thread Wei Fang
Compared with LS1028A, there are two main differences: first, i.MX95
ENETC uses NTMP 2.0 to manage the RSS table, and second, the offset
of the RSS Key registers is different. Some modifications have been
made in the previous patches based on these differences to ensure that
the relevant interfaces are compatible with i.MX95. So it's time to
add RSS support to i.MX95 ENETC PF.

Signed-off-by: Wei Fang 
---
v5 changes:
1. Add comments for enetc4_get_rxnfc()
2. Modify enetc4_set_rss_table() and enetc4_get_rss_table()
v6: no changes
---
 drivers/net/ethernet/freescale/enetc/enetc.c  |  5 +-
 drivers/net/ethernet/freescale/enetc/enetc.h  |  2 +
 .../net/ethernet/freescale/enetc/enetc4_pf.c  | 15 ++
 .../net/ethernet/freescale/enetc/enetc_cbdr.c | 12 +
 .../ethernet/freescale/enetc/enetc_ethtool.c  | 47 ---
 .../freescale/enetc/enetc_pf_common.c |  6 +--
 6 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c 
b/drivers/net/ethernet/freescale/enetc/enetc.c
index 494f8f77bf4c..08762772c045 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2446,10 +2446,7 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
if (si->hw_features & ENETC_SI_F_LSO)
enetc_set_lso_flags_mask(hw);
 
-   /* TODO: RSS support for i.MX95 will be supported later, and the
-* is_enetc_rev1() condition will be removed
-*/
-   if (si->num_rss && is_enetc_rev1(si)) {
+   if (si->num_rss) {
err = enetc_setup_default_rss_table(si, priv->num_rx_rings);
if (err)
return err;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h 
b/drivers/net/ethernet/freescale/enetc/enetc.h
index e49c1626e7e5..7b24f1a5969a 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -541,6 +541,8 @@ void enetc_set_rss_key(struct enetc_si *si, const u8 
*bytes);
 int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count);
 int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd);
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count);
+int enetc4_set_rss_table(struct enetc_si *si, const u32 *table, int count);
 
 static inline void *enetc_cbd_alloc_data_mem(struct enetc_si *si,
 struct enetc_cbd *cbd,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c 
b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index d2a414c28c21..2d890f7bcc95 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -523,6 +523,14 @@ static void enetc4_pf_set_rx_mode(struct net_device *ndev)
queue_work(si->workqueue, &si->rx_mode_task);
 }
 
+static int enetc4_pf_set_features(struct net_device *ndev,
+ netdev_features_t features)
+{
+   enetc_set_features(ndev, features);
+
+   return 0;
+}
+
 static const struct net_device_ops enetc4_ndev_ops = {
.ndo_open   = enetc_open,
.ndo_stop   = enetc_close,
@@ -530,6 +538,7 @@ static const struct net_device_ops enetc4_ndev_ops = {
.ndo_get_stats  = enetc_get_stats,
.ndo_set_mac_address= enetc_pf_set_mac_addr,
.ndo_set_rx_mode= enetc4_pf_set_rx_mode,
+   .ndo_set_features   = enetc4_pf_set_features,
 };
 
 static struct phylink_pcs *
@@ -957,6 +966,11 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
free_netdev(ndev);
 }
 
+static const struct enetc_si_ops enetc4_psi_ops = {
+   .get_rss_table = enetc4_get_rss_table,
+   .set_rss_table = enetc4_set_rss_table,
+};
+
 static int enetc4_pf_probe(struct pci_dev *pdev,
   const struct pci_device_id *ent)
 {
@@ -981,6 +995,7 @@ static int enetc4_pf_probe(struct pci_dev *pdev,
 "Couldn't map PF only space\n");
 
si->revision = enetc_get_ip_revision(&si->hw);
+   si->ops = &enetc4_psi_ops;
err = enetc_get_driver_data(si);
if (err)
return dev_err_probe(dev, err,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c 
b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
index 71e4da530028..3d5f31879d5c 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c
@@ -294,3 +294,15 @@ int enetc_set_rss_table(struct enetc_si *si, const u32 
*table, int count)
return enetc_cmd_rss_table(si, (u32 *)table, count, false);
 }
 EXPORT_SYMBOL_GPL(enetc_set_rss_table);
+
+int enetc4_get_rss_table(struct enetc_si *si, u32 *table, int count)
+{
+   return ntmp_rsst_query_entry(&a

  1   2   >