All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S
@ 2022-01-05  3:15 Luiz Angelo Daros de Luca
  2022-01-05  3:15 ` [PATCH net-next v4 01/11] net: dsa: realtek-smi: move to subdirectory Luiz Angelo Daros de Luca
                   ` (11 more replies)
  0 siblings, 12 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w

The old realtek-smi driver was linking subdrivers into a single
realtek-smi.ko After this series, each subdriver will be an independent
module required by either realtek-smi (platform driver) or the new
realtek-mdio (mdio driver). Both interface drivers (SMI or MDIO) are
independent, and they might even work side-by-side, although it will be
difficult to find such device. The subdriver can be individually
selected but only at buildtime, saving some storage space for custom
embedded systems.

Existing realtek-smi devices continue to work untouched during the
tests. The realtek-smi was moved into a realtek subdirectory, but it
normally does not break things.

I couldn't identify a fixed relation between port numbers (0..9) and
external interfaces (0..2), and I'm not sure if it is fixed for each
chip version or a device configuration. Until there is more info about
it, there is a new port property "realtek,ext-int" that can inform the
external interface.

The rtl8365mb might now handle multiple CPU ports and extint ports not
used as CPU ports. RTL8367S has an SGMII external interface, but my test
device (TP-Link Archer C5v4) uses only the second RGMII interface. We
need a test device with more external ports to test these features.
The driver still cannot handle SGMII ports.

The rtl8365mb was tested with a MDIO-connected RTL8367S (TP-Link Acher
C5v4) and a SMI-connected RTL8365MB-VC switch (Asus RT-AC88U)

The rtl8366rb subdriver was not tested with this patch series, but it
was only slightly touched. It would be nice to test it, especially in an
MDIO-connected switch.

Best,

Luiz

Changelog:

v1-v2)
- formatting fixes
- dropped the rtl8365mb->rtl8367c rename
- other suggestions
	
v2-v3)
* realtek-mdio.c:
  - cleanup realtek-mdio.c (BUG_ON, comments and includes)   
  - check devm_regmap_init return code
  - removed realtek,rtl8366s string from realtek-mdio
* realtek-smi.c:
  - removed void* type cast
* rtl8365mb.c:
  - using macros to identify EXT interfaces
  - rename some extra extport->extint cases
  - allow extint as non cpu (not tested)
  - allow multple cpu ports (not tested)
  - dropped cpu info from struct rtl8365mb
* dropped dt-bindings changes (dealing outside this series)
* formatting issues fixed

v3-v4)
* fix cover message numbering 0/13 -> 0/11
* use static for realtek_mdio_read_reg
  - Reported-by: kernel test robot <lkp@intel.com>
* use dsa_switch_for_each_cpu_port
* mention realtek_smi_{variant,ops} to realtek_{variant,ops}
  in commit message



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

* [PATCH net-next v4 01/11] net: dsa: realtek-smi: move to subdirectory
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-05  3:15 ` [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv Luiz Angelo Daros de Luca
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
---
 MAINTAINERS                                   |  3 +--
 drivers/net/dsa/Kconfig                       | 12 +----------
 drivers/net/dsa/Makefile                      |  3 +--
 drivers/net/dsa/realtek/Kconfig               | 20 +++++++++++++++++++
 drivers/net/dsa/realtek/Makefile              |  3 +++
 .../net/dsa/{ => realtek}/realtek-smi-core.c  |  0
 .../net/dsa/{ => realtek}/realtek-smi-core.h  |  0
 drivers/net/dsa/{ => realtek}/rtl8365mb.c     |  0
 drivers/net/dsa/{ => realtek}/rtl8366.c       |  0
 drivers/net/dsa/{ => realtek}/rtl8366rb.c     |  0
 10 files changed, 26 insertions(+), 15 deletions(-)
 create mode 100644 drivers/net/dsa/realtek/Kconfig
 create mode 100644 drivers/net/dsa/realtek/Makefile
 rename drivers/net/dsa/{ => realtek}/realtek-smi-core.c (100%)
 rename drivers/net/dsa/{ => realtek}/realtek-smi-core.h (100%)
 rename drivers/net/dsa/{ => realtek}/rtl8365mb.c (100%)
 rename drivers/net/dsa/{ => realtek}/rtl8366.c (100%)
 rename drivers/net/dsa/{ => realtek}/rtl8366rb.c (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0b5fdb517c76..fc63d1e46798 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16161,8 +16161,7 @@ REALTEK RTL83xx SMI DSA ROUTER CHIPS
 M:	Linus Walleij <linus.walleij@linaro.org>
 S:	Maintained
 F:	Documentation/devicetree/bindings/net/dsa/realtek-smi.txt
-F:	drivers/net/dsa/realtek-smi*
-F:	drivers/net/dsa/rtl83*
+F:	drivers/net/dsa/realtek/*
 
 REALTEK WIRELESS DRIVER (rtlwifi family)
 M:	Ping-Ke Shih <pkshih@realtek.com>
diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 7b1457a6e327..1251caf0f638 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -67,17 +67,7 @@ config NET_DSA_QCA8K
 	  This enables support for the Qualcomm Atheros QCA8K Ethernet
 	  switch chips.
 
-config NET_DSA_REALTEK_SMI
-	tristate "Realtek SMI Ethernet switch family support"
-	select NET_DSA_TAG_RTL4_A
-	select NET_DSA_TAG_RTL8_4
-	select FIXED_PHY
-	select IRQ_DOMAIN
-	select REALTEK_PHY
-	select REGMAP
-	help
-	  This enables support for the Realtek SMI-based switch
-	  chips, currently only RTL8366RB.
+source "drivers/net/dsa/realtek/Kconfig"
 
 config NET_DSA_SMSC_LAN9303
 	tristate
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index 8da1569a34e6..e73838c12256 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -9,8 +9,6 @@ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
 obj-$(CONFIG_NET_DSA_MT7530)	+= mt7530.o
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_QCA8K)	+= qca8k.o
-obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
-realtek-smi-objs		:= realtek-smi-core.o rtl8366.o rtl8366rb.o rtl8365mb.o
 obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o
 obj-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o
 obj-$(CONFIG_NET_DSA_SMSC_LAN9303_MDIO) += lan9303_mdio.o
@@ -23,5 +21,6 @@ obj-y				+= microchip/
 obj-y				+= mv88e6xxx/
 obj-y				+= ocelot/
 obj-y				+= qca/
+obj-y				+= realtek/
 obj-y				+= sja1105/
 obj-y				+= xrs700x/
diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
new file mode 100644
index 000000000000..1c62212fb0ec
--- /dev/null
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menuconfig NET_DSA_REALTEK
+	tristate "Realtek Ethernet switch family support"
+	depends on NET_DSA
+	select NET_DSA_TAG_RTL4_A
+	select NET_DSA_TAG_RTL8_4
+	select FIXED_PHY
+	select IRQ_DOMAIN
+	select REALTEK_PHY
+	select REGMAP
+	help
+	  Select to enable support for Realtek Ethernet switch chips.
+
+config NET_DSA_REALTEK_SMI
+	tristate "Realtek SMI connected switch driver"
+	depends on NET_DSA_REALTEK
+	default y
+	help
+	  Select to enable support for registering switches connected
+	  through SMI.
diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
new file mode 100644
index 000000000000..323b921bfce0
--- /dev/null
+++ b/drivers/net/dsa/realtek/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_NET_DSA_REALTEK_SMI) 	+= realtek-smi.o
+realtek-smi-objs			:= realtek-smi-core.o rtl8366.o rtl8366rb.o rtl8365mb.o
diff --git a/drivers/net/dsa/realtek-smi-core.c b/drivers/net/dsa/realtek/realtek-smi-core.c
similarity index 100%
rename from drivers/net/dsa/realtek-smi-core.c
rename to drivers/net/dsa/realtek/realtek-smi-core.c
diff --git a/drivers/net/dsa/realtek-smi-core.h b/drivers/net/dsa/realtek/realtek-smi-core.h
similarity index 100%
rename from drivers/net/dsa/realtek-smi-core.h
rename to drivers/net/dsa/realtek/realtek-smi-core.h
diff --git a/drivers/net/dsa/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
similarity index 100%
rename from drivers/net/dsa/rtl8365mb.c
rename to drivers/net/dsa/realtek/rtl8365mb.c
diff --git a/drivers/net/dsa/rtl8366.c b/drivers/net/dsa/realtek/rtl8366.c
similarity index 100%
rename from drivers/net/dsa/rtl8366.c
rename to drivers/net/dsa/realtek/rtl8366.c
diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
similarity index 100%
rename from drivers/net/dsa/rtl8366rb.c
rename to drivers/net/dsa/realtek/rtl8366rb.c
-- 
2.34.0


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

* [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
  2022-01-05  3:15 ` [PATCH net-next v4 01/11] net: dsa: realtek-smi: move to subdirectory Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-07  3:42   ` Jakub Kicinski
                     ` (3 more replies)
  2022-01-05  3:15 ` [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi Luiz Angelo Daros de Luca
                   ` (9 subsequent siblings)
  11 siblings, 4 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

In preparation to adding other interfaces, the private data structure
was renamed to priv. Also, realtek_smi_variant and realtek_smi_ops
were renamed to realtek_variant and realtek_ops as those structs are
not SMI specific.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/net/dsa/realtek/realtek-smi-core.c    | 316 +++++++-------
 .../realtek/{realtek-smi-core.h => realtek.h} |  68 +--
 drivers/net/dsa/realtek/rtl8365mb.c           | 394 ++++++++---------
 drivers/net/dsa/realtek/rtl8366.c             | 164 +++----
 drivers/net/dsa/realtek/rtl8366rb.c           | 402 +++++++++---------
 5 files changed, 672 insertions(+), 672 deletions(-)
 rename drivers/net/dsa/realtek/{realtek-smi-core.h => realtek.h} (57%)

diff --git a/drivers/net/dsa/realtek/realtek-smi-core.c b/drivers/net/dsa/realtek/realtek-smi-core.c
index aae46ada8d83..7dfd86a99c24 100644
--- a/drivers/net/dsa/realtek/realtek-smi-core.c
+++ b/drivers/net/dsa/realtek/realtek-smi-core.c
@@ -40,105 +40,105 @@
 #include <linux/bitops.h>
 #include <linux/if_bridge.h>
 
-#include "realtek-smi-core.h"
+#include "realtek.h"
 
 #define REALTEK_SMI_ACK_RETRY_COUNT		5
 #define REALTEK_SMI_HW_STOP_DELAY		25	/* msecs */
 #define REALTEK_SMI_HW_START_DELAY		100	/* msecs */
 
-static inline void realtek_smi_clk_delay(struct realtek_smi *smi)
+static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
 {
-	ndelay(smi->clk_delay);
+	ndelay(priv->clk_delay);
 }
 
-static void realtek_smi_start(struct realtek_smi *smi)
+static void realtek_smi_start(struct realtek_priv *priv)
 {
 	/* Set GPIO pins to output mode, with initial state:
 	 * SCK = 0, SDA = 1
 	 */
-	gpiod_direction_output(smi->mdc, 0);
-	gpiod_direction_output(smi->mdio, 1);
-	realtek_smi_clk_delay(smi);
+	gpiod_direction_output(priv->mdc, 0);
+	gpiod_direction_output(priv->mdio, 1);
+	realtek_smi_clk_delay(priv);
 
 	/* CLK 1: 0 -> 1, 1 -> 0 */
-	gpiod_set_value(smi->mdc, 1);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdc, 0);
-	realtek_smi_clk_delay(smi);
+	gpiod_set_value(priv->mdc, 1);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdc, 0);
+	realtek_smi_clk_delay(priv);
 
 	/* CLK 2: */
-	gpiod_set_value(smi->mdc, 1);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdio, 0);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdc, 0);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdio, 1);
+	gpiod_set_value(priv->mdc, 1);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdio, 0);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdc, 0);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdio, 1);
 }
 
-static void realtek_smi_stop(struct realtek_smi *smi)
+static void realtek_smi_stop(struct realtek_priv *priv)
 {
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdio, 0);
-	gpiod_set_value(smi->mdc, 1);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdio, 1);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdc, 1);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdc, 0);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdc, 1);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdio, 0);
+	gpiod_set_value(priv->mdc, 1);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdio, 1);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdc, 1);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdc, 0);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdc, 1);
 
 	/* Add a click */
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdc, 0);
-	realtek_smi_clk_delay(smi);
-	gpiod_set_value(smi->mdc, 1);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdc, 0);
+	realtek_smi_clk_delay(priv);
+	gpiod_set_value(priv->mdc, 1);
 
 	/* Set GPIO pins to input mode */
-	gpiod_direction_input(smi->mdio);
-	gpiod_direction_input(smi->mdc);
+	gpiod_direction_input(priv->mdio);
+	gpiod_direction_input(priv->mdc);
 }
 
-static void realtek_smi_write_bits(struct realtek_smi *smi, u32 data, u32 len)
+static void realtek_smi_write_bits(struct realtek_priv *priv, u32 data, u32 len)
 {
 	for (; len > 0; len--) {
-		realtek_smi_clk_delay(smi);
+		realtek_smi_clk_delay(priv);
 
 		/* Prepare data */
-		gpiod_set_value(smi->mdio, !!(data & (1 << (len - 1))));
-		realtek_smi_clk_delay(smi);
+		gpiod_set_value(priv->mdio, !!(data & (1 << (len - 1))));
+		realtek_smi_clk_delay(priv);
 
 		/* Clocking */
-		gpiod_set_value(smi->mdc, 1);
-		realtek_smi_clk_delay(smi);
-		gpiod_set_value(smi->mdc, 0);
+		gpiod_set_value(priv->mdc, 1);
+		realtek_smi_clk_delay(priv);
+		gpiod_set_value(priv->mdc, 0);
 	}
 }
 
-static void realtek_smi_read_bits(struct realtek_smi *smi, u32 len, u32 *data)
+static void realtek_smi_read_bits(struct realtek_priv *priv, u32 len, u32 *data)
 {
-	gpiod_direction_input(smi->mdio);
+	gpiod_direction_input(priv->mdio);
 
 	for (*data = 0; len > 0; len--) {
 		u32 u;
 
-		realtek_smi_clk_delay(smi);
+		realtek_smi_clk_delay(priv);
 
 		/* Clocking */
-		gpiod_set_value(smi->mdc, 1);
-		realtek_smi_clk_delay(smi);
-		u = !!gpiod_get_value(smi->mdio);
-		gpiod_set_value(smi->mdc, 0);
+		gpiod_set_value(priv->mdc, 1);
+		realtek_smi_clk_delay(priv);
+		u = !!gpiod_get_value(priv->mdio);
+		gpiod_set_value(priv->mdc, 0);
 
 		*data |= (u << (len - 1));
 	}
 
-	gpiod_direction_output(smi->mdio, 0);
+	gpiod_direction_output(priv->mdio, 0);
 }
 
-static int realtek_smi_wait_for_ack(struct realtek_smi *smi)
+static int realtek_smi_wait_for_ack(struct realtek_priv *priv)
 {
 	int retry_cnt;
 
@@ -146,12 +146,12 @@ static int realtek_smi_wait_for_ack(struct realtek_smi *smi)
 	do {
 		u32 ack;
 
-		realtek_smi_read_bits(smi, 1, &ack);
+		realtek_smi_read_bits(priv, 1, &ack);
 		if (ack == 0)
 			break;
 
 		if (++retry_cnt > REALTEK_SMI_ACK_RETRY_COUNT) {
-			dev_err(smi->dev, "ACK timeout\n");
+			dev_err(priv->dev, "ACK timeout\n");
 			return -ETIMEDOUT;
 		}
 	} while (1);
@@ -159,131 +159,131 @@ static int realtek_smi_wait_for_ack(struct realtek_smi *smi)
 	return 0;
 }
 
-static int realtek_smi_write_byte(struct realtek_smi *smi, u8 data)
+static int realtek_smi_write_byte(struct realtek_priv *priv, u8 data)
 {
-	realtek_smi_write_bits(smi, data, 8);
-	return realtek_smi_wait_for_ack(smi);
+	realtek_smi_write_bits(priv, data, 8);
+	return realtek_smi_wait_for_ack(priv);
 }
 
-static int realtek_smi_write_byte_noack(struct realtek_smi *smi, u8 data)
+static int realtek_smi_write_byte_noack(struct realtek_priv *priv, u8 data)
 {
-	realtek_smi_write_bits(smi, data, 8);
+	realtek_smi_write_bits(priv, data, 8);
 	return 0;
 }
 
-static int realtek_smi_read_byte0(struct realtek_smi *smi, u8 *data)
+static int realtek_smi_read_byte0(struct realtek_priv *priv, u8 *data)
 {
 	u32 t;
 
 	/* Read data */
-	realtek_smi_read_bits(smi, 8, &t);
+	realtek_smi_read_bits(priv, 8, &t);
 	*data = (t & 0xff);
 
 	/* Send an ACK */
-	realtek_smi_write_bits(smi, 0x00, 1);
+	realtek_smi_write_bits(priv, 0x00, 1);
 
 	return 0;
 }
 
-static int realtek_smi_read_byte1(struct realtek_smi *smi, u8 *data)
+static int realtek_smi_read_byte1(struct realtek_priv *priv, u8 *data)
 {
 	u32 t;
 
 	/* Read data */
-	realtek_smi_read_bits(smi, 8, &t);
+	realtek_smi_read_bits(priv, 8, &t);
 	*data = (t & 0xff);
 
 	/* Send an ACK */
-	realtek_smi_write_bits(smi, 0x01, 1);
+	realtek_smi_write_bits(priv, 0x01, 1);
 
 	return 0;
 }
 
-static int realtek_smi_read_reg(struct realtek_smi *smi, u32 addr, u32 *data)
+static int realtek_smi_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
 {
 	unsigned long flags;
 	u8 lo = 0;
 	u8 hi = 0;
 	int ret;
 
-	spin_lock_irqsave(&smi->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 
-	realtek_smi_start(smi);
+	realtek_smi_start(priv);
 
 	/* Send READ command */
-	ret = realtek_smi_write_byte(smi, smi->cmd_read);
+	ret = realtek_smi_write_byte(priv, priv->cmd_read);
 	if (ret)
 		goto out;
 
 	/* Set ADDR[7:0] */
-	ret = realtek_smi_write_byte(smi, addr & 0xff);
+	ret = realtek_smi_write_byte(priv, addr & 0xff);
 	if (ret)
 		goto out;
 
 	/* Set ADDR[15:8] */
-	ret = realtek_smi_write_byte(smi, addr >> 8);
+	ret = realtek_smi_write_byte(priv, addr >> 8);
 	if (ret)
 		goto out;
 
 	/* Read DATA[7:0] */
-	realtek_smi_read_byte0(smi, &lo);
+	realtek_smi_read_byte0(priv, &lo);
 	/* Read DATA[15:8] */
-	realtek_smi_read_byte1(smi, &hi);
+	realtek_smi_read_byte1(priv, &hi);
 
 	*data = ((u32)lo) | (((u32)hi) << 8);
 
 	ret = 0;
 
  out:
-	realtek_smi_stop(smi);
-	spin_unlock_irqrestore(&smi->lock, flags);
+	realtek_smi_stop(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return ret;
 }
 
-static int realtek_smi_write_reg(struct realtek_smi *smi,
+static int realtek_smi_write_reg(struct realtek_priv *priv,
 				 u32 addr, u32 data, bool ack)
 {
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&smi->lock, flags);
+	spin_lock_irqsave(&priv->lock, flags);
 
-	realtek_smi_start(smi);
+	realtek_smi_start(priv);
 
 	/* Send WRITE command */
-	ret = realtek_smi_write_byte(smi, smi->cmd_write);
+	ret = realtek_smi_write_byte(priv, priv->cmd_write);
 	if (ret)
 		goto out;
 
 	/* Set ADDR[7:0] */
-	ret = realtek_smi_write_byte(smi, addr & 0xff);
+	ret = realtek_smi_write_byte(priv, addr & 0xff);
 	if (ret)
 		goto out;
 
 	/* Set ADDR[15:8] */
-	ret = realtek_smi_write_byte(smi, addr >> 8);
+	ret = realtek_smi_write_byte(priv, addr >> 8);
 	if (ret)
 		goto out;
 
 	/* Write DATA[7:0] */
-	ret = realtek_smi_write_byte(smi, data & 0xff);
+	ret = realtek_smi_write_byte(priv, data & 0xff);
 	if (ret)
 		goto out;
 
 	/* Write DATA[15:8] */
 	if (ack)
-		ret = realtek_smi_write_byte(smi, data >> 8);
+		ret = realtek_smi_write_byte(priv, data >> 8);
 	else
-		ret = realtek_smi_write_byte_noack(smi, data >> 8);
+		ret = realtek_smi_write_byte_noack(priv, data >> 8);
 	if (ret)
 		goto out;
 
 	ret = 0;
 
  out:
-	realtek_smi_stop(smi);
-	spin_unlock_irqrestore(&smi->lock, flags);
+	realtek_smi_stop(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return ret;
 }
@@ -292,10 +292,10 @@ static int realtek_smi_write_reg(struct realtek_smi *smi,
  * is when issueing soft reset. Since the device reset as soon as we write
  * that bit, no ACK will come back for natural reasons.
  */
-int realtek_smi_write_reg_noack(struct realtek_smi *smi, u32 addr,
+int realtek_smi_write_reg_noack(struct realtek_priv *priv, u32 addr,
 				u32 data)
 {
-	return realtek_smi_write_reg(smi, addr, data, false);
+	return realtek_smi_write_reg(priv, addr, data, false);
 }
 EXPORT_SYMBOL_GPL(realtek_smi_write_reg_noack);
 
@@ -303,16 +303,16 @@ EXPORT_SYMBOL_GPL(realtek_smi_write_reg_noack);
 
 static int realtek_smi_write(void *ctx, u32 reg, u32 val)
 {
-	struct realtek_smi *smi = ctx;
+	struct realtek_priv *priv = ctx;
 
-	return realtek_smi_write_reg(smi, reg, val, true);
+	return realtek_smi_write_reg(priv, reg, val, true);
 }
 
 static int realtek_smi_read(void *ctx, u32 reg, u32 *val)
 {
-	struct realtek_smi *smi = ctx;
+	struct realtek_priv *priv = ctx;
 
-	return realtek_smi_read_reg(smi, reg, val);
+	return realtek_smi_read_reg(priv, reg, val);
 }
 
 static const struct regmap_config realtek_smi_mdio_regmap_config = {
@@ -329,49 +329,49 @@ static const struct regmap_config realtek_smi_mdio_regmap_config = {
 
 static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
 {
-	struct realtek_smi *smi = bus->priv;
+	struct realtek_priv *priv = bus->priv;
 
-	return smi->ops->phy_read(smi, addr, regnum);
+	return priv->ops->phy_read(priv, addr, regnum);
 }
 
 static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
 				  u16 val)
 {
-	struct realtek_smi *smi = bus->priv;
+	struct realtek_priv *priv = bus->priv;
 
-	return smi->ops->phy_write(smi, addr, regnum, val);
+	return priv->ops->phy_write(priv, addr, regnum, val);
 }
 
-int realtek_smi_setup_mdio(struct realtek_smi *smi)
+int realtek_smi_setup_mdio(struct realtek_priv *priv)
 {
 	struct device_node *mdio_np;
 	int ret;
 
-	mdio_np = of_get_compatible_child(smi->dev->of_node, "realtek,smi-mdio");
+	mdio_np = of_get_compatible_child(priv->dev->of_node, "realtek,smi-mdio");
 	if (!mdio_np) {
-		dev_err(smi->dev, "no MDIO bus node\n");
+		dev_err(priv->dev, "no MDIO bus node\n");
 		return -ENODEV;
 	}
 
-	smi->slave_mii_bus = devm_mdiobus_alloc(smi->dev);
-	if (!smi->slave_mii_bus) {
+	priv->slave_mii_bus = devm_mdiobus_alloc(priv->dev);
+	if (!priv->slave_mii_bus) {
 		ret = -ENOMEM;
 		goto err_put_node;
 	}
-	smi->slave_mii_bus->priv = smi;
-	smi->slave_mii_bus->name = "SMI slave MII";
-	smi->slave_mii_bus->read = realtek_smi_mdio_read;
-	smi->slave_mii_bus->write = realtek_smi_mdio_write;
-	snprintf(smi->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
-		 smi->ds->index);
-	smi->slave_mii_bus->dev.of_node = mdio_np;
-	smi->slave_mii_bus->parent = smi->dev;
-	smi->ds->slave_mii_bus = smi->slave_mii_bus;
-
-	ret = devm_of_mdiobus_register(smi->dev, smi->slave_mii_bus, mdio_np);
+	priv->slave_mii_bus->priv = priv;
+	priv->slave_mii_bus->name = "SMI slave MII";
+	priv->slave_mii_bus->read = realtek_smi_mdio_read;
+	priv->slave_mii_bus->write = realtek_smi_mdio_write;
+	snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
+		 priv->ds->index);
+	priv->slave_mii_bus->dev.of_node = mdio_np;
+	priv->slave_mii_bus->parent = priv->dev;
+	priv->ds->slave_mii_bus = priv->slave_mii_bus;
+
+	ret = devm_of_mdiobus_register(priv->dev, priv->slave_mii_bus, mdio_np);
 	if (ret) {
-		dev_err(smi->dev, "unable to register MDIO bus %s\n",
-			smi->slave_mii_bus->id);
+		dev_err(priv->dev, "unable to register MDIO bus %s\n",
+			priv->slave_mii_bus->id);
 		goto err_put_node;
 	}
 
@@ -385,76 +385,76 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
 
 static int realtek_smi_probe(struct platform_device *pdev)
 {
-	const struct realtek_smi_variant *var;
+	const struct realtek_variant *var;
 	struct device *dev = &pdev->dev;
-	struct realtek_smi *smi;
+	struct realtek_priv *priv;
 	struct device_node *np;
 	int ret;
 
 	var = of_device_get_match_data(dev);
 	np = dev->of_node;
 
-	smi = devm_kzalloc(dev, sizeof(*smi) + var->chip_data_sz, GFP_KERNEL);
-	if (!smi)
+	priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
-	smi->chip_data = (void *)smi + sizeof(*smi);
-	smi->map = devm_regmap_init(dev, NULL, smi,
-				    &realtek_smi_mdio_regmap_config);
-	if (IS_ERR(smi->map)) {
-		ret = PTR_ERR(smi->map);
+	priv->chip_data = (void *)priv + sizeof(*priv);
+	priv->map = devm_regmap_init(dev, NULL, priv,
+				     &realtek_smi_mdio_regmap_config);
+	if (IS_ERR(priv->map)) {
+		ret = PTR_ERR(priv->map);
 		dev_err(dev, "regmap init failed: %d\n", ret);
 		return ret;
 	}
 
 	/* Link forward and backward */
-	smi->dev = dev;
-	smi->clk_delay = var->clk_delay;
-	smi->cmd_read = var->cmd_read;
-	smi->cmd_write = var->cmd_write;
-	smi->ops = var->ops;
+	priv->dev = dev;
+	priv->clk_delay = var->clk_delay;
+	priv->cmd_read = var->cmd_read;
+	priv->cmd_write = var->cmd_write;
+	priv->ops = var->ops;
 
-	dev_set_drvdata(dev, smi);
-	spin_lock_init(&smi->lock);
+	dev_set_drvdata(dev, priv);
+	spin_lock_init(&priv->lock);
 
 	/* TODO: if power is software controlled, set up any regulators here */
 
 	/* Assert then deassert RESET */
-	smi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
-	if (IS_ERR(smi->reset)) {
+	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(priv->reset)) {
 		dev_err(dev, "failed to get RESET GPIO\n");
-		return PTR_ERR(smi->reset);
+		return PTR_ERR(priv->reset);
 	}
 	msleep(REALTEK_SMI_HW_STOP_DELAY);
-	gpiod_set_value(smi->reset, 0);
+	gpiod_set_value(priv->reset, 0);
 	msleep(REALTEK_SMI_HW_START_DELAY);
 	dev_info(dev, "deasserted RESET\n");
 
 	/* Fetch MDIO pins */
-	smi->mdc = devm_gpiod_get_optional(dev, "mdc", GPIOD_OUT_LOW);
-	if (IS_ERR(smi->mdc))
-		return PTR_ERR(smi->mdc);
-	smi->mdio = devm_gpiod_get_optional(dev, "mdio", GPIOD_OUT_LOW);
-	if (IS_ERR(smi->mdio))
-		return PTR_ERR(smi->mdio);
+	priv->mdc = devm_gpiod_get_optional(dev, "mdc", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->mdc))
+		return PTR_ERR(priv->mdc);
+	priv->mdio = devm_gpiod_get_optional(dev, "mdio", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->mdio))
+		return PTR_ERR(priv->mdio);
 
-	smi->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
+	priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
 
-	ret = smi->ops->detect(smi);
+	ret = priv->ops->detect(priv);
 	if (ret) {
 		dev_err(dev, "unable to detect switch\n");
 		return ret;
 	}
 
-	smi->ds = devm_kzalloc(dev, sizeof(*smi->ds), GFP_KERNEL);
-	if (!smi->ds)
+	priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
+	if (!priv->ds)
 		return -ENOMEM;
 
-	smi->ds->dev = dev;
-	smi->ds->num_ports = smi->num_ports;
-	smi->ds->priv = smi;
+	priv->ds->dev = dev;
+	priv->ds->num_ports = priv->num_ports;
+	priv->ds->priv = priv;
 
-	smi->ds->ops = var->ds_ops;
-	ret = dsa_register_switch(smi->ds);
+	priv->ds->ops = var->ds_ops;
+	ret = dsa_register_switch(priv->ds);
 	if (ret) {
 		dev_err_probe(dev, ret, "unable to register switch\n");
 		return ret;
@@ -464,15 +464,15 @@ static int realtek_smi_probe(struct platform_device *pdev)
 
 static int realtek_smi_remove(struct platform_device *pdev)
 {
-	struct realtek_smi *smi = platform_get_drvdata(pdev);
+	struct realtek_priv *priv = platform_get_drvdata(pdev);
 
-	if (!smi)
+	if (!priv)
 		return 0;
 
-	dsa_unregister_switch(smi->ds);
-	if (smi->slave_mii_bus)
-		of_node_put(smi->slave_mii_bus->dev.of_node);
-	gpiod_set_value(smi->reset, 1);
+	dsa_unregister_switch(priv->ds);
+	if (priv->slave_mii_bus)
+		of_node_put(priv->slave_mii_bus->dev.of_node);
+	gpiod_set_value(priv->reset, 1);
 
 	platform_set_drvdata(pdev, NULL);
 
@@ -481,12 +481,12 @@ static int realtek_smi_remove(struct platform_device *pdev)
 
 static void realtek_smi_shutdown(struct platform_device *pdev)
 {
-	struct realtek_smi *smi = platform_get_drvdata(pdev);
+	struct realtek_priv *priv = platform_get_drvdata(pdev);
 
-	if (!smi)
+	if (!priv)
 		return;
 
-	dsa_switch_shutdown(smi->ds);
+	dsa_switch_shutdown(priv->ds);
 
 	platform_set_drvdata(pdev, NULL);
 }
diff --git a/drivers/net/dsa/realtek/realtek-smi-core.h b/drivers/net/dsa/realtek/realtek.h
similarity index 57%
rename from drivers/net/dsa/realtek/realtek-smi-core.h
rename to drivers/net/dsa/realtek/realtek.h
index 5bfa53e2480a..177fff90b8a6 100644
--- a/drivers/net/dsa/realtek/realtek-smi-core.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -13,7 +13,7 @@
 #include <linux/gpio/consumer.h>
 #include <net/dsa.h>
 
-struct realtek_smi_ops;
+struct realtek_ops;
 struct dentry;
 struct inode;
 struct file;
@@ -43,7 +43,7 @@ struct rtl8366_vlan_4k {
 	u8	fid;
 };
 
-struct realtek_smi {
+struct realtek_priv {
 	struct device		*dev;
 	struct gpio_desc	*reset;
 	struct gpio_desc	*mdc;
@@ -65,7 +65,7 @@ struct realtek_smi {
 	unsigned int		num_mib_counters;
 	struct rtl8366_mib_counter *mib_counters;
 
-	const struct realtek_smi_ops *ops;
+	const struct realtek_ops *ops;
 
 	int			vlan_enabled;
 	int			vlan4k_enabled;
@@ -75,40 +75,40 @@ struct realtek_smi {
 };
 
 /**
- * struct realtek_smi_ops - vtable for the per-SMI-chiptype operations
+ * struct realtek_ops - vtable for the per-SMI-chiptype operations
  * @detect: detects the chiptype
  */
-struct realtek_smi_ops {
-	int	(*detect)(struct realtek_smi *smi);
-	int	(*reset_chip)(struct realtek_smi *smi);
-	int	(*setup)(struct realtek_smi *smi);
-	void	(*cleanup)(struct realtek_smi *smi);
-	int	(*get_mib_counter)(struct realtek_smi *smi,
+struct realtek_ops {
+	int	(*detect)(struct realtek_priv *priv);
+	int	(*reset_chip)(struct realtek_priv *priv);
+	int	(*setup)(struct realtek_priv *priv);
+	void	(*cleanup)(struct realtek_priv *priv);
+	int	(*get_mib_counter)(struct realtek_priv *priv,
 				   int port,
 				   struct rtl8366_mib_counter *mib,
 				   u64 *mibvalue);
-	int	(*get_vlan_mc)(struct realtek_smi *smi, u32 index,
+	int	(*get_vlan_mc)(struct realtek_priv *priv, u32 index,
 			       struct rtl8366_vlan_mc *vlanmc);
-	int	(*set_vlan_mc)(struct realtek_smi *smi, u32 index,
+	int	(*set_vlan_mc)(struct realtek_priv *priv, u32 index,
 			       const struct rtl8366_vlan_mc *vlanmc);
-	int	(*get_vlan_4k)(struct realtek_smi *smi, u32 vid,
+	int	(*get_vlan_4k)(struct realtek_priv *priv, u32 vid,
 			       struct rtl8366_vlan_4k *vlan4k);
-	int	(*set_vlan_4k)(struct realtek_smi *smi,
+	int	(*set_vlan_4k)(struct realtek_priv *priv,
 			       const struct rtl8366_vlan_4k *vlan4k);
-	int	(*get_mc_index)(struct realtek_smi *smi, int port, int *val);
-	int	(*set_mc_index)(struct realtek_smi *smi, int port, int index);
-	bool	(*is_vlan_valid)(struct realtek_smi *smi, unsigned int vlan);
-	int	(*enable_vlan)(struct realtek_smi *smi, bool enable);
-	int	(*enable_vlan4k)(struct realtek_smi *smi, bool enable);
-	int	(*enable_port)(struct realtek_smi *smi, int port, bool enable);
-	int	(*phy_read)(struct realtek_smi *smi, int phy, int regnum);
-	int	(*phy_write)(struct realtek_smi *smi, int phy, int regnum,
+	int	(*get_mc_index)(struct realtek_priv *priv, int port, int *val);
+	int	(*set_mc_index)(struct realtek_priv *priv, int port, int index);
+	bool	(*is_vlan_valid)(struct realtek_priv *priv, unsigned int vlan);
+	int	(*enable_vlan)(struct realtek_priv *priv, bool enable);
+	int	(*enable_vlan4k)(struct realtek_priv *priv, bool enable);
+	int	(*enable_port)(struct realtek_priv *priv, int port, bool enable);
+	int	(*phy_read)(struct realtek_priv *priv, int phy, int regnum);
+	int	(*phy_write)(struct realtek_priv *priv, int phy, int regnum,
 			     u16 val);
 };
 
-struct realtek_smi_variant {
+struct realtek_variant {
 	const struct dsa_switch_ops *ds_ops;
-	const struct realtek_smi_ops *ops;
+	const struct realtek_ops *ops;
 	unsigned int clk_delay;
 	u8 cmd_read;
 	u8 cmd_write;
@@ -116,19 +116,19 @@ struct realtek_smi_variant {
 };
 
 /* SMI core calls */
-int realtek_smi_write_reg_noack(struct realtek_smi *smi, u32 addr,
+int realtek_smi_write_reg_noack(struct realtek_priv *priv, u32 addr,
 				u32 data);
-int realtek_smi_setup_mdio(struct realtek_smi *smi);
+int realtek_smi_setup_mdio(struct realtek_priv *priv);
 
 /* RTL8366 library helpers */
-int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used);
-int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
+int rtl8366_mc_is_used(struct realtek_priv *priv, int mc_index, int *used);
+int rtl8366_set_vlan(struct realtek_priv *priv, int vid, u32 member,
 		     u32 untag, u32 fid);
-int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
+int rtl8366_set_pvid(struct realtek_priv *priv, unsigned int port,
 		     unsigned int vid);
-int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable);
-int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable);
-int rtl8366_reset_vlan(struct realtek_smi *smi);
+int rtl8366_enable_vlan4k(struct realtek_priv *priv, bool enable);
+int rtl8366_enable_vlan(struct realtek_priv *priv, bool enable);
+int rtl8366_reset_vlan(struct realtek_priv *priv);
 int rtl8366_vlan_add(struct dsa_switch *ds, int port,
 		     const struct switchdev_obj_port_vlan *vlan,
 		     struct netlink_ext_ack *extack);
@@ -139,7 +139,7 @@ void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
 int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset);
 void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
 
-extern const struct realtek_smi_variant rtl8366rb_variant;
-extern const struct realtek_smi_variant rtl8365mb_variant;
+extern const struct realtek_variant rtl8366rb_variant;
+extern const struct realtek_variant rtl8365mb_variant;
 
 #endif /*  _REALTEK_SMI_H */
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 3b729544798b..6b8797ba80c6 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -99,7 +99,7 @@
 #include <linux/regmap.h>
 #include <linux/if_bridge.h>
 
-#include "realtek-smi-core.h"
+#include "realtek.h"
 
 /* Chip-specific data and limits */
 #define RTL8365MB_CHIP_ID_8365MB_VC		0x6367
@@ -516,7 +516,7 @@ struct rtl8365mb_cpu {
 
 /**
  * struct rtl8365mb_port - private per-port data
- * @smi: pointer to parent realtek_smi data
+ * @priv: pointer to parent realtek_priv data
  * @index: DSA port index, same as dsa_port::index
  * @stats: link statistics populated by rtl8365mb_stats_poll, ready for atomic
  *         access via rtl8365mb_get_stats64
@@ -524,7 +524,7 @@ struct rtl8365mb_cpu {
  * @mib_work: delayed work for polling MIB counters
  */
 struct rtl8365mb_port {
-	struct realtek_smi *smi;
+	struct realtek_priv *priv;
 	unsigned int index;
 	struct rtnl_link_stats64 stats;
 	spinlock_t stats_lock;
@@ -533,7 +533,7 @@ struct rtl8365mb_port {
 
 /**
  * struct rtl8365mb - private chip-specific driver data
- * @smi: pointer to parent realtek_smi data
+ * @priv: pointer to parent realtek_priv data
  * @irq: registered IRQ or zero
  * @chip_id: chip identifier
  * @chip_ver: chip silicon revision
@@ -548,7 +548,7 @@ struct rtl8365mb_port {
  * Private data for this driver.
  */
 struct rtl8365mb {
-	struct realtek_smi *smi;
+	struct realtek_priv *priv;
 	int irq;
 	u32 chip_id;
 	u32 chip_ver;
@@ -561,16 +561,16 @@ struct rtl8365mb {
 	size_t jam_size;
 };
 
-static int rtl8365mb_phy_poll_busy(struct realtek_smi *smi)
+static int rtl8365mb_phy_poll_busy(struct realtek_priv *priv)
 {
 	u32 val;
 
-	return regmap_read_poll_timeout(smi->map,
+	return regmap_read_poll_timeout(priv->map,
 					RTL8365MB_INDIRECT_ACCESS_STATUS_REG,
 					val, !val, 10, 100);
 }
 
-static int rtl8365mb_phy_ocp_prepare(struct realtek_smi *smi, int phy,
+static int rtl8365mb_phy_ocp_prepare(struct realtek_priv *priv, int phy,
 				     u32 ocp_addr)
 {
 	u32 val;
@@ -579,7 +579,7 @@ static int rtl8365mb_phy_ocp_prepare(struct realtek_smi *smi, int phy,
 	/* Set OCP prefix */
 	val = FIELD_GET(RTL8365MB_PHY_OCP_ADDR_PREFIX_MASK, ocp_addr);
 	ret = regmap_update_bits(
-		smi->map, RTL8365MB_GPHY_OCP_MSB_0_REG,
+		priv->map, RTL8365MB_GPHY_OCP_MSB_0_REG,
 		RTL8365MB_GPHY_OCP_MSB_0_CFG_CPU_OCPADR_MASK,
 		FIELD_PREP(RTL8365MB_GPHY_OCP_MSB_0_CFG_CPU_OCPADR_MASK, val));
 	if (ret)
@@ -592,7 +592,7 @@ static int rtl8365mb_phy_ocp_prepare(struct realtek_smi *smi, int phy,
 			  ocp_addr >> 1);
 	val |= FIELD_PREP(RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_9_6_MASK,
 			  ocp_addr >> 6);
-	ret = regmap_write(smi->map, RTL8365MB_INDIRECT_ACCESS_ADDRESS_REG,
+	ret = regmap_write(priv->map, RTL8365MB_INDIRECT_ACCESS_ADDRESS_REG,
 			   val);
 	if (ret)
 		return ret;
@@ -600,17 +600,17 @@ static int rtl8365mb_phy_ocp_prepare(struct realtek_smi *smi, int phy,
 	return 0;
 }
 
-static int rtl8365mb_phy_ocp_read(struct realtek_smi *smi, int phy,
+static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
 				  u32 ocp_addr, u16 *data)
 {
 	u32 val;
 	int ret;
 
-	ret = rtl8365mb_phy_poll_busy(smi);
+	ret = rtl8365mb_phy_poll_busy(priv);
 	if (ret)
 		return ret;
 
-	ret = rtl8365mb_phy_ocp_prepare(smi, phy, ocp_addr);
+	ret = rtl8365mb_phy_ocp_prepare(priv, phy, ocp_addr);
 	if (ret)
 		return ret;
 
@@ -619,16 +619,16 @@ static int rtl8365mb_phy_ocp_read(struct realtek_smi *smi, int phy,
 			 RTL8365MB_INDIRECT_ACCESS_CTRL_CMD_VALUE) |
 	      FIELD_PREP(RTL8365MB_INDIRECT_ACCESS_CTRL_RW_MASK,
 			 RTL8365MB_INDIRECT_ACCESS_CTRL_RW_READ);
-	ret = regmap_write(smi->map, RTL8365MB_INDIRECT_ACCESS_CTRL_REG, val);
+	ret = regmap_write(priv->map, RTL8365MB_INDIRECT_ACCESS_CTRL_REG, val);
 	if (ret)
 		return ret;
 
-	ret = rtl8365mb_phy_poll_busy(smi);
+	ret = rtl8365mb_phy_poll_busy(priv);
 	if (ret)
 		return ret;
 
 	/* Get PHY register data */
-	ret = regmap_read(smi->map, RTL8365MB_INDIRECT_ACCESS_READ_DATA_REG,
+	ret = regmap_read(priv->map, RTL8365MB_INDIRECT_ACCESS_READ_DATA_REG,
 			  &val);
 	if (ret)
 		return ret;
@@ -638,22 +638,22 @@ static int rtl8365mb_phy_ocp_read(struct realtek_smi *smi, int phy,
 	return 0;
 }
 
-static int rtl8365mb_phy_ocp_write(struct realtek_smi *smi, int phy,
+static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
 				   u32 ocp_addr, u16 data)
 {
 	u32 val;
 	int ret;
 
-	ret = rtl8365mb_phy_poll_busy(smi);
+	ret = rtl8365mb_phy_poll_busy(priv);
 	if (ret)
 		return ret;
 
-	ret = rtl8365mb_phy_ocp_prepare(smi, phy, ocp_addr);
+	ret = rtl8365mb_phy_ocp_prepare(priv, phy, ocp_addr);
 	if (ret)
 		return ret;
 
 	/* Set PHY register data */
-	ret = regmap_write(smi->map, RTL8365MB_INDIRECT_ACCESS_WRITE_DATA_REG,
+	ret = regmap_write(priv->map, RTL8365MB_INDIRECT_ACCESS_WRITE_DATA_REG,
 			   data);
 	if (ret)
 		return ret;
@@ -663,18 +663,18 @@ static int rtl8365mb_phy_ocp_write(struct realtek_smi *smi, int phy,
 			 RTL8365MB_INDIRECT_ACCESS_CTRL_CMD_VALUE) |
 	      FIELD_PREP(RTL8365MB_INDIRECT_ACCESS_CTRL_RW_MASK,
 			 RTL8365MB_INDIRECT_ACCESS_CTRL_RW_WRITE);
-	ret = regmap_write(smi->map, RTL8365MB_INDIRECT_ACCESS_CTRL_REG, val);
+	ret = regmap_write(priv->map, RTL8365MB_INDIRECT_ACCESS_CTRL_REG, val);
 	if (ret)
 		return ret;
 
-	ret = rtl8365mb_phy_poll_busy(smi);
+	ret = rtl8365mb_phy_poll_busy(priv);
 	if (ret)
 		return ret;
 
 	return 0;
 }
 
-static int rtl8365mb_phy_read(struct realtek_smi *smi, int phy, int regnum)
+static int rtl8365mb_phy_read(struct realtek_priv *priv, int phy, int regnum)
 {
 	u32 ocp_addr;
 	u16 val;
@@ -688,21 +688,21 @@ static int rtl8365mb_phy_read(struct realtek_smi *smi, int phy, int regnum)
 
 	ocp_addr = RTL8365MB_PHY_OCP_ADDR_PHYREG_BASE + regnum * 2;
 
-	ret = rtl8365mb_phy_ocp_read(smi, phy, ocp_addr, &val);
+	ret = rtl8365mb_phy_ocp_read(priv, phy, ocp_addr, &val);
 	if (ret) {
-		dev_err(smi->dev,
+		dev_err(priv->dev,
 			"failed to read PHY%d reg %02x @ %04x, ret %d\n", phy,
 			regnum, ocp_addr, ret);
 		return ret;
 	}
 
-	dev_dbg(smi->dev, "read PHY%d register 0x%02x @ %04x, val <- %04x\n",
+	dev_dbg(priv->dev, "read PHY%d register 0x%02x @ %04x, val <- %04x\n",
 		phy, regnum, ocp_addr, val);
 
 	return val;
 }
 
-static int rtl8365mb_phy_write(struct realtek_smi *smi, int phy, int regnum,
+static int rtl8365mb_phy_write(struct realtek_priv *priv, int phy, int regnum,
 			       u16 val)
 {
 	u32 ocp_addr;
@@ -716,15 +716,15 @@ static int rtl8365mb_phy_write(struct realtek_smi *smi, int phy, int regnum,
 
 	ocp_addr = RTL8365MB_PHY_OCP_ADDR_PHYREG_BASE + regnum * 2;
 
-	ret = rtl8365mb_phy_ocp_write(smi, phy, ocp_addr, val);
+	ret = rtl8365mb_phy_ocp_write(priv, phy, ocp_addr, val);
 	if (ret) {
-		dev_err(smi->dev,
+		dev_err(priv->dev,
 			"failed to write PHY%d reg %02x @ %04x, ret %d\n", phy,
 			regnum, ocp_addr, ret);
 		return ret;
 	}
 
-	dev_dbg(smi->dev, "write PHY%d register 0x%02x @ %04x, val -> %04x\n",
+	dev_dbg(priv->dev, "write PHY%d register 0x%02x @ %04x, val -> %04x\n",
 		phy, regnum, ocp_addr, val);
 
 	return 0;
@@ -737,7 +737,7 @@ rtl8365mb_get_tag_protocol(struct dsa_switch *ds, int port,
 	return DSA_TAG_PROTO_RTL8_4;
 }
 
-static int rtl8365mb_ext_config_rgmii(struct realtek_smi *smi, int port,
+static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port,
 				      phy_interface_t interface)
 {
 	struct device_node *dn;
@@ -748,14 +748,14 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_smi *smi, int port,
 	u32 val;
 	int ret;
 
-	if (port == smi->cpu_port) {
+	if (port == priv->cpu_port) {
 		ext_port = 1;
 	} else {
-		dev_err(smi->dev, "only one EXT port is currently supported\n");
+		dev_err(priv->dev, "only one EXT port is currently supported\n");
 		return -EINVAL;
 	}
 
-	dp = dsa_to_port(smi->ds, port);
+	dp = dsa_to_port(priv->ds, port);
 	dn = dp->dn;
 
 	/* Set the RGMII TX/RX delay
@@ -786,7 +786,7 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_smi *smi, int port,
 		if (val == 0 || val == 2)
 			tx_delay = val / 2;
 		else
-			dev_warn(smi->dev,
+			dev_warn(priv->dev,
 				 "EXT port TX delay must be 0 or 2 ns\n");
 	}
 
@@ -796,12 +796,12 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_smi *smi, int port,
 		if (val <= 7)
 			rx_delay = val;
 		else
-			dev_warn(smi->dev,
+			dev_warn(priv->dev,
 				 "EXT port RX delay must be 0 to 2.1 ns\n");
 	}
 
 	ret = regmap_update_bits(
-		smi->map, RTL8365MB_EXT_RGMXF_REG(ext_port),
+		priv->map, RTL8365MB_EXT_RGMXF_REG(ext_port),
 		RTL8365MB_EXT_RGMXF_TXDELAY_MASK |
 			RTL8365MB_EXT_RGMXF_RXDELAY_MASK,
 		FIELD_PREP(RTL8365MB_EXT_RGMXF_TXDELAY_MASK, tx_delay) |
@@ -810,7 +810,7 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_smi *smi, int port,
 		return ret;
 
 	ret = regmap_update_bits(
-		smi->map, RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(ext_port),
+		priv->map, RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(ext_port),
 		RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(ext_port),
 		RTL8365MB_EXT_PORT_MODE_RGMII
 			<< RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_OFFSET(
@@ -821,7 +821,7 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_smi *smi, int port,
 	return 0;
 }
 
-static int rtl8365mb_ext_config_forcemode(struct realtek_smi *smi, int port,
+static int rtl8365mb_ext_config_forcemode(struct realtek_priv *priv, int port,
 					  bool link, int speed, int duplex,
 					  bool tx_pause, bool rx_pause)
 {
@@ -834,10 +834,10 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_smi *smi, int port,
 	int val;
 	int ret;
 
-	if (port == smi->cpu_port) {
+	if (port == priv->cpu_port) {
 		ext_port = 1;
 	} else {
-		dev_err(smi->dev, "only one EXT port is currently supported\n");
+		dev_err(priv->dev, "only one EXT port is currently supported\n");
 		return -EINVAL;
 	}
 
@@ -854,7 +854,7 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_smi *smi, int port,
 		} else if (speed == SPEED_10) {
 			r_speed = RTL8365MB_PORT_SPEED_10M;
 		} else {
-			dev_err(smi->dev, "unsupported port speed %s\n",
+			dev_err(priv->dev, "unsupported port speed %s\n",
 				phy_speed_to_str(speed));
 			return -EINVAL;
 		}
@@ -864,7 +864,7 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_smi *smi, int port,
 		} else if (duplex == DUPLEX_HALF) {
 			r_duplex = 0;
 		} else {
-			dev_err(smi->dev, "unsupported duplex %s\n",
+			dev_err(priv->dev, "unsupported duplex %s\n",
 				phy_duplex_to_str(duplex));
 			return -EINVAL;
 		}
@@ -886,7 +886,7 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_smi *smi, int port,
 	      FIELD_PREP(RTL8365MB_DIGITAL_INTERFACE_FORCE_DUPLEX_MASK,
 			 r_duplex) |
 	      FIELD_PREP(RTL8365MB_DIGITAL_INTERFACE_FORCE_SPEED_MASK, r_speed);
-	ret = regmap_write(smi->map,
+	ret = regmap_write(priv->map,
 			   RTL8365MB_DIGITAL_INTERFACE_FORCE_REG(ext_port),
 			   val);
 	if (ret)
@@ -916,7 +916,7 @@ static void rtl8365mb_phylink_validate(struct dsa_switch *ds, int port,
 				       unsigned long *supported,
 				       struct phylink_link_state *state)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0 };
 
 	/* include/linux/phylink.h says:
@@ -925,7 +925,7 @@ static void rtl8365mb_phylink_validate(struct dsa_switch *ds, int port,
 	 */
 	if (state->interface != PHY_INTERFACE_MODE_NA &&
 	    !rtl8365mb_phy_mode_supported(ds, port, state->interface)) {
-		dev_err(smi->dev, "phy mode %s is unsupported on port %d\n",
+		dev_err(priv->dev, "phy mode %s is unsupported on port %d\n",
 			phy_modes(state->interface), port);
 		linkmode_zero(supported);
 		return;
@@ -951,26 +951,26 @@ static void rtl8365mb_phylink_mac_config(struct dsa_switch *ds, int port,
 					 unsigned int mode,
 					 const struct phylink_link_state *state)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int ret;
 
 	if (!rtl8365mb_phy_mode_supported(ds, port, state->interface)) {
-		dev_err(smi->dev, "phy mode %s is unsupported on port %d\n",
+		dev_err(priv->dev, "phy mode %s is unsupported on port %d\n",
 			phy_modes(state->interface), port);
 		return;
 	}
 
 	if (mode != MLO_AN_PHY && mode != MLO_AN_FIXED) {
-		dev_err(smi->dev,
+		dev_err(priv->dev,
 			"port %d supports only conventional PHY or fixed-link\n",
 			port);
 		return;
 	}
 
 	if (phy_interface_mode_is_rgmii(state->interface)) {
-		ret = rtl8365mb_ext_config_rgmii(smi, port, state->interface);
+		ret = rtl8365mb_ext_config_rgmii(priv, port, state->interface);
 		if (ret)
-			dev_err(smi->dev,
+			dev_err(priv->dev,
 				"failed to configure RGMII mode on port %d: %d\n",
 				port, ret);
 		return;
@@ -985,20 +985,20 @@ static void rtl8365mb_phylink_mac_link_down(struct dsa_switch *ds, int port,
 					    unsigned int mode,
 					    phy_interface_t interface)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb_port *p;
 	struct rtl8365mb *mb;
 	int ret;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 	p = &mb->ports[port];
 	cancel_delayed_work_sync(&p->mib_work);
 
 	if (phy_interface_mode_is_rgmii(interface)) {
-		ret = rtl8365mb_ext_config_forcemode(smi, port, false, 0, 0,
+		ret = rtl8365mb_ext_config_forcemode(priv, port, false, 0, 0,
 						     false, false);
 		if (ret)
-			dev_err(smi->dev,
+			dev_err(priv->dev,
 				"failed to reset forced mode on port %d: %d\n",
 				port, ret);
 
@@ -1013,21 +1013,21 @@ static void rtl8365mb_phylink_mac_link_up(struct dsa_switch *ds, int port,
 					  int duplex, bool tx_pause,
 					  bool rx_pause)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb_port *p;
 	struct rtl8365mb *mb;
 	int ret;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 	p = &mb->ports[port];
 	schedule_delayed_work(&p->mib_work, 0);
 
 	if (phy_interface_mode_is_rgmii(interface)) {
-		ret = rtl8365mb_ext_config_forcemode(smi, port, true, speed,
+		ret = rtl8365mb_ext_config_forcemode(priv, port, true, speed,
 						     duplex, tx_pause,
 						     rx_pause);
 		if (ret)
-			dev_err(smi->dev,
+			dev_err(priv->dev,
 				"failed to force mode on port %d: %d\n", port,
 				ret);
 
@@ -1038,7 +1038,7 @@ static void rtl8365mb_phylink_mac_link_up(struct dsa_switch *ds, int port,
 static void rtl8365mb_port_stp_state_set(struct dsa_switch *ds, int port,
 					 u8 state)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	enum rtl8365mb_stp_state val;
 	int msti = 0;
 
@@ -1057,36 +1057,36 @@ static void rtl8365mb_port_stp_state_set(struct dsa_switch *ds, int port,
 		val = RTL8365MB_STP_STATE_FORWARDING;
 		break;
 	default:
-		dev_err(smi->dev, "invalid STP state: %u\n", state);
+		dev_err(priv->dev, "invalid STP state: %u\n", state);
 		return;
 	}
 
-	regmap_update_bits(smi->map, RTL8365MB_MSTI_CTRL_REG(msti, port),
+	regmap_update_bits(priv->map, RTL8365MB_MSTI_CTRL_REG(msti, port),
 			   RTL8365MB_MSTI_CTRL_PORT_STATE_MASK(port),
 			   val << RTL8365MB_MSTI_CTRL_PORT_STATE_OFFSET(port));
 }
 
-static int rtl8365mb_port_set_learning(struct realtek_smi *smi, int port,
+static int rtl8365mb_port_set_learning(struct realtek_priv *priv, int port,
 				       bool enable)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 
 	/* Enable/disable learning by limiting the number of L2 addresses the
 	 * port can learn. Realtek documentation states that a limit of zero
 	 * disables learning. When enabling learning, set it to the chip's
 	 * maximum.
 	 */
-	return regmap_write(smi->map, RTL8365MB_LUT_PORT_LEARN_LIMIT_REG(port),
+	return regmap_write(priv->map, RTL8365MB_LUT_PORT_LEARN_LIMIT_REG(port),
 			    enable ? mb->learn_limit_max : 0);
 }
 
-static int rtl8365mb_port_set_isolation(struct realtek_smi *smi, int port,
+static int rtl8365mb_port_set_isolation(struct realtek_priv *priv, int port,
 					u32 mask)
 {
-	return regmap_write(smi->map, RTL8365MB_PORT_ISOLATION_REG(port), mask);
+	return regmap_write(priv->map, RTL8365MB_PORT_ISOLATION_REG(port), mask);
 }
 
-static int rtl8365mb_mib_counter_read(struct realtek_smi *smi, int port,
+static int rtl8365mb_mib_counter_read(struct realtek_priv *priv, int port,
 				      u32 offset, u32 length, u64 *mibvalue)
 {
 	u64 tmpvalue = 0;
@@ -1098,13 +1098,13 @@ static int rtl8365mb_mib_counter_read(struct realtek_smi *smi, int port,
 	 * and then poll the control register before reading the value from some
 	 * counter registers.
 	 */
-	ret = regmap_write(smi->map, RTL8365MB_MIB_ADDRESS_REG,
+	ret = regmap_write(priv->map, RTL8365MB_MIB_ADDRESS_REG,
 			   RTL8365MB_MIB_ADDRESS(port, offset));
 	if (ret)
 		return ret;
 
 	/* Poll for completion */
-	ret = regmap_read_poll_timeout(smi->map, RTL8365MB_MIB_CTRL0_REG, val,
+	ret = regmap_read_poll_timeout(priv->map, RTL8365MB_MIB_CTRL0_REG, val,
 				       !(val & RTL8365MB_MIB_CTRL0_BUSY_MASK),
 				       10, 100);
 	if (ret)
@@ -1126,7 +1126,7 @@ static int rtl8365mb_mib_counter_read(struct realtek_smi *smi, int port,
 
 	/* Read the MIB counter 16 bits at a time */
 	for (i = 0; i < length; i++) {
-		ret = regmap_read(smi->map,
+		ret = regmap_read(priv->map,
 				  RTL8365MB_MIB_COUNTER_REG(offset - i), &val);
 		if (ret)
 			return ret;
@@ -1142,21 +1142,21 @@ static int rtl8365mb_mib_counter_read(struct realtek_smi *smi, int port,
 
 static void rtl8365mb_get_ethtool_stats(struct dsa_switch *ds, int port, u64 *data)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb *mb;
 	int ret;
 	int i;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 
 	mutex_lock(&mb->mib_lock);
 	for (i = 0; i < RTL8365MB_MIB_END; i++) {
 		struct rtl8365mb_mib_counter *mib = &rtl8365mb_mib_counters[i];
 
-		ret = rtl8365mb_mib_counter_read(smi, port, mib->offset,
+		ret = rtl8365mb_mib_counter_read(priv, port, mib->offset,
 						 mib->length, &data[i]);
 		if (ret) {
-			dev_err(smi->dev,
+			dev_err(priv->dev,
 				"failed to read port %d counters: %d\n", port,
 				ret);
 			break;
@@ -1190,15 +1190,15 @@ static int rtl8365mb_get_sset_count(struct dsa_switch *ds, int port, int sset)
 static void rtl8365mb_get_phy_stats(struct dsa_switch *ds, int port,
 				    struct ethtool_eth_phy_stats *phy_stats)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb_mib_counter *mib;
 	struct rtl8365mb *mb;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 	mib = &rtl8365mb_mib_counters[RTL8365MB_MIB_dot3StatsSymbolErrors];
 
 	mutex_lock(&mb->mib_lock);
-	rtl8365mb_mib_counter_read(smi, port, mib->offset, mib->length,
+	rtl8365mb_mib_counter_read(priv, port, mib->offset, mib->length,
 				   &phy_stats->SymbolErrorDuringCarrier);
 	mutex_unlock(&mb->mib_lock);
 }
@@ -1226,12 +1226,12 @@ static void rtl8365mb_get_mac_stats(struct dsa_switch *ds, int port,
 		[RTL8365MB_MIB_dot3StatsExcessiveCollisions] = 1,
 
 	};
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb *mb;
 	int ret;
 	int i;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 
 	mutex_lock(&mb->mib_lock);
 	for (i = 0; i < RTL8365MB_MIB_END; i++) {
@@ -1241,7 +1241,7 @@ static void rtl8365mb_get_mac_stats(struct dsa_switch *ds, int port,
 		if (!cnt[i])
 			continue;
 
-		ret = rtl8365mb_mib_counter_read(smi, port, mib->offset,
+		ret = rtl8365mb_mib_counter_read(priv, port, mib->offset,
 						 mib->length, &cnt[i]);
 		if (ret)
 			break;
@@ -1291,20 +1291,20 @@ static void rtl8365mb_get_mac_stats(struct dsa_switch *ds, int port,
 static void rtl8365mb_get_ctrl_stats(struct dsa_switch *ds, int port,
 				     struct ethtool_eth_ctrl_stats *ctrl_stats)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb_mib_counter *mib;
 	struct rtl8365mb *mb;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 	mib = &rtl8365mb_mib_counters[RTL8365MB_MIB_dot3ControlInUnknownOpcodes];
 
 	mutex_lock(&mb->mib_lock);
-	rtl8365mb_mib_counter_read(smi, port, mib->offset, mib->length,
+	rtl8365mb_mib_counter_read(priv, port, mib->offset, mib->length,
 				   &ctrl_stats->UnsupportedOpcodesReceived);
 	mutex_unlock(&mb->mib_lock);
 }
 
-static void rtl8365mb_stats_update(struct realtek_smi *smi, int port)
+static void rtl8365mb_stats_update(struct realtek_priv *priv, int port)
 {
 	u64 cnt[RTL8365MB_MIB_END] = {
 		[RTL8365MB_MIB_ifOutOctets] = 1,
@@ -1323,7 +1323,7 @@ static void rtl8365mb_stats_update(struct realtek_smi *smi, int port)
 		[RTL8365MB_MIB_dot3StatsFCSErrors] = 1,
 		[RTL8365MB_MIB_dot3StatsLateCollisions] = 1,
 	};
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	struct rtnl_link_stats64 *stats;
 	int ret;
 	int i;
@@ -1338,7 +1338,7 @@ static void rtl8365mb_stats_update(struct realtek_smi *smi, int port)
 		if (!cnt[i])
 			continue;
 
-		ret = rtl8365mb_mib_counter_read(smi, port, c->offset,
+		ret = rtl8365mb_mib_counter_read(priv, port, c->offset,
 						 c->length, &cnt[i]);
 		if (ret)
 			break;
@@ -1388,9 +1388,9 @@ static void rtl8365mb_stats_poll(struct work_struct *work)
 	struct rtl8365mb_port *p = container_of(to_delayed_work(work),
 						struct rtl8365mb_port,
 						mib_work);
-	struct realtek_smi *smi = p->smi;
+	struct realtek_priv *priv = p->priv;
 
-	rtl8365mb_stats_update(smi, p->index);
+	rtl8365mb_stats_update(priv, p->index);
 
 	schedule_delayed_work(&p->mib_work, RTL8365MB_STATS_INTERVAL_JIFFIES);
 }
@@ -1398,11 +1398,11 @@ static void rtl8365mb_stats_poll(struct work_struct *work)
 static void rtl8365mb_get_stats64(struct dsa_switch *ds, int port,
 				  struct rtnl_link_stats64 *s)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb_port *p;
 	struct rtl8365mb *mb;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 	p = &mb->ports[port];
 
 	spin_lock(&p->stats_lock);
@@ -1410,9 +1410,9 @@ static void rtl8365mb_get_stats64(struct dsa_switch *ds, int port,
 	spin_unlock(&p->stats_lock);
 }
 
-static void rtl8365mb_stats_setup(struct realtek_smi *smi)
+static void rtl8365mb_stats_setup(struct realtek_priv *priv)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	int i;
 
 	/* Per-chip global mutex to protect MIB counter access, since doing
@@ -1420,10 +1420,10 @@ static void rtl8365mb_stats_setup(struct realtek_smi *smi)
 	 */
 	mutex_init(&mb->mib_lock);
 
-	for (i = 0; i < smi->num_ports; i++) {
+	for (i = 0; i < priv->num_ports; i++) {
 		struct rtl8365mb_port *p = &mb->ports[i];
 
-		if (dsa_is_unused_port(smi->ds, i))
+		if (dsa_is_unused_port(priv->ds, i))
 			continue;
 
 		/* Per-port spinlock to protect the stats64 data */
@@ -1436,45 +1436,45 @@ static void rtl8365mb_stats_setup(struct realtek_smi *smi)
 	}
 }
 
-static void rtl8365mb_stats_teardown(struct realtek_smi *smi)
+static void rtl8365mb_stats_teardown(struct realtek_priv *priv)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	int i;
 
-	for (i = 0; i < smi->num_ports; i++) {
+	for (i = 0; i < priv->num_ports; i++) {
 		struct rtl8365mb_port *p = &mb->ports[i];
 
-		if (dsa_is_unused_port(smi->ds, i))
+		if (dsa_is_unused_port(priv->ds, i))
 			continue;
 
 		cancel_delayed_work_sync(&p->mib_work);
 	}
 }
 
-static int rtl8365mb_get_and_clear_status_reg(struct realtek_smi *smi, u32 reg,
+static int rtl8365mb_get_and_clear_status_reg(struct realtek_priv *priv, u32 reg,
 					      u32 *val)
 {
 	int ret;
 
-	ret = regmap_read(smi->map, reg, val);
+	ret = regmap_read(priv->map, reg, val);
 	if (ret)
 		return ret;
 
-	return regmap_write(smi->map, reg, *val);
+	return regmap_write(priv->map, reg, *val);
 }
 
 static irqreturn_t rtl8365mb_irq(int irq, void *data)
 {
-	struct realtek_smi *smi = data;
+	struct realtek_priv *priv = data;
 	unsigned long line_changes = 0;
 	struct rtl8365mb *mb;
 	u32 stat;
 	int line;
 	int ret;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 
-	ret = rtl8365mb_get_and_clear_status_reg(smi, RTL8365MB_INTR_STATUS_REG,
+	ret = rtl8365mb_get_and_clear_status_reg(priv, RTL8365MB_INTR_STATUS_REG,
 						 &stat);
 	if (ret)
 		goto out_error;
@@ -1485,14 +1485,14 @@ static irqreturn_t rtl8365mb_irq(int irq, void *data)
 		u32 val;
 
 		ret = rtl8365mb_get_and_clear_status_reg(
-			smi, RTL8365MB_PORT_LINKUP_IND_REG, &val);
+			priv, RTL8365MB_PORT_LINKUP_IND_REG, &val);
 		if (ret)
 			goto out_error;
 
 		linkup_ind = FIELD_GET(RTL8365MB_PORT_LINKUP_IND_MASK, val);
 
 		ret = rtl8365mb_get_and_clear_status_reg(
-			smi, RTL8365MB_PORT_LINKDOWN_IND_REG, &val);
+			priv, RTL8365MB_PORT_LINKDOWN_IND_REG, &val);
 		if (ret)
 			goto out_error;
 
@@ -1504,8 +1504,8 @@ static irqreturn_t rtl8365mb_irq(int irq, void *data)
 	if (!line_changes)
 		goto out_none;
 
-	for_each_set_bit(line, &line_changes, smi->num_ports) {
-		int child_irq = irq_find_mapping(smi->irqdomain, line);
+	for_each_set_bit(line, &line_changes, priv->num_ports) {
+		int child_irq = irq_find_mapping(priv->irqdomain, line);
 
 		handle_nested_irq(child_irq);
 	}
@@ -1513,7 +1513,7 @@ static irqreturn_t rtl8365mb_irq(int irq, void *data)
 	return IRQ_HANDLED;
 
 out_error:
-	dev_err(smi->dev, "failed to read interrupt status: %d\n", ret);
+	dev_err(priv->dev, "failed to read interrupt status: %d\n", ret);
 
 out_none:
 	return IRQ_NONE;
@@ -1548,27 +1548,27 @@ static const struct irq_domain_ops rtl8365mb_irqdomain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
-static int rtl8365mb_set_irq_enable(struct realtek_smi *smi, bool enable)
+static int rtl8365mb_set_irq_enable(struct realtek_priv *priv, bool enable)
 {
-	return regmap_update_bits(smi->map, RTL8365MB_INTR_CTRL_REG,
+	return regmap_update_bits(priv->map, RTL8365MB_INTR_CTRL_REG,
 				  RTL8365MB_INTR_LINK_CHANGE_MASK,
 				  FIELD_PREP(RTL8365MB_INTR_LINK_CHANGE_MASK,
 					     enable ? 1 : 0));
 }
 
-static int rtl8365mb_irq_enable(struct realtek_smi *smi)
+static int rtl8365mb_irq_enable(struct realtek_priv *priv)
 {
-	return rtl8365mb_set_irq_enable(smi, true);
+	return rtl8365mb_set_irq_enable(priv, true);
 }
 
-static int rtl8365mb_irq_disable(struct realtek_smi *smi)
+static int rtl8365mb_irq_disable(struct realtek_priv *priv)
 {
-	return rtl8365mb_set_irq_enable(smi, false);
+	return rtl8365mb_set_irq_enable(priv, false);
 }
 
-static int rtl8365mb_irq_setup(struct realtek_smi *smi)
+static int rtl8365mb_irq_setup(struct realtek_priv *priv)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	struct device_node *intc;
 	u32 irq_trig;
 	int virq;
@@ -1577,9 +1577,9 @@ static int rtl8365mb_irq_setup(struct realtek_smi *smi)
 	int ret;
 	int i;
 
-	intc = of_get_child_by_name(smi->dev->of_node, "interrupt-controller");
+	intc = of_get_child_by_name(priv->dev->of_node, "interrupt-controller");
 	if (!intc) {
-		dev_err(smi->dev, "missing child interrupt-controller node\n");
+		dev_err(priv->dev, "missing child interrupt-controller node\n");
 		return -EINVAL;
 	}
 
@@ -1587,24 +1587,24 @@ static int rtl8365mb_irq_setup(struct realtek_smi *smi)
 	irq = of_irq_get(intc, 0);
 	if (irq <= 0) {
 		if (irq != -EPROBE_DEFER)
-			dev_err(smi->dev, "failed to get parent irq: %d\n",
+			dev_err(priv->dev, "failed to get parent irq: %d\n",
 				irq);
 		ret = irq ? irq : -EINVAL;
 		goto out_put_node;
 	}
 
-	smi->irqdomain = irq_domain_add_linear(intc, smi->num_ports,
-					       &rtl8365mb_irqdomain_ops, smi);
-	if (!smi->irqdomain) {
-		dev_err(smi->dev, "failed to add irq domain\n");
+	priv->irqdomain = irq_domain_add_linear(intc, priv->num_ports,
+						&rtl8365mb_irqdomain_ops, priv);
+	if (!priv->irqdomain) {
+		dev_err(priv->dev, "failed to add irq domain\n");
 		ret = -ENOMEM;
 		goto out_put_node;
 	}
 
-	for (i = 0; i < smi->num_ports; i++) {
-		virq = irq_create_mapping(smi->irqdomain, i);
+	for (i = 0; i < priv->num_ports; i++) {
+		virq = irq_create_mapping(priv->irqdomain, i);
 		if (!virq) {
-			dev_err(smi->dev,
+			dev_err(priv->dev,
 				"failed to create irq domain mapping\n");
 			ret = -EINVAL;
 			goto out_remove_irqdomain;
@@ -1625,40 +1625,40 @@ static int rtl8365mb_irq_setup(struct realtek_smi *smi)
 		val = RTL8365MB_INTR_POLARITY_LOW;
 		break;
 	default:
-		dev_err(smi->dev, "unsupported irq trigger type %u\n",
+		dev_err(priv->dev, "unsupported irq trigger type %u\n",
 			irq_trig);
 		ret = -EINVAL;
 		goto out_remove_irqdomain;
 	}
 
-	ret = regmap_update_bits(smi->map, RTL8365MB_INTR_POLARITY_REG,
+	ret = regmap_update_bits(priv->map, RTL8365MB_INTR_POLARITY_REG,
 				 RTL8365MB_INTR_POLARITY_MASK,
 				 FIELD_PREP(RTL8365MB_INTR_POLARITY_MASK, val));
 	if (ret)
 		goto out_remove_irqdomain;
 
 	/* Disable the interrupt in case the chip has it enabled on reset */
-	ret = rtl8365mb_irq_disable(smi);
+	ret = rtl8365mb_irq_disable(priv);
 	if (ret)
 		goto out_remove_irqdomain;
 
 	/* Clear the interrupt status register */
-	ret = regmap_write(smi->map, RTL8365MB_INTR_STATUS_REG,
+	ret = regmap_write(priv->map, RTL8365MB_INTR_STATUS_REG,
 			   RTL8365MB_INTR_ALL_MASK);
 	if (ret)
 		goto out_remove_irqdomain;
 
 	ret = request_threaded_irq(irq, NULL, rtl8365mb_irq, IRQF_ONESHOT,
-				   "rtl8365mb", smi);
+				   "rtl8365mb", priv);
 	if (ret) {
-		dev_err(smi->dev, "failed to request irq: %d\n", ret);
+		dev_err(priv->dev, "failed to request irq: %d\n", ret);
 		goto out_remove_irqdomain;
 	}
 
 	/* Store the irq so that we know to free it during teardown */
 	mb->irq = irq;
 
-	ret = rtl8365mb_irq_enable(smi);
+	ret = rtl8365mb_irq_enable(priv);
 	if (ret)
 		goto out_free_irq;
 
@@ -1667,17 +1667,17 @@ static int rtl8365mb_irq_setup(struct realtek_smi *smi)
 	return 0;
 
 out_free_irq:
-	free_irq(mb->irq, smi);
+	free_irq(mb->irq, priv);
 	mb->irq = 0;
 
 out_remove_irqdomain:
-	for (i = 0; i < smi->num_ports; i++) {
-		virq = irq_find_mapping(smi->irqdomain, i);
+	for (i = 0; i < priv->num_ports; i++) {
+		virq = irq_find_mapping(priv->irqdomain, i);
 		irq_dispose_mapping(virq);
 	}
 
-	irq_domain_remove(smi->irqdomain);
-	smi->irqdomain = NULL;
+	irq_domain_remove(priv->irqdomain);
+	priv->irqdomain = NULL;
 
 out_put_node:
 	of_node_put(intc);
@@ -1685,36 +1685,36 @@ static int rtl8365mb_irq_setup(struct realtek_smi *smi)
 	return ret;
 }
 
-static void rtl8365mb_irq_teardown(struct realtek_smi *smi)
+static void rtl8365mb_irq_teardown(struct realtek_priv *priv)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	int virq;
 	int i;
 
 	if (mb->irq) {
-		free_irq(mb->irq, smi);
+		free_irq(mb->irq, priv);
 		mb->irq = 0;
 	}
 
-	if (smi->irqdomain) {
-		for (i = 0; i < smi->num_ports; i++) {
-			virq = irq_find_mapping(smi->irqdomain, i);
+	if (priv->irqdomain) {
+		for (i = 0; i < priv->num_ports; i++) {
+			virq = irq_find_mapping(priv->irqdomain, i);
 			irq_dispose_mapping(virq);
 		}
 
-		irq_domain_remove(smi->irqdomain);
-		smi->irqdomain = NULL;
+		irq_domain_remove(priv->irqdomain);
+		priv->irqdomain = NULL;
 	}
 }
 
-static int rtl8365mb_cpu_config(struct realtek_smi *smi)
+static int rtl8365mb_cpu_config(struct realtek_priv *priv)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	struct rtl8365mb_cpu *cpu = &mb->cpu;
 	u32 val;
 	int ret;
 
-	ret = regmap_update_bits(smi->map, RTL8365MB_CPU_PORT_MASK_REG,
+	ret = regmap_update_bits(priv->map, RTL8365MB_CPU_PORT_MASK_REG,
 				 RTL8365MB_CPU_PORT_MASK_MASK,
 				 FIELD_PREP(RTL8365MB_CPU_PORT_MASK_MASK,
 					    cpu->mask));
@@ -1729,23 +1729,23 @@ static int rtl8365mb_cpu_config(struct realtek_smi *smi)
 	      FIELD_PREP(RTL8365MB_CPU_CTRL_TRAP_PORT_MASK, cpu->trap_port) |
 	      FIELD_PREP(RTL8365MB_CPU_CTRL_TRAP_PORT_EXT_MASK,
 			 cpu->trap_port >> 3);
-	ret = regmap_write(smi->map, RTL8365MB_CPU_CTRL_REG, val);
+	ret = regmap_write(priv->map, RTL8365MB_CPU_CTRL_REG, val);
 	if (ret)
 		return ret;
 
 	return 0;
 }
 
-static int rtl8365mb_switch_init(struct realtek_smi *smi)
+static int rtl8365mb_switch_init(struct realtek_priv *priv)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	int ret;
 	int i;
 
 	/* Do any chip-specific init jam before getting to the common stuff */
 	if (mb->jam_table) {
 		for (i = 0; i < mb->jam_size; i++) {
-			ret = regmap_write(smi->map, mb->jam_table[i].reg,
+			ret = regmap_write(priv->map, mb->jam_table[i].reg,
 					   mb->jam_table[i].val);
 			if (ret)
 				return ret;
@@ -1754,7 +1754,7 @@ static int rtl8365mb_switch_init(struct realtek_smi *smi)
 
 	/* Common init jam */
 	for (i = 0; i < ARRAY_SIZE(rtl8365mb_init_jam_common); i++) {
-		ret = regmap_write(smi->map, rtl8365mb_init_jam_common[i].reg,
+		ret = regmap_write(priv->map, rtl8365mb_init_jam_common[i].reg,
 				   rtl8365mb_init_jam_common[i].val);
 		if (ret)
 			return ret;
@@ -1763,11 +1763,11 @@ static int rtl8365mb_switch_init(struct realtek_smi *smi)
 	return 0;
 }
 
-static int rtl8365mb_reset_chip(struct realtek_smi *smi)
+static int rtl8365mb_reset_chip(struct realtek_priv *priv)
 {
 	u32 val;
 
-	realtek_smi_write_reg_noack(smi, RTL8365MB_CHIP_RESET_REG,
+	realtek_smi_write_reg_noack(priv, RTL8365MB_CHIP_RESET_REG,
 				    FIELD_PREP(RTL8365MB_CHIP_RESET_HW_MASK,
 					       1));
 
@@ -1775,63 +1775,63 @@ static int rtl8365mb_reset_chip(struct realtek_smi *smi)
 	 * for 100 ms before accessing any registers to prevent ACK timeouts.
 	 */
 	msleep(100);
-	return regmap_read_poll_timeout(smi->map, RTL8365MB_CHIP_RESET_REG, val,
+	return regmap_read_poll_timeout(priv->map, RTL8365MB_CHIP_RESET_REG, val,
 					!(val & RTL8365MB_CHIP_RESET_HW_MASK),
 					20000, 1e6);
 }
 
 static int rtl8365mb_setup(struct dsa_switch *ds)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8365mb *mb;
 	int ret;
 	int i;
 
-	mb = smi->chip_data;
+	mb = priv->chip_data;
 
-	ret = rtl8365mb_reset_chip(smi);
+	ret = rtl8365mb_reset_chip(priv);
 	if (ret) {
-		dev_err(smi->dev, "failed to reset chip: %d\n", ret);
+		dev_err(priv->dev, "failed to reset chip: %d\n", ret);
 		goto out_error;
 	}
 
 	/* Configure switch to vendor-defined initial state */
-	ret = rtl8365mb_switch_init(smi);
+	ret = rtl8365mb_switch_init(priv);
 	if (ret) {
-		dev_err(smi->dev, "failed to initialize switch: %d\n", ret);
+		dev_err(priv->dev, "failed to initialize switch: %d\n", ret);
 		goto out_error;
 	}
 
 	/* Set up cascading IRQs */
-	ret = rtl8365mb_irq_setup(smi);
+	ret = rtl8365mb_irq_setup(priv);
 	if (ret == -EPROBE_DEFER)
 		return ret;
 	else if (ret)
-		dev_info(smi->dev, "no interrupt support\n");
+		dev_info(priv->dev, "no interrupt support\n");
 
 	/* Configure CPU tagging */
-	ret = rtl8365mb_cpu_config(smi);
+	ret = rtl8365mb_cpu_config(priv);
 	if (ret)
 		goto out_teardown_irq;
 
 	/* Configure ports */
-	for (i = 0; i < smi->num_ports; i++) {
+	for (i = 0; i < priv->num_ports; i++) {
 		struct rtl8365mb_port *p = &mb->ports[i];
 
-		if (dsa_is_unused_port(smi->ds, i))
+		if (dsa_is_unused_port(priv->ds, i))
 			continue;
 
 		/* Set up per-port private data */
-		p->smi = smi;
+		p->priv = priv;
 		p->index = i;
 
 		/* Forward only to the CPU */
-		ret = rtl8365mb_port_set_isolation(smi, i, BIT(smi->cpu_port));
+		ret = rtl8365mb_port_set_isolation(priv, i, BIT(priv->cpu_port));
 		if (ret)
 			goto out_teardown_irq;
 
 		/* Disable learning */
-		ret = rtl8365mb_port_set_learning(smi, i, false);
+		ret = rtl8365mb_port_set_learning(priv, i, false);
 		if (ret)
 			goto out_teardown_irq;
 
@@ -1839,29 +1839,29 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 		 * ports will still forward frames to the CPU despite being
 		 * administratively down by default.
 		 */
-		rtl8365mb_port_stp_state_set(smi->ds, i, BR_STATE_DISABLED);
+		rtl8365mb_port_stp_state_set(priv->ds, i, BR_STATE_DISABLED);
 	}
 
 	/* Set maximum packet length to 1536 bytes */
-	ret = regmap_update_bits(smi->map, RTL8365MB_CFG0_MAX_LEN_REG,
+	ret = regmap_update_bits(priv->map, RTL8365MB_CFG0_MAX_LEN_REG,
 				 RTL8365MB_CFG0_MAX_LEN_MASK,
 				 FIELD_PREP(RTL8365MB_CFG0_MAX_LEN_MASK, 1536));
 	if (ret)
 		goto out_teardown_irq;
 
-	ret = realtek_smi_setup_mdio(smi);
+	ret = realtek_smi_setup_mdio(priv);
 	if (ret) {
-		dev_err(smi->dev, "could not set up MDIO bus\n");
+		dev_err(priv->dev, "could not set up MDIO bus\n");
 		goto out_teardown_irq;
 	}
 
 	/* Start statistics counter polling */
-	rtl8365mb_stats_setup(smi);
+	rtl8365mb_stats_setup(priv);
 
 	return 0;
 
 out_teardown_irq:
-	rtl8365mb_irq_teardown(smi);
+	rtl8365mb_irq_teardown(priv);
 
 out_error:
 	return ret;
@@ -1869,10 +1869,10 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 
 static void rtl8365mb_teardown(struct dsa_switch *ds)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 
-	rtl8365mb_stats_teardown(smi);
-	rtl8365mb_irq_teardown(smi);
+	rtl8365mb_stats_teardown(priv);
+	rtl8365mb_irq_teardown(priv);
 }
 
 static int rtl8365mb_get_chip_id_and_ver(struct regmap *map, u32 *id, u32 *ver)
@@ -1902,40 +1902,40 @@ static int rtl8365mb_get_chip_id_and_ver(struct regmap *map, u32 *id, u32 *ver)
 	return 0;
 }
 
-static int rtl8365mb_detect(struct realtek_smi *smi)
+static int rtl8365mb_detect(struct realtek_priv *priv)
 {
-	struct rtl8365mb *mb = smi->chip_data;
+	struct rtl8365mb *mb = priv->chip_data;
 	u32 chip_id;
 	u32 chip_ver;
 	int ret;
 
-	ret = rtl8365mb_get_chip_id_and_ver(smi->map, &chip_id, &chip_ver);
+	ret = rtl8365mb_get_chip_id_and_ver(priv->map, &chip_id, &chip_ver);
 	if (ret) {
-		dev_err(smi->dev, "failed to read chip id and version: %d\n",
+		dev_err(priv->dev, "failed to read chip id and version: %d\n",
 			ret);
 		return ret;
 	}
 
 	switch (chip_id) {
 	case RTL8365MB_CHIP_ID_8365MB_VC:
-		dev_info(smi->dev,
+		dev_info(priv->dev,
 			 "found an RTL8365MB-VC switch (ver=0x%04x)\n",
 			 chip_ver);
 
-		smi->cpu_port = RTL8365MB_CPU_PORT_NUM_8365MB_VC;
-		smi->num_ports = smi->cpu_port + 1;
+		priv->cpu_port = RTL8365MB_CPU_PORT_NUM_8365MB_VC;
+		priv->num_ports = priv->cpu_port + 1;
 
-		mb->smi = smi;
+		mb->priv = priv;
 		mb->chip_id = chip_id;
 		mb->chip_ver = chip_ver;
-		mb->port_mask = BIT(smi->num_ports) - 1;
+		mb->port_mask = BIT(priv->num_ports) - 1;
 		mb->learn_limit_max = RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC;
 		mb->jam_table = rtl8365mb_init_jam_8365mb_vc;
 		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);
 
 		mb->cpu.enable = 1;
-		mb->cpu.mask = BIT(smi->cpu_port);
-		mb->cpu.trap_port = smi->cpu_port;
+		mb->cpu.mask = BIT(priv->cpu_port);
+		mb->cpu.trap_port = priv->cpu_port;
 		mb->cpu.insert = RTL8365MB_CPU_INSERT_TO_ALL;
 		mb->cpu.position = RTL8365MB_CPU_POS_AFTER_SA;
 		mb->cpu.rx_length = RTL8365MB_CPU_RXLEN_64BYTES;
@@ -1943,7 +1943,7 @@ static int rtl8365mb_detect(struct realtek_smi *smi)
 
 		break;
 	default:
-		dev_err(smi->dev,
+		dev_err(priv->dev,
 			"found an unknown Realtek switch (id=0x%04x, ver=0x%04x)\n",
 			chip_id, chip_ver);
 		return -ENODEV;
@@ -1970,15 +1970,15 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
 	.get_stats64 = rtl8365mb_get_stats64,
 };
 
-static const struct realtek_smi_ops rtl8365mb_smi_ops = {
+static const struct realtek_ops rtl8365mb_ops = {
 	.detect = rtl8365mb_detect,
 	.phy_read = rtl8365mb_phy_read,
 	.phy_write = rtl8365mb_phy_write,
 };
 
-const struct realtek_smi_variant rtl8365mb_variant = {
+const struct realtek_variant rtl8365mb_variant = {
 	.ds_ops = &rtl8365mb_switch_ops,
-	.ops = &rtl8365mb_smi_ops,
+	.ops = &rtl8365mb_ops,
 	.clk_delay = 10,
 	.cmd_read = 0xb9,
 	.cmd_write = 0xb8,
diff --git a/drivers/net/dsa/realtek/rtl8366.c b/drivers/net/dsa/realtek/rtl8366.c
index bdb8d8d34880..dc5f75be3017 100644
--- a/drivers/net/dsa/realtek/rtl8366.c
+++ b/drivers/net/dsa/realtek/rtl8366.c
@@ -11,18 +11,18 @@
 #include <linux/if_bridge.h>
 #include <net/dsa.h>
 
-#include "realtek-smi-core.h"
+#include "realtek.h"
 
-int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used)
+int rtl8366_mc_is_used(struct realtek_priv *priv, int mc_index, int *used)
 {
 	int ret;
 	int i;
 
 	*used = 0;
-	for (i = 0; i < smi->num_ports; i++) {
+	for (i = 0; i < priv->num_ports; i++) {
 		int index = 0;
 
-		ret = smi->ops->get_mc_index(smi, i, &index);
+		ret = priv->ops->get_mc_index(priv, i, &index);
 		if (ret)
 			return ret;
 
@@ -38,13 +38,13 @@ EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
 
 /**
  * rtl8366_obtain_mc() - retrieve or allocate a VLAN member configuration
- * @smi: the Realtek SMI device instance
+ * @priv: the Realtek SMI device instance
  * @vid: the VLAN ID to look up or allocate
  * @vlanmc: the pointer will be assigned to a pointer to a valid member config
  * if successful
  * @return: index of a new member config or negative error number
  */
-static int rtl8366_obtain_mc(struct realtek_smi *smi, int vid,
+static int rtl8366_obtain_mc(struct realtek_priv *priv, int vid,
 			     struct rtl8366_vlan_mc *vlanmc)
 {
 	struct rtl8366_vlan_4k vlan4k;
@@ -52,10 +52,10 @@ static int rtl8366_obtain_mc(struct realtek_smi *smi, int vid,
 	int i;
 
 	/* Try to find an existing member config entry for this VID */
-	for (i = 0; i < smi->num_vlan_mc; i++) {
-		ret = smi->ops->get_vlan_mc(smi, i, vlanmc);
+	for (i = 0; i < priv->num_vlan_mc; i++) {
+		ret = priv->ops->get_vlan_mc(priv, i, vlanmc);
 		if (ret) {
-			dev_err(smi->dev, "error searching for VLAN MC %d for VID %d\n",
+			dev_err(priv->dev, "error searching for VLAN MC %d for VID %d\n",
 				i, vid);
 			return ret;
 		}
@@ -65,19 +65,19 @@ static int rtl8366_obtain_mc(struct realtek_smi *smi, int vid,
 	}
 
 	/* We have no MC entry for this VID, try to find an empty one */
-	for (i = 0; i < smi->num_vlan_mc; i++) {
-		ret = smi->ops->get_vlan_mc(smi, i, vlanmc);
+	for (i = 0; i < priv->num_vlan_mc; i++) {
+		ret = priv->ops->get_vlan_mc(priv, i, vlanmc);
 		if (ret) {
-			dev_err(smi->dev, "error searching for VLAN MC %d for VID %d\n",
+			dev_err(priv->dev, "error searching for VLAN MC %d for VID %d\n",
 				i, vid);
 			return ret;
 		}
 
 		if (vlanmc->vid == 0 && vlanmc->member == 0) {
 			/* Update the entry from the 4K table */
-			ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
+			ret = priv->ops->get_vlan_4k(priv, vid, &vlan4k);
 			if (ret) {
-				dev_err(smi->dev, "error looking for 4K VLAN MC %d for VID %d\n",
+				dev_err(priv->dev, "error looking for 4K VLAN MC %d for VID %d\n",
 					i, vid);
 				return ret;
 			}
@@ -86,30 +86,30 @@ static int rtl8366_obtain_mc(struct realtek_smi *smi, int vid,
 			vlanmc->member = vlan4k.member;
 			vlanmc->untag = vlan4k.untag;
 			vlanmc->fid = vlan4k.fid;
-			ret = smi->ops->set_vlan_mc(smi, i, vlanmc);
+			ret = priv->ops->set_vlan_mc(priv, i, vlanmc);
 			if (ret) {
-				dev_err(smi->dev, "unable to set/update VLAN MC %d for VID %d\n",
+				dev_err(priv->dev, "unable to set/update VLAN MC %d for VID %d\n",
 					i, vid);
 				return ret;
 			}
 
-			dev_dbg(smi->dev, "created new MC at index %d for VID %d\n",
+			dev_dbg(priv->dev, "created new MC at index %d for VID %d\n",
 				i, vid);
 			return i;
 		}
 	}
 
 	/* MC table is full, try to find an unused entry and replace it */
-	for (i = 0; i < smi->num_vlan_mc; i++) {
+	for (i = 0; i < priv->num_vlan_mc; i++) {
 		int used;
 
-		ret = rtl8366_mc_is_used(smi, i, &used);
+		ret = rtl8366_mc_is_used(priv, i, &used);
 		if (ret)
 			return ret;
 
 		if (!used) {
 			/* Update the entry from the 4K table */
-			ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
+			ret = priv->ops->get_vlan_4k(priv, vid, &vlan4k);
 			if (ret)
 				return ret;
 
@@ -117,23 +117,23 @@ static int rtl8366_obtain_mc(struct realtek_smi *smi, int vid,
 			vlanmc->member = vlan4k.member;
 			vlanmc->untag = vlan4k.untag;
 			vlanmc->fid = vlan4k.fid;
-			ret = smi->ops->set_vlan_mc(smi, i, vlanmc);
+			ret = priv->ops->set_vlan_mc(priv, i, vlanmc);
 			if (ret) {
-				dev_err(smi->dev, "unable to set/update VLAN MC %d for VID %d\n",
+				dev_err(priv->dev, "unable to set/update VLAN MC %d for VID %d\n",
 					i, vid);
 				return ret;
 			}
-			dev_dbg(smi->dev, "recycled MC at index %i for VID %d\n",
+			dev_dbg(priv->dev, "recycled MC at index %i for VID %d\n",
 				i, vid);
 			return i;
 		}
 	}
 
-	dev_err(smi->dev, "all VLAN member configurations are in use\n");
+	dev_err(priv->dev, "all VLAN member configurations are in use\n");
 	return -ENOSPC;
 }
 
-int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
+int rtl8366_set_vlan(struct realtek_priv *priv, int vid, u32 member,
 		     u32 untag, u32 fid)
 {
 	struct rtl8366_vlan_mc vlanmc;
@@ -141,31 +141,31 @@ int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
 	int mc;
 	int ret;
 
-	if (!smi->ops->is_vlan_valid(smi, vid))
+	if (!priv->ops->is_vlan_valid(priv, vid))
 		return -EINVAL;
 
-	dev_dbg(smi->dev,
+	dev_dbg(priv->dev,
 		"setting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
 		vid, member, untag);
 
 	/* Update the 4K table */
-	ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
+	ret = priv->ops->get_vlan_4k(priv, vid, &vlan4k);
 	if (ret)
 		return ret;
 
 	vlan4k.member |= member;
 	vlan4k.untag |= untag;
 	vlan4k.fid = fid;
-	ret = smi->ops->set_vlan_4k(smi, &vlan4k);
+	ret = priv->ops->set_vlan_4k(priv, &vlan4k);
 	if (ret)
 		return ret;
 
-	dev_dbg(smi->dev,
+	dev_dbg(priv->dev,
 		"resulting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
 		vid, vlan4k.member, vlan4k.untag);
 
 	/* Find or allocate a member config for this VID */
-	ret = rtl8366_obtain_mc(smi, vid, &vlanmc);
+	ret = rtl8366_obtain_mc(priv, vid, &vlanmc);
 	if (ret < 0)
 		return ret;
 	mc = ret;
@@ -176,12 +176,12 @@ int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
 	vlanmc.fid = fid;
 
 	/* Commit updates to the MC entry */
-	ret = smi->ops->set_vlan_mc(smi, mc, &vlanmc);
+	ret = priv->ops->set_vlan_mc(priv, mc, &vlanmc);
 	if (ret)
-		dev_err(smi->dev, "failed to commit changes to VLAN MC index %d for VID %d\n",
+		dev_err(priv->dev, "failed to commit changes to VLAN MC index %d for VID %d\n",
 			mc, vid);
 	else
-		dev_dbg(smi->dev,
+		dev_dbg(priv->dev,
 			"resulting VLAN%d MC members: 0x%02x, untagged: 0x%02x\n",
 			vid, vlanmc.member, vlanmc.untag);
 
@@ -189,37 +189,37 @@ int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
 }
 EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
 
-int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
+int rtl8366_set_pvid(struct realtek_priv *priv, unsigned int port,
 		     unsigned int vid)
 {
 	struct rtl8366_vlan_mc vlanmc;
 	int mc;
 	int ret;
 
-	if (!smi->ops->is_vlan_valid(smi, vid))
+	if (!priv->ops->is_vlan_valid(priv, vid))
 		return -EINVAL;
 
 	/* Find or allocate a member config for this VID */
-	ret = rtl8366_obtain_mc(smi, vid, &vlanmc);
+	ret = rtl8366_obtain_mc(priv, vid, &vlanmc);
 	if (ret < 0)
 		return ret;
 	mc = ret;
 
-	ret = smi->ops->set_mc_index(smi, port, mc);
+	ret = priv->ops->set_mc_index(priv, port, mc);
 	if (ret) {
-		dev_err(smi->dev, "set PVID: failed to set MC index %d for port %d\n",
+		dev_err(priv->dev, "set PVID: failed to set MC index %d for port %d\n",
 			mc, port);
 		return ret;
 	}
 
-	dev_dbg(smi->dev, "set PVID: the PVID for port %d set to %d using existing MC index %d\n",
+	dev_dbg(priv->dev, "set PVID: the PVID for port %d set to %d using existing MC index %d\n",
 		port, vid, mc);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
 
-int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
+int rtl8366_enable_vlan4k(struct realtek_priv *priv, bool enable)
 {
 	int ret;
 
@@ -229,52 +229,52 @@ int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
 	 */
 	if (enable) {
 		/* Make sure VLAN is ON */
-		ret = smi->ops->enable_vlan(smi, true);
+		ret = priv->ops->enable_vlan(priv, true);
 		if (ret)
 			return ret;
 
-		smi->vlan_enabled = true;
+		priv->vlan_enabled = true;
 	}
 
-	ret = smi->ops->enable_vlan4k(smi, enable);
+	ret = priv->ops->enable_vlan4k(priv, enable);
 	if (ret)
 		return ret;
 
-	smi->vlan4k_enabled = enable;
+	priv->vlan4k_enabled = enable;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan4k);
 
-int rtl8366_enable_vlan(struct realtek_smi *smi, bool enable)
+int rtl8366_enable_vlan(struct realtek_priv *priv, bool enable)
 {
 	int ret;
 
-	ret = smi->ops->enable_vlan(smi, enable);
+	ret = priv->ops->enable_vlan(priv, enable);
 	if (ret)
 		return ret;
 
-	smi->vlan_enabled = enable;
+	priv->vlan_enabled = enable;
 
 	/* If we turn VLAN off, make sure that we turn off
 	 * 4k VLAN as well, if that happened to be on.
 	 */
 	if (!enable) {
-		smi->vlan4k_enabled = false;
-		ret = smi->ops->enable_vlan4k(smi, false);
+		priv->vlan4k_enabled = false;
+		ret = priv->ops->enable_vlan4k(priv, false);
 	}
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(rtl8366_enable_vlan);
 
-int rtl8366_reset_vlan(struct realtek_smi *smi)
+int rtl8366_reset_vlan(struct realtek_priv *priv)
 {
 	struct rtl8366_vlan_mc vlanmc;
 	int ret;
 	int i;
 
-	rtl8366_enable_vlan(smi, false);
-	rtl8366_enable_vlan4k(smi, false);
+	rtl8366_enable_vlan(priv, false);
+	rtl8366_enable_vlan4k(priv, false);
 
 	/* Clear the 16 VLAN member configurations */
 	vlanmc.vid = 0;
@@ -282,8 +282,8 @@ int rtl8366_reset_vlan(struct realtek_smi *smi)
 	vlanmc.member = 0;
 	vlanmc.untag = 0;
 	vlanmc.fid = 0;
-	for (i = 0; i < smi->num_vlan_mc; i++) {
-		ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
+	for (i = 0; i < priv->num_vlan_mc; i++) {
+		ret = priv->ops->set_vlan_mc(priv, i, &vlanmc);
 		if (ret)
 			return ret;
 	}
@@ -298,12 +298,12 @@ int rtl8366_vlan_add(struct dsa_switch *ds, int port,
 {
 	bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
 	bool pvid = !!(vlan->flags & BRIDGE_VLAN_INFO_PVID);
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	u32 member = 0;
 	u32 untag = 0;
 	int ret;
 
-	if (!smi->ops->is_vlan_valid(smi, vlan->vid)) {
+	if (!priv->ops->is_vlan_valid(priv, vlan->vid)) {
 		NL_SET_ERR_MSG_MOD(extack, "VLAN ID not valid");
 		return -EINVAL;
 	}
@@ -312,13 +312,13 @@ int rtl8366_vlan_add(struct dsa_switch *ds, int port,
 	 * FIXME: what's with this 4k business?
 	 * Just rtl8366_enable_vlan() seems inconclusive.
 	 */
-	ret = rtl8366_enable_vlan4k(smi, true);
+	ret = rtl8366_enable_vlan4k(priv, true);
 	if (ret) {
 		NL_SET_ERR_MSG_MOD(extack, "Failed to enable VLAN 4K");
 		return ret;
 	}
 
-	dev_dbg(smi->dev, "add VLAN %d on port %d, %s, %s\n",
+	dev_dbg(priv->dev, "add VLAN %d on port %d, %s, %s\n",
 		vlan->vid, port, untagged ? "untagged" : "tagged",
 		pvid ? "PVID" : "no PVID");
 
@@ -327,18 +327,18 @@ int rtl8366_vlan_add(struct dsa_switch *ds, int port,
 	if (untagged)
 		untag |= BIT(port);
 
-	ret = rtl8366_set_vlan(smi, vlan->vid, member, untag, 0);
+	ret = rtl8366_set_vlan(priv, vlan->vid, member, untag, 0);
 	if (ret) {
-		dev_err(smi->dev, "failed to set up VLAN %04x", vlan->vid);
+		dev_err(priv->dev, "failed to set up VLAN %04x", vlan->vid);
 		return ret;
 	}
 
 	if (!pvid)
 		return 0;
 
-	ret = rtl8366_set_pvid(smi, port, vlan->vid);
+	ret = rtl8366_set_pvid(priv, port, vlan->vid);
 	if (ret) {
-		dev_err(smi->dev, "failed to set PVID on port %d to VLAN %04x",
+		dev_err(priv->dev, "failed to set PVID on port %d to VLAN %04x",
 			port, vlan->vid);
 		return ret;
 	}
@@ -350,15 +350,15 @@ EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
 int rtl8366_vlan_del(struct dsa_switch *ds, int port,
 		     const struct switchdev_obj_port_vlan *vlan)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int ret, i;
 
-	dev_dbg(smi->dev, "del VLAN %d on port %d\n", vlan->vid, port);
+	dev_dbg(priv->dev, "del VLAN %d on port %d\n", vlan->vid, port);
 
-	for (i = 0; i < smi->num_vlan_mc; i++) {
+	for (i = 0; i < priv->num_vlan_mc; i++) {
 		struct rtl8366_vlan_mc vlanmc;
 
-		ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
+		ret = priv->ops->get_vlan_mc(priv, i, &vlanmc);
 		if (ret)
 			return ret;
 
@@ -376,9 +376,9 @@ int rtl8366_vlan_del(struct dsa_switch *ds, int port,
 				vlanmc.priority = 0;
 				vlanmc.fid = 0;
 			}
-			ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
+			ret = priv->ops->set_vlan_mc(priv, i, &vlanmc);
 			if (ret) {
-				dev_err(smi->dev,
+				dev_err(priv->dev,
 					"failed to remove VLAN %04x\n",
 					vlan->vid);
 				return ret;
@@ -394,15 +394,15 @@ EXPORT_SYMBOL_GPL(rtl8366_vlan_del);
 void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
 			 uint8_t *data)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8366_mib_counter *mib;
 	int i;
 
-	if (port >= smi->num_ports)
+	if (port >= priv->num_ports)
 		return;
 
-	for (i = 0; i < smi->num_mib_counters; i++) {
-		mib = &smi->mib_counters[i];
+	for (i = 0; i < priv->num_mib_counters; i++) {
+		mib = &priv->mib_counters[i];
 		strncpy(data + i * ETH_GSTRING_LEN,
 			mib->name, ETH_GSTRING_LEN);
 	}
@@ -411,35 +411,35 @@ EXPORT_SYMBOL_GPL(rtl8366_get_strings);
 
 int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 
 	/* We only support SS_STATS */
 	if (sset != ETH_SS_STATS)
 		return 0;
-	if (port >= smi->num_ports)
+	if (port >= priv->num_ports)
 		return -EINVAL;
 
-	return smi->num_mib_counters;
+	return priv->num_mib_counters;
 }
 EXPORT_SYMBOL_GPL(rtl8366_get_sset_count);
 
 void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int i;
 	int ret;
 
-	if (port >= smi->num_ports)
+	if (port >= priv->num_ports)
 		return;
 
-	for (i = 0; i < smi->num_mib_counters; i++) {
+	for (i = 0; i < priv->num_mib_counters; i++) {
 		struct rtl8366_mib_counter *mib;
 		u64 mibvalue = 0;
 
-		mib = &smi->mib_counters[i];
-		ret = smi->ops->get_mib_counter(smi, port, mib, &mibvalue);
+		mib = &priv->mib_counters[i];
+		ret = priv->ops->get_mib_counter(priv, port, mib, &mibvalue);
 		if (ret) {
-			dev_err(smi->dev, "error reading MIB counter %s\n",
+			dev_err(priv->dev, "error reading MIB counter %s\n",
 				mib->name);
 		}
 		data[i] = mibvalue;
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index ecc19bd5115f..241e6b6ebea5 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -21,7 +21,7 @@
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
 
-#include "realtek-smi-core.h"
+#include "realtek.h"
 
 #define RTL8366RB_PORT_NUM_CPU		5
 #define RTL8366RB_NUM_PORTS		6
@@ -396,7 +396,7 @@ static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = {
 	{ 0, 70, 2, "IfOutBroadcastPkts"			},
 };
 
-static int rtl8366rb_get_mib_counter(struct realtek_smi *smi,
+static int rtl8366rb_get_mib_counter(struct realtek_priv *priv,
 				     int port,
 				     struct rtl8366_mib_counter *mib,
 				     u64 *mibvalue)
@@ -412,12 +412,12 @@ static int rtl8366rb_get_mib_counter(struct realtek_smi *smi,
 	/* Writing access counter address first
 	 * then ASIC will prepare 64bits counter wait for being retrived
 	 */
-	ret = regmap_write(smi->map, addr, 0); /* Write whatever */
+	ret = regmap_write(priv->map, addr, 0); /* Write whatever */
 	if (ret)
 		return ret;
 
 	/* Read MIB control register */
-	ret = regmap_read(smi->map, RTL8366RB_MIB_CTRL_REG, &val);
+	ret = regmap_read(priv->map, RTL8366RB_MIB_CTRL_REG, &val);
 	if (ret)
 		return -EIO;
 
@@ -430,7 +430,7 @@ static int rtl8366rb_get_mib_counter(struct realtek_smi *smi,
 	/* Read each individual MIB 16 bits at the time */
 	*mibvalue = 0;
 	for (i = mib->length; i > 0; i--) {
-		ret = regmap_read(smi->map, addr + (i - 1), &val);
+		ret = regmap_read(priv->map, addr + (i - 1), &val);
 		if (ret)
 			return ret;
 		*mibvalue = (*mibvalue << 16) | (val & 0xFFFF);
@@ -455,38 +455,38 @@ static u32 rtl8366rb_get_irqmask(struct irq_data *d)
 
 static void rtl8366rb_mask_irq(struct irq_data *d)
 {
-	struct realtek_smi *smi = irq_data_get_irq_chip_data(d);
+	struct realtek_priv *priv = irq_data_get_irq_chip_data(d);
 	int ret;
 
-	ret = regmap_update_bits(smi->map, RTL8366RB_INTERRUPT_MASK_REG,
+	ret = regmap_update_bits(priv->map, RTL8366RB_INTERRUPT_MASK_REG,
 				 rtl8366rb_get_irqmask(d), 0);
 	if (ret)
-		dev_err(smi->dev, "could not mask IRQ\n");
+		dev_err(priv->dev, "could not mask IRQ\n");
 }
 
 static void rtl8366rb_unmask_irq(struct irq_data *d)
 {
-	struct realtek_smi *smi = irq_data_get_irq_chip_data(d);
+	struct realtek_priv *priv = irq_data_get_irq_chip_data(d);
 	int ret;
 
-	ret = regmap_update_bits(smi->map, RTL8366RB_INTERRUPT_MASK_REG,
+	ret = regmap_update_bits(priv->map, RTL8366RB_INTERRUPT_MASK_REG,
 				 rtl8366rb_get_irqmask(d),
 				 rtl8366rb_get_irqmask(d));
 	if (ret)
-		dev_err(smi->dev, "could not unmask IRQ\n");
+		dev_err(priv->dev, "could not unmask IRQ\n");
 }
 
 static irqreturn_t rtl8366rb_irq(int irq, void *data)
 {
-	struct realtek_smi *smi = data;
+	struct realtek_priv *priv = data;
 	u32 stat;
 	int ret;
 
 	/* This clears the IRQ status register */
-	ret = regmap_read(smi->map, RTL8366RB_INTERRUPT_STATUS_REG,
+	ret = regmap_read(priv->map, RTL8366RB_INTERRUPT_STATUS_REG,
 			  &stat);
 	if (ret) {
-		dev_err(smi->dev, "can't read interrupt status\n");
+		dev_err(priv->dev, "can't read interrupt status\n");
 		return IRQ_NONE;
 	}
 	stat &= RTL8366RB_INTERRUPT_VALID;
@@ -502,7 +502,7 @@ static irqreturn_t rtl8366rb_irq(int irq, void *data)
 		 */
 		if (line < 12 && line > 5)
 			line -= 5;
-		child_irq = irq_find_mapping(smi->irqdomain, line);
+		child_irq = irq_find_mapping(priv->irqdomain, line);
 		handle_nested_irq(child_irq);
 	}
 	return IRQ_HANDLED;
@@ -538,7 +538,7 @@ static const struct irq_domain_ops rtl8366rb_irqdomain_ops = {
 	.xlate  = irq_domain_xlate_onecell,
 };
 
-static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
+static int rtl8366rb_setup_cascaded_irq(struct realtek_priv *priv)
 {
 	struct device_node *intc;
 	unsigned long irq_trig;
@@ -547,24 +547,24 @@ static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
 	u32 val;
 	int i;
 
-	intc = of_get_child_by_name(smi->dev->of_node, "interrupt-controller");
+	intc = of_get_child_by_name(priv->dev->of_node, "interrupt-controller");
 	if (!intc) {
-		dev_err(smi->dev, "missing child interrupt-controller node\n");
+		dev_err(priv->dev, "missing child interrupt-controller node\n");
 		return -EINVAL;
 	}
 	/* RB8366RB IRQs cascade off this one */
 	irq = of_irq_get(intc, 0);
 	if (irq <= 0) {
-		dev_err(smi->dev, "failed to get parent IRQ\n");
+		dev_err(priv->dev, "failed to get parent IRQ\n");
 		ret = irq ? irq : -EINVAL;
 		goto out_put_node;
 	}
 
 	/* This clears the IRQ status register */
-	ret = regmap_read(smi->map, RTL8366RB_INTERRUPT_STATUS_REG,
+	ret = regmap_read(priv->map, RTL8366RB_INTERRUPT_STATUS_REG,
 			  &val);
 	if (ret) {
-		dev_err(smi->dev, "can't read interrupt status\n");
+		dev_err(priv->dev, "can't read interrupt status\n");
 		goto out_put_node;
 	}
 
@@ -573,48 +573,48 @@ static int rtl8366rb_setup_cascaded_irq(struct realtek_smi *smi)
 	switch (irq_trig) {
 	case IRQF_TRIGGER_RISING:
 	case IRQF_TRIGGER_HIGH:
-		dev_info(smi->dev, "active high/rising IRQ\n");
+		dev_info(priv->dev, "active high/rising IRQ\n");
 		val = 0;
 		break;
 	case IRQF_TRIGGER_FALLING:
 	case IRQF_TRIGGER_LOW:
-		dev_info(smi->dev, "active low/falling IRQ\n");
+		dev_info(priv->dev, "active low/falling IRQ\n");
 		val = RTL8366RB_INTERRUPT_POLARITY;
 		break;
 	}
-	ret = regmap_update_bits(smi->map, RTL8366RB_INTERRUPT_CONTROL_REG,
+	ret = regmap_update_bits(priv->map, RTL8366RB_INTERRUPT_CONTROL_REG,
 				 RTL8366RB_INTERRUPT_POLARITY,
 				 val);
 	if (ret) {
-		dev_err(smi->dev, "could not configure IRQ polarity\n");
+		dev_err(priv->dev, "could not configure IRQ polarity\n");
 		goto out_put_node;
 	}
 
-	ret = devm_request_threaded_irq(smi->dev, irq, NULL,
+	ret = devm_request_threaded_irq(priv->dev, irq, NULL,
 					rtl8366rb_irq, IRQF_ONESHOT,
-					"RTL8366RB", smi);
+					"RTL8366RB", priv);
 	if (ret) {
-		dev_err(smi->dev, "unable to request irq: %d\n", ret);
+		dev_err(priv->dev, "unable to request irq: %d\n", ret);
 		goto out_put_node;
 	}
-	smi->irqdomain = irq_domain_add_linear(intc,
-					       RTL8366RB_NUM_INTERRUPT,
-					       &rtl8366rb_irqdomain_ops,
-					       smi);
-	if (!smi->irqdomain) {
-		dev_err(smi->dev, "failed to create IRQ domain\n");
+	priv->irqdomain = irq_domain_add_linear(intc,
+						RTL8366RB_NUM_INTERRUPT,
+						&rtl8366rb_irqdomain_ops,
+						priv);
+	if (!priv->irqdomain) {
+		dev_err(priv->dev, "failed to create IRQ domain\n");
 		ret = -EINVAL;
 		goto out_put_node;
 	}
-	for (i = 0; i < smi->num_ports; i++)
-		irq_set_parent(irq_create_mapping(smi->irqdomain, i), irq);
+	for (i = 0; i < priv->num_ports; i++)
+		irq_set_parent(irq_create_mapping(priv->irqdomain, i), irq);
 
 out_put_node:
 	of_node_put(intc);
 	return ret;
 }
 
-static int rtl8366rb_set_addr(struct realtek_smi *smi)
+static int rtl8366rb_set_addr(struct realtek_priv *priv)
 {
 	u8 addr[ETH_ALEN];
 	u16 val;
@@ -622,18 +622,18 @@ static int rtl8366rb_set_addr(struct realtek_smi *smi)
 
 	eth_random_addr(addr);
 
-	dev_info(smi->dev, "set MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
+	dev_info(priv->dev, "set MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
 		 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
 	val = addr[0] << 8 | addr[1];
-	ret = regmap_write(smi->map, RTL8366RB_SMAR0, val);
+	ret = regmap_write(priv->map, RTL8366RB_SMAR0, val);
 	if (ret)
 		return ret;
 	val = addr[2] << 8 | addr[3];
-	ret = regmap_write(smi->map, RTL8366RB_SMAR1, val);
+	ret = regmap_write(priv->map, RTL8366RB_SMAR1, val);
 	if (ret)
 		return ret;
 	val = addr[4] << 8 | addr[5];
-	ret = regmap_write(smi->map, RTL8366RB_SMAR2, val);
+	ret = regmap_write(priv->map, RTL8366RB_SMAR2, val);
 	if (ret)
 		return ret;
 
@@ -765,7 +765,7 @@ static const struct rtl8366rb_jam_tbl_entry rtl8366rb_green_jam[] = {
 
 /* Function that jams the tables in the proper registers */
 static int rtl8366rb_jam_table(const struct rtl8366rb_jam_tbl_entry *jam_table,
-			       int jam_size, struct realtek_smi *smi,
+			       int jam_size, struct realtek_priv *priv,
 			       bool write_dbg)
 {
 	u32 val;
@@ -774,24 +774,24 @@ static int rtl8366rb_jam_table(const struct rtl8366rb_jam_tbl_entry *jam_table,
 
 	for (i = 0; i < jam_size; i++) {
 		if ((jam_table[i].reg & 0xBE00) == 0xBE00) {
-			ret = regmap_read(smi->map,
+			ret = regmap_read(priv->map,
 					  RTL8366RB_PHY_ACCESS_BUSY_REG,
 					  &val);
 			if (ret)
 				return ret;
 			if (!(val & RTL8366RB_PHY_INT_BUSY)) {
-				ret = regmap_write(smi->map,
-						RTL8366RB_PHY_ACCESS_CTRL_REG,
-						RTL8366RB_PHY_CTRL_WRITE);
+				ret = regmap_write(priv->map,
+						   RTL8366RB_PHY_ACCESS_CTRL_REG,
+						   RTL8366RB_PHY_CTRL_WRITE);
 				if (ret)
 					return ret;
 			}
 		}
 		if (write_dbg)
-			dev_dbg(smi->dev, "jam %04x into register %04x\n",
+			dev_dbg(priv->dev, "jam %04x into register %04x\n",
 				jam_table[i].val,
 				jam_table[i].reg);
-		ret = regmap_write(smi->map,
+		ret = regmap_write(priv->map,
 				   jam_table[i].reg,
 				   jam_table[i].val);
 		if (ret)
@@ -802,7 +802,7 @@ static int rtl8366rb_jam_table(const struct rtl8366rb_jam_tbl_entry *jam_table,
 
 static int rtl8366rb_setup(struct dsa_switch *ds)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	const struct rtl8366rb_jam_tbl_entry *jam_table;
 	struct rtl8366rb *rb;
 	u32 chip_ver = 0;
@@ -812,11 +812,11 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	int ret;
 	int i;
 
-	rb = smi->chip_data;
+	rb = priv->chip_data;
 
-	ret = regmap_read(smi->map, RTL8366RB_CHIP_ID_REG, &chip_id);
+	ret = regmap_read(priv->map, RTL8366RB_CHIP_ID_REG, &chip_id);
 	if (ret) {
-		dev_err(smi->dev, "unable to read chip id\n");
+		dev_err(priv->dev, "unable to read chip id\n");
 		return ret;
 	}
 
@@ -824,18 +824,18 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	case RTL8366RB_CHIP_ID_8366:
 		break;
 	default:
-		dev_err(smi->dev, "unknown chip id (%04x)\n", chip_id);
+		dev_err(priv->dev, "unknown chip id (%04x)\n", chip_id);
 		return -ENODEV;
 	}
 
-	ret = regmap_read(smi->map, RTL8366RB_CHIP_VERSION_CTRL_REG,
+	ret = regmap_read(priv->map, RTL8366RB_CHIP_VERSION_CTRL_REG,
 			  &chip_ver);
 	if (ret) {
-		dev_err(smi->dev, "unable to read chip version\n");
+		dev_err(priv->dev, "unable to read chip version\n");
 		return ret;
 	}
 
-	dev_info(smi->dev, "RTL%04x ver %u chip found\n",
+	dev_info(priv->dev, "RTL%04x ver %u chip found\n",
 		 chip_id, chip_ver & RTL8366RB_CHIP_VERSION_MASK);
 
 	/* Do the init dance using the right jam table */
@@ -872,20 +872,20 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 		jam_size = ARRAY_SIZE(rtl8366rb_init_jam_dgn3500);
 	}
 
-	ret = rtl8366rb_jam_table(jam_table, jam_size, smi, true);
+	ret = rtl8366rb_jam_table(jam_table, jam_size, priv, true);
 	if (ret)
 		return ret;
 
 	/* Isolate all user ports so they can only send packets to itself and the CPU port */
 	for (i = 0; i < RTL8366RB_PORT_NUM_CPU; i++) {
-		ret = regmap_write(smi->map, RTL8366RB_PORT_ISO(i),
+		ret = regmap_write(priv->map, RTL8366RB_PORT_ISO(i),
 				   RTL8366RB_PORT_ISO_PORTS(BIT(RTL8366RB_PORT_NUM_CPU)) |
 				   RTL8366RB_PORT_ISO_EN);
 		if (ret)
 			return ret;
 	}
 	/* CPU port can send packets to all ports */
-	ret = regmap_write(smi->map, RTL8366RB_PORT_ISO(RTL8366RB_PORT_NUM_CPU),
+	ret = regmap_write(priv->map, RTL8366RB_PORT_ISO(RTL8366RB_PORT_NUM_CPU),
 			   RTL8366RB_PORT_ISO_PORTS(dsa_user_ports(ds)) |
 			   RTL8366RB_PORT_ISO_EN);
 	if (ret)
@@ -893,26 +893,26 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 
 	/* Set up the "green ethernet" feature */
 	ret = rtl8366rb_jam_table(rtl8366rb_green_jam,
-				  ARRAY_SIZE(rtl8366rb_green_jam), smi, false);
+				  ARRAY_SIZE(rtl8366rb_green_jam), priv, false);
 	if (ret)
 		return ret;
 
-	ret = regmap_write(smi->map,
+	ret = regmap_write(priv->map,
 			   RTL8366RB_GREEN_FEATURE_REG,
 			   (chip_ver == 1) ? 0x0007 : 0x0003);
 	if (ret)
 		return ret;
 
 	/* Vendor driver sets 0x240 in registers 0xc and 0xd (undocumented) */
-	ret = regmap_write(smi->map, 0x0c, 0x240);
+	ret = regmap_write(priv->map, 0x0c, 0x240);
 	if (ret)
 		return ret;
-	ret = regmap_write(smi->map, 0x0d, 0x240);
+	ret = regmap_write(priv->map, 0x0d, 0x240);
 	if (ret)
 		return ret;
 
 	/* Set some random MAC address */
-	ret = rtl8366rb_set_addr(smi);
+	ret = rtl8366rb_set_addr(priv);
 	if (ret)
 		return ret;
 
@@ -921,21 +921,21 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	 * If you set RTL8368RB_CPU_NO_TAG (bit 15) in this registers
 	 * the custom tag is turned off.
 	 */
-	ret = regmap_update_bits(smi->map, RTL8368RB_CPU_CTRL_REG,
+	ret = regmap_update_bits(priv->map, RTL8368RB_CPU_CTRL_REG,
 				 0xFFFF,
-				 BIT(smi->cpu_port));
+				 BIT(priv->cpu_port));
 	if (ret)
 		return ret;
 
 	/* Make sure we default-enable the fixed CPU port */
-	ret = regmap_update_bits(smi->map, RTL8366RB_PECR,
-				 BIT(smi->cpu_port),
+	ret = regmap_update_bits(priv->map, RTL8366RB_PECR,
+				 BIT(priv->cpu_port),
 				 0);
 	if (ret)
 		return ret;
 
 	/* Set maximum packet length to 1536 bytes */
-	ret = regmap_update_bits(smi->map, RTL8366RB_SGCR,
+	ret = regmap_update_bits(priv->map, RTL8366RB_SGCR,
 				 RTL8366RB_SGCR_MAX_LENGTH_MASK,
 				 RTL8366RB_SGCR_MAX_LENGTH_1536);
 	if (ret)
@@ -945,13 +945,13 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 		rb->max_mtu[i] = 1532;
 
 	/* Disable learning for all ports */
-	ret = regmap_write(smi->map, RTL8366RB_PORT_LEARNDIS_CTRL,
+	ret = regmap_write(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
 			   RTL8366RB_PORT_ALL);
 	if (ret)
 		return ret;
 
 	/* Enable auto ageing for all ports */
-	ret = regmap_write(smi->map, RTL8366RB_SECURITY_CTRL, 0);
+	ret = regmap_write(priv->map, RTL8366RB_SECURITY_CTRL, 0);
 	if (ret)
 		return ret;
 
@@ -962,30 +962,30 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	 * connected to something exotic such as fiber, then this might
 	 * be worth experimenting with.
 	 */
-	ret = regmap_update_bits(smi->map, RTL8366RB_PMC0,
+	ret = regmap_update_bits(priv->map, RTL8366RB_PMC0,
 				 RTL8366RB_PMC0_P4_IOMODE_MASK,
 				 0 << RTL8366RB_PMC0_P4_IOMODE_SHIFT);
 	if (ret)
 		return ret;
 
 	/* Accept all packets by default, we enable filtering on-demand */
-	ret = regmap_write(smi->map, RTL8366RB_VLAN_INGRESS_CTRL1_REG,
+	ret = regmap_write(priv->map, RTL8366RB_VLAN_INGRESS_CTRL1_REG,
 			   0);
 	if (ret)
 		return ret;
-	ret = regmap_write(smi->map, RTL8366RB_VLAN_INGRESS_CTRL2_REG,
+	ret = regmap_write(priv->map, RTL8366RB_VLAN_INGRESS_CTRL2_REG,
 			   0);
 	if (ret)
 		return ret;
 
 	/* Don't drop packets whose DA has not been learned */
-	ret = regmap_update_bits(smi->map, RTL8366RB_SSCR2,
+	ret = regmap_update_bits(priv->map, RTL8366RB_SSCR2,
 				 RTL8366RB_SSCR2_DROP_UNKNOWN_DA, 0);
 	if (ret)
 		return ret;
 
 	/* Set blinking, TODO: make this configurable */
-	ret = regmap_update_bits(smi->map, RTL8366RB_LED_BLINKRATE_REG,
+	ret = regmap_update_bits(priv->map, RTL8366RB_LED_BLINKRATE_REG,
 				 RTL8366RB_LED_BLINKRATE_MASK,
 				 RTL8366RB_LED_BLINKRATE_56MS);
 	if (ret)
@@ -996,15 +996,15 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	 * behaviour (no individual config) but we can set up each
 	 * LED separately.
 	 */
-	if (smi->leds_disabled) {
+	if (priv->leds_disabled) {
 		/* Turn everything off */
-		regmap_update_bits(smi->map,
+		regmap_update_bits(priv->map,
 				   RTL8366RB_LED_0_1_CTRL_REG,
 				   0x0FFF, 0);
-		regmap_update_bits(smi->map,
+		regmap_update_bits(priv->map,
 				   RTL8366RB_LED_2_3_CTRL_REG,
 				   0x0FFF, 0);
-		regmap_update_bits(smi->map,
+		regmap_update_bits(priv->map,
 				   RTL8366RB_INTERRUPT_CONTROL_REG,
 				   RTL8366RB_P4_RGMII_LED,
 				   0);
@@ -1014,7 +1014,7 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 		val = RTL8366RB_LED_FORCE;
 	}
 	for (i = 0; i < 4; i++) {
-		ret = regmap_update_bits(smi->map,
+		ret = regmap_update_bits(priv->map,
 					 RTL8366RB_LED_CTRL_REG,
 					 0xf << (i * 4),
 					 val << (i * 4));
@@ -1022,17 +1022,17 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 			return ret;
 	}
 
-	ret = rtl8366_reset_vlan(smi);
+	ret = rtl8366_reset_vlan(priv);
 	if (ret)
 		return ret;
 
-	ret = rtl8366rb_setup_cascaded_irq(smi);
+	ret = rtl8366rb_setup_cascaded_irq(priv);
 	if (ret)
-		dev_info(smi->dev, "no interrupt support\n");
+		dev_info(priv->dev, "no interrupt support\n");
 
-	ret = realtek_smi_setup_mdio(smi);
+	ret = realtek_smi_setup_mdio(priv);
 	if (ret) {
-		dev_info(smi->dev, "could not set up MDIO bus\n");
+		dev_info(priv->dev, "could not set up MDIO bus\n");
 		return -ENODEV;
 	}
 
@@ -1052,35 +1052,35 @@ rtl8366rb_mac_link_up(struct dsa_switch *ds, int port, unsigned int mode,
 		      phy_interface_t interface, struct phy_device *phydev,
 		      int speed, int duplex, bool tx_pause, bool rx_pause)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int ret;
 
-	if (port != smi->cpu_port)
+	if (port != priv->cpu_port)
 		return;
 
-	dev_dbg(smi->dev, "MAC link up on CPU port (%d)\n", port);
+	dev_dbg(priv->dev, "MAC link up on CPU port (%d)\n", port);
 
 	/* Force the fixed CPU port into 1Gbit mode, no autonegotiation */
-	ret = regmap_update_bits(smi->map, RTL8366RB_MAC_FORCE_CTRL_REG,
+	ret = regmap_update_bits(priv->map, RTL8366RB_MAC_FORCE_CTRL_REG,
 				 BIT(port), BIT(port));
 	if (ret) {
-		dev_err(smi->dev, "failed to force 1Gbit on CPU port\n");
+		dev_err(priv->dev, "failed to force 1Gbit on CPU port\n");
 		return;
 	}
 
-	ret = regmap_update_bits(smi->map, RTL8366RB_PAACR2,
+	ret = regmap_update_bits(priv->map, RTL8366RB_PAACR2,
 				 0xFF00U,
 				 RTL8366RB_PAACR_CPU_PORT << 8);
 	if (ret) {
-		dev_err(smi->dev, "failed to set PAACR on CPU port\n");
+		dev_err(priv->dev, "failed to set PAACR on CPU port\n");
 		return;
 	}
 
 	/* Enable the CPU port */
-	ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
+	ret = regmap_update_bits(priv->map, RTL8366RB_PECR, BIT(port),
 				 0);
 	if (ret) {
-		dev_err(smi->dev, "failed to enable the CPU port\n");
+		dev_err(priv->dev, "failed to enable the CPU port\n");
 		return;
 	}
 }
@@ -1089,99 +1089,99 @@ static void
 rtl8366rb_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
 			phy_interface_t interface)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int ret;
 
-	if (port != smi->cpu_port)
+	if (port != priv->cpu_port)
 		return;
 
-	dev_dbg(smi->dev, "MAC link down on CPU port (%d)\n", port);
+	dev_dbg(priv->dev, "MAC link down on CPU port (%d)\n", port);
 
 	/* Disable the CPU port */
-	ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
+	ret = regmap_update_bits(priv->map, RTL8366RB_PECR, BIT(port),
 				 BIT(port));
 	if (ret) {
-		dev_err(smi->dev, "failed to disable the CPU port\n");
+		dev_err(priv->dev, "failed to disable the CPU port\n");
 		return;
 	}
 }
 
-static void rb8366rb_set_port_led(struct realtek_smi *smi,
+static void rb8366rb_set_port_led(struct realtek_priv *priv,
 				  int port, bool enable)
 {
 	u16 val = enable ? 0x3f : 0;
 	int ret;
 
-	if (smi->leds_disabled)
+	if (priv->leds_disabled)
 		return;
 
 	switch (port) {
 	case 0:
-		ret = regmap_update_bits(smi->map,
+		ret = regmap_update_bits(priv->map,
 					 RTL8366RB_LED_0_1_CTRL_REG,
 					 0x3F, val);
 		break;
 	case 1:
-		ret = regmap_update_bits(smi->map,
+		ret = regmap_update_bits(priv->map,
 					 RTL8366RB_LED_0_1_CTRL_REG,
 					 0x3F << RTL8366RB_LED_1_OFFSET,
 					 val << RTL8366RB_LED_1_OFFSET);
 		break;
 	case 2:
-		ret = regmap_update_bits(smi->map,
+		ret = regmap_update_bits(priv->map,
 					 RTL8366RB_LED_2_3_CTRL_REG,
 					 0x3F, val);
 		break;
 	case 3:
-		ret = regmap_update_bits(smi->map,
+		ret = regmap_update_bits(priv->map,
 					 RTL8366RB_LED_2_3_CTRL_REG,
 					 0x3F << RTL8366RB_LED_3_OFFSET,
 					 val << RTL8366RB_LED_3_OFFSET);
 		break;
 	case 4:
-		ret = regmap_update_bits(smi->map,
+		ret = regmap_update_bits(priv->map,
 					 RTL8366RB_INTERRUPT_CONTROL_REG,
 					 RTL8366RB_P4_RGMII_LED,
 					 enable ? RTL8366RB_P4_RGMII_LED : 0);
 		break;
 	default:
-		dev_err(smi->dev, "no LED for port %d\n", port);
+		dev_err(priv->dev, "no LED for port %d\n", port);
 		return;
 	}
 	if (ret)
-		dev_err(smi->dev, "error updating LED on port %d\n", port);
+		dev_err(priv->dev, "error updating LED on port %d\n", port);
 }
 
 static int
 rtl8366rb_port_enable(struct dsa_switch *ds, int port,
 		      struct phy_device *phy)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int ret;
 
-	dev_dbg(smi->dev, "enable port %d\n", port);
-	ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
+	dev_dbg(priv->dev, "enable port %d\n", port);
+	ret = regmap_update_bits(priv->map, RTL8366RB_PECR, BIT(port),
 				 0);
 	if (ret)
 		return ret;
 
-	rb8366rb_set_port_led(smi, port, true);
+	rb8366rb_set_port_led(priv, port, true);
 	return 0;
 }
 
 static void
 rtl8366rb_port_disable(struct dsa_switch *ds, int port)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int ret;
 
-	dev_dbg(smi->dev, "disable port %d\n", port);
-	ret = regmap_update_bits(smi->map, RTL8366RB_PECR, BIT(port),
+	dev_dbg(priv->dev, "disable port %d\n", port);
+	ret = regmap_update_bits(priv->map, RTL8366RB_PECR, BIT(port),
 				 BIT(port));
 	if (ret)
 		return;
 
-	rb8366rb_set_port_led(smi, port, false);
+	rb8366rb_set_port_led(priv, port, false);
 }
 
 static int
@@ -1189,7 +1189,7 @@ rtl8366rb_port_bridge_join(struct dsa_switch *ds, int port,
 			   struct dsa_bridge bridge,
 			   bool *tx_fwd_offload)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	unsigned int port_bitmap = 0;
 	int ret, i;
 
@@ -1202,17 +1202,17 @@ rtl8366rb_port_bridge_join(struct dsa_switch *ds, int port,
 		if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
 			continue;
 		/* Join this port to each other port on the bridge */
-		ret = regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(i),
+		ret = regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(i),
 					 RTL8366RB_PORT_ISO_PORTS(BIT(port)),
 					 RTL8366RB_PORT_ISO_PORTS(BIT(port)));
 		if (ret)
-			dev_err(smi->dev, "failed to join port %d\n", port);
+			dev_err(priv->dev, "failed to join port %d\n", port);
 
 		port_bitmap |= BIT(i);
 	}
 
 	/* Set the bits for the ports we can access */
-	return regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(port),
+	return regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(port),
 				  RTL8366RB_PORT_ISO_PORTS(port_bitmap),
 				  RTL8366RB_PORT_ISO_PORTS(port_bitmap));
 }
@@ -1221,7 +1221,7 @@ static void
 rtl8366rb_port_bridge_leave(struct dsa_switch *ds, int port,
 			    struct dsa_bridge bridge)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	unsigned int port_bitmap = 0;
 	int ret, i;
 
@@ -1234,28 +1234,28 @@ rtl8366rb_port_bridge_leave(struct dsa_switch *ds, int port,
 		if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
 			continue;
 		/* Remove this port from any other port on the bridge */
-		ret = regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(i),
+		ret = regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(i),
 					 RTL8366RB_PORT_ISO_PORTS(BIT(port)), 0);
 		if (ret)
-			dev_err(smi->dev, "failed to leave port %d\n", port);
+			dev_err(priv->dev, "failed to leave port %d\n", port);
 
 		port_bitmap |= BIT(i);
 	}
 
 	/* Clear the bits for the ports we can not access, leave ourselves */
-	regmap_update_bits(smi->map, RTL8366RB_PORT_ISO(port),
+	regmap_update_bits(priv->map, RTL8366RB_PORT_ISO(port),
 			   RTL8366RB_PORT_ISO_PORTS(port_bitmap), 0);
 }
 
 /**
  * rtl8366rb_drop_untagged() - make the switch drop untagged and C-tagged frames
- * @smi: SMI state container
+ * @priv: SMI state container
  * @port: the port to drop untagged and C-tagged frames on
  * @drop: whether to drop or pass untagged and C-tagged frames
  */
-static int rtl8366rb_drop_untagged(struct realtek_smi *smi, int port, bool drop)
+static int rtl8366rb_drop_untagged(struct realtek_priv *priv, int port, bool drop)
 {
-	return regmap_update_bits(smi->map, RTL8366RB_VLAN_INGRESS_CTRL1_REG,
+	return regmap_update_bits(priv->map, RTL8366RB_VLAN_INGRESS_CTRL1_REG,
 				  RTL8366RB_VLAN_INGRESS_CTRL1_DROP(port),
 				  drop ? RTL8366RB_VLAN_INGRESS_CTRL1_DROP(port) : 0);
 }
@@ -1264,17 +1264,17 @@ static int rtl8366rb_vlan_filtering(struct dsa_switch *ds, int port,
 				    bool vlan_filtering,
 				    struct netlink_ext_ack *extack)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8366rb *rb;
 	int ret;
 
-	rb = smi->chip_data;
+	rb = priv->chip_data;
 
-	dev_dbg(smi->dev, "port %d: %s VLAN filtering\n", port,
+	dev_dbg(priv->dev, "port %d: %s VLAN filtering\n", port,
 		vlan_filtering ? "enable" : "disable");
 
 	/* If the port is not in the member set, the frame will be dropped */
-	ret = regmap_update_bits(smi->map, RTL8366RB_VLAN_INGRESS_CTRL2_REG,
+	ret = regmap_update_bits(priv->map, RTL8366RB_VLAN_INGRESS_CTRL2_REG,
 				 BIT(port), vlan_filtering ? BIT(port) : 0);
 	if (ret)
 		return ret;
@@ -1284,9 +1284,9 @@ static int rtl8366rb_vlan_filtering(struct dsa_switch *ds, int port,
 	 * filtering on a port, we need to accept any frames.
 	 */
 	if (vlan_filtering)
-		ret = rtl8366rb_drop_untagged(smi, port, !rb->pvid_enabled[port]);
+		ret = rtl8366rb_drop_untagged(priv, port, !rb->pvid_enabled[port]);
 	else
-		ret = rtl8366rb_drop_untagged(smi, port, false);
+		ret = rtl8366rb_drop_untagged(priv, port, false);
 
 	return ret;
 }
@@ -1308,11 +1308,11 @@ rtl8366rb_port_bridge_flags(struct dsa_switch *ds, int port,
 			    struct switchdev_brport_flags flags,
 			    struct netlink_ext_ack *extack)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	int ret;
 
 	if (flags.mask & BR_LEARNING) {
-		ret = regmap_update_bits(smi->map, RTL8366RB_PORT_LEARNDIS_CTRL,
+		ret = regmap_update_bits(priv->map, RTL8366RB_PORT_LEARNDIS_CTRL,
 					 BIT(port),
 					 (flags.val & BR_LEARNING) ? 0 : BIT(port));
 		if (ret)
@@ -1325,7 +1325,7 @@ rtl8366rb_port_bridge_flags(struct dsa_switch *ds, int port,
 static void
 rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	u32 val;
 	int i;
 
@@ -1344,13 +1344,13 @@ rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 		val = RTL8366RB_STP_STATE_FORWARDING;
 		break;
 	default:
-		dev_err(smi->dev, "unknown bridge state requested\n");
+		dev_err(priv->dev, "unknown bridge state requested\n");
 		return;
 	}
 
 	/* Set the same status for the port on all the FIDs */
 	for (i = 0; i < RTL8366RB_NUM_FIDS; i++) {
-		regmap_update_bits(smi->map, RTL8366RB_STP_STATE_BASE + i,
+		regmap_update_bits(priv->map, RTL8366RB_STP_STATE_BASE + i,
 				   RTL8366RB_STP_STATE_MASK(port),
 				   RTL8366RB_STP_STATE(port, val));
 	}
@@ -1359,26 +1359,26 @@ rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 static void
 rtl8366rb_port_fast_age(struct dsa_switch *ds, int port)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 
 	/* This will age out any learned L2 entries */
-	regmap_update_bits(smi->map, RTL8366RB_SECURITY_CTRL,
+	regmap_update_bits(priv->map, RTL8366RB_SECURITY_CTRL,
 			   BIT(port), BIT(port));
 	/* Restore the normal state of things */
-	regmap_update_bits(smi->map, RTL8366RB_SECURITY_CTRL,
+	regmap_update_bits(priv->map, RTL8366RB_SECURITY_CTRL,
 			   BIT(port), 0);
 }
 
 static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
 {
-	struct realtek_smi *smi = ds->priv;
+	struct realtek_priv *priv = ds->priv;
 	struct rtl8366rb *rb;
 	unsigned int max_mtu;
 	u32 len;
 	int i;
 
 	/* Cache the per-port MTU setting */
-	rb = smi->chip_data;
+	rb = priv->chip_data;
 	rb->max_mtu[port] = new_mtu;
 
 	/* Roof out the MTU for the entire switch to the greatest
@@ -1406,7 +1406,7 @@ static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
 	else
 		len = RTL8366RB_SGCR_MAX_LENGTH_16000;
 
-	return regmap_update_bits(smi->map, RTL8366RB_SGCR,
+	return regmap_update_bits(priv->map, RTL8366RB_SGCR,
 				  RTL8366RB_SGCR_MAX_LENGTH_MASK,
 				  len);
 }
@@ -1419,7 +1419,7 @@ static int rtl8366rb_max_mtu(struct dsa_switch *ds, int port)
 	return 15996;
 }
 
-static int rtl8366rb_get_vlan_4k(struct realtek_smi *smi, u32 vid,
+static int rtl8366rb_get_vlan_4k(struct realtek_priv *priv, u32 vid,
 				 struct rtl8366_vlan_4k *vlan4k)
 {
 	u32 data[3];
@@ -1432,19 +1432,19 @@ static int rtl8366rb_get_vlan_4k(struct realtek_smi *smi, u32 vid,
 		return -EINVAL;
 
 	/* write VID */
-	ret = regmap_write(smi->map, RTL8366RB_VLAN_TABLE_WRITE_BASE,
+	ret = regmap_write(priv->map, RTL8366RB_VLAN_TABLE_WRITE_BASE,
 			   vid & RTL8366RB_VLAN_VID_MASK);
 	if (ret)
 		return ret;
 
 	/* write table access control word */
-	ret = regmap_write(smi->map, RTL8366RB_TABLE_ACCESS_CTRL_REG,
+	ret = regmap_write(priv->map, RTL8366RB_TABLE_ACCESS_CTRL_REG,
 			   RTL8366RB_TABLE_VLAN_READ_CTRL);
 	if (ret)
 		return ret;
 
 	for (i = 0; i < 3; i++) {
-		ret = regmap_read(smi->map,
+		ret = regmap_read(priv->map,
 				  RTL8366RB_VLAN_TABLE_READ_BASE + i,
 				  &data[i]);
 		if (ret)
@@ -1460,7 +1460,7 @@ static int rtl8366rb_get_vlan_4k(struct realtek_smi *smi, u32 vid,
 	return 0;
 }
 
-static int rtl8366rb_set_vlan_4k(struct realtek_smi *smi,
+static int rtl8366rb_set_vlan_4k(struct realtek_priv *priv,
 				 const struct rtl8366_vlan_4k *vlan4k)
 {
 	u32 data[3];
@@ -1480,7 +1480,7 @@ static int rtl8366rb_set_vlan_4k(struct realtek_smi *smi,
 	data[2] = vlan4k->fid & RTL8366RB_VLAN_FID_MASK;
 
 	for (i = 0; i < 3; i++) {
-		ret = regmap_write(smi->map,
+		ret = regmap_write(priv->map,
 				   RTL8366RB_VLAN_TABLE_WRITE_BASE + i,
 				   data[i]);
 		if (ret)
@@ -1488,13 +1488,13 @@ static int rtl8366rb_set_vlan_4k(struct realtek_smi *smi,
 	}
 
 	/* write table access control word */
-	ret = regmap_write(smi->map, RTL8366RB_TABLE_ACCESS_CTRL_REG,
+	ret = regmap_write(priv->map, RTL8366RB_TABLE_ACCESS_CTRL_REG,
 			   RTL8366RB_TABLE_VLAN_WRITE_CTRL);
 
 	return ret;
 }
 
-static int rtl8366rb_get_vlan_mc(struct realtek_smi *smi, u32 index,
+static int rtl8366rb_get_vlan_mc(struct realtek_priv *priv, u32 index,
 				 struct rtl8366_vlan_mc *vlanmc)
 {
 	u32 data[3];
@@ -1507,7 +1507,7 @@ static int rtl8366rb_get_vlan_mc(struct realtek_smi *smi, u32 index,
 		return -EINVAL;
 
 	for (i = 0; i < 3; i++) {
-		ret = regmap_read(smi->map,
+		ret = regmap_read(priv->map,
 				  RTL8366RB_VLAN_MC_BASE(index) + i,
 				  &data[i]);
 		if (ret)
@@ -1525,7 +1525,7 @@ static int rtl8366rb_get_vlan_mc(struct realtek_smi *smi, u32 index,
 	return 0;
 }
 
-static int rtl8366rb_set_vlan_mc(struct realtek_smi *smi, u32 index,
+static int rtl8366rb_set_vlan_mc(struct realtek_priv *priv, u32 index,
 				 const struct rtl8366_vlan_mc *vlanmc)
 {
 	u32 data[3];
@@ -1549,7 +1549,7 @@ static int rtl8366rb_set_vlan_mc(struct realtek_smi *smi, u32 index,
 	data[2] = vlanmc->fid & RTL8366RB_VLAN_FID_MASK;
 
 	for (i = 0; i < 3; i++) {
-		ret = regmap_write(smi->map,
+		ret = regmap_write(priv->map,
 				   RTL8366RB_VLAN_MC_BASE(index) + i,
 				   data[i]);
 		if (ret)
@@ -1559,15 +1559,15 @@ static int rtl8366rb_set_vlan_mc(struct realtek_smi *smi, u32 index,
 	return 0;
 }
 
-static int rtl8366rb_get_mc_index(struct realtek_smi *smi, int port, int *val)
+static int rtl8366rb_get_mc_index(struct realtek_priv *priv, int port, int *val)
 {
 	u32 data;
 	int ret;
 
-	if (port >= smi->num_ports)
+	if (port >= priv->num_ports)
 		return -EINVAL;
 
-	ret = regmap_read(smi->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
+	ret = regmap_read(priv->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
 			  &data);
 	if (ret)
 		return ret;
@@ -1578,22 +1578,22 @@ static int rtl8366rb_get_mc_index(struct realtek_smi *smi, int port, int *val)
 	return 0;
 }
 
-static int rtl8366rb_set_mc_index(struct realtek_smi *smi, int port, int index)
+static int rtl8366rb_set_mc_index(struct realtek_priv *priv, int port, int index)
 {
 	struct rtl8366rb *rb;
 	bool pvid_enabled;
 	int ret;
 
-	rb = smi->chip_data;
+	rb = priv->chip_data;
 	pvid_enabled = !!index;
 
-	if (port >= smi->num_ports || index >= RTL8366RB_NUM_VLANS)
+	if (port >= priv->num_ports || index >= RTL8366RB_NUM_VLANS)
 		return -EINVAL;
 
-	ret = regmap_update_bits(smi->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
-				RTL8366RB_PORT_VLAN_CTRL_MASK <<
+	ret = regmap_update_bits(priv->map, RTL8366RB_PORT_VLAN_CTRL_REG(port),
+				 RTL8366RB_PORT_VLAN_CTRL_MASK <<
 					RTL8366RB_PORT_VLAN_CTRL_SHIFT(port),
-				(index & RTL8366RB_PORT_VLAN_CTRL_MASK) <<
+				 (index & RTL8366RB_PORT_VLAN_CTRL_MASK) <<
 					RTL8366RB_PORT_VLAN_CTRL_SHIFT(port));
 	if (ret)
 		return ret;
@@ -1604,17 +1604,17 @@ static int rtl8366rb_set_mc_index(struct realtek_smi *smi, int port, int index)
 	 * not drop any untagged or C-tagged frames. Make sure to update the
 	 * filtering setting.
 	 */
-	if (dsa_port_is_vlan_filtering(dsa_to_port(smi->ds, port)))
-		ret = rtl8366rb_drop_untagged(smi, port, !pvid_enabled);
+	if (dsa_port_is_vlan_filtering(dsa_to_port(priv->ds, port)))
+		ret = rtl8366rb_drop_untagged(priv, port, !pvid_enabled);
 
 	return ret;
 }
 
-static bool rtl8366rb_is_vlan_valid(struct realtek_smi *smi, unsigned int vlan)
+static bool rtl8366rb_is_vlan_valid(struct realtek_priv *priv, unsigned int vlan)
 {
 	unsigned int max = RTL8366RB_NUM_VLANS - 1;
 
-	if (smi->vlan4k_enabled)
+	if (priv->vlan4k_enabled)
 		max = RTL8366RB_NUM_VIDS - 1;
 
 	if (vlan > max)
@@ -1623,23 +1623,23 @@ static bool rtl8366rb_is_vlan_valid(struct realtek_smi *smi, unsigned int vlan)
 	return true;
 }
 
-static int rtl8366rb_enable_vlan(struct realtek_smi *smi, bool enable)
+static int rtl8366rb_enable_vlan(struct realtek_priv *priv, bool enable)
 {
-	dev_dbg(smi->dev, "%s VLAN\n", enable ? "enable" : "disable");
-	return regmap_update_bits(smi->map,
+	dev_dbg(priv->dev, "%s VLAN\n", enable ? "enable" : "disable");
+	return regmap_update_bits(priv->map,
 				  RTL8366RB_SGCR, RTL8366RB_SGCR_EN_VLAN,
 				  enable ? RTL8366RB_SGCR_EN_VLAN : 0);
 }
 
-static int rtl8366rb_enable_vlan4k(struct realtek_smi *smi, bool enable)
+static int rtl8366rb_enable_vlan4k(struct realtek_priv *priv, bool enable)
 {
-	dev_dbg(smi->dev, "%s VLAN 4k\n", enable ? "enable" : "disable");
-	return regmap_update_bits(smi->map, RTL8366RB_SGCR,
+	dev_dbg(priv->dev, "%s VLAN 4k\n", enable ? "enable" : "disable");
+	return regmap_update_bits(priv->map, RTL8366RB_SGCR,
 				  RTL8366RB_SGCR_EN_VLAN_4KTB,
 				  enable ? RTL8366RB_SGCR_EN_VLAN_4KTB : 0);
 }
 
-static int rtl8366rb_phy_read(struct realtek_smi *smi, int phy, int regnum)
+static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
 {
 	u32 val;
 	u32 reg;
@@ -1648,32 +1648,32 @@ static int rtl8366rb_phy_read(struct realtek_smi *smi, int phy, int regnum)
 	if (phy > RTL8366RB_PHY_NO_MAX)
 		return -EINVAL;
 
-	ret = regmap_write(smi->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
+	ret = regmap_write(priv->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
 			   RTL8366RB_PHY_CTRL_READ);
 	if (ret)
 		return ret;
 
 	reg = 0x8000 | (1 << (phy + RTL8366RB_PHY_NO_OFFSET)) | regnum;
 
-	ret = regmap_write(smi->map, reg, 0);
+	ret = regmap_write(priv->map, reg, 0);
 	if (ret) {
-		dev_err(smi->dev,
+		dev_err(priv->dev,
 			"failed to write PHY%d reg %04x @ %04x, ret %d\n",
 			phy, regnum, reg, ret);
 		return ret;
 	}
 
-	ret = regmap_read(smi->map, RTL8366RB_PHY_ACCESS_DATA_REG, &val);
+	ret = regmap_read(priv->map, RTL8366RB_PHY_ACCESS_DATA_REG, &val);
 	if (ret)
 		return ret;
 
-	dev_dbg(smi->dev, "read PHY%d register 0x%04x @ %08x, val <- %04x\n",
+	dev_dbg(priv->dev, "read PHY%d register 0x%04x @ %08x, val <- %04x\n",
 		phy, regnum, reg, val);
 
 	return val;
 }
 
-static int rtl8366rb_phy_write(struct realtek_smi *smi, int phy, int regnum,
+static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
 			       u16 val)
 {
 	u32 reg;
@@ -1682,34 +1682,34 @@ static int rtl8366rb_phy_write(struct realtek_smi *smi, int phy, int regnum,
 	if (phy > RTL8366RB_PHY_NO_MAX)
 		return -EINVAL;
 
-	ret = regmap_write(smi->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
+	ret = regmap_write(priv->map, RTL8366RB_PHY_ACCESS_CTRL_REG,
 			   RTL8366RB_PHY_CTRL_WRITE);
 	if (ret)
 		return ret;
 
 	reg = 0x8000 | (1 << (phy + RTL8366RB_PHY_NO_OFFSET)) | regnum;
 
-	dev_dbg(smi->dev, "write PHY%d register 0x%04x @ %04x, val -> %04x\n",
+	dev_dbg(priv->dev, "write PHY%d register 0x%04x @ %04x, val -> %04x\n",
 		phy, regnum, reg, val);
 
-	ret = regmap_write(smi->map, reg, val);
+	ret = regmap_write(priv->map, reg, val);
 	if (ret)
 		return ret;
 
 	return 0;
 }
 
-static int rtl8366rb_reset_chip(struct realtek_smi *smi)
+static int rtl8366rb_reset_chip(struct realtek_priv *priv)
 {
 	int timeout = 10;
 	u32 val;
 	int ret;
 
-	realtek_smi_write_reg_noack(smi, RTL8366RB_RESET_CTRL_REG,
+	realtek_smi_write_reg_noack(priv, RTL8366RB_RESET_CTRL_REG,
 				    RTL8366RB_CHIP_CTRL_RESET_HW);
 	do {
 		usleep_range(20000, 25000);
-		ret = regmap_read(smi->map, RTL8366RB_RESET_CTRL_REG, &val);
+		ret = regmap_read(priv->map, RTL8366RB_RESET_CTRL_REG, &val);
 		if (ret)
 			return ret;
 
@@ -1718,21 +1718,21 @@ static int rtl8366rb_reset_chip(struct realtek_smi *smi)
 	} while (--timeout);
 
 	if (!timeout) {
-		dev_err(smi->dev, "timeout waiting for the switch to reset\n");
+		dev_err(priv->dev, "timeout waiting for the switch to reset\n");
 		return -EIO;
 	}
 
 	return 0;
 }
 
-static int rtl8366rb_detect(struct realtek_smi *smi)
+static int rtl8366rb_detect(struct realtek_priv *priv)
 {
-	struct device *dev = smi->dev;
+	struct device *dev = priv->dev;
 	int ret;
 	u32 val;
 
 	/* Detect device */
-	ret = regmap_read(smi->map, 0x5c, &val);
+	ret = regmap_read(priv->map, 0x5c, &val);
 	if (ret) {
 		dev_err(dev, "can't get chip ID (%d)\n", ret);
 		return ret;
@@ -1745,11 +1745,11 @@ static int rtl8366rb_detect(struct realtek_smi *smi)
 		return -ENODEV;
 	case 0x5937:
 		dev_info(dev, "found an RTL8366RB switch\n");
-		smi->cpu_port = RTL8366RB_PORT_NUM_CPU;
-		smi->num_ports = RTL8366RB_NUM_PORTS;
-		smi->num_vlan_mc = RTL8366RB_NUM_VLANS;
-		smi->mib_counters = rtl8366rb_mib_counters;
-		smi->num_mib_counters = ARRAY_SIZE(rtl8366rb_mib_counters);
+		priv->cpu_port = RTL8366RB_PORT_NUM_CPU;
+		priv->num_ports = RTL8366RB_NUM_PORTS;
+		priv->num_vlan_mc = RTL8366RB_NUM_VLANS;
+		priv->mib_counters = rtl8366rb_mib_counters;
+		priv->num_mib_counters = ARRAY_SIZE(rtl8366rb_mib_counters);
 		break;
 	default:
 		dev_info(dev, "found an Unknown Realtek switch (id=0x%04x)\n",
@@ -1757,7 +1757,7 @@ static int rtl8366rb_detect(struct realtek_smi *smi)
 		break;
 	}
 
-	ret = rtl8366rb_reset_chip(smi);
+	ret = rtl8366rb_reset_chip(priv);
 	if (ret)
 		return ret;
 
@@ -1787,7 +1787,7 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops = {
 	.port_max_mtu = rtl8366rb_max_mtu,
 };
 
-static const struct realtek_smi_ops rtl8366rb_smi_ops = {
+static const struct realtek_ops rtl8366rb_ops = {
 	.detect		= rtl8366rb_detect,
 	.get_vlan_mc	= rtl8366rb_get_vlan_mc,
 	.set_vlan_mc	= rtl8366rb_set_vlan_mc,
@@ -1803,9 +1803,9 @@ static const struct realtek_smi_ops rtl8366rb_smi_ops = {
 	.phy_write	= rtl8366rb_phy_write,
 };
 
-const struct realtek_smi_variant rtl8366rb_variant = {
+const struct realtek_variant rtl8366rb_variant = {
 	.ds_ops = &rtl8366rb_switch_ops,
-	.ops = &rtl8366rb_smi_ops,
+	.ops = &rtl8366rb_ops,
 	.clk_delay = 10,
 	.cmd_read = 0xa9,
 	.cmd_write = 0xa8,
-- 
2.34.0


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

* [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
  2022-01-05  3:15 ` [PATCH net-next v4 01/11] net: dsa: realtek-smi: move to subdirectory Luiz Angelo Daros de Luca
  2022-01-05  3:15 ` [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 12:38   ` Alvin Šipraga
                     ` (2 more replies)
  2022-01-05  3:15 ` [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules Luiz Angelo Daros de Luca
                   ` (8 subsequent siblings)
  11 siblings, 3 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

Remove the only two direct calls from subdrivers to realtek-smi.
Now they are called from realtek_priv. Subdrivers can now be
linked independently from realtek-smi.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/realtek-smi-core.c | 15 +++++++++------
 drivers/net/dsa/realtek/realtek.h          |  7 ++-----
 drivers/net/dsa/realtek/rtl8365mb.c        | 12 +++++++-----
 drivers/net/dsa/realtek/rtl8366rb.c        | 12 +++++++-----
 4 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/net/dsa/realtek/realtek-smi-core.c b/drivers/net/dsa/realtek/realtek-smi-core.c
index 7dfd86a99c24..a917801385c9 100644
--- a/drivers/net/dsa/realtek/realtek-smi-core.c
+++ b/drivers/net/dsa/realtek/realtek-smi-core.c
@@ -292,12 +292,11 @@ static int realtek_smi_write_reg(struct realtek_priv *priv,
  * is when issueing soft reset. Since the device reset as soon as we write
  * that bit, no ACK will come back for natural reasons.
  */
-int realtek_smi_write_reg_noack(struct realtek_priv *priv, u32 addr,
-				u32 data)
+static int realtek_smi_write_reg_noack(struct realtek_priv *priv, u32 addr,
+				       u32 data)
 {
 	return realtek_smi_write_reg(priv, addr, data, false);
 }
-EXPORT_SYMBOL_GPL(realtek_smi_write_reg_noack);
 
 /* Regmap accessors */
 
@@ -342,8 +341,9 @@ static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
 	return priv->ops->phy_write(priv, addr, regnum, val);
 }
 
-int realtek_smi_setup_mdio(struct realtek_priv *priv)
+static int realtek_smi_setup_mdio(struct dsa_switch *ds)
 {
+	struct realtek_priv *priv =  ds->priv;
 	struct device_node *mdio_np;
 	int ret;
 
@@ -363,10 +363,10 @@ int realtek_smi_setup_mdio(struct realtek_priv *priv)
 	priv->slave_mii_bus->read = realtek_smi_mdio_read;
 	priv->slave_mii_bus->write = realtek_smi_mdio_write;
 	snprintf(priv->slave_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
-		 priv->ds->index);
+		 ds->index);
 	priv->slave_mii_bus->dev.of_node = mdio_np;
 	priv->slave_mii_bus->parent = priv->dev;
-	priv->ds->slave_mii_bus = priv->slave_mii_bus;
+	ds->slave_mii_bus = priv->slave_mii_bus;
 
 	ret = devm_of_mdiobus_register(priv->dev, priv->slave_mii_bus, mdio_np);
 	if (ret) {
@@ -413,6 +413,9 @@ static int realtek_smi_probe(struct platform_device *pdev)
 	priv->cmd_write = var->cmd_write;
 	priv->ops = var->ops;
 
+	priv->setup_interface = realtek_smi_setup_mdio;
+	priv->write_reg_noack = realtek_smi_write_reg_noack;
+
 	dev_set_drvdata(dev, priv);
 	spin_lock_init(&priv->lock);
 
diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index 177fff90b8a6..58814de563a2 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -66,6 +66,8 @@ struct realtek_priv {
 	struct rtl8366_mib_counter *mib_counters;
 
 	const struct realtek_ops *ops;
+	int			(*setup_interface)(struct dsa_switch *ds);
+	int			(*write_reg_noack)(struct realtek_priv *priv, u32 addr, u32 data);
 
 	int			vlan_enabled;
 	int			vlan4k_enabled;
@@ -115,11 +117,6 @@ struct realtek_variant {
 	size_t chip_data_sz;
 };
 
-/* SMI core calls */
-int realtek_smi_write_reg_noack(struct realtek_priv *priv, u32 addr,
-				u32 data);
-int realtek_smi_setup_mdio(struct realtek_priv *priv);
-
 /* RTL8366 library helpers */
 int rtl8366_mc_is_used(struct realtek_priv *priv, int mc_index, int *used);
 int rtl8366_set_vlan(struct realtek_priv *priv, int vid, u32 member,
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 6b8797ba80c6..5fb453b5f650 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -1767,7 +1767,7 @@ static int rtl8365mb_reset_chip(struct realtek_priv *priv)
 {
 	u32 val;
 
-	realtek_smi_write_reg_noack(priv, RTL8365MB_CHIP_RESET_REG,
+	priv->write_reg_noack(priv, RTL8365MB_CHIP_RESET_REG,
 				    FIELD_PREP(RTL8365MB_CHIP_RESET_HW_MASK,
 					       1));
 
@@ -1849,10 +1849,12 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 	if (ret)
 		goto out_teardown_irq;
 
-	ret = realtek_smi_setup_mdio(priv);
-	if (ret) {
-		dev_err(priv->dev, "could not set up MDIO bus\n");
-		goto out_teardown_irq;
+	if (priv->setup_interface) {
+		ret = priv->setup_interface(ds);
+		if (ret) {
+			dev_err(priv->dev, "could not set up MDIO bus\n");
+			goto out_teardown_irq;
+		}
 	}
 
 	/* Start statistics counter polling */
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 241e6b6ebea5..34e371084d6d 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1030,10 +1030,12 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	if (ret)
 		dev_info(priv->dev, "no interrupt support\n");
 
-	ret = realtek_smi_setup_mdio(priv);
-	if (ret) {
-		dev_info(priv->dev, "could not set up MDIO bus\n");
-		return -ENODEV;
+	if (priv->setup_interface) {
+		ret = priv->setup_interface(ds);
+		if (ret) {
+			dev_err(priv->dev, "could not set up MDIO bus\n");
+			return -ENODEV;
+		}
 	}
 
 	return 0;
@@ -1705,7 +1707,7 @@ static int rtl8366rb_reset_chip(struct realtek_priv *priv)
 	u32 val;
 	int ret;
 
-	realtek_smi_write_reg_noack(priv, RTL8366RB_RESET_CTRL_REG,
+	priv->write_reg_noack(priv, RTL8366RB_RESET_CTRL_REG,
 				    RTL8366RB_CHIP_CTRL_RESET_HW);
 	do {
 		usleep_range(20000, 25000);
-- 
2.34.0


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

* [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (2 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 12:43   ` Alvin Šipraga
  2022-01-17  4:02   ` Florian Fainelli
  2022-01-05  3:15 ` [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops Luiz Angelo Daros de Luca
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

Preparing for multiple interfaces support, the drivers
must be independent of realtek-smi.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/net/dsa/realtek/Kconfig               | 20 +++++++++++++++++--
 drivers/net/dsa/realtek/Makefile              |  4 +++-
 .../{realtek-smi-core.c => realtek-smi.c}     |  6 ++++++
 drivers/net/dsa/realtek/rtl8365mb.c           |  4 ++++
 .../dsa/realtek/{rtl8366.c => rtl8366-core.c} |  0
 drivers/net/dsa/realtek/rtl8366rb.c           |  4 ++++
 6 files changed, 35 insertions(+), 3 deletions(-)
 rename drivers/net/dsa/realtek/{realtek-smi-core.c => realtek-smi.c} (97%)
 rename drivers/net/dsa/realtek/{rtl8366.c => rtl8366-core.c} (100%)

diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
index 1c62212fb0ec..cd1aa95b7bf0 100644
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -2,8 +2,6 @@
 menuconfig NET_DSA_REALTEK
 	tristate "Realtek Ethernet switch family support"
 	depends on NET_DSA
-	select NET_DSA_TAG_RTL4_A
-	select NET_DSA_TAG_RTL8_4
 	select FIXED_PHY
 	select IRQ_DOMAIN
 	select REALTEK_PHY
@@ -18,3 +16,21 @@ config NET_DSA_REALTEK_SMI
 	help
 	  Select to enable support for registering switches connected
 	  through SMI.
+
+config NET_DSA_REALTEK_RTL8365MB
+	tristate "Realtek RTL8365MB switch subdriver"
+	default y
+	depends on NET_DSA_REALTEK
+	depends on NET_DSA_REALTEK_SMI
+	select NET_DSA_TAG_RTL8_4
+	help
+	  Select to enable support for Realtek RTL8365MB
+
+config NET_DSA_REALTEK_RTL8366RB
+	tristate "Realtek RTL8366RB switch subdriver"
+	default y
+	depends on NET_DSA_REALTEK
+	depends on NET_DSA_REALTEK_SMI
+	select NET_DSA_TAG_RTL4_A
+	help
+	  Select to enable support for Realtek RTL8366RB
diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
index 323b921bfce0..8b5a4abcedd3 100644
--- a/drivers/net/dsa/realtek/Makefile
+++ b/drivers/net/dsa/realtek/Makefile
@@ -1,3 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_NET_DSA_REALTEK_SMI) 	+= realtek-smi.o
-realtek-smi-objs			:= realtek-smi-core.o rtl8366.o rtl8366rb.o rtl8365mb.o
+obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
+rtl8366-objs 				:= rtl8366-core.o rtl8366rb.o
+obj-$(CONFIG_NET_DSA_REALTEK_RTL8365MB) += rtl8365mb.o
diff --git a/drivers/net/dsa/realtek/realtek-smi-core.c b/drivers/net/dsa/realtek/realtek-smi.c
similarity index 97%
rename from drivers/net/dsa/realtek/realtek-smi-core.c
rename to drivers/net/dsa/realtek/realtek-smi.c
index a917801385c9..5514fe81d64f 100644
--- a/drivers/net/dsa/realtek/realtek-smi-core.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -495,19 +495,23 @@ static void realtek_smi_shutdown(struct platform_device *pdev)
 }
 
 static const struct of_device_id realtek_smi_of_match[] = {
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
 	{
 		.compatible = "realtek,rtl8366rb",
 		.data = &rtl8366rb_variant,
 	},
+#endif
 	{
 		/* FIXME: add support for RTL8366S and more */
 		.compatible = "realtek,rtl8366s",
 		.data = NULL,
 	},
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
 	{
 		.compatible = "realtek,rtl8365mb",
 		.data = &rtl8365mb_variant,
 	},
+#endif
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
@@ -523,4 +527,6 @@ static struct platform_driver realtek_smi_driver = {
 };
 module_platform_driver(realtek_smi_driver);
 
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 5fb453b5f650..b52bb987027c 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -1987,3 +1987,7 @@ const struct realtek_variant rtl8365mb_variant = {
 	.chip_data_sz = sizeof(struct rtl8365mb),
 };
 EXPORT_SYMBOL_GPL(rtl8365mb_variant);
+
+MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
+MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/realtek/rtl8366.c b/drivers/net/dsa/realtek/rtl8366-core.c
similarity index 100%
rename from drivers/net/dsa/realtek/rtl8366.c
rename to drivers/net/dsa/realtek/rtl8366-core.c
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 34e371084d6d..ff607608dead 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1814,3 +1814,7 @@ const struct realtek_variant rtl8366rb_variant = {
 	.chip_data_sz = sizeof(struct rtl8366rb),
 };
 EXPORT_SYMBOL_GPL(rtl8366rb_variant);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
+MODULE_LICENSE("GPL");
-- 
2.34.0


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

* [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (3 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 13:09   ` Alvin Šipraga
  2022-01-17  4:15   ` Florian Fainelli
  2022-01-05  3:15 ` [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers Luiz Angelo Daros de Luca
                   ` (6 subsequent siblings)
  11 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

The ds->ops->phy_read will only be used if the ds->slave_mii_bus
was not initialized. Calling realtek_smi_setup_mdio will create a
ds->slave_mii_bus, making ds->ops->phy_read dormant.

Using ds->ops->phy_read will allow switches connected through non-SMI
interfaces (like mdio) to let ds allocate slave_mii_bus and reuse the
same code.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/net/dsa/realtek/realtek-smi.c |  6 ++++--
 drivers/net/dsa/realtek/realtek.h     |  3 ---
 drivers/net/dsa/realtek/rtl8365mb.c   | 10 ++++++----
 drivers/net/dsa/realtek/rtl8366rb.c   | 10 ++++++----
 4 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 5514fe81d64f..1f024e2520a6 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -329,16 +329,18 @@ static const struct regmap_config realtek_smi_mdio_regmap_config = {
 static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
 {
 	struct realtek_priv *priv = bus->priv;
+	struct dsa_switch *ds = priv->ds;
 
-	return priv->ops->phy_read(priv, addr, regnum);
+	return ds->ops->phy_read(ds, addr, regnum);
 }
 
 static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
 				  u16 val)
 {
 	struct realtek_priv *priv = bus->priv;
+	struct dsa_switch *ds = priv->ds;
 
-	return priv->ops->phy_write(priv, addr, regnum, val);
+	return ds->ops->phy_write(ds, addr, regnum, val);
 }
 
 static int realtek_smi_setup_mdio(struct dsa_switch *ds)
diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index 58814de563a2..a03de15c4a94 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -103,9 +103,6 @@ struct realtek_ops {
 	int	(*enable_vlan)(struct realtek_priv *priv, bool enable);
 	int	(*enable_vlan4k)(struct realtek_priv *priv, bool enable);
 	int	(*enable_port)(struct realtek_priv *priv, int port, bool enable);
-	int	(*phy_read)(struct realtek_priv *priv, int phy, int regnum);
-	int	(*phy_write)(struct realtek_priv *priv, int phy, int regnum,
-			     u16 val);
 };
 
 struct realtek_variant {
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index b52bb987027c..11a985900c57 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -674,8 +674,9 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
 	return 0;
 }
 
-static int rtl8365mb_phy_read(struct realtek_priv *priv, int phy, int regnum)
+static int rtl8365mb_phy_read(struct dsa_switch *ds, int phy, int regnum)
 {
+	struct realtek_priv *priv = ds->priv;
 	u32 ocp_addr;
 	u16 val;
 	int ret;
@@ -702,9 +703,10 @@ static int rtl8365mb_phy_read(struct realtek_priv *priv, int phy, int regnum)
 	return val;
 }
 
-static int rtl8365mb_phy_write(struct realtek_priv *priv, int phy, int regnum,
+static int rtl8365mb_phy_write(struct dsa_switch *ds, int phy, int regnum,
 			       u16 val)
 {
+	struct realtek_priv *priv = (struct realtek_priv *)ds->priv;
 	u32 ocp_addr;
 	int ret;
 
@@ -1958,6 +1960,8 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
 	.get_tag_protocol = rtl8365mb_get_tag_protocol,
 	.setup = rtl8365mb_setup,
 	.teardown = rtl8365mb_teardown,
+	.phy_read = rtl8365mb_phy_read,
+	.phy_write = rtl8365mb_phy_write,
 	.phylink_validate = rtl8365mb_phylink_validate,
 	.phylink_mac_config = rtl8365mb_phylink_mac_config,
 	.phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
@@ -1974,8 +1978,6 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
 
 static const struct realtek_ops rtl8365mb_ops = {
 	.detect = rtl8365mb_detect,
-	.phy_read = rtl8365mb_phy_read,
-	.phy_write = rtl8365mb_phy_write,
 };
 
 const struct realtek_variant rtl8365mb_variant = {
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index ff607608dead..4576f9b797c5 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1641,8 +1641,9 @@ static int rtl8366rb_enable_vlan4k(struct realtek_priv *priv, bool enable)
 				  enable ? RTL8366RB_SGCR_EN_VLAN_4KTB : 0);
 }
 
-static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
+static int rtl8366rb_phy_read(struct dsa_switch *ds, int phy, int regnum)
 {
+	struct realtek_priv *priv = ds->priv;
 	u32 val;
 	u32 reg;
 	int ret;
@@ -1675,9 +1676,10 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
 	return val;
 }
 
-static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
+static int rtl8366rb_phy_write(struct dsa_switch *ds, int phy, int regnum,
 			       u16 val)
 {
+	struct realtek_priv *priv = ds->priv;
 	u32 reg;
 	int ret;
 
@@ -1769,6 +1771,8 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
 static const struct dsa_switch_ops rtl8366rb_switch_ops = {
 	.get_tag_protocol = rtl8366_get_tag_protocol,
 	.setup = rtl8366rb_setup,
+	.phy_read = rtl8366rb_phy_read,
+	.phy_write = rtl8366rb_phy_write,
 	.phylink_mac_link_up = rtl8366rb_mac_link_up,
 	.phylink_mac_link_down = rtl8366rb_mac_link_down,
 	.get_strings = rtl8366_get_strings,
@@ -1801,8 +1805,6 @@ static const struct realtek_ops rtl8366rb_ops = {
 	.is_vlan_valid	= rtl8366rb_is_vlan_valid,
 	.enable_vlan	= rtl8366rb_enable_vlan,
 	.enable_vlan4k	= rtl8366rb_enable_vlan4k,
-	.phy_read	= rtl8366rb_phy_read,
-	.phy_write	= rtl8366rb_phy_write,
 };
 
 const struct realtek_variant rtl8366rb_variant = {
-- 
2.34.0


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

* [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (4 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 13:09   ` Alvin Šipraga
  2022-01-17  4:22   ` Florian Fainelli
  2022-01-05  3:15 ` [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int" Luiz Angelo Daros de Luca
                   ` (5 subsequent siblings)
  11 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

This driver is a mdio_driver instead of a platform driver (like
realtek-smi).

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
---
 drivers/net/dsa/realtek/Kconfig        |  11 +-
 drivers/net/dsa/realtek/Makefile       |   1 +
 drivers/net/dsa/realtek/realtek-mdio.c | 221 +++++++++++++++++++++++++
 drivers/net/dsa/realtek/realtek.h      |   2 +
 4 files changed, 233 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/dsa/realtek/realtek-mdio.c

diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
index cd1aa95b7bf0..73b26171fade 100644
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -9,6 +9,13 @@ menuconfig NET_DSA_REALTEK
 	help
 	  Select to enable support for Realtek Ethernet switch chips.
 
+config NET_DSA_REALTEK_MDIO
+	tristate "Realtek MDIO connected switch driver"
+	depends on NET_DSA_REALTEK
+	default y
+	help
+	  Select to enable support for registering switches configured
+	  through MDIO.
 config NET_DSA_REALTEK_SMI
 	tristate "Realtek SMI connected switch driver"
 	depends on NET_DSA_REALTEK
@@ -21,7 +28,7 @@ config NET_DSA_REALTEK_RTL8365MB
 	tristate "Realtek RTL8365MB switch subdriver"
 	default y
 	depends on NET_DSA_REALTEK
-	depends on NET_DSA_REALTEK_SMI
+	depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
 	select NET_DSA_TAG_RTL8_4
 	help
 	  Select to enable support for Realtek RTL8365MB
@@ -30,7 +37,7 @@ config NET_DSA_REALTEK_RTL8366RB
 	tristate "Realtek RTL8366RB switch subdriver"
 	default y
 	depends on NET_DSA_REALTEK
-	depends on NET_DSA_REALTEK_SMI
+	depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
 	select NET_DSA_TAG_RTL4_A
 	help
 	  Select to enable support for Realtek RTL8366RB
diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
index 8b5a4abcedd3..0aab57252a7c 100644
--- a/drivers/net/dsa/realtek/Makefile
+++ b/drivers/net/dsa/realtek/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_NET_DSA_REALTEK_MDIO) 	+= realtek-mdio.o
 obj-$(CONFIG_NET_DSA_REALTEK_SMI) 	+= realtek-smi.o
 obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
 rtl8366-objs 				:= rtl8366-core.o rtl8366rb.o
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
new file mode 100644
index 000000000000..b505f4d3c5f0
--- /dev/null
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Realtek MDIO interface driver
+ *
+ * ASICs we intend to support with this driver:
+ *
+ * RTL8366   - The original version, apparently
+ * RTL8369   - Similar enough to have the same datsheet as RTL8366
+ * RTL8366RB - Probably reads out "RTL8366 revision B", has a quite
+ *             different register layout from the other two
+ * RTL8366S  - Is this "RTL8366 super"?
+ * RTL8367   - Has an OpenWRT driver as well
+ * RTL8368S  - Seems to be an alternative name for RTL8366RB
+ * RTL8370   - Also uses SMI
+ *
+ * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
+ * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
+ * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
+ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include "realtek.h"
+
+/* Read/write via mdiobus */
+#define REALTEK_MDIO_CTRL0_REG		31
+#define REALTEK_MDIO_START_REG		29
+#define REALTEK_MDIO_CTRL1_REG		21
+#define REALTEK_MDIO_ADDRESS_REG	23
+#define REALTEK_MDIO_DATA_WRITE_REG	24
+#define REALTEK_MDIO_DATA_READ_REG	25
+
+#define REALTEK_MDIO_START_OP		0xFFFF
+#define REALTEK_MDIO_ADDR_OP		0x000E
+#define REALTEK_MDIO_READ_OP		0x0001
+#define REALTEK_MDIO_WRITE_OP		0x0003
+
+static int realtek_mdio_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
+{
+	u32 phy_id = priv->phy_id;
+	struct mii_bus *bus = priv->bus;
+
+	mutex_lock(&bus->mdio_lock);
+
+	bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);
+	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
+	*data = bus->read(bus, phy_id, REALTEK_MDIO_DATA_READ_REG);
+
+	mutex_unlock(&bus->mdio_lock);
+
+	return 0;
+}
+
+static int realtek_mdio_write_reg(struct realtek_priv *priv, u32 addr, u32 data)
+{
+	u32 phy_id = priv->phy_id;
+	struct mii_bus *bus = priv->bus;
+
+	mutex_lock(&bus->mdio_lock);
+
+	bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);
+	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_DATA_WRITE_REG, data);
+	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
+	bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP);
+
+	mutex_unlock(&bus->mdio_lock);
+
+	return 0;
+}
+
+/* Regmap accessors */
+
+static int realtek_mdio_write(void *ctx, u32 reg, u32 val)
+{
+	struct realtek_priv *priv = ctx;
+
+	return realtek_mdio_write_reg(priv, reg, val);
+}
+
+static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
+{
+	struct realtek_priv *priv = ctx;
+
+	return realtek_mdio_read_reg(priv, reg, val);
+}
+
+static const struct regmap_config realtek_mdio_regmap_config = {
+	.reg_bits = 10, /* A4..A0 R4..R0 */
+	.val_bits = 16,
+	.reg_stride = 1,
+	/* PHY regs are at 0x8000 */
+	.max_register = 0xffff,
+	.reg_format_endian = REGMAP_ENDIAN_BIG,
+	.reg_read = realtek_mdio_read,
+	.reg_write = realtek_mdio_write,
+	.cache_type = REGCACHE_NONE,
+};
+
+static int realtek_mdio_probe(struct mdio_device *mdiodev)
+{
+	struct realtek_priv *priv;
+	struct device *dev = &mdiodev->dev;
+	const struct realtek_variant *var;
+	int ret;
+	struct device_node *np;
+
+	var = of_device_get_match_data(dev);
+	priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->map = devm_regmap_init(dev, NULL, priv, &realtek_mdio_regmap_config);
+	if (IS_ERR(priv->map)) {
+		ret = PTR_ERR(priv->map);
+		dev_err(dev, "regmap init failed: %d\n", ret);
+		return ret;
+	}
+
+	priv->phy_id = mdiodev->addr;
+	priv->bus = mdiodev->bus;
+	priv->dev = &mdiodev->dev;
+	priv->chip_data = (void *)priv + sizeof(*priv);
+
+	priv->clk_delay = var->clk_delay;
+	priv->cmd_read = var->cmd_read;
+	priv->cmd_write = var->cmd_write;
+	priv->ops = var->ops;
+
+	priv->write_reg_noack = realtek_mdio_write_reg;
+
+	np = dev->of_node;
+
+	dev_set_drvdata(dev, priv);
+
+	/* TODO: if power is software controlled, set up any regulators here */
+	priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
+
+	ret = priv->ops->detect(priv);
+	if (ret) {
+		dev_err(dev, "unable to detect switch\n");
+		return ret;
+	}
+
+	priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
+	if (!priv->ds)
+		return -ENOMEM;
+
+	priv->ds->dev = dev;
+	priv->ds->num_ports = priv->num_ports;
+	priv->ds->priv = priv;
+	priv->ds->ops = var->ds_ops;
+
+	ret = dsa_register_switch(priv->ds);
+	if (ret) {
+		dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void realtek_mdio_remove(struct mdio_device *mdiodev)
+{
+	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
+
+	if (!priv)
+		return;
+
+	dsa_unregister_switch(priv->ds);
+
+	dev_set_drvdata(&mdiodev->dev, NULL);
+}
+
+static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
+{
+	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
+
+	if (!priv)
+		return;
+
+	dsa_switch_shutdown(priv->ds);
+
+	dev_set_drvdata(&mdiodev->dev, NULL);
+}
+
+static const struct of_device_id realtek_mdio_of_match[] = {
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
+	{ .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
+	{ .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
+#endif
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, realtek_mdio_of_match);
+
+static struct mdio_driver realtek_mdio_driver = {
+	.mdiodrv.driver = {
+		.name = "realtek-mdio",
+		.of_match_table = of_match_ptr(realtek_mdio_of_match),
+	},
+	.probe  = realtek_mdio_probe,
+	.remove = realtek_mdio_remove,
+	.shutdown = realtek_mdio_shutdown,
+};
+
+mdio_module_driver(realtek_mdio_driver);
+
+MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
+MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index a03de15c4a94..97274273cb3b 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -50,6 +50,8 @@ struct realtek_priv {
 	struct gpio_desc	*mdio;
 	struct regmap		*map;
 	struct mii_bus		*slave_mii_bus;
+	struct mii_bus		*bus;
+	int			phy_id;
 
 	unsigned int		clk_delay;
 	u8			cmd_read;
-- 
2.34.0


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

* [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int"
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (5 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 13:15   ` Alvin Šipraga
  2022-01-17  4:25   ` Florian Fainelli
  2022-01-05  3:15 ` [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1 Luiz Angelo Daros de Luca
                   ` (4 subsequent siblings)
  11 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

"extport" 0, 1, 2 was used to reference external ports (ext0,
ext1, ext2). Meanwhile, port 0..9 is used as switch ports,
including external ports. "extport" was renamed to extint to
make it clear it does not mean the port number but the external
interface number.

The macros that map extint numbers to registers addresses now
use inline ifs instead of binary arithmetic.

"extint" was hardcoded to 1. However, some chips have multiple
external interfaces. It's not right to assume the CPU port uses
extint 1 nor that all extint are CPU ports. Now the association
between the port and the external interface can be defined with
a device-tree port property "realtek,ext-int".

This patch still does not allow multiple CPU ports nor extint
as a non CPU port.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
---
 drivers/net/dsa/realtek/rtl8365mb.c | 135 ++++++++++++++++++----------
 1 file changed, 88 insertions(+), 47 deletions(-)

diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 11a985900c57..e115129cd5cd 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -191,7 +191,13 @@
 /* The PHY OCP addresses of PHY registers 0~31 start here */
 #define RTL8365MB_PHY_OCP_ADDR_PHYREG_BASE		0xA400
 
-/* EXT port interface mode values - used in DIGITAL_INTERFACE_SELECT */
+/* EXT interface numbers */
+#define RTL8365MB_NOT_EXT			-1
+#define RTL8365MB_EXT0				 0
+#define RTL8365MB_EXT1				 1
+#define RTL8365MB_EXT2				 2
+
+/* EXT interface port mode values - used in DIGITAL_INTERFACE_SELECT */
 #define RTL8365MB_EXT_PORT_MODE_DISABLE		0
 #define RTL8365MB_EXT_PORT_MODE_RGMII		1
 #define RTL8365MB_EXT_PORT_MODE_MII_MAC		2
@@ -207,39 +213,44 @@
 #define RTL8365MB_EXT_PORT_MODE_1000X		12
 #define RTL8365MB_EXT_PORT_MODE_100FX		13
 
-/* EXT port interface mode configuration registers 0~1 */
-#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0		0x1305
-#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG1		0x13C3
-#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(_extport)   \
-		(RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 + \
-		 ((_extport) >> 1) * (0x13C3 - 0x1305))
-#define   RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(_extport) \
-		(0xF << (((_extport) % 2)))
-#define   RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_OFFSET(_extport) \
-		(((_extport) % 2) * 4)
-
-/* EXT port RGMII TX/RX delay configuration registers 1~2 */
-#define RTL8365MB_EXT_RGMXF_REG1		0x1307
-#define RTL8365MB_EXT_RGMXF_REG2		0x13C5
-#define RTL8365MB_EXT_RGMXF_REG(_extport)   \
-		(RTL8365MB_EXT_RGMXF_REG1 + \
-		 (((_extport) >> 1) * (0x13C5 - 0x1307)))
+/* EXT interface mode configuration registers 0~1 */
+#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0		0x1305 /* EXT1 */
+#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG1		0x13C3 /* EXT2 */
+#define RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(_extint) \
+		((_extint) == 1 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG0 : \
+		 (_extint) == 2 ? RTL8365MB_DIGITAL_INTERFACE_SELECT_REG1 : \
+		 0x0)
+#define   RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(_extint) \
+		(0xF << (((_extint) % 2)))
+#define   RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_OFFSET(_extint) \
+		(((_extint) % 2) * 4)
+
+/* EXT interface RGMII TX/RX delay configuration registers 0~2 */
+#define RTL8365MB_EXT_RGMXF_REG0		0x1306 /* EXT0 */
+#define RTL8365MB_EXT_RGMXF_REG1		0x1307 /* EXT1 */
+#define RTL8365MB_EXT_RGMXF_REG2		0x13C5 /* EXT2 */
+#define RTL8365MB_EXT_RGMXF_REG(_extint) \
+		((_extint) == 0 ? RTL8365MB_EXT_RGMXF_REG0 : \
+		 (_extint) == 1 ? RTL8365MB_EXT_RGMXF_REG1 : \
+		 (_extint) == 2 ? RTL8365MB_EXT_RGMXF_REG2 : \
+		 0x0)
 #define   RTL8365MB_EXT_RGMXF_RXDELAY_MASK	0x0007
 #define   RTL8365MB_EXT_RGMXF_TXDELAY_MASK	0x0008
 
-/* External port speed values - used in DIGITAL_INTERFACE_FORCE */
+/* External interface port speed values - used in DIGITAL_INTERFACE_FORCE */
 #define RTL8365MB_PORT_SPEED_10M	0
 #define RTL8365MB_PORT_SPEED_100M	1
 #define RTL8365MB_PORT_SPEED_1000M	2
 
-/* EXT port force configuration registers 0~2 */
-#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG0			0x1310
-#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG1			0x1311
-#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG2			0x13C4
-#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG(_extport)   \
-		(RTL8365MB_DIGITAL_INTERFACE_FORCE_REG0 + \
-		 ((_extport) & 0x1) +                     \
-		 ((((_extport) >> 1) & 0x1) * (0x13C4 - 0x1310)))
+/* EXT interface force configuration registers 0~2 */
+#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG0		0x1310 /* EXT0 */
+#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG1		0x1311 /* EXT1 */
+#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG2		0x13C4 /* EXT2 */
+#define RTL8365MB_DIGITAL_INTERFACE_FORCE_REG(_extint) \
+		((_extint) == 0 ? RTL8365MB_DIGITAL_INTERFACE_FORCE_REG0 : \
+		 (_extint) == 1 ? RTL8365MB_DIGITAL_INTERFACE_FORCE_REG1 : \
+		 (_extint) == 2 ? RTL8365MB_DIGITAL_INTERFACE_FORCE_REG2 : \
+		 0x0)
 #define   RTL8365MB_DIGITAL_INTERFACE_FORCE_EN_MASK		0x1000
 #define   RTL8365MB_DIGITAL_INTERFACE_FORCE_NWAY_MASK		0x0080
 #define   RTL8365MB_DIGITAL_INTERFACE_FORCE_TXPAUSE_MASK	0x0040
@@ -522,6 +533,7 @@ struct rtl8365mb_cpu {
  *         access via rtl8365mb_get_stats64
  * @stats_lock: protect the stats structure during read/update
  * @mib_work: delayed work for polling MIB counters
+ * @ext_int: the external interface port related to this port, RTL8365MB_NOT_EXT(-1) if none
  */
 struct rtl8365mb_port {
 	struct realtek_priv *priv;
@@ -529,6 +541,7 @@ struct rtl8365mb_port {
 	struct rtnl_link_stats64 stats;
 	spinlock_t stats_lock;
 	struct delayed_work mib_work;
+	int ext_int;
 };
 
 /**
@@ -742,24 +755,28 @@ rtl8365mb_get_tag_protocol(struct dsa_switch *ds, int port,
 static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port,
 				      phy_interface_t interface)
 {
+	struct rtl8365mb_port *p;
 	struct device_node *dn;
+	struct rtl8365mb *mb;
 	struct dsa_port *dp;
 	int tx_delay = 0;
 	int rx_delay = 0;
-	int ext_port;
+	int ext_int;
 	u32 val;
 	int ret;
 
-	if (port == priv->cpu_port) {
-		ext_port = 1;
-	} else {
-		dev_err(priv->dev, "only one EXT port is currently supported\n");
+	if (port != priv->cpu_port) {
+		dev_err(priv->dev, "only one EXT interface is currently supported\n");
 		return -EINVAL;
 	}
 
 	dp = dsa_to_port(priv->ds, port);
 	dn = dp->dn;
 
+	mb = priv->chip_data;
+	p = &mb->ports[port];
+	ext_int = p->ext_int;
+
 	/* Set the RGMII TX/RX delay
 	 *
 	 * The Realtek vendor driver indicates the following possible
@@ -789,7 +806,7 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port,
 			tx_delay = val / 2;
 		else
 			dev_warn(priv->dev,
-				 "EXT port TX delay must be 0 or 2 ns\n");
+				 "EXT interface TX delay must be 0 or 2 ns\n");
 	}
 
 	if (!of_property_read_u32(dn, "rx-internal-delay-ps", &val)) {
@@ -799,11 +816,11 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port,
 			rx_delay = val;
 		else
 			dev_warn(priv->dev,
-				 "EXT port RX delay must be 0 to 2.1 ns\n");
+				 "EXT interface RX delay must be 0 to 2.1 ns\n");
 	}
 
 	ret = regmap_update_bits(
-		priv->map, RTL8365MB_EXT_RGMXF_REG(ext_port),
+		priv->map, RTL8365MB_EXT_RGMXF_REG(ext_int),
 		RTL8365MB_EXT_RGMXF_TXDELAY_MASK |
 			RTL8365MB_EXT_RGMXF_RXDELAY_MASK,
 		FIELD_PREP(RTL8365MB_EXT_RGMXF_TXDELAY_MASK, tx_delay) |
@@ -812,11 +829,11 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port,
 		return ret;
 
 	ret = regmap_update_bits(
-		priv->map, RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(ext_port),
-		RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(ext_port),
+		priv->map, RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(ext_int),
+		RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(ext_int),
 		RTL8365MB_EXT_PORT_MODE_RGMII
 			<< RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_OFFSET(
-				   ext_port));
+				   ext_int));
 	if (ret)
 		return ret;
 
@@ -827,22 +844,26 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_priv *priv, int port,
 					  bool link, int speed, int duplex,
 					  bool tx_pause, bool rx_pause)
 {
+	struct rtl8365mb_port *p;
+	struct rtl8365mb *mb;
 	u32 r_tx_pause;
 	u32 r_rx_pause;
 	u32 r_duplex;
 	u32 r_speed;
 	u32 r_link;
-	int ext_port;
+	int ext_int;
 	int val;
 	int ret;
 
-	if (port == priv->cpu_port) {
-		ext_port = 1;
-	} else {
-		dev_err(priv->dev, "only one EXT port is currently supported\n");
+	if (port != priv->cpu_port) {
+		dev_err(priv->dev, "only one EXT interface is currently supported\n");
 		return -EINVAL;
 	}
 
+	mb = priv->chip_data;
+	p = &mb->ports[port];
+	ext_int = p->ext_int;
+
 	if (link) {
 		/* Force the link up with the desired configuration */
 		r_link = 1;
@@ -889,7 +910,7 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_priv *priv, int port,
 			 r_duplex) |
 	      FIELD_PREP(RTL8365MB_DIGITAL_INTERFACE_FORCE_SPEED_MASK, r_speed);
 	ret = regmap_write(priv->map,
-			   RTL8365MB_DIGITAL_INTERFACE_FORCE_REG(ext_port),
+			   RTL8365MB_DIGITAL_INTERFACE_FORCE_REG(ext_int),
 			   val);
 	if (ret)
 		return ret;
@@ -1819,13 +1840,13 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 	/* Configure ports */
 	for (i = 0; i < priv->num_ports; i++) {
 		struct rtl8365mb_port *p = &mb->ports[i];
+		struct device_node *dn;
+		u32 val;
 
 		if (dsa_is_unused_port(priv->ds, i))
 			continue;
 
-		/* Set up per-port private data */
-		p->priv = priv;
-		p->index = i;
+		dn = dsa_to_port(priv->ds, i)->dn;
 
 		/* Forward only to the CPU */
 		ret = rtl8365mb_port_set_isolation(priv, i, BIT(priv->cpu_port));
@@ -1842,6 +1863,26 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 		 * administratively down by default.
 		 */
 		rtl8365mb_port_stp_state_set(priv->ds, i, BR_STATE_DISABLED);
+
+		/* Set up per-port private data */
+		p->priv = priv;
+		p->index = i;
+
+		if (!of_property_read_u32(dn, "realtek,ext-int", &val)) {
+			if (val < 0 || val > 2) {
+				dev_err(priv->dev,
+					"realtek,ext-int must be between 0 and 2\n");
+				return -EINVAL;
+			}
+
+			p->ext_int = val;
+		} else {
+			if (dsa_is_cpu_port(priv->ds, i))
+				/* Default for compatibility with older device trees */
+				p->ext_int = RTL8365MB_EXT1;
+			else
+				p->ext_int = RTL8365MB_NOT_EXT;
+		}
 	}
 
 	/* Set maximum packet length to 1536 bytes */
-- 
2.34.0


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

* [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (6 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int" Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 13:18   ` Alvin Šipraga
  2022-01-17  4:25   ` Florian Fainelli
  2022-01-05  3:15 ` [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port Luiz Angelo Daros de Luca
                   ` (3 subsequent siblings)
  11 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/net/dsa/realtek/rtl8365mb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index e115129cd5cd..b22f50a9d1ef 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -1973,7 +1973,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 		mb->priv = priv;
 		mb->chip_id = chip_id;
 		mb->chip_ver = chip_ver;
-		mb->port_mask = BIT(priv->num_ports) - 1;
+		mb->port_mask = GENMASK(priv->num_ports - 1, 0);
 		mb->learn_limit_max = RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC;
 		mb->jam_table = rtl8365mb_init_jam_8365mb_vc;
 		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);
-- 
2.34.0


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

* [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (7 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1 Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-07  3:37   ` Jakub Kicinski
                     ` (2 more replies)
  2022-01-05  3:15 ` [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support Luiz Angelo Daros de Luca
                   ` (2 subsequent siblings)
  11 siblings, 3 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

Instead of a fixed CPU port, assume that DSA is correct.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
---
 drivers/net/dsa/realtek/rtl8365mb.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index b22f50a9d1ef..adc72f0844ae 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -103,14 +103,13 @@
 
 /* Chip-specific data and limits */
 #define RTL8365MB_CHIP_ID_8365MB_VC		0x6367
-#define RTL8365MB_CPU_PORT_NUM_8365MB_VC	6
 #define RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC	2112
 
 /* Family-specific data and limits */
 #define RTL8365MB_PHYADDRMAX	7
 #define RTL8365MB_NUM_PHYREGS	32
 #define RTL8365MB_PHYREGMAX	(RTL8365MB_NUM_PHYREGS - 1)
-#define RTL8365MB_MAX_NUM_PORTS	(RTL8365MB_CPU_PORT_NUM_8365MB_VC + 1)
+#define RTL8365MB_MAX_NUM_PORTS  7
 
 /* Chip identification registers */
 #define RTL8365MB_CHIP_ID_REG		0x1300
@@ -1806,6 +1805,8 @@ static int rtl8365mb_reset_chip(struct realtek_priv *priv)
 static int rtl8365mb_setup(struct dsa_switch *ds)
 {
 	struct realtek_priv *priv = ds->priv;
+	struct rtl8365mb_cpu cpu;
+	struct dsa_port *cpu_dp;
 	struct rtl8365mb *mb;
 	int ret;
 	int i;
@@ -1833,9 +1834,16 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 		dev_info(priv->dev, "no interrupt support\n");
 
 	/* Configure CPU tagging */
-	ret = rtl8365mb_cpu_config(priv);
-	if (ret)
-		goto out_teardown_irq;
+	dsa_switch_for_each_cpu_port(cpu_dp, priv->ds) {
+		priv->cpu_port = cpu_dp->index;
+		mb->cpu.mask = BIT(priv->cpu_port);
+		mb->cpu.trap_port = priv->cpu_port;
+		ret = rtl8365mb_cpu_config(priv);
+		if (ret)
+			goto out_teardown_irq;
+
+		break;
+	}
 
 	/* Configure ports */
 	for (i = 0; i < priv->num_ports; i++) {
@@ -1967,8 +1975,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 			 "found an RTL8365MB-VC switch (ver=0x%04x)\n",
 			 chip_ver);
 
-		priv->cpu_port = RTL8365MB_CPU_PORT_NUM_8365MB_VC;
-		priv->num_ports = priv->cpu_port + 1;
+		priv->num_ports = RTL8365MB_MAX_NUM_PORTS;
 
 		mb->priv = priv;
 		mb->chip_id = chip_id;
@@ -1979,8 +1986,6 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);
 
 		mb->cpu.enable = 1;
-		mb->cpu.mask = BIT(priv->cpu_port);
-		mb->cpu.trap_port = priv->cpu_port;
 		mb->cpu.insert = RTL8365MB_CPU_INSERT_TO_ALL;
 		mb->cpu.position = RTL8365MB_CPU_POS_AFTER_SA;
 		mb->cpu.rx_length = RTL8365MB_CPU_RXLEN_64BYTES;
-- 
2.34.0


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

* [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (8 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 13:26   ` Alvin Šipraga
  2022-01-17  4:26   ` Florian Fainelli
  2022-01-05  3:15 ` [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint Luiz Angelo Daros de Luca
  2022-01-20 14:36 ` [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Vladimir Oltean
  11 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

Realtek's RTL8367S, a 5+2 port 10/100/1000M Ethernet switch.
It shares the same driver family (RTL8367C) with other models
as the RTL8365MB-VC. Its compatible string is "realtek,rtl8367s".

It was tested only with MDIO interface (realtek-mdio), although it might
work out-of-the-box with SMI interface (using realtek-smi).

This patch was based on an unpublished patch from Alvin Šipraga
<alsi@bang-olufsen.dk>.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
---
 drivers/net/dsa/realtek/Kconfig        |  2 +-
 drivers/net/dsa/realtek/realtek-mdio.c |  1 +
 drivers/net/dsa/realtek/realtek-smi.c  |  4 +++
 drivers/net/dsa/realtek/rtl8365mb.c    | 38 +++++++++++++++++++-------
 4 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
index 73b26171fade..d0d6b5ba4bdd 100644
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -31,7 +31,7 @@ config NET_DSA_REALTEK_RTL8365MB
 	depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
 	select NET_DSA_TAG_RTL8_4
 	help
-	  Select to enable support for Realtek RTL8365MB
+	  Select to enable support for Realtek RTL8365MB-VC and RTL8367S.
 
 config NET_DSA_REALTEK_RTL8366RB
 	tristate "Realtek RTL8366RB switch subdriver"
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index b505f4d3c5f0..2bed65981c7d 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -199,6 +199,7 @@ static const struct of_device_id realtek_mdio_of_match[] = {
 #endif
 #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
 	{ .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
+	{ .compatible = "realtek,rtl8367s", .data = &rtl8365mb_variant, },
 #endif
 	{ /* sentinel */ },
 };
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 1f024e2520a6..c330a4d8ebf0 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -513,6 +513,10 @@ static const struct of_device_id realtek_smi_of_match[] = {
 		.compatible = "realtek,rtl8365mb",
 		.data = &rtl8365mb_variant,
 	},
+	{
+		.compatible = "realtek,rtl8367s",
+		.data = &rtl8365mb_variant,
+	},
 #endif
 	{ /* sentinel */ },
 };
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index adc72f0844ae..59e08b192c06 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -102,14 +102,19 @@
 #include "realtek.h"
 
 /* Chip-specific data and limits */
-#define RTL8365MB_CHIP_ID_8365MB_VC		0x6367
-#define RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC	2112
+#define RTL8365MB_CHIP_ID_8365MB_VC	0x6367
+#define RTL8365MB_CHIP_VER_8365MB_VC	0x0040
+
+#define RTL8365MB_CHIP_ID_8367S		0x6367
+#define RTL8365MB_CHIP_VER_8367S	0x00A0
 
 /* Family-specific data and limits */
-#define RTL8365MB_PHYADDRMAX	7
-#define RTL8365MB_NUM_PHYREGS	32
-#define RTL8365MB_PHYREGMAX	(RTL8365MB_NUM_PHYREGS - 1)
-#define RTL8365MB_MAX_NUM_PORTS  7
+#define RTL8365MB_PHYADDRMAX		7
+#define RTL8365MB_NUM_PHYREGS		32
+#define RTL8365MB_PHYREGMAX		(RTL8365MB_NUM_PHYREGS - 1)
+/* RTL8370MB and RTL8310SR, possibly suportable by this driver, have 10 ports */
+#define RTL8365MB_MAX_NUM_PORTS		10
+#define RTL8365MB_LEARN_LIMIT_MAX	2112
 
 /* Chip identification registers */
 #define RTL8365MB_CHIP_ID_REG		0x1300
@@ -1971,9 +1976,22 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 
 	switch (chip_id) {
 	case RTL8365MB_CHIP_ID_8365MB_VC:
-		dev_info(priv->dev,
-			 "found an RTL8365MB-VC switch (ver=0x%04x)\n",
-			 chip_ver);
+		switch (chip_ver) {
+		case RTL8365MB_CHIP_VER_8365MB_VC:
+			dev_info(priv->dev,
+				 "found an RTL8365MB-VC switch (ver=0x%04x)\n",
+				 chip_ver);
+			break;
+		case RTL8365MB_CHIP_VER_8367S:
+			dev_info(priv->dev,
+				 "found an RTL8367S switch (ver=0x%04x)\n",
+				 chip_ver);
+			break;
+		default:
+			dev_err(priv->dev, "unrecognized switch version (ver=0x%04x)",
+				chip_ver);
+			return -ENODEV;
+		}
 
 		priv->num_ports = RTL8365MB_MAX_NUM_PORTS;
 
@@ -1981,7 +1999,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 		mb->chip_id = chip_id;
 		mb->chip_ver = chip_ver;
 		mb->port_mask = GENMASK(priv->num_ports - 1, 0);
-		mb->learn_limit_max = RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC;
+		mb->learn_limit_max = RTL8365MB_LEARN_LIMIT_MAX;
 		mb->jam_table = rtl8365mb_init_jam_8365mb_vc;
 		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);
 
-- 
2.34.0


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

* [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (9 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support Luiz Angelo Daros de Luca
@ 2022-01-05  3:15 ` Luiz Angelo Daros de Luca
  2022-01-10 13:39   ` Alvin Šipraga
  2022-01-20 14:36 ` [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Vladimir Oltean
  11 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-05  3:15 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, andrew, vivien.didelot, f.fainelli, olteanv, alsi,
	arinc.unal, frank-w, Luiz Angelo Daros de Luca

Now CPU port is not limited to a single port. Also, extint can be used
as non-cpu ports, as long as it defines relatek,ext-int. The last cpu
port will be used as trap_port.

The CPU information was dropped from chip data as it was not used
outside setup. The only other place it was used is when it wrongly
checks for CPU port when it should check for extint.

realtek_priv->cpu_port is now only used by rtl8366rb.c

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/rtl8365mb.c | 53 +++++++++++++++--------------
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 59e08b192c06..6a00a162b2ac 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -556,7 +556,6 @@ struct rtl8365mb_port {
  * @chip_ver: chip silicon revision
  * @port_mask: mask of all ports
  * @learn_limit_max: maximum number of L2 addresses the chip can learn
- * @cpu: CPU tagging and CPU port configuration for this chip
  * @mib_lock: prevent concurrent reads of MIB counters
  * @ports: per-port data
  * @jam_table: chip-specific initialization jam table
@@ -571,7 +570,6 @@ struct rtl8365mb {
 	u32 chip_ver;
 	u32 port_mask;
 	u32 learn_limit_max;
-	struct rtl8365mb_cpu cpu;
 	struct mutex mib_lock;
 	struct rtl8365mb_port ports[RTL8365MB_MAX_NUM_PORTS];
 	const struct rtl8365mb_jam_tbl_entry *jam_table;
@@ -769,17 +767,20 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port,
 	u32 val;
 	int ret;
 
-	if (port != priv->cpu_port) {
-		dev_err(priv->dev, "only one EXT interface is currently supported\n");
+	mb = priv->chip_data;
+	p = &mb->ports[port];
+	ext_int = p->ext_int;
+
+	if (ext_int == RTL8365MB_NOT_EXT) {
+		dev_err(priv->dev,
+			"Port %d is not identified as extenal interface.\n",
+			port);
 		return -EINVAL;
 	}
 
 	dp = dsa_to_port(priv->ds, port);
 	dn = dp->dn;
 
-	mb = priv->chip_data;
-	p = &mb->ports[port];
-	ext_int = p->ext_int;
 
 	/* Set the RGMII TX/RX delay
 	 *
@@ -859,15 +860,17 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_priv *priv, int port,
 	int val;
 	int ret;
 
-	if (port != priv->cpu_port) {
-		dev_err(priv->dev, "only one EXT interface is currently supported\n");
-		return -EINVAL;
-	}
-
 	mb = priv->chip_data;
 	p = &mb->ports[port];
 	ext_int = p->ext_int;
 
+	if (ext_int == RTL8365MB_NOT_EXT) {
+		dev_err(priv->dev,
+			"Port %d is not identified as extenal interface.\n",
+			port);
+		return -EINVAL;
+	}
+
 	if (link) {
 		/* Force the link up with the desired configuration */
 		r_link = 1;
@@ -1734,10 +1737,8 @@ static void rtl8365mb_irq_teardown(struct realtek_priv *priv)
 	}
 }
 
-static int rtl8365mb_cpu_config(struct realtek_priv *priv)
+static int rtl8365mb_cpu_config(struct realtek_priv *priv, struct rtl8365mb_cpu *cpu)
 {
-	struct rtl8365mb *mb = priv->chip_data;
-	struct rtl8365mb_cpu *cpu = &mb->cpu;
 	u32 val;
 	int ret;
 
@@ -1839,11 +1840,17 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 		dev_info(priv->dev, "no interrupt support\n");
 
 	/* Configure CPU tagging */
+	cpu.mask = 0;
 	dsa_switch_for_each_cpu_port(cpu_dp, priv->ds) {
-		priv->cpu_port = cpu_dp->index;
-		mb->cpu.mask = BIT(priv->cpu_port);
-		mb->cpu.trap_port = priv->cpu_port;
-		ret = rtl8365mb_cpu_config(priv);
+		cpu.enable = 1;
+		cpu.insert = RTL8365MB_CPU_INSERT_TO_ALL;
+		cpu.position = RTL8365MB_CPU_POS_AFTER_SA;
+		cpu.rx_length = RTL8365MB_CPU_RXLEN_64BYTES;
+		cpu.format = RTL8365MB_CPU_FORMAT_8BYTES;
+		cpu.trap_port = cpu_dp->index;
+		cpu.mask |= BIT(cpu_dp->index);
+
+		ret = rtl8365mb_cpu_config(priv, &cpu);
 		if (ret)
 			goto out_teardown_irq;
 
@@ -1862,7 +1869,7 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 		dn = dsa_to_port(priv->ds, i)->dn;
 
 		/* Forward only to the CPU */
-		ret = rtl8365mb_port_set_isolation(priv, i, BIT(priv->cpu_port));
+		ret = rtl8365mb_port_set_isolation(priv, i, cpu.mask);
 		if (ret)
 			goto out_teardown_irq;
 
@@ -2003,12 +2010,6 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 		mb->jam_table = rtl8365mb_init_jam_8365mb_vc;
 		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);
 
-		mb->cpu.enable = 1;
-		mb->cpu.insert = RTL8365MB_CPU_INSERT_TO_ALL;
-		mb->cpu.position = RTL8365MB_CPU_POS_AFTER_SA;
-		mb->cpu.rx_length = RTL8365MB_CPU_RXLEN_64BYTES;
-		mb->cpu.format = RTL8365MB_CPU_FORMAT_8BYTES;
-
 		break;
 	default:
 		dev_err(priv->dev,
-- 
2.34.0


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

* Re: [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port
  2022-01-05  3:15 ` [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port Luiz Angelo Daros de Luca
@ 2022-01-07  3:37   ` Jakub Kicinski
  2022-01-10 13:22   ` Alvin Šipraga
  2022-01-17  4:26   ` Florian Fainelli
  2 siblings, 0 replies; 88+ messages in thread
From: Jakub Kicinski @ 2022-01-07  3:37 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, alsi, arinc.unal, frank-w

On Wed,  5 Jan 2022 00:15:13 -0300 Luiz Angelo Daros de Luca wrote:
> Instead of a fixed CPU port, assume that DSA is correct.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

Transient build warning here:

drivers/net/dsa/realtek/rtl8365mb.c:1808:23: warning: unused variable 'cpu' [-Wunused-variable]
        struct rtl8365mb_cpu cpu;
                             ^

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

* Re: [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv
  2022-01-05  3:15 ` [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv Luiz Angelo Daros de Luca
@ 2022-01-07  3:42   ` Jakub Kicinski
  2022-01-10 12:33   ` Alvin Šipraga
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 88+ messages in thread
From: Jakub Kicinski @ 2022-01-07  3:42 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, alsi, arinc.unal, frank-w

On Wed,  5 Jan 2022 00:15:06 -0300 Luiz Angelo Daros de Luca wrote:
>  /**
> - * struct realtek_smi_ops - vtable for the per-SMI-chiptype operations
> + * struct realtek_ops - vtable for the per-SMI-chiptype operations
>   * @detect: detects the chiptype

This kdoc is missing decriptions for a lot of members.

Would you mind adding a patch to the front of the series to resolve all
kdoc issues in realtek-smi-core.h AKA realtek.h so that we don't get
the errors re-reported each time the file is renamed in the series?
Since the kdoc doesn't add much here I think you can just replace the
/** with a /* for now, or remove it completely.

>   */
> -struct realtek_smi_ops {
> -	int	(*detect)(struct realtek_smi *smi);
> -	int	(*reset_chip)(struct realtek_smi *smi);
> -	int	(*setup)(struct realtek_smi *smi);
> -	void	(*cleanup)(struct realtek_smi *smi);
> -	int	(*get_mib_counter)(struct realtek_smi *smi,
> +struct realtek_ops {
> +	int	(*detect)(struct realtek_priv *priv);
> +	int	(*reset_chip)(struct realtek_priv *priv);
> +	int	(*setup)(struct realtek_priv *priv);
> +	void	(*cleanup)(struct realtek_priv *priv);
> +	int	(*get_mib_counter)(struct realtek_priv *priv,
>  				   int port,
>  				   struct rtl8366_mib_counter *mib,
>  				   u64 *mibvalue);
> -	int	(*get_vlan_mc)(struct realtek_smi *smi, u32 index,
> +	int	(*get_vlan_mc)(struct realtek_priv *priv, u32 index,
>  			       struct rtl8366_vlan_mc *vlanmc);
> -	int	(*set_vlan_mc)(struct realtek_smi *smi, u32 index,
> +	int	(*set_vlan_mc)(struct realtek_priv *priv, u32 index,
>  			       const struct rtl8366_vlan_mc *vlanmc);
> -	int	(*get_vlan_4k)(struct realtek_smi *smi, u32 vid,
> +	int	(*get_vlan_4k)(struct realtek_priv *priv, u32 vid,
>  			       struct rtl8366_vlan_4k *vlan4k);
> -	int	(*set_vlan_4k)(struct realtek_smi *smi,
> +	int	(*set_vlan_4k)(struct realtek_priv *priv,
>  			       const struct rtl8366_vlan_4k *vlan4k);
> -	int	(*get_mc_index)(struct realtek_smi *smi, int port, int *val);
> -	int	(*set_mc_index)(struct realtek_smi *smi, int port, int index);
> -	bool	(*is_vlan_valid)(struct realtek_smi *smi, unsigned int vlan);
> -	int	(*enable_vlan)(struct realtek_smi *smi, bool enable);
> -	int	(*enable_vlan4k)(struct realtek_smi *smi, bool enable);
> -	int	(*enable_port)(struct realtek_smi *smi, int port, bool enable);
> -	int	(*phy_read)(struct realtek_smi *smi, int phy, int regnum);
> -	int	(*phy_write)(struct realtek_smi *smi, int phy, int regnum,
> +	int	(*get_mc_index)(struct realtek_priv *priv, int port, int *val);
> +	int	(*set_mc_index)(struct realtek_priv *priv, int port, int index);
> +	bool	(*is_vlan_valid)(struct realtek_priv *priv, unsigned int vlan);
> +	int	(*enable_vlan)(struct realtek_priv *priv, bool enable);
> +	int	(*enable_vlan4k)(struct realtek_priv *priv, bool enable);
> +	int	(*enable_port)(struct realtek_priv *priv, int port, bool enable);
> +	int	(*phy_read)(struct realtek_priv *priv, int phy, int regnum);
> +	int	(*phy_write)(struct realtek_priv *priv, int phy, int regnum,
>  			     u16 val);
>  };

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

* Re: [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv
  2022-01-05  3:15 ` [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv Luiz Angelo Daros de Luca
  2022-01-07  3:42   ` Jakub Kicinski
@ 2022-01-10 12:33   ` Alvin Šipraga
  2022-01-16  0:04   ` Linus Walleij
  2022-01-20 14:37   ` Vladimir Oltean
  3 siblings, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 12:33 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> In preparation to adding other interfaces, the private data structure
> was renamed to priv. Also, realtek_smi_variant and realtek_smi_ops
> were renamed to realtek_variant and realtek_ops as those structs are
> not SMI specific.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

> ---
>  drivers/net/dsa/realtek/realtek-smi-core.c    | 316 +++++++-------
>  .../realtek/{realtek-smi-core.h => realtek.h} |  68 +--
>  drivers/net/dsa/realtek/rtl8365mb.c           | 394 ++++++++---------
>  drivers/net/dsa/realtek/rtl8366.c             | 164 +++----
>  drivers/net/dsa/realtek/rtl8366rb.c           | 402 +++++++++---------
>  5 files changed, 672 insertions(+), 672 deletions(-)
>  rename drivers/net/dsa/realtek/{realtek-smi-core.h => realtek.h} (57%)

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

* Re: [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi
  2022-01-05  3:15 ` [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi Luiz Angelo Daros de Luca
@ 2022-01-10 12:38   ` Alvin Šipraga
  2022-01-16  0:05   ` Linus Walleij
  2022-01-17  3:46   ` Florian Fainelli
  2 siblings, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 12:38 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> Remove the only two direct calls from subdrivers to realtek-smi.
> Now they are called from realtek_priv. Subdrivers can now be
> linked independently from realtek-smi.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

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

* Re: [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules
  2022-01-05  3:15 ` [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules Luiz Angelo Daros de Luca
@ 2022-01-10 12:43   ` Alvin Šipraga
  2022-01-17  4:02   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 12:43 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> Preparing for multiple interfaces support, the drivers
> must be independent of realtek-smi.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

> ---
>  drivers/net/dsa/realtek/Kconfig               | 20 +++++++++++++++++--
>  drivers/net/dsa/realtek/Makefile              |  4 +++-
>  .../{realtek-smi-core.c => realtek-smi.c}     |  6 ++++++
>  drivers/net/dsa/realtek/rtl8365mb.c           |  4 ++++
>  .../dsa/realtek/{rtl8366.c => rtl8366-core.c} |  0
>  drivers/net/dsa/realtek/rtl8366rb.c           |  4 ++++
>  6 files changed, 35 insertions(+), 3 deletions(-)
>  rename drivers/net/dsa/realtek/{realtek-smi-core.c => realtek-smi.c} (97%)
>  rename drivers/net/dsa/realtek/{rtl8366.c => rtl8366-core.c} (100%)
>
> diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
> index 1c62212fb0ec..cd1aa95b7bf0 100644
> --- a/drivers/net/dsa/realtek/Kconfig
> +++ b/drivers/net/dsa/realtek/Kconfig
> @@ -2,8 +2,6 @@
>  menuconfig NET_DSA_REALTEK
>  	tristate "Realtek Ethernet switch family support"
>  	depends on NET_DSA
> -	select NET_DSA_TAG_RTL4_A
> -	select NET_DSA_TAG_RTL8_4
>  	select FIXED_PHY
>  	select IRQ_DOMAIN
>  	select REALTEK_PHY
> @@ -18,3 +16,21 @@ config NET_DSA_REALTEK_SMI
>  	help
>  	  Select to enable support for registering switches connected
>  	  through SMI.
> +
> +config NET_DSA_REALTEK_RTL8365MB
> +	tristate "Realtek RTL8365MB switch subdriver"
> +	default y
> +	depends on NET_DSA_REALTEK
> +	depends on NET_DSA_REALTEK_SMI
> +	select NET_DSA_TAG_RTL8_4
> +	help
> +	  Select to enable support for Realtek RTL8365MB
> +
> +config NET_DSA_REALTEK_RTL8366RB
> +	tristate "Realtek RTL8366RB switch subdriver"
> +	default y
> +	depends on NET_DSA_REALTEK
> +	depends on NET_DSA_REALTEK_SMI
> +	select NET_DSA_TAG_RTL4_A
> +	help
> +	  Select to enable support for Realtek RTL8366RB
> diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> index 323b921bfce0..8b5a4abcedd3 100644
> --- a/drivers/net/dsa/realtek/Makefile
> +++ b/drivers/net/dsa/realtek/Makefile
> @@ -1,3 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0
>  obj-$(CONFIG_NET_DSA_REALTEK_SMI) 	+= realtek-smi.o
> -realtek-smi-objs			:= realtek-smi-core.o rtl8366.o rtl8366rb.o rtl8365mb.o
> +obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
> +rtl8366-objs 				:= rtl8366-core.o rtl8366rb.o
> +obj-$(CONFIG_NET_DSA_REALTEK_RTL8365MB) += rtl8365mb.o
> diff --git a/drivers/net/dsa/realtek/realtek-smi-core.c b/drivers/net/dsa/realtek/realtek-smi.c
> similarity index 97%
> rename from drivers/net/dsa/realtek/realtek-smi-core.c
> rename to drivers/net/dsa/realtek/realtek-smi.c
> index a917801385c9..5514fe81d64f 100644
> --- a/drivers/net/dsa/realtek/realtek-smi-core.c
> +++ b/drivers/net/dsa/realtek/realtek-smi.c
> @@ -495,19 +495,23 @@ static void realtek_smi_shutdown(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id realtek_smi_of_match[] = {
> +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
>  	{
>  		.compatible = "realtek,rtl8366rb",
>  		.data = &rtl8366rb_variant,
>  	},
> +#endif
>  	{
>  		/* FIXME: add support for RTL8366S and more */
>  		.compatible = "realtek,rtl8366s",
>  		.data = NULL,
>  	},

If you send a v5, maybe add a patch to remove this. It is going to crash
anyway so I am sure nobody uses it.

> +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
>  	{
>  		.compatible = "realtek,rtl8365mb",
>  		.data = &rtl8365mb_variant,
>  	},
> +#endif
>  	{ /* sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
> @@ -523,4 +527,6 @@ static struct platform_driver realtek_smi_driver = {
>  };
>  module_platform_driver(realtek_smi_driver);
>  
> +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> +MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
>  MODULE_LICENSE("GPL");
> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index 5fb453b5f650..b52bb987027c 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -1987,3 +1987,7 @@ const struct realtek_variant rtl8365mb_variant = {
>  	.chip_data_sz = sizeof(struct rtl8365mb),
>  };
>  EXPORT_SYMBOL_GPL(rtl8365mb_variant);
> +
> +MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
> +MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/dsa/realtek/rtl8366.c b/drivers/net/dsa/realtek/rtl8366-core.c
> similarity index 100%
> rename from drivers/net/dsa/realtek/rtl8366.c
> rename to drivers/net/dsa/realtek/rtl8366-core.c
> diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> index 34e371084d6d..ff607608dead 100644
> --- a/drivers/net/dsa/realtek/rtl8366rb.c
> +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> @@ -1814,3 +1814,7 @@ const struct realtek_variant rtl8366rb_variant = {
>  	.chip_data_sz = sizeof(struct rtl8366rb),
>  };
>  EXPORT_SYMBOL_GPL(rtl8366rb_variant);
> +
> +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> +MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
> +MODULE_LICENSE("GPL");

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

* Re: [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers
  2022-01-05  3:15 ` [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers Luiz Angelo Daros de Luca
@ 2022-01-10 13:09   ` Alvin Šipraga
  2022-01-17  4:22   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 13:09 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> This driver is a mdio_driver instead of a platform driver (like
> realtek-smi).
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

This looks good but I still wonder about the START_OPs, see below.

> ---
>  drivers/net/dsa/realtek/Kconfig        |  11 +-
>  drivers/net/dsa/realtek/Makefile       |   1 +
>  drivers/net/dsa/realtek/realtek-mdio.c | 221 +++++++++++++++++++++++++
>  drivers/net/dsa/realtek/realtek.h      |   2 +
>  4 files changed, 233 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/net/dsa/realtek/realtek-mdio.c
>
> diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
> index cd1aa95b7bf0..73b26171fade 100644
> --- a/drivers/net/dsa/realtek/Kconfig
> +++ b/drivers/net/dsa/realtek/Kconfig
> @@ -9,6 +9,13 @@ menuconfig NET_DSA_REALTEK
>  	help
>  	  Select to enable support for Realtek Ethernet switch chips.
>  
> +config NET_DSA_REALTEK_MDIO
> +	tristate "Realtek MDIO connected switch driver"
> +	depends on NET_DSA_REALTEK
> +	default y
> +	help
> +	  Select to enable support for registering switches configured
> +	  through MDIO.

Missing newline here

>  config NET_DSA_REALTEK_SMI
>  	tristate "Realtek SMI connected switch driver"
>  	depends on NET_DSA_REALTEK
> @@ -21,7 +28,7 @@ config NET_DSA_REALTEK_RTL8365MB
>  	tristate "Realtek RTL8365MB switch subdriver"
>  	default y
>  	depends on NET_DSA_REALTEK
> -	depends on NET_DSA_REALTEK_SMI
> +	depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
>  	select NET_DSA_TAG_RTL8_4
>  	help
>  	  Select to enable support for Realtek RTL8365MB
> @@ -30,7 +37,7 @@ config NET_DSA_REALTEK_RTL8366RB
>  	tristate "Realtek RTL8366RB switch subdriver"
>  	default y
>  	depends on NET_DSA_REALTEK
> -	depends on NET_DSA_REALTEK_SMI
> +	depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
>  	select NET_DSA_TAG_RTL4_A
>  	help
>  	  Select to enable support for Realtek RTL8366RB
> diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> index 8b5a4abcedd3..0aab57252a7c 100644
> --- a/drivers/net/dsa/realtek/Makefile
> +++ b/drivers/net/dsa/realtek/Makefile
> @@ -1,4 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_NET_DSA_REALTEK_MDIO) 	+= realtek-mdio.o
>  obj-$(CONFIG_NET_DSA_REALTEK_SMI) 	+= realtek-smi.o
>  obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
>  rtl8366-objs 				:= rtl8366-core.o rtl8366rb.o
> diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> new file mode 100644
> index 000000000000..b505f4d3c5f0
> --- /dev/null
> +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> @@ -0,0 +1,221 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Realtek MDIO interface driver
> + *
> + * ASICs we intend to support with this driver:
> + *
> + * RTL8366   - The original version, apparently
> + * RTL8369   - Similar enough to have the same datsheet as RTL8366
> + * RTL8366RB - Probably reads out "RTL8366 revision B", has a quite
> + *             different register layout from the other two
> + * RTL8366S  - Is this "RTL8366 super"?
> + * RTL8367   - Has an OpenWRT driver as well
> + * RTL8368S  - Seems to be an alternative name for RTL8366RB
> + * RTL8370   - Also uses SMI
> + *
> + * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
> + * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com>
> + * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv>
> + * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com>
> + * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/regmap.h>
> +
> +#include "realtek.h"
> +
> +/* Read/write via mdiobus */
> +#define REALTEK_MDIO_CTRL0_REG		31
> +#define REALTEK_MDIO_START_REG		29
> +#define REALTEK_MDIO_CTRL1_REG		21
> +#define REALTEK_MDIO_ADDRESS_REG	23
> +#define REALTEK_MDIO_DATA_WRITE_REG	24
> +#define REALTEK_MDIO_DATA_READ_REG	25
> +
> +#define REALTEK_MDIO_START_OP		0xFFFF
> +#define REALTEK_MDIO_ADDR_OP		0x000E
> +#define REALTEK_MDIO_READ_OP		0x0001
> +#define REALTEK_MDIO_WRITE_OP		0x0003
> +
> +static int realtek_mdio_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
> +{
> +	u32 phy_id = priv->phy_id;
> +	struct mii_bus *bus = priv->bus;
> +
> +	mutex_lock(&bus->mdio_lock);
> +
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);

Hm, I thought you said it works without these START_OPs? Or just without
the first one?

I don't know if it matters but I would suggest removing all START_OPs
and seeing if things still work. If so then it's probably best to omit
this because it is not present in the vendor driver, and nobody seems to
know what it's for. I agree it could be something for older models but
if it works on your model then let's leave it out :-)

> +	bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	*data = bus->read(bus, phy_id, REALTEK_MDIO_DATA_READ_REG);
> +
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return 0;
> +}
> +
> +static int realtek_mdio_write_reg(struct realtek_priv *priv, u32 addr, u32 data)
> +{
> +	u32 phy_id = priv->phy_id;
> +	struct mii_bus *bus = priv->bus;
> +
> +	mutex_lock(&bus->mdio_lock);
> +
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_DATA_WRITE_REG, data);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP);
> +
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return 0;
> +}
> +
> +/* Regmap accessors */
> +
> +static int realtek_mdio_write(void *ctx, u32 reg, u32 val)
> +{
> +	struct realtek_priv *priv = ctx;
> +
> +	return realtek_mdio_write_reg(priv, reg, val);
> +}
> +
> +static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
> +{
> +	struct realtek_priv *priv = ctx;
> +
> +	return realtek_mdio_read_reg(priv, reg, val);
> +}
> +
> +static const struct regmap_config realtek_mdio_regmap_config = {
> +	.reg_bits = 10, /* A4..A0 R4..R0 */
> +	.val_bits = 16,
> +	.reg_stride = 1,
> +	/* PHY regs are at 0x8000 */
> +	.max_register = 0xffff,
> +	.reg_format_endian = REGMAP_ENDIAN_BIG,
> +	.reg_read = realtek_mdio_read,
> +	.reg_write = realtek_mdio_write,
> +	.cache_type = REGCACHE_NONE,
> +};
> +
> +static int realtek_mdio_probe(struct mdio_device *mdiodev)
> +{
> +	struct realtek_priv *priv;
> +	struct device *dev = &mdiodev->dev;
> +	const struct realtek_variant *var;
> +	int ret;
> +	struct device_node *np;
> +
> +	var = of_device_get_match_data(dev);
> +	priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->map = devm_regmap_init(dev, NULL, priv, &realtek_mdio_regmap_config);
> +	if (IS_ERR(priv->map)) {
> +		ret = PTR_ERR(priv->map);
> +		dev_err(dev, "regmap init failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	priv->phy_id = mdiodev->addr;
> +	priv->bus = mdiodev->bus;
> +	priv->dev = &mdiodev->dev;
> +	priv->chip_data = (void *)priv + sizeof(*priv);
> +
> +	priv->clk_delay = var->clk_delay;
> +	priv->cmd_read = var->cmd_read;
> +	priv->cmd_write = var->cmd_write;
> +	priv->ops = var->ops;
> +
> +	priv->write_reg_noack = realtek_mdio_write_reg;
> +
> +	np = dev->of_node;
> +
> +	dev_set_drvdata(dev, priv);
> +
> +	/* TODO: if power is software controlled, set up any regulators here */
> +	priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
> +
> +	ret = priv->ops->detect(priv);
> +	if (ret) {
> +		dev_err(dev, "unable to detect switch\n");
> +		return ret;
> +	}
> +
> +	priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
> +	if (!priv->ds)
> +		return -ENOMEM;
> +
> +	priv->ds->dev = dev;
> +	priv->ds->num_ports = priv->num_ports;
> +	priv->ds->priv = priv;
> +	priv->ds->ops = var->ds_ops;
> +
> +	ret = dsa_register_switch(priv->ds);
> +	if (ret) {
> +		dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void realtek_mdio_remove(struct mdio_device *mdiodev)
> +{
> +	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
> +
> +	if (!priv)
> +		return;
> +
> +	dsa_unregister_switch(priv->ds);
> +
> +	dev_set_drvdata(&mdiodev->dev, NULL);
> +}
> +
> +static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
> +{
> +	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
> +
> +	if (!priv)
> +		return;
> +
> +	dsa_switch_shutdown(priv->ds);
> +
> +	dev_set_drvdata(&mdiodev->dev, NULL);
> +}
> +
> +static const struct of_device_id realtek_mdio_of_match[] = {
> +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB)
> +	{ .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
> +#endif
> +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
> +	{ .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
> +#endif
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, realtek_mdio_of_match);
> +
> +static struct mdio_driver realtek_mdio_driver = {
> +	.mdiodrv.driver = {
> +		.name = "realtek-mdio",
> +		.of_match_table = of_match_ptr(realtek_mdio_of_match),
> +	},
> +	.probe  = realtek_mdio_probe,
> +	.remove = realtek_mdio_remove,
> +	.shutdown = realtek_mdio_shutdown,
> +};
> +
> +mdio_module_driver(realtek_mdio_driver);
> +
> +MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
> +MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> index a03de15c4a94..97274273cb3b 100644
> --- a/drivers/net/dsa/realtek/realtek.h
> +++ b/drivers/net/dsa/realtek/realtek.h
> @@ -50,6 +50,8 @@ struct realtek_priv {
>  	struct gpio_desc	*mdio;
>  	struct regmap		*map;
>  	struct mii_bus		*slave_mii_bus;
> +	struct mii_bus		*bus;
> +	int			phy_id;
>  
>  	unsigned int		clk_delay;
>  	u8			cmd_read;

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

* Re: [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops
  2022-01-05  3:15 ` [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops Luiz Angelo Daros de Luca
@ 2022-01-10 13:09   ` Alvin Šipraga
  2022-01-17  4:15   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 13:09 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> The ds->ops->phy_read will only be used if the ds->slave_mii_bus
> was not initialized. Calling realtek_smi_setup_mdio will create a
> ds->slave_mii_bus, making ds->ops->phy_read dormant.
>
> Using ds->ops->phy_read will allow switches connected through non-SMI
> interfaces (like mdio) to let ds allocate slave_mii_bus and reuse the
> same code.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

> ---
>  drivers/net/dsa/realtek/realtek-smi.c |  6 ++++--
>  drivers/net/dsa/realtek/realtek.h     |  3 ---
>  drivers/net/dsa/realtek/rtl8365mb.c   | 10 ++++++----
>  drivers/net/dsa/realtek/rtl8366rb.c   | 10 ++++++----
>  4 files changed, 16 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> index 5514fe81d64f..1f024e2520a6 100644
> --- a/drivers/net/dsa/realtek/realtek-smi.c
> +++ b/drivers/net/dsa/realtek/realtek-smi.c
> @@ -329,16 +329,18 @@ static const struct regmap_config realtek_smi_mdio_regmap_config = {
>  static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
>  {
>  	struct realtek_priv *priv = bus->priv;
> +	struct dsa_switch *ds = priv->ds;
>  
> -	return priv->ops->phy_read(priv, addr, regnum);
> +	return ds->ops->phy_read(ds, addr, regnum);
>  }
>  
>  static int realtek_smi_mdio_write(struct mii_bus *bus, int addr, int regnum,
>  				  u16 val)
>  {
>  	struct realtek_priv *priv = bus->priv;
> +	struct dsa_switch *ds = priv->ds;
>  
> -	return priv->ops->phy_write(priv, addr, regnum, val);
> +	return ds->ops->phy_write(ds, addr, regnum, val);
>  }
>  
>  static int realtek_smi_setup_mdio(struct dsa_switch *ds)
> diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> index 58814de563a2..a03de15c4a94 100644
> --- a/drivers/net/dsa/realtek/realtek.h
> +++ b/drivers/net/dsa/realtek/realtek.h
> @@ -103,9 +103,6 @@ struct realtek_ops {
>  	int	(*enable_vlan)(struct realtek_priv *priv, bool enable);
>  	int	(*enable_vlan4k)(struct realtek_priv *priv, bool enable);
>  	int	(*enable_port)(struct realtek_priv *priv, int port, bool enable);
> -	int	(*phy_read)(struct realtek_priv *priv, int phy, int regnum);
> -	int	(*phy_write)(struct realtek_priv *priv, int phy, int regnum,
> -			     u16 val);
>  };
>  
>  struct realtek_variant {
> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index b52bb987027c..11a985900c57 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -674,8 +674,9 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
>  	return 0;
>  }
>  
> -static int rtl8365mb_phy_read(struct realtek_priv *priv, int phy, int regnum)
> +static int rtl8365mb_phy_read(struct dsa_switch *ds, int phy, int regnum)
>  {
> +	struct realtek_priv *priv = ds->priv;
>  	u32 ocp_addr;
>  	u16 val;
>  	int ret;
> @@ -702,9 +703,10 @@ static int rtl8365mb_phy_read(struct realtek_priv *priv, int phy, int regnum)
>  	return val;
>  }
>  
> -static int rtl8365mb_phy_write(struct realtek_priv *priv, int phy, int regnum,
> +static int rtl8365mb_phy_write(struct dsa_switch *ds, int phy, int regnum,
>  			       u16 val)
>  {
> +	struct realtek_priv *priv = (struct realtek_priv *)ds->priv;
>  	u32 ocp_addr;
>  	int ret;
>  
> @@ -1958,6 +1960,8 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
>  	.get_tag_protocol = rtl8365mb_get_tag_protocol,
>  	.setup = rtl8365mb_setup,
>  	.teardown = rtl8365mb_teardown,
> +	.phy_read = rtl8365mb_phy_read,
> +	.phy_write = rtl8365mb_phy_write,
>  	.phylink_validate = rtl8365mb_phylink_validate,
>  	.phylink_mac_config = rtl8365mb_phylink_mac_config,
>  	.phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
> @@ -1974,8 +1978,6 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
>  
>  static const struct realtek_ops rtl8365mb_ops = {
>  	.detect = rtl8365mb_detect,
> -	.phy_read = rtl8365mb_phy_read,
> -	.phy_write = rtl8365mb_phy_write,
>  };
>  
>  const struct realtek_variant rtl8365mb_variant = {
> diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> index ff607608dead..4576f9b797c5 100644
> --- a/drivers/net/dsa/realtek/rtl8366rb.c
> +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> @@ -1641,8 +1641,9 @@ static int rtl8366rb_enable_vlan4k(struct realtek_priv *priv, bool enable)
>  				  enable ? RTL8366RB_SGCR_EN_VLAN_4KTB : 0);
>  }
>  
> -static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
> +static int rtl8366rb_phy_read(struct dsa_switch *ds, int phy, int regnum)
>  {
> +	struct realtek_priv *priv = ds->priv;
>  	u32 val;
>  	u32 reg;
>  	int ret;
> @@ -1675,9 +1676,10 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
>  	return val;
>  }
>  
> -static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
> +static int rtl8366rb_phy_write(struct dsa_switch *ds, int phy, int regnum,
>  			       u16 val)
>  {
> +	struct realtek_priv *priv = ds->priv;
>  	u32 reg;
>  	int ret;
>  
> @@ -1769,6 +1771,8 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
>  static const struct dsa_switch_ops rtl8366rb_switch_ops = {
>  	.get_tag_protocol = rtl8366_get_tag_protocol,
>  	.setup = rtl8366rb_setup,
> +	.phy_read = rtl8366rb_phy_read,
> +	.phy_write = rtl8366rb_phy_write,
>  	.phylink_mac_link_up = rtl8366rb_mac_link_up,
>  	.phylink_mac_link_down = rtl8366rb_mac_link_down,
>  	.get_strings = rtl8366_get_strings,
> @@ -1801,8 +1805,6 @@ static const struct realtek_ops rtl8366rb_ops = {
>  	.is_vlan_valid	= rtl8366rb_is_vlan_valid,
>  	.enable_vlan	= rtl8366rb_enable_vlan,
>  	.enable_vlan4k	= rtl8366rb_enable_vlan4k,
> -	.phy_read	= rtl8366rb_phy_read,
> -	.phy_write	= rtl8366rb_phy_write,
>  };
>  
>  const struct realtek_variant rtl8366rb_variant = {

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

* Re: [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int"
  2022-01-05  3:15 ` [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int" Luiz Angelo Daros de Luca
@ 2022-01-10 13:15   ` Alvin Šipraga
  2022-01-17  4:25   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 13:15 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> "extport" 0, 1, 2 was used to reference external ports (ext0,
> ext1, ext2). Meanwhile, port 0..9 is used as switch ports,
> including external ports. "extport" was renamed to extint to
> make it clear it does not mean the port number but the external
> interface number.
>
> The macros that map extint numbers to registers addresses now
> use inline ifs instead of binary arithmetic.
>
> "extint" was hardcoded to 1. However, some chips have multiple
> external interfaces. It's not right to assume the CPU port uses
> extint 1 nor that all extint are CPU ports. Now the association
> between the port and the external interface can be defined with
> a device-tree port property "realtek,ext-int".
>
> This patch still does not allow multiple CPU ports nor extint
> as a non CPU port.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

> ---
>  drivers/net/dsa/realtek/rtl8365mb.c | 135 ++++++++++++++++++----------
>  1 file changed, 88 insertions(+), 47 deletions(-)

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

* Re: [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1
  2022-01-05  3:15 ` [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1 Luiz Angelo Daros de Luca
@ 2022-01-10 13:18   ` Alvin Šipraga
  2022-01-17  4:25   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 13:18 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

> ---
>  drivers/net/dsa/realtek/rtl8365mb.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index e115129cd5cd..b22f50a9d1ef 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -1973,7 +1973,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
>  		mb->priv = priv;
>  		mb->chip_id = chip_id;
>  		mb->chip_ver = chip_ver;
> -		mb->port_mask = BIT(priv->num_ports) - 1;
> +		mb->port_mask = GENMASK(priv->num_ports - 1, 0);
>  		mb->learn_limit_max = RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC;
>  		mb->jam_table = rtl8365mb_init_jam_8365mb_vc;
>  		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);

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

* Re: [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port
  2022-01-05  3:15 ` [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port Luiz Angelo Daros de Luca
  2022-01-07  3:37   ` Jakub Kicinski
@ 2022-01-10 13:22   ` Alvin Šipraga
  2022-01-17  4:26   ` Florian Fainelli
  2 siblings, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 13:22 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> Instead of a fixed CPU port, assume that DSA is correct.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

With the warning fixed:

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

> ---
>  drivers/net/dsa/realtek/rtl8365mb.c | 23 ++++++++++++++---------
>  1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index b22f50a9d1ef..adc72f0844ae 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -103,14 +103,13 @@
>  
>  /* Chip-specific data and limits */
>  #define RTL8365MB_CHIP_ID_8365MB_VC		0x6367
> -#define RTL8365MB_CPU_PORT_NUM_8365MB_VC	6
>  #define RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC	2112
>  
>  /* Family-specific data and limits */
>  #define RTL8365MB_PHYADDRMAX	7
>  #define RTL8365MB_NUM_PHYREGS	32
>  #define RTL8365MB_PHYREGMAX	(RTL8365MB_NUM_PHYREGS - 1)
> -#define RTL8365MB_MAX_NUM_PORTS	(RTL8365MB_CPU_PORT_NUM_8365MB_VC + 1)
> +#define RTL8365MB_MAX_NUM_PORTS  7
>  
>  /* Chip identification registers */
>  #define RTL8365MB_CHIP_ID_REG		0x1300
> @@ -1806,6 +1805,8 @@ static int rtl8365mb_reset_chip(struct realtek_priv *priv)
>  static int rtl8365mb_setup(struct dsa_switch *ds)
>  {
>  	struct realtek_priv *priv = ds->priv;
> +	struct rtl8365mb_cpu cpu;

Unused?

> +	struct dsa_port *cpu_dp;
>  	struct rtl8365mb *mb;
>  	int ret;
>  	int i;
> @@ -1833,9 +1834,16 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
>  		dev_info(priv->dev, "no interrupt support\n");
>  
>  	/* Configure CPU tagging */
> -	ret = rtl8365mb_cpu_config(priv);
> -	if (ret)
> -		goto out_teardown_irq;
> +	dsa_switch_for_each_cpu_port(cpu_dp, priv->ds) {
> +		priv->cpu_port = cpu_dp->index;
> +		mb->cpu.mask = BIT(priv->cpu_port);
> +		mb->cpu.trap_port = priv->cpu_port;
> +		ret = rtl8365mb_cpu_config(priv);
> +		if (ret)
> +			goto out_teardown_irq;
> +
> +		break;

Maybe a comment like /* Currently, only one CPU port is supported */?

> +	}
>  
>  	/* Configure ports */
>  	for (i = 0; i < priv->num_ports; i++) {
> @@ -1967,8 +1975,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
>  			 "found an RTL8365MB-VC switch (ver=0x%04x)\n",
>  			 chip_ver);
>  
> -		priv->cpu_port = RTL8365MB_CPU_PORT_NUM_8365MB_VC;
> -		priv->num_ports = priv->cpu_port + 1;
> +		priv->num_ports = RTL8365MB_MAX_NUM_PORTS;
>  
>  		mb->priv = priv;
>  		mb->chip_id = chip_id;
> @@ -1979,8 +1986,6 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
>  		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);
>  
>  		mb->cpu.enable = 1;
> -		mb->cpu.mask = BIT(priv->cpu_port);
> -		mb->cpu.trap_port = priv->cpu_port;
>  		mb->cpu.insert = RTL8365MB_CPU_INSERT_TO_ALL;
>  		mb->cpu.position = RTL8365MB_CPU_POS_AFTER_SA;
>  		mb->cpu.rx_length = RTL8365MB_CPU_RXLEN_64BYTES;

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

* Re: [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support
  2022-01-05  3:15 ` [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support Luiz Angelo Daros de Luca
@ 2022-01-10 13:26   ` Alvin Šipraga
  2022-01-17  4:26   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 13:26 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> Realtek's RTL8367S, a 5+2 port 10/100/1000M Ethernet switch.
> It shares the same driver family (RTL8367C) with other models
> as the RTL8365MB-VC. Its compatible string is "realtek,rtl8367s".
>
> It was tested only with MDIO interface (realtek-mdio), although it might
> work out-of-the-box with SMI interface (using realtek-smi).
>
> This patch was based on an unpublished patch from Alvin Šipraga
> <alsi@bang-olufsen.dk>.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-05  3:15 ` [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint Luiz Angelo Daros de Luca
@ 2022-01-10 13:39   ` Alvin Šipraga
  2022-01-10 13:53     ` Aw: " Frank Wunderlich
  0 siblings, 1 reply; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-10 13:39 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli,
	olteanv, arinc.unal, frank-w

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

> Now CPU port is not limited to a single port. Also, extint can be used
> as non-cpu ports, as long as it defines relatek,ext-int. The last cpu
> port will be used as trap_port.
>
> The CPU information was dropped from chip data as it was not used
> outside setup. The only other place it was used is when it wrongly
> checks for CPU port when it should check for extint.
>
> realtek_priv->cpu_port is now only used by rtl8366rb.c

Great work with this series! If I understood correctly from your last
emails, you weren't actually able to test this due to hardware
constraints. While I think this change is not going to introduce any
surprises, I think you should still mention that it is not tested.

Some more comments below but in general the change makes sense to me.

>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
>  drivers/net/dsa/realtek/rtl8365mb.c | 53 +++++++++++++++--------------
>  1 file changed, 27 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index 59e08b192c06..6a00a162b2ac 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -556,7 +556,6 @@ struct rtl8365mb_port {
>   * @chip_ver: chip silicon revision
>   * @port_mask: mask of all ports
>   * @learn_limit_max: maximum number of L2 addresses the chip can learn
> - * @cpu: CPU tagging and CPU port configuration for this chip
>   * @mib_lock: prevent concurrent reads of MIB counters
>   * @ports: per-port data
>   * @jam_table: chip-specific initialization jam table
> @@ -571,7 +570,6 @@ struct rtl8365mb {
>  	u32 chip_ver;
>  	u32 port_mask;
>  	u32 learn_limit_max;
> -	struct rtl8365mb_cpu cpu;
>  	struct mutex mib_lock;
>  	struct rtl8365mb_port ports[RTL8365MB_MAX_NUM_PORTS];
>  	const struct rtl8365mb_jam_tbl_entry *jam_table;
> @@ -769,17 +767,20 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port,
>  	u32 val;
>  	int ret;
>  
> -	if (port != priv->cpu_port) {
> -		dev_err(priv->dev, "only one EXT interface is currently supported\n");
> +	mb = priv->chip_data;
> +	p = &mb->ports[port];
> +	ext_int = p->ext_int;
> +
> +	if (ext_int == RTL8365MB_NOT_EXT) {
> +		dev_err(priv->dev,
> +			"Port %d is not identified as extenal interface.\n",

Maybe just a warning?
also: s/as extenal/as an external/

> +			port);
>  		return -EINVAL;
>  	}
>  
>  	dp = dsa_to_port(priv->ds, port);
>  	dn = dp->dn;
>  
> -	mb = priv->chip_data;
> -	p = &mb->ports[port];
> -	ext_int = p->ext_int;
>  
>  	/* Set the RGMII TX/RX delay
>  	 *
> @@ -859,15 +860,17 @@ static int rtl8365mb_ext_config_forcemode(struct realtek_priv *priv, int port,
>  	int val;
>  	int ret;
>  
> -	if (port != priv->cpu_port) {
> -		dev_err(priv->dev, "only one EXT interface is currently supported\n");
> -		return -EINVAL;
> -	}
> -
>  	mb = priv->chip_data;
>  	p = &mb->ports[port];
>  	ext_int = p->ext_int;
>  
> +	if (ext_int == RTL8365MB_NOT_EXT) {
> +		dev_err(priv->dev,
> +			"Port %d is not identified as extenal interface.\n",

ditto

> +			port);
> +		return -EINVAL;
> +	}
> +
>  	if (link) {
>  		/* Force the link up with the desired configuration */
>  		r_link = 1;
> @@ -1734,10 +1737,8 @@ static void rtl8365mb_irq_teardown(struct realtek_priv *priv)
>  	}
>  }
>  
> -static int rtl8365mb_cpu_config(struct realtek_priv *priv)
> +static int rtl8365mb_cpu_config(struct realtek_priv *priv, struct rtl8365mb_cpu *cpu)

const struct rtl8365mb_cpu?

>  {
> -	struct rtl8365mb *mb = priv->chip_data;
> -	struct rtl8365mb_cpu *cpu = &mb->cpu;
>  	u32 val;
>  	int ret;
>  
> @@ -1839,11 +1840,17 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
>  		dev_info(priv->dev, "no interrupt support\n");
>  
>  	/* Configure CPU tagging */
> +	cpu.mask = 0;

I guess the unused cpu variable in the earlier patch belongs in this
one, in which case you can just initialize it = { 0 } so that you don't
need to explicitly set cpu.mask = 0.

>  	dsa_switch_for_each_cpu_port(cpu_dp, priv->ds) {
> -		priv->cpu_port = cpu_dp->index;
> -		mb->cpu.mask = BIT(priv->cpu_port);
> -		mb->cpu.trap_port = priv->cpu_port;
> -		ret = rtl8365mb_cpu_config(priv);
> +		cpu.enable = 1;
> +		cpu.insert = RTL8365MB_CPU_INSERT_TO_ALL;
> +		cpu.position = RTL8365MB_CPU_POS_AFTER_SA;
> +		cpu.rx_length = RTL8365MB_CPU_RXLEN_64BYTES;
> +		cpu.format = RTL8365MB_CPU_FORMAT_8BYTES;
> +		cpu.trap_port = cpu_dp->index;

If you are going to do this, perhaps it's better specified as a device
tree property like the external interface index? Making the "last" CPU
port the trap port is not incorrect, but it seems quite arbitrary.

> +		cpu.mask |= BIT(cpu_dp->index);
> +
> +		ret = rtl8365mb_cpu_config(priv, &cpu);

Shouldn't this go outside the loop to avoid potentially calling it twice
in a row?

>  		if (ret)
>  			goto out_teardown_irq;
>  
> @@ -1862,7 +1869,7 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
>  		dn = dsa_to_port(priv->ds, i)->dn;
>  
>  		/* Forward only to the CPU */
> -		ret = rtl8365mb_port_set_isolation(priv, i, BIT(priv->cpu_port));
> +		ret = rtl8365mb_port_set_isolation(priv, i, cpu.mask);
>  		if (ret)
>  			goto out_teardown_irq;
>  
> @@ -2003,12 +2010,6 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
>  		mb->jam_table = rtl8365mb_init_jam_8365mb_vc;
>  		mb->jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc);
>  
> -		mb->cpu.enable = 1;
> -		mb->cpu.insert = RTL8365MB_CPU_INSERT_TO_ALL;
> -		mb->cpu.position = RTL8365MB_CPU_POS_AFTER_SA;
> -		mb->cpu.rx_length = RTL8365MB_CPU_RXLEN_64BYTES;
> -		mb->cpu.format = RTL8365MB_CPU_FORMAT_8BYTES;
> -
>  		break;
>  	default:
>  		dev_err(priv->dev,

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

* Aw: Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-10 13:39   ` Alvin Šipraga
@ 2022-01-10 13:53     ` Frank Wunderlich
  2022-01-11 18:17       ` Alvin Šipraga
  0 siblings, 1 reply; 88+ messages in thread
From: Frank Wunderlich @ 2022-01-10 13:53 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: Luiz Angelo Daros de Luca, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

Hi,

i have 2 devices here i currently try this series.

1x Bananapi R64 v0.1 (mt7622 SOC) with rtl8367s (sgmii+rgmii) - configured to use extport 2 in rgmii mode
1x Bananapi R2 Pro v0 (rk3568 SOC) with rtl8367RB (rgmii+rgmii) - configured to use extport 1 in rgmii mode

on both devices i get mdio running after additional reset in probe and ports are
recognizing link up (got the real port-reg-mapping)

on r64 i get pings working but tcp (ssh, http) seems not working.
on r2pro i cannot get even ping working (but rk3568 gmac seems to come up).

but i'm not deep enough in driver coding to find out whats wrong not having technical documents for checking registers to values needed.

so i need support from anyone to test it further, but devices are here ;)

regards Frank

> Gesendet: Montag, 10. Januar 2022 um 14:39 Uhr
> Von: "Alvin Šipraga" <ALSI@bang-olufsen.dk>
> Great work with this series! If I understood correctly from your last
> emails, you weren't actually able to test this due to hardware
> constraints. While I think this change is not going to introduce any
> surprises, I think you should still mention that it is not tested.


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

* Re: Aw: Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-10 13:53     ` Aw: " Frank Wunderlich
@ 2022-01-11 18:17       ` Alvin Šipraga
  2022-01-11 18:45         ` Aw: " Frank Wunderlich
  0 siblings, 1 reply; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-11 18:17 UTC (permalink / raw)
  To: Frank Wunderlich
  Cc: Luiz Angelo Daros de Luca, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

Frank Wunderlich <frank-w@public-files.de> writes:

> Hi,
>
> i have 2 devices here i currently try this series.
>
> 1x Bananapi R64 v0.1 (mt7622 SOC) with rtl8367s (sgmii+rgmii) - configured to use extport 2 in rgmii mode
> 1x Bananapi R2 Pro v0 (rk3568 SOC) with rtl8367RB (rgmii+rgmii) - configured to use extport 1 in rgmii mode
>
> on both devices i get mdio running after additional reset in probe and ports are
> recognizing link up (got the real port-reg-mapping)
>
> on r64 i get pings working but tcp (ssh, http) seems not working.
> on r2pro i cannot get even ping working (but rk3568 gmac seems to come
> up).

Luiz, any comments regarding this? I suppose if the chip ID/revision is
the same for both 67S and 67RB, they should work pretty much the same,
right?

>
> but i'm not deep enough in driver coding to find out whats wrong not having technical documents for checking registers to values needed.

Ping working but TCP not working is a bit strange. You could check the
output of ethtool -S and see if that meets your expectations. If you
have a relatively modern ethtool you can also append --all-groups to the
comment to get a more standard output.

You can also try adjusting the RGMII TX/RX delay and pause settings -
that might help for the R2 where you aren't getting any packets
through.

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

* Aw: Re:  Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-11 18:17       ` Alvin Šipraga
@ 2022-01-11 18:45         ` Frank Wunderlich
  2022-01-13 12:37           ` Alvin Šipraga
  0 siblings, 1 reply; 88+ messages in thread
From: Frank Wunderlich @ 2022-01-11 18:45 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: Luiz Angelo Daros de Luca, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

Hi,

> Gesendet: Dienstag, 11. Januar 2022 um 19:17 Uhr
> Von: "Alvin Šipraga" <ALSI@bang-olufsen.dk>

> Luiz, any comments regarding this? I suppose if the chip ID/revision is
> the same for both 67S and 67RB, they should work pretty much the same,
> right?

my phy driver is same for both devices and afaik only do different RX/TX delays. With the chip-rev-patch 0x0020 i can init the switch, but have no technical documentation except the phy driver code.

> Ping working but TCP not working is a bit strange. You could check the
> output of ethtool -S and see if that meets your expectations. If you
> have a relatively modern ethtool you can also append --all-groups to the
> comment to get a more standard output.

as far as i see in tcpdump (suggested by luiz) on target it is a checksum error where checksum is always 0x8382 (maybe some kind of fixed tag).

16:39:07.994825 IP (tos 0x10, ttl 64, id 54002, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.1.2.43284 > 192.168.1.1.22: Flags [S], cksum 0x8382 (incorrect -> 0xa6f6), seq 3231275121, win 64240, options [mss 1460,sackOK,TS val 1615921214 ecr 0,nop,wscale 7], length 0
16:39:12.154790 IP (tos 0x10, ttl 64, id 54003, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.1.2.43284 > 192.168.1.1.22: Flags [S], cksum 0x8382 (incorrect -> 0x96b6), seq 3231275121, win 64240, options [mss 1460,sackOK,TS val 1615925374 ecr 0,nop,wscale 7], length 0

> You can also try adjusting the RGMII TX/RX delay and pause settings -
> that might help for the R2 where you aren't getting any packets
> through.

r2pro i got working by setting both delays to 0 as phy-driver does the same (after some calculation).

on r64 this is a bit more tricky, because the phy driver uses  tx=1 and rx=3 with this calculation for reg-value

regData = (regData & 0xFFF0) | ((txDelay << 3) & 0x0008) | (rxDelay & 0x0007);

but in dts i need the values in picosends (?) and here i do not know how to calculate them

regards Frank

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

* Re: Aw: Re:  Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-11 18:45         ` Aw: " Frank Wunderlich
@ 2022-01-13 12:37           ` Alvin Šipraga
  2022-01-13 15:56             ` Aw: " Frank Wunderlich
  0 siblings, 1 reply; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-13 12:37 UTC (permalink / raw)
  To: Frank Wunderlich
  Cc: Luiz Angelo Daros de Luca, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

Frank Wunderlich <frank-w@public-files.de> writes:

> Hi,
>
>> Gesendet: Dienstag, 11. Januar 2022 um 19:17 Uhr
>> Von: "Alvin Šipraga" <ALSI@bang-olufsen.dk>
>
>> Luiz, any comments regarding this? I suppose if the chip ID/revision is
>> the same for both 67S and 67RB, they should work pretty much the same,
>> right?
>
> my phy driver is same for both devices and afaik only do different
> RX/TX delays. With the chip-rev-patch 0x0020 i can init the switch,
> but have no technical documentation except the phy driver code.
>
>> Ping working but TCP not working is a bit strange. You could check the
>> output of ethtool -S and see if that meets your expectations. If you
>> have a relatively modern ethtool you can also append --all-groups to the
>> comment to get a more standard output.
>
> as far as i see in tcpdump (suggested by luiz) on target it is a checksum error where checksum is always 0x8382 (maybe some kind of fixed tag).
>
> 16:39:07.994825 IP (tos 0x10, ttl 64, id 54002, offset 0, flags [DF], proto TCP (6), length 60)
>     192.168.1.2.43284 > 192.168.1.1.22: Flags [S], cksum 0x8382
> (incorrect -> 0xa6f6), seq 3231275121, win 64240, options [mss
> 1460,sackOK,TS val 1615921214 ecr 0,nop,wscale 7], length 0
> 16:39:12.154790 IP (tos 0x10, ttl 64, id 54003, offset 0, flags [DF], proto TCP (6), length 60)
>     192.168.1.2.43284 > 192.168.1.1.22: Flags [S], cksum 0x8382
> (incorrect -> 0x96b6), seq 3231275121, win 64240, options [mss
> 1460,sackOK,TS val 1615925374 ecr 0,nop,wscale 7], length 0

That's weird, I must admit I do not recognize this issue at all. Try
dumping the whole packet with -x and maybe you can see what kind of data
you are getting.

>
>> You can also try adjusting the RGMII TX/RX delay and pause settings -
>> that might help for the R2 where you aren't getting any packets
>> through.
>
> r2pro i got working by setting both delays to 0 as phy-driver does the same (after some calculation).
>
> on r64 this is a bit more tricky, because the phy driver uses  tx=1 and rx=3 with this calculation for reg-value
>
> regData = (regData & 0xFFF0) | ((txDelay << 3) & 0x0008) | (rxDelay & 0x0007);
>
> but in dts i need the values in picosends (?) and here i do not know
> how to calculate them

Try:

    tx-internal-delay-ps = <2000>;
    rx-internal-delay-ps = <1000>;

This should correspond to internal values tx=1 and rx=3.

Kind regards,
Alvin

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

* Aw: Re:  Re:  Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-13 12:37           ` Alvin Šipraga
@ 2022-01-13 15:56             ` Frank Wunderlich
  2022-01-18  4:58               ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 88+ messages in thread
From: Frank Wunderlich @ 2022-01-13 15:56 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: Luiz Angelo Daros de Luca, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

Hi,

the problem is checksum offloading on the gmac (soc-side)

root@bpi-r64:~# ethtool -k eth1 | grep checksum                                                                                                  
rx-checksumming: on                                                                                                                              
tx-checksumming: on                                                                                                                              
        tx-checksum-ipv4: on    #<<<<<<<<<<<<<                           
        tx-checksum-ip-generic: off [fixed]                                                                                                      
        tx-checksum-ipv6: on    #<<<<<<<<<<<<<                          
        tx-checksum-fcoe-crc: off [fixed]                                                                                                        
        tx-checksum-sctp: off [fixed]

in my case i tried ipv4....and after disabling the offload i get a connection

root@bpi-r64:~# ethtool -K eth1 rx off tx off                                                                                                    
Actual changes:                                                                                                                                  
tx-checksum-ipv4: off                                                                                                                            
tx-checksum-ipv6: off                                                                                                                            
tx-tcp-segmentation: off [not requested]                                                                                                         
tx-tcp6-segmentation: off [not requested]                                                                                                        
rx-checksum: off                                                                                                                                 
root@bpi-r64:~# telnet 192.168.1.1 22                                                                                                            
Trying 192.168.1.1...                                                                                                                            
Connected to 192.168.1.1.                                                                                                                        
Escape character is '^]'.                                                                                                                        
SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.3                                                                                                          
^C

regards Frank


> Gesendet: Donnerstag, 13. Januar 2022 um 13:37 Uhr
> Von: "Alvin Šipraga" <ALSI@bang-olufsen.dk>
> An: "Frank Wunderlich" <frank-w@public-files.de>
> Cc: "Luiz Angelo Daros de Luca" <luizluca@gmail.com>, "netdev@vger.kernel.org" <netdev@vger.kernel.org>, "linus.walleij@linaro.org" <linus.walleij@linaro.org>, "andrew@lunn.ch" <andrew@lunn.ch>, "vivien.didelot@gmail.com" <vivien.didelot@gmail.com>, "f.fainelli@gmail.com" <f.fainelli@gmail.com>, "olteanv@gmail.com" <olteanv@gmail.com>, "arinc.unal@arinc9.com" <arinc.unal@arinc9.com>
> Betreff: Re: Aw: Re:  Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
>
> Frank Wunderlich <frank-w@public-files.de> writes:
> 
> > Hi,
> >
> >> Gesendet: Dienstag, 11. Januar 2022 um 19:17 Uhr
> >> Von: "Alvin Šipraga" <ALSI@bang-olufsen.dk>
> >
> >> Luiz, any comments regarding this? I suppose if the chip ID/revision is
> >> the same for both 67S and 67RB, they should work pretty much the same,
> >> right?
> >
> > my phy driver is same for both devices and afaik only do different
> > RX/TX delays. With the chip-rev-patch 0x0020 i can init the switch,
> > but have no technical documentation except the phy driver code.
> >
> >> Ping working but TCP not working is a bit strange. You could check the
> >> output of ethtool -S and see if that meets your expectations. If you
> >> have a relatively modern ethtool you can also append --all-groups to the
> >> comment to get a more standard output.
> >
> > as far as i see in tcpdump (suggested by luiz) on target it is a checksum error where checksum is always 0x8382 (maybe some kind of fixed tag).
> >
> > 16:39:07.994825 IP (tos 0x10, ttl 64, id 54002, offset 0, flags [DF], proto TCP (6), length 60)
> >     192.168.1.2.43284 > 192.168.1.1.22: Flags [S], cksum 0x8382
> > (incorrect -> 0xa6f6), seq 3231275121, win 64240, options [mss
> > 1460,sackOK,TS val 1615921214 ecr 0,nop,wscale 7], length 0
> > 16:39:12.154790 IP (tos 0x10, ttl 64, id 54003, offset 0, flags [DF], proto TCP (6), length 60)
> >     192.168.1.2.43284 > 192.168.1.1.22: Flags [S], cksum 0x8382
> > (incorrect -> 0x96b6), seq 3231275121, win 64240, options [mss
> > 1460,sackOK,TS val 1615925374 ecr 0,nop,wscale 7], length 0
> 
> That's weird, I must admit I do not recognize this issue at all. Try
> dumping the whole packet with -x and maybe you can see what kind of data
> you are getting.

2 example packets from tcpdump (if you still want to see it)

$ sudo tcpdump -i enx00131100063c -vvv -nn -x
tcpdump: listening on enx00131100063c, link-type EN10MB (Ethernet), capture size 262144 bytes


16:43:50.297259 IP (tos 0x10, ttl 64, id 19802, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.1.2.38278 > 192.168.1.1.22: Flags [S], cksum 0x8382 (incorrect -> 0xb704), seq 2565260294, win 64240, options [mss 1460,sackOK,TS val 2917954112 ecr 0,nop,wscale 7], length 0
	0x0000:  4510 003c 4d5a 4000 4006 69fe c0a8 0102
	0x0010:  c0a8 0101 9586 0016 98e6 c406 0000 0000
	0x0020:  a002 faf0 8382 0000 0204 05b4 0402 080a
	0x0030:  adec 7240 0000 0000 0103 0307
16:43:51.324255 IP (tos 0x10, ttl 64, id 19803, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.1.2.38278 > 192.168.1.1.22: Flags [S], cksum 0x8382 (incorrect -> 0xb300), seq 2565260294, win 64240, options [mss 1460,sackOK,TS val 2917955140 ecr 0,nop,wscale 7], length 0
	0x0000:  4510 003c 4d5b 4000 4006 69fd c0a8 0102
	0x0010:  c0a8 0101 9586 0016 98e6 c406 0000 0000
	0x0020:  a002 faf0 8382 0000 0204 05b4 0402 080a
	0x0030:  adec 7644 0000 0000 0103 0307


> >> You can also try adjusting the RGMII TX/RX delay and pause settings -
> >> that might help for the R2 where you aren't getting any packets
> >> through.
> >
> > r2pro i got working by setting both delays to 0 as phy-driver does the same (after some calculation).
> >
> > on r64 this is a bit more tricky, because the phy driver uses  tx=1 and rx=3 with this calculation for reg-value
> >
> > regData = (regData & 0xFFF0) | ((txDelay << 3) & 0x0008) | (rxDelay & 0x0007);
> >
> > but in dts i need the values in picosends (?) and here i do not know
> > how to calculate them
> 
> Try:
> 
>     tx-internal-delay-ps = <2000>;
>     rx-internal-delay-ps = <1000>;
> 
> This should correspond to internal values tx=1 and rx=3.

thanks i've found out and used tx=2000 and rx=900 (your 1000 is rounded to 3), but only disabling checksum-offloading fixed the problem. need to look how to make it persistent.

Afaik switch driver does not do any Checksum-handling so problem lies in the SOC ethernet driver (here i guess the mtk_soc_eth.c for mt7622). maybe i find an option to disable the offloading in dts because boards with mt7531 switch  working. maybe DSA-Tag handling can be changed, but this is no breaking point from my POV.

regards Frank

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

* Re: [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv
  2022-01-05  3:15 ` [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv Luiz Angelo Daros de Luca
  2022-01-07  3:42   ` Jakub Kicinski
  2022-01-10 12:33   ` Alvin Šipraga
@ 2022-01-16  0:04   ` Linus Walleij
  2022-01-20 14:37   ` Vladimir Oltean
  3 siblings, 0 replies; 88+ messages in thread
From: Linus Walleij @ 2022-01-16  0:04 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, andrew, vivien.didelot, f.fainelli, olteanv, ALSI,
	arinc.unal, frank-w

On Wed, Jan 5, 2022 at 4:15 AM Luiz Angelo Daros de Luca
<luizluca@gmail.com> wrote:

> In preparation to adding other interfaces, the private data structure
> was renamed to priv. Also, realtek_smi_variant and realtek_smi_ops
> were renamed to realtek_variant and realtek_ops as those structs are
> not SMI specific.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Fine by me:
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi
  2022-01-05  3:15 ` [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi Luiz Angelo Daros de Luca
  2022-01-10 12:38   ` Alvin Šipraga
@ 2022-01-16  0:05   ` Linus Walleij
  2022-01-17  3:46   ` Florian Fainelli
  2 siblings, 0 replies; 88+ messages in thread
From: Linus Walleij @ 2022-01-16  0:05 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, andrew, vivien.didelot, f.fainelli, olteanv, ALSI,
	arinc.unal, frank-w

On Wed, Jan 5, 2022 at 4:15 AM Luiz Angelo Daros de Luca
<luizluca@gmail.com> wrote:

> Remove the only two direct calls from subdrivers to realtek-smi.
> Now they are called from realtek_priv. Subdrivers can now be
> linked independently from realtek-smi.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi
  2022-01-05  3:15 ` [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi Luiz Angelo Daros de Luca
  2022-01-10 12:38   ` Alvin Šipraga
  2022-01-16  0:05   ` Linus Walleij
@ 2022-01-17  3:46   ` Florian Fainelli
  2 siblings, 0 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  3:46 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> Remove the only two direct calls from subdrivers to realtek-smi.
> Now they are called from realtek_priv. Subdrivers can now be
> linked independently from realtek-smi.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
[snip]

Just a nit below.

>   	return 0;
> @@ -1705,7 +1707,7 @@ static int rtl8366rb_reset_chip(struct realtek_priv *priv)
>   	u32 val;
>   	int ret;
>   
> -	realtek_smi_write_reg_noack(priv, RTL8366RB_RESET_CTRL_REG,
> +	priv->write_reg_noack(priv, RTL8366RB_RESET_CTRL_REG,
>   				    RTL8366RB_CHIP_CTRL_RESET_HW);

Only if you need to spin a new version, the second line should start at 
the character after the opening parenthesis on the previous line.

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules
  2022-01-05  3:15 ` [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules Luiz Angelo Daros de Luca
  2022-01-10 12:43   ` Alvin Šipraga
@ 2022-01-17  4:02   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  4:02 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> Preparing for multiple interfaces support, the drivers
> must be independent of realtek-smi.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops
  2022-01-05  3:15 ` [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops Luiz Angelo Daros de Luca
  2022-01-10 13:09   ` Alvin Šipraga
@ 2022-01-17  4:15   ` Florian Fainelli
  2022-01-18  2:55     ` Luiz Angelo Daros de Luca
  1 sibling, 1 reply; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  4:15 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> The ds->ops->phy_read will only be used if the ds->slave_mii_bus
> was not initialized. Calling realtek_smi_setup_mdio will create a
> ds->slave_mii_bus, making ds->ops->phy_read dormant.
> 
> Using ds->ops->phy_read will allow switches connected through non-SMI
> interfaces (like mdio) to let ds allocate slave_mii_bus and reuse the
> same code.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Humm assigning dsa_switch_ops::phy_read will force DSA into tearing down 
the MDIO bus in dsa_switch_teardown() instead of letting your driver do 
it and since realtek-smi-core.c uses devm_mdiobus_unregister(), it is 
not clear to me what is going to happen but it sounds like a double free 
might happen?

It seems more prudent to me to leave existing code.
-- 
Florian

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

* Re: [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers
  2022-01-05  3:15 ` [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers Luiz Angelo Daros de Luca
  2022-01-10 13:09   ` Alvin Šipraga
@ 2022-01-17  4:22   ` Florian Fainelli
  2022-01-18  4:38     ` Luiz Angelo Daros de Luca
  1 sibling, 1 reply; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  4:22 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> This driver is a mdio_driver instead of a platform driver (like
> realtek-smi).
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> ---
>   drivers/net/dsa/realtek/Kconfig        |  11 +-
>   drivers/net/dsa/realtek/Makefile       |   1 +
>   drivers/net/dsa/realtek/realtek-mdio.c | 221 +++++++++++++++++++++++++
>   drivers/net/dsa/realtek/realtek.h      |   2 +
>   4 files changed, 233 insertions(+), 2 deletions(-)
>   create mode 100644 drivers/net/dsa/realtek/realtek-mdio.c
> 
> diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
> index cd1aa95b7bf0..73b26171fade 100644
> --- a/drivers/net/dsa/realtek/Kconfig
> +++ b/drivers/net/dsa/realtek/Kconfig
> @@ -9,6 +9,13 @@ menuconfig NET_DSA_REALTEK
>   	help
>   	  Select to enable support for Realtek Ethernet switch chips.
>   
> +config NET_DSA_REALTEK_MDIO
> +	tristate "Realtek MDIO connected switch driver"
> +	depends on NET_DSA_REALTEK
> +	default y

I suppose this is fine since we depend on NET_DSA_REALTEK.

[snip]

> +static int realtek_mdio_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
> +{
> +	u32 phy_id = priv->phy_id;
> +	struct mii_bus *bus = priv->bus;
> +
> +	mutex_lock(&bus->mdio_lock);
> +
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	*data = bus->read(bus, phy_id, REALTEK_MDIO_DATA_READ_REG);

Do you have no way to return an error for instance, if you read from a 
non-existent PHY device on the MDIO bus, -EIO would be expected for 
instance. If the data returned is 0xffff that ought to be enough.

> +
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return 0;
> +}
> +
> +static int realtek_mdio_write_reg(struct realtek_priv *priv, u32 addr, u32 data)
> +{
> +	u32 phy_id = priv->phy_id;
> +	struct mii_bus *bus = priv->bus;
> +
> +	mutex_lock(&bus->mdio_lock);
> +
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);

This repeats between read and writes, might be worth a helper function.

> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_DATA_WRITE_REG, data);
> +	bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> +	bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP);
> +
> +	mutex_unlock(&bus->mdio_lock);
> +
> +	return 0;
> +}
> +
> +/* Regmap accessors */
> +
> +static int realtek_mdio_write(void *ctx, u32 reg, u32 val)
> +{
> +	struct realtek_priv *priv = ctx;
> +
> +	return realtek_mdio_write_reg(priv, reg, val);
> +}
> +
> +static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
> +{
> +	struct realtek_priv *priv = ctx;
> +
> +	return realtek_mdio_read_reg(priv, reg, val);
> +}

Do you see a value for this function as oppposed to inlining the bodies 
of realtek_mdio_read_reg and realtek_mdio_write_reg directly into these 
two functions?

> +
> +static const struct regmap_config realtek_mdio_regmap_config = {
> +	.reg_bits = 10, /* A4..A0 R4..R0 */
> +	.val_bits = 16,
> +	.reg_stride = 1,
> +	/* PHY regs are at 0x8000 */
> +	.max_register = 0xffff,
> +	.reg_format_endian = REGMAP_ENDIAN_BIG,
> +	.reg_read = realtek_mdio_read,
> +	.reg_write = realtek_mdio_write,
> +	.cache_type = REGCACHE_NONE,
> +};
> +
> +static int realtek_mdio_probe(struct mdio_device *mdiodev)
> +{
> +	struct realtek_priv *priv;
> +	struct device *dev = &mdiodev->dev;
> +	const struct realtek_variant *var;
> +	int ret;
> +	struct device_node *np;
> +
> +	var = of_device_get_match_data(dev);

Don't you have to check that var is non-NULL just in case?

> +	priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->map = devm_regmap_init(dev, NULL, priv, &realtek_mdio_regmap_config);
> +	if (IS_ERR(priv->map)) {
> +		ret = PTR_ERR(priv->map);
> +		dev_err(dev, "regmap init failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	priv->phy_id = mdiodev->addr;

Please use a more descriptive variable name such as mdio_addr or 
something like that. I know that phy_id is typically used but it could 
also mean a 32-bit PHY unique identifier, which a MDIO device does not 
have typically.

Looks fine otherwise.
-- 
Florian

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

* Re: [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int"
  2022-01-05  3:15 ` [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int" Luiz Angelo Daros de Luca
  2022-01-10 13:15   ` Alvin Šipraga
@ 2022-01-17  4:25   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  4:25 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> "extport" 0, 1, 2 was used to reference external ports (ext0,
> ext1, ext2). Meanwhile, port 0..9 is used as switch ports,
> including external ports. "extport" was renamed to extint to
> make it clear it does not mean the port number but the external
> interface number.
> 
> The macros that map extint numbers to registers addresses now
> use inline ifs instead of binary arithmetic.
> 
> "extint" was hardcoded to 1. However, some chips have multiple
> external interfaces. It's not right to assume the CPU port uses
> extint 1 nor that all extint are CPU ports. Now the association
> between the port and the external interface can be defined with
> a device-tree port property "realtek,ext-int".
> 
> This patch still does not allow multiple CPU ports nor extint
> as a non CPU port.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1
  2022-01-05  3:15 ` [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1 Luiz Angelo Daros de Luca
  2022-01-10 13:18   ` Alvin Šipraga
@ 2022-01-17  4:25   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  4:25 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port
  2022-01-05  3:15 ` [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port Luiz Angelo Daros de Luca
  2022-01-07  3:37   ` Jakub Kicinski
  2022-01-10 13:22   ` Alvin Šipraga
@ 2022-01-17  4:26   ` Florian Fainelli
  2 siblings, 0 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  4:26 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> Instead of a fixed CPU port, assume that DSA is correct.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support
  2022-01-05  3:15 ` [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support Luiz Angelo Daros de Luca
  2022-01-10 13:26   ` Alvin Šipraga
@ 2022-01-17  4:26   ` Florian Fainelli
  1 sibling, 0 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-17  4:26 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, netdev
  Cc: linus.walleij, andrew, vivien.didelot, olteanv, alsi, arinc.unal,
	frank-w



On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> Realtek's RTL8367S, a 5+2 port 10/100/1000M Ethernet switch.
> It shares the same driver family (RTL8367C) with other models
> as the RTL8365MB-VC. Its compatible string is "realtek,rtl8367s".
> 
> It was tested only with MDIO interface (realtek-mdio), although it might
> work out-of-the-box with SMI interface (using realtek-smi).
> 
> This patch was based on an unpublished patch from Alvin Šipraga
> <alsi@bang-olufsen.dk>.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-- 
Florian

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

* Re: [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops
  2022-01-17  4:15   ` Florian Fainelli
@ 2022-01-18  2:55     ` Luiz Angelo Daros de Luca
  2022-01-18 13:16       ` Andrew Lunn
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-18  2:55 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: open list:NETWORKING DRIVERS, Linus Walleij, Andrew Lunn,
	Vivien Didelot, Vladimir Oltean, Alvin Šipraga,
	Arınç ÜNAL, Frank Wunderlich

> On 1/4/2022 7:15 PM, Luiz Angelo Daros de Luca wrote:
> > The ds->ops->phy_read will only be used if the ds->slave_mii_bus
> > was not initialized. Calling realtek_smi_setup_mdio will create a
> > ds->slave_mii_bus, making ds->ops->phy_read dormant.
> >
> > Using ds->ops->phy_read will allow switches connected through non-SMI
> > interfaces (like mdio) to let ds allocate slave_mii_bus and reuse the
> > same code.
> >
> > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> > Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
>
> Humm assigning dsa_switch_ops::phy_read will force DSA into tearing down
> the MDIO bus in dsa_switch_teardown() instead of letting your driver do
> it and since realtek-smi-core.c uses devm_mdiobus_unregister(), it is
> not clear to me what is going to happen but it sounds like a double free
> might happen?

Thanks, Florian. You should be correct. It might call
mdiobus_unregister() and mdiobus_free() twice, once inside the dsa
code and another one by the devm (if I understood how devm functions
work).

The issue is that the dsa switch is assuming that if slave_mii is
allocated and ds->ops->phy_read is defined, it has allocated the
slave_mii by itself and it should clean up the slave_mii during
teardown.
That assumption came from commit
5135e96a3dd2f4555ae6981c3155a62bcf3227f6 "So I can only guess that no
driver that implements ds->ops->phy_read also allocates and registers
ds->slave_mii_bus itself.". If that is true, the condition during
dsa_switch_setup() is not correct.

During dsa_switch_setup(), if it does not fail, I know that
ds->slave_mii_bus will be allocated, either by ds->ops->setup() or by
itself.

dsa_switch_setup() {
        ....
        ds->ops->setup()
        ....
        if (!ds->slave_mii_bus && ds->ops->phy_read) {
              ...allocate and register ds->slave_mii_bus...
        }
}

During the teardown, ds->slave_mii_bus will always be true (if not
cleaning from an error before it was allocated). So, the test is
really about having ds->ops->phy_read.

dsa_switch_teardown() {
        ...
        if (ds->slave_mii_bus && ds->ops->phy_read) {
             ...unregister and free ds->slave_mii_bus...
        }
        ...
        ds->ops->teardown();
        ...
}

As ds->ops->teardown() is called after slave_mii_bus is gone, there is
no opportunity for ds->ops to clean the mii_slave_bus it might have
allocated.
It does not make sense for me to have those two "if" conditions
working together. It should be either:

dsa_switch_setup() {
        ....
        ds->ops->setup()
        ....
        if (ds->ops->phy_read) {
              if (ds->slave_mii_bus)
                    error("ds->ops->phy_read is set, I should be the
one allocating ds->slave_mii_bus!")
              ...allocate and register ds->slave_mii_bus...
        }
}

if "no driver that implements ds->ops->phy_read also allocates and
registers ds->slave_mii_bus itself" or:

dsa_switch_teardown() {
        ...
        if (ds->slave_mii_bus && "slave_mii_bus was allocated by myself") {
             ...unregister and free ds->slave_mii_bus...
        }
        ds->ops->teardown();
        ...
}

if ds->ops->phy_read value should not tell if ds->slave_mii_bus should
be cleaned by the DSA switch.

I would selfishly hope the correct one was the second option because
it would make my code much cleaner. If not, that's a complex issue to
solve without lots of duplications: realtek-smi drivers should not
have ds->ops->phy_read defined while realtek-mdio requires it. I'll
need to duplicate dsa_switch_ops for each subdriver only to unset
phy_read and also duplicate realtek_variant for each interface only to
reference that different dsa_switch_ops.

BTW, the realtek-smi calls
of_node_put(priv->slave_mii_bus->dev.of_node) during shutdown while
other dsa drivers do not seem to care. Wouldn't devm controls be
enough for cleaning that mii_bus?
Even if not, wouldn't the ds->ops->teardown be the correct place for
that cleanup and not realtek_smi_remove()?

> It seems more prudent to me to leave existing code.

As I mentioned, It would require a good amount of duplications. But
I'll do what needs to be done.

Regards,

Luiz

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

* Re: [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers
  2022-01-17  4:22   ` Florian Fainelli
@ 2022-01-18  4:38     ` Luiz Angelo Daros de Luca
  0 siblings, 0 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-18  4:38 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: open list:NETWORKING DRIVERS, Linus Walleij, Andrew Lunn,
	Vivien Didelot, Vladimir Oltean, Alvin Šipraga,
	Arınç ÜNAL, Frank Wunderlich

> > +static int realtek_mdio_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
> > +{
> > +     u32 phy_id = priv->phy_id;
> > +     struct mii_bus *bus = priv->bus;
> > +
> > +     mutex_lock(&bus->mdio_lock);
> > +
> > +     bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> > +     *data = bus->read(bus, phy_id, REALTEK_MDIO_DATA_READ_REG);
>
> Do you have no way to return an error for instance, if you read from a
> non-existent PHY device on the MDIO bus, -EIO would be expected for
> instance. If the data returned is 0xffff that ought to be enough.

I'll check for error (non zero for write, negative for read) and
return that value

> > +
> > +     mutex_unlock(&bus->mdio_lock);
> > +
> > +     return 0;
> > +}
> > +
> > +static int realtek_mdio_write_reg(struct realtek_priv *priv, u32 addr, u32 data)
> > +{
> > +     u32 phy_id = priv->phy_id;
> > +     struct mii_bus *bus = priv->bus;
> > +
> > +     mutex_lock(&bus->mdio_lock);
> > +
> > +     bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr);
>
> This repeats between read and writes, might be worth a helper function.

Without the REALTEK_MDIO_START_OP Alvin asked, it is not worth it anymore.

>
> > +     bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_DATA_WRITE_REG, data);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP);
> > +     bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP);
> > +
> > +     mutex_unlock(&bus->mdio_lock);
> > +
> > +     return 0;
> > +}
> > +
> > +/* Regmap accessors */
> > +
> > +static int realtek_mdio_write(void *ctx, u32 reg, u32 val)
> > +{
> > +     struct realtek_priv *priv = ctx;
> > +
> > +     return realtek_mdio_write_reg(priv, reg, val);
> > +}
> > +
> > +static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
> > +{
> > +     struct realtek_priv *priv = ctx;
> > +
> > +     return realtek_mdio_read_reg(priv, reg, val);
> > +}
>
> Do you see a value for this function as oppposed to inlining the bodies
> of realtek_mdio_read_reg and realtek_mdio_write_reg directly into these
> two functions?
>

I merged them. I also changed the write_reg_noack signature to match
regmap->write_reg, so I can use it without a wrapper.

> > +
> > +static const struct regmap_config realtek_mdio_regmap_config = {
> > +     .reg_bits = 10, /* A4..A0 R4..R0 */
> > +     .val_bits = 16,
> > +     .reg_stride = 1,
> > +     /* PHY regs are at 0x8000 */
> > +     .max_register = 0xffff,
> > +     .reg_format_endian = REGMAP_ENDIAN_BIG,
> > +     .reg_read = realtek_mdio_read,
> > +     .reg_write = realtek_mdio_write,
> > +     .cache_type = REGCACHE_NONE,
> > +};
> > +
> > +static int realtek_mdio_probe(struct mdio_device *mdiodev)
> > +{
> > +     struct realtek_priv *priv;
> > +     struct device *dev = &mdiodev->dev;
> > +     const struct realtek_variant *var;
> > +     int ret;
> > +     struct device_node *np;
> > +
> > +     var = of_device_get_match_data(dev);
>
> Don't you have to check that var is non-NULL just in case?

I'll add that check but it is not likely to happen.

>
> > +     priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
> > +     if (!priv)
> > +             return -ENOMEM;
> > +
> > +     priv->map = devm_regmap_init(dev, NULL, priv, &realtek_mdio_regmap_config);
> > +     if (IS_ERR(priv->map)) {
> > +             ret = PTR_ERR(priv->map);
> > +             dev_err(dev, "regmap init failed: %d\n", ret);
> > +             return ret;
> > +     }
> > +
> > +     priv->phy_id = mdiodev->addr;
>
> Please use a more descriptive variable name such as mdio_addr or
> something like that. I know that phy_id is typically used but it could
> also mean a 32-bit PHY unique identifier, which a MDIO device does not
> have typically.

Renamed to mdio_addr. As you said, I just used what is typically used
but you know best.

>
> Looks fine otherwise.

Thanks, Florian.

Luiz

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

* Re: Re: Re: Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-13 15:56             ` Aw: " Frank Wunderlich
@ 2022-01-18  4:58               ` Luiz Angelo Daros de Luca
  2022-01-18 10:13                 ` Alvin Šipraga
                                   ` (2 more replies)
  0 siblings, 3 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-18  4:58 UTC (permalink / raw)
  To: Frank Wunderlich
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

> the problem is checksum offloading on the gmac (soc-side)

I suggested it might be checksum problem because I'm also affected. In
my case, I have an mt7620a SoC connected to the rtl8367s switch. The
OS offloads checksum to HW but the mt7620a cannot calculate the
checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
move the CPU tag to test if the mt7620a will then digest the frame
correctly.

Regards,

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-18  4:58               ` Luiz Angelo Daros de Luca
@ 2022-01-18 10:13                 ` Alvin Šipraga
  2022-01-18 13:20                 ` Re: Re: " Andrew Lunn
  2022-01-30  1:54                 ` Re: Re: " Luiz Angelo Daros de Luca
  2 siblings, 0 replies; 88+ messages in thread
From: Alvin Šipraga @ 2022-01-18 10:13 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Frank Wunderlich, netdev, linus.walleij, andrew, vivien.didelot,
	f.fainelli, olteanv, arinc.unal

Luiz Angelo Daros de Luca <luizluca@gmail.com> writes:

>> the problem is checksum offloading on the gmac (soc-side)
>
> I suggested it might be checksum problem because I'm also affected. In
> my case, I have an mt7620a SoC connected to the rtl8367s switch. The
> OS offloads checksum to HW but the mt7620a cannot calculate the
> checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
> move the CPU tag to test if the mt7620a will then digest the frame
> correctly.

You have two choices:

    enum rtl8365mb_cpu_position {
            RTL8365MB_CPU_POS_AFTER_SA = 0,
            RTL8365MB_CPU_POS_BEFORE_CRC = 1,
    };

I hardcoded it to AFTER_SA but if you find that this solves the problem
for some MACs then it might be worth adding a device tree property for
this to make it configurable. Of course remember to keep it
backward-compatible, and add a note to future travellers in the bindings
that this might solve checksum errors :-)

Kind regards,
Alvin

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

* Re: [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops
  2022-01-18  2:55     ` Luiz Angelo Daros de Luca
@ 2022-01-18 13:16       ` Andrew Lunn
  2022-01-21 22:13         ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 88+ messages in thread
From: Andrew Lunn @ 2022-01-18 13:16 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Florian Fainelli, open list:NETWORKING DRIVERS, Linus Walleij,
	Vivien Didelot, Vladimir Oltean, Alvin Šipraga,
	Arınç ÜNAL, Frank Wunderlich

> Thanks, Florian. You should be correct. It might call
> mdiobus_unregister() and mdiobus_free() twice, once inside the dsa
> code and another one by the devm (if I understood how devm functions
> work).
> 
> The issue is that the dsa switch is assuming that if slave_mii is
> allocated and ds->ops->phy_read is defined, it has allocated the
> slave_mii by itself and it should clean up the slave_mii during
> teardown.

Correct. Either the DSA core takes care of the mdiobus and uses the
phy_read and phy_write ops, or the driver internally registers its own
mdiobus, and phy_read and phy_write ops are not implemented. The core
is not designed to mix those together.

> if ds->ops->phy_read value should not tell if ds->slave_mii_bus should
> be cleaned by the DSA switch.
> 
> I would selfishly hope the correct one was the second option because
> it would make my code much cleaner. If not, that's a complex issue to
> solve without lots of duplications: realtek-smi drivers should not
> have ds->ops->phy_read defined while realtek-mdio requires it. I'll
> need to duplicate dsa_switch_ops for each subdriver only to unset
> phy_read and also duplicate realtek_variant for each interface only to
> reference that different dsa_switch_ops.

One option would be to provide a dummy mdiobus driver for
realtek-mdio, which simply passes the access through to the existing
MDIO bus.

     Andrew

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

* Re: Re: Re: Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-18  4:58               ` Luiz Angelo Daros de Luca
  2022-01-18 10:13                 ` Alvin Šipraga
@ 2022-01-18 13:20                 ` Andrew Lunn
  2022-01-20 15:12                   ` Vladimir Oltean
  2022-01-30  1:54                 ` Re: Re: " Luiz Angelo Daros de Luca
  2 siblings, 1 reply; 88+ messages in thread
From: Andrew Lunn @ 2022-01-18 13:20 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

On Tue, Jan 18, 2022 at 01:58:39AM -0300, Luiz Angelo Daros de Luca wrote:
> > the problem is checksum offloading on the gmac (soc-side)
> 
> I suggested it might be checksum problem because I'm also affected. In
> my case, I have an mt7620a SoC connected to the rtl8367s switch. The
> OS offloads checksum to HW but the mt7620a cannot calculate the
> checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
> move the CPU tag to test if the mt7620a will then digest the frame
> correctly.

Some MAC hardware you can tell it where the ether type value is in the
frame. This is often used to skip over the VLAN header, but it can
also be used to skip DSA headers. Check the datasheet for the hardware
and see if there is anything like that.

    Andrew

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

* Re: [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S
  2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
                   ` (10 preceding siblings ...)
  2022-01-05  3:15 ` [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint Luiz Angelo Daros de Luca
@ 2022-01-20 14:36 ` Vladimir Oltean
  2022-01-20 17:46   ` Luiz Angelo Daros de Luca
  11 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-20 14:36 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli, alsi,
	arinc.unal, frank-w

On Wed, Jan 05, 2022 at 12:15:04AM -0300, Luiz Angelo Daros de Luca wrote:
> The old realtek-smi driver was linking subdrivers into a single
> realtek-smi.ko After this series, each subdriver will be an independent
> module required by either realtek-smi (platform driver) or the new
> realtek-mdio (mdio driver). Both interface drivers (SMI or MDIO) are
> independent, and they might even work side-by-side, although it will be
> difficult to find such device. The subdriver can be individually
> selected but only at buildtime, saving some storage space for custom
> embedded systems.
> 
> Existing realtek-smi devices continue to work untouched during the
> tests. The realtek-smi was moved into a realtek subdirectory, but it
> normally does not break things.
> 
> I couldn't identify a fixed relation between port numbers (0..9) and
> external interfaces (0..2), and I'm not sure if it is fixed for each
> chip version or a device configuration. Until there is more info about
> it, there is a new port property "realtek,ext-int" that can inform the
> external interface.

Generally it isn't a good idea to put in the device tree things that you
don't understand. The reason being that you'd have to support those
device tree bindings even when you do understand those things. A device
tree blob has a separate lifetime compared to the kernel image, so a new
kernel image would have to support the device trees in circulation which
have this realtek,ext-int property.

Can you use a fixed relationship between the port number and the
external interface in the driver, until it is proven that this info
cannot be known statically or by reading some device configuration?

> The rtl8365mb might now handle multiple CPU ports and extint ports not
> used as CPU ports. RTL8367S has an SGMII external interface, but my test
> device (TP-Link Archer C5v4) uses only the second RGMII interface. We
> need a test device with more external ports to test these features.
> The driver still cannot handle SGMII ports.
> 
> The rtl8365mb was tested with a MDIO-connected RTL8367S (TP-Link Acher
> C5v4) and a SMI-connected RTL8365MB-VC switch (Asus RT-AC88U)
> 
> The rtl8366rb subdriver was not tested with this patch series, but it
> was only slightly touched. It would be nice to test it, especially in an
> MDIO-connected switch.
> 
> Best,
> 
> Luiz
> 
> Changelog:
> 
> v1-v2)
> - formatting fixes
> - dropped the rtl8365mb->rtl8367c rename
> - other suggestions
> 	
> v2-v3)
> * realtek-mdio.c:
>   - cleanup realtek-mdio.c (BUG_ON, comments and includes)   
>   - check devm_regmap_init return code
>   - removed realtek,rtl8366s string from realtek-mdio
> * realtek-smi.c:
>   - removed void* type cast
> * rtl8365mb.c:
>   - using macros to identify EXT interfaces
>   - rename some extra extport->extint cases
>   - allow extint as non cpu (not tested)
>   - allow multple cpu ports (not tested)
>   - dropped cpu info from struct rtl8365mb
> * dropped dt-bindings changes (dealing outside this series)
> * formatting issues fixed
> 
> v3-v4)
> * fix cover message numbering 0/13 -> 0/11
> * use static for realtek_mdio_read_reg
>   - Reported-by: kernel test robot <lkp@intel.com>
> * use dsa_switch_for_each_cpu_port
> * mention realtek_smi_{variant,ops} to realtek_{variant,ops}
>   in commit message
> 
> 

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

* Re: [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv
  2022-01-05  3:15 ` [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv Luiz Angelo Daros de Luca
                     ` (2 preceding siblings ...)
  2022-01-16  0:04   ` Linus Walleij
@ 2022-01-20 14:37   ` Vladimir Oltean
  3 siblings, 0 replies; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-20 14:37 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, vivien.didelot, f.fainelli, alsi,
	arinc.unal, frank-w

On Wed, Jan 05, 2022 at 12:15:06AM -0300, Luiz Angelo Daros de Luca wrote:
> In preparation to adding other interfaces, the private data structure
> was renamed to priv. Also, realtek_smi_variant and realtek_smi_ops
> were renamed to realtek_variant and realtek_ops as those structs are
> not SMI specific.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
> ---

Reviewed-by: Vladimir Oltean <olteanv@gmail.com>

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-18 13:20                 ` Re: Re: " Andrew Lunn
@ 2022-01-20 15:12                   ` Vladimir Oltean
  2022-01-20 23:35                     ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-20 15:12 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Luiz Angelo Daros de Luca, Frank Wunderlich, Alvin Šipraga,
	netdev, linus.walleij, vivien.didelot, f.fainelli, arinc.unal

On Tue, Jan 18, 2022 at 02:20:57PM +0100, Andrew Lunn wrote:
> On Tue, Jan 18, 2022 at 01:58:39AM -0300, Luiz Angelo Daros de Luca wrote:
> > > the problem is checksum offloading on the gmac (soc-side)
> > 
> > I suggested it might be checksum problem because I'm also affected. In
> > my case, I have an mt7620a SoC connected to the rtl8367s switch. The
> > OS offloads checksum to HW but the mt7620a cannot calculate the
> > checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
> > move the CPU tag to test if the mt7620a will then digest the frame
> > correctly.
> 
> Some MAC hardware you can tell it where the ether type value is in the
> frame. This is often used to skip over the VLAN header, but it can
> also be used to skip DSA headers. Check the datasheet for the hardware
> and see if there is anything like that.
> 
>     Andrew

And what is the problem if the hardware cannot calculate the checksum
with an unknown EtherType? Is it the DSA master that drops the packets
in hardware? What is the reported error counter?

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

* Re: [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S
  2022-01-20 14:36 ` [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Vladimir Oltean
@ 2022-01-20 17:46   ` Luiz Angelo Daros de Luca
  0 siblings, 0 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-20 17:46 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: open list:NETWORKING DRIVERS, Linus Walleij, Andrew Lunn,
	Vivien Didelot, Florian Fainelli, Alvin Šipraga,
	Arınç ÜNAL, Frank Wunderlich

> On Wed, Jan 05, 2022 at 12:15:04AM -0300, Luiz Angelo Daros de Luca wrote:
> > The old realtek-smi driver was linking subdrivers into a single
> > realtek-smi.ko After this series, each subdriver will be an independent
> > module required by either realtek-smi (platform driver) or the new
> > realtek-mdio (mdio driver). Both interface drivers (SMI or MDIO) are
> > independent, and they might even work side-by-side, although it will be
> > difficult to find such device. The subdriver can be individually
> > selected but only at buildtime, saving some storage space for custom
> > embedded systems.
> >
> > Existing realtek-smi devices continue to work untouched during the
> > tests. The realtek-smi was moved into a realtek subdirectory, but it
> > normally does not break things.
> >
> > I couldn't identify a fixed relation between port numbers (0..9) and
> > external interfaces (0..2), and I'm not sure if it is fixed for each
> > chip version or a device configuration. Until there is more info about
> > it, there is a new port property "realtek,ext-int" that can inform the
> > external interface.
>
> Generally it isn't a good idea to put in the device tree things that you
> don't understand. The reason being that you'd have to support those
> device tree bindings even when you do understand those things. A device
> tree blob has a separate lifetime compared to the kernel image, so a new
> kernel image would have to support the device trees in circulation which
> have this realtek,ext-int property.
>
> Can you use a fixed relationship between the port number and the
> external interface in the driver, until it is proven that this info
> cannot be known statically or by reading some device configuration?

Thanks, Vladimir. OK. I'll make it automatically defined. I dug again
into the realtek driver and I might be able to remove that property.
There are just a couple of situations that I might select based on
chip_id/version.

BTW, Should I split the series in two, submitting the already consensus patch?

Luiz

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-20 15:12                   ` Vladimir Oltean
@ 2022-01-20 23:35                     ` Luiz Angelo Daros de Luca
  2022-01-21  2:06                       ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-20 23:35 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

> And what is the problem if the hardware cannot calculate the checksum
> with an unknown EtherType? Is it the DSA master that drops the packets
> in hardware? What is the reported error counter?

No, the issue is with outgoing packets and nothing is dropped inside
the DSA device.

If the OS is configured to offload (I'm using OpenWrt.), it will send
a packet with the wrong checksum expecting that the HW will fix that.
After DSA is brought up, the OS is still expecting the HW to calculate
the checksums. However, with the EtherType DSA tag from a , it cannot
understand it anymore, leaving the checksum as is. The DSA switch
(Realtek) passes the packet to the network and the other end receives
a broken packet. Maybe if the DSA knew that the CPU Ethernet HW cannot
handle that DSA tag, it could disable checksums by default. But it is
difficult to foresee how each offload HW will digest each type of CPU
tag.

Is the kernel enabling checksum by default when the driver reports it
is supported? If so, it would be nice to somehow disable offloading
with some kind of device-tree dsa cpu port property.

Regards,

Luiz

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-20 23:35                     ` Luiz Angelo Daros de Luca
@ 2022-01-21  2:06                       ` Vladimir Oltean
  2022-01-21  3:13                         ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-21  2:06 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

On Thu, Jan 20, 2022 at 08:35:54PM -0300, Luiz Angelo Daros de Luca wrote:
> > And what is the problem if the hardware cannot calculate the checksum
> > with an unknown EtherType? Is it the DSA master that drops the packets
> > in hardware? What is the reported error counter?
> 
> No, the issue is with outgoing packets and nothing is dropped inside
> the DSA device.

Ah, sorry, I missed that.

> If the OS is configured to offload (I'm using OpenWrt.), it will send
> a packet with the wrong checksum expecting that the HW will fix that.
> After DSA is brought up, the OS is still expecting the HW to calculate
> the checksums. However, with the EtherType DSA tag from a , it cannot
> understand it anymore, leaving the checksum as is. The DSA switch
> (Realtek) passes the packet to the network and the other end receives
> a broken packet. Maybe if the DSA knew that the CPU Ethernet HW cannot
> handle that DSA tag, it could disable checksums by default. But it is
> difficult to foresee how each offload HW will digest each type of CPU
> tag.
> 
> Is the kernel enabling checksum by default when the driver reports it
> is supported? If so, it would be nice to somehow disable offloading
> with some kind of device-tree dsa cpu port property.

:) device tree properties are not the fix for everything!

I think I know what the problem is. But I'd need to know what the driver
for the DSA master is, to confirm. To be precise, what I'd like to check
is the value of master->vlan_features.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21  2:06                       ` Vladimir Oltean
@ 2022-01-21  3:13                         ` Luiz Angelo Daros de Luca
  2022-01-21  3:22                           ` Florian Fainelli
  2022-01-21 18:50                           ` Vladimir Oltean
  0 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-21  3:13 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

> :) device tree properties are not the fix for everything!

I'm still getting used to it ;-)

In this thread, Alvin suggested adding a new property to define which
port will be used as trap_port instead of using the last CPU port.
Should I try something different?

        switch1 {
               compatible = "realtek,rtl8367s";
               reg = <29>;

               realtek,trap-port = <&port7>;

               ports {
                        ....
                        port7: port@7 {
                            ...
                       };
        };

Should I do something differently?

> I think I know what the problem is. But I'd need to know what the driver
> for the DSA master is, to confirm. To be precise, what I'd like to check
> is the value of master->vlan_features.

Here it is 0x1099513266227 (I hope). Oh, this DSA driver still does
not implement vlan nor bridge offload. Maybe it would matter.

Regards,

Luiz

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21  3:13                         ` Luiz Angelo Daros de Luca
@ 2022-01-21  3:22                           ` Florian Fainelli
  2022-01-21  3:42                             ` Luiz Angelo Daros de Luca
  2022-01-21 18:50                           ` Vladimir Oltean
  1 sibling, 1 reply; 88+ messages in thread
From: Florian Fainelli @ 2022-01-21  3:22 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, Vladimir Oltean
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, arinc.unal



On 1/20/2022 7:13 PM, Luiz Angelo Daros de Luca wrote:
>> :) device tree properties are not the fix for everything!
> 
> I'm still getting used to it ;-)
> 
> In this thread, Alvin suggested adding a new property to define which
> port will be used as trap_port instead of using the last CPU port.
> Should I try something different?
> 
>          switch1 {
>                 compatible = "realtek,rtl8367s";
>                 reg = <29>;
> 
>                 realtek,trap-port = <&port7>;
> 
>                 ports {
>                          ....
>                          port7: port@7 {
>                              ...
>                         };
>          };
> 
> Should I do something differently?
> 
>> I think I know what the problem is. But I'd need to know what the driver
>> for the DSA master is, to confirm. To be precise, what I'd like to check
>> is the value of master->vlan_features.
> 
> Here it is 0x1099513266227 (I hope). Oh, this DSA driver still does
> not implement vlan nor bridge offload. Maybe it would matter.

Are we talking about an in tree driver? If so which is it?
-- 
Florian

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21  3:22                           ` Florian Fainelli
@ 2022-01-21  3:42                             ` Luiz Angelo Daros de Luca
  2022-01-21  3:50                               ` Florian Fainelli
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-21  3:42 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Vladimir Oltean, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal

> Are we talking about an in tree driver? If so which is it?

Yes, the one the patch touches: rtl8365mb.

My device uses a mt7620a SoC and traffic passes through its mt7530
switch with vlan disabled before reaching the realtek switch. It still
loads a swconfig driver but I think it might work without one.
I just didn't stop to try it yet.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21  3:42                             ` Luiz Angelo Daros de Luca
@ 2022-01-21  3:50                               ` Florian Fainelli
  2022-01-21  4:37                                 ` Luiz Angelo Daros de Luca
  2022-01-21  9:07                                 ` Arınç ÜNAL
  0 siblings, 2 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-21  3:50 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Vladimir Oltean, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal



On 1/20/2022 7:42 PM, Luiz Angelo Daros de Luca wrote:
>> Are we talking about an in tree driver? If so which is it?
> 
> Yes, the one the patch touches: rtl8365mb.

I meant the DSA master network device, but you answered that, it uses a 
mt7260a SoC, but there is no Ethernet driver upstream for it yet?

git grep ralink,mt7620-gsw *
Documentation/devicetree/bindings/net/mediatek,mt7620-gsw.txt: 
compatible = "ralink,mt7620-gsw";

> 
> My device uses a mt7620a SoC and traffic passes through its mt7530
> switch with vlan disabled before reaching the realtek switch. It still
> loads a swconfig driver but I think it might work without one.

Ah so you have a cascade of switches here, that could confuse your 
Ethernet MAC. Do you have a knob to adjust where to calculate the 
checksum from, say a L2 or L3 offset for instance?
-- 
Florian

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21  3:50                               ` Florian Fainelli
@ 2022-01-21  4:37                                 ` Luiz Angelo Daros de Luca
  2022-01-21  9:07                                 ` Arınç ÜNAL
  1 sibling, 0 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-21  4:37 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Vladimir Oltean, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal

> >> Are we talking about an in tree driver? If so which is it?
> >
> > Yes, the one the patch touches: rtl8365mb.
>
> I meant the DSA master network device, but you answered that, it uses a
> mt7260a SoC, but there is no Ethernet driver upstream for it yet?
>
> git grep ralink,mt7620-gsw *
> Documentation/devicetree/bindings/net/mediatek,mt7620-gsw.txt:
> compatible = "ralink,mt7620-gsw";
>
> >
> > My device uses a mt7620a SoC and traffic passes through its mt7530
> > switch with vlan disabled before reaching the realtek switch. It still
> > loads a swconfig driver but I think it might work without one.
>
> Ah so you have a cascade of switches here, that could confuse your
> Ethernet MAC. Do you have a knob to adjust where to calculate the
> checksum from, say a L2 or L3 offset for instance?

Not that I could find in any docs. I just found registers to set it on
and off. However, Realtek supports two locations for the CPU tag. I'll
try the RTL8365MB_CPU_POS_BEFORE_CRC and hope the checksum will work
as expected. But I might leave that test for a moment after this
series is solved.

> --
> Florian

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21  3:50                               ` Florian Fainelli
  2022-01-21  4:37                                 ` Luiz Angelo Daros de Luca
@ 2022-01-21  9:07                                 ` Arınç ÜNAL
  1 sibling, 0 replies; 88+ messages in thread
From: Arınç ÜNAL @ 2022-01-21  9:07 UTC (permalink / raw)
  To: Florian Fainelli, Luiz Angelo Daros de Luca
  Cc: Vladimir Oltean, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	erkin.bozoglu, Sergio Paracuellos, gregkh

On 21/01/2022 06:50, Florian Fainelli wrote:
> 
> 
> On 1/20/2022 7:42 PM, Luiz Angelo Daros de Luca wrote:
>>> Are we talking about an in tree driver? If so which is it?
>>
>> Yes, the one the patch touches: rtl8365mb.
> 
> I meant the DSA master network device, but you answered that, it uses a 
> mt7260a SoC, but there is no Ethernet driver upstream for it yet?
> 
> git grep ralink,mt7620-gsw *
> Documentation/devicetree/bindings/net/mediatek,mt7620-gsw.txt: 
> compatible = "ralink,mt7620-gsw";
> 
>>
>> My device uses a mt7620a SoC and traffic passes through its mt7530
>> switch with vlan disabled before reaching the realtek switch. It still
>> loads a swconfig driver but I think it might work without one.
> 
> Ah so you have a cascade of switches here, that could confuse your 
> Ethernet MAC. Do you have a knob to adjust where to calculate the 
> checksum from, say a L2 or L3 offset for instance?

The company I currently work for has got their own mt7621a board with an 
external rtl8367s switch.

According to Documentation/devicetree/bindings/net/dsa/mt7530.txt I can 
either connect the rtl switch directly to the second GMAC of the mt7621 
SoC or to MT7530's GMAC5 to create a cascade.

I've been running gregkh/staging staging-next branch but I can't seem to 
have traffic flow on the RGMII2 bus which is shared by the 2nd GMAC of 
the SoC, MT7530's GMAC5 and an external phy (rtl switch in this case).

None of the documented configurations work:
PHY0/4 <-> 2nd GMAC
External phy <-> 2nd GMAC
External phy <-> MT7530's GMAC5

Arınç

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21  3:13                         ` Luiz Angelo Daros de Luca
  2022-01-21  3:22                           ` Florian Fainelli
@ 2022-01-21 18:50                           ` Vladimir Oltean
  2022-01-21 21:51                             ` Luiz Angelo Daros de Luca
  1 sibling, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-21 18:50 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

On Fri, Jan 21, 2022 at 12:13:58AM -0300, Luiz Angelo Daros de Luca wrote:
> > :) device tree properties are not the fix for everything!
> 
> I'm still getting used to it ;-)
> 
> In this thread, Alvin suggested adding a new property to define which
> port will be used as trap_port instead of using the last CPU port.
> Should I try something different?
> 
>         switch1 {
>                compatible = "realtek,rtl8367s";
>                reg = <29>;
> 
>                realtek,trap-port = <&port7>;
> 
>                ports {
>                         ....
>                         port7: port@7 {
>                             ...
>                        };
>         };
> 
> Should I do something differently?

To clarify, I don't know what a trap_port is. I just saw this
description in rtl8365mb.c:

 * @trap_port: forward trapped frames to this port

but I still don't know to which packets does this configuration apply
(where are the packet traps installed, and for what kind of packets).

Speculating here, but it appears quite arbitrary, and I'd guess also
broken, to make the trap_port the last CPU port. Is this also part of
the things which you didn't really test? See commit 8d5f7954b7c8 ("net:
dsa: felix: break at first CPU port during init and teardown") for a
similar issue with this. When there are multiple 'ethernet = <&phandle>'
properties in the device tree, DSA makes the owners of all those
phandles a DSA master, and all those switch ports as CPU ports. But out
of all those CPU ports, only the first one is an active CPU port. The
others have no dp->cpu_dp pointing to them.
See dsa_tree_setup_default_cpu() -> dsa_tree_find_first_cpu().
Even when DSA gets full-blown support for multiple CPU ports, I think
it's safe to say that this default will remain the way it is: a single
CPU port will be active to begin with: the first one. Given that fact
(and depending on what you need to do with the trap_port info exactly),
it might be broken to set as the trap port a CPU port that isn't used.
Stuff like dsa_port_host_fdb_add()/dsa_port_host_fdb_del() will be
broken, because they rely on the dp->cpu_dp association, and
dp->cpu_dp->index will be != trap_port.

> > I think I know what the problem is. But I'd need to know what the driver
> > for the DSA master is, to confirm. To be precise, what I'd like to check
> > is the value of master->vlan_features.
> 
> Here it is 0x1099513266227 (I hope).

That's quite an extraordinary set of vlan_features. In that number, I
notice BIT(2) is set, which corresponds to __UNUSED_NETIF_F_1. So it
probably isn't correctly printed.

This is what I would have liked to see:

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 22241afcac81..b41f1b414c69 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1909,6 +1909,7 @@ void dsa_slave_setup_tagger(struct net_device *slave)
 	p->xmit = cpu_dp->tag_ops->xmit;
 
 	slave->features = master->vlan_features | NETIF_F_HW_TC;
+	netdev_err(slave, "master %s vlan_features 0x%llx\n", master->name, master->vlan_features);
 	slave->hw_features |= NETIF_F_HW_TC;
 	slave->features |= NETIF_F_LLTX;
 	if (slave->needed_tailroom)

And I don't think you fully answered Florian's questions either, really.
Can we see the a link to the code of the Ethernet controller whose role
is to be a host port (DSA master) for the rtl8365mb switch? If that DSA
master is a DSA switch itself, could you please unroll the chain all the
way with more links to drivers? No matter whether upstream or downstream,
just what you use.

I hate to guess, but since both you and Arınç have mentioned the
mt7620a/mt7621 SoCs, I'd guess that the top-most DSA driver in both
cases is "mediatek,eth-mac" (drivers/net/ethernet/mediatek/mtk_eth_soc.c).
If so, this would confirm my suspicions, since it sets its vlan_features
to include NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM. Please confirm that
master->vlan_features contains these 2 bits.

> Oh, this DSA driver still does not implement vlan nor bridge offload.
> Maybe it would matter.

It doesn't matter. The vlan_features is a confusing name for what it
really does here. I'll explain in a bit once you clarify the other
things I asked for.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21 18:50                           ` Vladimir Oltean
@ 2022-01-21 21:51                             ` Luiz Angelo Daros de Luca
  2022-01-21 22:49                               ` Vladimir Oltean
  2022-01-22 15:51                               ` Andrew Lunn
  0 siblings, 2 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-21 21:51 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

> > I'm still getting used to it ;-)
> >
> > In this thread, Alvin suggested adding a new property to define which
> > port will be used as trap_port instead of using the last CPU port.
> > Should I try something different?
> >
> >         switch1 {
> >                compatible = "realtek,rtl8367s";
> >                reg = <29>;
> >
> >                realtek,trap-port = <&port7>;
> >
> >                ports {
> >                         ....
> >                         port7: port@7 {
> >                             ...
> >                        };
> >         };
> >
> > Should I do something differently?
>
> To clarify, I don't know what a trap_port is. I just saw this
> description in rtl8365mb.c:
>
>  * @trap_port: forward trapped frames to this port
>
> but I still don't know to which packets does this configuration apply
> (where are the packet traps installed, and for what kind of packets).

Thank you, Vladimir.

trap_port seems to be where the switch will send any packet captured
from LAN ports. There are a couple of situations it will be used like:
1) untagged or unmatched vlan packets (if configured to do so)
2) some multicasting packets (Reserved Multicast Address), for some
cases like capturing STP or LACP
3) IGMP and 802.1X EAPOL packets
4) Switch ACL rules that could match a packet and send it to the trap port.

In my early tests, I only saw some IGMP packets trapped to CPU. I also
do not know how important they are.

> Speculating here, but it appears quite arbitrary, and I'd guess also
> broken, to make the trap_port the last CPU port. Is this also part of
> the things which you didn't really test? See commit 8d5f7954b7c8 ("net:
> dsa: felix: break at first CPU port during init and teardown") for a
> similar issue with this. When there are multiple 'ethernet = <&phandle>'
> properties in the device tree, DSA makes the owners of all those
> phandles a DSA master, and all those switch ports as CPU ports. But out
> of all those CPU ports, only the first one is an active CPU port. The
> others have no dp->cpu_dp pointing to them.
> See dsa_tree_setup_default_cpu() -> dsa_tree_find_first_cpu().
> Even when DSA gets full-blown support for multiple CPU ports, I think
> it's safe to say that this default will remain the way it is: a single
> CPU port will be active to begin with: the first one. Given that fact
> (and depending on what you need to do with the trap_port info exactly),
> it might be broken to set as the trap port a CPU port that isn't used.
> Stuff like dsa_port_host_fdb_add()/dsa_port_host_fdb_del() will be
> broken, because they rely on the dp->cpu_dp association, and
> dp->cpu_dp->index will be != trap_port.

Although it would be interesting to have some sniffed traffic sent to
a second CPU port, I agree it might break more things than
it will help. Until multiple CPU ports can be used as first-class
citizens, I'll simply force it to be the first CPU port.

The multiple CPU port is not a target but a byproduct of removing the
assumption that "CPU port" is equal to "external interface port".
The real change is to allow an external interface to be configured,
even if it is not the CPU port, as it could be used to stack a second
switch.
I'll leave the multiple CPU as a note in the commit message and not
the subject. It was wrong to emphasize that.

> > > I think I know what the problem is. But I'd need to know what the driver
> > > for the DSA master is, to confirm. To be precise, what I'd like to check
> > > is the value of master->vlan_features.
> >
> > Here it is 0x1099513266227 (I hope).
>
> That's quite an extraordinary set of vlan_features. In that number, I
> notice BIT(2) is set, which corresponds to __UNUSED_NETIF_F_1. So it
> probably isn't correctly printed.

Oh my... I printed it as an unsigned decimal. Sorry.

>
> This is what I would have liked to see:
>
> diff --git a/net/dsa/slave.c b/net/dsa/slave.c
> index 22241afcac81..b41f1b414c69 100644
> --- a/net/dsa/slave.c
> +++ b/net/dsa/slave.c
> @@ -1909,6 +1909,7 @@ void dsa_slave_setup_tagger(struct net_device *slave)
>         p->xmit = cpu_dp->tag_ops->xmit;
>
>         slave->features = master->vlan_features | NETIF_F_HW_TC;
> +       netdev_err(slave, "master %s vlan_features 0x%llx\n", master->name, master->vlan_features);
>         slave->hw_features |= NETIF_F_HW_TC;
>         slave->features |= NETIF_F_LLTX;
>         if (slave->needed_tailroom)

0x10000190033. If I got it right:

NETIF_F_SG_BIT
NETIF_F_IP_CSUM_BIT
NETIF_F_IPV6_CSUM_BIT
NETIF_F_HIGHDMA_BIT
NETIF_F_GSO_SHIFT
NETIF_F_TSO_MANGLEID_BIT
NETIF_F_TSO6_BIT
NETIF_F_RXCSUM_BIT

> And I don't think you fully answered Florian's questions either, really.
> Can we see the a link to the code of the Ethernet controller whose role
> is to be a host port (DSA master) for the rtl8365mb switch?

The code is from the OpenWrt tree.
https://github.com/openwrt/openwrt/tree/master/target/linux/ramips/files/drivers/net/ethernet/ralink

I only patched it to accept Jumbo Frames (it was dropping incoming
packets with MTU 1508)
https://patchwork.ozlabs.org/project/openwrt/list/?series=279773

> If that DSA
> master is a DSA switch itself, could you please unroll the chain all the
> way with more links to drivers? No matter whether upstream or downstream,
> just what you use.

OpenWrt (soc mt7620a) eth0 (mtk_eth_soc) connected to internal SoC
MT7530 switch port 6 (, mediatek,mt7620-gsw).
MT7530 port 5 connected to RTL8367S port 7 (RGMII).

The internal SoC switch is behaving as an unmanaged switch, with no
vlans. It would be just extra overhead to have it working as a DSA
switch, specially
as those two switches tags are not compatible. I still have the
swconfig driver installed but I was only using it for some debugging
(checking metrics). I think that the state the bootloader leaves that
switchis enough to make it forward packets to the Realtek switch. In
device-tree conf, I'm directly using that eth0 as the CPU port.

> I hate to guess, but since both you and Arınç have mentioned the
> mt7620a/mt7621 SoCs,

Sorry for the incomplete answer. If it helps, this is my device
https://github.com/luizluca/openwrt/blob/tplink_c5v4_dsa/target/linux/ramips/dts/mt7620a_tplink_archer-c5-v4.dts

I try to keep my remote branch updated, although it has some dirty changes:
https://github.com/luizluca/openwrt/tree/tplink_c5v4_dsa

> I'd guess that the top-most DSA driver in both cases is "mediatek,eth-mac" (drivers/net/ethernet/mediatek/mtk_eth_soc.c).

Not in my case. The driver I use also supports mt7621 but the upstream
driver skipped the mt7620a support.

> If so, this would confirm my suspicions, since it sets its vlan_features
> to include NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM. Please confirm that
> master->vlan_features contains these 2 bits.

Yes.

> > Oh, this DSA driver still does not implement vlan nor bridge offload.
> > Maybe it would matter.
>
> It doesn't matter. The vlan_features is a confusing name for what it
> really does here. I'll explain in a bit once you clarify the other
> things I asked for.

That is good news as we can deal with it independently. I wish to
focus on that afterwards.

Regards,

Luiz

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

* Re: [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops
  2022-01-18 13:16       ` Andrew Lunn
@ 2022-01-21 22:13         ` Luiz Angelo Daros de Luca
  2022-01-21 23:48           ` Andrew Lunn
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-21 22:13 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Florian Fainelli, open list:NETWORKING DRIVERS, Linus Walleij,
	Vivien Didelot, Vladimir Oltean, Alvin Šipraga,
	Arınç ÜNAL, Frank Wunderlich

---
> > Thanks, Florian. You should be correct. It might call
> > mdiobus_unregister() and mdiobus_free() twice, once inside the dsa
> > code and another one by the devm (if I understood how devm functions
> > work).
> >
> > The issue is that the dsa switch is assuming that if slave_mii is
> > allocated and ds->ops->phy_read is defined, it has allocated the
> > slave_mii by itself and it should clean up the slave_mii during
> > teardown.
>
> Correct. Either the DSA core takes care of the mdiobus and uses the
> phy_read and phy_write ops, or the driver internally registers its own
> mdiobus, and phy_read and phy_write ops are not implemented. The core
> is not designed to mix those together.
>
> > if ds->ops->phy_read value should not tell if ds->slave_mii_bus should
> > be cleaned by the DSA switch.
> >
> > I would selfishly hope the correct one was the second option because
> > it would make my code much cleaner. If not, that's a complex issue to
> > solve without lots of duplications: realtek-smi drivers should not
> > have ds->ops->phy_read defined while realtek-mdio requires it. I'll
> > need to duplicate dsa_switch_ops for each subdriver only to unset
> > phy_read and also duplicate realtek_variant for each interface only to
> > reference that different dsa_switch_ops.
>
> One option would be to provide a dummy mdiobus driver for
> realtek-mdio, which simply passes the access through to the existing
> MDIO bus.
>
>      Andrew

Ok, thanks for the clarification, Andrew. In the end, I simply
duplicated ds_ops and wrote a wrap funcion.
Much less painful than I anticipated.

Should I submit a patch to make dsa work like this then?

dsa_switch_setup() {
        ....
        ds->ops->setup()
        ....
        if (ds->ops->phy_read) {
              if (ds->slave_mii_bus)
                    error("ds->ops->phy_read is set, I should be the
one allocating ds->slave_mii_bus!")
              ...allocate and register ds->slave_mii_bus...
        }
}

I think it is better to fail when there is an invalid setup than to
expect the dsa driver to behave correctly.

Regards,

Luiz

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21 21:51                             ` Luiz Angelo Daros de Luca
@ 2022-01-21 22:49                               ` Vladimir Oltean
  2022-01-22 20:12                                 ` Luiz Angelo Daros de Luca
  2022-01-22 15:51                               ` Andrew Lunn
  1 sibling, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-21 22:49 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

On Fri, Jan 21, 2022 at 06:51:14PM -0300, Luiz Angelo Daros de Luca wrote:
> The code is from the OpenWrt tree.
> https://github.com/openwrt/openwrt/tree/master/target/linux/ramips/files/drivers/net/ethernet/ralink
> 
> I only patched it to accept Jumbo Frames (it was dropping incoming
> packets with MTU 1508)
> https://patchwork.ozlabs.org/project/openwrt/list/?series=279773
> 
> > If that DSA
> > master is a DSA switch itself, could you please unroll the chain all the
> > way with more links to drivers? No matter whether upstream or downstream,
> > just what you use.
> 
> OpenWrt (soc mt7620a) eth0 (mtk_eth_soc) connected to internal SoC
> MT7530 switch port 6 (, mediatek,mt7620-gsw).
> MT7530 port 5 connected to RTL8367S port 7 (RGMII).
> 
> The internal SoC switch is behaving as an unmanaged switch, with no
> vlans. It would be just extra overhead to have it working as a DSA
> switch, specially
> as those two switches tags are not compatible. I still have the
> swconfig driver installed but I was only using it for some debugging
> (checking metrics). I think that the state the bootloader leaves that
> switchis enough to make it forward packets to the Realtek switch. In
> device-tree conf, I'm directly using that eth0 as the CPU port.

There could be value in managing the internal switch with DSA too, for
example in a situation like this:

 +-------------------------------------------------+
 |  SoC                                            |
 |                                                 |
 |  +----------------+--------+---------------+    |
 |  |                |        |               |    |
 |  | Internal       |        |               |    |
 |  |  switch        +--------+               |    |
 |  | (dsa,member = <0 0>;)                   |    |
 |  | +-------+ +-------+ +-------+ +-------+ |    |
 |  | |       | |       | |       | |       | |    |
 |  | | sw0p0 | | sw0p1 | | sw0p2 | | sw0p3 | |    |
 |  | |       | |       | |       | |       | |    |
 +--+-+-------+-+-------+-+-------+-+-------+-+----+

 +----+--------+------------------+
 |    |        |                  |
 |    +--------+                  |
 | External switch                |
 | (dsa,member = <1 0>;)          |
 |  +-------+ +-------+ +-------+ |
 |  |       | |       | |       | |
 |  | sw1p0 | | sw1p1 | | sw1p2 | |
 |  |       | |       | |       | |
 +--+-------+-+-------+-+-------+-+

where you'd create a bridge spanning all of sw0p1, sw0p2, sw0p3, sw1p0,
sw1p1, sw1p2. Forwarding between the internal and the external switch is
done in software, and that deals with the "impedance matching" between
the tagging protocols too - first the packet is stripped of the DSA tag
of the ingress switch, then the DSA tag of the egress switch is added.
With a transparent internal switch (no driver), ports sw0p1, sw0p2,
sw0p3 are dead, since if you'd connect them to a PHY, they'd spit out
DSA-tagged packets from the external switch.

> > I hate to guess, but since both you and Arınç have mentioned the
> > mt7620a/mt7621 SoCs,
> 
> Sorry for the incomplete answer. If it helps, this is my device
> https://github.com/luizluca/openwrt/blob/tplink_c5v4_dsa/target/linux/ramips/dts/mt7620a_tplink_archer-c5-v4.dts
> 
> I try to keep my remote branch updated, although it has some dirty changes:
> https://github.com/luizluca/openwrt/tree/tplink_c5v4_dsa
> 
> > I'd guess that the top-most DSA driver in both cases is "mediatek,eth-mac" (drivers/net/ethernet/mediatek/mtk_eth_soc.c).
> 
> Not in my case. The driver I use also supports mt7621 but the upstream
> driver skipped the mt7620a support.
> 
> > If so, this would confirm my suspicions, since it sets its vlan_features
> > to include NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM. Please confirm that
> > master->vlan_features contains these 2 bits.
> 
> Yes.

Ok. See the discussion with Lino Sanfilippo here:
https://lore.kernel.org/netdev/YPAzZXaC%2FEn3s4ly@lunn.ch/
Basically, the moving parts of this mechanism are:

- when the DSA master doesn't understand DSA tags, the transmit
  checksums must be calculated in software.

- this is already supported, we just need to make sure that the DSA
  slave->features does not include any checksum offload bits
  (NETIF_F_HW_CSUM, NETIF_F_IP_CSUM, NETIF_F_IPV6_CSUM), otherwise that
  will be delegated to the device driver. The place that checks that
  condition and calculates the checksum in software is validate_xmit_skb() ->
  skb_csum_hwoffload_help().

- the checksum is evaluated on the skb before the DSA tag is even
  inserted, and is preserved when DSA inserts the header, and is
  therefore still correct by the time the skb reaches the DSA master
  driver. A DSA-unaware master doesn't have to do anything for this
  packet, the IP header checksum will still be correct despite the
  hardware not recognizing the IP header.

- the way DSA populates slave->features is by inheriting master->vlan_features
  (vlan_features means "netdev features which are inheritable by VLAN
  upper interfaces"). This directly makes or breaks what happens in
  validate_xmit_skb() on a DSA slave interface.

- the problem occurs when the DSA master puts checksum offload bits in
  both dev->features and dev->vlan_features. The master thinks this
  means: "I can offload IP checksumming for myself and for VLAN upper
  interfaces (I can recognize the IP header past the VLAN header)."
  Little does it know that DSA assumes this means it can also offload
  checksumming in the presence of switch tags.

So just stop inheriting NETIF_F_HW_CSUM and friends from
master->vlan_features, right?

Well, you can't help but wonder a bit how come it's 2022 and we could
still have an obvious omission like that? And at the same time: but why
does the mt7530 DSA driver work with the same DSA master, but not rtl8365mb?
The answer to both, I think, is "some DSA masters do understand a
particular DSA switch tag, particularly the one from the same vendor".
So if we stop inheriting the checksum offload bits from vlan_features,
we introduce a performance regression for those.

We should instead ask the DSA master "for this DSA tagging protocol,
what netdev features can DSA inherit"? Because of the variability per
tagging protocol, this probably needs to be done through a new netdev
operation, I don't know of any cleaner way.
The complicated part is that we'd need to correctly identify the pairs
of DSA master drivers and tagging protocols where some features can be
safely inherited. Then, it's not too clear whether we want this new ndo
to cover other functionality as well, or if netdev features are enough.

So the sad news for you is that this is pretty much "net-next" material,
even if it fixes what is essentially a design shortcoming. If we're
quick, we could start doing this right as net-next reopens, and that
would give other developers maximum opportunity to fix up the
performance regressions caused by lack of TX checksumming.

> > > Oh, this DSA driver still does not implement vlan nor bridge offload.
> > > Maybe it would matter.
> >
> > It doesn't matter. The vlan_features is a confusing name for what it
> > really does here. I'll explain in a bit once you clarify the other
> > things I asked for.
> 
> That is good news as we can deal with it independently. I wish to
> focus on that afterwards.
> 
> Regards,
> 
> Luiz

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

* Re: [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops
  2022-01-21 22:13         ` Luiz Angelo Daros de Luca
@ 2022-01-21 23:48           ` Andrew Lunn
  0 siblings, 0 replies; 88+ messages in thread
From: Andrew Lunn @ 2022-01-21 23:48 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Florian Fainelli, open list:NETWORKING DRIVERS, Linus Walleij,
	Vivien Didelot, Vladimir Oltean, Alvin Šipraga,
	Arınç ÜNAL, Frank Wunderlich

> Should I submit a patch to make dsa work like this then?
> 
> dsa_switch_setup() {
>         ....
>         ds->ops->setup()
>         ....
>         if (ds->ops->phy_read) {
>               if (ds->slave_mii_bus)
>                     error("ds->ops->phy_read is set, I should be the
> one allocating ds->slave_mii_bus!")
>               ...allocate and register ds->slave_mii_bus...
>         }
> }

You could add a WARN_ON(ds->ops->phy_read && ds->ops->phy_read);

    Andrew

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21 21:51                             ` Luiz Angelo Daros de Luca
  2022-01-21 22:49                               ` Vladimir Oltean
@ 2022-01-22 15:51                               ` Andrew Lunn
  1 sibling, 0 replies; 88+ messages in thread
From: Andrew Lunn @ 2022-01-22 15:51 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Vladimir Oltean, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

> trap_port seems to be where the switch will send any packet captured
> from LAN ports. There are a couple of situations it will be used like:
> 1) untagged or unmatched vlan packets (if configured to do so)
> 2) some multicasting packets (Reserved Multicast Address), for some
> cases like capturing STP or LACP
> 3) IGMP and 802.1X EAPOL packets
> 4) Switch ACL rules that could match a packet and send it to the trap port.
> 
> In my early tests, I only saw some IGMP packets trapped to CPU. I also
> do not know how important they are.

STP is important for detecting loops in the ethernet traffic and
blocking ports. The linux software bridge will want to see these
packets.

IGMP will become important when you implement multicast support in the
switch. It will allow you to optimize the distribution of multicast to
only ports which have expressed an interest in receiving the group.

Currently we don't have any switch driver making use of 802.1x. It is
something which many switches have, but so far nobody has spent the
time to implement an interface to wpa_supplicant etc.

     Andrew

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-21 22:49                               ` Vladimir Oltean
@ 2022-01-22 20:12                                 ` Luiz Angelo Daros de Luca
  2022-01-24 15:31                                   ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-22 20:12 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

> > The internal SoC switch is behaving as an unmanaged switch, with no
> > vlans. It would be just extra overhead to have it working as a DSA
> > switch, specially
> > as those two switches tags are not compatible. I still have the
> > swconfig driver installed but I was only using it for some debugging
> > (checking metrics). I think that the state the bootloader leaves that
> > switchis enough to make it forward packets to the Realtek switch. In
> > device-tree conf, I'm directly using that eth0 as the CPU port.
>
> There could be value in managing the internal switch with DSA too, for
> example in a situation like this:
>
>  +-------------------------------------------------+
>  |  SoC                                            |
>  |                                                 |
>  |  +----------------+--------+---------------+    |
>  |  |                |        |               |    |
>  |  | Internal       |        |               |    |
>  |  |  switch        +--------+               |    |
>  |  | (dsa,member = <0 0>;)                   |    |
>  |  | +-------+ +-------+ +-------+ +-------+ |    |
>  |  | |       | |       | |       | |       | |    |
>  |  | | sw0p0 | | sw0p1 | | sw0p2 | | sw0p3 | |    |
>  |  | |       | |       | |       | |       | |    |
>  +--+-+-------+-+-------+-+-------+-+-------+-+----+
>
>  +----+--------+------------------+
>  |    |        |                  |
>  |    +--------+                  |
>  | External switch                |
>  | (dsa,member = <1 0>;)          |
>  |  +-------+ +-------+ +-------+ |
>  |  |       | |       | |       | |
>  |  | sw1p0 | | sw1p1 | | sw1p2 | |
>  |  |       | |       | |       | |
>  +--+-------+-+-------+-+-------+-+
>
> where you'd create a bridge spanning all of sw0p1, sw0p2, sw0p3, sw1p0,
> sw1p1, sw1p2. Forwarding between the internal and the external switch is
> done in software, and that deals with the "impedance matching" between
> the tagging protocols too - first the packet is stripped of the DSA tag
> of the ingress switch, then the DSA tag of the egress switch is added.
> With a transparent internal switch (no driver), ports sw0p1, sw0p2,
> sw0p3 are dead, since if you'd connect them to a PHY, they'd spit out
> DSA-tagged packets from the external switch.

Oh, any other internal switch ports are physically not in use.  Those
ports are 10/100. I think that in my device, some of its pins are even
used as GPIO.
And the offload issue will remain as the HW will not be able to
offload the second layer of DSA tag.

> > > I hate to guess, but since both you and Arınç have mentioned the
> > > mt7620a/mt7621 SoCs,
> >
> > Sorry for the incomplete answer. If it helps, this is my device
> > https://github.com/luizluca/openwrt/blob/tplink_c5v4_dsa/target/linux/ramips/dts/mt7620a_tplink_archer-c5-v4.dts
> >
> > I try to keep my remote branch updated, although it has some dirty changes:
> > https://github.com/luizluca/openwrt/tree/tplink_c5v4_dsa
> >
> > > I'd guess that the top-most DSA driver in both cases is "mediatek,eth-mac" (drivers/net/ethernet/mediatek/mtk_eth_soc.c).
> >
> > Not in my case. The driver I use also supports mt7621 but the upstream
> > driver skipped the mt7620a support.
> >
> > > If so, this would confirm my suspicions, since it sets its vlan_features
> > > to include NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM. Please confirm that
> > > master->vlan_features contains these 2 bits.
> >
> > Yes.
>
> Ok. See the discussion with Lino Sanfilippo here:
> https://lore.kernel.org/netdev/YPAzZXaC%2FEn3s4ly@lunn.ch/
> Basically, the moving parts of this mechanism are:
>
> - when the DSA master doesn't understand DSA tags, the transmit
>   checksums must be calculated in software.
>
> - this is already supported, we just need to make sure that the DSA
>   slave->features does not include any checksum offload bits
>   (NETIF_F_HW_CSUM, NETIF_F_IP_CSUM, NETIF_F_IPV6_CSUM), otherwise that
>   will be delegated to the device driver. The place that checks that
>   condition and calculates the checksum in software is validate_xmit_skb() ->
>   skb_csum_hwoffload_help().
>
> - the checksum is evaluated on the skb before the DSA tag is even
>   inserted, and is preserved when DSA inserts the header, and is
>   therefore still correct by the time the skb reaches the DSA master
>   driver. A DSA-unaware master doesn't have to do anything for this
>   packet, the IP header checksum will still be correct despite the
>   hardware not recognizing the IP header.
>
> - the way DSA populates slave->features is by inheriting master->vlan_features
>   (vlan_features means "netdev features which are inheritable by VLAN
>   upper interfaces"). This directly makes or breaks what happens in
>   validate_xmit_skb() on a DSA slave interface.
>
> - the problem occurs when the DSA master puts checksum offload bits in
>   both dev->features and dev->vlan_features. The master thinks this
>   means: "I can offload IP checksumming for myself and for VLAN upper
>   interfaces (I can recognize the IP header past the VLAN header)."
>   Little does it know that DSA assumes this means it can also offload
>   checksumming in the presence of switch tags.
>
> So just stop inheriting NETIF_F_HW_CSUM and friends from
> master->vlan_features, right?
>
> Well, you can't help but wonder a bit how come it's 2022 and we could
> still have an obvious omission like that? And at the same time: but why
> does the mt7530 DSA driver work with the same DSA master, but not rtl8365mb?
> The answer to both, I think, is "some DSA masters do understand a
> particular DSA switch tag, particularly the one from the same vendor".
> So if we stop inheriting the checksum offload bits from vlan_features,
> we introduce a performance regression for those.
>
> We should instead ask the DSA master "for this DSA tagging protocol,
> what netdev features can DSA inherit"? Because of the variability per
> tagging protocol, this probably needs to be done through a new netdev
> operation, I don't know of any cleaner way.
> The complicated part is that we'd need to correctly identify the pairs
> of DSA master drivers and tagging protocols where some features can be
> safely inherited. Then, it's not too clear whether we want this new ndo
> to cover other functionality as well, or if netdev features are enough.

I'm new to DSA but I think that a solution like that might not scale
well. For every possible master network driver, it needs to know if
its offload feature will handle every different tag.
Imagining that both new offload HW and new switch tags will still
appear in the kernel, it might be untreatable.

I know dsa properties are not the solution for everything (and I'm
still adapting to where that border is) but, in this case, it is a
device specific arrangement between the ethernet device and the
switch. Wouldn't it be better to allow the
one writing the device-tree description inform if a master feature
cannot be copied to slave devices?

I checked DSA doc again and it says:

"Since tagging protocols in category 1 and 2 break software (and most
often also hardware) packet dissection on the DSA master, features
such as RPS (Receive Packet Steering) on the DSA master would be
broken. The DSA framework deals with this by hooking into the flow
dissector and shifting the offset at which the IP header is to be
found in the tagged frame as seen by the DSA master. This behavior is
automatic based on the overhead value of the tagging protocol. If not
all packets are of equal size, the tagger can implement the
flow_dissect method of the struct dsa_device_ops and override this
default behavior by specifying the correct offset incurred by each
individual RX packet. Tail taggers do not cause issues to the flow
dissector."

It makes me think that it is the master network driver that does not
implement that IP header location shift. Anyway, I believe it also
depends on HW capabilities to inform that shift, right?

I'm trying to think as a DSA newbie (which is exactly what I am).
Differently from an isolated ethernet driver, with DSA, the system
does have control of "something" after the offload should be applied:
the dsa switch. Can't we have a generic way to send a packet to the
switch and make it bounce back to the CPU (passing through the offload
engine)? Would it work if I set the destination port as the CPU port?
This way, we could simply detect if the offload worked and disable
those features that did not work. It could work with a generic
implementation or, if needed, a specialized optional ds_switch_ops
function just to setup that temporary lookback forwarding rule.

> So the sad news for you is that this is pretty much "net-next" material,
> even if it fixes what is essentially a design shortcoming. If we're
> quick, we could start doing this right as net-next reopens, and that
> would give other developers maximum opportunity to fix up the
> performance regressions caused by lack of TX checksumming.

No problem. I'm already playing the long game. I'm just trying to fix
a device I own using my free time and I don't have any manager with
impossible deadlines.
However, any solution with a performance regression would break the
kernel API. I would rather add a new device-tree option :-)

> > > > Oh, this DSA driver still does not implement vlan nor bridge offload.
> > > > Maybe it would matter.
> > >
> > > It doesn't matter. The vlan_features is a confusing name for what it
> > > really does here. I'll explain in a bit once you clarify the other
> > > things I asked for.
> >
> > That is good news as we can deal with it independently. I wish to
> > focus on that afterwards.
> >
> > Regards,
> >
> > Luiz

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-22 20:12                                 ` Luiz Angelo Daros de Luca
@ 2022-01-24 15:31                                   ` Vladimir Oltean
  2022-01-24 16:46                                     ` Jakub Kicinski
  0 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-24 15:31 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Andrew Lunn, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, vivien.didelot, f.fainelli, arinc.unal

On Sat, Jan 22, 2022 at 05:12:28PM -0300, Luiz Angelo Daros de Luca wrote:
> I'm new to DSA but I think that a solution like that might not scale
> well. For every possible master network driver, it needs to know if
> its offload feature will handle every different tag.

Correct, with the sensible default being that no checksum offloading in
the presence of DSA tags is supported.

> Imagining that both new offload HW and new switch tags will still
> appear in the kernel, it might be untreatable.

You don't see DSA masters understanding DSA tagging protocols every day,
I think you're overstating this. We'd have to cover Marvell-on-Marvell,
Broadcom-on-Broadcom, Mediatek-on-Mediatek, and the rest will have to
add their support when they add the hardware.

> I know dsa properties are not the solution for everything (and I'm
> still adapting to where that border is) but, in this case, it is a
> device specific arrangement between the ethernet device and the
> switch. Wouldn't it be better to allow the
> one writing the device-tree description inform if a master feature
> cannot be copied to slave devices?

Assuming an ultra-generic Ethernet controller with advanced soft parser
capabilities, you'd have to teach it the format of each DSA tagging
protocol you intend it to understand anyway, so this doesn't appear the
kind of thing best described in the device tree, since it may easily be
out of sync with what the driver is able to tell the hardware to do.

> 
> I checked DSA doc again and it says:
> 
> "Since tagging protocols in category 1 and 2 break software (and most
> often also hardware) packet dissection on the DSA master, features
> such as RPS (Receive Packet Steering) on the DSA master would be
> broken. The DSA framework deals with this by hooking into the flow
> dissector and shifting the offset at which the IP header is to be
> found in the tagged frame as seen by the DSA master. This behavior is
> automatic based on the overhead value of the tagging protocol. If not
> all packets are of equal size, the tagger can implement the
> flow_dissect method of the struct dsa_device_ops and override this
> default behavior by specifying the correct offset incurred by each
> individual RX packet. Tail taggers do not cause issues to the flow
> dissector."
> 
> It makes me think that it is the master network driver that does not
> implement that IP header location shift. Anyway, I believe it also
> depends on HW capabilities to inform that shift, right?
> 
> I'm trying to think as a DSA newbie (which is exactly what I am).
> Differently from an isolated ethernet driver, with DSA, the system
> does have control of "something" after the offload should be applied:
> the dsa switch. Can't we have a generic way to send a packet to the
> switch and make it bounce back to the CPU (passing through the offload
> engine)? Would it work if I set the destination port as the CPU port?
> This way, we could simply detect if the offload worked and disable
> those features that did not work. It could work with a generic
> implementation or, if needed, a specialized optional ds_switch_ops
> function just to setup that temporary lookback forwarding rule.

To be clear, do you consider this simpler than an ndo operation that
returns true or false if a certain DSA master can offload a certain
netdev feature in the presence of a certain DSA tag?

Ignoring the fact that there are subtly different ways in which various
hardware manufacturers implement packet injection from the CPU (and this
is reflected in the various struct dsa_device_ops :: xmit operation),
plus the fact that dsa_device_ops :: xmit takes a slave net_device as
argument, for which there is none to represent the CPU port. These
points mean that you'd need to implement a separate, hardware-specific
loopback xmit for each tagging protocol. But again, ignoring that for a
second.

When would be a good time to probe for DSA master features? The DSA
master might be down when DSA switches probe. What should we do with
packets sent on a DSA port until we've finished probing for DSA master
capabilities?

> > So the sad news for you is that this is pretty much "net-next" material,
> > even if it fixes what is essentially a design shortcoming. If we're
> > quick, we could start doing this right as net-next reopens, and that
> > would give other developers maximum opportunity to fix up the
> > performance regressions caused by lack of TX checksumming.
> 
> No problem. I'm already playing the long game. I'm just trying to fix
> a device I own using my free time and I don't have any manager with
> impossible deadlines.
> However, any solution with a performance regression would break the
> kernel API. I would rather add a new device-tree option :-)

Feel free to do whatever you want in OpenWRT, but as a general rule of
thumb, if something can be solved without involving the device tree,
then involving the device tree is probably the wrong approach.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 15:31                                   ` Vladimir Oltean
@ 2022-01-24 16:46                                     ` Jakub Kicinski
  2022-01-24 16:55                                       ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Jakub Kicinski @ 2022-01-24 16:46 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	f.fainelli, arinc.unal

On Mon, 24 Jan 2022 17:31:47 +0200 Vladimir Oltean wrote:
> > I checked DSA doc again and it says:
> > 
> > "Since tagging protocols in category 1 and 2 break software (and most
> > often also hardware) packet dissection on the DSA master, features
> > such as RPS (Receive Packet Steering) on the DSA master would be
> > broken. The DSA framework deals with this by hooking into the flow
> > dissector and shifting the offset at which the IP header is to be
> > found in the tagged frame as seen by the DSA master. This behavior is
> > automatic based on the overhead value of the tagging protocol. If not
> > all packets are of equal size, the tagger can implement the
> > flow_dissect method of the struct dsa_device_ops and override this
> > default behavior by specifying the correct offset incurred by each
> > individual RX packet. Tail taggers do not cause issues to the flow
> > dissector."
> > 
> > It makes me think that it is the master network driver that does not
> > implement that IP header location shift. Anyway, I believe it also
> > depends on HW capabilities to inform that shift, right?
> > 
> > I'm trying to think as a DSA newbie (which is exactly what I am).
> > Differently from an isolated ethernet driver, with DSA, the system
> > does have control of "something" after the offload should be applied:
> > the dsa switch. Can't we have a generic way to send a packet to the
> > switch and make it bounce back to the CPU (passing through the offload
> > engine)? Would it work if I set the destination port as the CPU port?
> > This way, we could simply detect if the offload worked and disable
> > those features that did not work. It could work with a generic
> > implementation or, if needed, a specialized optional ds_switch_ops
> > function just to setup that temporary lookback forwarding rule.  
> 
> To be clear, do you consider this simpler than an ndo operation that
> returns true or false if a certain DSA master can offload a certain
> netdev feature in the presence of a certain DSA tag?
> 
> Ignoring the fact that there are subtly different ways in which various
> hardware manufacturers implement packet injection from the CPU (and this
> is reflected in the various struct dsa_device_ops :: xmit operation),
> plus the fact that dsa_device_ops :: xmit takes a slave net_device as
> argument, for which there is none to represent the CPU port. These
> points mean that you'd need to implement a separate, hardware-specific
> loopback xmit for each tagging protocol. But again, ignoring that for a
> second.
> 
> When would be a good time to probe for DSA master features? The DSA
> master might be down when DSA switches probe. What should we do with
> packets sent on a DSA port until we've finished probing for DSA master
> capabilities?

I thought for drivers setting the legacy NETIF_F_IP*_CSUM feature
it's driver's responsibility to validate the geometry of the packet
will work with the parser the device has. Or at least I think that's
what Tom was pushing for when he was cleaning up the checksumming last
(and wrote the long comment on the subject in skbuff.h).

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 16:46                                     ` Jakub Kicinski
@ 2022-01-24 16:55                                       ` Vladimir Oltean
  2022-01-24 17:01                                         ` Florian Fainelli
  0 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-24 16:55 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	f.fainelli, arinc.unal

On Mon, Jan 24, 2022 at 08:46:49AM -0800, Jakub Kicinski wrote:
> I thought for drivers setting the legacy NETIF_F_IP*_CSUM feature
> it's driver's responsibility to validate the geometry of the packet
> will work with the parser the device has. Or at least I think that's
> what Tom was pushing for when he was cleaning up the checksumming last
> (and wrote the long comment on the subject in skbuff.h).

Sorry Jakub, I don't understand what you mean to say when applied to the
context discussed here?

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 16:55                                       ` Vladimir Oltean
@ 2022-01-24 17:01                                         ` Florian Fainelli
  2022-01-24 17:21                                           ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Florian Fainelli @ 2022-01-24 17:01 UTC (permalink / raw)
  To: Vladimir Oltean, Jakub Kicinski
  Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal



On 1/24/2022 8:55 AM, Vladimir Oltean wrote:
> On Mon, Jan 24, 2022 at 08:46:49AM -0800, Jakub Kicinski wrote:
>> I thought for drivers setting the legacy NETIF_F_IP*_CSUM feature
>> it's driver's responsibility to validate the geometry of the packet
>> will work with the parser the device has. Or at least I think that's
>> what Tom was pushing for when he was cleaning up the checksumming last
>> (and wrote the long comment on the subject in skbuff.h).
> 
> Sorry Jakub, I don't understand what you mean to say when applied to the
> context discussed here?

I believe what Jakub meant to say is that if a DSA conduit device driver 
advertises any of the NETIF_F_IP*_CSUM feature bits, then the driver's 
transmit path has the responsibility of checking that the payload being 
transmitted has a chance of being checksummed properly by the hardware. 
The problem here is not so much the geometry itself (linear or not, 
number/size of fragments, etc.) as much as the placement of the L2/L3 
headers usually.

DSA conduit network device drivers do not have the ability today to 
determine what type of DSA tagging is being applied onto the DSA master 
but they do know whether DSA tagging is in use or not which may be 
enough to be overly compatible.

It is not clear to me whether we can solve this generically within the 
DSA framework or even if this is desirable, but once we have identified 
a problematic association of DSA tagger and DSA conduit, we can always 
have the DSA conduit driver do something like:

if (netdev_uses_dsa(dev))
	skb_checksum_help()

or have a fix_features callback which does reject the enabling of 
NETIF_F_IP*_CSUM if netdev_uses_dsa() becomes true.
-- 
Florian

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 17:01                                         ` Florian Fainelli
@ 2022-01-24 17:21                                           ` Vladimir Oltean
  2022-01-24 17:30                                             ` Florian Fainelli
  2022-01-24 17:35                                             ` Jakub Kicinski
  0 siblings, 2 replies; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-24 17:21 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Jakub Kicinski, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, Jan 24, 2022 at 09:01:20AM -0800, Florian Fainelli wrote:
> On 1/24/2022 8:55 AM, Vladimir Oltean wrote:
> > On Mon, Jan 24, 2022 at 08:46:49AM -0800, Jakub Kicinski wrote:
> > > I thought for drivers setting the legacy NETIF_F_IP*_CSUM feature
> > > it's driver's responsibility to validate the geometry of the packet
> > > will work with the parser the device has. Or at least I think that's
> > > what Tom was pushing for when he was cleaning up the checksumming last
> > > (and wrote the long comment on the subject in skbuff.h).
> > 
> > Sorry Jakub, I don't understand what you mean to say when applied to the
> > context discussed here?
> 
> I believe what Jakub meant to say is that if a DSA conduit device driver
> advertises any of the NETIF_F_IP*_CSUM feature bits, then the driver's
> transmit path has the responsibility of checking that the payload being
> transmitted has a chance of being checksummed properly by the hardware. The
> problem here is not so much the geometry itself (linear or not, number/size
> of fragments, etc.) as much as the placement of the L2/L3 headers usually.
> 
> DSA conduit network device drivers do not have the ability today to
> determine what type of DSA tagging is being applied onto the DSA master but
> they do know whether DSA tagging is in use or not which may be enough to be
> overly compatible.
> 
> It is not clear to me whether we can solve this generically within the DSA
> framework or even if this is desirable, but once we have identified a
> problematic association of DSA tagger and DSA conduit, we can always have
> the DSA conduit driver do something like:
> 
> if (netdev_uses_dsa(dev))
> 	skb_checksum_help()
> 
> or have a fix_features callback which does reject the enabling of
> NETIF_F_IP*_CSUM if netdev_uses_dsa() becomes true.

Yes, but as you point out, the DSA master driver doesn't know what
header/trailer format it's dealing with. We could use netdev_uses_dsa()
as a very rough approximation, and that might work when we know that the
particular Ethernet controller is used only in conjunction with a single
type of DSA switch [from the same vendor], but I think we're just
delaying the inevitable, which is to treat the case where an Ethernet
controller can be a DSA master for more than one switch type, and it
understands some protocols but not others.
Also, scattering "if (netdev_uses_dsa(dev)) skb_checksum_help()" in
DSA-unaware drivers (the common case) seems like the improper approach.
We might end up seeing this pattern quite a lot, so DSA-unaware drivers
won't be DSA-unaware any longer.
It's still possible I'm misunderstanding something...

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 17:21                                           ` Vladimir Oltean
@ 2022-01-24 17:30                                             ` Florian Fainelli
  2022-01-24 17:35                                             ` Jakub Kicinski
  1 sibling, 0 replies; 88+ messages in thread
From: Florian Fainelli @ 2022-01-24 17:30 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Jakub Kicinski, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal



On 1/24/2022 9:21 AM, Vladimir Oltean wrote:
> On Mon, Jan 24, 2022 at 09:01:20AM -0800, Florian Fainelli wrote:
>> On 1/24/2022 8:55 AM, Vladimir Oltean wrote:
>>> On Mon, Jan 24, 2022 at 08:46:49AM -0800, Jakub Kicinski wrote:
>>>> I thought for drivers setting the legacy NETIF_F_IP*_CSUM feature
>>>> it's driver's responsibility to validate the geometry of the packet
>>>> will work with the parser the device has. Or at least I think that's
>>>> what Tom was pushing for when he was cleaning up the checksumming last
>>>> (and wrote the long comment on the subject in skbuff.h).
>>>
>>> Sorry Jakub, I don't understand what you mean to say when applied to the
>>> context discussed here?
>>
>> I believe what Jakub meant to say is that if a DSA conduit device driver
>> advertises any of the NETIF_F_IP*_CSUM feature bits, then the driver's
>> transmit path has the responsibility of checking that the payload being
>> transmitted has a chance of being checksummed properly by the hardware. The
>> problem here is not so much the geometry itself (linear or not, number/size
>> of fragments, etc.) as much as the placement of the L2/L3 headers usually.
>>
>> DSA conduit network device drivers do not have the ability today to
>> determine what type of DSA tagging is being applied onto the DSA master but
>> they do know whether DSA tagging is in use or not which may be enough to be
>> overly compatible.
>>
>> It is not clear to me whether we can solve this generically within the DSA
>> framework or even if this is desirable, but once we have identified a
>> problematic association of DSA tagger and DSA conduit, we can always have
>> the DSA conduit driver do something like:
>>
>> if (netdev_uses_dsa(dev))
>> 	skb_checksum_help()
>>
>> or have a fix_features callback which does reject the enabling of
>> NETIF_F_IP*_CSUM if netdev_uses_dsa() becomes true.
> 
> Yes, but as you point out, the DSA master driver doesn't know what
> header/trailer format it's dealing with. We could use netdev_uses_dsa()
> as a very rough approximation, and that might work when we know that the
> particular Ethernet controller is used only in conjunction with a single
> type of DSA switch [from the same vendor], but I think we're just
> delaying the inevitable, which is to treat the case where an Ethernet
> controller can be a DSA master for more than one switch type, and it
> understands some protocols but not others.
> Also, scattering "if (netdev_uses_dsa(dev)) skb_checksum_help()" in
> DSA-unaware drivers (the common case) seems like the improper approach.
> We might end up seeing this pattern quite a lot, so DSA-unaware drivers
> won't be DSA-unaware any longer.
> It's still possible I'm misunderstanding something...

I don't think you are, and my crude proposal was just so we have it 
working, and then we can think about having it work fast.

A long time (but in the same galaxy) DSA used to set skb->protocol to 
the value of the DSA tagging protocol used (say ETH_P_EDSA), long before 
they were all consolidated within ETH_P_XDSA, but this would be breaking 
any checksum setting up that looks at skb->protocol to determine if it 
is IP, IPv6 or else, so in a way it might have done what we wanted it to 
do, but this was mostly by accident.

The tagger on transmit can definitively tell us via an out of band 
signaling what type of tagging protocol is being used and where it is 
located within the packet if necessary, and I suppose we can then update 
the DSA conduit in order to not ask the HW to checksum if this is deemed 
problematic. Doing that for every single packet transmitted however may 
not be very efficient given that usually we set-up one tagging protocol, 
then we set-up another one (possibly), but it won't change on a packet 
by packet basis. So maybe what we need to do is at the time we "connect" 
the tagger we inform the DSA master that from there on, all that is 
supposed to go through that interface will look that way, along with a 
description of the tagger offset and length?
-- 
Florian

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 17:21                                           ` Vladimir Oltean
  2022-01-24 17:30                                             ` Florian Fainelli
@ 2022-01-24 17:35                                             ` Jakub Kicinski
  2022-01-24 18:20                                               ` Jakub Kicinski
  1 sibling, 1 reply; 88+ messages in thread
From: Jakub Kicinski @ 2022-01-24 17:35 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, 24 Jan 2022 19:21:58 +0200 Vladimir Oltean wrote:
> On Mon, Jan 24, 2022 at 09:01:20AM -0800, Florian Fainelli wrote:
> > On 1/24/2022 8:55 AM, Vladimir Oltean wrote:  
> > > Sorry Jakub, I don't understand what you mean to say when applied to the
> > > context discussed here?  
> > 
> > I believe what Jakub meant to say is that if a DSA conduit device driver
> > advertises any of the NETIF_F_IP*_CSUM feature bits, then the driver's
> > transmit path has the responsibility of checking that the payload being
> > transmitted has a chance of being checksummed properly by the hardware. The
> > problem here is not so much the geometry itself (linear or not, number/size
> > of fragments, etc.) as much as the placement of the L2/L3 headers usually.

Sorry I used "geometry" loosely.

What I meant is simply that if the driver uses NETIF_F_IP*_CSUM 
it should parse the packet before it hands it off to the HW.

There is infinity of protocols users can come up with, while the device
parser is very much finite, so it's only practical to check compliance
with the HW parser in the driver. The reverse approach of adding
per-protocol caps is a dead end IMO. And we should not bloat the stack
when NETIF_F_HW_CSUM exists and the memo that parsing packets on Tx is
bad b/c of protocol ossification went out a decade ago.

> > DSA conduit network device drivers do not have the ability today to
> > determine what type of DSA tagging is being applied onto the DSA master but
> > they do know whether DSA tagging is in use or not which may be enough to be
> > overly compatible.
> > 
> > It is not clear to me whether we can solve this generically within the DSA
> > framework or even if this is desirable, but once we have identified a
> > problematic association of DSA tagger and DSA conduit, we can always have
> > the DSA conduit driver do something like:
> > 
> > if (netdev_uses_dsa(dev))
> > 	skb_checksum_help()
> > 
> > or have a fix_features callback which does reject the enabling of
> > NETIF_F_IP*_CSUM if netdev_uses_dsa() becomes true.  
> 
> Yes, but as you point out, the DSA master driver doesn't know what
> header/trailer format it's dealing with. We could use netdev_uses_dsa()
> as a very rough approximation, and that might work when we know that the
> particular Ethernet controller is used only in conjunction with a single
> type of DSA switch [from the same vendor], but I think we're just
> delaying the inevitable, which is to treat the case where an Ethernet
> controller can be a DSA master for more than one switch type, and it
> understands some protocols but not others.
> Also, scattering "if (netdev_uses_dsa(dev)) skb_checksum_help()" in
> DSA-unaware drivers (the common case) seems like the improper approach.
> We might end up seeing this pattern quite a lot, so DSA-unaware drivers
> won't be DSA-unaware any longer.

It's not about DSA. The driver should not check

if (dsa())
	blah;

it should check 

if (!(eth [-> vlan] -> ip -> tcp/udp))
	csum_help();

> It's still possible I'm misunderstanding something...

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 17:35                                             ` Jakub Kicinski
@ 2022-01-24 18:20                                               ` Jakub Kicinski
  2022-01-24 19:08                                                 ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Jakub Kicinski @ 2022-01-24 18:20 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, 24 Jan 2022 09:35:56 -0800 Jakub Kicinski wrote:
> Sorry I used "geometry" loosely.
> 
> What I meant is simply that if the driver uses NETIF_F_IP*_CSUM 
> it should parse the packet before it hands it off to the HW.
> 
> There is infinity of protocols users can come up with, while the device
> parser is very much finite, so it's only practical to check compliance
> with the HW parser in the driver. The reverse approach of adding
> per-protocol caps is a dead end IMO. And we should not bloat the stack
> when NETIF_F_HW_CSUM exists and the memo that parsing packets on Tx is
> bad b/c of protocol ossification went out a decade ago.

> It's not about DSA. The driver should not check
> 
> if (dsa())
> 	blah;
> 
> it should check 
> 
> if (!(eth [-> vlan] -> ip -> tcp/udp))
> 	csum_help();

Admittedly on a quick look thru the drivers which already do this 
I only see L3, L4 and GRE/UDP encap checks. Nothing validates L2.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 18:20                                               ` Jakub Kicinski
@ 2022-01-24 19:08                                                 ` Vladimir Oltean
  2022-01-24 19:38                                                   ` Jakub Kicinski
  0 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-24 19:08 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, Jan 24, 2022 at 10:20:51AM -0800, Jakub Kicinski wrote:
> On Mon, 24 Jan 2022 09:35:56 -0800 Jakub Kicinski wrote:
> > Sorry I used "geometry" loosely.
> >
> > What I meant is simply that if the driver uses NETIF_F_IP*_CSUM
> > it should parse the packet before it hands it off to the HW.
> >
> > There is infinity of protocols users can come up with, while the device
> > parser is very much finite, so it's only practical to check compliance
> > with the HW parser in the driver. The reverse approach of adding
> > per-protocol caps is a dead end IMO. And we should not bloat the stack
> > when NETIF_F_HW_CSUM exists and the memo that parsing packets on Tx is
> > bad b/c of protocol ossification went out a decade ago.
>
> > It's not about DSA. The driver should not check
> >
> > if (dsa())
> > 	blah;
> >
> > it should check
> >
> > if (!(eth [-> vlan] -> ip -> tcp/udp))
> > 	csum_help();
>
> Admittedly on a quick look thru the drivers which already do this
> I only see L3, L4 and GRE/UDP encap checks. Nothing validates L2.

So before we declare that any given Ethernet driver is buggy for declaring
NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and not checking that skb->csum_start
points where it expects it to (taking into consideration potential VLAN
headers, IPv6 extension headers), is there any driver that _does_
perform these checks correctly, that could be used as an example?

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 19:08                                                 ` Vladimir Oltean
@ 2022-01-24 19:38                                                   ` Jakub Kicinski
  2022-01-24 20:56                                                     ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Jakub Kicinski @ 2022-01-24 19:38 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, 24 Jan 2022 21:08:45 +0200 Vladimir Oltean wrote:
> On Mon, Jan 24, 2022 at 10:20:51AM -0800, Jakub Kicinski wrote:
> > On Mon, 24 Jan 2022 09:35:56 -0800 Jakub Kicinski wrote:  
> > > Sorry I used "geometry" loosely.
> > >
> > > What I meant is simply that if the driver uses NETIF_F_IP*_CSUM
> > > it should parse the packet before it hands it off to the HW.
> > >
> > > There is infinity of protocols users can come up with, while the device
> > > parser is very much finite, so it's only practical to check compliance
> > > with the HW parser in the driver. The reverse approach of adding
> > > per-protocol caps is a dead end IMO. And we should not bloat the stack
> > > when NETIF_F_HW_CSUM exists and the memo that parsing packets on Tx is
> > > bad b/c of protocol ossification went out a decade ago.  
> >  
> > > It's not about DSA. The driver should not check
> > >
> > > if (dsa())
> > > 	blah;
> > >
> > > it should check
> > >
> > > if (!(eth [-> vlan] -> ip -> tcp/udp))
> > > 	csum_help();  
> >
> > Admittedly on a quick look thru the drivers which already do this
> > I only see L3, L4 and GRE/UDP encap checks. Nothing validates L2.  
> 
> So before we declare that any given Ethernet driver is buggy for declaring
> NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and not checking that skb->csum_start
> points where it expects it to (taking into consideration potential VLAN
> headers, IPv6 extension headers), 

Extension headers are explicitly not supported by NETIF_F_IPV6_CSUM.

IIRC Tom's hope was to delete NETIF_F_IP*_CSUM completely once all
drivers are converted to parsing and therefore can use NETIF_F_HW_CSUM.

> is there any driver that _does_ perform these checks correctly, that
> could be used as an example?

I don't think so. Let me put it this way - my understanding is that up
until now we had been using the vlan_features, mpls_features etc to
perform L2/L2.5/below-IP feature stripping. This scales poorly to DSA
tags, as discussed in this thread.

I'm suggesting we extend the kind of checking we already do to work
around inevitable deficiencies of device parsers for tunnels to DSA
tags.

We can come up with various schemes of expressing capabilities
between underlying driver and tag driver. I'm not aware of similar
out-of-band schemes existing today so it'd be "DSA doing it's own
thing", which does not seem great.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 19:38                                                   ` Jakub Kicinski
@ 2022-01-24 20:56                                                     ` Vladimir Oltean
  2022-01-24 21:42                                                       ` Jakub Kicinski
  0 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-24 20:56 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, Jan 24, 2022 at 11:38:12AM -0800, Jakub Kicinski wrote:
> On Mon, 24 Jan 2022 21:08:45 +0200 Vladimir Oltean wrote:
> > On Mon, Jan 24, 2022 at 10:20:51AM -0800, Jakub Kicinski wrote:
> > > On Mon, 24 Jan 2022 09:35:56 -0800 Jakub Kicinski wrote:
> > > > Sorry I used "geometry" loosely.
> > > >
> > > > What I meant is simply that if the driver uses NETIF_F_IP*_CSUM
> > > > it should parse the packet before it hands it off to the HW.
> > > >
> > > > There is infinity of protocols users can come up with, while the device
> > > > parser is very much finite, so it's only practical to check compliance
> > > > with the HW parser in the driver. The reverse approach of adding
> > > > per-protocol caps is a dead end IMO. And we should not bloat the stack
> > > > when NETIF_F_HW_CSUM exists and the memo that parsing packets on Tx is
> > > > bad b/c of protocol ossification went out a decade ago.
> > >
> > > > It's not about DSA. The driver should not check
> > > >
> > > > if (dsa())
> > > > 	blah;
> > > >
> > > > it should check
> > > >
> > > > if (!(eth [-> vlan] -> ip -> tcp/udp))
> > > > 	csum_help();
> > >
> > > Admittedly on a quick look thru the drivers which already do this
> > > I only see L3, L4 and GRE/UDP encap checks. Nothing validates L2.
> >
> > So before we declare that any given Ethernet driver is buggy for declaring
> > NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and not checking that skb->csum_start
> > points where it expects it to (taking into consideration potential VLAN
> > headers, IPv6 extension headers),
>
> Extension headers are explicitly not supported by NETIF_F_IPV6_CSUM.
>
> IIRC Tom's hope was to delete NETIF_F_IP*_CSUM completely once all
> drivers are converted to parsing and therefore can use NETIF_F_HW_CSUM.

IIUC, NETIF_F_IP*_CSUM vs NETIF_F_HW_CSUM doesn't make that big of a
difference in terms of what the driver should check for, if the hardware
checksum offload engine can't directly be given the csum_start and
csum_offset, wherever they may be.

> > is there any driver that _does_ perform these checks correctly, that
> > could be used as an example?
>
> I don't think so. Let me put it this way - my understanding is that up
> until now we had been using the vlan_features, mpls_features etc to
> perform L2/L2.5/below-IP feature stripping. This scales poorly to DSA
> tags, as discussed in this thread.
>
> I'm suggesting we extend the kind of checking we already do to work
> around inevitable deficiencies of device parsers for tunnels to DSA
> tags.

Sorry, I'm very tired and I probably don't understand what you're
saying, so excuse the extra clarification questions.

The typical protocol checking that drivers with NETIF_F_HW_CSUM do seems
to be based on vlan_get_protocol()/skb->protocol/skb_network_header()/
skb_transport_header() values, all of which make DSA invisible. So they
don't work if the underlying hardware really doesn't like seeing an
unexpected DSA header.

When you say "I'm suggesting we extend the kind of checking we already do",
do you mean we should modify the likes of e1000e and igb such that, if
they're ever used as DSA masters, they do a full header parse of the
packet (struct ethhdr :: h_proto, check if VLAN, struct iphdr/ipv6hdr,
etc.) instead of the current logic? It will be pretty convoluted unless
we have some helper. Because if I follow through, for a DSA-tagged IP
packet on xmit, skb->protocol is certainly htons(ETH_P_IP):

ntohs(skb->protocol) = 0x800, csum_offset = 16, csum_start = 280, skb_checksum_start_offset = 54, skb->network_header = 260, skb_network_header_len = 20

skb_dump output:
skb len=94 headroom=226 headlen=94 tailroom=384
mac=(226,34) net=(260,20) trans=280
shinfo(txflags=0 nr_frags=0 gso(size=0 type=1 segs=1))
csum(0x100118 ip_summed=3 complete_sw=0 valid=0 level=0)
hash(0x7710ee84 sw=0 l4=1) proto=0x0800 pkttype=0 iif=0
dev name=eno2 feat=0x00020100001149a9
sk family=2 type=1 proto=6
skb headroom: 00000000: 6c 00 03 02 64 65 76 00 fe ed ca fe 28 00 00 00
...(junk)...
skb headroom: 000000e0: 5f 43
                        20 byte DSA tag
                        |
                        v
skb linear:   00000000: 88 80 00 0a 80 00 00 00 00 00 00 00 08 00 30 00
                                    skb_mac_header()
                                    |
                                    v
skb linear:   00000010: 00 00 00 00 68 05 ca 92 af 20 00 04 9f 05 f6 28
                              skb_network_header()
                              |
                              v
skb linear:   00000020: 08 00 45 00 00 3c 26 47 40 00 40 06 00 49 0a 00
                                          skb_checksum_start_offset
                                          |
                                          |                       csum_offset
                                          v                       v
skb linear:   00000030: 00 2c 0a 00 00 01 b6 08 14 51 11 1f 91 4f 00 00
skb linear:   00000040: 00 00 a0 02 fa f0 14 5b 00 00 02 04 05 b4 04 02
skb linear:   00000050: 08 0a 2e 00 e5 b8 00 00 00 00 01 03 03 07

I don't know, I just don't expect that non-DSA users of those drivers
will be very happy about such changes. Do these existing protocol
checking schemes qualify as buggy?

If this is the convention that we want to enforce, then I can't really
help Luiz with fixing the OpenWRT mtk_eth_soc.c - he'll have to figure
out a way to parse the packets for which his hardware will accept the
checksumming offload, and call skb_checksum_help() otherwise.

> We can come up with various schemes of expressing capabilities
> between underlying driver and tag driver. I'm not aware of similar
> out-of-band schemes existing today so it'd be "DSA doing it's own
> thing", which does not seem great.

It at least seems less complex to me, and less checking in the fast path
if I understand everything that's been said correctly.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 20:56                                                     ` Vladimir Oltean
@ 2022-01-24 21:42                                                       ` Jakub Kicinski
  2022-01-24 22:30                                                         ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Jakub Kicinski @ 2022-01-24 21:42 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, 24 Jan 2022 22:56:07 +0200 Vladimir Oltean wrote:
> On Mon, Jan 24, 2022 at 11:38:12AM -0800, Jakub Kicinski wrote:
> > On Mon, 24 Jan 2022 21:08:45 +0200 Vladimir Oltean wrote:  
> > > So before we declare that any given Ethernet driver is buggy for declaring
> > > NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and not checking that skb->csum_start
> > > points where it expects it to (taking into consideration potential VLAN
> > > headers, IPv6 extension headers),  
> >
> > Extension headers are explicitly not supported by NETIF_F_IPV6_CSUM.
> >
> > IIRC Tom's hope was to delete NETIF_F_IP*_CSUM completely once all
> > drivers are converted to parsing and therefore can use NETIF_F_HW_CSUM.  
> 
> IIUC, NETIF_F_IP*_CSUM vs NETIF_F_HW_CSUM doesn't make that big of a
> difference in terms of what the driver should check for, if the hardware
> checksum offload engine can't directly be given the csum_start and
> csum_offset, wherever they may be.
> 
> > > is there any driver that _does_ perform these checks correctly, that
> > > could be used as an example?  
> >
> > I don't think so. Let me put it this way - my understanding is that up
> > until now we had been using the vlan_features, mpls_features etc to
> > perform L2/L2.5/below-IP feature stripping. This scales poorly to DSA
> > tags, as discussed in this thread.
> >
> > I'm suggesting we extend the kind of checking we already do to work
> > around inevitable deficiencies of device parsers for tunnels to DSA
> > tags.  
> 
> Sorry, I'm very tired and I probably don't understand what you're
> saying, so excuse the extra clarification questions.
> 
> The typical protocol checking that drivers with NETIF_F_HW_CSUM do seems
> to be based on vlan_get_protocol()/skb->protocol/skb_network_header()/
> skb_transport_header() values, all of which make DSA invisible. So they
> don't work if the underlying hardware really doesn't like seeing an
> unexpected DSA header.
> 
> When you say "I'm suggesting we extend the kind of checking we already do",
> do you mean we should modify the likes of e1000e and igb such that, if
> they're ever used as DSA masters, they do a full header parse of the
> packet (struct ethhdr :: h_proto, check if VLAN, struct iphdr/ipv6hdr,
> etc.) instead of the current logic?

That was my thinking, yes. The exact amount of work depends on the
driver, I believe that more recent Intel parts (igb, ixgbe and newer)
pass a L3 offset to the HW. They treat L2 as opaque, ergo no patches
needed. At a glance e1000e passes the full skb_checksum_start_offset()
to HW, so likely even better. 

It's only drivers for devices which actually want to parse the Ethertype
that would need extra checks. (Coincidentally such devices can't support
MPLS given the lack of L3 indication in the frame.)

> It will be pretty convoluted unless
> we have some helper. Because if I follow through, for a DSA-tagged IP
> packet on xmit, skb->protocol is certainly htons(ETH_P_IP):
> 
> ntohs(skb->protocol) = 0x800, csum_offset = 16, csum_start = 280, skb_checksum_start_offset = 54, skb->network_header = 260, skb_network_header_len = 20
> 
> skb_dump output:
> skb len=94 headroom=226 headlen=94 tailroom=384
> mac=(226,34) net=(260,20) trans=280
> shinfo(txflags=0 nr_frags=0 gso(size=0 type=1 segs=1))
> csum(0x100118 ip_summed=3 complete_sw=0 valid=0 level=0)
> hash(0x7710ee84 sw=0 l4=1) proto=0x0800 pkttype=0 iif=0
> dev name=eno2 feat=0x00020100001149a9
> sk family=2 type=1 proto=6
> skb headroom: 00000000: 6c 00 03 02 64 65 76 00 fe ed ca fe 28 00 00 00
> ...(junk)...
> skb headroom: 000000e0: 5f 43
>                         20 byte DSA tag
>                         |
>                         v
> skb linear:   00000000: 88 80 00 0a 80 00 00 00 00 00 00 00 08 00 30 00
>                                     skb_mac_header()
>                                     |
>                                     v
> skb linear:   00000010: 00 00 00 00 68 05 ca 92 af 20 00 04 9f 05 f6 28
>                               skb_network_header()
>                               |
>                               v
> skb linear:   00000020: 08 00 45 00 00 3c 26 47 40 00 40 06 00 49 0a 00
>                                           skb_checksum_start_offset
>                                           |
>                                           |                       csum_offset
>                                           v                       v
> skb linear:   00000030: 00 2c 0a 00 00 01 b6 08 14 51 11 1f 91 4f 00 00
> skb linear:   00000040: 00 00 a0 02 fa f0 14 5b 00 00 02 04 05 b4 04 02
> skb linear:   00000050: 08 0a 2e 00 e5 b8 00 00 00 00 01 03 03 07

Oof, so in this case the DSA tag is _before_ the skb_mac_header()?
Or the prepend is supposed to be parsable as a Ethernet header?
Seems like any device that can do csum over this packet must already 
use L3/L4 offsets or have explicit knowledge of DSA, right?

> I don't know, I just don't expect that non-DSA users of those drivers
> will be very happy about such changes. Do these existing protocol
> checking schemes qualify as buggy?

Unfortunate reality of the checksum offloads is that most drivers for
devices which parse on Tx are buggy, it's more of a question of whether
anyone tried to use an unsupported protocol stack :( Recent example
that comes to mind is 1698d600b361 ("bnxt_en: Implement
.ndo_features_check().").

> If this is the convention that we want to enforce, then I can't really
> help Luiz with fixing the OpenWRT mtk_eth_soc.c - he'll have to figure
> out a way to parse the packets for which his hardware will accept the
> checksumming offload, and call skb_checksum_help() otherwise.
> 
> > We can come up with various schemes of expressing capabilities
> > between underlying driver and tag driver. I'm not aware of similar
> > out-of-band schemes existing today so it'd be "DSA doing it's own
> > thing", which does not seem great.  
> 
> It at least seems less complex to me, and less checking in the fast path
> if I understand everything that's been said correctly.

I understand, I'm primarily trying to share some context and prior work.
I don't mean to nack all other approaches.

I believe writing a parser matching the device behavior would be easier
for a driver author than interpreting the runes of our csum offload API
and getting thru the thicket of all the bits. If that's not the case my
argument is likely defeated.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 21:42                                                       ` Jakub Kicinski
@ 2022-01-24 22:30                                                         ` Vladimir Oltean
  2022-01-25  7:15                                                           ` Luiz Angelo Daros de Luca
  2022-01-25  9:44                                                           ` Arınç ÜNAL
  0 siblings, 2 replies; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-24 22:30 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot, arinc.unal

On Mon, Jan 24, 2022 at 01:42:42PM -0800, Jakub Kicinski wrote:
> On Mon, 24 Jan 2022 22:56:07 +0200 Vladimir Oltean wrote:
> > On Mon, Jan 24, 2022 at 11:38:12AM -0800, Jakub Kicinski wrote:
> > > On Mon, 24 Jan 2022 21:08:45 +0200 Vladimir Oltean wrote:
> > > > So before we declare that any given Ethernet driver is buggy for declaring
> > > > NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and not checking that skb->csum_start
> > > > points where it expects it to (taking into consideration potential VLAN
> > > > headers, IPv6 extension headers),
> > >
> > > Extension headers are explicitly not supported by NETIF_F_IPV6_CSUM.
> > >
> > > IIRC Tom's hope was to delete NETIF_F_IP*_CSUM completely once all
> > > drivers are converted to parsing and therefore can use NETIF_F_HW_CSUM.
> >
> > IIUC, NETIF_F_IP*_CSUM vs NETIF_F_HW_CSUM doesn't make that big of a
> > difference in terms of what the driver should check for, if the hardware
> > checksum offload engine can't directly be given the csum_start and
> > csum_offset, wherever they may be.
> >
> > > > is there any driver that _does_ perform these checks correctly, that
> > > > could be used as an example?
> > >
> > > I don't think so. Let me put it this way - my understanding is that up
> > > until now we had been using the vlan_features, mpls_features etc to
> > > perform L2/L2.5/below-IP feature stripping. This scales poorly to DSA
> > > tags, as discussed in this thread.
> > >
> > > I'm suggesting we extend the kind of checking we already do to work
> > > around inevitable deficiencies of device parsers for tunnels to DSA
> > > tags.
> >
> > Sorry, I'm very tired and I probably don't understand what you're
> > saying, so excuse the extra clarification questions.
> >
> > The typical protocol checking that drivers with NETIF_F_HW_CSUM do seems
> > to be based on vlan_get_protocol()/skb->protocol/skb_network_header()/
> > skb_transport_header() values, all of which make DSA invisible. So they
> > don't work if the underlying hardware really doesn't like seeing an
> > unexpected DSA header.
> >
> > When you say "I'm suggesting we extend the kind of checking we already do",
> > do you mean we should modify the likes of e1000e and igb such that, if
> > they're ever used as DSA masters, they do a full header parse of the
> > packet (struct ethhdr :: h_proto, check if VLAN, struct iphdr/ipv6hdr,
> > etc.) instead of the current logic?
>
> That was my thinking, yes. The exact amount of work depends on the
> driver, I believe that more recent Intel parts (igb, ixgbe and newer)
> pass a L3 offset to the HW. They treat L2 as opaque, ergo no patches
> needed. At a glance e1000e passes the full skb_checksum_start_offset()
> to HW, so likely even better.

Ah, right, I missed that. I agree that a driver that uses
skb->csum_start is very likely to work unmodified with DSA headers
(not trailers). I didn't notice this in e1000 because I was just
searching for csum_start.

> It's only drivers for devices which actually want to parse the Ethertype
> that would need extra checks. (Coincidentally such devices can't support
> MPLS given the lack of L3 indication in the frame.)
>
> > It will be pretty convoluted unless
> > we have some helper. Because if I follow through, for a DSA-tagged IP
> > packet on xmit, skb->protocol is certainly htons(ETH_P_IP):
> >
> > ntohs(skb->protocol) = 0x800, csum_offset = 16, csum_start = 280, skb_checksum_start_offset = 54, skb->network_header = 260, skb_network_header_len = 20
> >
> > skb_dump output:
> > skb len=94 headroom=226 headlen=94 tailroom=384
> > mac=(226,34) net=(260,20) trans=280
> > shinfo(txflags=0 nr_frags=0 gso(size=0 type=1 segs=1))
> > csum(0x100118 ip_summed=3 complete_sw=0 valid=0 level=0)
> > hash(0x7710ee84 sw=0 l4=1) proto=0x0800 pkttype=0 iif=0
> > dev name=eno2 feat=0x00020100001149a9
> > sk family=2 type=1 proto=6
> > skb headroom: 00000000: 6c 00 03 02 64 65 76 00 fe ed ca fe 28 00 00 00
> > ...(junk)...
> > skb headroom: 000000e0: 5f 43
> >                         20 byte DSA tag
> >                         |
> >                         v
> > skb linear:   00000000: 88 80 00 0a 80 00 00 00 00 00 00 00 08 00 30 00
> >                                     skb_mac_header()
> >                                     |
> >                                     v
> > skb linear:   00000010: 00 00 00 00 68 05 ca 92 af 20 00 04 9f 05 f6 28
> >                               skb_network_header()
> >                               |
> >                               v
> > skb linear:   00000020: 08 00 45 00 00 3c 26 47 40 00 40 06 00 49 0a 00
> >                                           skb_checksum_start_offset
> >                                           |
> >                                           |                       csum_offset
> >                                           v                       v
> > skb linear:   00000030: 00 2c 0a 00 00 01 b6 08 14 51 11 1f 91 4f 00 00
> > skb linear:   00000040: 00 00 a0 02 fa f0 14 5b 00 00 02 04 05 b4 04 02
> > skb linear:   00000050: 08 0a 2e 00 e5 b8 00 00 00 00 01 03 03 07
>
> Oof, so in this case the DSA tag is _before_ the skb_mac_header()?
> Or the prepend is supposed to be parsable as a Ethernet header?
> Seems like any device that can do csum over this packet must already
> use L3/L4 offsets or have explicit knowledge of DSA, right?

I'm sorry, there's a mistake, skb_mac_header() points to the DSA tag
here (and skb_mac_header_len is 34), I wanted to say "real MAC header"
but failed to do so. This case shouldn't pose any special problems.

> > I don't know, I just don't expect that non-DSA users of those drivers
> > will be very happy about such changes. Do these existing protocol
> > checking schemes qualify as buggy?
>
> Unfortunate reality of the checksum offloads is that most drivers for
> devices which parse on Tx are buggy, it's more of a question of whether
> anyone tried to use an unsupported protocol stack :( Recent example
> that comes to mind is 1698d600b361 ("bnxt_en: Implement
> .ndo_features_check().").

Nice hook this ndo_features_check! In my reading of validate_xmit_skb()
I went right past it.

> > If this is the convention that we want to enforce, then I can't really
> > help Luiz with fixing the OpenWRT mtk_eth_soc.c - he'll have to figure
> > out a way to parse the packets for which his hardware will accept the
> > checksumming offload, and call skb_checksum_help() otherwise.
> >
> > > We can come up with various schemes of expressing capabilities
> > > between underlying driver and tag driver. I'm not aware of similar
> > > out-of-band schemes existing today so it'd be "DSA doing it's own
> > > thing", which does not seem great.
> >
> > It at least seems less complex to me, and less checking in the fast path
> > if I understand everything that's been said correctly.
>
> I understand, I'm primarily trying to share some context and prior work.
> I don't mean to nack all other approaches.
>
> I believe writing a parser matching the device behavior would be easier
> for a driver author than interpreting the runes of our csum offload API
> and getting thru the thicket of all the bits. If that's not the case my
> argument is likely defeated.

Ok, writing a parser might be needed if the DSA master is going, for
some reason, to support TX checksum offloading with some DSA headers but
not with others.

If that is not the case, and that Ethernet controller simply doesn't
support TX checksumming unless it's the plain old Ethernet {+ VLAN} +
IP/IPv6 + TCP/UDP, then this blanket patch below should fix the problem
almost elegantly, and parsing is a useless complication (warning, not
even compile-tested!):

-----------------------------[ cut here ]-----------------------------
From 5ef3d3cd8441d756933558212f518f48754c64d9 Mon Sep 17 00:00:00 2001
From: Vladimir Oltean <vladimir.oltean@nxp.com>
Date: Tue, 25 Jan 2022 00:16:57 +0200
Subject: [PATCH] ramips: ethernet: ralink: disable TX checksumming on DSA
 masters

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 .../files/drivers/net/ethernet/ralink/mtk_eth_soc.c  | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
index e07e5ed5a8f8..6ed9bc5942fd 100644
--- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
+++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
@@ -31,6 +31,7 @@
 #include <linux/io.h>
 #include <linux/bug.h>
 #include <linux/netfilter.h>
+#include <net/dsa.h>
 #include <net/netfilter/nf_flow_table.h>
 #include <linux/of_gpio.h>
 #include <linux/gpio.h>
@@ -1497,6 +1498,16 @@ static int fe_change_mtu(struct net_device *dev, int new_mtu)
 	return fe_open(dev);
 }
 
+static netdev_features_t fe_features_check(struct sk_buff *skb,
+					   struct net_device *dev,
+					   netdev_features_t features)
+{
+	if (netdev_uses_dsa(dev))
+		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+
+	return features;
+}
+
 static const struct net_device_ops fe_netdev_ops = {
 	.ndo_init		= fe_init,
 	.ndo_uninit		= fe_uninit,
@@ -1514,6 +1525,7 @@ static const struct net_device_ops fe_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= fe_poll_controller,
 #endif
+	.ndo_features_check	= fe_features_check,
 };
 
 static void fe_reset_pending(struct fe_priv *priv)
-----------------------------[ cut here ]-----------------------------

This is essentially what Florian said ages ago, it just took me a very
long time to process. I guess what hadn't fully clicked in my head is
that the TX checksumming offload being functional is more a matter of
telling the hardware what are the L3 and L4 offsets, and the csum_offset,
rather than it requiring any particular understanding of the DSA header.
In turn, it means that for "nice" Ethernet controller implementations
where that is the case, it would be actively detrimential to add a new
.ndo_get_dsa_features() or something like that - because such a driver
would report that it supports all DSA header-type formats (trailers are
still broken as long as there isn't a csum_end). And keeping that kind
of driver in sync with all DSA protocols that appear will become a
repetitive task.

So crisis averted, I guess?
Thanks a lot to both of you for the patient explanations!
I retract my proposal for a new ndo and also suggest that the DSA master
driver takes care to not leave as zero a TX checksum it can't offload.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 22:30                                                         ` Vladimir Oltean
@ 2022-01-25  7:15                                                           ` Luiz Angelo Daros de Luca
  2022-01-25  9:47                                                             ` Vladimir Oltean
  2022-01-25  9:44                                                           ` Arınç ÜNAL
  1 sibling, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-25  7:15 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Jakub Kicinski, Florian Fainelli, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal

Wow... that's a lot to digest.

> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  .../files/drivers/net/ethernet/ralink/mtk_eth_soc.c  | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
> index e07e5ed5a8f8..6ed9bc5942fd 100644
> --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
> +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
> @@ -31,6 +31,7 @@
>  #include <linux/io.h>
>  #include <linux/bug.h>
>  #include <linux/netfilter.h>
> +#include <net/dsa.h>
>  #include <net/netfilter/nf_flow_table.h>
>  #include <linux/of_gpio.h>
>  #include <linux/gpio.h>
> @@ -1497,6 +1498,16 @@ static int fe_change_mtu(struct net_device *dev, int new_mtu)
>         return fe_open(dev);
>  }
>
> +static netdev_features_t fe_features_check(struct sk_buff *skb,
> +                                          struct net_device *dev,
> +                                          netdev_features_t features)
> +{
> +       if (netdev_uses_dsa(dev))
> +               features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
> +
> +       return features;
> +}
> +
>  static const struct net_device_ops fe_netdev_ops = {
>         .ndo_init               = fe_init,
>         .ndo_uninit             = fe_uninit,
> @@ -1514,6 +1525,7 @@ static const struct net_device_ops fe_netdev_ops = {
>  #ifdef CONFIG_NET_POLL_CONTROLLER
>         .ndo_poll_controller    = fe_poll_controller,
>  #endif
> +       .ndo_features_check     = fe_features_check,
>  };
>
>  static void fe_reset_pending(struct fe_priv *priv)

Thanks, Vladimir. I'll try that patch soon. However, it will never be
accepted even in OpenWrt as is because it does offload its own
proprietary tag.
I might need to add another if like:

> +       if (netdev_uses_dsa(dev))
> +               if (skb->???->proto_in_use != DSA_TAG_PROTO_MTK)
> +                      features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);

I think it would need to save the used tag in some form of an oob
signal (as Florian suggested). In that case, even the
netdev_uses_dsa() test can be removed as a skb with an oob tag signal
is surely from a dsa device.

Anyway, even with existing offload code not doing exactly what they
should, they normally work given a normal device usage. The strange
part is that DSA assumes those features, copied from master to slave,
will still be the same even after a tag was injected into the packet.

Sorry for my arrogance being a newbie but I think the place to fix the
problem is still in slave feature list. It is better than having the
kernel repeat the test for every single packet. And nobody will be
willing to add extra overhead to a working code just because DSA needs
it. It is easier to add a new function that does not touch existing
code paths.

I believe that those drivers with NETIF_F_HW_CSUM are fine for every
type of DSA, right? So, just those with NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM set needs to be adjusted. A fully implemented
ndo_features_check() will work but improving it for every driver will
add extra code/overhead for all packets, used with DSA or not. And
that extra code needed for DSA will either always keep or remove the
same features for a given slave.

I imagine that for NETIF_F_CSUM_MASK and NETIF_F_GSO_MASK, it would
not be too hard to build a set of candidate packets to test if that
feature is still valid after the tag was added. With that assumption,
a new ndo_features_check_offline(), similar to ndo_features_check()
but not be called by netif_skb_features, will test each candidate
during slave setup. If the check disagrees after the tag was added,
that feature should be disabled for that slave. Something like:

slave->features = master->features;
if (slave->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))
    if (dev->netdev_ops->ndo_features_check_offline)
        foreach (test_candidate)
            tagged_test_candidate = add_tag (test_candidate, slave->tag);

            slave->features &=
~(master->netdev_ops->ndo_features_check_offline(test_candidate,
master, slave->features) ^

master->netdev_ops->ndo_features_check_offline(tagged_test_candidate,
master, slave->features)
    else
        slave->features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK)

The only drivers that would have performance regression while used as
DSA master ports are those:
1) that does not have NETIF_F_HW_CSUM set
2) but could still offload after a particular DSA tag was added (when
tag vendor and HW matches)
3) and still didn't implement the new ndo_features_check_offline().

ndo_features_check_offline() would not be too much different from what
Vladmir suggested for the out-of-tree mtk_eth_soc driver.

ndo_features_check_offline(sbk, dev, features) {
    switch (sbk->oob->tag) {
    case SUPPORTED_TAG_1:
    case SUPPORTED_TAG_2:
    case SUPPORTED_TAG_3:
    case NO_TAG:
        break;
    default:
        features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
    }

    if (dev->netdev_ops->ndo_features_check)
         features &= dev->netdev_ops->ndo_features_check(skb, dev, features);

    /* some more test if needed*/

    return features;
}

If used exclusively by DSA, ndo_features_check_offline could also be
called ndo_dsa_features_check (or any better name than
ndo_features_check_offline). That is not far away from what Vladmir
suggested (and later retracted) in the first place.

Regards,

Luiz

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-24 22:30                                                         ` Vladimir Oltean
  2022-01-25  7:15                                                           ` Luiz Angelo Daros de Luca
@ 2022-01-25  9:44                                                           ` Arınç ÜNAL
  1 sibling, 0 replies; 88+ messages in thread
From: Arınç ÜNAL @ 2022-01-25  9:44 UTC (permalink / raw)
  To: Vladimir Oltean, Jakub Kicinski
  Cc: Florian Fainelli, Luiz Angelo Daros de Luca, Andrew Lunn,
	Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	vivien.didelot

On 25/01/2022 01:30, Vladimir Oltean wrote:
> On Mon, Jan 24, 2022 at 01:42:42PM -0800, Jakub Kicinski wrote:
>> On Mon, 24 Jan 2022 22:56:07 +0200 Vladimir Oltean wrote:
>>> On Mon, Jan 24, 2022 at 11:38:12AM -0800, Jakub Kicinski wrote:
>>>> On Mon, 24 Jan 2022 21:08:45 +0200 Vladimir Oltean wrote:
>>>>> So before we declare that any given Ethernet driver is buggy for declaring
>>>>> NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and not checking that skb->csum_start
>>>>> points where it expects it to (taking into consideration potential VLAN
>>>>> headers, IPv6 extension headers),
>>>>
>>>> Extension headers are explicitly not supported by NETIF_F_IPV6_CSUM.
>>>>
>>>> IIRC Tom's hope was to delete NETIF_F_IP*_CSUM completely once all
>>>> drivers are converted to parsing and therefore can use NETIF_F_HW_CSUM.
>>>
>>> IIUC, NETIF_F_IP*_CSUM vs NETIF_F_HW_CSUM doesn't make that big of a
>>> difference in terms of what the driver should check for, if the hardware
>>> checksum offload engine can't directly be given the csum_start and
>>> csum_offset, wherever they may be.
>>>
>>>>> is there any driver that _does_ perform these checks correctly, that
>>>>> could be used as an example?
>>>>
>>>> I don't think so. Let me put it this way - my understanding is that up
>>>> until now we had been using the vlan_features, mpls_features etc to
>>>> perform L2/L2.5/below-IP feature stripping. This scales poorly to DSA
>>>> tags, as discussed in this thread.
>>>>
>>>> I'm suggesting we extend the kind of checking we already do to work
>>>> around inevitable deficiencies of device parsers for tunnels to DSA
>>>> tags.
>>>
>>> Sorry, I'm very tired and I probably don't understand what you're
>>> saying, so excuse the extra clarification questions.
>>>
>>> The typical protocol checking that drivers with NETIF_F_HW_CSUM do seems
>>> to be based on vlan_get_protocol()/skb->protocol/skb_network_header()/
>>> skb_transport_header() values, all of which make DSA invisible. So they
>>> don't work if the underlying hardware really doesn't like seeing an
>>> unexpected DSA header.
>>>
>>> When you say "I'm suggesting we extend the kind of checking we already do",
>>> do you mean we should modify the likes of e1000e and igb such that, if
>>> they're ever used as DSA masters, they do a full header parse of the
>>> packet (struct ethhdr :: h_proto, check if VLAN, struct iphdr/ipv6hdr,
>>> etc.) instead of the current logic?
>>
>> That was my thinking, yes. The exact amount of work depends on the
>> driver, I believe that more recent Intel parts (igb, ixgbe and newer)
>> pass a L3 offset to the HW. They treat L2 as opaque, ergo no patches
>> needed. At a glance e1000e passes the full skb_checksum_start_offset()
>> to HW, so likely even better.
> 
> Ah, right, I missed that. I agree that a driver that uses
> skb->csum_start is very likely to work unmodified with DSA headers
> (not trailers). I didn't notice this in e1000 because I was just
> searching for csum_start.
> 
>> It's only drivers for devices which actually want to parse the Ethertype
>> that would need extra checks. (Coincidentally such devices can't support
>> MPLS given the lack of L3 indication in the frame.)
>>
>>> It will be pretty convoluted unless
>>> we have some helper. Because if I follow through, for a DSA-tagged IP
>>> packet on xmit, skb->protocol is certainly htons(ETH_P_IP):
>>>
>>> ntohs(skb->protocol) = 0x800, csum_offset = 16, csum_start = 280, skb_checksum_start_offset = 54, skb->network_header = 260, skb_network_header_len = 20
>>>
>>> skb_dump output:
>>> skb len=94 headroom=226 headlen=94 tailroom=384
>>> mac=(226,34) net=(260,20) trans=280
>>> shinfo(txflags=0 nr_frags=0 gso(size=0 type=1 segs=1))
>>> csum(0x100118 ip_summed=3 complete_sw=0 valid=0 level=0)
>>> hash(0x7710ee84 sw=0 l4=1) proto=0x0800 pkttype=0 iif=0
>>> dev name=eno2 feat=0x00020100001149a9
>>> sk family=2 type=1 proto=6
>>> skb headroom: 00000000: 6c 00 03 02 64 65 76 00 fe ed ca fe 28 00 00 00
>>> ...(junk)...
>>> skb headroom: 000000e0: 5f 43
>>>                          20 byte DSA tag
>>>                          |
>>>                          v
>>> skb linear:   00000000: 88 80 00 0a 80 00 00 00 00 00 00 00 08 00 30 00
>>>                                      skb_mac_header()
>>>                                      |
>>>                                      v
>>> skb linear:   00000010: 00 00 00 00 68 05 ca 92 af 20 00 04 9f 05 f6 28
>>>                                skb_network_header()
>>>                                |
>>>                                v
>>> skb linear:   00000020: 08 00 45 00 00 3c 26 47 40 00 40 06 00 49 0a 00
>>>                                            skb_checksum_start_offset
>>>                                            |
>>>                                            |                       csum_offset
>>>                                            v                       v
>>> skb linear:   00000030: 00 2c 0a 00 00 01 b6 08 14 51 11 1f 91 4f 00 00
>>> skb linear:   00000040: 00 00 a0 02 fa f0 14 5b 00 00 02 04 05 b4 04 02
>>> skb linear:   00000050: 08 0a 2e 00 e5 b8 00 00 00 00 01 03 03 07
>>
>> Oof, so in this case the DSA tag is _before_ the skb_mac_header()?
>> Or the prepend is supposed to be parsable as a Ethernet header?
>> Seems like any device that can do csum over this packet must already
>> use L3/L4 offsets or have explicit knowledge of DSA, right?
> 
> I'm sorry, there's a mistake, skb_mac_header() points to the DSA tag
> here (and skb_mac_header_len is 34), I wanted to say "real MAC header"
> but failed to do so. This case shouldn't pose any special problems.
> 
>>> I don't know, I just don't expect that non-DSA users of those drivers
>>> will be very happy about such changes. Do these existing protocol
>>> checking schemes qualify as buggy?
>>
>> Unfortunate reality of the checksum offloads is that most drivers for
>> devices which parse on Tx are buggy, it's more of a question of whether
>> anyone tried to use an unsupported protocol stack :( Recent example
>> that comes to mind is 1698d600b361 ("bnxt_en: Implement
>> .ndo_features_check().").
> 
> Nice hook this ndo_features_check! In my reading of validate_xmit_skb()
> I went right past it.
> 
>>> If this is the convention that we want to enforce, then I can't really
>>> help Luiz with fixing the OpenWRT mtk_eth_soc.c - he'll have to figure
>>> out a way to parse the packets for which his hardware will accept the
>>> checksumming offload, and call skb_checksum_help() otherwise.
>>>
>>>> We can come up with various schemes of expressing capabilities
>>>> between underlying driver and tag driver. I'm not aware of similar
>>>> out-of-band schemes existing today so it'd be "DSA doing it's own
>>>> thing", which does not seem great.
>>>
>>> It at least seems less complex to me, and less checking in the fast path
>>> if I understand everything that's been said correctly.
>>
>> I understand, I'm primarily trying to share some context and prior work.
>> I don't mean to nack all other approaches.
>>
>> I believe writing a parser matching the device behavior would be easier
>> for a driver author than interpreting the runes of our csum offload API
>> and getting thru the thicket of all the bits. If that's not the case my
>> argument is likely defeated.
> 
> Ok, writing a parser might be needed if the DSA master is going, for
> some reason, to support TX checksum offloading with some DSA headers but
> not with others.
> 
> If that is not the case, and that Ethernet controller simply doesn't
> support TX checksumming unless it's the plain old Ethernet {+ VLAN} +
> IP/IPv6 + TCP/UDP, then this blanket patch below should fix the problem
> almost elegantly, and parsing is a useless complication (warning, not
> even compile-tested!):

I tried it on the upstream mtk_eth_soc on an mt7621a board with an 
rtl8367s switch connected to the 2nd GMAC of the SoC running 5.17-rc1.

Although "ethtool --show-offload eth1" does not show anything different, 
I can now ssh to the device (only way that came into my mind to quickly 
check TCP traffic).

--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1986,6 +1986,16 @@ static int mtk_hwlro_get_fdir_all(struct
  	return 0;
  }

+static netdev_features_t fe_features_check(struct sk_buff *skb,
+					   struct net_device *dev,
+					   netdev_features_t features)
+{
+	if (netdev_uses_dsa(dev))
+		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+
+	return features;
+}
+
  static netdev_features_t mtk_fix_features(struct net_device *dev,
  					  netdev_features_t features)
  {
@@ -2906,6 +2916,7 @@ static const struct net_device_ops mtk_n
  #ifdef CONFIG_NET_POLL_CONTROLLER
  	.ndo_poll_controller	= mtk_poll_controller,
  #endif
+	.ndo_features_check	= fe_features_check,
  	.ndo_setup_tc		= mtk_eth_setup_tc,
  };


> 
> -----------------------------[ cut here ]-----------------------------
>  From 5ef3d3cd8441d756933558212f518f48754c64d9 Mon Sep 17 00:00:00 2001
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
> Date: Tue, 25 Jan 2022 00:16:57 +0200
> Subject: [PATCH] ramips: ethernet: ralink: disable TX checksumming on DSA
>   masters
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>   .../files/drivers/net/ethernet/ralink/mtk_eth_soc.c  | 12 ++++++++++++
>   1 file changed, 12 insertions(+)
> 
> diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
> index e07e5ed5a8f8..6ed9bc5942fd 100644
> --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
> +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
> @@ -31,6 +31,7 @@
>   #include <linux/io.h>
>   #include <linux/bug.h>
>   #include <linux/netfilter.h>
> +#include <net/dsa.h>
>   #include <net/netfilter/nf_flow_table.h>
>   #include <linux/of_gpio.h>
>   #include <linux/gpio.h>
> @@ -1497,6 +1498,16 @@ static int fe_change_mtu(struct net_device *dev, int new_mtu)
>   	return fe_open(dev);
>   }
>   
> +static netdev_features_t fe_features_check(struct sk_buff *skb,
> +					   struct net_device *dev,
> +					   netdev_features_t features)
> +{
> +	if (netdev_uses_dsa(dev))
> +		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
> +
> +	return features;
> +}
> +
>   static const struct net_device_ops fe_netdev_ops = {
>   	.ndo_init		= fe_init,
>   	.ndo_uninit		= fe_uninit,
> @@ -1514,6 +1525,7 @@ static const struct net_device_ops fe_netdev_ops = {
>   #ifdef CONFIG_NET_POLL_CONTROLLER
>   	.ndo_poll_controller	= fe_poll_controller,
>   #endif
> +	.ndo_features_check	= fe_features_check,
>   };
>   
>   static void fe_reset_pending(struct fe_priv *priv)
> -----------------------------[ cut here ]-----------------------------
> 
> This is essentially what Florian said ages ago, it just took me a very
> long time to process. I guess what hadn't fully clicked in my head is
> that the TX checksumming offload being functional is more a matter of
> telling the hardware what are the L3 and L4 offsets, and the csum_offset,
> rather than it requiring any particular understanding of the DSA header.
> In turn, it means that for "nice" Ethernet controller implementations
> where that is the case, it would be actively detrimential to add a new
> .ndo_get_dsa_features() or something like that - because such a driver
> would report that it supports all DSA header-type formats (trailers are
> still broken as long as there isn't a csum_end). And keeping that kind
> of driver in sync with all DSA protocols that appear will become a
> repetitive task.
> 
> So crisis averted, I guess?
> Thanks a lot to both of you for the patient explanations!
> I retract my proposal for a new ndo and also suggest that the DSA master
> driver takes care to not leave as zero a TX checksum it can't offload.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-25  7:15                                                           ` Luiz Angelo Daros de Luca
@ 2022-01-25  9:47                                                             ` Vladimir Oltean
  2022-01-25 22:29                                                               ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 88+ messages in thread
From: Vladimir Oltean @ 2022-01-25  9:47 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Jakub Kicinski, Florian Fainelli, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal

Hi Luiz,

On Tue, Jan 25, 2022 at 04:15:23AM -0300, Luiz Angelo Daros de Luca wrote:
> I believe that those drivers with NETIF_F_HW_CSUM are fine for every
> type of DSA, right? So, just those with NETIF_F_IP_CSUM |
> NETIF_F_IPV6_CSUM set needs to be adjusted. A fully implemented
> ndo_features_check() will work but improving it for every driver will
> add extra code/overhead for all packets, used with DSA or not. And
> that extra code needed for DSA will either always keep or remove the
> same features for a given slave.

Could you implement a prototype of packet parsing in ndo_features_check,
which checks for the known DSA EtherType and clears the offload bit for
unsupported packets, and do some performance testing before and after,
to lean the argument in your favor with some numbers? I've no problem if
you test for the worst case, i.e. line rate with small UDP packets
encapsulated with the known (offload-capable) DSA tag format, where
there is little benefit for offloading TX checksumming.

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-25  9:47                                                             ` Vladimir Oltean
@ 2022-01-25 22:29                                                               ` Luiz Angelo Daros de Luca
  2022-01-25 23:56                                                                 ` Florian Fainelli
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-25 22:29 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Jakub Kicinski, Florian Fainelli, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal

> Could you implement a prototype of packet parsing in ndo_features_check,
> which checks for the known DSA EtherType and clears the offload bit for
> unsupported packets, and do some performance testing before and after,
> to lean the argument in your favor with some numbers? I've no problem if
> you test for the worst case, i.e. line rate with small UDP packets
> encapsulated with the known (offload-capable) DSA tag format, where
> there is little benefit for offloading TX checksumming.

There is no way to tell if a packet has a DSA tag only by parsing its
content. For Realtek and Marvel EDSA, there is a distinct ethertype
(although Marvel EDSA uses a non-registered number) that drivers can
check. For others, specially those that add the tag before the
ethernet header or after the payload, it might not have a magic
number. It is impossible to securely identify if and which DSA is in
use for some DSA tags from the packet alone. This is also the case for
mediatek. Although it places its tag just before ethertype (like
Realtek and Marvel), there is no magic number. It needs some context
to know what type of DSA was applied.

skb_buf today knows nothing about the added DSA tag. Although
net_device does know if it is a master port in a dsa tree, and it has
a default dsa tag, with multiple switches using different tags, it
cannot tell which dsa tag was added to that packet.
That is the information I need to test if that tag is supported or not
by this drive.

I believe once an offload HW can digest a dsa tag, it might support
the same type of protocols with or without the tag.
In the end, what really matters is if a driver supports a specific dsa tag.

Wouldn't it be much easier to have a dedicated optional
ndo_dsa_tag_supported()? It would be only needed for those drivers
that still use NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and only those that
can digest a tag.

Regards,

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-25 22:29                                                               ` Luiz Angelo Daros de Luca
@ 2022-01-25 23:56                                                                 ` Florian Fainelli
  2022-01-26 22:49                                                                   ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 88+ messages in thread
From: Florian Fainelli @ 2022-01-25 23:56 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, Vladimir Oltean
  Cc: Jakub Kicinski, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal



On 1/25/2022 2:29 PM, Luiz Angelo Daros de Luca wrote:
>> Could you implement a prototype of packet parsing in ndo_features_check,
>> which checks for the known DSA EtherType and clears the offload bit for
>> unsupported packets, and do some performance testing before and after,
>> to lean the argument in your favor with some numbers? I've no problem if
>> you test for the worst case, i.e. line rate with small UDP packets
>> encapsulated with the known (offload-capable) DSA tag format, where
>> there is little benefit for offloading TX checksumming.
> 
> There is no way to tell if a packet has a DSA tag only by parsing its
> content. For Realtek and Marvel EDSA, there is a distinct ethertype
> (although Marvel EDSA uses a non-registered number) that drivers can
> check. For others, specially those that add the tag before the
> ethernet header or after the payload, it might not have a magic
> number. It is impossible to securely identify if and which DSA is in
> use for some DSA tags from the packet alone. This is also the case for
> mediatek. Although it places its tag just before ethertype (like
> Realtek and Marvel), there is no magic number. It needs some context
> to know what type of DSA was applied.

Looking at mtk_eth_soc.h TX_DMA_CHKSUM is 0x7 << 29 so we set 3 bits 
there, which makes me think that either we defined too many bits, or 
some of those bits have a compounded meaning. The rest of the bits do 
not seem to be defined, so maybe there is a programmable offset where to 
calculate the checksum from and deposit it. Is there a public 
programmable manual?

> 
> skb_buf today knows nothing about the added DSA tag. Although
> net_device does know if it is a master port in a dsa tree, and it has
> a default dsa tag, with multiple switches using different tags, it
> cannot tell which dsa tag was added to that packet.
> That is the information I need to test if that tag is supported or not
> by this drive.
> 
> I believe once an offload HW can digest a dsa tag, it might support
> the same type of protocols with or without the tag.
> In the end, what really matters is if a driver supports a specific dsa tag.

To be honest, I am not sure if we need to know about the specific 
details of the tag like is it Realtek, Broadcom, Mediatek, QCA, more 
than knowing whether the L3/L4 offsets will be at "expected" locations. 
By that I mean, located at 14 bytes from the start of the frame for IP 
without VLAN , and 18 bytes with VLAN, did we "stack" switch tags on top 
of another thus moving by another X bytes etc.

> 
> Wouldn't it be much easier to have a dedicated optional
> ndo_dsa_tag_supported()? It would be only needed for those drivers
> that still use NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and only those that
> can digest a tag.

I don't think we need to invent something new, we "just" need to tell 
the DSA conduit interface what type of switch tagger it is attached to 
and where it is in the Ethernet frame. Once we do that, the DSA conduit 
ought to be able to strip out features statically, or dynamically via 
ndo_features_check().
-- 
Florian

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-25 23:56                                                                 ` Florian Fainelli
@ 2022-01-26 22:49                                                                   ` Luiz Angelo Daros de Luca
  0 siblings, 0 replies; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-26 22:49 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Vladimir Oltean, Jakub Kicinski, Andrew Lunn, Frank Wunderlich,
	Alvin Šipraga, netdev, linus.walleij, vivien.didelot,
	arinc.unal

> On 1/25/2022 2:29 PM, Luiz Angelo Daros de Luca wrote:
> >> Could you implement a prototype of packet parsing in ndo_features_check,
> >> which checks for the known DSA EtherType and clears the offload bit for
> >> unsupported packets, and do some performance testing before and after,
> >> to lean the argument in your favor with some numbers? I've no problem if
> >> you test for the worst case, i.e. line rate with small UDP packets
> >> encapsulated with the known (offload-capable) DSA tag format, where
> >> there is little benefit for offloading TX checksumming.
> >
> > There is no way to tell if a packet has a DSA tag only by parsing its
> > content. For Realtek and Marvel EDSA, there is a distinct ethertype
> > (although Marvel EDSA uses a non-registered number) that drivers can
> > check. For others, specially those that add the tag before the
> > ethernet header or after the payload, it might not have a magic
> > number. It is impossible to securely identify if and which DSA is in
> > use for some DSA tags from the packet alone. This is also the case for
> > mediatek. Although it places its tag just before ethertype (like
> > Realtek and Marvel), there is no magic number. It needs some context
> > to know what type of DSA was applied.
>
> Looking at mtk_eth_soc.h TX_DMA_CHKSUM is 0x7 << 29 so we set 3 bits
> there, which makes me think that either we defined too many bits, or
> some of those bits have a compounded meaning. The rest of the bits do
> not seem to be defined, so maybe there is a programmable offset where to
> calculate the checksum from and deposit it. Is there a public
> programmable manual?

Thanks Florian, I'm using this that I googled ;-)

http://download.villagetelco.org/hardware/MT7620/MT7620_ProgrammingGuide.pdf
page 206?

It says:

DWORD0 31:0 SDP0 Segment Data Pointer0

DWORD1 31 DDONE DMA Done: Indicates DMA has transferred the segment
pointed to by this Tx
descriptor.
30 LS0 Last Segment0: Data pointed to by SDP0 is the last segment.
29:16 SDL0 Segment Data Length0: Segment data length for the data
pointed to by SDP0.
15 BURST When set, the scheduler cannot hand over to other Tx queues.
Should not transmit
the next packet.
14 LS1 Last Segment1: Data pointed to by SDP1 is the last segment.
13:0 SDL1 Segment Data Length1: Segment data length for the data
pointed to by SDP1.

DWORD2
31:0 SDP1 Segment Data Pointer1

DWORD3 (TXINFO)
31 ICO IP checksum offload enable
30 UCO UDP checksum offload enable
23 TCO TCP checksum offload enable
28 TSO TCP segmentation offload
27:20 FP_BMAP Forced destination port on GSW
bit[0:5]: Ports 0 to 5
bit[6]: CPU
bit[7]: PPE
FP_BMAP = 0: routing by DA
19:15 UDF User defined field
14 0 Reserved
13 0 Reserved
12 INSP Insert PPPoE header
11:8 SIDX PPPoE session index
7 INSV Insert VLAN tag
6:4 VPRI VLAN priority tag to be inserted
3:0 VIDX VLAN ID index

It looks like st->txd.txd4 is DWORD3. There is nothing too useful for
pointing L3 headers. The remaining bits are about vlan and pppoe
offload (and forcing the forwarding port).
There are those two segment 0 and 1 data pointers and their size in
txd{1,2,3} that I don't understand how it works (yet), but I guess
that is not what we are looking for.

There are also some offload settings at CDMA (page 217), but it is
simply an enable bit. (And I don't know what CDMA or GDMA are :-/).

> > skb_buf today knows nothing about the added DSA tag. Although
> > net_device does know if it is a master port in a dsa tree, and it has
> > a default dsa tag, with multiple switches using different tags, it
> > cannot tell which dsa tag was added to that packet.
> > That is the information I need to test if that tag is supported or not
> > by this drive.
> >
> > I believe once an offload HW can digest a dsa tag, it might support
> > the same type of protocols with or without the tag.
> > In the end, what really matters is if a driver supports a specific dsa tag.
>
> To be honest, I am not sure if we need to know about the specific
> details of the tag like is it Realtek, Broadcom, Mediatek, QCA, more
> than knowing whether the L3/L4 offsets will be at "expected" locations.
> By that I mean, located at 14 bytes from the start of the frame for IP
> without VLAN , and 18 bytes with VLAN, did we "stack" switch tags on top
> of another thus moving by another X bytes etc.

I would be perfect if the HW supported that (and I'm afraid it does not).

>
>
> >
> > Wouldn't it be much easier to have a dedicated optional
> > ndo_dsa_tag_supported()? It would be only needed for those drivers
> > that still use NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM and only those that
> > can digest a tag.
>
> I don't think we need to invent something new, we "just" need to tell
> the DSA conduit interface what type of switch tagger it is attached to
> and where it is in the Ethernet frame. Once we do that, the DSA conduit
> ought to be able to strip out features statically, or dynamically via
> ndo_features_check().

Is it a 1:1 relation between tags and the DSA conduit interface (I'm
guessing this is the CPU port Ethernet device)?
Anyway, this mediatek does not seem to support multiple tags. This
patch might disable offloading when it is using any DSA tags but the
mediatek one.
I never used the NONE tag but maybe I should also exempt that tag from
disabling offloading.

diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
index 0ae520183b..8eb5dd8721 100644
--- a/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
+++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c
@@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/bug.h>
#include <linux/netfilter.h>
+#include <net/dsa.h>
#include <net/netfilter/nf_flow_table.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
@@ -788,6 +789,27 @@ err_out:
       return -1;
}

+static netdev_features_t fe_features_check(struct sk_buff *skb,
+                                          struct net_device *dev,
+                                          netdev_features_t features)
+{
+       /* No point in doing any of this if neither checksum nor GSO are
+        * being requested for this frame. We can rule out both by just
+        * checking for CHECKSUM_PARTIAL
+        */
+       if (skb->ip_summed != CHECKSUM_PARTIAL)
+               return features;
+
+       if (netdev_uses_dsa(dev)) {
+               struct dsa_device_ops *tag_ops = dev->dsa_ptr->tag_ops;
+
+               if (tag_ops && (tag_ops->proto != DSA_TAG_PROTO_MTK))
+                       features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+       }
+
+       return features;
+}
+
static inline int fe_skb_padto(struct sk_buff *skb, struct fe_priv *priv)
{
       unsigned int len;
@@ -1523,6 +1545,7 @@ static const struct net_device_ops fe_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
       .ndo_poll_controller    = fe_poll_controller,
#endif
+       .ndo_features_check     = fe_features_check,
};

static void fe_reset_pending(struct fe_priv *priv)

However, I still feel odd to call a function for every single packet
when the return value is exclusively dependent on a state that will
change only when the CPU port joins or leaves the DSA switch (or when
tag is changed).

Regards,

Luiz

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

* Re: Re: Re: Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-18  4:58               ` Luiz Angelo Daros de Luca
  2022-01-18 10:13                 ` Alvin Šipraga
  2022-01-18 13:20                 ` Re: Re: " Andrew Lunn
@ 2022-01-30  1:54                 ` Luiz Angelo Daros de Luca
  2022-01-30  4:42                   ` Luiz Angelo Daros de Luca
  2 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-30  1:54 UTC (permalink / raw)
  To: Frank Wunderlich
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

> I suggested it might be checksum problem because I'm also affected. In
> my case, I have an mt7620a SoC connected to the rtl8367s switch. The
> OS offloads checksum to HW but the mt7620a cannot calculate the
> checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
> move the CPU tag to test if the mt7620a will then digest the frame
> correctly.

I implemented a new DSA tag (rtl8_4t, with "t" as in trailing) that
puts the DSA tag before the Ethernet CRC (the switch supports both).
With no tag in the mac layer, mediatek correctly calculated the ip
checksum. However, mediatek SoC included the extra bytes from the DSA
tag in the TCP checksum, even if they are after the ip length.

This is the packet leaving the OS:

0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
0030   fe 88 83 82 00 00 02 04 05 b4 04 02 08 0a 01 64
0040   fb 28 66 42 e0 79 01 03 03 03 88 99 04 00 00 20
0050   00 08

TCP checksum is at 0x0032 with 0x8382 is the tcp checksum
DSA Tag is at 0x4a with 8899040000200008

This is what arrived at the other end:

0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
0030   fe 88 c3 e8 00 00 02 04 05 b4 04 02 08 0a 01 64
0040   fb 28 66 42 e0 79 01 03 03 03

TCP checksum is 0xc3e8, but the correct one should be 0x50aa
If you calculate tcp checksum including 8899040000200008, you'll get exactly
0xc3e8 (I did the math).

So, If we use a trailing DSA tag, we can leave the IP checksum offloading on
and just turn off the TCP checksum offload. Is it worth it?

Is it still interesting to have the rtl8_4t merged?

Regards,

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

* Re: Re: Re: Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-30  1:54                 ` Re: Re: " Luiz Angelo Daros de Luca
@ 2022-01-30  4:42                   ` Luiz Angelo Daros de Luca
  2022-01-30 17:24                     ` Florian Fainelli
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-30  4:42 UTC (permalink / raw)
  To: Frank Wunderlich
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew,
	vivien.didelot, f.fainelli, olteanv, arinc.unal

> > I suggested it might be checksum problem because I'm also affected. In
> > my case, I have an mt7620a SoC connected to the rtl8367s switch. The
> > OS offloads checksum to HW but the mt7620a cannot calculate the
> > checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
> > move the CPU tag to test if the mt7620a will then digest the frame
> > correctly.
>
> I implemented a new DSA tag (rtl8_4t, with "t" as in trailing) that
> puts the DSA tag before the Ethernet CRC (the switch supports both).
> With no tag in the mac layer, mediatek correctly calculated the ip
> checksum. However, mediatek SoC included the extra bytes from the DSA
> tag in the TCP checksum, even if they are after the ip length.
>
> This is the packet leaving the OS:
>
> 0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
> 0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
> 0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
> 0030   fe 88 83 82 00 00 02 04 05 b4 04 02 08 0a 01 64
> 0040   fb 28 66 42 e0 79 01 03 03 03 88 99 04 00 00 20
> 0050   00 08
>
> TCP checksum is at 0x0032 with 0x8382 is the tcp checksum
> DSA Tag is at 0x4a with 8899040000200008
>
> This is what arrived at the other end:
>
> 0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
> 0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
> 0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
> 0030   fe 88 c3 e8 00 00 02 04 05 b4 04 02 08 0a 01 64
> 0040   fb 28 66 42 e0 79 01 03 03 03
>
> TCP checksum is 0xc3e8, but the correct one should be 0x50aa
> If you calculate tcp checksum including 8899040000200008, you'll get exactly
> 0xc3e8 (I did the math).
>
> So, If we use a trailing DSA tag, we can leave the IP checksum offloading on
> and just turn off the TCP checksum offload. Is it worth it?

No, IP checksum is always done in SW.

> Is it still interesting to have the rtl8_4t merged?

Maybe it is. It has uncovered a problem. The case of trailing tags
seems to be unsolvable even with csum_start. AFAIK, the driver must
cksum from "skb->csum_start up to the end". When the switch is using
an incompatible tag, we have:

slave(): my features copied from master tells me I can offload
checksum. Do nothing
tagger(): add tag to the end of skb
master(): Offloading HW, chksum from csum_start until the end,
including the added tag
switch(): remove the tag, forward to the network
remove_client(): I got a packet with a broken checksum.

ndo_features_check() will not help because, either in HW or SW, it is
expected to calculate the checksum up to the end. However, there is no
csum_end or csum_len. I don't know if HW offloading will support some
kind of csum_end but it would not be a problem in SW (considering
skb_checksum_help() is adapted to something like skb_checksum_trimmed
without the clone).

That amount of bytes to ignore at the end is a complex question: the
driver either needs some hint (like it happens with skb->csum_offset)
to know where transport payload ends or the taggers (or the dsa) must
save the amount of extra bytes (or which tags were added) in the
sbk_buff. With that info, the driver can check if HW will work with a
different csum_start / csum_end or if only a supported tag is in use.

In my case, using an incompatible tailing tag, I just made it work
hacking dsa and forcing slave interfaces to disable offloading. This
way, checksum is calculated before any tag is added and offloading is
skipped. But it is not a real solution.

Regards,

Luiz,

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-30  4:42                   ` Luiz Angelo Daros de Luca
@ 2022-01-30 17:24                     ` Florian Fainelli
  2022-01-31 17:26                       ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 88+ messages in thread
From: Florian Fainelli @ 2022-01-30 17:24 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca, Frank Wunderlich
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew,
	vivien.didelot, olteanv, arinc.unal



On 1/29/2022 8:42 PM, Luiz Angelo Daros de Luca wrote:
>>> I suggested it might be checksum problem because I'm also affected. In
>>> my case, I have an mt7620a SoC connected to the rtl8367s switch. The
>>> OS offloads checksum to HW but the mt7620a cannot calculate the
>>> checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
>>> move the CPU tag to test if the mt7620a will then digest the frame
>>> correctly.
>>
>> I implemented a new DSA tag (rtl8_4t, with "t" as in trailing) that
>> puts the DSA tag before the Ethernet CRC (the switch supports both).
>> With no tag in the mac layer, mediatek correctly calculated the ip
>> checksum. However, mediatek SoC included the extra bytes from the DSA
>> tag in the TCP checksum, even if they are after the ip length.
>>
>> This is the packet leaving the OS:
>>
>> 0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
>> 0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
>> 0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
>> 0030   fe 88 83 82 00 00 02 04 05 b4 04 02 08 0a 01 64
>> 0040   fb 28 66 42 e0 79 01 03 03 03 88 99 04 00 00 20
>> 0050   00 08
>>
>> TCP checksum is at 0x0032 with 0x8382 is the tcp checksum
>> DSA Tag is at 0x4a with 8899040000200008
>>
>> This is what arrived at the other end:
>>
>> 0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
>> 0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
>> 0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
>> 0030   fe 88 c3 e8 00 00 02 04 05 b4 04 02 08 0a 01 64
>> 0040   fb 28 66 42 e0 79 01 03 03 03
>>
>> TCP checksum is 0xc3e8, but the correct one should be 0x50aa
>> If you calculate tcp checksum including 8899040000200008, you'll get exactly
>> 0xc3e8 (I did the math).
>>
>> So, If we use a trailing DSA tag, we can leave the IP checksum offloading on
>> and just turn off the TCP checksum offload. Is it worth it?
> 
> No, IP checksum is always done in SW.
> 
>> Is it still interesting to have the rtl8_4t merged?
> 
> Maybe it is. It has uncovered a problem. The case of trailing tags
> seems to be unsolvable even with csum_start. AFAIK, the driver must
> cksum from "skb->csum_start up to the end". When the switch is using
> an incompatible tag, we have:
> 
> slave(): my features copied from master tells me I can offload
> checksum. Do nothing
> tagger(): add tag to the end of skb
> master(): Offloading HW, chksum from csum_start until the end,
> including the added tag
> switch(): remove the tag, forward to the network
> remove_client(): I got a packet with a broken checksum.

This is unfortunately expected here, because you program the hardware 
with the full Ethernet frame length which does include the trailer tag, 
and it then uses that length to calculate the transport header checksum 
over the enter payload, thinking the trailer tag is the UDP/TCP payload.

The checksum is calculated "on the fly" as part of the DMA operation to 
send the packet on the wire, so you cannot decouple the checksum 
calculation from the DMA operation, other than by not asking the HW *not 
to* checksum the packet, and instead having software provide that.

Now looking at the datasheet you quoted, there is this:

241. FE_GLO_CFG: Frame Engine Global Configuration (offset: 0x0000)

7:4 RW L2_SPACE L2 Space
(unit: 8 bytes)
0xB

Can you play with this and see if you can account for the extra 4 bytes 
added by the Realtek tag?

> 
> ndo_features_check() will not help because, either in HW or SW, it is
> expected to calculate the checksum up to the end. However, there is no
> csum_end or csum_len. I don't know if HW offloading will support some
> kind of csum_end but it would not be a problem in SW (considering
> skb_checksum_help() is adapted to something like skb_checksum_trimmed
> without the clone).
> 
> That amount of bytes to ignore at the end is a complex question: the
> driver either needs some hint (like it happens with skb->csum_offset)
> to know where transport payload ends or the taggers (or the dsa) must
> save the amount of extra bytes (or which tags were added) in the
> sbk_buff. With that info, the driver can check if HW will work with a
> different csum_start / csum_end or if only a supported tag is in use.
> 
> In my case, using an incompatible tailing tag, I just made it work
> hacking dsa and forcing slave interfaces to disable offloading. This
> way, checksum is calculated before any tag is added and offloading is
> skipped. But it is not a real solution.

Not sure which one is not a "real solution", but for this specific 
combination of DSA conduit driver and switch tag, you have to disable 
checksum offload in the conduit driver and provide it in software. The 
other way would be to configure the realtek switch to work with 
DSA_TAG_8021Q and see if you can continue to offload the data path since 
tagging would use regular 802.1Q vlans, but that means you are going to 
lose a whole lot of management functionality offered by the native 
Realtek tag.
-- 
Florian

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-30 17:24                     ` Florian Fainelli
@ 2022-01-31 17:26                       ` Luiz Angelo Daros de Luca
  2022-02-01 14:46                         ` Vladimir Oltean
  0 siblings, 1 reply; 88+ messages in thread
From: Luiz Angelo Daros de Luca @ 2022-01-31 17:26 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Frank Wunderlich, Alvin Šipraga, netdev, linus.walleij,
	andrew, vivien.didelot, olteanv, arinc.unal

> On 1/29/2022 8:42 PM, Luiz Angelo Daros de Luca wrote:
> >>> I suggested it might be checksum problem because I'm also affected. In
> >>> my case, I have an mt7620a SoC connected to the rtl8367s switch. The
> >>> OS offloads checksum to HW but the mt7620a cannot calculate the
> >>> checksum with the (EtherType) Realtek CPU Tag in place. I'll try to
> >>> move the CPU tag to test if the mt7620a will then digest the frame
> >>> correctly.
> >>
> >> I implemented a new DSA tag (rtl8_4t, with "t" as in trailing) that
> >> puts the DSA tag before the Ethernet CRC (the switch supports both).
> >> With no tag in the mac layer, mediatek correctly calculated the ip
> >> checksum. However, mediatek SoC included the extra bytes from the DSA
> >> tag in the TCP checksum, even if they are after the ip length.
> >>
> >> This is the packet leaving the OS:
> >>
> >> 0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
> >> 0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
> >> 0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
> >> 0030   fe 88 83 82 00 00 02 04 05 b4 04 02 08 0a 01 64
> >> 0040   fb 28 66 42 e0 79 01 03 03 03 88 99 04 00 00 20
> >> 0050   00 08
> >>
> >> TCP checksum is at 0x0032 with 0x8382 is the tcp checksum
> >> DSA Tag is at 0x4a with 8899040000200008
> >>
> >> This is what arrived at the other end:
> >>
> >> 0000   04 0e 3c fc 4f aa 50 d4 f7 33 15 8a 08 00 45 10
> >> 0010   00 3c 00 00 40 00 40 06 b7 58 c0 a8 01 01 c0 a8
> >> 0020   01 02 00 16 a1 50 80 da 39 e9 b2 2a 23 cf a0 12
> >> 0030   fe 88 c3 e8 00 00 02 04 05 b4 04 02 08 0a 01 64
> >> 0040   fb 28 66 42 e0 79 01 03 03 03
> >>
> >> TCP checksum is 0xc3e8, but the correct one should be 0x50aa
> >> If you calculate tcp checksum including 8899040000200008, you'll get exactly
> >> 0xc3e8 (I did the math).
> >>
> >> So, If we use a trailing DSA tag, we can leave the IP checksum offloading on
> >> and just turn off the TCP checksum offload. Is it worth it?
> >
> > No, IP checksum is always done in SW.
> >
> >> Is it still interesting to have the rtl8_4t merged?
> >
> > Maybe it is. It has uncovered a problem. The case of trailing tags
> > seems to be unsolvable even with csum_start. AFAIK, the driver must
> > cksum from "skb->csum_start up to the end". When the switch is using
> > an incompatible tag, we have:
> >
> > slave(): my features copied from master tells me I can offload
> > checksum. Do nothing
> > tagger(): add tag to the end of skb
> > master(): Offloading HW, chksum from csum_start until the end,
> > including the added tag
> > switch(): remove the tag, forward to the network
> > remove_client(): I got a packet with a broken checksum.
>
> This is unfortunately expected here, because you program the hardware
> with the full Ethernet frame length which does include the trailer tag,
> and it then uses that length to calculate the transport header checksum
> over the enter payload, thinking the trailer tag is the UDP/TCP payload.
>
> The checksum is calculated "on the fly" as part of the DMA operation to
> send the packet on the wire, so you cannot decouple the checksum
> calculation from the DMA operation, other than by not asking the HW *not
> to* checksum the packet, and instead having software provide that.
>
> Now looking at the datasheet you quoted, there is this:
>
> 241. FE_GLO_CFG: Frame Engine Global Configuration (offset: 0x0000)
>
> 7:4 RW L2_SPACE L2 Space
> (unit: 8 bytes)
> 0xB
>
> Can you play with this and see if you can account for the extra 4 bytes
> added by the Realtek tag?
>

I played with it, both with the L2_SPACE and RATE_MINUS:

FE_GLO_CFG_REG=0x10100000 FE_GLO_CFG_SIZE=32
FE_GLO_CFG=$(($(devmem $FE_GLO_CFG_REG $FE_GLO_CFG_SIZE)));
for l2space_sig in b0 b1 c0 c1 d0 d1 e0 e1 a0 a1 90 91 80 81 70 71 60
61 50 51 40 41 30 31 20 21 10 11 01 00 e0 e1; do
    FE_GLO_CFG=$(($(devmem $FE_GLO_CFG_REG $FE_GLO_CFG_SIZE)));
    printf 'Before FE_GLO_CFG = 0x%X\n' $FE_GLO_CFG;
    devmem $FE_GLO_CFG_REG $FE_GLO_CFG_SIZE $((FE_GLO_CFG & ~0x00000ff
| (0x$l2space_sig)));
    FE_GLO_CFG=$(($(devmem $FE_GLO_CFG_REG $FE_GLO_CFG_SIZE)));
    printf 'After  FE_GLO_CFG = 0x%X\n' $FE_GLO_CFG;
    echo "Please test L2_SPACE_sig==$l2space_sig"; read;
done; devmem $FE_GLO_CFG_REG $FE_GLO_CFG_SIZE $FE_GLO_CFG_ORIG

It only made a difference for values 0x0 and 0xf but it looks more
like an overflow. And only on the traffic I receive, not send. The
remote endpoint
always receive 0x8382 as the tcp checksum, which is the "fake ip header" sum.

The default value is 0xb (11) and docs says it is a 8-byte unit. What
is 11 * 8 bytes? 88 bytes? Maybe it is wrong in docs.
That same register also has EXT_VLAN, which points to 0x8100 (802.1Q ethertype).

In the same doc, there is also a mention about the L2 space usage,
only related to received traffic:

"1. RX_CTRL pass through VLAN tags on L2 space (at most 2 tags)" (page 245-247)

Anyway, even if the Mediatek switch could remove the Realtek tag, it
should not do that. The Realtek switch still needs it.

> > ndo_features_check() will not help because, either in HW or SW, it is
> > expected to calculate the checksum up to the end. However, there is no
> > csum_end or csum_len. I don't know if HW offloading will support some
> > kind of csum_end but it would not be a problem in SW (considering
> > skb_checksum_help() is adapted to something like skb_checksum_trimmed
> > without the clone).
> >
> > That amount of bytes to ignore at the end is a complex question: the
> > driver either needs some hint (like it happens with skb->csum_offset)
> > to know where transport payload ends or the taggers (or the dsa) must
> > save the amount of extra bytes (or which tags were added) in the
> > sbk_buff. With that info, the driver can check if HW will work with a
> > different csum_start / csum_end or if only a supported tag is in use.

I must be missing something. Is SW TCP checksum really broken when a
tailing tag is in use? If so, it will only work if TCP checksum
offload is enabled in a compatible HW. Anything else like different
vendors, software checksum or stacked tags will be broken.

> > In my case, using an incompatible tailing tag, I just made it work
> > hacking dsa and forcing slave interfaces to disable offloading. This
> > way, checksum is calculated before any tag is added and offloading is
> > skipped. But it is not a real solution.
>
> Not sure which one is not a "real solution", but for this specific
> combination of DSA conduit driver and switch tag, you have to disable
> checksum offload in the conduit driver and provide it in software. The
> other way would be to configure the realtek switch to work with
> DSA_TAG_8021Q and see if you can continue to offload the data path since
> tagging would use regular 802.1Q vlans, but that means you are going to
> lose a whole lot of management functionality offered by the native
> Realtek tag.

Definitely not a real solution. It was just a hack to check if
checksumming at slave device will overcome the issue. As I said,
simply disabling checksum and doing it in SW "as usual" is not enough
because SW checksum also sums to the end. We need to parse each
possible transport layer to find its end or taggers must hint how many
bytes to ignore, something like a new skb->cksum_stop_before_end.
Another solution would be to hint the slave interface if it needs to
checksum right there (modifying slave->vlan_features). None of that
exists today. Is it the right way?

--

Luiz

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

* Re: [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint
  2022-01-31 17:26                       ` Luiz Angelo Daros de Luca
@ 2022-02-01 14:46                         ` Vladimir Oltean
  0 siblings, 0 replies; 88+ messages in thread
From: Vladimir Oltean @ 2022-02-01 14:46 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Florian Fainelli, Frank Wunderlich, Alvin Šipraga, netdev,
	linus.walleij, andrew, vivien.didelot, arinc.unal

On Mon, Jan 31, 2022 at 02:26:30PM -0300, Luiz Angelo Daros de Luca wrote:
> > > In my case, using an incompatible tailing tag, I just made it work
> > > hacking dsa and forcing slave interfaces to disable offloading. This
> > > way, checksum is calculated before any tag is added and offloading is
> > > skipped. But it is not a real solution.
> >
> > Not sure which one is not a "real solution", but for this specific
> > combination of DSA conduit driver and switch tag, you have to disable
> > checksum offload in the conduit driver and provide it in software. The
> > other way would be to configure the realtek switch to work with
> > DSA_TAG_8021Q and see if you can continue to offload the data path since
> > tagging would use regular 802.1Q vlans, but that means you are going to
> > lose a whole lot of management functionality offered by the native
> > Realtek tag.
> 
> Definitely not a real solution. It was just a hack to check if
> checksumming at slave device will overcome the issue. As I said,
> simply disabling checksum and doing it in SW "as usual" is not enough
> because SW checksum also sums to the end. We need to parse each
> possible transport layer to find its end or taggers must hint how many
> bytes to ignore, something like a new skb->cksum_stop_before_end.
> Another solution would be to hint the slave interface if it needs to
> checksum right there (modifying slave->vlan_features). None of that
> exists today. Is it the right way?

I think we're not getting any closer to a solution if we've started
discussing tail taggers.

See commit 37120f23ac89 ("net: dsa: tag_ksz: dont let the hardware
process the layer 4 checksum"). It proves that if you calculate the L4
checksum in software before inserting the DSA tag, it won't get
recalculated upon dev_queue_xmit() on the DSA master, since
skb_checksum_help() transitions skb->ip_summed to CHECKSUM_NONE, and the
process of inserting a header/trailer will not update the checksum, so
it will end up being correct on the receive end after the tail tag is
stripped.

Otherwise, I don't completely understand what is the end goal you're
after. Each skb is checked for netdev features when determining whether
to calculate the L4 checksum in software or not. Then even if that skb
was marked for L4 checksum offload by the stack, you can still call
skb_checksum_help() from the xmit procedure of the driver.

Do you want hardware offloading with your DSA header, or why do you say
that forcing slave interfaces to disable the offload is not a real
solution? If so, I recommend looking into a custom tagging protocol
based on tag_8021q.c, but word of warning, some elbow grease will be
required.

If you're ok with software checksumming and just want the minimum amount
of checks in the fastpath, I believe you should listen for
NETDEV_CHANGEUPPER events in your DSA master driver, where
dsa_slave_dev_check(info->upper_dev) is true. From there you should be
able to retrieve the tagging protocol used (if you can't, then export some
helpers that will do that), and enable NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
in master->features if the tag is Mediatek, clear them otherwise.
See bcmsysport.c for an example.
The timing of this notifier is such that it's pointless to mangle
master->vlan_features at that stage, since DSA has already inherited
them. So DSA slaves would still report NETIF_F_IP_CSUM, but the DSA
master would force a software calculation from the correct L3 & L4
offsets, and it would practically work.
Alternatively, I think you could move dsa_slave_setup_tagger() beneath
netdev_upper_dev_link(), and this would give the DSA master an
opportunity to modulate its master->vlan_features in a way that is
desirable to you. I don't see something that would break if you do that.

As Florian and Jakub explained, the APIs for TX checksumming are what
they are, I'm not very happy with the state of things either, but I
can't justify a DSA-specific API. With HW_CSUM, the stack gives you an
L3 and L4 offset, and that is compatible with DSA headers (not
trailers), so the onus is on the DSA master to fall back to software on
offsets it doesn't like.  One could argue that DSA should not work with
IP_CSUM | IPV6_CSUM, but I believe that there are existing drivers that
use these checksum features and that do work at least with certain DSA
tagging protocols (bcmsysport) or even look at the L3 and L4 offsets
(mvneta), meaning that they would work generically with DSA. So
practically speaking, if we issue a blanket statement that DSA shouldn't
inherit IP_CSUM | IPV6_CSUM but just HW_CSUM, that would still break
working setups. Now, we could still do that (since IP_CSUM | IPV6_CSUM
are theoretically deprecated), but then you'd have to be there and help
with some more elbow grease to fix the breakage in mvneta etc, to
convert them to HW_CSUM.

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

end of thread, other threads:[~2022-02-01 14:46 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-05  3:15 [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Luiz Angelo Daros de Luca
2022-01-05  3:15 ` [PATCH net-next v4 01/11] net: dsa: realtek-smi: move to subdirectory Luiz Angelo Daros de Luca
2022-01-05  3:15 ` [PATCH net-next v4 02/11] net: dsa: realtek: rename realtek_smi to realtek_priv Luiz Angelo Daros de Luca
2022-01-07  3:42   ` Jakub Kicinski
2022-01-10 12:33   ` Alvin Šipraga
2022-01-16  0:04   ` Linus Walleij
2022-01-20 14:37   ` Vladimir Oltean
2022-01-05  3:15 ` [PATCH net-next v4 03/11] net: dsa: realtek: remove direct calls to realtek-smi Luiz Angelo Daros de Luca
2022-01-10 12:38   ` Alvin Šipraga
2022-01-16  0:05   ` Linus Walleij
2022-01-17  3:46   ` Florian Fainelli
2022-01-05  3:15 ` [PATCH net-next v4 04/11] net: dsa: realtek: convert subdrivers into modules Luiz Angelo Daros de Luca
2022-01-10 12:43   ` Alvin Šipraga
2022-01-17  4:02   ` Florian Fainelli
2022-01-05  3:15 ` [PATCH net-next v4 05/11] net: dsa: realtek: use phy_read in ds->ops Luiz Angelo Daros de Luca
2022-01-10 13:09   ` Alvin Šipraga
2022-01-17  4:15   ` Florian Fainelli
2022-01-18  2:55     ` Luiz Angelo Daros de Luca
2022-01-18 13:16       ` Andrew Lunn
2022-01-21 22:13         ` Luiz Angelo Daros de Luca
2022-01-21 23:48           ` Andrew Lunn
2022-01-05  3:15 ` [PATCH net-next v4 06/11] net: dsa: realtek: add new mdio interface for drivers Luiz Angelo Daros de Luca
2022-01-10 13:09   ` Alvin Šipraga
2022-01-17  4:22   ` Florian Fainelli
2022-01-18  4:38     ` Luiz Angelo Daros de Luca
2022-01-05  3:15 ` [PATCH net-next v4 07/11] net: dsa: realtek: rtl8365mb: rename extport to extint, add "realtek,ext-int" Luiz Angelo Daros de Luca
2022-01-10 13:15   ` Alvin Šipraga
2022-01-17  4:25   ` Florian Fainelli
2022-01-05  3:15 ` [PATCH net-next v4 08/11] net: dsa: realtek: rtl8365mb: use GENMASK(n-1,0) instead of BIT(n)-1 Luiz Angelo Daros de Luca
2022-01-10 13:18   ` Alvin Šipraga
2022-01-17  4:25   ` Florian Fainelli
2022-01-05  3:15 ` [PATCH net-next v4 09/11] net: dsa: realtek: rtl8365mb: use DSA CPU port Luiz Angelo Daros de Luca
2022-01-07  3:37   ` Jakub Kicinski
2022-01-10 13:22   ` Alvin Šipraga
2022-01-17  4:26   ` Florian Fainelli
2022-01-05  3:15 ` [PATCH net-next v4 10/11] net: dsa: realtek: rtl8365mb: add RTL8367S support Luiz Angelo Daros de Luca
2022-01-10 13:26   ` Alvin Šipraga
2022-01-17  4:26   ` Florian Fainelli
2022-01-05  3:15 ` [PATCH net-next v4 11/11] net: dsa: realtek: rtl8365mb: multiple cpu ports, non cpu extint Luiz Angelo Daros de Luca
2022-01-10 13:39   ` Alvin Šipraga
2022-01-10 13:53     ` Aw: " Frank Wunderlich
2022-01-11 18:17       ` Alvin Šipraga
2022-01-11 18:45         ` Aw: " Frank Wunderlich
2022-01-13 12:37           ` Alvin Šipraga
2022-01-13 15:56             ` Aw: " Frank Wunderlich
2022-01-18  4:58               ` Luiz Angelo Daros de Luca
2022-01-18 10:13                 ` Alvin Šipraga
2022-01-18 13:20                 ` Re: Re: " Andrew Lunn
2022-01-20 15:12                   ` Vladimir Oltean
2022-01-20 23:35                     ` Luiz Angelo Daros de Luca
2022-01-21  2:06                       ` Vladimir Oltean
2022-01-21  3:13                         ` Luiz Angelo Daros de Luca
2022-01-21  3:22                           ` Florian Fainelli
2022-01-21  3:42                             ` Luiz Angelo Daros de Luca
2022-01-21  3:50                               ` Florian Fainelli
2022-01-21  4:37                                 ` Luiz Angelo Daros de Luca
2022-01-21  9:07                                 ` Arınç ÜNAL
2022-01-21 18:50                           ` Vladimir Oltean
2022-01-21 21:51                             ` Luiz Angelo Daros de Luca
2022-01-21 22:49                               ` Vladimir Oltean
2022-01-22 20:12                                 ` Luiz Angelo Daros de Luca
2022-01-24 15:31                                   ` Vladimir Oltean
2022-01-24 16:46                                     ` Jakub Kicinski
2022-01-24 16:55                                       ` Vladimir Oltean
2022-01-24 17:01                                         ` Florian Fainelli
2022-01-24 17:21                                           ` Vladimir Oltean
2022-01-24 17:30                                             ` Florian Fainelli
2022-01-24 17:35                                             ` Jakub Kicinski
2022-01-24 18:20                                               ` Jakub Kicinski
2022-01-24 19:08                                                 ` Vladimir Oltean
2022-01-24 19:38                                                   ` Jakub Kicinski
2022-01-24 20:56                                                     ` Vladimir Oltean
2022-01-24 21:42                                                       ` Jakub Kicinski
2022-01-24 22:30                                                         ` Vladimir Oltean
2022-01-25  7:15                                                           ` Luiz Angelo Daros de Luca
2022-01-25  9:47                                                             ` Vladimir Oltean
2022-01-25 22:29                                                               ` Luiz Angelo Daros de Luca
2022-01-25 23:56                                                                 ` Florian Fainelli
2022-01-26 22:49                                                                   ` Luiz Angelo Daros de Luca
2022-01-25  9:44                                                           ` Arınç ÜNAL
2022-01-22 15:51                               ` Andrew Lunn
2022-01-30  1:54                 ` Re: Re: " Luiz Angelo Daros de Luca
2022-01-30  4:42                   ` Luiz Angelo Daros de Luca
2022-01-30 17:24                     ` Florian Fainelli
2022-01-31 17:26                       ` Luiz Angelo Daros de Luca
2022-02-01 14:46                         ` Vladimir Oltean
2022-01-20 14:36 ` [PATCH net-next v4 00/11] net: dsa: realtek: MDIO interface and RTL8367S Vladimir Oltean
2022-01-20 17:46   ` Luiz Angelo Daros de Luca

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.