All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module
@ 2023-12-08  4:41 Luiz Angelo Daros de Luca
  2023-12-08  4:41 ` [PATCH net-next 1/7] net: dsa: realtek: drop cleanup from realtek_priv Luiz Angelo Daros de Luca
                   ` (6 more replies)
  0 siblings, 7 replies; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

The current driver comprises two interface modules (SMI and MDIO) and two family/variant modules (RTL8365MB and RTL8366RB). The SMI and MDIO modules are, respectively, the platform and MDIO drivers that call functions from the variant modules. In this scenario, one interface module can be loaded independently from the other one, but both variants, if not disabled at build time, must be loaded for any type of interface. This approach does not scale well, particularly with the addition of more switch variants (e.g., RTL8366B), resulting in loaded but unused modules. This also seems to be upside down, as the specific driver code normally depends on the more generic functions and not the other way around.

The series starts with two preliminary patches. The first just cleans an unused function declaration until someone actually references it. The second one moves the of_node_put from the driver remove to just after it was used. We don't really need to keep a reference for that node after the MDIO was registered.

Each variant module was converted into real drivers, both as a platform driver (for switches connected using the SMI interface) and an MDIO driver (for MDIO connected switches). The relationship between the variant and interface module is also reversed. Now the variant module calls interface functions, depending on both interface modules (if not disabled at build time). Although probably in all devices only one interface will be used, the interface code is multiple times smaller than a variant module, using much fewer resources than the previous code. With variant modules as real drivers, the compatible strings are published only in a single variant module, avoiding conflicts.

The patch series also introduces a new common module for functions used by both variants. This module also incorporates the two previous interface modules as they will always be loaded anyway.

Finally, the series moves the user MII driver from realtek-smi to common. It is now also used by MDIO-connected switches instead of the generic DSA driver.

In the end, the driver relation is simpler, with a common module and multiple independent variant modules, and we require much fewer resources.

Tested with an RTL8367S (RTL8365MB) using MDIO interface and an RTL8366RB (RTL8366) with SMI interface.

--

Luiz


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

* [PATCH net-next 1/7] net: dsa: realtek: drop cleanup from realtek_priv
  2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
@ 2023-12-08  4:41 ` Luiz Angelo Daros de Luca
  2023-12-08  9:49   ` Alvin Šipraga
  2023-12-08  4:41 ` [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration Luiz Angelo Daros de Luca
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal, Luiz Angelo Daros de Luca

It was never used and never referenced.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/realtek.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index 790488e9c667..e9ee778665b2 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -91,7 +91,6 @@ 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,
-- 
2.43.0


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

* [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
  2023-12-08  4:41 ` [PATCH net-next 1/7] net: dsa: realtek: drop cleanup from realtek_priv Luiz Angelo Daros de Luca
@ 2023-12-08  4:41 ` Luiz Angelo Daros de Luca
  2023-12-08  5:13   ` Luiz Angelo Daros de Luca
  2023-12-08  4:41 ` [PATCH net-next 3/7] net: dsa: realtek: convert variants into a real driver Luiz Angelo Daros de Luca
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal, Luiz Angelo Daros de Luca

If we don't keep a reference to the OF node, we can put it right after
we use it during MDIO registration.

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

diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 755546ed8db6..ddcae546afbc 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -389,15 +389,15 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
 	priv->user_mii_bus->write = realtek_smi_mdio_write;
 	snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
 		 ds->index);
-	priv->user_mii_bus->dev.of_node = mdio_np;
 	priv->user_mii_bus->parent = priv->dev;
 	ds->user_mii_bus = priv->user_mii_bus;
 
 	ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
+	of_node_put(mdio_np);
 	if (ret) {
 		dev_err(priv->dev, "unable to register MDIO bus %s\n",
 			priv->user_mii_bus->id);
-		goto err_put_node;
+		return ret;
 	}
 
 	return 0;
@@ -514,8 +514,6 @@ static void realtek_smi_remove(struct platform_device *pdev)
 		return;
 
 	dsa_unregister_switch(priv->ds);
-	if (priv->user_mii_bus)
-		of_node_put(priv->user_mii_bus->dev.of_node);
 
 	/* leave the device reset asserted */
 	if (priv->reset)
-- 
2.43.0


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

* [PATCH net-next 3/7] net: dsa: realtek: convert variants into a real driver
  2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
  2023-12-08  4:41 ` [PATCH net-next 1/7] net: dsa: realtek: drop cleanup from realtek_priv Luiz Angelo Daros de Luca
  2023-12-08  4:41 ` [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration Luiz Angelo Daros de Luca
@ 2023-12-08  4:41 ` Luiz Angelo Daros de Luca
  2023-12-08 10:23   ` Alvin Šipraga
  2023-12-08  4:41 ` [PATCH net-next 4/7] net: dsa: realtek: create realtek-common Luiz Angelo Daros de Luca
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal, Luiz Angelo Daros de Luca

Previously, the interface modules realtek-smi and realtek-mdio were,
respectively, a platform and an MDIO driver. Each interface module
repeated the same compatible strings for both variants and they
referenced symbols from variants.

Now each variant module was converted into both a platform and an MDIO
driver. It reverses the relationship between interface and variant
module, with the variant now using symbols from interface modules.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/Kconfig        | 20 ++++-------
 drivers/net/dsa/realtek/realtek-mdio.c | 33 ++++--------------
 drivers/net/dsa/realtek/realtek-mdio.h | 48 ++++++++++++++++++++++++++
 drivers/net/dsa/realtek/realtek-smi.c  | 38 ++++----------------
 drivers/net/dsa/realtek/realtek-smi.h  | 48 ++++++++++++++++++++++++++
 drivers/net/dsa/realtek/rtl8365mb.c    | 48 +++++++++++++++++++++++++-
 drivers/net/dsa/realtek/rtl8366rb.c    | 48 +++++++++++++++++++++++++-
 7 files changed, 210 insertions(+), 73 deletions(-)
 create mode 100644 drivers/net/dsa/realtek/realtek-mdio.h
 create mode 100644 drivers/net/dsa/realtek/realtek-smi.h

diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
index 060165a85fb7..9d182fde11b4 100644
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -16,37 +16,29 @@ menuconfig NET_DSA_REALTEK
 if NET_DSA_REALTEK
 
 config NET_DSA_REALTEK_MDIO
-	tristate "Realtek MDIO interface driver"
+	tristate "Realtek MDIO interface support"
 	depends on OF
-	depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
-	depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
-	depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
 	help
 	  Select to enable support for registering switches configured
 	  through MDIO.
 
 config NET_DSA_REALTEK_SMI
-	tristate "Realtek SMI interface driver"
+	tristate "Realtek SMI interface support"
 	depends on OF
-	depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
-	depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
-	depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
 	help
 	  Select to enable support for registering switches connected
 	  through SMI.
 
 config NET_DSA_REALTEK_RTL8365MB
-	tristate "Realtek RTL8365MB switch subdriver"
-	imply NET_DSA_REALTEK_SMI
-	imply NET_DSA_REALTEK_MDIO
+	tristate "Realtek RTL8365MB switch driver"
+	depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
 	select NET_DSA_TAG_RTL8_4
 	help
 	  Select to enable support for Realtek RTL8365MB-VC and RTL8367S.
 
 config NET_DSA_REALTEK_RTL8366RB
-	tristate "Realtek RTL8366RB switch subdriver"
-	imply NET_DSA_REALTEK_SMI
-	imply NET_DSA_REALTEK_MDIO
+	tristate "Realtek RTL8366RB switch driver"
+	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/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index 292e6d087e8b..58966d0625c8 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -25,6 +25,7 @@
 #include <linux/regmap.h>
 
 #include "realtek.h"
+#include "realtek-mdio.h"
 
 /* Read/write via mdiobus */
 #define REALTEK_MDIO_CTRL0_REG		31
@@ -140,7 +141,7 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
 	.disable_locking = true,
 };
 
-static int realtek_mdio_probe(struct mdio_device *mdiodev)
+int realtek_mdio_probe(struct mdio_device *mdiodev)
 {
 	struct realtek_priv *priv;
 	struct device *dev = &mdiodev->dev;
@@ -235,8 +236,9 @@ static int realtek_mdio_probe(struct mdio_device *mdiodev)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(realtek_mdio_probe);
 
-static void realtek_mdio_remove(struct mdio_device *mdiodev)
+void realtek_mdio_remove(struct mdio_device *mdiodev)
 {
 	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
 
@@ -249,8 +251,9 @@ static void realtek_mdio_remove(struct mdio_device *mdiodev)
 	if (priv->reset)
 		gpiod_set_value(priv->reset, 1);
 }
+EXPORT_SYMBOL_GPL(realtek_mdio_remove);
 
-static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
+void realtek_mdio_shutdown(struct mdio_device *mdiodev)
 {
 	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
 
@@ -261,29 +264,7 @@ static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
 
 	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 = realtek_mdio_of_match,
-	},
-	.probe  = realtek_mdio_probe,
-	.remove = realtek_mdio_remove,
-	.shutdown = realtek_mdio_shutdown,
-};
-
-mdio_module_driver(realtek_mdio_driver);
+EXPORT_SYMBOL_GPL(realtek_mdio_shutdown);
 
 MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
 MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
diff --git a/drivers/net/dsa/realtek/realtek-mdio.h b/drivers/net/dsa/realtek/realtek-mdio.h
new file mode 100644
index 000000000000..b938a55249c9
--- /dev/null
+++ b/drivers/net/dsa/realtek/realtek-mdio.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _REALTEK_MDIO_H
+#define _REALTEK_MDIO_H
+
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO)
+
+static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
+{
+	return mdio_driver_register(drv);
+}
+
+static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
+{
+	mdio_driver_unregister(drv);
+}
+
+int realtek_mdio_probe(struct mdio_device *mdiodev);
+void realtek_mdio_remove(struct mdio_device *mdiodev);
+void realtek_mdio_shutdown(struct mdio_device *mdiodev);
+
+#else
+
+static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
+{
+	return 0;
+}
+
+static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
+{
+}
+
+static inline int realtek_mdio_probe(struct mdio_device *mdiodev)
+{
+	return -ENOENT;
+}
+
+static inline void realtek_mdio_remove(struct mdio_device *mdiodev)
+{
+}
+
+static inline void realtek_mdio_shutdown(struct mdio_device *mdiodev)
+{
+}
+
+#endif
+
+#endif
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index ddcae546afbc..55586d158c0e 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -40,6 +40,7 @@
 #include <linux/if_bridge.h>
 
 #include "realtek.h"
+#include "realtek-smi.h"
 
 #define REALTEK_SMI_ACK_RETRY_COUNT		5
 
@@ -408,7 +409,7 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
 	return ret;
 }
 
-static int realtek_smi_probe(struct platform_device *pdev)
+int realtek_smi_probe(struct platform_device *pdev)
 {
 	const struct realtek_variant *var;
 	struct device *dev = &pdev->dev;
@@ -505,8 +506,9 @@ static int realtek_smi_probe(struct platform_device *pdev)
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(realtek_smi_probe);
 
-static void realtek_smi_remove(struct platform_device *pdev)
+void realtek_smi_remove(struct platform_device *pdev)
 {
 	struct realtek_priv *priv = platform_get_drvdata(pdev);
 
@@ -519,8 +521,9 @@ static void realtek_smi_remove(struct platform_device *pdev)
 	if (priv->reset)
 		gpiod_set_value(priv->reset, 1);
 }
+EXPORT_SYMBOL_GPL(realtek_smi_remove);
 
-static void realtek_smi_shutdown(struct platform_device *pdev)
+void realtek_smi_shutdown(struct platform_device *pdev)
 {
 	struct realtek_priv *priv = platform_get_drvdata(pdev);
 
@@ -531,34 +534,7 @@ static void realtek_smi_shutdown(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, NULL);
 }
-
-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
-#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
-	{
-		.compatible = "realtek,rtl8365mb",
-		.data = &rtl8365mb_variant,
-	},
-#endif
-	{ /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
-
-static struct platform_driver realtek_smi_driver = {
-	.driver = {
-		.name = "realtek-smi",
-		.of_match_table = realtek_smi_of_match,
-	},
-	.probe  = realtek_smi_probe,
-	.remove_new = realtek_smi_remove,
-	.shutdown = realtek_smi_shutdown,
-};
-module_platform_driver(realtek_smi_driver);
+EXPORT_SYMBOL_GPL(realtek_smi_shutdown);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
diff --git a/drivers/net/dsa/realtek/realtek-smi.h b/drivers/net/dsa/realtek/realtek-smi.h
new file mode 100644
index 000000000000..76fb58df728b
--- /dev/null
+++ b/drivers/net/dsa/realtek/realtek-smi.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _REALTEK_SMI_H
+#define _REALTEK_SMI_H
+
+#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI)
+
+static inline int realtek_smi_driver_register(struct platform_driver *drv)
+{
+	return platform_driver_register(drv);
+}
+
+static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
+{
+	platform_driver_unregister(drv);
+}
+
+int realtek_smi_probe(struct platform_device *pdev);
+void realtek_smi_remove(struct platform_device *pdev);
+void realtek_smi_shutdown(struct platform_device *pdev);
+
+#else
+
+static inline int realtek_smi_driver_register(struct platform_driver *drv)
+{
+	return 0;
+}
+
+static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
+{
+}
+
+static inline int realtek_smi_probe(struct platform_device *pdev)
+{
+	return -ENOENT;
+}
+
+static inline void realtek_smi_remove(struct platform_device *pdev)
+{
+}
+
+static inline void realtek_smi_shutdown(struct platform_device *pdev)
+{
+}
+
+#endif
+
+#endif
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 0875e4fc9f57..526bf98cef1d 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -101,6 +101,8 @@
 #include <linux/if_vlan.h>
 
 #include "realtek.h"
+#include "realtek-smi.h"
+#include "realtek-mdio.h"
 
 /* Family-specific data and limits */
 #define RTL8365MB_PHYADDRMAX		7
@@ -2172,7 +2174,51 @@ const struct realtek_variant rtl8365mb_variant = {
 	.cmd_write = 0xb8,
 	.chip_data_sz = sizeof(struct rtl8365mb),
 };
-EXPORT_SYMBOL_GPL(rtl8365mb_variant);
+
+static const struct of_device_id rtl8365mb_of_match[] = {
+	{ .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, rtl8365mb_of_match);
+
+static struct platform_driver rtl8365mb_smi_driver = {
+	.driver = {
+		.name = "rtl8365mb-smi",
+		.of_match_table = rtl8365mb_of_match,
+	},
+	.probe  = realtek_smi_probe,
+	.remove_new = realtek_smi_remove,
+	.shutdown = realtek_smi_shutdown,
+};
+
+static struct mdio_driver rtl8365mb_mdio_driver = {
+	.mdiodrv.driver = {
+		.name = "rtl8365mb-mdio",
+		.of_match_table = rtl8365mb_of_match,
+	},
+	.probe  = realtek_mdio_probe,
+	.remove = realtek_mdio_remove,
+	.shutdown = realtek_mdio_shutdown,
+};
+
+static int rtl8365mb_init(void)
+{
+	int ret;
+
+	ret = realtek_mdio_driver_register(&rtl8365mb_mdio_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&rtl8365mb_smi_driver);
+}
+module_init(rtl8365mb_init);
+
+static void __exit rtl8365mb_exit(void)
+{
+	realtek_mdio_driver_unregister(&rtl8365mb_mdio_driver);
+	platform_driver_unregister(&rtl8365mb_smi_driver);
+}
+module_exit(rtl8365mb_exit);
 
 MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
 MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index b39b719a5b8f..09c17de19457 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -22,6 +22,8 @@
 #include <linux/regmap.h>
 
 #include "realtek.h"
+#include "realtek-smi.h"
+#include "realtek-mdio.h"
 
 #define RTL8366RB_PORT_NUM_CPU		5
 #define RTL8366RB_NUM_PORTS		6
@@ -1920,7 +1922,51 @@ const struct realtek_variant rtl8366rb_variant = {
 	.cmd_write = 0xa8,
 	.chip_data_sz = sizeof(struct rtl8366rb),
 };
-EXPORT_SYMBOL_GPL(rtl8366rb_variant);
+
+static const struct of_device_id rtl8366rb_of_match[] = {
+	{ .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, rtl8366rb_of_match);
+
+static struct platform_driver rtl8366rb_smi_driver = {
+	.driver = {
+		.name = "rtl8366rb-smi",
+		.of_match_table = rtl8366rb_of_match,
+	},
+	.probe  = realtek_smi_probe,
+	.remove_new = realtek_smi_remove,
+	.shutdown = realtek_smi_shutdown,
+};
+
+static struct mdio_driver rtl8366rb_mdio_driver = {
+	.mdiodrv.driver = {
+		.name = "rtl8366rb-mdio",
+		.of_match_table = rtl8366rb_of_match,
+	},
+	.probe  = realtek_mdio_probe,
+	.remove = realtek_mdio_remove,
+	.shutdown = realtek_mdio_shutdown,
+};
+
+static int rtl8366rb_init(void)
+{
+	int ret;
+
+	ret = realtek_mdio_driver_register(&rtl8366rb_mdio_driver);
+	if (ret)
+		return ret;
+
+	return realtek_smi_driver_register(&rtl8366rb_smi_driver);
+}
+module_init(rtl8366rb_init);
+
+static void __exit rtl8366rb_exit(void)
+{
+	realtek_mdio_driver_unregister(&rtl8366rb_mdio_driver);
+	realtek_smi_driver_unregister(&rtl8366rb_smi_driver);
+}
+module_exit(rtl8366rb_exit);
 
 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
-- 
2.43.0


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

* [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
                   ` (2 preceding siblings ...)
  2023-12-08  4:41 ` [PATCH net-next 3/7] net: dsa: realtek: convert variants into a real driver Luiz Angelo Daros de Luca
@ 2023-12-08  4:41 ` Luiz Angelo Daros de Luca
  2023-12-08  5:01   ` Luiz Angelo Daros de Luca
                     ` (2 more replies)
  2023-12-08  4:41 ` [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common Luiz Angelo Daros de Luca
                   ` (2 subsequent siblings)
  6 siblings, 3 replies; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal, Luiz Angelo Daros de Luca

Some code can be shared between both interface modules (MDIO and SMI)
and among variants. Currently, these interface functions are shared:

- realtek_common_lock
- realtek_common_unlock
- realtek_common_probe
- realtek_common_remove

The reset during probe was moved to the last moment before a variant
detects the switch. This way, we avoid a reset if anything else fails.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/net/dsa/realtek/Makefile         |   1 +
 drivers/net/dsa/realtek/realtek-common.c | 136 +++++++++++++++++++++++
 drivers/net/dsa/realtek/realtek-common.h |  16 +++
 drivers/net/dsa/realtek/realtek-mdio.c   | 121 ++------------------
 drivers/net/dsa/realtek/realtek-smi.c    | 124 +++------------------
 drivers/net/dsa/realtek/realtek.h        |   6 +-
 drivers/net/dsa/realtek/rtl8365mb.c      |   9 +-
 drivers/net/dsa/realtek/rtl8366rb.c      |   9 +-
 8 files changed, 194 insertions(+), 228 deletions(-)
 create mode 100644 drivers/net/dsa/realtek/realtek-common.c
 create mode 100644 drivers/net/dsa/realtek/realtek-common.h

diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
index 0aab57252a7c..5e0c1ef200a3 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)		+= realtek-common.o
 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
diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
new file mode 100644
index 000000000000..75b6aa071990
--- /dev/null
+++ b/drivers/net/dsa/realtek/realtek-common.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/module.h>
+
+#include "realtek.h"
+#include "realtek-common.h"
+
+void realtek_common_lock(void *ctx)
+{
+	struct realtek_priv *priv = ctx;
+
+	mutex_lock(&priv->map_lock);
+}
+EXPORT_SYMBOL_GPL(realtek_common_lock);
+
+void realtek_common_unlock(void *ctx)
+{
+	struct realtek_priv *priv = ctx;
+
+	mutex_unlock(&priv->map_lock);
+}
+EXPORT_SYMBOL_GPL(realtek_common_unlock);
+
+struct realtek_priv *
+realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
+			 struct regmap_config rc_nolock)
+{
+	const struct realtek_variant *var;
+	struct realtek_priv *priv;
+	struct device_node *np;
+	int ret;
+
+	var = of_device_get_match_data(dev);
+	if (!var)
+		return ERR_PTR(-EINVAL);
+
+	priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz),
+			    GFP_KERNEL);
+	if (!priv)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&priv->map_lock);
+
+	rc.lock_arg = priv;
+	priv->map = devm_regmap_init(dev, NULL, priv, &rc);
+	if (IS_ERR(priv->map)) {
+		ret = PTR_ERR(priv->map);
+		dev_err(dev, "regmap init failed: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc_nolock);
+	if (IS_ERR(priv->map_nolock)) {
+		ret = PTR_ERR(priv->map_nolock);
+		dev_err(dev, "regmap init failed: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	/* Link forward and backward */
+	priv->dev = dev;
+	priv->variant = var;
+	priv->ops = var->ops;
+	priv->chip_data = (void *)priv + sizeof(*priv);
+
+	dev_set_drvdata(dev, priv);
+	spin_lock_init(&priv->lock);
+
+	np = dev->of_node;
+
+	priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
+
+	/* TODO: if power is software controlled, set up any regulators here */
+
+	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->reset)) {
+		dev_err(dev, "failed to get RESET GPIO\n");
+		return ERR_CAST(priv->reset);
+	}
+	if (priv->reset) {
+		gpiod_set_value(priv->reset, 1);
+		dev_dbg(dev, "asserted RESET\n");
+		msleep(REALTEK_HW_STOP_DELAY);
+		gpiod_set_value(priv->reset, 0);
+		msleep(REALTEK_HW_START_DELAY);
+		dev_dbg(dev, "deasserted RESET\n");
+	}
+
+	return priv;
+}
+EXPORT_SYMBOL(realtek_common_probe_pre);
+
+int realtek_common_probe_post(struct realtek_priv *priv)
+{
+	int ret;
+
+	ret = priv->ops->detect(priv);
+	if (ret) {
+		dev_err(priv->dev, "unable to detect switch\n");
+		return ret;
+	}
+
+	priv->ds = devm_kzalloc(priv->dev, sizeof(*priv->ds), GFP_KERNEL);
+	if (!priv->ds)
+		return -ENOMEM;
+
+	priv->ds->priv = priv;
+	priv->ds->dev = priv->dev;
+	priv->ds->ops = priv->ds_ops;
+	priv->ds->num_ports = priv->num_ports;
+
+	ret = dsa_register_switch(priv->ds);
+	if (ret) {
+		dev_err_probe(priv->dev, ret, "unable to register switch\n");
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(realtek_common_probe_post);
+
+void realtek_common_remove(struct realtek_priv *priv)
+{
+	if (!priv)
+		return;
+
+	dsa_unregister_switch(priv->ds);
+
+	/* leave the device reset asserted */
+	if (priv->reset)
+		gpiod_set_value(priv->reset, 1);
+}
+EXPORT_SYMBOL(realtek_common_remove);
+
+MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
+MODULE_DESCRIPTION("Realtek DSA switches common module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/realtek/realtek-common.h b/drivers/net/dsa/realtek/realtek-common.h
new file mode 100644
index 000000000000..405bd0d85d2b
--- /dev/null
+++ b/drivers/net/dsa/realtek/realtek-common.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _REALTEK_INTERFACE_H
+#define _REALTEK_INTERFACE_H
+
+#include <linux/regmap.h>
+
+void realtek_common_lock(void *ctx);
+void realtek_common_unlock(void *ctx);
+struct realtek_priv *
+realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
+			 struct regmap_config rc_nolock);
+int realtek_common_probe_post(struct realtek_priv *priv);
+void realtek_common_remove(struct realtek_priv *priv);
+
+#endif
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index 58966d0625c8..4c9a744b72f8 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -26,6 +26,7 @@
 
 #include "realtek.h"
 #include "realtek-mdio.h"
+#include "realtek-common.h"
 
 /* Read/write via mdiobus */
 #define REALTEK_MDIO_CTRL0_REG		31
@@ -100,20 +101,6 @@ static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
 	return ret;
 }
 
-static void realtek_mdio_lock(void *ctx)
-{
-	struct realtek_priv *priv = ctx;
-
-	mutex_lock(&priv->map_lock);
-}
-
-static void realtek_mdio_unlock(void *ctx)
-{
-	struct realtek_priv *priv = ctx;
-
-	mutex_unlock(&priv->map_lock);
-}
-
 static const struct regmap_config realtek_mdio_regmap_config = {
 	.reg_bits = 10, /* A4..A0 R4..R0 */
 	.val_bits = 16,
@@ -124,8 +111,8 @@ static const struct regmap_config realtek_mdio_regmap_config = {
 	.reg_read = realtek_mdio_read,
 	.reg_write = realtek_mdio_write,
 	.cache_type = REGCACHE_NONE,
-	.lock = realtek_mdio_lock,
-	.unlock = realtek_mdio_unlock,
+	.lock = realtek_common_lock,
+	.unlock = realtek_common_unlock,
 };
 
 static const struct regmap_config realtek_mdio_nolock_regmap_config = {
@@ -143,98 +130,21 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
 
 int realtek_mdio_probe(struct mdio_device *mdiodev)
 {
-	struct realtek_priv *priv;
 	struct device *dev = &mdiodev->dev;
-	const struct realtek_variant *var;
-	struct regmap_config rc;
-	struct device_node *np;
-	int ret;
-
-	var = of_device_get_match_data(dev);
-	if (!var)
-		return -EINVAL;
-
-	priv = devm_kzalloc(&mdiodev->dev,
-			    size_add(sizeof(*priv), var->chip_data_sz),
-			    GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	mutex_init(&priv->map_lock);
-
-	rc = realtek_mdio_regmap_config;
-	rc.lock_arg = priv;
-	priv->map = devm_regmap_init(dev, NULL, priv, &rc);
-	if (IS_ERR(priv->map)) {
-		ret = PTR_ERR(priv->map);
-		dev_err(dev, "regmap init failed: %d\n", ret);
-		return ret;
-	}
+	struct realtek_priv *priv;
 
-	rc = realtek_mdio_nolock_regmap_config;
-	priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
-	if (IS_ERR(priv->map_nolock)) {
-		ret = PTR_ERR(priv->map_nolock);
-		dev_err(dev, "regmap init failed: %d\n", ret);
-		return ret;
-	}
+	priv = realtek_common_probe_pre(dev, realtek_mdio_regmap_config,
+					realtek_mdio_nolock_regmap_config);
+	if (IS_ERR(priv))
+		return PTR_ERR(priv);
 
-	priv->mdio_addr = 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->mdio_addr = mdiodev->addr;
 	priv->write_reg_noack = realtek_mdio_write;
+	priv->ds_ops = priv->variant->ds_ops_mdio;
 
-	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");
-
-	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
-	if (IS_ERR(priv->reset)) {
-		dev_err(dev, "failed to get RESET GPIO\n");
-		return PTR_ERR(priv->reset);
-	}
-
-	if (priv->reset) {
-		gpiod_set_value(priv->reset, 1);
-		dev_dbg(dev, "asserted RESET\n");
-		msleep(REALTEK_HW_STOP_DELAY);
-		gpiod_set_value(priv->reset, 0);
-		msleep(REALTEK_HW_START_DELAY);
-		dev_dbg(dev, "deasserted RESET\n");
-	}
-
-	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_mdio;
-
-	ret = dsa_register_switch(priv->ds);
-	if (ret) {
-		dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
-		return ret;
-	}
+	return realtek_common_probe_post(priv);
 
-	return 0;
 }
 EXPORT_SYMBOL_GPL(realtek_mdio_probe);
 
@@ -242,14 +152,7 @@ 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);
-
-	/* leave the device reset asserted */
-	if (priv->reset)
-		gpiod_set_value(priv->reset, 1);
+	realtek_common_remove(priv);
 }
 EXPORT_SYMBOL_GPL(realtek_mdio_remove);
 
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 55586d158c0e..246024eec3bd 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -41,12 +41,13 @@
 
 #include "realtek.h"
 #include "realtek-smi.h"
+#include "realtek-common.h"
 
 #define REALTEK_SMI_ACK_RETRY_COUNT		5
 
 static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
 {
-	ndelay(priv->clk_delay);
+	ndelay(priv->variant->clk_delay);
 }
 
 static void realtek_smi_start(struct realtek_priv *priv)
@@ -209,7 +210,7 @@ static int realtek_smi_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
 	realtek_smi_start(priv);
 
 	/* Send READ command */
-	ret = realtek_smi_write_byte(priv, priv->cmd_read);
+	ret = realtek_smi_write_byte(priv, priv->variant->cmd_read);
 	if (ret)
 		goto out;
 
@@ -250,7 +251,7 @@ static int realtek_smi_write_reg(struct realtek_priv *priv,
 	realtek_smi_start(priv);
 
 	/* Send WRITE command */
-	ret = realtek_smi_write_byte(priv, priv->cmd_write);
+	ret = realtek_smi_write_byte(priv, priv->variant->cmd_write);
 	if (ret)
 		goto out;
 
@@ -311,20 +312,6 @@ static int realtek_smi_read(void *ctx, u32 reg, u32 *val)
 	return realtek_smi_read_reg(priv, reg, val);
 }
 
-static void realtek_smi_lock(void *ctx)
-{
-	struct realtek_priv *priv = ctx;
-
-	mutex_lock(&priv->map_lock);
-}
-
-static void realtek_smi_unlock(void *ctx)
-{
-	struct realtek_priv *priv = ctx;
-
-	mutex_unlock(&priv->map_lock);
-}
-
 static const struct regmap_config realtek_smi_regmap_config = {
 	.reg_bits = 10, /* A4..A0 R4..R0 */
 	.val_bits = 16,
@@ -335,8 +322,8 @@ static const struct regmap_config realtek_smi_regmap_config = {
 	.reg_read = realtek_smi_read,
 	.reg_write = realtek_smi_write,
 	.cache_type = REGCACHE_NONE,
-	.lock = realtek_smi_lock,
-	.unlock = realtek_smi_unlock,
+	.lock = realtek_common_lock,
+	.unlock = realtek_common_unlock,
 };
 
 static const struct regmap_config realtek_smi_nolock_regmap_config = {
@@ -411,100 +398,28 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
 
 int realtek_smi_probe(struct platform_device *pdev)
 {
-	const struct realtek_variant *var;
 	struct device *dev = &pdev->dev;
 	struct realtek_priv *priv;
-	struct regmap_config rc;
-	struct device_node *np;
-	int ret;
-
-	var = of_device_get_match_data(dev);
-	np = dev->of_node;
-
-	priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-	priv->chip_data = (void *)priv + sizeof(*priv);
-
-	mutex_init(&priv->map_lock);
-
-	rc = realtek_smi_regmap_config;
-	rc.lock_arg = priv;
-	priv->map = devm_regmap_init(dev, NULL, priv, &rc);
-	if (IS_ERR(priv->map)) {
-		ret = PTR_ERR(priv->map);
-		dev_err(dev, "regmap init failed: %d\n", ret);
-		return ret;
-	}
-
-	rc = realtek_smi_nolock_regmap_config;
-	priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
-	if (IS_ERR(priv->map_nolock)) {
-		ret = PTR_ERR(priv->map_nolock);
-		dev_err(dev, "regmap init failed: %d\n", ret);
-		return ret;
-	}
-
-	/* Link forward and backward */
-	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;
-
-	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);
 
-	/* TODO: if power is software controlled, set up any regulators here */
-
-	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
-	if (IS_ERR(priv->reset)) {
-		dev_err(dev, "failed to get RESET GPIO\n");
-		return PTR_ERR(priv->reset);
-	}
-	if (priv->reset) {
-		gpiod_set_value(priv->reset, 1);
-		dev_dbg(dev, "asserted RESET\n");
-		msleep(REALTEK_HW_STOP_DELAY);
-		gpiod_set_value(priv->reset, 0);
-		msleep(REALTEK_HW_START_DELAY);
-		dev_dbg(dev, "deasserted RESET\n");
-	}
+	priv = realtek_common_probe_pre(dev, realtek_smi_regmap_config,
+					realtek_smi_nolock_regmap_config);
+	if (IS_ERR(priv))
+		return PTR_ERR(priv);
 
 	/* Fetch MDIO pins */
 	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);
 
-	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->write_reg_noack = realtek_smi_write_reg_noack;
+	priv->setup_interface = realtek_smi_setup_mdio;
+	priv->ds_ops = priv->variant->ds_ops_smi;
 
-	priv->ds->ops = var->ds_ops_smi;
-	ret = dsa_register_switch(priv->ds);
-	if (ret) {
-		dev_err_probe(dev, ret, "unable to register switch\n");
-		return ret;
-	}
-	return 0;
+	return realtek_common_probe_post(priv);
 }
 EXPORT_SYMBOL_GPL(realtek_smi_probe);
 
@@ -512,14 +427,7 @@ void realtek_smi_remove(struct platform_device *pdev)
 {
 	struct realtek_priv *priv = platform_get_drvdata(pdev);
 
-	if (!priv)
-		return;
-
-	dsa_unregister_switch(priv->ds);
-
-	/* leave the device reset asserted */
-	if (priv->reset)
-		gpiod_set_value(priv->reset, 1);
+	realtek_common_remove(priv);
 }
 EXPORT_SYMBOL_GPL(realtek_smi_remove);
 
diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index e9ee778665b2..fbd0616c1df3 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -58,11 +58,9 @@ struct realtek_priv {
 	struct mii_bus		*bus;
 	int			mdio_addr;
 
-	unsigned int		clk_delay;
-	u8			cmd_read;
-	u8			cmd_write;
 	spinlock_t		lock; /* Locks around command writes */
 	struct dsa_switch	*ds;
+	const struct dsa_switch_ops *ds_ops;
 	struct irq_domain	*irqdomain;
 	bool			leds_disabled;
 
@@ -79,6 +77,8 @@ struct realtek_priv {
 	int			vlan_enabled;
 	int			vlan4k_enabled;
 
+	const struct realtek_variant *variant;
+
 	char			buf[4096];
 	void			*chip_data; /* Per-chip extra variant data */
 };
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 526bf98cef1d..ac848b965f84 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -103,6 +103,7 @@
 #include "realtek.h"
 #include "realtek-smi.h"
 #include "realtek-mdio.h"
+#include "realtek-common.h"
 
 /* Family-specific data and limits */
 #define RTL8365MB_PHYADDRMAX		7
@@ -691,7 +692,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
 	u32 val;
 	int ret;
 
-	mutex_lock(&priv->map_lock);
+	realtek_common_lock(priv);
 
 	ret = rtl8365mb_phy_poll_busy(priv);
 	if (ret)
@@ -724,7 +725,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
 	*data = val & 0xFFFF;
 
 out:
-	mutex_unlock(&priv->map_lock);
+	realtek_common_unlock(priv);
 
 	return ret;
 }
@@ -735,7 +736,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
 	u32 val;
 	int ret;
 
-	mutex_lock(&priv->map_lock);
+	realtek_common_lock(priv);
 
 	ret = rtl8365mb_phy_poll_busy(priv);
 	if (ret)
@@ -766,7 +767,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
 		goto out;
 
 out:
-	mutex_unlock(&priv->map_lock);
+	realtek_common_unlock(priv);
 
 	return 0;
 }
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 09c17de19457..1cc4de3cf54f 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -24,6 +24,7 @@
 #include "realtek.h"
 #include "realtek-smi.h"
 #include "realtek-mdio.h"
+#include "realtek-common.h"
 
 #define RTL8366RB_PORT_NUM_CPU		5
 #define RTL8366RB_NUM_PORTS		6
@@ -1707,7 +1708,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
 	if (phy > RTL8366RB_PHY_NO_MAX)
 		return -EINVAL;
 
-	mutex_lock(&priv->map_lock);
+	realtek_common_lock(priv);
 
 	ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
 			   RTL8366RB_PHY_CTRL_READ);
@@ -1735,7 +1736,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
 		phy, regnum, reg, val);
 
 out:
-	mutex_unlock(&priv->map_lock);
+	realtek_common_unlock(priv);
 
 	return ret;
 }
@@ -1749,7 +1750,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
 	if (phy > RTL8366RB_PHY_NO_MAX)
 		return -EINVAL;
 
-	mutex_lock(&priv->map_lock);
+	realtek_common_lock(priv);
 
 	ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
 			   RTL8366RB_PHY_CTRL_WRITE);
@@ -1766,7 +1767,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
 		goto out;
 
 out:
-	mutex_unlock(&priv->map_lock);
+	realtek_common_unlock(priv);
 
 	return ret;
 }
-- 
2.43.0


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

* [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common
  2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
                   ` (3 preceding siblings ...)
  2023-12-08  4:41 ` [PATCH net-next 4/7] net: dsa: realtek: create realtek-common Luiz Angelo Daros de Luca
@ 2023-12-08  4:41 ` Luiz Angelo Daros de Luca
  2023-12-08 10:57   ` Alvin Šipraga
  2023-12-08  4:41 ` [PATCH net-next 6/7] net: dsa: realtek: migrate user_mii setup to common Luiz Angelo Daros de Luca
  2023-12-08  4:41 ` [PATCH net-next 7/7] net: dsa: realtek: always use the realtek user mdio driver Luiz Angelo Daros de Luca
  6 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal, Luiz Angelo Daros de Luca

As both realtek-common and realtek-{smi,mdio} must always be loaded
together, we can save some resources merging them into a single module.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/Kconfig          | 4 ++--
 drivers/net/dsa/realtek/Makefile         | 8 +++++---
 drivers/net/dsa/realtek/realtek-common.c | 1 +
 drivers/net/dsa/realtek/realtek-mdio.c   | 4 ----
 drivers/net/dsa/realtek/realtek-smi.c    | 4 ----
 5 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
index 9d182fde11b4..6989972eebc3 100644
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -16,14 +16,14 @@ menuconfig NET_DSA_REALTEK
 if NET_DSA_REALTEK
 
 config NET_DSA_REALTEK_MDIO
-	tristate "Realtek MDIO interface support"
+	bool "Realtek MDIO interface support"
 	depends on OF
 	help
 	  Select to enable support for registering switches configured
 	  through MDIO.
 
 config NET_DSA_REALTEK_SMI
-	tristate "Realtek SMI interface support"
+	bool "Realtek SMI interface support"
 	depends on OF
 	help
 	  Select to enable support for registering switches connected
diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
index 5e0c1ef200a3..88f6652f9850 100644
--- a/drivers/net/dsa/realtek/Makefile
+++ b/drivers/net/dsa/realtek/Makefile
@@ -1,7 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_NET_DSA_REALTEK)		+= realtek-common.o
-obj-$(CONFIG_NET_DSA_REALTEK_MDIO) 	+= realtek-mdio.o
-obj-$(CONFIG_NET_DSA_REALTEK_SMI) 	+= realtek-smi.o
+obj-$(CONFIG_NET_DSA_REALTEK)		+= realtek_common.o
+realtek_common-objs-y			:= realtek-common.o
+realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
+realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
+realtek_common-objs			:= $(realtek_common-objs-y)
 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-common.c b/drivers/net/dsa/realtek/realtek-common.c
index 75b6aa071990..73c25d114dd3 100644
--- a/drivers/net/dsa/realtek/realtek-common.c
+++ b/drivers/net/dsa/realtek/realtek-common.c
@@ -132,5 +132,6 @@ void realtek_common_remove(struct realtek_priv *priv)
 EXPORT_SYMBOL(realtek_common_remove);
 
 MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 MODULE_DESCRIPTION("Realtek DSA switches common module");
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index 4c9a744b72f8..bb5bff719ae9 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -168,7 +168,3 @@ void realtek_mdio_shutdown(struct mdio_device *mdiodev)
 	dev_set_drvdata(&mdiodev->dev, NULL);
 }
 EXPORT_SYMBOL_GPL(realtek_mdio_shutdown);
-
-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-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 246024eec3bd..1ca2aa784d24 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -443,7 +443,3 @@ void realtek_smi_shutdown(struct platform_device *pdev)
 	platform_set_drvdata(pdev, NULL);
 }
 EXPORT_SYMBOL_GPL(realtek_smi_shutdown);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
-MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
-MODULE_LICENSE("GPL");
-- 
2.43.0


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

* [PATCH net-next 6/7] net: dsa: realtek: migrate user_mii setup to common
  2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
                   ` (4 preceding siblings ...)
  2023-12-08  4:41 ` [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common Luiz Angelo Daros de Luca
@ 2023-12-08  4:41 ` Luiz Angelo Daros de Luca
  2023-12-08 11:05   ` Alvin Šipraga
  2023-12-08  4:41 ` [PATCH net-next 7/7] net: dsa: realtek: always use the realtek user mdio driver Luiz Angelo Daros de Luca
  6 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal, Luiz Angelo Daros de Luca

Although there are many mentions to SMI in in the user mdio driver,
including its compatible string, there is nothing special about the SMI
interface in the user mdio bus. That way, the code was migrated to the
common module.

All references to SMI were removed, except for the compatible string
that will still work but warn about using the mdio node name instead.

The variant ds_ops_{smi,mdio} fields were rename to, respectively,
ds_ops_custom_user_mdio and ds_ops_default_user_mdio.

The priv->setup_interface() is also gone. If the ds_ops defines
phy_read/write, it means DSA will handle the user_mii_bus. We don't need
to check in another place. Also, with the function that would define
setup_interface() in common, we can call it directly.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/realtek-common.c | 67 ++++++++++++++++++++++++
 drivers/net/dsa/realtek/realtek-common.h |  1 +
 drivers/net/dsa/realtek/realtek-mdio.c   |  2 +-
 drivers/net/dsa/realtek/realtek-smi.c    | 61 +--------------------
 drivers/net/dsa/realtek/realtek.h        |  5 +-
 drivers/net/dsa/realtek/rtl8365mb.c      | 12 ++---
 drivers/net/dsa/realtek/rtl8366rb.c      | 12 ++---
 7 files changed, 84 insertions(+), 76 deletions(-)

diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
index 73c25d114dd3..64a55cb1ea05 100644
--- a/drivers/net/dsa/realtek/realtek-common.c
+++ b/drivers/net/dsa/realtek/realtek-common.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 
 #include <linux/module.h>
+#include <linux/of_mdio.h>
 
 #include "realtek.h"
 #include "realtek-common.h"
@@ -21,6 +22,72 @@ void realtek_common_unlock(void *ctx)
 }
 EXPORT_SYMBOL_GPL(realtek_common_unlock);
 
+static int realtek_common_user_mdio_read(struct mii_bus *bus, int addr,
+					 int regnum)
+{
+	struct realtek_priv *priv = bus->priv;
+
+	return priv->ops->phy_read(priv, addr, regnum);
+}
+
+static int realtek_common_user_mdio_write(struct mii_bus *bus, int addr,
+					  int regnum, u16 val)
+{
+	struct realtek_priv *priv = bus->priv;
+
+	return priv->ops->phy_write(priv, addr, regnum, val);
+}
+
+int realtek_common_setup_user_mdio(struct dsa_switch *ds)
+{
+	struct realtek_priv *priv =  ds->priv;
+	struct device_node *mdio_np;
+	const char compatible = "realtek,smi-mdio";
+	int ret;
+
+	mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
+	if (!mdio_np) {
+		mdio_np = of_get_compatible_child(priv->dev->of_node, compatible);
+		if (!mdio_np) {
+			dev_err(priv->dev, "no MDIO bus node\n");
+			return -ENODEV;
+		}
+		dev_warn(priv->dev,
+			 "Rename node '%s' to 'mdio' and remove compatible '%s'",
+			 mdio_np->name, compatible);
+	}
+
+	priv->user_mii_bus = devm_mdiobus_alloc(priv->dev);
+	if (!priv->user_mii_bus) {
+		ret = -ENOMEM;
+		goto err_put_node;
+	}
+	priv->user_mii_bus->priv = priv;
+	priv->user_mii_bus->name = "Realtek user MII";
+	priv->user_mii_bus->read = realtek_common_user_mdio_read;
+	priv->user_mii_bus->write = realtek_common_user_mdio_write;
+	snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "Realtek-%d",
+		 ds->index);
+	priv->user_mii_bus->parent = priv->dev;
+	ds->user_mii_bus = priv->user_mii_bus;
+
+	ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
+	of_node_put(mdio_np);
+	if (ret) {
+		dev_err(priv->dev, "unable to register MDIO bus %s\n",
+			priv->user_mii_bus->id);
+		return ret;
+	}
+
+	return 0;
+
+err_put_node:
+	of_node_put(mdio_np);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(realtek_common_setup_user_mdio);
+
 struct realtek_priv *
 realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
 			 struct regmap_config rc_nolock)
diff --git a/drivers/net/dsa/realtek/realtek-common.h b/drivers/net/dsa/realtek/realtek-common.h
index 405bd0d85d2b..4f8c66167b15 100644
--- a/drivers/net/dsa/realtek/realtek-common.h
+++ b/drivers/net/dsa/realtek/realtek-common.h
@@ -7,6 +7,7 @@
 
 void realtek_common_lock(void *ctx);
 void realtek_common_unlock(void *ctx);
+int realtek_common_setup_user_mdio(struct dsa_switch *ds);
 struct realtek_priv *
 realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
 			 struct regmap_config rc_nolock);
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index bb5bff719ae9..37a41bab20b4 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -141,7 +141,7 @@ int realtek_mdio_probe(struct mdio_device *mdiodev)
 	priv->bus = mdiodev->bus;
 	priv->mdio_addr = mdiodev->addr;
 	priv->write_reg_noack = realtek_mdio_write;
-	priv->ds_ops = priv->variant->ds_ops_mdio;
+	priv->ds_ops = priv->variant->ds_ops_default_user_mdio;
 
 	return realtek_common_probe_post(priv);
 
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 1ca2aa784d24..84dde2123b09 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -31,7 +31,6 @@
 #include <linux/spinlock.h>
 #include <linux/skbuff.h>
 #include <linux/of.h>
-#include <linux/of_mdio.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/platform_device.h>
@@ -339,63 +338,6 @@ static const struct regmap_config realtek_smi_nolock_regmap_config = {
 	.disable_locking = true,
 };
 
-static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
-{
-	struct realtek_priv *priv = bus->priv;
-
-	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_priv *priv = bus->priv;
-
-	return priv->ops->phy_write(priv, addr, regnum, val);
-}
-
-static int realtek_smi_setup_mdio(struct dsa_switch *ds)
-{
-	struct realtek_priv *priv =  ds->priv;
-	struct device_node *mdio_np;
-	int ret;
-
-	mdio_np = of_get_compatible_child(priv->dev->of_node, "realtek,smi-mdio");
-	if (!mdio_np) {
-		dev_err(priv->dev, "no MDIO bus node\n");
-		return -ENODEV;
-	}
-
-	priv->user_mii_bus = devm_mdiobus_alloc(priv->dev);
-	if (!priv->user_mii_bus) {
-		ret = -ENOMEM;
-		goto err_put_node;
-	}
-	priv->user_mii_bus->priv = priv;
-	priv->user_mii_bus->name = "SMI user MII";
-	priv->user_mii_bus->read = realtek_smi_mdio_read;
-	priv->user_mii_bus->write = realtek_smi_mdio_write;
-	snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
-		 ds->index);
-	priv->user_mii_bus->parent = priv->dev;
-	ds->user_mii_bus = priv->user_mii_bus;
-
-	ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
-	of_node_put(mdio_np);
-	if (ret) {
-		dev_err(priv->dev, "unable to register MDIO bus %s\n",
-			priv->user_mii_bus->id);
-		return ret;
-	}
-
-	return 0;
-
-err_put_node:
-	of_node_put(mdio_np);
-
-	return ret;
-}
-
 int realtek_smi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -416,8 +358,7 @@ int realtek_smi_probe(struct platform_device *pdev)
 		return PTR_ERR(priv->mdio);
 
 	priv->write_reg_noack = realtek_smi_write_reg_noack;
-	priv->setup_interface = realtek_smi_setup_mdio;
-	priv->ds_ops = priv->variant->ds_ops_smi;
+	priv->ds_ops = priv->variant->ds_ops_custom_user_mdio;
 
 	return realtek_common_probe_post(priv);
 }
diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index fbd0616c1df3..3fa8479c396f 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -71,7 +71,6 @@ 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)(void *ctx, u32 addr, u32 data);
 
 	int			vlan_enabled;
@@ -115,8 +114,8 @@ struct realtek_ops {
 };
 
 struct realtek_variant {
-	const struct dsa_switch_ops *ds_ops_smi;
-	const struct dsa_switch_ops *ds_ops_mdio;
+	const struct dsa_switch_ops *ds_ops_default_user_mdio;
+	const struct dsa_switch_ops *ds_ops_custom_user_mdio;
 	const struct realtek_ops *ops;
 	unsigned int clk_delay;
 	u8 cmd_read;
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index ac848b965f84..a52fb07504b5 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -2017,8 +2017,8 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 	if (ret)
 		goto out_teardown_irq;
 
-	if (priv->setup_interface) {
-		ret = priv->setup_interface(ds);
+	if (!priv->ds_ops->phy_read) {
+		ret = realtek_common_setup_user_mdio(ds);
 		if (ret) {
 			dev_err(priv->dev, "could not set up MDIO bus\n");
 			goto out_teardown_irq;
@@ -2116,7 +2116,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 	return 0;
 }
 
-static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
+static const struct dsa_switch_ops rtl8365mb_switch_ops_custom_user_mdio = {
 	.get_tag_protocol = rtl8365mb_get_tag_protocol,
 	.change_tag_protocol = rtl8365mb_change_tag_protocol,
 	.setup = rtl8365mb_setup,
@@ -2137,7 +2137,7 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
 	.port_max_mtu = rtl8365mb_port_max_mtu,
 };
 
-static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8365mb_switch_ops_default_user_mdio = {
 	.get_tag_protocol = rtl8365mb_get_tag_protocol,
 	.change_tag_protocol = rtl8365mb_change_tag_protocol,
 	.setup = rtl8365mb_setup,
@@ -2167,8 +2167,8 @@ static const struct realtek_ops rtl8365mb_ops = {
 };
 
 const struct realtek_variant rtl8365mb_variant = {
-	.ds_ops_smi = &rtl8365mb_switch_ops_smi,
-	.ds_ops_mdio = &rtl8365mb_switch_ops_mdio,
+	.ds_ops_default_user_mdio = &rtl8365mb_switch_ops_default_user_mdio,
+	.ds_ops_custom_user_mdio = &rtl8365mb_switch_ops_custom_user_mdio,
 	.ops = &rtl8365mb_ops,
 	.clk_delay = 10,
 	.cmd_read = 0xb9,
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 1cc4de3cf54f..9b6997574d2c 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1027,8 +1027,8 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	if (ret)
 		dev_info(priv->dev, "no interrupt support\n");
 
-	if (priv->setup_interface) {
-		ret = priv->setup_interface(ds);
+	if (!priv->ds_ops->phy_read) {
+		ret = realtek_common_setup_user_mdio(ds);
 		if (ret) {
 			dev_err(priv->dev, "could not set up MDIO bus\n");
 			return -ENODEV;
@@ -1848,7 +1848,7 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
 	return 0;
 }
 
-static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
+static const struct dsa_switch_ops rtl8366rb_switch_ops_custom_user_mdio = {
 	.get_tag_protocol = rtl8366_get_tag_protocol,
 	.setup = rtl8366rb_setup,
 	.phylink_get_caps = rtl8366rb_phylink_get_caps,
@@ -1872,7 +1872,7 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
 	.port_max_mtu = rtl8366rb_max_mtu,
 };
 
-static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8366rb_switch_ops_default_user_mdio = {
 	.get_tag_protocol = rtl8366_get_tag_protocol,
 	.setup = rtl8366rb_setup,
 	.phy_read = rtl8366rb_dsa_phy_read,
@@ -1915,8 +1915,8 @@ static const struct realtek_ops rtl8366rb_ops = {
 };
 
 const struct realtek_variant rtl8366rb_variant = {
-	.ds_ops_smi = &rtl8366rb_switch_ops_smi,
-	.ds_ops_mdio = &rtl8366rb_switch_ops_mdio,
+	.ds_ops_default_user_mdio = &rtl8366rb_switch_ops_default_user_mdio,
+	.ds_ops_custom_user_mdio = &rtl8366rb_switch_ops_custom_user_mdio,
 	.ops = &rtl8366rb_ops,
 	.clk_delay = 10,
 	.cmd_read = 0xa9,
-- 
2.43.0


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

* [PATCH net-next 7/7] net: dsa: realtek: always use the realtek user mdio driver
  2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
                   ` (5 preceding siblings ...)
  2023-12-08  4:41 ` [PATCH net-next 6/7] net: dsa: realtek: migrate user_mii setup to common Luiz Angelo Daros de Luca
@ 2023-12-08  4:41 ` Luiz Angelo Daros de Luca
  2023-12-08 11:06   ` Alvin Šipraga
  6 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  4:41 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal, Luiz Angelo Daros de Luca

Although the DSA switch will register a generic mdio driver when
ds_ops.phy_{read,write} exists ("dsa user smi"), it was pointed out that
it was not a core feature to depend on [1]. That way, the realtek user
mdio driver will be used by both interfaces.

[1] https://lkml.kernel.org/netdev/20220630200423.tieprdu5fpabflj7@bang-olufsen.dk/T/

The ds_ops field in realtek_priv was also dropped as now we can directly
reference the variant->ds_ops.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
 drivers/net/dsa/realtek/realtek-common.c |  4 +-
 drivers/net/dsa/realtek/realtek-mdio.c   |  1 -
 drivers/net/dsa/realtek/realtek-smi.c    |  1 -
 drivers/net/dsa/realtek/realtek.h        |  4 +-
 drivers/net/dsa/realtek/rtl8365mb.c      | 49 +++-------------------
 drivers/net/dsa/realtek/rtl8366rb.c      | 52 +++---------------------
 6 files changed, 15 insertions(+), 96 deletions(-)

diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
index 64a55cb1ea05..058c16cea6c3 100644
--- a/drivers/net/dsa/realtek/realtek-common.c
+++ b/drivers/net/dsa/realtek/realtek-common.c
@@ -42,7 +42,7 @@ int realtek_common_setup_user_mdio(struct dsa_switch *ds)
 {
 	struct realtek_priv *priv =  ds->priv;
 	struct device_node *mdio_np;
-	const char compatible = "realtek,smi-mdio";
+	const char *compatible = "realtek,smi-mdio";
 	int ret;
 
 	mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
@@ -172,7 +172,7 @@ int realtek_common_probe_post(struct realtek_priv *priv)
 
 	priv->ds->priv = priv;
 	priv->ds->dev = priv->dev;
-	priv->ds->ops = priv->ds_ops;
+	priv->ds->ops = priv->variant->ds_ops;
 	priv->ds->num_ports = priv->num_ports;
 
 	ret = dsa_register_switch(priv->ds);
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index 37a41bab20b4..bfa2bda35232 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -141,7 +141,6 @@ int realtek_mdio_probe(struct mdio_device *mdiodev)
 	priv->bus = mdiodev->bus;
 	priv->mdio_addr = mdiodev->addr;
 	priv->write_reg_noack = realtek_mdio_write;
-	priv->ds_ops = priv->variant->ds_ops_default_user_mdio;
 
 	return realtek_common_probe_post(priv);
 
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index 84dde2123b09..9a62c9993d7c 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -358,7 +358,6 @@ int realtek_smi_probe(struct platform_device *pdev)
 		return PTR_ERR(priv->mdio);
 
 	priv->write_reg_noack = realtek_smi_write_reg_noack;
-	priv->ds_ops = priv->variant->ds_ops_custom_user_mdio;
 
 	return realtek_common_probe_post(priv);
 }
diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
index 3fa8479c396f..7af6dcc1bb24 100644
--- a/drivers/net/dsa/realtek/realtek.h
+++ b/drivers/net/dsa/realtek/realtek.h
@@ -60,7 +60,6 @@ struct realtek_priv {
 
 	spinlock_t		lock; /* Locks around command writes */
 	struct dsa_switch	*ds;
-	const struct dsa_switch_ops *ds_ops;
 	struct irq_domain	*irqdomain;
 	bool			leds_disabled;
 
@@ -114,8 +113,7 @@ struct realtek_ops {
 };
 
 struct realtek_variant {
-	const struct dsa_switch_ops *ds_ops_default_user_mdio;
-	const struct dsa_switch_ops *ds_ops_custom_user_mdio;
+	const struct dsa_switch_ops *ds_ops;
 	const struct realtek_ops *ops;
 	unsigned int clk_delay;
 	u8 cmd_read;
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index a52fb07504b5..eb20ade9e025 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -828,17 +828,6 @@ static int rtl8365mb_phy_write(struct realtek_priv *priv, int phy, int regnum,
 	return 0;
 }
 
-static int rtl8365mb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
-{
-	return rtl8365mb_phy_read(ds->priv, phy, regnum);
-}
-
-static int rtl8365mb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
-				   u16 val)
-{
-	return rtl8365mb_phy_write(ds->priv, phy, regnum, val);
-}
-
 static const struct rtl8365mb_extint *
 rtl8365mb_get_port_extint(struct realtek_priv *priv, int port)
 {
@@ -2017,12 +2006,10 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
 	if (ret)
 		goto out_teardown_irq;
 
-	if (!priv->ds_ops->phy_read) {
-		ret = realtek_common_setup_user_mdio(ds);
-		if (ret) {
-			dev_err(priv->dev, "could not set up MDIO bus\n");
-			goto out_teardown_irq;
-		}
+	ret = realtek_common_setup_user_mdio(ds);
+	if (ret) {
+		dev_err(priv->dev, "could not set up MDIO bus\n");
+		goto out_teardown_irq;
 	}
 
 	/* Start statistics counter polling */
@@ -2116,28 +2103,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
 	return 0;
 }
 
-static const struct dsa_switch_ops rtl8365mb_switch_ops_custom_user_mdio = {
-	.get_tag_protocol = rtl8365mb_get_tag_protocol,
-	.change_tag_protocol = rtl8365mb_change_tag_protocol,
-	.setup = rtl8365mb_setup,
-	.teardown = rtl8365mb_teardown,
-	.phylink_get_caps = rtl8365mb_phylink_get_caps,
-	.phylink_mac_config = rtl8365mb_phylink_mac_config,
-	.phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
-	.phylink_mac_link_up = rtl8365mb_phylink_mac_link_up,
-	.port_stp_state_set = rtl8365mb_port_stp_state_set,
-	.get_strings = rtl8365mb_get_strings,
-	.get_ethtool_stats = rtl8365mb_get_ethtool_stats,
-	.get_sset_count = rtl8365mb_get_sset_count,
-	.get_eth_phy_stats = rtl8365mb_get_phy_stats,
-	.get_eth_mac_stats = rtl8365mb_get_mac_stats,
-	.get_eth_ctrl_stats = rtl8365mb_get_ctrl_stats,
-	.get_stats64 = rtl8365mb_get_stats64,
-	.port_change_mtu = rtl8365mb_port_change_mtu,
-	.port_max_mtu = rtl8365mb_port_max_mtu,
-};
-
-static const struct dsa_switch_ops rtl8365mb_switch_ops_default_user_mdio = {
+static const struct dsa_switch_ops rtl8365mb_switch_ops = {
 	.get_tag_protocol = rtl8365mb_get_tag_protocol,
 	.change_tag_protocol = rtl8365mb_change_tag_protocol,
 	.setup = rtl8365mb_setup,
@@ -2146,8 +2112,6 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops_default_user_mdio = {
 	.phylink_mac_config = rtl8365mb_phylink_mac_config,
 	.phylink_mac_link_down = rtl8365mb_phylink_mac_link_down,
 	.phylink_mac_link_up = rtl8365mb_phylink_mac_link_up,
-	.phy_read = rtl8365mb_dsa_phy_read,
-	.phy_write = rtl8365mb_dsa_phy_write,
 	.port_stp_state_set = rtl8365mb_port_stp_state_set,
 	.get_strings = rtl8365mb_get_strings,
 	.get_ethtool_stats = rtl8365mb_get_ethtool_stats,
@@ -2167,8 +2131,7 @@ static const struct realtek_ops rtl8365mb_ops = {
 };
 
 const struct realtek_variant rtl8365mb_variant = {
-	.ds_ops_default_user_mdio = &rtl8365mb_switch_ops_default_user_mdio,
-	.ds_ops_custom_user_mdio = &rtl8365mb_switch_ops_custom_user_mdio,
+	.ds_ops = &rtl8365mb_switch_ops,
 	.ops = &rtl8365mb_ops,
 	.clk_delay = 10,
 	.cmd_read = 0xb9,
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 9b6997574d2c..a6caa3cb4e30 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -1027,12 +1027,10 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
 	if (ret)
 		dev_info(priv->dev, "no interrupt support\n");
 
-	if (!priv->ds_ops->phy_read) {
-		ret = realtek_common_setup_user_mdio(ds);
-		if (ret) {
-			dev_err(priv->dev, "could not set up MDIO bus\n");
-			return -ENODEV;
-		}
+	ret = realtek_common_setup_user_mdio(ds);
+	if (ret) {
+		dev_err(priv->dev, "could not set up MDIO bus\n");
+		return -ENODEV;
 	}
 
 	return 0;
@@ -1772,17 +1770,6 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
 	return ret;
 }
 
-static int rtl8366rb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
-{
-	return rtl8366rb_phy_read(ds->priv, phy, regnum);
-}
-
-static int rtl8366rb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
-				   u16 val)
-{
-	return rtl8366rb_phy_write(ds->priv, phy, regnum, val);
-}
-
 static int rtl8366rb_reset_chip(struct realtek_priv *priv)
 {
 	int timeout = 10;
@@ -1848,35 +1835,9 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
 	return 0;
 }
 
-static const struct dsa_switch_ops rtl8366rb_switch_ops_custom_user_mdio = {
-	.get_tag_protocol = rtl8366_get_tag_protocol,
-	.setup = rtl8366rb_setup,
-	.phylink_get_caps = rtl8366rb_phylink_get_caps,
-	.phylink_mac_link_up = rtl8366rb_mac_link_up,
-	.phylink_mac_link_down = rtl8366rb_mac_link_down,
-	.get_strings = rtl8366_get_strings,
-	.get_ethtool_stats = rtl8366_get_ethtool_stats,
-	.get_sset_count = rtl8366_get_sset_count,
-	.port_bridge_join = rtl8366rb_port_bridge_join,
-	.port_bridge_leave = rtl8366rb_port_bridge_leave,
-	.port_vlan_filtering = rtl8366rb_vlan_filtering,
-	.port_vlan_add = rtl8366_vlan_add,
-	.port_vlan_del = rtl8366_vlan_del,
-	.port_enable = rtl8366rb_port_enable,
-	.port_disable = rtl8366rb_port_disable,
-	.port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags,
-	.port_bridge_flags = rtl8366rb_port_bridge_flags,
-	.port_stp_state_set = rtl8366rb_port_stp_state_set,
-	.port_fast_age = rtl8366rb_port_fast_age,
-	.port_change_mtu = rtl8366rb_change_mtu,
-	.port_max_mtu = rtl8366rb_max_mtu,
-};
-
-static const struct dsa_switch_ops rtl8366rb_switch_ops_default_user_mdio = {
+static const struct dsa_switch_ops rtl8366rb_switch_ops = {
 	.get_tag_protocol = rtl8366_get_tag_protocol,
 	.setup = rtl8366rb_setup,
-	.phy_read = rtl8366rb_dsa_phy_read,
-	.phy_write = rtl8366rb_dsa_phy_write,
 	.phylink_get_caps = rtl8366rb_phylink_get_caps,
 	.phylink_mac_link_up = rtl8366rb_mac_link_up,
 	.phylink_mac_link_down = rtl8366rb_mac_link_down,
@@ -1915,8 +1876,7 @@ static const struct realtek_ops rtl8366rb_ops = {
 };
 
 const struct realtek_variant rtl8366rb_variant = {
-	.ds_ops_default_user_mdio = &rtl8366rb_switch_ops_default_user_mdio,
-	.ds_ops_custom_user_mdio = &rtl8366rb_switch_ops_custom_user_mdio,
+	.ds_ops = &rtl8366rb_switch_ops,
 	.ops = &rtl8366rb_ops,
 	.clk_delay = 10,
 	.cmd_read = 0xa9,
-- 
2.43.0


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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-08  4:41 ` [PATCH net-next 4/7] net: dsa: realtek: create realtek-common Luiz Angelo Daros de Luca
@ 2023-12-08  5:01   ` Luiz Angelo Daros de Luca
  2023-12-08 10:52   ` Alvin Šipraga
  2023-12-08 14:02   ` Alvin Šipraga
  2 siblings, 0 replies; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  5:01 UTC (permalink / raw)
  To: linus.walleij
  Cc: alsi, andrew, f.fainelli, olteanv, davem, edumazet, kuba, pabeni,
	arinc.unal, netdev

> Some code can be shared between both interface modules (MDIO and SMI)
> and among variants. Currently, these interface functions are shared:
>
> - realtek_common_lock
> - realtek_common_unlock
> - realtek_common_probe
> - realtek_common_remove
>
> The reset during probe was moved to the last moment before a variant
> detects the switch. This way, we avoid a reset if anything else fails.
>
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Linus, I think I should not have kept your Reviewed-by as there are
changes like moving the match table out of the common module and
splitting the probe into pre/post.

Regards,

Luiz

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-08  4:41 ` [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration Luiz Angelo Daros de Luca
@ 2023-12-08  5:13   ` Luiz Angelo Daros de Luca
  2023-12-08  9:49     ` Alvin Šipraga
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08  5:13 UTC (permalink / raw)
  To: netdev
  Cc: linus.walleij, alsi, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

> diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> index 755546ed8db6..ddcae546afbc 100644
> --- a/drivers/net/dsa/realtek/realtek-smi.c
> +++ b/drivers/net/dsa/realtek/realtek-smi.c
> @@ -389,15 +389,15 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
>         priv->user_mii_bus->write = realtek_smi_mdio_write;
>         snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
>                  ds->index);
> -       priv->user_mii_bus->dev.of_node = mdio_np;
>         priv->user_mii_bus->parent = priv->dev;
>         ds->user_mii_bus = priv->user_mii_bus;
>
>         ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
> +       of_node_put(mdio_np);

I would like some advice on this line. I have seen similar code like
this but I'm not sure if a function that receives that node as an
argument should be responsible to call kobject_get() (or alike) if it
keeps a reference for that node. The of_mdiobus_register does not keep
that node but it does get some child nodes. I don't know if it is ok
to free the parent node (if that ever happens when a child is still in
use).

Regards,

Luiz

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-08  5:13   ` Luiz Angelo Daros de Luca
@ 2023-12-08  9:49     ` Alvin Šipraga
  2023-12-08 18:05       ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08  9:49 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 02:13:25AM -0300, Luiz Angelo Daros de Luca wrote:
> > diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> > index 755546ed8db6..ddcae546afbc 100644
> > --- a/drivers/net/dsa/realtek/realtek-smi.c
> > +++ b/drivers/net/dsa/realtek/realtek-smi.c
> > @@ -389,15 +389,15 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
> >         priv->user_mii_bus->write = realtek_smi_mdio_write;
> >         snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
> >                  ds->index);
> > -       priv->user_mii_bus->dev.of_node = mdio_np;

You do not really justify removing this in your patch. This is not a
purely cosmetic change because now the associated mdiodev will not be
associated with the OF node. I don't know if there is any consequence to
that but it is usually nice to populate this info in the device struct
when it is actually available.

> >         priv->user_mii_bus->parent = priv->dev;
> >         ds->user_mii_bus = priv->user_mii_bus;
> >
> >         ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
> > +       of_node_put(mdio_np);
> 
> I would like some advice on this line. I have seen similar code like
> this but I'm not sure if a function that receives that node as an
> argument should be responsible to call kobject_get() (or alike) if it
> keeps a reference for that node. The of_mdiobus_register does not keep
> that node but it does get some child nodes. I don't know if it is ok
> to free the parent node (if that ever happens when a child is still in
> use).

Yes, it's OK to do that.

> 
> Regards,
> 
> Luiz

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

* Re: [PATCH net-next 1/7] net: dsa: realtek: drop cleanup from realtek_priv
  2023-12-08  4:41 ` [PATCH net-next 1/7] net: dsa: realtek: drop cleanup from realtek_priv Luiz Angelo Daros de Luca
@ 2023-12-08  9:49   ` Alvin Šipraga
  0 siblings, 0 replies; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08  9:49 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 01:41:37AM -0300, Luiz Angelo Daros de Luca wrote:
> It was never used and never referenced.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---

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

>  drivers/net/dsa/realtek/realtek.h | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> index 790488e9c667..e9ee778665b2 100644
> --- a/drivers/net/dsa/realtek/realtek.h
> +++ b/drivers/net/dsa/realtek/realtek.h
> @@ -91,7 +91,6 @@ 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,
> -- 
> 2.43.0
>

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

* Re: [PATCH net-next 3/7] net: dsa: realtek: convert variants into a real driver
  2023-12-08  4:41 ` [PATCH net-next 3/7] net: dsa: realtek: convert variants into a real driver Luiz Angelo Daros de Luca
@ 2023-12-08 10:23   ` Alvin Šipraga
  0 siblings, 0 replies; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08 10:23 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 01:41:39AM -0300, Luiz Angelo Daros de Luca wrote:
> Previously, the interface modules realtek-smi and realtek-mdio were,
> respectively, a platform and an MDIO driver. Each interface module
> repeated the same compatible strings for both variants and they
> referenced symbols from variants.
> 
> Now each variant module was converted into both a platform and an MDIO
> driver. It reverses the relationship between interface and variant
> module, with the variant now using symbols from interface modules.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
>  drivers/net/dsa/realtek/Kconfig        | 20 ++++-------
>  drivers/net/dsa/realtek/realtek-mdio.c | 33 ++++--------------
>  drivers/net/dsa/realtek/realtek-mdio.h | 48 ++++++++++++++++++++++++++
>  drivers/net/dsa/realtek/realtek-smi.c  | 38 ++++----------------
>  drivers/net/dsa/realtek/realtek-smi.h  | 48 ++++++++++++++++++++++++++
>  drivers/net/dsa/realtek/rtl8365mb.c    | 48 +++++++++++++++++++++++++-
>  drivers/net/dsa/realtek/rtl8366rb.c    | 48 +++++++++++++++++++++++++-
>  7 files changed, 210 insertions(+), 73 deletions(-)
>  create mode 100644 drivers/net/dsa/realtek/realtek-mdio.h
>  create mode 100644 drivers/net/dsa/realtek/realtek-smi.h
> 
> diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
> index 060165a85fb7..9d182fde11b4 100644
> --- a/drivers/net/dsa/realtek/Kconfig
> +++ b/drivers/net/dsa/realtek/Kconfig
> @@ -16,37 +16,29 @@ menuconfig NET_DSA_REALTEK
>  if NET_DSA_REALTEK
>  
>  config NET_DSA_REALTEK_MDIO
> -	tristate "Realtek MDIO interface driver"
> +	tristate "Realtek MDIO interface support"
>  	depends on OF
> -	depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
> -	depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
> -	depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
>  	help
>  	  Select to enable support for registering switches configured
>  	  through MDIO.
>  
>  config NET_DSA_REALTEK_SMI
> -	tristate "Realtek SMI interface driver"
> +	tristate "Realtek SMI interface support"
>  	depends on OF
> -	depends on NET_DSA_REALTEK_RTL8365MB || NET_DSA_REALTEK_RTL8366RB
> -	depends on NET_DSA_REALTEK_RTL8365MB || !NET_DSA_REALTEK_RTL8365MB
> -	depends on NET_DSA_REALTEK_RTL8366RB || !NET_DSA_REALTEK_RTL8366RB
>  	help
>  	  Select to enable support for registering switches connected
>  	  through SMI.
>  
>  config NET_DSA_REALTEK_RTL8365MB
> -	tristate "Realtek RTL8365MB switch subdriver"
> -	imply NET_DSA_REALTEK_SMI
> -	imply NET_DSA_REALTEK_MDIO
> +	tristate "Realtek RTL8365MB switch driver"
> +	depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
>  	select NET_DSA_TAG_RTL8_4
>  	help
>  	  Select to enable support for Realtek RTL8365MB-VC and RTL8367S.
>  
>  config NET_DSA_REALTEK_RTL8366RB
> -	tristate "Realtek RTL8366RB switch subdriver"
> -	imply NET_DSA_REALTEK_SMI
> -	imply NET_DSA_REALTEK_MDIO
> +	tristate "Realtek RTL8366RB switch driver"
> +	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/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> index 292e6d087e8b..58966d0625c8 100644
> --- a/drivers/net/dsa/realtek/realtek-mdio.c
> +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> @@ -25,6 +25,7 @@
>  #include <linux/regmap.h>
>  
>  #include "realtek.h"
> +#include "realtek-mdio.h"
>  
>  /* Read/write via mdiobus */
>  #define REALTEK_MDIO_CTRL0_REG		31
> @@ -140,7 +141,7 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
>  	.disable_locking = true,
>  };
>  
> -static int realtek_mdio_probe(struct mdio_device *mdiodev)
> +int realtek_mdio_probe(struct mdio_device *mdiodev)
>  {
>  	struct realtek_priv *priv;
>  	struct device *dev = &mdiodev->dev;
> @@ -235,8 +236,9 @@ static int realtek_mdio_probe(struct mdio_device *mdiodev)
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(realtek_mdio_probe);
>  
> -static void realtek_mdio_remove(struct mdio_device *mdiodev)
> +void realtek_mdio_remove(struct mdio_device *mdiodev)
>  {
>  	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
>  
> @@ -249,8 +251,9 @@ static void realtek_mdio_remove(struct mdio_device *mdiodev)
>  	if (priv->reset)
>  		gpiod_set_value(priv->reset, 1);
>  }
> +EXPORT_SYMBOL_GPL(realtek_mdio_remove);
>  
> -static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
> +void realtek_mdio_shutdown(struct mdio_device *mdiodev)
>  {
>  	struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev);
>  
> @@ -261,29 +264,7 @@ static void realtek_mdio_shutdown(struct mdio_device *mdiodev)
>  
>  	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 = realtek_mdio_of_match,
> -	},
> -	.probe  = realtek_mdio_probe,
> -	.remove = realtek_mdio_remove,
> -	.shutdown = realtek_mdio_shutdown,
> -};
> -
> -mdio_module_driver(realtek_mdio_driver);
> +EXPORT_SYMBOL_GPL(realtek_mdio_shutdown);
>  
>  MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
>  MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface");
> diff --git a/drivers/net/dsa/realtek/realtek-mdio.h b/drivers/net/dsa/realtek/realtek-mdio.h
> new file mode 100644
> index 000000000000..b938a55249c9
> --- /dev/null
> +++ b/drivers/net/dsa/realtek/realtek-mdio.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _REALTEK_MDIO_H
> +#define _REALTEK_MDIO_H
> +
> +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_MDIO)
> +
> +static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
> +{
> +	return mdio_driver_register(drv);
> +}
> +
> +static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
> +{
> +	mdio_driver_unregister(drv);
> +}
> +
> +int realtek_mdio_probe(struct mdio_device *mdiodev);
> +void realtek_mdio_remove(struct mdio_device *mdiodev);
> +void realtek_mdio_shutdown(struct mdio_device *mdiodev);
> +
> +#else
> +
> +static inline int realtek_mdio_driver_register(struct mdio_driver *drv)
> +{
> +	return 0;
> +}
> +
> +static inline void realtek_mdio_driver_unregister(struct mdio_driver *drv)
> +{
> +}
> +
> +static inline int realtek_mdio_probe(struct mdio_device *mdiodev)
> +{
> +	return -ENOENT;
> +}
> +
> +static inline void realtek_mdio_remove(struct mdio_device *mdiodev)
> +{
> +}
> +
> +static inline void realtek_mdio_shutdown(struct mdio_device *mdiodev)
> +{
> +}
> +
> +#endif
> +
> +#endif
> diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> index ddcae546afbc..55586d158c0e 100644
> --- a/drivers/net/dsa/realtek/realtek-smi.c
> +++ b/drivers/net/dsa/realtek/realtek-smi.c
> @@ -40,6 +40,7 @@
>  #include <linux/if_bridge.h>
>  
>  #include "realtek.h"
> +#include "realtek-smi.h"
>  
>  #define REALTEK_SMI_ACK_RETRY_COUNT		5
>  
> @@ -408,7 +409,7 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
>  	return ret;
>  }
>  
> -static int realtek_smi_probe(struct platform_device *pdev)
> +int realtek_smi_probe(struct platform_device *pdev)
>  {
>  	const struct realtek_variant *var;
>  	struct device *dev = &pdev->dev;
> @@ -505,8 +506,9 @@ static int realtek_smi_probe(struct platform_device *pdev)
>  	}
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(realtek_smi_probe);
>  
> -static void realtek_smi_remove(struct platform_device *pdev)
> +void realtek_smi_remove(struct platform_device *pdev)
>  {
>  	struct realtek_priv *priv = platform_get_drvdata(pdev);
>  
> @@ -519,8 +521,9 @@ static void realtek_smi_remove(struct platform_device *pdev)
>  	if (priv->reset)
>  		gpiod_set_value(priv->reset, 1);
>  }
> +EXPORT_SYMBOL_GPL(realtek_smi_remove);
>  
> -static void realtek_smi_shutdown(struct platform_device *pdev)
> +void realtek_smi_shutdown(struct platform_device *pdev)
>  {
>  	struct realtek_priv *priv = platform_get_drvdata(pdev);
>  
> @@ -531,34 +534,7 @@ static void realtek_smi_shutdown(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, NULL);
>  }
> -
> -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
> -#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB)
> -	{
> -		.compatible = "realtek,rtl8365mb",
> -		.data = &rtl8365mb_variant,
> -	},
> -#endif
> -	{ /* sentinel */ },
> -};
> -MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
> -
> -static struct platform_driver realtek_smi_driver = {
> -	.driver = {
> -		.name = "realtek-smi",
> -		.of_match_table = realtek_smi_of_match,
> -	},
> -	.probe  = realtek_smi_probe,
> -	.remove_new = realtek_smi_remove,
> -	.shutdown = realtek_smi_shutdown,
> -};
> -module_platform_driver(realtek_smi_driver);
> +EXPORT_SYMBOL_GPL(realtek_smi_shutdown);
>  
>  MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
>  MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
> diff --git a/drivers/net/dsa/realtek/realtek-smi.h b/drivers/net/dsa/realtek/realtek-smi.h
> new file mode 100644
> index 000000000000..76fb58df728b
> --- /dev/null
> +++ b/drivers/net/dsa/realtek/realtek-smi.h
> @@ -0,0 +1,48 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _REALTEK_SMI_H
> +#define _REALTEK_SMI_H
> +
> +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_SMI)
> +
> +static inline int realtek_smi_driver_register(struct platform_driver *drv)
> +{
> +	return platform_driver_register(drv);
> +}
> +
> +static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
> +{
> +	platform_driver_unregister(drv);
> +}
> +
> +int realtek_smi_probe(struct platform_device *pdev);
> +void realtek_smi_remove(struct platform_device *pdev);
> +void realtek_smi_shutdown(struct platform_device *pdev);
> +
> +#else
> +
> +static inline int realtek_smi_driver_register(struct platform_driver *drv)
> +{
> +	return 0;
> +}
> +
> +static inline void realtek_smi_driver_unregister(struct platform_driver *drv)
> +{
> +}
> +
> +static inline int realtek_smi_probe(struct platform_device *pdev)
> +{
> +	return -ENOENT;
> +}
> +
> +static inline void realtek_smi_remove(struct platform_device *pdev)
> +{
> +}
> +
> +static inline void realtek_smi_shutdown(struct platform_device *pdev)
> +{
> +}
> +
> +#endif
> +
> +#endif

nit: please add /* _REALTEK_SMI_H */ and /* IS_ENABLED(etc.) */ after
the #endifs to make it more readable.

> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index 0875e4fc9f57..526bf98cef1d 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -101,6 +101,8 @@
>  #include <linux/if_vlan.h>
>  
>  #include "realtek.h"
> +#include "realtek-smi.h"
> +#include "realtek-mdio.h"
>  
>  /* Family-specific data and limits */
>  #define RTL8365MB_PHYADDRMAX		7
> @@ -2172,7 +2174,51 @@ const struct realtek_variant rtl8365mb_variant = {
>  	.cmd_write = 0xb8,
>  	.chip_data_sz = sizeof(struct rtl8365mb),
>  };
> -EXPORT_SYMBOL_GPL(rtl8365mb_variant);
> +
> +static const struct of_device_id rtl8365mb_of_match[] = {
> +	{ .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, },
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, rtl8365mb_of_match);
> +
> +static struct platform_driver rtl8365mb_smi_driver = {
> +	.driver = {
> +		.name = "rtl8365mb-smi",
> +		.of_match_table = rtl8365mb_of_match,
> +	},
> +	.probe  = realtek_smi_probe,
> +	.remove_new = realtek_smi_remove,
> +	.shutdown = realtek_smi_shutdown,
> +};
> +
> +static struct mdio_driver rtl8365mb_mdio_driver = {
> +	.mdiodrv.driver = {
> +		.name = "rtl8365mb-mdio",
> +		.of_match_table = rtl8365mb_of_match,
> +	},
> +	.probe  = realtek_mdio_probe,
> +	.remove = realtek_mdio_remove,
> +	.shutdown = realtek_mdio_shutdown,
> +};
> +
> +static int rtl8365mb_init(void)
> +{
> +	int ret;
> +
> +	ret = realtek_mdio_driver_register(&rtl8365mb_mdio_driver);
> +	if (ret)
> +		return ret;
> +
> +	return platform_driver_register(&rtl8365mb_smi_driver);

If this fails I think you should also unwind by unregistering the mdio
driver.

> +}
> +module_init(rtl8365mb_init);
> +
> +static void __exit rtl8365mb_exit(void)
> +{
> +	realtek_mdio_driver_unregister(&rtl8365mb_mdio_driver);
> +	platform_driver_unregister(&rtl8365mb_smi_driver);

Normally in these unwind functions I like to see the unregistration
performed in an RAII manner, so unregistering the last-registered thing
first. i.e. reverse the order of these lines. Same comments hold for SMI
below.

> +}
> +module_exit(rtl8365mb_exit);
>  
>  MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
>  MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
> diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> index b39b719a5b8f..09c17de19457 100644
> --- a/drivers/net/dsa/realtek/rtl8366rb.c
> +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> @@ -22,6 +22,8 @@
>  #include <linux/regmap.h>
>  
>  #include "realtek.h"
> +#include "realtek-smi.h"
> +#include "realtek-mdio.h"
>  
>  #define RTL8366RB_PORT_NUM_CPU		5
>  #define RTL8366RB_NUM_PORTS		6
> @@ -1920,7 +1922,51 @@ const struct realtek_variant rtl8366rb_variant = {
>  	.cmd_write = 0xa8,
>  	.chip_data_sz = sizeof(struct rtl8366rb),
>  };
> -EXPORT_SYMBOL_GPL(rtl8366rb_variant);
> +
> +static const struct of_device_id rtl8366rb_of_match[] = {
> +	{ .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, },
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, rtl8366rb_of_match);
> +
> +static struct platform_driver rtl8366rb_smi_driver = {
> +	.driver = {
> +		.name = "rtl8366rb-smi",
> +		.of_match_table = rtl8366rb_of_match,
> +	},
> +	.probe  = realtek_smi_probe,
> +	.remove_new = realtek_smi_remove,
> +	.shutdown = realtek_smi_shutdown,
> +};
> +
> +static struct mdio_driver rtl8366rb_mdio_driver = {
> +	.mdiodrv.driver = {
> +		.name = "rtl8366rb-mdio",
> +		.of_match_table = rtl8366rb_of_match,
> +	},
> +	.probe  = realtek_mdio_probe,
> +	.remove = realtek_mdio_remove,
> +	.shutdown = realtek_mdio_shutdown,
> +};
> +
> +static int rtl8366rb_init(void)
> +{
> +	int ret;
> +
> +	ret = realtek_mdio_driver_register(&rtl8366rb_mdio_driver);
> +	if (ret)
> +		return ret;
> +
> +	return realtek_smi_driver_register(&rtl8366rb_smi_driver);
> +}
> +module_init(rtl8366rb_init);
> +
> +static void __exit rtl8366rb_exit(void)
> +{
> +	realtek_mdio_driver_unregister(&rtl8366rb_mdio_driver);
> +	realtek_smi_driver_unregister(&rtl8366rb_smi_driver);
> +}
> +module_exit(rtl8366rb_exit);
>  
>  MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
>  MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
> -- 
> 2.43.0
>

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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-08  4:41 ` [PATCH net-next 4/7] net: dsa: realtek: create realtek-common Luiz Angelo Daros de Luca
  2023-12-08  5:01   ` Luiz Angelo Daros de Luca
@ 2023-12-08 10:52   ` Alvin Šipraga
  2023-12-11  5:02     ` Luiz Angelo Daros de Luca
  2023-12-08 14:02   ` Alvin Šipraga
  2 siblings, 1 reply; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08 10:52 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 01:41:40AM -0300, Luiz Angelo Daros de Luca wrote:
> Some code can be shared between both interface modules (MDIO and SMI)
> and among variants. Currently, these interface functions are shared:
> 
> - realtek_common_lock
> - realtek_common_unlock
> - realtek_common_probe
> - realtek_common_remove
> 
> The reset during probe was moved to the last moment before a variant
> detects the switch. This way, we avoid a reset if anything else fails.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> ---
>  drivers/net/dsa/realtek/Makefile         |   1 +
>  drivers/net/dsa/realtek/realtek-common.c | 136 +++++++++++++++++++++++
>  drivers/net/dsa/realtek/realtek-common.h |  16 +++
>  drivers/net/dsa/realtek/realtek-mdio.c   | 121 ++------------------
>  drivers/net/dsa/realtek/realtek-smi.c    | 124 +++------------------
>  drivers/net/dsa/realtek/realtek.h        |   6 +-
>  drivers/net/dsa/realtek/rtl8365mb.c      |   9 +-
>  drivers/net/dsa/realtek/rtl8366rb.c      |   9 +-
>  8 files changed, 194 insertions(+), 228 deletions(-)
>  create mode 100644 drivers/net/dsa/realtek/realtek-common.c
>  create mode 100644 drivers/net/dsa/realtek/realtek-common.h
> 
> diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> index 0aab57252a7c..5e0c1ef200a3 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)		+= realtek-common.o

No corresponding Kconfig change?

>  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
> diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
> new file mode 100644
> index 000000000000..75b6aa071990
> --- /dev/null
> +++ b/drivers/net/dsa/realtek/realtek-common.c
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +#include <linux/module.h>
> +
> +#include "realtek.h"
> +#include "realtek-common.h"
> +
> +void realtek_common_lock(void *ctx)
> +{
> +	struct realtek_priv *priv = ctx;
> +
> +	mutex_lock(&priv->map_lock);
> +}
> +EXPORT_SYMBOL_GPL(realtek_common_lock);
> +
> +void realtek_common_unlock(void *ctx)
> +{
> +	struct realtek_priv *priv = ctx;
> +
> +	mutex_unlock(&priv->map_lock);
> +}
> +EXPORT_SYMBOL_GPL(realtek_common_unlock);
> +
> +struct realtek_priv *
> +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> +			 struct regmap_config rc_nolock)
> +{
> +	const struct realtek_variant *var;
> +	struct realtek_priv *priv;
> +	struct device_node *np;
> +	int ret;
> +
> +	var = of_device_get_match_data(dev);
> +	if (!var)
> +		return ERR_PTR(-EINVAL);
> +
> +	priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz),
> +			    GFP_KERNEL);
> +	if (!priv)
> +		return ERR_PTR(-ENOMEM);
> +
> +	mutex_init(&priv->map_lock);
> +
> +	rc.lock_arg = priv;
> +	priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> +	if (IS_ERR(priv->map)) {
> +		ret = PTR_ERR(priv->map);
> +		dev_err(dev, "regmap init failed: %d\n", ret);
> +		return ERR_PTR(ret);
> +	}
> +
> +	priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc_nolock);
> +	if (IS_ERR(priv->map_nolock)) {
> +		ret = PTR_ERR(priv->map_nolock);
> +		dev_err(dev, "regmap init failed: %d\n", ret);
> +		return ERR_PTR(ret);
> +	}
> +
> +	/* Link forward and backward */
> +	priv->dev = dev;
> +	priv->variant = var;
> +	priv->ops = var->ops;
> +	priv->chip_data = (void *)priv + sizeof(*priv);
> +
> +	dev_set_drvdata(dev, priv);
> +	spin_lock_init(&priv->lock);
> +
> +	np = dev->of_node;

This is kind of a pointless variable, just do
of_property_read_bool(dev->of_node, ...) below.

> +
> +	priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
> +
> +	/* TODO: if power is software controlled, set up any regulators here */
> +
> +	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> +	if (IS_ERR(priv->reset)) {
> +		dev_err(dev, "failed to get RESET GPIO\n");
> +		return ERR_CAST(priv->reset);
> +	}
> +	if (priv->reset) {
> +		gpiod_set_value(priv->reset, 1);
> +		dev_dbg(dev, "asserted RESET\n");
> +		msleep(REALTEK_HW_STOP_DELAY);
> +		gpiod_set_value(priv->reset, 0);
> +		msleep(REALTEK_HW_START_DELAY);
> +		dev_dbg(dev, "deasserted RESET\n");
> +	}
> +
> +	return priv;
> +}
> +EXPORT_SYMBOL(realtek_common_probe_pre);
> +
> +int realtek_common_probe_post(struct realtek_priv *priv)
> +{
> +	int ret;
> +
> +	ret = priv->ops->detect(priv);
> +	if (ret) {
> +		dev_err(priv->dev, "unable to detect switch\n");

dev_err_probe()?

> +		return ret;
> +	}
> +
> +	priv->ds = devm_kzalloc(priv->dev, sizeof(*priv->ds), GFP_KERNEL);
> +	if (!priv->ds)
> +		return -ENOMEM;

I guess this could actually just be embedded in realtek_priv and then
you don't need to allocate it dynamically here.

> +
> +	priv->ds->priv = priv;
> +	priv->ds->dev = priv->dev;
> +	priv->ds->ops = priv->ds_ops;
> +	priv->ds->num_ports = priv->num_ports;
> +
> +	ret = dsa_register_switch(priv->ds);
> +	if (ret) {
> +		dev_err_probe(priv->dev, ret, "unable to register switch\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(realtek_common_probe_post);
> +
> +void realtek_common_remove(struct realtek_priv *priv)
> +{
> +	if (!priv)
> +		return;
> +
> +	dsa_unregister_switch(priv->ds);
> +
> +	/* leave the device reset asserted */
> +	if (priv->reset)
> +		gpiod_set_value(priv->reset, 1);
> +}
> +EXPORT_SYMBOL(realtek_common_remove);
> +
> +MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
> +MODULE_DESCRIPTION("Realtek DSA switches common module");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/dsa/realtek/realtek-common.h b/drivers/net/dsa/realtek/realtek-common.h
> new file mode 100644
> index 000000000000..405bd0d85d2b
> --- /dev/null
> +++ b/drivers/net/dsa/realtek/realtek-common.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef _REALTEK_INTERFACE_H
> +#define _REALTEK_INTERFACE_H
> +
> +#include <linux/regmap.h>
> +
> +void realtek_common_lock(void *ctx);
> +void realtek_common_unlock(void *ctx);
> +struct realtek_priv *
> +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> +			 struct regmap_config rc_nolock);
> +int realtek_common_probe_post(struct realtek_priv *priv);

Maybe it is worth describing what these functions do with a comment.

pre:  sets up driver private data struct, sets up regmaps, issues
      hardware reset

post: registers the dsa switch, calls detect() and then expects
      priv->num_ports to be set

The detect() function in itself is a bit funny. Maybe it's not even
necessary. Both chip variants set a static num_ports value anyway. You
can maybe dump detect() completely and move that code into the
variant-specific probe between the calls to common_probe_{pre,post}().

> +void realtek_common_remove(struct realtek_priv *priv);
> +
> +#endif

#endif /* _REALTEK_INTERFACE_H */

Actually shouldn't it be _REALTEK_COMMON_H?

> diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> index 58966d0625c8..4c9a744b72f8 100644
> --- a/drivers/net/dsa/realtek/realtek-mdio.c
> +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> @@ -26,6 +26,7 @@
>  
>  #include "realtek.h"
>  #include "realtek-mdio.h"
> +#include "realtek-common.h"
>  
>  /* Read/write via mdiobus */
>  #define REALTEK_MDIO_CTRL0_REG		31
> @@ -100,20 +101,6 @@ static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
>  	return ret;
>  }
>  
> -static void realtek_mdio_lock(void *ctx)
> -{
> -	struct realtek_priv *priv = ctx;
> -
> -	mutex_lock(&priv->map_lock);
> -}
> -
> -static void realtek_mdio_unlock(void *ctx)
> -{
> -	struct realtek_priv *priv = ctx;
> -
> -	mutex_unlock(&priv->map_lock);
> -}
> -
>  static const struct regmap_config realtek_mdio_regmap_config = {
>  	.reg_bits = 10, /* A4..A0 R4..R0 */
>  	.val_bits = 16,
> @@ -124,8 +111,8 @@ static const struct regmap_config realtek_mdio_regmap_config = {
>  	.reg_read = realtek_mdio_read,
>  	.reg_write = realtek_mdio_write,
>  	.cache_type = REGCACHE_NONE,
> -	.lock = realtek_mdio_lock,
> -	.unlock = realtek_mdio_unlock,
> +	.lock = realtek_common_lock,
> +	.unlock = realtek_common_unlock,
>  };
>  
>  static const struct regmap_config realtek_mdio_nolock_regmap_config = {
> @@ -143,98 +130,21 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
>  
>  int realtek_mdio_probe(struct mdio_device *mdiodev)
>  {
> -	struct realtek_priv *priv;
>  	struct device *dev = &mdiodev->dev;
> -	const struct realtek_variant *var;
> -	struct regmap_config rc;
> -	struct device_node *np;
> -	int ret;
> -
> -	var = of_device_get_match_data(dev);
> -	if (!var)
> -		return -EINVAL;
> -
> -	priv = devm_kzalloc(&mdiodev->dev,
> -			    size_add(sizeof(*priv), var->chip_data_sz),
> -			    GFP_KERNEL);
> -	if (!priv)
> -		return -ENOMEM;
> -
> -	mutex_init(&priv->map_lock);
> -
> -	rc = realtek_mdio_regmap_config;
> -	rc.lock_arg = priv;
> -	priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> -	if (IS_ERR(priv->map)) {
> -		ret = PTR_ERR(priv->map);
> -		dev_err(dev, "regmap init failed: %d\n", ret);
> -		return ret;
> -	}
> +	struct realtek_priv *priv;
>  
> -	rc = realtek_mdio_nolock_regmap_config;
> -	priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
> -	if (IS_ERR(priv->map_nolock)) {
> -		ret = PTR_ERR(priv->map_nolock);
> -		dev_err(dev, "regmap init failed: %d\n", ret);
> -		return ret;
> -	}
> +	priv = realtek_common_probe_pre(dev, realtek_mdio_regmap_config,
> +					realtek_mdio_nolock_regmap_config);
> +	if (IS_ERR(priv))
> +		return PTR_ERR(priv);
>  
> -	priv->mdio_addr = 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->mdio_addr = mdiodev->addr;
>  	priv->write_reg_noack = realtek_mdio_write;
> +	priv->ds_ops = priv->variant->ds_ops_mdio;
>  
> -	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");
> -
> -	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> -	if (IS_ERR(priv->reset)) {
> -		dev_err(dev, "failed to get RESET GPIO\n");
> -		return PTR_ERR(priv->reset);
> -	}
> -
> -	if (priv->reset) {
> -		gpiod_set_value(priv->reset, 1);
> -		dev_dbg(dev, "asserted RESET\n");
> -		msleep(REALTEK_HW_STOP_DELAY);
> -		gpiod_set_value(priv->reset, 0);
> -		msleep(REALTEK_HW_START_DELAY);
> -		dev_dbg(dev, "deasserted RESET\n");
> -	}
> -
> -	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_mdio;
> -
> -	ret = dsa_register_switch(priv->ds);
> -	if (ret) {
> -		dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
> -		return ret;
> -	}
> +	return realtek_common_probe_post(priv);
>  
> -	return 0;
>  }
>  EXPORT_SYMBOL_GPL(realtek_mdio_probe);
>  
> @@ -242,14 +152,7 @@ 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);
> -
> -	/* leave the device reset asserted */
> -	if (priv->reset)
> -		gpiod_set_value(priv->reset, 1);
> +	realtek_common_remove(priv);
>  }
>  EXPORT_SYMBOL_GPL(realtek_mdio_remove);
>  
> diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> index 55586d158c0e..246024eec3bd 100644
> --- a/drivers/net/dsa/realtek/realtek-smi.c
> +++ b/drivers/net/dsa/realtek/realtek-smi.c
> @@ -41,12 +41,13 @@
>  
>  #include "realtek.h"
>  #include "realtek-smi.h"
> +#include "realtek-common.h"
>  
>  #define REALTEK_SMI_ACK_RETRY_COUNT		5
>  
>  static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
>  {
> -	ndelay(priv->clk_delay);
> +	ndelay(priv->variant->clk_delay);
>  }
>  
>  static void realtek_smi_start(struct realtek_priv *priv)
> @@ -209,7 +210,7 @@ static int realtek_smi_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
>  	realtek_smi_start(priv);
>  
>  	/* Send READ command */
> -	ret = realtek_smi_write_byte(priv, priv->cmd_read);
> +	ret = realtek_smi_write_byte(priv, priv->variant->cmd_read);
>  	if (ret)
>  		goto out;
>  
> @@ -250,7 +251,7 @@ static int realtek_smi_write_reg(struct realtek_priv *priv,
>  	realtek_smi_start(priv);
>  
>  	/* Send WRITE command */
> -	ret = realtek_smi_write_byte(priv, priv->cmd_write);
> +	ret = realtek_smi_write_byte(priv, priv->variant->cmd_write);
>  	if (ret)
>  		goto out;
>  
> @@ -311,20 +312,6 @@ static int realtek_smi_read(void *ctx, u32 reg, u32 *val)
>  	return realtek_smi_read_reg(priv, reg, val);
>  }
>  
> -static void realtek_smi_lock(void *ctx)
> -{
> -	struct realtek_priv *priv = ctx;
> -
> -	mutex_lock(&priv->map_lock);
> -}
> -
> -static void realtek_smi_unlock(void *ctx)
> -{
> -	struct realtek_priv *priv = ctx;
> -
> -	mutex_unlock(&priv->map_lock);
> -}
> -
>  static const struct regmap_config realtek_smi_regmap_config = {
>  	.reg_bits = 10, /* A4..A0 R4..R0 */
>  	.val_bits = 16,
> @@ -335,8 +322,8 @@ static const struct regmap_config realtek_smi_regmap_config = {
>  	.reg_read = realtek_smi_read,
>  	.reg_write = realtek_smi_write,
>  	.cache_type = REGCACHE_NONE,
> -	.lock = realtek_smi_lock,
> -	.unlock = realtek_smi_unlock,
> +	.lock = realtek_common_lock,
> +	.unlock = realtek_common_unlock,
>  };
>  
>  static const struct regmap_config realtek_smi_nolock_regmap_config = {
> @@ -411,100 +398,28 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
>  
>  int realtek_smi_probe(struct platform_device *pdev)
>  {
> -	const struct realtek_variant *var;
>  	struct device *dev = &pdev->dev;
>  	struct realtek_priv *priv;
> -	struct regmap_config rc;
> -	struct device_node *np;
> -	int ret;
> -
> -	var = of_device_get_match_data(dev);
> -	np = dev->of_node;
> -
> -	priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
> -	if (!priv)
> -		return -ENOMEM;
> -	priv->chip_data = (void *)priv + sizeof(*priv);
> -
> -	mutex_init(&priv->map_lock);
> -
> -	rc = realtek_smi_regmap_config;
> -	rc.lock_arg = priv;
> -	priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> -	if (IS_ERR(priv->map)) {
> -		ret = PTR_ERR(priv->map);
> -		dev_err(dev, "regmap init failed: %d\n", ret);
> -		return ret;
> -	}
> -
> -	rc = realtek_smi_nolock_regmap_config;
> -	priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
> -	if (IS_ERR(priv->map_nolock)) {
> -		ret = PTR_ERR(priv->map_nolock);
> -		dev_err(dev, "regmap init failed: %d\n", ret);
> -		return ret;
> -	}
> -
> -	/* Link forward and backward */
> -	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;
> -
> -	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);
>  
> -	/* TODO: if power is software controlled, set up any regulators here */
> -
> -	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> -	if (IS_ERR(priv->reset)) {
> -		dev_err(dev, "failed to get RESET GPIO\n");
> -		return PTR_ERR(priv->reset);
> -	}
> -	if (priv->reset) {
> -		gpiod_set_value(priv->reset, 1);
> -		dev_dbg(dev, "asserted RESET\n");
> -		msleep(REALTEK_HW_STOP_DELAY);
> -		gpiod_set_value(priv->reset, 0);
> -		msleep(REALTEK_HW_START_DELAY);
> -		dev_dbg(dev, "deasserted RESET\n");
> -	}
> +	priv = realtek_common_probe_pre(dev, realtek_smi_regmap_config,
> +					realtek_smi_nolock_regmap_config);
> +	if (IS_ERR(priv))
> +		return PTR_ERR(priv);
>  
>  	/* Fetch MDIO pins */
>  	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);
>  
> -	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->write_reg_noack = realtek_smi_write_reg_noack;
> +	priv->setup_interface = realtek_smi_setup_mdio;
> +	priv->ds_ops = priv->variant->ds_ops_smi;
>  
> -	priv->ds->ops = var->ds_ops_smi;
> -	ret = dsa_register_switch(priv->ds);
> -	if (ret) {
> -		dev_err_probe(dev, ret, "unable to register switch\n");
> -		return ret;
> -	}
> -	return 0;
> +	return realtek_common_probe_post(priv);

ret = realtek_common_probe_post(priv);
if (ret)
  return ret;

return 0;

>  }
>  EXPORT_SYMBOL_GPL(realtek_smi_probe);
>  
> @@ -512,14 +427,7 @@ void realtek_smi_remove(struct platform_device *pdev)
>  {
>  	struct realtek_priv *priv = platform_get_drvdata(pdev);
>  
> -	if (!priv)
> -		return;
> -
> -	dsa_unregister_switch(priv->ds);
> -
> -	/* leave the device reset asserted */
> -	if (priv->reset)
> -		gpiod_set_value(priv->reset, 1);
> +	realtek_common_remove(priv);
>  }
>  EXPORT_SYMBOL_GPL(realtek_smi_remove);
>  
> diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> index e9ee778665b2..fbd0616c1df3 100644
> --- a/drivers/net/dsa/realtek/realtek.h
> +++ b/drivers/net/dsa/realtek/realtek.h
> @@ -58,11 +58,9 @@ struct realtek_priv {
>  	struct mii_bus		*bus;
>  	int			mdio_addr;
>  
> -	unsigned int		clk_delay;
> -	u8			cmd_read;
> -	u8			cmd_write;
>  	spinlock_t		lock; /* Locks around command writes */
>  	struct dsa_switch	*ds;
> +	const struct dsa_switch_ops *ds_ops;
>  	struct irq_domain	*irqdomain;
>  	bool			leds_disabled;
>  
> @@ -79,6 +77,8 @@ struct realtek_priv {
>  	int			vlan_enabled;
>  	int			vlan4k_enabled;
>  
> +	const struct realtek_variant *variant;
> +
>  	char			buf[4096];
>  	void			*chip_data; /* Per-chip extra variant data */
>  };
> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index 526bf98cef1d..ac848b965f84 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -103,6 +103,7 @@
>  #include "realtek.h"
>  #include "realtek-smi.h"
>  #include "realtek-mdio.h"
> +#include "realtek-common.h"
>  
>  /* Family-specific data and limits */
>  #define RTL8365MB_PHYADDRMAX		7
> @@ -691,7 +692,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
>  	u32 val;
>  	int ret;
>  
> -	mutex_lock(&priv->map_lock);
> +	realtek_common_lock(priv);
>  
>  	ret = rtl8365mb_phy_poll_busy(priv);
>  	if (ret)
> @@ -724,7 +725,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
>  	*data = val & 0xFFFF;
>  
>  out:
> -	mutex_unlock(&priv->map_lock);
> +	realtek_common_unlock(priv);
>  
>  	return ret;
>  }
> @@ -735,7 +736,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
>  	u32 val;
>  	int ret;
>  
> -	mutex_lock(&priv->map_lock);
> +	realtek_common_lock(priv);
>  
>  	ret = rtl8365mb_phy_poll_busy(priv);
>  	if (ret)
> @@ -766,7 +767,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
>  		goto out;
>  
>  out:
> -	mutex_unlock(&priv->map_lock);
> +	realtek_common_unlock(priv);
>  
>  	return 0;
>  }
> diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> index 09c17de19457..1cc4de3cf54f 100644
> --- a/drivers/net/dsa/realtek/rtl8366rb.c
> +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> @@ -24,6 +24,7 @@
>  #include "realtek.h"
>  #include "realtek-smi.h"
>  #include "realtek-mdio.h"
> +#include "realtek-common.h"
>  
>  #define RTL8366RB_PORT_NUM_CPU		5
>  #define RTL8366RB_NUM_PORTS		6
> @@ -1707,7 +1708,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
>  	if (phy > RTL8366RB_PHY_NO_MAX)
>  		return -EINVAL;
>  
> -	mutex_lock(&priv->map_lock);
> +	realtek_common_lock(priv);
>  
>  	ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
>  			   RTL8366RB_PHY_CTRL_READ);
> @@ -1735,7 +1736,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
>  		phy, regnum, reg, val);
>  
>  out:
> -	mutex_unlock(&priv->map_lock);
> +	realtek_common_unlock(priv);
>  
>  	return ret;
>  }
> @@ -1749,7 +1750,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
>  	if (phy > RTL8366RB_PHY_NO_MAX)
>  		return -EINVAL;
>  
> -	mutex_lock(&priv->map_lock);
> +	realtek_common_lock(priv);
>  
>  	ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
>  			   RTL8366RB_PHY_CTRL_WRITE);
> @@ -1766,7 +1767,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
>  		goto out;
>  
>  out:
> -	mutex_unlock(&priv->map_lock);
> +	realtek_common_unlock(priv);
>  
>  	return ret;
>  }
> -- 
> 2.43.0
>

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

* Re: [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common
  2023-12-08  4:41 ` [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common Luiz Angelo Daros de Luca
@ 2023-12-08 10:57   ` Alvin Šipraga
  2023-12-11  5:13     ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08 10:57 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 01:41:41AM -0300, Luiz Angelo Daros de Luca wrote:
> As both realtek-common and realtek-{smi,mdio} must always be loaded
> together, we can save some resources merging them into a single module.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
>  drivers/net/dsa/realtek/Kconfig          | 4 ++--
>  drivers/net/dsa/realtek/Makefile         | 8 +++++---
>  drivers/net/dsa/realtek/realtek-common.c | 1 +
>  drivers/net/dsa/realtek/realtek-mdio.c   | 4 ----
>  drivers/net/dsa/realtek/realtek-smi.c    | 4 ----
>  5 files changed, 8 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
> index 9d182fde11b4..6989972eebc3 100644
> --- a/drivers/net/dsa/realtek/Kconfig
> +++ b/drivers/net/dsa/realtek/Kconfig
> @@ -16,14 +16,14 @@ menuconfig NET_DSA_REALTEK
>  if NET_DSA_REALTEK
>  
>  config NET_DSA_REALTEK_MDIO
> -	tristate "Realtek MDIO interface support"
> +	bool "Realtek MDIO interface support"
>  	depends on OF
>  	help
>  	  Select to enable support for registering switches configured
>  	  through MDIO.
>  
>  config NET_DSA_REALTEK_SMI
> -	tristate "Realtek SMI interface support"
> +	bool "Realtek SMI interface support"
>  	depends on OF
>  	help
>  	  Select to enable support for registering switches connected
> diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> index 5e0c1ef200a3..88f6652f9850 100644
> --- a/drivers/net/dsa/realtek/Makefile
> +++ b/drivers/net/dsa/realtek/Makefile
> @@ -1,7 +1,9 @@
>  # SPDX-License-Identifier: GPL-2.0
> -obj-$(CONFIG_NET_DSA_REALTEK)		+= realtek-common.o
> -obj-$(CONFIG_NET_DSA_REALTEK_MDIO) 	+= realtek-mdio.o
> -obj-$(CONFIG_NET_DSA_REALTEK_SMI) 	+= realtek-smi.o
> +obj-$(CONFIG_NET_DSA_REALTEK)		+= realtek_common.o
> +realtek_common-objs-y			:= realtek-common.o

This is weird with the - and _. Also realtek-common is not a very
descriptive module name. Maybe realtek-dsa?

obj-$(CONFIG_NET_DSA_REALTEK) += realtek-dsa.o
realtek-dsa-objs-y            += realtek-common.o
realtek-dsa-objs-$(..._MDIO)  += realtek-mdio.o
realtek-dsa-objs-$(..._SMI)   += realtek-smi.o

Also what happens if I just enable CONFIG_NET_DSA_REALTEK and nothing
else. Do I get a module that doesn't do anything? Not sure if it's a big
deal.

> +realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
> +realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
> +realtek_common-objs			:= $(realtek_common-objs-y)
>  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-common.c b/drivers/net/dsa/realtek/realtek-common.c
> index 75b6aa071990..73c25d114dd3 100644
> --- a/drivers/net/dsa/realtek/realtek-common.c
> +++ b/drivers/net/dsa/realtek/realtek-common.c
> @@ -132,5 +132,6 @@ void realtek_common_remove(struct realtek_priv *priv)
>  EXPORT_SYMBOL(realtek_common_remove);
>  
>  MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
> +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
>  MODULE_DESCRIPTION("Realtek DSA switches common module");
>  MODULE_LICENSE("GPL");
> diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> index 4c9a744b72f8..bb5bff719ae9 100644
> --- a/drivers/net/dsa/realtek/realtek-mdio.c
> +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> @@ -168,7 +168,3 @@ void realtek_mdio_shutdown(struct mdio_device *mdiodev)
>  	dev_set_drvdata(&mdiodev->dev, NULL);
>  }
>  EXPORT_SYMBOL_GPL(realtek_mdio_shutdown);
> -
> -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-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> index 246024eec3bd..1ca2aa784d24 100644
> --- a/drivers/net/dsa/realtek/realtek-smi.c
> +++ b/drivers/net/dsa/realtek/realtek-smi.c
> @@ -443,7 +443,3 @@ void realtek_smi_shutdown(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, NULL);
>  }
>  EXPORT_SYMBOL_GPL(realtek_smi_shutdown);
> -
> -MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> -MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
> -MODULE_LICENSE("GPL");
> -- 
> 2.43.0
>

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

* Re: [PATCH net-next 6/7] net: dsa: realtek: migrate user_mii setup to common
  2023-12-08  4:41 ` [PATCH net-next 6/7] net: dsa: realtek: migrate user_mii setup to common Luiz Angelo Daros de Luca
@ 2023-12-08 11:05   ` Alvin Šipraga
  2023-12-11  5:16     ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08 11:05 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 01:41:42AM -0300, Luiz Angelo Daros de Luca wrote:
> Although there are many mentions to SMI in in the user mdio driver,
> including its compatible string, there is nothing special about the SMI
> interface in the user mdio bus. That way, the code was migrated to the
> common module.
> 
> All references to SMI were removed, except for the compatible string
> that will still work but warn about using the mdio node name instead.
> 
> The variant ds_ops_{smi,mdio} fields were rename to, respectively,
> ds_ops_custom_user_mdio and ds_ops_default_user_mdio.
> 
> The priv->setup_interface() is also gone. If the ds_ops defines
> phy_read/write, it means DSA will handle the user_mii_bus. We don't need
> to check in another place. Also, with the function that would define
> setup_interface() in common, we can call it directly.

What is default?  It's MDIO. What is custom? It's SMI right now. If
there is another interface (SPI) then we may need a third way. Frankly I
do not see the benefit of this change, sorry.

> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
>  drivers/net/dsa/realtek/realtek-common.c | 67 ++++++++++++++++++++++++
>  drivers/net/dsa/realtek/realtek-common.h |  1 +
>  drivers/net/dsa/realtek/realtek-mdio.c   |  2 +-
>  drivers/net/dsa/realtek/realtek-smi.c    | 61 +--------------------
>  drivers/net/dsa/realtek/realtek.h        |  5 +-
>  drivers/net/dsa/realtek/rtl8365mb.c      | 12 ++---
>  drivers/net/dsa/realtek/rtl8366rb.c      | 12 ++---
>  7 files changed, 84 insertions(+), 76 deletions(-)
> 
> diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
> index 73c25d114dd3..64a55cb1ea05 100644
> --- a/drivers/net/dsa/realtek/realtek-common.c
> +++ b/drivers/net/dsa/realtek/realtek-common.c
> @@ -1,6 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  
>  #include <linux/module.h>
> +#include <linux/of_mdio.h>
>  
>  #include "realtek.h"
>  #include "realtek-common.h"
> @@ -21,6 +22,72 @@ void realtek_common_unlock(void *ctx)
>  }
>  EXPORT_SYMBOL_GPL(realtek_common_unlock);
>  
> +static int realtek_common_user_mdio_read(struct mii_bus *bus, int addr,
> +					 int regnum)
> +{
> +	struct realtek_priv *priv = bus->priv;
> +
> +	return priv->ops->phy_read(priv, addr, regnum);
> +}
> +
> +static int realtek_common_user_mdio_write(struct mii_bus *bus, int addr,
> +					  int regnum, u16 val)
> +{
> +	struct realtek_priv *priv = bus->priv;
> +
> +	return priv->ops->phy_write(priv, addr, regnum, val);
> +}
> +
> +int realtek_common_setup_user_mdio(struct dsa_switch *ds)
> +{
> +	struct realtek_priv *priv =  ds->priv;
> +	struct device_node *mdio_np;
> +	const char compatible = "realtek,smi-mdio";

const char *compatible

> +	int ret;
> +
> +	mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
> +	if (!mdio_np) {
> +		mdio_np = of_get_compatible_child(priv->dev->of_node, compatible);
> +		if (!mdio_np) {
> +			dev_err(priv->dev, "no MDIO bus node\n");
> +			return -ENODEV;
> +		}
> +		dev_warn(priv->dev,
> +			 "Rename node '%s' to 'mdio' and remove compatible '%s'",
> +			 mdio_np->name, compatible);
> +	}
> +
> +	priv->user_mii_bus = devm_mdiobus_alloc(priv->dev);
> +	if (!priv->user_mii_bus) {
> +		ret = -ENOMEM;
> +		goto err_put_node;
> +	}
> +	priv->user_mii_bus->priv = priv;
> +	priv->user_mii_bus->name = "Realtek user MII";
> +	priv->user_mii_bus->read = realtek_common_user_mdio_read;
> +	priv->user_mii_bus->write = realtek_common_user_mdio_write;
> +	snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "Realtek-%d",
> +		 ds->index);
> +	priv->user_mii_bus->parent = priv->dev;
> +	ds->user_mii_bus = priv->user_mii_bus;
> +
> +	ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
> +	of_node_put(mdio_np);
> +	if (ret) {
> +		dev_err(priv->dev, "unable to register MDIO bus %s\n",
> +			priv->user_mii_bus->id);
> +		return ret;
> +	}
> +
> +	return 0;
> +
> +err_put_node:
> +	of_node_put(mdio_np);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(realtek_common_setup_user_mdio);
> +
>  struct realtek_priv *
>  realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
>  			 struct regmap_config rc_nolock)
> diff --git a/drivers/net/dsa/realtek/realtek-common.h b/drivers/net/dsa/realtek/realtek-common.h
> index 405bd0d85d2b..4f8c66167b15 100644
> --- a/drivers/net/dsa/realtek/realtek-common.h
> +++ b/drivers/net/dsa/realtek/realtek-common.h
> @@ -7,6 +7,7 @@
>  
>  void realtek_common_lock(void *ctx);
>  void realtek_common_unlock(void *ctx);
> +int realtek_common_setup_user_mdio(struct dsa_switch *ds);
>  struct realtek_priv *
>  realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
>  			 struct regmap_config rc_nolock);
> diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> index bb5bff719ae9..37a41bab20b4 100644
> --- a/drivers/net/dsa/realtek/realtek-mdio.c
> +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> @@ -141,7 +141,7 @@ int realtek_mdio_probe(struct mdio_device *mdiodev)
>  	priv->bus = mdiodev->bus;
>  	priv->mdio_addr = mdiodev->addr;
>  	priv->write_reg_noack = realtek_mdio_write;
> -	priv->ds_ops = priv->variant->ds_ops_mdio;
> +	priv->ds_ops = priv->variant->ds_ops_default_user_mdio;
>  
>  	return realtek_common_probe_post(priv);
>  
> diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> index 1ca2aa784d24..84dde2123b09 100644
> --- a/drivers/net/dsa/realtek/realtek-smi.c
> +++ b/drivers/net/dsa/realtek/realtek-smi.c
> @@ -31,7 +31,6 @@
>  #include <linux/spinlock.h>
>  #include <linux/skbuff.h>
>  #include <linux/of.h>
> -#include <linux/of_mdio.h>
>  #include <linux/delay.h>
>  #include <linux/gpio/consumer.h>
>  #include <linux/platform_device.h>
> @@ -339,63 +338,6 @@ static const struct regmap_config realtek_smi_nolock_regmap_config = {
>  	.disable_locking = true,
>  };
>  
> -static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
> -{
> -	struct realtek_priv *priv = bus->priv;
> -
> -	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_priv *priv = bus->priv;
> -
> -	return priv->ops->phy_write(priv, addr, regnum, val);
> -}
> -
> -static int realtek_smi_setup_mdio(struct dsa_switch *ds)
> -{
> -	struct realtek_priv *priv =  ds->priv;
> -	struct device_node *mdio_np;
> -	int ret;
> -
> -	mdio_np = of_get_compatible_child(priv->dev->of_node, "realtek,smi-mdio");
> -	if (!mdio_np) {
> -		dev_err(priv->dev, "no MDIO bus node\n");
> -		return -ENODEV;
> -	}
> -
> -	priv->user_mii_bus = devm_mdiobus_alloc(priv->dev);
> -	if (!priv->user_mii_bus) {
> -		ret = -ENOMEM;
> -		goto err_put_node;
> -	}
> -	priv->user_mii_bus->priv = priv;
> -	priv->user_mii_bus->name = "SMI user MII";
> -	priv->user_mii_bus->read = realtek_smi_mdio_read;
> -	priv->user_mii_bus->write = realtek_smi_mdio_write;
> -	snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
> -		 ds->index);
> -	priv->user_mii_bus->parent = priv->dev;
> -	ds->user_mii_bus = priv->user_mii_bus;
> -
> -	ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
> -	of_node_put(mdio_np);
> -	if (ret) {
> -		dev_err(priv->dev, "unable to register MDIO bus %s\n",
> -			priv->user_mii_bus->id);
> -		return ret;
> -	}
> -
> -	return 0;
> -
> -err_put_node:
> -	of_node_put(mdio_np);
> -
> -	return ret;
> -}
> -
>  int realtek_smi_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -416,8 +358,7 @@ int realtek_smi_probe(struct platform_device *pdev)
>  		return PTR_ERR(priv->mdio);
>  
>  	priv->write_reg_noack = realtek_smi_write_reg_noack;
> -	priv->setup_interface = realtek_smi_setup_mdio;
> -	priv->ds_ops = priv->variant->ds_ops_smi;
> +	priv->ds_ops = priv->variant->ds_ops_custom_user_mdio;
>  
>  	return realtek_common_probe_post(priv);
>  }
> diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> index fbd0616c1df3..3fa8479c396f 100644
> --- a/drivers/net/dsa/realtek/realtek.h
> +++ b/drivers/net/dsa/realtek/realtek.h
> @@ -71,7 +71,6 @@ 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)(void *ctx, u32 addr, u32 data);
>  
>  	int			vlan_enabled;
> @@ -115,8 +114,8 @@ struct realtek_ops {
>  };
>  
>  struct realtek_variant {
> -	const struct dsa_switch_ops *ds_ops_smi;
> -	const struct dsa_switch_ops *ds_ops_mdio;
> +	const struct dsa_switch_ops *ds_ops_default_user_mdio;
> +	const struct dsa_switch_ops *ds_ops_custom_user_mdio;
>  	const struct realtek_ops *ops;
>  	unsigned int clk_delay;
>  	u8 cmd_read;
> diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> index ac848b965f84..a52fb07504b5 100644
> --- a/drivers/net/dsa/realtek/rtl8365mb.c
> +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> @@ -2017,8 +2017,8 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
>  	if (ret)
>  		goto out_teardown_irq;
>  
> -	if (priv->setup_interface) {
> -		ret = priv->setup_interface(ds);
> +	if (!priv->ds_ops->phy_read) {
> +		ret = realtek_common_setup_user_mdio(ds);
>  		if (ret) {
>  			dev_err(priv->dev, "could not set up MDIO bus\n");
>  			goto out_teardown_irq;
> @@ -2116,7 +2116,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
>  	return 0;
>  }
>  
> -static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
> +static const struct dsa_switch_ops rtl8365mb_switch_ops_custom_user_mdio = {
>  	.get_tag_protocol = rtl8365mb_get_tag_protocol,
>  	.change_tag_protocol = rtl8365mb_change_tag_protocol,
>  	.setup = rtl8365mb_setup,
> @@ -2137,7 +2137,7 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
>  	.port_max_mtu = rtl8365mb_port_max_mtu,
>  };
>  
> -static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
> +static const struct dsa_switch_ops rtl8365mb_switch_ops_default_user_mdio = {
>  	.get_tag_protocol = rtl8365mb_get_tag_protocol,
>  	.change_tag_protocol = rtl8365mb_change_tag_protocol,
>  	.setup = rtl8365mb_setup,
> @@ -2167,8 +2167,8 @@ static const struct realtek_ops rtl8365mb_ops = {
>  };
>  
>  const struct realtek_variant rtl8365mb_variant = {
> -	.ds_ops_smi = &rtl8365mb_switch_ops_smi,
> -	.ds_ops_mdio = &rtl8365mb_switch_ops_mdio,
> +	.ds_ops_default_user_mdio = &rtl8365mb_switch_ops_default_user_mdio,
> +	.ds_ops_custom_user_mdio = &rtl8365mb_switch_ops_custom_user_mdio,
>  	.ops = &rtl8365mb_ops,
>  	.clk_delay = 10,
>  	.cmd_read = 0xb9,
> diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> index 1cc4de3cf54f..9b6997574d2c 100644
> --- a/drivers/net/dsa/realtek/rtl8366rb.c
> +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> @@ -1027,8 +1027,8 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
>  	if (ret)
>  		dev_info(priv->dev, "no interrupt support\n");
>  
> -	if (priv->setup_interface) {
> -		ret = priv->setup_interface(ds);
> +	if (!priv->ds_ops->phy_read) {
> +		ret = realtek_common_setup_user_mdio(ds);
>  		if (ret) {
>  			dev_err(priv->dev, "could not set up MDIO bus\n");
>  			return -ENODEV;
> @@ -1848,7 +1848,7 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
>  	return 0;
>  }
>  
> -static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
> +static const struct dsa_switch_ops rtl8366rb_switch_ops_custom_user_mdio = {
>  	.get_tag_protocol = rtl8366_get_tag_protocol,
>  	.setup = rtl8366rb_setup,
>  	.phylink_get_caps = rtl8366rb_phylink_get_caps,
> @@ -1872,7 +1872,7 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
>  	.port_max_mtu = rtl8366rb_max_mtu,
>  };
>  
> -static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
> +static const struct dsa_switch_ops rtl8366rb_switch_ops_default_user_mdio = {
>  	.get_tag_protocol = rtl8366_get_tag_protocol,
>  	.setup = rtl8366rb_setup,
>  	.phy_read = rtl8366rb_dsa_phy_read,
> @@ -1915,8 +1915,8 @@ static const struct realtek_ops rtl8366rb_ops = {
>  };
>  
>  const struct realtek_variant rtl8366rb_variant = {
> -	.ds_ops_smi = &rtl8366rb_switch_ops_smi,
> -	.ds_ops_mdio = &rtl8366rb_switch_ops_mdio,
> +	.ds_ops_default_user_mdio = &rtl8366rb_switch_ops_default_user_mdio,
> +	.ds_ops_custom_user_mdio = &rtl8366rb_switch_ops_custom_user_mdio,
>  	.ops = &rtl8366rb_ops,
>  	.clk_delay = 10,
>  	.cmd_read = 0xa9,
> -- 
> 2.43.0
>

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

* Re: [PATCH net-next 7/7] net: dsa: realtek: always use the realtek user mdio driver
  2023-12-08  4:41 ` [PATCH net-next 7/7] net: dsa: realtek: always use the realtek user mdio driver Luiz Angelo Daros de Luca
@ 2023-12-08 11:06   ` Alvin Šipraga
  2023-12-11  5:29     ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08 11:06 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 01:41:43AM -0300, Luiz Angelo Daros de Luca wrote:
> Although the DSA switch will register a generic mdio driver when
> ds_ops.phy_{read,write} exists ("dsa user smi"), it was pointed out that
> it was not a core feature to depend on [1]. That way, the realtek user
> mdio driver will be used by both interfaces.
> 
> [1] https://lkml.kernel.org/netdev/20220630200423.tieprdu5fpabflj7@bang-olufsen.dk/T/
> 
> The ds_ops field in realtek_priv was also dropped as now we can directly
> reference the variant->ds_ops.

Ah OK, this makes more sense. Can you fold this into the previous patch?
Then it might look more reasonable.

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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-08  4:41 ` [PATCH net-next 4/7] net: dsa: realtek: create realtek-common Luiz Angelo Daros de Luca
  2023-12-08  5:01   ` Luiz Angelo Daros de Luca
  2023-12-08 10:52   ` Alvin Šipraga
@ 2023-12-08 14:02   ` Alvin Šipraga
  2023-12-11  5:02     ` Luiz Angelo Daros de Luca
  2 siblings, 1 reply; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-08 14:02 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 01:41:40AM -0300, Luiz Angelo Daros de Luca wrote:
> +struct realtek_priv *
> +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> +			 struct regmap_config rc_nolock)
> +{

<snip>

> +
> +	/* TODO: if power is software controlled, set up any regulators here */
> +
> +	priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> +	if (IS_ERR(priv->reset)) {
> +		dev_err(dev, "failed to get RESET GPIO\n");
> +		return ERR_CAST(priv->reset);
> +	}
> +	if (priv->reset) {
> +		gpiod_set_value(priv->reset, 1);
> +		dev_dbg(dev, "asserted RESET\n");
> +		msleep(REALTEK_HW_STOP_DELAY);
> +		gpiod_set_value(priv->reset, 0);
> +		msleep(REALTEK_HW_START_DELAY);
> +		dev_dbg(dev, "deasserted RESET\n");
> +	}

Another thing I would like to suggest is that you do not move the
hardware reset and the /* TODO: regulators */ into the common code. I
actually wanted to add regulator support for rtl8365mb after you are
finished with your series, and I noticed that it will not fit well here,
because the supplies are different for the two switch variants.

If we were to do the hardware reset here in common_probe_pre(), where
should I put my variant-specific regulator_bulk_enable()? I can't put it
before _pre() because I do not have the private data allocated yet. If I
put it afterwards, then the above hardware reset toggle will have had no
effect.

So why not:

realtek_variant_probe() {
  realtek_common_probe_pre();

  /* enable regulators */
  /* hardware reset */
  /* other chip specific stuff here */

  realtek_common_probe_post();
}

> +
> +	return priv;
> +}
> +EXPORT_SYMBOL(realtek_common_probe_pre);
> +
> +int realtek_common_probe_post(struct realtek_priv *priv)
> +{
> +	int ret;
> +
> +	ret = priv->ops->detect(priv);
> +	if (ret) {
> +		dev_err(priv->dev, "unable to detect switch\n");
> +		return ret;
> +	}

This detect() logic can also then be folded into the variant's probe
function between _pre() and _post().

> +
> +	priv->ds = devm_kzalloc(priv->dev, sizeof(*priv->ds), GFP_KERNEL);
> +	if (!priv->ds)
> +		return -ENOMEM;
> +
> +	priv->ds->priv = priv;
> +	priv->ds->dev = priv->dev;
> +	priv->ds->ops = priv->ds_ops;
> +	priv->ds->num_ports = priv->num_ports;
> +
> +	ret = dsa_register_switch(priv->ds);
> +	if (ret) {
> +		dev_err_probe(priv->dev, ret, "unable to register switch\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(realtek_common_probe_post);

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-08  9:49     ` Alvin Šipraga
@ 2023-12-08 18:05       ` Luiz Angelo Daros de Luca
  2023-12-11 17:11         ` Vladimir Oltean
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-08 18:05 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

> On Fri, Dec 08, 2023 at 02:13:25AM -0300, Luiz Angelo Daros de Luca wrote:
> > > diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> > > index 755546ed8db6..ddcae546afbc 100644
> > > --- a/drivers/net/dsa/realtek/realtek-smi.c
> > > +++ b/drivers/net/dsa/realtek/realtek-smi.c
> > > @@ -389,15 +389,15 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
> > >         priv->user_mii_bus->write = realtek_smi_mdio_write;
> > >         snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
> > >                  ds->index);
> > > -       priv->user_mii_bus->dev.of_node = mdio_np;
>
> You do not really justify removing this in your patch. This is not a
> purely cosmetic change because now the associated mdiodev will not be
> associated with the OF node. I don't know if there is any consequence to
> that but it is usually nice to populate this info in the device struct
> when it is actually available.

Reviewing the code again, I believe it was not just misplacing the
of_put_node() but probably calling it twice.

devm_mdiobus_alloc() doesn't set the dev in mii_bus. So, dev is all
zeros. The dev.of_node normal place to be defined is:

devm_of_mdiobus_register()
  __devm_of_mdiobus_register()
    __of_mdiobus_register()
      device_set_node()

The only way for that value, set by the line I removed, to persist is
when the devm_of_mdiobus_register() fails before device_set_node(). My
guess is that it was set to be used by realtek_smi_remove() if it is
called when registration fails. However, in that case, both
realtek_smi_setup_mdio() and realtek_smi_setup_mdio() would put the
node. So, either the line is useless or it will effectively result in
calling of_node_put() twice.

If I really needed to put that node in the realtek_smi_remove(), I
would use a dedicated field in realtek_priv instead of reusing a
reference for it inside another structure.

I'll add some notes to the commit message about all these but moving
the of_node_put() to the same function that gets the node solved all
the issues.

Regards,

Luiz

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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-08 10:52   ` Alvin Šipraga
@ 2023-12-11  5:02     ` Luiz Angelo Daros de Luca
  2023-12-11  9:44       ` Alvin Šipraga
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-11  5:02 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

> On Fri, Dec 08, 2023 at 01:41:40AM -0300, Luiz Angelo Daros de Luca wrote:
> > Some code can be shared between both interface modules (MDIO and SMI)
> > and among variants. Currently, these interface functions are shared:
> >
> > - realtek_common_lock
> > - realtek_common_unlock
> > - realtek_common_probe
> > - realtek_common_remove
> >
> > The reset during probe was moved to the last moment before a variant
> > detects the switch. This way, we avoid a reset if anything else fails.
> >
> > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> > ---
> >  drivers/net/dsa/realtek/Makefile         |   1 +
> >  drivers/net/dsa/realtek/realtek-common.c | 136 +++++++++++++++++++++++
> >  drivers/net/dsa/realtek/realtek-common.h |  16 +++
> >  drivers/net/dsa/realtek/realtek-mdio.c   | 121 ++------------------
> >  drivers/net/dsa/realtek/realtek-smi.c    | 124 +++------------------
> >  drivers/net/dsa/realtek/realtek.h        |   6 +-
> >  drivers/net/dsa/realtek/rtl8365mb.c      |   9 +-
> >  drivers/net/dsa/realtek/rtl8366rb.c      |   9 +-
> >  8 files changed, 194 insertions(+), 228 deletions(-)
> >  create mode 100644 drivers/net/dsa/realtek/realtek-common.c
> >  create mode 100644 drivers/net/dsa/realtek/realtek-common.h
> >
> > diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> > index 0aab57252a7c..5e0c1ef200a3 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)                += realtek-common.o
>
> No corresponding Kconfig change?

NET_DSA_REALTEK already existed for "Realtek Ethernet switch family
support" entry to the Realtek DSA switch submenu. In the way we used
to use it, I believe it should be a bool entry, not a tristate. Now,
with a common module, a tristate fits just fine. So, by mistake, no
change is needed.

> >  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
> > diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
> > new file mode 100644
> > index 000000000000..75b6aa071990
> > --- /dev/null
> > +++ b/drivers/net/dsa/realtek/realtek-common.c
> > @@ -0,0 +1,136 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +
> > +#include <linux/module.h>
> > +
> > +#include "realtek.h"
> > +#include "realtek-common.h"
> > +
> > +void realtek_common_lock(void *ctx)
> > +{
> > +     struct realtek_priv *priv = ctx;
> > +
> > +     mutex_lock(&priv->map_lock);
> > +}
> > +EXPORT_SYMBOL_GPL(realtek_common_lock);
> > +
> > +void realtek_common_unlock(void *ctx)
> > +{
> > +     struct realtek_priv *priv = ctx;
> > +
> > +     mutex_unlock(&priv->map_lock);
> > +}
> > +EXPORT_SYMBOL_GPL(realtek_common_unlock);
> > +
> > +struct realtek_priv *
> > +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> > +                      struct regmap_config rc_nolock)
> > +{
> > +     const struct realtek_variant *var;
> > +     struct realtek_priv *priv;
> > +     struct device_node *np;
> > +     int ret;
> > +
> > +     var = of_device_get_match_data(dev);
> > +     if (!var)
> > +             return ERR_PTR(-EINVAL);
> > +
> > +     priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz),
> > +                         GFP_KERNEL);
> > +     if (!priv)
> > +             return ERR_PTR(-ENOMEM);
> > +
> > +     mutex_init(&priv->map_lock);
> > +
> > +     rc.lock_arg = priv;
> > +     priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> > +     if (IS_ERR(priv->map)) {
> > +             ret = PTR_ERR(priv->map);
> > +             dev_err(dev, "regmap init failed: %d\n", ret);
> > +             return ERR_PTR(ret);
> > +     }
> > +
> > +     priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc_nolock);
> > +     if (IS_ERR(priv->map_nolock)) {
> > +             ret = PTR_ERR(priv->map_nolock);
> > +             dev_err(dev, "regmap init failed: %d\n", ret);
> > +             return ERR_PTR(ret);
> > +     }
> > +
> > +     /* Link forward and backward */
> > +     priv->dev = dev;
> > +     priv->variant = var;
> > +     priv->ops = var->ops;
> > +     priv->chip_data = (void *)priv + sizeof(*priv);
> > +
> > +     dev_set_drvdata(dev, priv);
> > +     spin_lock_init(&priv->lock);
> > +
> > +     np = dev->of_node;
>
> This is kind of a pointless variable, just do
> of_property_read_bool(dev->of_node, ...) below.

OK.

>
> > +
> > +     priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
> > +
> > +     /* TODO: if power is software controlled, set up any regulators here */
> > +
> > +     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > +     if (IS_ERR(priv->reset)) {
> > +             dev_err(dev, "failed to get RESET GPIO\n");
> > +             return ERR_CAST(priv->reset);
> > +     }
> > +     if (priv->reset) {
> > +             gpiod_set_value(priv->reset, 1);
> > +             dev_dbg(dev, "asserted RESET\n");
> > +             msleep(REALTEK_HW_STOP_DELAY);
> > +             gpiod_set_value(priv->reset, 0);
> > +             msleep(REALTEK_HW_START_DELAY);
> > +             dev_dbg(dev, "deasserted RESET\n");
> > +     }
> > +
> > +     return priv;
> > +}
> > +EXPORT_SYMBOL(realtek_common_probe_pre);
> > +
> > +int realtek_common_probe_post(struct realtek_priv *priv)
> > +{
> > +     int ret;
> > +
> > +     ret = priv->ops->detect(priv);
> > +     if (ret) {
> > +             dev_err(priv->dev, "unable to detect switch\n");
>
> dev_err_probe()?

I'm not sure if detect() is able to return -EPROBE. At least for SMI,
gpio read/write never returns errors. However, it will not hurt to use
dev_err_probe() here.

>
> > +             return ret;
> > +     }
> > +
> > +     priv->ds = devm_kzalloc(priv->dev, sizeof(*priv->ds), GFP_KERNEL);
> > +     if (!priv->ds)
> > +             return -ENOMEM;
>
> I guess this could actually just be embedded in realtek_priv and then
> you don't need to allocate it dynamically here.

It makes sense. However, shouldn't it be a different commit? This one
is just moving stuff to a common file, not trying to optimize de code.

> > +
> > +     priv->ds->priv = priv;
> > +     priv->ds->dev = priv->dev;
> > +     priv->ds->ops = priv->ds_ops;
> > +     priv->ds->num_ports = priv->num_ports;
> > +
> > +     ret = dsa_register_switch(priv->ds);
> > +     if (ret) {
> > +             dev_err_probe(priv->dev, ret, "unable to register switch\n");
> > +             return ret;
> > +     }
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL(realtek_common_probe_post);
> > +
> > +void realtek_common_remove(struct realtek_priv *priv)
> > +{
> > +     if (!priv)
> > +             return;
> > +
> > +     dsa_unregister_switch(priv->ds);
> > +
> > +     /* leave the device reset asserted */
> > +     if (priv->reset)
> > +             gpiod_set_value(priv->reset, 1);
> > +}
> > +EXPORT_SYMBOL(realtek_common_remove);
> > +
> > +MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
> > +MODULE_DESCRIPTION("Realtek DSA switches common module");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/net/dsa/realtek/realtek-common.h b/drivers/net/dsa/realtek/realtek-common.h
> > new file mode 100644
> > index 000000000000..405bd0d85d2b
> > --- /dev/null
> > +++ b/drivers/net/dsa/realtek/realtek-common.h
> > @@ -0,0 +1,16 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +
> > +#ifndef _REALTEK_INTERFACE_H
> > +#define _REALTEK_INTERFACE_H
> > +
> > +#include <linux/regmap.h>
> > +
> > +void realtek_common_lock(void *ctx);
> > +void realtek_common_unlock(void *ctx);
> > +struct realtek_priv *
> > +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> > +                      struct regmap_config rc_nolock);
> > +int realtek_common_probe_post(struct realtek_priv *priv);
>
> Maybe it is worth describing what these functions do with a comment.
>
> pre:  sets up driver private data struct, sets up regmaps, issues
>       hardware reset
>
> post: registers the dsa switch, calls detect() and then expects
>       priv->num_ports to be set

Sure. I'm not sure about the "expects". If I need something, I should
check and fail. The DSA switch will already fail to register without a
non-zero number of ports. (although too silently for my taste).

I don't like names that need too much explanation. It is just a
symptom of a bad name. Would it make more sense to have

realtek_common_probe_pre -> realtek_common_probe
realtek_common_probe_post -> realtek_common_register_switch (although
it is also detecting the switch)

?

> The detect() function in itself is a bit funny. Maybe it's not even
> necessary. Both chip variants set a static num_ports value anyway. You
> can maybe dump detect() completely and move that code into the
> variant-specific probe between the calls to common_probe_{pre,post}().

The probe is not variant-specific but interface-specific. We could,
indeed, put a static num_ports into realtek_variant and use it.
However, the main use for detect is to validate you really got a
supported switch, with the setups being a secondary function. I would
leave it as is for now. I'm trying to keep the series as small as
possible.

> > +void realtek_common_remove(struct realtek_priv *priv);
> > +
> > +#endif
>
> #endif /* _REALTEK_INTERFACE_H */
>
> Actually shouldn't it be _REALTEK_COMMON_H?

Yes, bad ctrl+c/ctrl+v from Vladmir example code.

> > diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> > index 58966d0625c8..4c9a744b72f8 100644
> > --- a/drivers/net/dsa/realtek/realtek-mdio.c
> > +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> > @@ -26,6 +26,7 @@
> >
> >  #include "realtek.h"
> >  #include "realtek-mdio.h"
> > +#include "realtek-common.h"
> >
> >  /* Read/write via mdiobus */
> >  #define REALTEK_MDIO_CTRL0_REG               31
> > @@ -100,20 +101,6 @@ static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
> >       return ret;
> >  }
> >
> > -static void realtek_mdio_lock(void *ctx)
> > -{
> > -     struct realtek_priv *priv = ctx;
> > -
> > -     mutex_lock(&priv->map_lock);
> > -}
> > -
> > -static void realtek_mdio_unlock(void *ctx)
> > -{
> > -     struct realtek_priv *priv = ctx;
> > -
> > -     mutex_unlock(&priv->map_lock);
> > -}
> > -
> >  static const struct regmap_config realtek_mdio_regmap_config = {
> >       .reg_bits = 10, /* A4..A0 R4..R0 */
> >       .val_bits = 16,
> > @@ -124,8 +111,8 @@ static const struct regmap_config realtek_mdio_regmap_config = {
> >       .reg_read = realtek_mdio_read,
> >       .reg_write = realtek_mdio_write,
> >       .cache_type = REGCACHE_NONE,
> > -     .lock = realtek_mdio_lock,
> > -     .unlock = realtek_mdio_unlock,
> > +     .lock = realtek_common_lock,
> > +     .unlock = realtek_common_unlock,
> >  };
> >
> >  static const struct regmap_config realtek_mdio_nolock_regmap_config = {
> > @@ -143,98 +130,21 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
> >
> >  int realtek_mdio_probe(struct mdio_device *mdiodev)
> >  {
> > -     struct realtek_priv *priv;
> >       struct device *dev = &mdiodev->dev;
> > -     const struct realtek_variant *var;
> > -     struct regmap_config rc;
> > -     struct device_node *np;
> > -     int ret;
> > -
> > -     var = of_device_get_match_data(dev);
> > -     if (!var)
> > -             return -EINVAL;
> > -
> > -     priv = devm_kzalloc(&mdiodev->dev,
> > -                         size_add(sizeof(*priv), var->chip_data_sz),
> > -                         GFP_KERNEL);
> > -     if (!priv)
> > -             return -ENOMEM;
> > -
> > -     mutex_init(&priv->map_lock);
> > -
> > -     rc = realtek_mdio_regmap_config;
> > -     rc.lock_arg = priv;
> > -     priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> > -     if (IS_ERR(priv->map)) {
> > -             ret = PTR_ERR(priv->map);
> > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > -             return ret;
> > -     }
> > +     struct realtek_priv *priv;
> >
> > -     rc = realtek_mdio_nolock_regmap_config;
> > -     priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
> > -     if (IS_ERR(priv->map_nolock)) {
> > -             ret = PTR_ERR(priv->map_nolock);
> > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > -             return ret;
> > -     }
> > +     priv = realtek_common_probe_pre(dev, realtek_mdio_regmap_config,
> > +                                     realtek_mdio_nolock_regmap_config);
> > +     if (IS_ERR(priv))
> > +             return PTR_ERR(priv);
> >
> > -     priv->mdio_addr = 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->mdio_addr = mdiodev->addr;
> >       priv->write_reg_noack = realtek_mdio_write;
> > +     priv->ds_ops = priv->variant->ds_ops_mdio;
> >
> > -     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");
> > -
> > -     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > -     if (IS_ERR(priv->reset)) {
> > -             dev_err(dev, "failed to get RESET GPIO\n");
> > -             return PTR_ERR(priv->reset);
> > -     }
> > -
> > -     if (priv->reset) {
> > -             gpiod_set_value(priv->reset, 1);
> > -             dev_dbg(dev, "asserted RESET\n");
> > -             msleep(REALTEK_HW_STOP_DELAY);
> > -             gpiod_set_value(priv->reset, 0);
> > -             msleep(REALTEK_HW_START_DELAY);
> > -             dev_dbg(dev, "deasserted RESET\n");
> > -     }
> > -
> > -     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_mdio;
> > -
> > -     ret = dsa_register_switch(priv->ds);
> > -     if (ret) {
> > -             dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
> > -             return ret;
> > -     }
> > +     return realtek_common_probe_post(priv);
> >
> > -     return 0;
> >  }
> >  EXPORT_SYMBOL_GPL(realtek_mdio_probe);
> >
> > @@ -242,14 +152,7 @@ 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);
> > -
> > -     /* leave the device reset asserted */
> > -     if (priv->reset)
> > -             gpiod_set_value(priv->reset, 1);
> > +     realtek_common_remove(priv);
> >  }
> >  EXPORT_SYMBOL_GPL(realtek_mdio_remove);
> >
> > diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> > index 55586d158c0e..246024eec3bd 100644
> > --- a/drivers/net/dsa/realtek/realtek-smi.c
> > +++ b/drivers/net/dsa/realtek/realtek-smi.c
> > @@ -41,12 +41,13 @@
> >
> >  #include "realtek.h"
> >  #include "realtek-smi.h"
> > +#include "realtek-common.h"
> >
> >  #define REALTEK_SMI_ACK_RETRY_COUNT          5
> >
> >  static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
> >  {
> > -     ndelay(priv->clk_delay);
> > +     ndelay(priv->variant->clk_delay);
> >  }
> >
> >  static void realtek_smi_start(struct realtek_priv *priv)
> > @@ -209,7 +210,7 @@ static int realtek_smi_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
> >       realtek_smi_start(priv);
> >
> >       /* Send READ command */
> > -     ret = realtek_smi_write_byte(priv, priv->cmd_read);
> > +     ret = realtek_smi_write_byte(priv, priv->variant->cmd_read);
> >       if (ret)
> >               goto out;
> >
> > @@ -250,7 +251,7 @@ static int realtek_smi_write_reg(struct realtek_priv *priv,
> >       realtek_smi_start(priv);
> >
> >       /* Send WRITE command */
> > -     ret = realtek_smi_write_byte(priv, priv->cmd_write);
> > +     ret = realtek_smi_write_byte(priv, priv->variant->cmd_write);
> >       if (ret)
> >               goto out;
> >
> > @@ -311,20 +312,6 @@ static int realtek_smi_read(void *ctx, u32 reg, u32 *val)
> >       return realtek_smi_read_reg(priv, reg, val);
> >  }
> >
> > -static void realtek_smi_lock(void *ctx)
> > -{
> > -     struct realtek_priv *priv = ctx;
> > -
> > -     mutex_lock(&priv->map_lock);
> > -}
> > -
> > -static void realtek_smi_unlock(void *ctx)
> > -{
> > -     struct realtek_priv *priv = ctx;
> > -
> > -     mutex_unlock(&priv->map_lock);
> > -}
> > -
> >  static const struct regmap_config realtek_smi_regmap_config = {
> >       .reg_bits = 10, /* A4..A0 R4..R0 */
> >       .val_bits = 16,
> > @@ -335,8 +322,8 @@ static const struct regmap_config realtek_smi_regmap_config = {
> >       .reg_read = realtek_smi_read,
> >       .reg_write = realtek_smi_write,
> >       .cache_type = REGCACHE_NONE,
> > -     .lock = realtek_smi_lock,
> > -     .unlock = realtek_smi_unlock,
> > +     .lock = realtek_common_lock,
> > +     .unlock = realtek_common_unlock,
> >  };
> >
> >  static const struct regmap_config realtek_smi_nolock_regmap_config = {
> > @@ -411,100 +398,28 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
> >
> >  int realtek_smi_probe(struct platform_device *pdev)
> >  {
> > -     const struct realtek_variant *var;
> >       struct device *dev = &pdev->dev;
> >       struct realtek_priv *priv;
> > -     struct regmap_config rc;
> > -     struct device_node *np;
> > -     int ret;
> > -
> > -     var = of_device_get_match_data(dev);
> > -     np = dev->of_node;
> > -
> > -     priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
> > -     if (!priv)
> > -             return -ENOMEM;
> > -     priv->chip_data = (void *)priv + sizeof(*priv);
> > -
> > -     mutex_init(&priv->map_lock);
> > -
> > -     rc = realtek_smi_regmap_config;
> > -     rc.lock_arg = priv;
> > -     priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> > -     if (IS_ERR(priv->map)) {
> > -             ret = PTR_ERR(priv->map);
> > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > -             return ret;
> > -     }
> > -
> > -     rc = realtek_smi_nolock_regmap_config;
> > -     priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
> > -     if (IS_ERR(priv->map_nolock)) {
> > -             ret = PTR_ERR(priv->map_nolock);
> > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > -             return ret;
> > -     }
> > -
> > -     /* Link forward and backward */
> > -     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;
> > -
> > -     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);
> >
> > -     /* TODO: if power is software controlled, set up any regulators here */
> > -
> > -     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > -     if (IS_ERR(priv->reset)) {
> > -             dev_err(dev, "failed to get RESET GPIO\n");
> > -             return PTR_ERR(priv->reset);
> > -     }
> > -     if (priv->reset) {
> > -             gpiod_set_value(priv->reset, 1);
> > -             dev_dbg(dev, "asserted RESET\n");
> > -             msleep(REALTEK_HW_STOP_DELAY);
> > -             gpiod_set_value(priv->reset, 0);
> > -             msleep(REALTEK_HW_START_DELAY);
> > -             dev_dbg(dev, "deasserted RESET\n");
> > -     }
> > +     priv = realtek_common_probe_pre(dev, realtek_smi_regmap_config,
> > +                                     realtek_smi_nolock_regmap_config);
> > +     if (IS_ERR(priv))
> > +             return PTR_ERR(priv);
> >
> >       /* Fetch MDIO pins */
> >       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);
> >
> > -     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->write_reg_noack = realtek_smi_write_reg_noack;
> > +     priv->setup_interface = realtek_smi_setup_mdio;
> > +     priv->ds_ops = priv->variant->ds_ops_smi;
> >
> > -     priv->ds->ops = var->ds_ops_smi;
> > -     ret = dsa_register_switch(priv->ds);
> > -     if (ret) {
> > -             dev_err_probe(dev, ret, "unable to register switch\n");
> > -             return ret;
> > -     }
> > -     return 0;
> > +     return (priv);
>
> ret = realtek_common_probe_post(priv);
> if (ret)
>   return ret;
>
> return 0;

The ret variable is no more. Is it worth it to replace a single line
with 4 more?

> >  }
> >  EXPORT_SYMBOL_GPL(realtek_smi_probe);
> >
> > @@ -512,14 +427,7 @@ void realtek_smi_remove(struct platform_device *pdev)
> >  {
> >       struct realtek_priv *priv = platform_get_drvdata(pdev);
> >
> > -     if (!priv)
> > -             return;
> > -
> > -     dsa_unregister_switch(priv->ds);
> > -
> > -     /* leave the device reset asserted */
> > -     if (priv->reset)
> > -             gpiod_set_value(priv->reset, 1);
> > +     realtek_common_remove(priv);
> >  }
> >  EXPORT_SYMBOL_GPL(realtek_smi_remove);
> >
> > diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> > index e9ee778665b2..fbd0616c1df3 100644
> > --- a/drivers/net/dsa/realtek/realtek.h
> > +++ b/drivers/net/dsa/realtek/realtek.h
> > @@ -58,11 +58,9 @@ struct realtek_priv {
> >       struct mii_bus          *bus;
> >       int                     mdio_addr;
> >
> > -     unsigned int            clk_delay;
> > -     u8                      cmd_read;
> > -     u8                      cmd_write;
> >       spinlock_t              lock; /* Locks around command writes */
> >       struct dsa_switch       *ds;
> > +     const struct dsa_switch_ops *ds_ops;
> >       struct irq_domain       *irqdomain;
> >       bool                    leds_disabled;
> >
> > @@ -79,6 +77,8 @@ struct realtek_priv {
> >       int                     vlan_enabled;
> >       int                     vlan4k_enabled;
> >
> > +     const struct realtek_variant *variant;
> > +
> >       char                    buf[4096];
> >       void                    *chip_data; /* Per-chip extra variant data */
> >  };
> > diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> > index 526bf98cef1d..ac848b965f84 100644
> > --- a/drivers/net/dsa/realtek/rtl8365mb.c
> > +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> > @@ -103,6 +103,7 @@
> >  #include "realtek.h"
> >  #include "realtek-smi.h"
> >  #include "realtek-mdio.h"
> > +#include "realtek-common.h"
> >
> >  /* Family-specific data and limits */
> >  #define RTL8365MB_PHYADDRMAX         7
> > @@ -691,7 +692,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
> >       u32 val;
> >       int ret;
> >
> > -     mutex_lock(&priv->map_lock);
> > +     realtek_common_lock(priv);
> >
> >       ret = rtl8365mb_phy_poll_busy(priv);
> >       if (ret)
> > @@ -724,7 +725,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
> >       *data = val & 0xFFFF;
> >
> >  out:
> > -     mutex_unlock(&priv->map_lock);
> > +     realtek_common_unlock(priv);
> >
> >       return ret;
> >  }
> > @@ -735,7 +736,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
> >       u32 val;
> >       int ret;
> >
> > -     mutex_lock(&priv->map_lock);
> > +     realtek_common_lock(priv);
> >
> >       ret = rtl8365mb_phy_poll_busy(priv);
> >       if (ret)
> > @@ -766,7 +767,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
> >               goto out;
> >
> >  out:
> > -     mutex_unlock(&priv->map_lock);
> > +     realtek_common_unlock(priv);
> >
> >       return 0;
> >  }
> > diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> > index 09c17de19457..1cc4de3cf54f 100644
> > --- a/drivers/net/dsa/realtek/rtl8366rb.c
> > +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> > @@ -24,6 +24,7 @@
> >  #include "realtek.h"
> >  #include "realtek-smi.h"
> >  #include "realtek-mdio.h"
> > +#include "realtek-common.h"
> >
> >  #define RTL8366RB_PORT_NUM_CPU               5
> >  #define RTL8366RB_NUM_PORTS          6
> > @@ -1707,7 +1708,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
> >       if (phy > RTL8366RB_PHY_NO_MAX)
> >               return -EINVAL;
> >
> > -     mutex_lock(&priv->map_lock);
> > +     realtek_common_lock(priv);
> >
> >       ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
> >                          RTL8366RB_PHY_CTRL_READ);
> > @@ -1735,7 +1736,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
> >               phy, regnum, reg, val);
> >
> >  out:
> > -     mutex_unlock(&priv->map_lock);
> > +     realtek_common_unlock(priv);
> >
> >       return ret;
> >  }
> > @@ -1749,7 +1750,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
> >       if (phy > RTL8366RB_PHY_NO_MAX)
> >               return -EINVAL;
> >
> > -     mutex_lock(&priv->map_lock);
> > +     realtek_common_lock(priv);
> >
> >       ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
> >                          RTL8366RB_PHY_CTRL_WRITE);
> > @@ -1766,7 +1767,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
> >               goto out;
> >
> >  out:
> > -     mutex_unlock(&priv->map_lock);
> > +     realtek_common_unlock(priv);
> >
> >       return ret;
> >  }
> > --
> > 2.43.0
> >

Regards,

Luiz

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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-08 14:02   ` Alvin Šipraga
@ 2023-12-11  5:02     ` Luiz Angelo Daros de Luca
  2023-12-11  9:24       ` Alvin Šipraga
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-11  5:02 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

> > +struct realtek_priv *
> > +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> > +                      struct regmap_config rc_nolock)
> > +{
>
> <snip>
>
> > +
> > +     /* TODO: if power is software controlled, set up any regulators here */
> > +
> > +     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > +     if (IS_ERR(priv->reset)) {
> > +             dev_err(dev, "failed to get RESET GPIO\n");
> > +             return ERR_CAST(priv->reset);
> > +     }
> > +     if (priv->reset) {
> > +             gpiod_set_value(priv->reset, 1);
> > +             dev_dbg(dev, "asserted RESET\n");
> > +             msleep(REALTEK_HW_STOP_DELAY);
> > +             gpiod_set_value(priv->reset, 0);
> > +             msleep(REALTEK_HW_START_DELAY);
> > +             dev_dbg(dev, "deasserted RESET\n");
> > +     }
>
> Another thing I would like to suggest is that you do not move the
> hardware reset and the /* TODO: regulators */ into the common code. I
> actually wanted to add regulator support for rtl8365mb after you are
> finished with your series, and I noticed that it will not fit well here,
> because the supplies are different for the two switch variants.
>
> If we were to do the hardware reset here in common_probe_pre(), where
> should I put my variant-specific regulator_bulk_enable()? I can't put it
> before _pre() because I do not have the private data allocated yet. If I
> put it afterwards, then the above hardware reset toggle will have had no
> effect.

We would need to move the HW reset out of common_probe_pre(). Putting
it in _post() or between _pre() and _post() would not solve your case
as that happens in interface context. The probe is currently
interface-specific, not variant-specific. Maybe the easiest solution
would be to move the reset into the detect(), just before getting the
chip id, creating a new realtek_common_hwreset(). That way, you could
set up the regulators a little bit before the reset in the variant
context.

We could also change the interface-specific to a variant-specific
probe like this:

rtl8365mb_probe_smi(){
       priv = realtek_common_probe() /* previously the _pre func */
       realtek_smi_probe(priv) /* everything but the common calls */
       rtl8365mb_setup_regulators(priv)
       realtek_common_hwreset(priv) /* the reset code from common_probe_pre */
       rtl8365mb_detect(priv)
       realtek_common_register(priv) /* previously the
common_probe_post without the detect */
}

rtl8365mb_probe_mdio(){
    <repeat rtl8365rb_probe_smi but replace realtek_smi_probe with
realtek_mdio_probe>
}

rtl8366rb_probe_smi() { ... }
rtl8366rb_probe_mdio() { ... }

But it would be mostly 4 times the same code above, with lots of extra checks.

For the sake of keeping this patch as small as possible, I would
prefer to maintain the reset in its current location unless it is a
merging requirement. You can easily move it out when necessary. I
don't believe preparing for a potential future change fits in this
series, as we may misjudge what will be needed to set up the
regulators.

Regards,

Luiz

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

* Re: [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common
  2023-12-08 10:57   ` Alvin Šipraga
@ 2023-12-11  5:13     ` Luiz Angelo Daros de Luca
  2023-12-11  9:25       ` Alvin Šipraga
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-11  5:13 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

> > As both realtek-common and realtek-{smi,mdio} must always be loaded
> > together, we can save some resources merging them into a single module.
> >
> > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > ---
> >  drivers/net/dsa/realtek/Kconfig          | 4 ++--
> >  drivers/net/dsa/realtek/Makefile         | 8 +++++---
> >  drivers/net/dsa/realtek/realtek-common.c | 1 +
> >  drivers/net/dsa/realtek/realtek-mdio.c   | 4 ----
> >  drivers/net/dsa/realtek/realtek-smi.c    | 4 ----
> >  5 files changed, 8 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
> > index 9d182fde11b4..6989972eebc3 100644
> > --- a/drivers/net/dsa/realtek/Kconfig
> > +++ b/drivers/net/dsa/realtek/Kconfig
> > @@ -16,14 +16,14 @@ menuconfig NET_DSA_REALTEK
> >  if NET_DSA_REALTEK
> >
> >  config NET_DSA_REALTEK_MDIO
> > -     tristate "Realtek MDIO interface support"
> > +     bool "Realtek MDIO interface support"
> >       depends on OF
> >       help
> >         Select to enable support for registering switches configured
> >         through MDIO.
> >
> >  config NET_DSA_REALTEK_SMI
> > -     tristate "Realtek SMI interface support"
> > +     bool "Realtek SMI interface support"
> >       depends on OF
> >       help
> >         Select to enable support for registering switches connected
> > diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> > index 5e0c1ef200a3..88f6652f9850 100644
> > --- a/drivers/net/dsa/realtek/Makefile
> > +++ b/drivers/net/dsa/realtek/Makefile
> > @@ -1,7 +1,9 @@
> >  # SPDX-License-Identifier: GPL-2.0
> > -obj-$(CONFIG_NET_DSA_REALTEK)                += realtek-common.o
> > -obj-$(CONFIG_NET_DSA_REALTEK_MDIO)   += realtek-mdio.o
> > -obj-$(CONFIG_NET_DSA_REALTEK_SMI)    += realtek-smi.o
> > +obj-$(CONFIG_NET_DSA_REALTEK)                += realtek_common.o
> > +realtek_common-objs-y                        := realtek-common.o
>
> This is weird with the - and _. Also realtek-common is not a very
> descriptive module name. Maybe realtek-dsa?
>
> obj-$(CONFIG_NET_DSA_REALTEK) += realtek-dsa.o
> realtek-dsa-objs-y            += realtek-common.o
> realtek-dsa-objs-$(..._MDIO)  += realtek-mdio.o
> realtek-dsa-objs-$(..._SMI)   += realtek-smi.o

Yes, I'm not proud of it. The realtek_common/realtek-common trick is
just to bypass the fact that I cannot link multiple files into a
module that has the same name as one of these files. But realtek-dsa
is fine and it would avoid conflicts with other realtek stuff in the
kernel that might have a common module. However, I would introduce
that name already in the previous patch.

> Also what happens if I just enable CONFIG_NET_DSA_REALTEK and nothing
> else. Do I get a module that doesn't do anything? Not sure if it's a big
> deal.

The config language might not be good enough to handle that nicely.
There is the "imply" keyword but it does not force anything. I don't
know how to require "at least one of these two interfaces" without
creating a dependency cycle. I would just let it build a useless
common module. Building without variants does make a little bit of
sense if you want to build a new driver out-of-tree.

> > +realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
> > +realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
> > +realtek_common-objs                  := $(realtek_common-objs-y)
> >  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-common.c b/drivers/net/dsa/realtek/realtek-common.c
> > index 75b6aa071990..73c25d114dd3 100644
> > --- a/drivers/net/dsa/realtek/realtek-common.c
> > +++ b/drivers/net/dsa/realtek/realtek-common.c
> > @@ -132,5 +132,6 @@ void realtek_common_remove(struct realtek_priv *priv)
> >  EXPORT_SYMBOL(realtek_common_remove);
> >
> >  MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
> > +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> >  MODULE_DESCRIPTION("Realtek DSA switches common module");
> >  MODULE_LICENSE("GPL");
> > diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> > index 4c9a744b72f8..bb5bff719ae9 100644
> > --- a/drivers/net/dsa/realtek/realtek-mdio.c
> > +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> > @@ -168,7 +168,3 @@ void realtek_mdio_shutdown(struct mdio_device *mdiodev)
> >       dev_set_drvdata(&mdiodev->dev, NULL);
> >  }
> >  EXPORT_SYMBOL_GPL(realtek_mdio_shutdown);
> > -
> > -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-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> > index 246024eec3bd..1ca2aa784d24 100644
> > --- a/drivers/net/dsa/realtek/realtek-smi.c
> > +++ b/drivers/net/dsa/realtek/realtek-smi.c
> > @@ -443,7 +443,3 @@ void realtek_smi_shutdown(struct platform_device *pdev)
> >       platform_set_drvdata(pdev, NULL);
> >  }
> >  EXPORT_SYMBOL_GPL(realtek_smi_shutdown);
> > -
> > -MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> > -MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
> > -MODULE_LICENSE("GPL");
> > --
> > 2.43.0
> >

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

* Re: [PATCH net-next 6/7] net: dsa: realtek: migrate user_mii setup to common
  2023-12-08 11:05   ` Alvin Šipraga
@ 2023-12-11  5:16     ` Luiz Angelo Daros de Luca
  0 siblings, 0 replies; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-11  5:16 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

> On Fri, Dec 08, 2023 at 01:41:42AM -0300, Luiz Angelo Daros de Luca wrote:
> > Although there are many mentions to SMI in in the user mdio driver,
> > including its compatible string, there is nothing special about the SMI
> > interface in the user mdio bus. That way, the code was migrated to the
> > common module.
> >
> > All references to SMI were removed, except for the compatible string
> > that will still work but warn about using the mdio node name instead.
> >
> > The variant ds_ops_{smi,mdio} fields were rename to, respectively,
> > ds_ops_custom_user_mdio and ds_ops_default_user_mdio.
> >
> > The priv->setup_interface() is also gone. If the ds_ops defines
> > phy_read/write, it means DSA will handle the user_mii_bus. We don't need
> > to check in another place. Also, with the function that would define
> > setup_interface() in common, we can call it directly.
>
> What is default?  It's MDIO. What is custom? It's SMI right now. If
> there is another interface (SPI) then we may need a third way. Frankly I
> do not see the benefit of this change, sorry.

Default should actually be "generic", the one created by DSA when
user_mii is not defined.
But I'll solve this by squashing with the next patch.

>
> >
> > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > ---
> >  drivers/net/dsa/realtek/realtek-common.c | 67 ++++++++++++++++++++++++
> >  drivers/net/dsa/realtek/realtek-common.h |  1 +
> >  drivers/net/dsa/realtek/realtek-mdio.c   |  2 +-
> >  drivers/net/dsa/realtek/realtek-smi.c    | 61 +--------------------
> >  drivers/net/dsa/realtek/realtek.h        |  5 +-
> >  drivers/net/dsa/realtek/rtl8365mb.c      | 12 ++---
> >  drivers/net/dsa/realtek/rtl8366rb.c      | 12 ++---
> >  7 files changed, 84 insertions(+), 76 deletions(-)
> >
> > diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
> > index 73c25d114dd3..64a55cb1ea05 100644
> > --- a/drivers/net/dsa/realtek/realtek-common.c
> > +++ b/drivers/net/dsa/realtek/realtek-common.c
> > @@ -1,6 +1,7 @@
> >  // SPDX-License-Identifier: GPL-2.0+
> >
> >  #include <linux/module.h>
> > +#include <linux/of_mdio.h>
> >
> >  #include "realtek.h"
> >  #include "realtek-common.h"
> > @@ -21,6 +22,72 @@ void realtek_common_unlock(void *ctx)
> >  }
> >  EXPORT_SYMBOL_GPL(realtek_common_unlock);
> >
> > +static int realtek_common_user_mdio_read(struct mii_bus *bus, int addr,
> > +                                      int regnum)
> > +{
> > +     struct realtek_priv *priv = bus->priv;
> > +
> > +     return priv->ops->phy_read(priv, addr, regnum);
> > +}
> > +
> > +static int realtek_common_user_mdio_write(struct mii_bus *bus, int addr,
> > +                                       int regnum, u16 val)
> > +{
> > +     struct realtek_priv *priv = bus->priv;
> > +
> > +     return priv->ops->phy_write(priv, addr, regnum, val);
> > +}
> > +
> > +int realtek_common_setup_user_mdio(struct dsa_switch *ds)
> > +{
> > +     struct realtek_priv *priv =  ds->priv;
> > +     struct device_node *mdio_np;
> > +     const char compatible = "realtek,smi-mdio";
>
> const char *compatible
>
> > +     int ret;
> > +
> > +     mdio_np = of_get_child_by_name(priv->dev->of_node, "mdio");
> > +     if (!mdio_np) {
> > +             mdio_np = of_get_compatible_child(priv->dev->of_node, compatible);
> > +             if (!mdio_np) {
> > +                     dev_err(priv->dev, "no MDIO bus node\n");
> > +                     return -ENODEV;
> > +             }
> > +             dev_warn(priv->dev,
> > +                      "Rename node '%s' to 'mdio' and remove compatible '%s'",
> > +                      mdio_np->name, compatible);
> > +     }
> > +
> > +     priv->user_mii_bus = devm_mdiobus_alloc(priv->dev);
> > +     if (!priv->user_mii_bus) {
> > +             ret = -ENOMEM;
> > +             goto err_put_node;
> > +     }
> > +     priv->user_mii_bus->priv = priv;
> > +     priv->user_mii_bus->name = "Realtek user MII";
> > +     priv->user_mii_bus->read = realtek_common_user_mdio_read;
> > +     priv->user_mii_bus->write = realtek_common_user_mdio_write;
> > +     snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "Realtek-%d",
> > +              ds->index);
> > +     priv->user_mii_bus->parent = priv->dev;
> > +     ds->user_mii_bus = priv->user_mii_bus;
> > +
> > +     ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
> > +     of_node_put(mdio_np);
> > +     if (ret) {
> > +             dev_err(priv->dev, "unable to register MDIO bus %s\n",
> > +                     priv->user_mii_bus->id);
> > +             return ret;
> > +     }
> > +
> > +     return 0;
> > +
> > +err_put_node:
> > +     of_node_put(mdio_np);
> > +
> > +     return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(realtek_common_setup_user_mdio);
> > +
> >  struct realtek_priv *
> >  realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> >                        struct regmap_config rc_nolock)
> > diff --git a/drivers/net/dsa/realtek/realtek-common.h b/drivers/net/dsa/realtek/realtek-common.h
> > index 405bd0d85d2b..4f8c66167b15 100644
> > --- a/drivers/net/dsa/realtek/realtek-common.h
> > +++ b/drivers/net/dsa/realtek/realtek-common.h
> > @@ -7,6 +7,7 @@
> >
> >  void realtek_common_lock(void *ctx);
> >  void realtek_common_unlock(void *ctx);
> > +int realtek_common_setup_user_mdio(struct dsa_switch *ds);
> >  struct realtek_priv *
> >  realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> >                        struct regmap_config rc_nolock);
> > diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> > index bb5bff719ae9..37a41bab20b4 100644
> > --- a/drivers/net/dsa/realtek/realtek-mdio.c
> > +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> > @@ -141,7 +141,7 @@ int realtek_mdio_probe(struct mdio_device *mdiodev)
> >       priv->bus = mdiodev->bus;
> >       priv->mdio_addr = mdiodev->addr;
> >       priv->write_reg_noack = realtek_mdio_write;
> > -     priv->ds_ops = priv->variant->ds_ops_mdio;
> > +     priv->ds_ops = priv->variant->ds_ops_default_user_mdio;
> >
> >       return realtek_common_probe_post(priv);
> >
> > diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> > index 1ca2aa784d24..84dde2123b09 100644
> > --- a/drivers/net/dsa/realtek/realtek-smi.c
> > +++ b/drivers/net/dsa/realtek/realtek-smi.c
> > @@ -31,7 +31,6 @@
> >  #include <linux/spinlock.h>
> >  #include <linux/skbuff.h>
> >  #include <linux/of.h>
> > -#include <linux/of_mdio.h>
> >  #include <linux/delay.h>
> >  #include <linux/gpio/consumer.h>
> >  #include <linux/platform_device.h>
> > @@ -339,63 +338,6 @@ static const struct regmap_config realtek_smi_nolock_regmap_config = {
> >       .disable_locking = true,
> >  };
> >
> > -static int realtek_smi_mdio_read(struct mii_bus *bus, int addr, int regnum)
> > -{
> > -     struct realtek_priv *priv = bus->priv;
> > -
> > -     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_priv *priv = bus->priv;
> > -
> > -     return priv->ops->phy_write(priv, addr, regnum, val);
> > -}
> > -
> > -static int realtek_smi_setup_mdio(struct dsa_switch *ds)
> > -{
> > -     struct realtek_priv *priv =  ds->priv;
> > -     struct device_node *mdio_np;
> > -     int ret;
> > -
> > -     mdio_np = of_get_compatible_child(priv->dev->of_node, "realtek,smi-mdio");
> > -     if (!mdio_np) {
> > -             dev_err(priv->dev, "no MDIO bus node\n");
> > -             return -ENODEV;
> > -     }
> > -
> > -     priv->user_mii_bus = devm_mdiobus_alloc(priv->dev);
> > -     if (!priv->user_mii_bus) {
> > -             ret = -ENOMEM;
> > -             goto err_put_node;
> > -     }
> > -     priv->user_mii_bus->priv = priv;
> > -     priv->user_mii_bus->name = "SMI user MII";
> > -     priv->user_mii_bus->read = realtek_smi_mdio_read;
> > -     priv->user_mii_bus->write = realtek_smi_mdio_write;
> > -     snprintf(priv->user_mii_bus->id, MII_BUS_ID_SIZE, "SMI-%d",
> > -              ds->index);
> > -     priv->user_mii_bus->parent = priv->dev;
> > -     ds->user_mii_bus = priv->user_mii_bus;
> > -
> > -     ret = devm_of_mdiobus_register(priv->dev, priv->user_mii_bus, mdio_np);
> > -     of_node_put(mdio_np);
> > -     if (ret) {
> > -             dev_err(priv->dev, "unable to register MDIO bus %s\n",
> > -                     priv->user_mii_bus->id);
> > -             return ret;
> > -     }
> > -
> > -     return 0;
> > -
> > -err_put_node:
> > -     of_node_put(mdio_np);
> > -
> > -     return ret;
> > -}
> > -
> >  int realtek_smi_probe(struct platform_device *pdev)
> >  {
> >       struct device *dev = &pdev->dev;
> > @@ -416,8 +358,7 @@ int realtek_smi_probe(struct platform_device *pdev)
> >               return PTR_ERR(priv->mdio);
> >
> >       priv->write_reg_noack = realtek_smi_write_reg_noack;
> > -     priv->setup_interface = realtek_smi_setup_mdio;
> > -     priv->ds_ops = priv->variant->ds_ops_smi;
> > +     priv->ds_ops = priv->variant->ds_ops_custom_user_mdio;
> >
> >       return realtek_common_probe_post(priv);
> >  }
> > diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> > index fbd0616c1df3..3fa8479c396f 100644
> > --- a/drivers/net/dsa/realtek/realtek.h
> > +++ b/drivers/net/dsa/realtek/realtek.h
> > @@ -71,7 +71,6 @@ 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)(void *ctx, u32 addr, u32 data);
> >
> >       int                     vlan_enabled;
> > @@ -115,8 +114,8 @@ struct realtek_ops {
> >  };
> >
> >  struct realtek_variant {
> > -     const struct dsa_switch_ops *ds_ops_smi;
> > -     const struct dsa_switch_ops *ds_ops_mdio;
> > +     const struct dsa_switch_ops *ds_ops_default_user_mdio;
> > +     const struct dsa_switch_ops *ds_ops_custom_user_mdio;
> >       const struct realtek_ops *ops;
> >       unsigned int clk_delay;
> >       u8 cmd_read;
> > diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> > index ac848b965f84..a52fb07504b5 100644
> > --- a/drivers/net/dsa/realtek/rtl8365mb.c
> > +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> > @@ -2017,8 +2017,8 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
> >       if (ret)
> >               goto out_teardown_irq;
> >
> > -     if (priv->setup_interface) {
> > -             ret = priv->setup_interface(ds);
> > +     if (!priv->ds_ops->phy_read) {
> > +             ret = realtek_common_setup_user_mdio(ds);
> >               if (ret) {
> >                       dev_err(priv->dev, "could not set up MDIO bus\n");
> >                       goto out_teardown_irq;
> > @@ -2116,7 +2116,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
> >       return 0;
> >  }
> >
> > -static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
> > +static const struct dsa_switch_ops rtl8365mb_switch_ops_custom_user_mdio = {
> >       .get_tag_protocol = rtl8365mb_get_tag_protocol,
> >       .change_tag_protocol = rtl8365mb_change_tag_protocol,
> >       .setup = rtl8365mb_setup,
> > @@ -2137,7 +2137,7 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
> >       .port_max_mtu = rtl8365mb_port_max_mtu,
> >  };
> >
> > -static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
> > +static const struct dsa_switch_ops rtl8365mb_switch_ops_default_user_mdio = {
> >       .get_tag_protocol = rtl8365mb_get_tag_protocol,
> >       .change_tag_protocol = rtl8365mb_change_tag_protocol,
> >       .setup = rtl8365mb_setup,
> > @@ -2167,8 +2167,8 @@ static const struct realtek_ops rtl8365mb_ops = {
> >  };
> >
> >  const struct realtek_variant rtl8365mb_variant = {
> > -     .ds_ops_smi = &rtl8365mb_switch_ops_smi,
> > -     .ds_ops_mdio = &rtl8365mb_switch_ops_mdio,
> > +     .ds_ops_default_user_mdio = &rtl8365mb_switch_ops_default_user_mdio,
> > +     .ds_ops_custom_user_mdio = &rtl8365mb_switch_ops_custom_user_mdio,
> >       .ops = &rtl8365mb_ops,
> >       .clk_delay = 10,
> >       .cmd_read = 0xb9,
> > diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> > index 1cc4de3cf54f..9b6997574d2c 100644
> > --- a/drivers/net/dsa/realtek/rtl8366rb.c
> > +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> > @@ -1027,8 +1027,8 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
> >       if (ret)
> >               dev_info(priv->dev, "no interrupt support\n");
> >
> > -     if (priv->setup_interface) {
> > -             ret = priv->setup_interface(ds);
> > +     if (!priv->ds_ops->phy_read) {
> > +             ret = realtek_common_setup_user_mdio(ds);
> >               if (ret) {
> >                       dev_err(priv->dev, "could not set up MDIO bus\n");
> >                       return -ENODEV;
> > @@ -1848,7 +1848,7 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
> >       return 0;
> >  }
> >
> > -static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
> > +static const struct dsa_switch_ops rtl8366rb_switch_ops_custom_user_mdio = {
> >       .get_tag_protocol = rtl8366_get_tag_protocol,
> >       .setup = rtl8366rb_setup,
> >       .phylink_get_caps = rtl8366rb_phylink_get_caps,
> > @@ -1872,7 +1872,7 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
> >       .port_max_mtu = rtl8366rb_max_mtu,
> >  };
> >
> > -static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
> > +static const struct dsa_switch_ops rtl8366rb_switch_ops_default_user_mdio = {
> >       .get_tag_protocol = rtl8366_get_tag_protocol,
> >       .setup = rtl8366rb_setup,
> >       .phy_read = rtl8366rb_dsa_phy_read,
> > @@ -1915,8 +1915,8 @@ static const struct realtek_ops rtl8366rb_ops = {
> >  };
> >
> >  const struct realtek_variant rtl8366rb_variant = {
> > -     .ds_ops_smi = &rtl8366rb_switch_ops_smi,
> > -     .ds_ops_mdio = &rtl8366rb_switch_ops_mdio,
> > +     .ds_ops_default_user_mdio = &rtl8366rb_switch_ops_default_user_mdio,
> > +     .ds_ops_custom_user_mdio = &rtl8366rb_switch_ops_custom_user_mdio,
> >       .ops = &rtl8366rb_ops,
> >       .clk_delay = 10,
> >       .cmd_read = 0xa9,
> > --
> > 2.43.0
> >
Regards,

Luiz

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

* Re: [PATCH net-next 7/7] net: dsa: realtek: always use the realtek user mdio driver
  2023-12-08 11:06   ` Alvin Šipraga
@ 2023-12-11  5:29     ` Luiz Angelo Daros de Luca
  0 siblings, 0 replies; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-11  5:29 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

> On Fri, Dec 08, 2023 at 01:41:43AM -0300, Luiz Angelo Daros de Luca wrote:
> > Although the DSA switch will register a generic mdio driver when
> > ds_ops.phy_{read,write} exists ("dsa user smi"), it was pointed out that
> > it was not a core feature to depend on [1]. That way, the realtek user
> > mdio driver will be used by both interfaces.
> >
> > [1] https://lkml.kernel.org/netdev/20220630200423.tieprdu5fpabflj7@bang-olufsen.dk/T/
> >
> > The ds_ops field in realtek_priv was also dropped as now we can directly
> > reference the variant->ds_ops.
>
> Ah OK, this makes more sense. Can you fold this into the previous patch?
> Then it might look more reasonable.

Yes, that makes sense. I almost did that before submitting but I
thought splitting it into two parts might make the review easier. I
guess I was wrong.

Regards,

Luiz

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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-11  5:02     ` Luiz Angelo Daros de Luca
@ 2023-12-11  9:24       ` Alvin Šipraga
  2023-12-11 17:19         ` Vladimir Oltean
  0 siblings, 1 reply; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-11  9:24 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Mon, Dec 11, 2023 at 02:02:30AM -0300, Luiz Angelo Daros de Luca wrote:
> > > +struct realtek_priv *
> > > +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> > > +                      struct regmap_config rc_nolock)
> > > +{
> >
> > <snip>
> >
> > > +
> > > +     /* TODO: if power is software controlled, set up any regulators here */
> > > +
> > > +     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > > +     if (IS_ERR(priv->reset)) {
> > > +             dev_err(dev, "failed to get RESET GPIO\n");
> > > +             return ERR_CAST(priv->reset);
> > > +     }
> > > +     if (priv->reset) {
> > > +             gpiod_set_value(priv->reset, 1);
> > > +             dev_dbg(dev, "asserted RESET\n");
> > > +             msleep(REALTEK_HW_STOP_DELAY);
> > > +             gpiod_set_value(priv->reset, 0);
> > > +             msleep(REALTEK_HW_START_DELAY);
> > > +             dev_dbg(dev, "deasserted RESET\n");
> > > +     }
> >
> > Another thing I would like to suggest is that you do not move the
> > hardware reset and the /* TODO: regulators */ into the common code. I
> > actually wanted to add regulator support for rtl8365mb after you are
> > finished with your series, and I noticed that it will not fit well here,
> > because the supplies are different for the two switch variants.
> >
> > If we were to do the hardware reset here in common_probe_pre(), where
> > should I put my variant-specific regulator_bulk_enable()? I can't put it
> > before _pre() because I do not have the private data allocated yet. If I
> > put it afterwards, then the above hardware reset toggle will have had no
> > effect.
> 
> We would need to move the HW reset out of common_probe_pre(). Putting
> it in _post() or between _pre() and _post() would not solve your case
> as that happens in interface context. The probe is currently
> interface-specific, not variant-specific. Maybe the easiest solution
> would be to move the reset into the detect(), just before getting the
> chip id, creating a new realtek_common_hwreset(). That way, you could
> set up the regulators a little bit before the reset in the variant
> context.
> 
> We could also change the interface-specific to a variant-specific
> probe like this:
> 
> rtl8365mb_probe_smi(){
>        priv = realtek_common_probe() /* previously the _pre func */
>        realtek_smi_probe(priv) /* everything but the common calls */
>        rtl8365mb_setup_regulators(priv)
>        realtek_common_hwreset(priv) /* the reset code from common_probe_pre */
>        rtl8365mb_detect(priv)
>        realtek_common_register(priv) /* previously the
> common_probe_post without the detect */
> }
> 
> rtl8365mb_probe_mdio(){
>     <repeat rtl8365rb_probe_smi but replace realtek_smi_probe with
> realtek_mdio_probe>
> }
> 
> rtl8366rb_probe_smi() { ... }
> rtl8366rb_probe_mdio() { ... }
> 
> But it would be mostly 4 times the same code above, with lots of extra checks.
> 
> For the sake of keeping this patch as small as possible, I would
> prefer to maintain the reset in its current location unless it is a
> merging requirement. You can easily move it out when necessary. I
> don't believe preparing for a potential future change fits in this
> series, as we may misjudge what will be needed to set up the
> regulators.

Yes, it is exhausting with this back and forth. Please just address what
you are willing to address and I will review again. Thanks.

> 
> Regards,
> 
> Luiz

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

* Re: [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common
  2023-12-11  5:13     ` Luiz Angelo Daros de Luca
@ 2023-12-11  9:25       ` Alvin Šipraga
  0 siblings, 0 replies; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-11  9:25 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Mon, Dec 11, 2023 at 02:13:56AM -0300, Luiz Angelo Daros de Luca wrote:
> > > As both realtek-common and realtek-{smi,mdio} must always be loaded
> > > together, we can save some resources merging them into a single module.
> > >
> > > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > > ---
> > >  drivers/net/dsa/realtek/Kconfig          | 4 ++--
> > >  drivers/net/dsa/realtek/Makefile         | 8 +++++---
> > >  drivers/net/dsa/realtek/realtek-common.c | 1 +
> > >  drivers/net/dsa/realtek/realtek-mdio.c   | 4 ----
> > >  drivers/net/dsa/realtek/realtek-smi.c    | 4 ----
> > >  5 files changed, 8 insertions(+), 13 deletions(-)
> > >
> > > diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
> > > index 9d182fde11b4..6989972eebc3 100644
> > > --- a/drivers/net/dsa/realtek/Kconfig
> > > +++ b/drivers/net/dsa/realtek/Kconfig
> > > @@ -16,14 +16,14 @@ menuconfig NET_DSA_REALTEK
> > >  if NET_DSA_REALTEK
> > >
> > >  config NET_DSA_REALTEK_MDIO
> > > -     tristate "Realtek MDIO interface support"
> > > +     bool "Realtek MDIO interface support"
> > >       depends on OF
> > >       help
> > >         Select to enable support for registering switches configured
> > >         through MDIO.
> > >
> > >  config NET_DSA_REALTEK_SMI
> > > -     tristate "Realtek SMI interface support"
> > > +     bool "Realtek SMI interface support"
> > >       depends on OF
> > >       help
> > >         Select to enable support for registering switches connected
> > > diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> > > index 5e0c1ef200a3..88f6652f9850 100644
> > > --- a/drivers/net/dsa/realtek/Makefile
> > > +++ b/drivers/net/dsa/realtek/Makefile
> > > @@ -1,7 +1,9 @@
> > >  # SPDX-License-Identifier: GPL-2.0
> > > -obj-$(CONFIG_NET_DSA_REALTEK)                += realtek-common.o
> > > -obj-$(CONFIG_NET_DSA_REALTEK_MDIO)   += realtek-mdio.o
> > > -obj-$(CONFIG_NET_DSA_REALTEK_SMI)    += realtek-smi.o
> > > +obj-$(CONFIG_NET_DSA_REALTEK)                += realtek_common.o
> > > +realtek_common-objs-y                        := realtek-common.o
> >
> > This is weird with the - and _. Also realtek-common is not a very
> > descriptive module name. Maybe realtek-dsa?
> >
> > obj-$(CONFIG_NET_DSA_REALTEK) += realtek-dsa.o
> > realtek-dsa-objs-y            += realtek-common.o
> > realtek-dsa-objs-$(..._MDIO)  += realtek-mdio.o
> > realtek-dsa-objs-$(..._SMI)   += realtek-smi.o
> 
> Yes, I'm not proud of it. The realtek_common/realtek-common trick is
> just to bypass the fact that I cannot link multiple files into a
> module that has the same name as one of these files. But realtek-dsa
> is fine and it would avoid conflicts with other realtek stuff in the
> kernel that might have a common module. However, I would introduce
> that name already in the previous patch.

OK

> 
> > Also what happens if I just enable CONFIG_NET_DSA_REALTEK and nothing
> > else. Do I get a module that doesn't do anything? Not sure if it's a big
> > deal.
> 
> The config language might not be good enough to handle that nicely.
> There is the "imply" keyword but it does not force anything. I don't
> know how to require "at least one of these two interfaces" without
> creating a dependency cycle. I would just let it build a useless
> common module. Building without variants does make a little bit of
> sense if you want to build a new driver out-of-tree.

Agree, I don't know a good way to prevent it. I don't think it's a big
deal.

> 
> > > +realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o
> > > +realtek_common-objs-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
> > > +realtek_common-objs                  := $(realtek_common-objs-y)
> > >  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-common.c b/drivers/net/dsa/realtek/realtek-common.c
> > > index 75b6aa071990..73c25d114dd3 100644
> > > --- a/drivers/net/dsa/realtek/realtek-common.c
> > > +++ b/drivers/net/dsa/realtek/realtek-common.c
> > > @@ -132,5 +132,6 @@ void realtek_common_remove(struct realtek_priv *priv)
> > >  EXPORT_SYMBOL(realtek_common_remove);
> > >
> > >  MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
> > > +MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> > >  MODULE_DESCRIPTION("Realtek DSA switches common module");
> > >  MODULE_LICENSE("GPL");
> > > diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> > > index 4c9a744b72f8..bb5bff719ae9 100644
> > > --- a/drivers/net/dsa/realtek/realtek-mdio.c
> > > +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> > > @@ -168,7 +168,3 @@ void realtek_mdio_shutdown(struct mdio_device *mdiodev)
> > >       dev_set_drvdata(&mdiodev->dev, NULL);
> > >  }
> > >  EXPORT_SYMBOL_GPL(realtek_mdio_shutdown);
> > > -
> > > -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-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> > > index 246024eec3bd..1ca2aa784d24 100644
> > > --- a/drivers/net/dsa/realtek/realtek-smi.c
> > > +++ b/drivers/net/dsa/realtek/realtek-smi.c
> > > @@ -443,7 +443,3 @@ void realtek_smi_shutdown(struct platform_device *pdev)
> > >       platform_set_drvdata(pdev, NULL);
> > >  }
> > >  EXPORT_SYMBOL_GPL(realtek_smi_shutdown);
> > > -
> > > -MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
> > > -MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via SMI interface");
> > > -MODULE_LICENSE("GPL");
> > > --
> > > 2.43.0
> > >

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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-11  5:02     ` Luiz Angelo Daros de Luca
@ 2023-12-11  9:44       ` Alvin Šipraga
  0 siblings, 0 replies; 34+ messages in thread
From: Alvin Šipraga @ 2023-12-11  9:44 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: netdev, linus.walleij, andrew, f.fainelli, olteanv, davem,
	edumazet, kuba, pabeni, arinc.unal

On Mon, Dec 11, 2023 at 02:02:18AM -0300, Luiz Angelo Daros de Luca wrote:
> > On Fri, Dec 08, 2023 at 01:41:40AM -0300, Luiz Angelo Daros de Luca wrote:
> > > Some code can be shared between both interface modules (MDIO and SMI)
> > > and among variants. Currently, these interface functions are shared:
> > >
> > > - realtek_common_lock
> > > - realtek_common_unlock
> > > - realtek_common_probe
> > > - realtek_common_remove
> > >
> > > The reset during probe was moved to the last moment before a variant
> > > detects the switch. This way, we avoid a reset if anything else fails.
> > >
> > > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > > Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> > > ---
> > >  drivers/net/dsa/realtek/Makefile         |   1 +
> > >  drivers/net/dsa/realtek/realtek-common.c | 136 +++++++++++++++++++++++
> > >  drivers/net/dsa/realtek/realtek-common.h |  16 +++
> > >  drivers/net/dsa/realtek/realtek-mdio.c   | 121 ++------------------
> > >  drivers/net/dsa/realtek/realtek-smi.c    | 124 +++------------------
> > >  drivers/net/dsa/realtek/realtek.h        |   6 +-
> > >  drivers/net/dsa/realtek/rtl8365mb.c      |   9 +-
> > >  drivers/net/dsa/realtek/rtl8366rb.c      |   9 +-
> > >  8 files changed, 194 insertions(+), 228 deletions(-)
> > >  create mode 100644 drivers/net/dsa/realtek/realtek-common.c
> > >  create mode 100644 drivers/net/dsa/realtek/realtek-common.h
> > >
> > > diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
> > > index 0aab57252a7c..5e0c1ef200a3 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)                += realtek-common.o
> >
> > No corresponding Kconfig change?
> 
> NET_DSA_REALTEK already existed for "Realtek Ethernet switch family
> support" entry to the Realtek DSA switch submenu. In the way we used
> to use it, I believe it should be a bool entry, not a tristate. Now,
> with a common module, a tristate fits just fine. So, by mistake, no
> change is needed.
> 
> > >  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
> > > diff --git a/drivers/net/dsa/realtek/realtek-common.c b/drivers/net/dsa/realtek/realtek-common.c
> > > new file mode 100644
> > > index 000000000000..75b6aa071990
> > > --- /dev/null
> > > +++ b/drivers/net/dsa/realtek/realtek-common.c
> > > @@ -0,0 +1,136 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +
> > > +#include <linux/module.h>
> > > +
> > > +#include "realtek.h"
> > > +#include "realtek-common.h"
> > > +
> > > +void realtek_common_lock(void *ctx)
> > > +{
> > > +     struct realtek_priv *priv = ctx;
> > > +
> > > +     mutex_lock(&priv->map_lock);
> > > +}
> > > +EXPORT_SYMBOL_GPL(realtek_common_lock);
> > > +
> > > +void realtek_common_unlock(void *ctx)
> > > +{
> > > +     struct realtek_priv *priv = ctx;
> > > +
> > > +     mutex_unlock(&priv->map_lock);
> > > +}
> > > +EXPORT_SYMBOL_GPL(realtek_common_unlock);
> > > +
> > > +struct realtek_priv *
> > > +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> > > +                      struct regmap_config rc_nolock)
> > > +{
> > > +     const struct realtek_variant *var;
> > > +     struct realtek_priv *priv;
> > > +     struct device_node *np;
> > > +     int ret;
> > > +
> > > +     var = of_device_get_match_data(dev);
> > > +     if (!var)
> > > +             return ERR_PTR(-EINVAL);
> > > +
> > > +     priv = devm_kzalloc(dev, size_add(sizeof(*priv), var->chip_data_sz),
> > > +                         GFP_KERNEL);
> > > +     if (!priv)
> > > +             return ERR_PTR(-ENOMEM);
> > > +
> > > +     mutex_init(&priv->map_lock);
> > > +
> > > +     rc.lock_arg = priv;
> > > +     priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> > > +     if (IS_ERR(priv->map)) {
> > > +             ret = PTR_ERR(priv->map);
> > > +             dev_err(dev, "regmap init failed: %d\n", ret);
> > > +             return ERR_PTR(ret);
> > > +     }
> > > +
> > > +     priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc_nolock);
> > > +     if (IS_ERR(priv->map_nolock)) {
> > > +             ret = PTR_ERR(priv->map_nolock);
> > > +             dev_err(dev, "regmap init failed: %d\n", ret);
> > > +             return ERR_PTR(ret);
> > > +     }
> > > +
> > > +     /* Link forward and backward */
> > > +     priv->dev = dev;
> > > +     priv->variant = var;
> > > +     priv->ops = var->ops;
> > > +     priv->chip_data = (void *)priv + sizeof(*priv);
> > > +
> > > +     dev_set_drvdata(dev, priv);
> > > +     spin_lock_init(&priv->lock);
> > > +
> > > +     np = dev->of_node;
> >
> > This is kind of a pointless variable, just do
> > of_property_read_bool(dev->of_node, ...) below.
> 
> OK.
> 
> >
> > > +
> > > +     priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds");
> > > +
> > > +     /* TODO: if power is software controlled, set up any regulators here */
> > > +
> > > +     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > > +     if (IS_ERR(priv->reset)) {
> > > +             dev_err(dev, "failed to get RESET GPIO\n");
> > > +             return ERR_CAST(priv->reset);
> > > +     }
> > > +     if (priv->reset) {
> > > +             gpiod_set_value(priv->reset, 1);
> > > +             dev_dbg(dev, "asserted RESET\n");
> > > +             msleep(REALTEK_HW_STOP_DELAY);
> > > +             gpiod_set_value(priv->reset, 0);
> > > +             msleep(REALTEK_HW_START_DELAY);
> > > +             dev_dbg(dev, "deasserted RESET\n");
> > > +     }
> > > +
> > > +     return priv;
> > > +}
> > > +EXPORT_SYMBOL(realtek_common_probe_pre);
> > > +
> > > +int realtek_common_probe_post(struct realtek_priv *priv)
> > > +{
> > > +     int ret;
> > > +
> > > +     ret = priv->ops->detect(priv);
> > > +     if (ret) {
> > > +             dev_err(priv->dev, "unable to detect switch\n");
> >
> > dev_err_probe()?
> 
> I'm not sure if detect() is able to return -EPROBE. At least for SMI,
> gpio read/write never returns errors. However, it will not hurt to use
> dev_err_probe() here.

You can just use it to print error values as well, I seem to recall even
the kdoc around it stating as such.

> 
> >
> > > +             return ret;
> > > +     }
> > > +
> > > +     priv->ds = devm_kzalloc(priv->dev, sizeof(*priv->ds), GFP_KERNEL);
> > > +     if (!priv->ds)
> > > +             return -ENOMEM;
> >
> > I guess this could actually just be embedded in realtek_priv and then
> > you don't need to allocate it dynamically here.
> 
> It makes sense. However, shouldn't it be a different commit? This one
> is just moving stuff to a common file, not trying to optimize de code.

You can put it in a separate patch, that's fine.

> 
> > > +
> > > +     priv->ds->priv = priv;
> > > +     priv->ds->dev = priv->dev;
> > > +     priv->ds->ops = priv->ds_ops;
> > > +     priv->ds->num_ports = priv->num_ports;
> > > +
> > > +     ret = dsa_register_switch(priv->ds);
> > > +     if (ret) {
> > > +             dev_err_probe(priv->dev, ret, "unable to register switch\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +EXPORT_SYMBOL(realtek_common_probe_post);
> > > +
> > > +void realtek_common_remove(struct realtek_priv *priv)
> > > +{
> > > +     if (!priv)
> > > +             return;
> > > +
> > > +     dsa_unregister_switch(priv->ds);
> > > +
> > > +     /* leave the device reset asserted */
> > > +     if (priv->reset)
> > > +             gpiod_set_value(priv->reset, 1);
> > > +}
> > > +EXPORT_SYMBOL(realtek_common_remove);
> > > +
> > > +MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>");
> > > +MODULE_DESCRIPTION("Realtek DSA switches common module");
> > > +MODULE_LICENSE("GPL");
> > > diff --git a/drivers/net/dsa/realtek/realtek-common.h b/drivers/net/dsa/realtek/realtek-common.h
> > > new file mode 100644
> > > index 000000000000..405bd0d85d2b
> > > --- /dev/null
> > > +++ b/drivers/net/dsa/realtek/realtek-common.h
> > > @@ -0,0 +1,16 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +
> > > +#ifndef _REALTEK_INTERFACE_H
> > > +#define _REALTEK_INTERFACE_H
> > > +
> > > +#include <linux/regmap.h>
> > > +
> > > +void realtek_common_lock(void *ctx);
> > > +void realtek_common_unlock(void *ctx);
> > > +struct realtek_priv *
> > > +realtek_common_probe_pre(struct device *dev, struct regmap_config rc,
> > > +                      struct regmap_config rc_nolock);
> > > +int realtek_common_probe_post(struct realtek_priv *priv);
> >
> > Maybe it is worth describing what these functions do with a comment.
> >
> > pre:  sets up driver private data struct, sets up regmaps, issues
> >       hardware reset
> >
> > post: registers the dsa switch, calls detect() and then expects
> >       priv->num_ports to be set
> 
> Sure. I'm not sure about the "expects". If I need something, I should
> check and fail. The DSA switch will already fail to register without a
> non-zero number of ports. (although too silently for my taste).
> 
> I don't like names that need too much explanation. It is just a
> symptom of a bad name. Would it make more sense to have
> 
> realtek_common_probe_pre -> realtek_common_probe
> realtek_common_probe_post -> realtek_common_register_switch (although
> it is also detecting the switch)

I prefer _probe and _register_switch actually. But that is because I
would remove the detect() op, so there is no controversy for me.

I agree that a good name would require no explanation to let's go with
_probe and _register_switch if you agree.

> 
> ?
> 
> > The detect() function in itself is a bit funny. Maybe it's not even
> > necessary. Both chip variants set a static num_ports value anyway. You
> > can maybe dump detect() completely and move that code into the
> > variant-specific probe between the calls to common_probe_{pre,post}().
> 
> The probe is not variant-specific but interface-specific. We could,
> indeed, put a static num_ports into realtek_variant and use it.
> However, the main use for detect is to validate you really got a
> supported switch, with the setups being a secondary function. I would
> leave it as is for now. I'm trying to keep the series as small as
> possible.

Fine.

> 
> > > +void realtek_common_remove(struct realtek_priv *priv);
> > > +
> > > +#endif
> >
> > #endif /* _REALTEK_INTERFACE_H */
> >
> > Actually shouldn't it be _REALTEK_COMMON_H?
> 
> Yes, bad ctrl+c/ctrl+v from Vladmir example code.
> 
> > > diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
> > > index 58966d0625c8..4c9a744b72f8 100644
> > > --- a/drivers/net/dsa/realtek/realtek-mdio.c
> > > +++ b/drivers/net/dsa/realtek/realtek-mdio.c
> > > @@ -26,6 +26,7 @@
> > >
> > >  #include "realtek.h"
> > >  #include "realtek-mdio.h"
> > > +#include "realtek-common.h"
> > >
> > >  /* Read/write via mdiobus */
> > >  #define REALTEK_MDIO_CTRL0_REG               31
> > > @@ -100,20 +101,6 @@ static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
> > >       return ret;
> > >  }
> > >
> > > -static void realtek_mdio_lock(void *ctx)
> > > -{
> > > -     struct realtek_priv *priv = ctx;
> > > -
> > > -     mutex_lock(&priv->map_lock);
> > > -}
> > > -
> > > -static void realtek_mdio_unlock(void *ctx)
> > > -{
> > > -     struct realtek_priv *priv = ctx;
> > > -
> > > -     mutex_unlock(&priv->map_lock);
> > > -}
> > > -
> > >  static const struct regmap_config realtek_mdio_regmap_config = {
> > >       .reg_bits = 10, /* A4..A0 R4..R0 */
> > >       .val_bits = 16,
> > > @@ -124,8 +111,8 @@ static const struct regmap_config realtek_mdio_regmap_config = {
> > >       .reg_read = realtek_mdio_read,
> > >       .reg_write = realtek_mdio_write,
> > >       .cache_type = REGCACHE_NONE,
> > > -     .lock = realtek_mdio_lock,
> > > -     .unlock = realtek_mdio_unlock,
> > > +     .lock = realtek_common_lock,
> > > +     .unlock = realtek_common_unlock,
> > >  };
> > >
> > >  static const struct regmap_config realtek_mdio_nolock_regmap_config = {
> > > @@ -143,98 +130,21 @@ static const struct regmap_config realtek_mdio_nolock_regmap_config = {
> > >
> > >  int realtek_mdio_probe(struct mdio_device *mdiodev)
> > >  {
> > > -     struct realtek_priv *priv;
> > >       struct device *dev = &mdiodev->dev;
> > > -     const struct realtek_variant *var;
> > > -     struct regmap_config rc;
> > > -     struct device_node *np;
> > > -     int ret;
> > > -
> > > -     var = of_device_get_match_data(dev);
> > > -     if (!var)
> > > -             return -EINVAL;
> > > -
> > > -     priv = devm_kzalloc(&mdiodev->dev,
> > > -                         size_add(sizeof(*priv), var->chip_data_sz),
> > > -                         GFP_KERNEL);
> > > -     if (!priv)
> > > -             return -ENOMEM;
> > > -
> > > -     mutex_init(&priv->map_lock);
> > > -
> > > -     rc = realtek_mdio_regmap_config;
> > > -     rc.lock_arg = priv;
> > > -     priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> > > -     if (IS_ERR(priv->map)) {
> > > -             ret = PTR_ERR(priv->map);
> > > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > > -             return ret;
> > > -     }
> > > +     struct realtek_priv *priv;
> > >
> > > -     rc = realtek_mdio_nolock_regmap_config;
> > > -     priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
> > > -     if (IS_ERR(priv->map_nolock)) {
> > > -             ret = PTR_ERR(priv->map_nolock);
> > > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > > -             return ret;
> > > -     }
> > > +     priv = realtek_common_probe_pre(dev, realtek_mdio_regmap_config,
> > > +                                     realtek_mdio_nolock_regmap_config);
> > > +     if (IS_ERR(priv))
> > > +             return PTR_ERR(priv);
> > >
> > > -     priv->mdio_addr = 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->mdio_addr = mdiodev->addr;
> > >       priv->write_reg_noack = realtek_mdio_write;
> > > +     priv->ds_ops = priv->variant->ds_ops_mdio;
> > >
> > > -     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");
> > > -
> > > -     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > > -     if (IS_ERR(priv->reset)) {
> > > -             dev_err(dev, "failed to get RESET GPIO\n");
> > > -             return PTR_ERR(priv->reset);
> > > -     }
> > > -
> > > -     if (priv->reset) {
> > > -             gpiod_set_value(priv->reset, 1);
> > > -             dev_dbg(dev, "asserted RESET\n");
> > > -             msleep(REALTEK_HW_STOP_DELAY);
> > > -             gpiod_set_value(priv->reset, 0);
> > > -             msleep(REALTEK_HW_START_DELAY);
> > > -             dev_dbg(dev, "deasserted RESET\n");
> > > -     }
> > > -
> > > -     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_mdio;
> > > -
> > > -     ret = dsa_register_switch(priv->ds);
> > > -     if (ret) {
> > > -             dev_err(priv->dev, "unable to register switch ret = %d\n", ret);
> > > -             return ret;
> > > -     }
> > > +     return realtek_common_probe_post(priv);
> > >
> > > -     return 0;
> > >  }
> > >  EXPORT_SYMBOL_GPL(realtek_mdio_probe);
> > >
> > > @@ -242,14 +152,7 @@ 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);
> > > -
> > > -     /* leave the device reset asserted */
> > > -     if (priv->reset)
> > > -             gpiod_set_value(priv->reset, 1);
> > > +     realtek_common_remove(priv);
> > >  }
> > >  EXPORT_SYMBOL_GPL(realtek_mdio_remove);
> > >
> > > diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
> > > index 55586d158c0e..246024eec3bd 100644
> > > --- a/drivers/net/dsa/realtek/realtek-smi.c
> > > +++ b/drivers/net/dsa/realtek/realtek-smi.c
> > > @@ -41,12 +41,13 @@
> > >
> > >  #include "realtek.h"
> > >  #include "realtek-smi.h"
> > > +#include "realtek-common.h"
> > >
> > >  #define REALTEK_SMI_ACK_RETRY_COUNT          5
> > >
> > >  static inline void realtek_smi_clk_delay(struct realtek_priv *priv)
> > >  {
> > > -     ndelay(priv->clk_delay);
> > > +     ndelay(priv->variant->clk_delay);
> > >  }
> > >
> > >  static void realtek_smi_start(struct realtek_priv *priv)
> > > @@ -209,7 +210,7 @@ static int realtek_smi_read_reg(struct realtek_priv *priv, u32 addr, u32 *data)
> > >       realtek_smi_start(priv);
> > >
> > >       /* Send READ command */
> > > -     ret = realtek_smi_write_byte(priv, priv->cmd_read);
> > > +     ret = realtek_smi_write_byte(priv, priv->variant->cmd_read);
> > >       if (ret)
> > >               goto out;
> > >
> > > @@ -250,7 +251,7 @@ static int realtek_smi_write_reg(struct realtek_priv *priv,
> > >       realtek_smi_start(priv);
> > >
> > >       /* Send WRITE command */
> > > -     ret = realtek_smi_write_byte(priv, priv->cmd_write);
> > > +     ret = realtek_smi_write_byte(priv, priv->variant->cmd_write);
> > >       if (ret)
> > >               goto out;
> > >
> > > @@ -311,20 +312,6 @@ static int realtek_smi_read(void *ctx, u32 reg, u32 *val)
> > >       return realtek_smi_read_reg(priv, reg, val);
> > >  }
> > >
> > > -static void realtek_smi_lock(void *ctx)
> > > -{
> > > -     struct realtek_priv *priv = ctx;
> > > -
> > > -     mutex_lock(&priv->map_lock);
> > > -}
> > > -
> > > -static void realtek_smi_unlock(void *ctx)
> > > -{
> > > -     struct realtek_priv *priv = ctx;
> > > -
> > > -     mutex_unlock(&priv->map_lock);
> > > -}
> > > -
> > >  static const struct regmap_config realtek_smi_regmap_config = {
> > >       .reg_bits = 10, /* A4..A0 R4..R0 */
> > >       .val_bits = 16,
> > > @@ -335,8 +322,8 @@ static const struct regmap_config realtek_smi_regmap_config = {
> > >       .reg_read = realtek_smi_read,
> > >       .reg_write = realtek_smi_write,
> > >       .cache_type = REGCACHE_NONE,
> > > -     .lock = realtek_smi_lock,
> > > -     .unlock = realtek_smi_unlock,
> > > +     .lock = realtek_common_lock,
> > > +     .unlock = realtek_common_unlock,
> > >  };
> > >
> > >  static const struct regmap_config realtek_smi_nolock_regmap_config = {
> > > @@ -411,100 +398,28 @@ static int realtek_smi_setup_mdio(struct dsa_switch *ds)
> > >
> > >  int realtek_smi_probe(struct platform_device *pdev)
> > >  {
> > > -     const struct realtek_variant *var;
> > >       struct device *dev = &pdev->dev;
> > >       struct realtek_priv *priv;
> > > -     struct regmap_config rc;
> > > -     struct device_node *np;
> > > -     int ret;
> > > -
> > > -     var = of_device_get_match_data(dev);
> > > -     np = dev->of_node;
> > > -
> > > -     priv = devm_kzalloc(dev, sizeof(*priv) + var->chip_data_sz, GFP_KERNEL);
> > > -     if (!priv)
> > > -             return -ENOMEM;
> > > -     priv->chip_data = (void *)priv + sizeof(*priv);
> > > -
> > > -     mutex_init(&priv->map_lock);
> > > -
> > > -     rc = realtek_smi_regmap_config;
> > > -     rc.lock_arg = priv;
> > > -     priv->map = devm_regmap_init(dev, NULL, priv, &rc);
> > > -     if (IS_ERR(priv->map)) {
> > > -             ret = PTR_ERR(priv->map);
> > > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > > -             return ret;
> > > -     }
> > > -
> > > -     rc = realtek_smi_nolock_regmap_config;
> > > -     priv->map_nolock = devm_regmap_init(dev, NULL, priv, &rc);
> > > -     if (IS_ERR(priv->map_nolock)) {
> > > -             ret = PTR_ERR(priv->map_nolock);
> > > -             dev_err(dev, "regmap init failed: %d\n", ret);
> > > -             return ret;
> > > -     }
> > > -
> > > -     /* Link forward and backward */
> > > -     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;
> > > -
> > > -     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);
> > >
> > > -     /* TODO: if power is software controlled, set up any regulators here */
> > > -
> > > -     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> > > -     if (IS_ERR(priv->reset)) {
> > > -             dev_err(dev, "failed to get RESET GPIO\n");
> > > -             return PTR_ERR(priv->reset);
> > > -     }
> > > -     if (priv->reset) {
> > > -             gpiod_set_value(priv->reset, 1);
> > > -             dev_dbg(dev, "asserted RESET\n");
> > > -             msleep(REALTEK_HW_STOP_DELAY);
> > > -             gpiod_set_value(priv->reset, 0);
> > > -             msleep(REALTEK_HW_START_DELAY);
> > > -             dev_dbg(dev, "deasserted RESET\n");
> > > -     }
> > > +     priv = realtek_common_probe_pre(dev, realtek_smi_regmap_config,
> > > +                                     realtek_smi_nolock_regmap_config);
> > > +     if (IS_ERR(priv))
> > > +             return PTR_ERR(priv);
> > >
> > >       /* Fetch MDIO pins */
> > >       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);
> > >
> > > -     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->write_reg_noack = realtek_smi_write_reg_noack;
> > > +     priv->setup_interface = realtek_smi_setup_mdio;
> > > +     priv->ds_ops = priv->variant->ds_ops_smi;
> > >
> > > -     priv->ds->ops = var->ds_ops_smi;
> > > -     ret = dsa_register_switch(priv->ds);
> > > -     if (ret) {
> > > -             dev_err_probe(dev, ret, "unable to register switch\n");
> > > -             return ret;
> > > -     }
> > > -     return 0;
> > > +     return (priv);
> >
> > ret = realtek_common_probe_post(priv);
> > if (ret)
> >   return ret;
> >
> > return 0;
> 
> The ret variable is no more. Is it worth it to replace a single line
> with 4 more?

Please keep the ret variable and conform with the style in the rest of
the driver.

> 
> > >  }
> > >  EXPORT_SYMBOL_GPL(realtek_smi_probe);
> > >
> > > @@ -512,14 +427,7 @@ void realtek_smi_remove(struct platform_device *pdev)
> > >  {
> > >       struct realtek_priv *priv = platform_get_drvdata(pdev);
> > >
> > > -     if (!priv)
> > > -             return;
> > > -
> > > -     dsa_unregister_switch(priv->ds);
> > > -
> > > -     /* leave the device reset asserted */
> > > -     if (priv->reset)
> > > -             gpiod_set_value(priv->reset, 1);
> > > +     realtek_common_remove(priv);
> > >  }
> > >  EXPORT_SYMBOL_GPL(realtek_smi_remove);
> > >
> > > diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h
> > > index e9ee778665b2..fbd0616c1df3 100644
> > > --- a/drivers/net/dsa/realtek/realtek.h
> > > +++ b/drivers/net/dsa/realtek/realtek.h
> > > @@ -58,11 +58,9 @@ struct realtek_priv {
> > >       struct mii_bus          *bus;
> > >       int                     mdio_addr;
> > >
> > > -     unsigned int            clk_delay;
> > > -     u8                      cmd_read;
> > > -     u8                      cmd_write;
> > >       spinlock_t              lock; /* Locks around command writes */
> > >       struct dsa_switch       *ds;
> > > +     const struct dsa_switch_ops *ds_ops;
> > >       struct irq_domain       *irqdomain;
> > >       bool                    leds_disabled;
> > >
> > > @@ -79,6 +77,8 @@ struct realtek_priv {
> > >       int                     vlan_enabled;
> > >       int                     vlan4k_enabled;
> > >
> > > +     const struct realtek_variant *variant;
> > > +
> > >       char                    buf[4096];
> > >       void                    *chip_data; /* Per-chip extra variant data */
> > >  };
> > > diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
> > > index 526bf98cef1d..ac848b965f84 100644
> > > --- a/drivers/net/dsa/realtek/rtl8365mb.c
> > > +++ b/drivers/net/dsa/realtek/rtl8365mb.c
> > > @@ -103,6 +103,7 @@
> > >  #include "realtek.h"
> > >  #include "realtek-smi.h"
> > >  #include "realtek-mdio.h"
> > > +#include "realtek-common.h"
> > >
> > >  /* Family-specific data and limits */
> > >  #define RTL8365MB_PHYADDRMAX         7
> > > @@ -691,7 +692,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
> > >       u32 val;
> > >       int ret;
> > >
> > > -     mutex_lock(&priv->map_lock);
> > > +     realtek_common_lock(priv);
> > >
> > >       ret = rtl8365mb_phy_poll_busy(priv);
> > >       if (ret)
> > > @@ -724,7 +725,7 @@ static int rtl8365mb_phy_ocp_read(struct realtek_priv *priv, int phy,
> > >       *data = val & 0xFFFF;
> > >
> > >  out:
> > > -     mutex_unlock(&priv->map_lock);
> > > +     realtek_common_unlock(priv);
> > >
> > >       return ret;
> > >  }
> > > @@ -735,7 +736,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
> > >       u32 val;
> > >       int ret;
> > >
> > > -     mutex_lock(&priv->map_lock);
> > > +     realtek_common_lock(priv);
> > >
> > >       ret = rtl8365mb_phy_poll_busy(priv);
> > >       if (ret)
> > > @@ -766,7 +767,7 @@ static int rtl8365mb_phy_ocp_write(struct realtek_priv *priv, int phy,
> > >               goto out;
> > >
> > >  out:
> > > -     mutex_unlock(&priv->map_lock);
> > > +     realtek_common_unlock(priv);
> > >
> > >       return 0;
> > >  }
> > > diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
> > > index 09c17de19457..1cc4de3cf54f 100644
> > > --- a/drivers/net/dsa/realtek/rtl8366rb.c
> > > +++ b/drivers/net/dsa/realtek/rtl8366rb.c
> > > @@ -24,6 +24,7 @@
> > >  #include "realtek.h"
> > >  #include "realtek-smi.h"
> > >  #include "realtek-mdio.h"
> > > +#include "realtek-common.h"
> > >
> > >  #define RTL8366RB_PORT_NUM_CPU               5
> > >  #define RTL8366RB_NUM_PORTS          6
> > > @@ -1707,7 +1708,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
> > >       if (phy > RTL8366RB_PHY_NO_MAX)
> > >               return -EINVAL;
> > >
> > > -     mutex_lock(&priv->map_lock);
> > > +     realtek_common_lock(priv);
> > >
> > >       ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
> > >                          RTL8366RB_PHY_CTRL_READ);
> > > @@ -1735,7 +1736,7 @@ static int rtl8366rb_phy_read(struct realtek_priv *priv, int phy, int regnum)
> > >               phy, regnum, reg, val);
> > >
> > >  out:
> > > -     mutex_unlock(&priv->map_lock);
> > > +     realtek_common_unlock(priv);
> > >
> > >       return ret;
> > >  }
> > > @@ -1749,7 +1750,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
> > >       if (phy > RTL8366RB_PHY_NO_MAX)
> > >               return -EINVAL;
> > >
> > > -     mutex_lock(&priv->map_lock);
> > > +     realtek_common_lock(priv);
> > >
> > >       ret = regmap_write(priv->map_nolock, RTL8366RB_PHY_ACCESS_CTRL_REG,
> > >                          RTL8366RB_PHY_CTRL_WRITE);
> > > @@ -1766,7 +1767,7 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
> > >               goto out;
> > >
> > >  out:
> > > -     mutex_unlock(&priv->map_lock);
> > > +     realtek_common_unlock(priv);
> > >
> > >       return ret;
> > >  }
> > > --
> > > 2.43.0
> > >
> 
> Regards,
> 
> Luiz

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-08 18:05       ` Luiz Angelo Daros de Luca
@ 2023-12-11 17:11         ` Vladimir Oltean
  2023-12-12  3:47           ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 34+ messages in thread
From: Vladimir Oltean @ 2023-12-11 17:11 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew, f.fainelli,
	davem, edumazet, kuba, pabeni, arinc.unal

On Fri, Dec 08, 2023 at 03:05:41PM -0300, Luiz Angelo Daros de Luca wrote:
> Reviewing the code again, I believe it was not just misplacing the
> of_put_node() but probably calling it twice.
> 
> devm_mdiobus_alloc() doesn't set the dev in mii_bus. So, dev is all
> zeros. The dev.of_node normal place to be defined is:
> 
> devm_of_mdiobus_register()
>   __devm_of_mdiobus_register()
>     __of_mdiobus_register()
>       device_set_node()
> 
> The only way for that value, set by the line I removed, to persist is
> when the devm_of_mdiobus_register() fails before device_set_node().

Did you consider that __of_mdiobus_register() -> device_set_node() is
actually overwriting priv->user_mii_bus->dev.of_node with the same value?
So the reference to mdio_np persists even if technically overwritten.
The fact that the assignment looks redundant is another story.

> My guess is that it was set to be used by realtek_smi_remove() if it
> is called when registration fails. However, in that case, both
> realtek_smi_setup_mdio() and realtek_smi_setup_mdio() would put the

You listed the same function name twice. You meant realtek_smi_remove()
the second time?

> node. So, either the line is useless or it will effectively result in
> calling of_node_put() twice.

False logic, since realtek_smi_remove() is not called when probe() fails.
ds->ops->setup() is called from probe() context. So no double of_node_put().
That's a general rule with the kernel API. When a setup API function fails,
it is responsible of cleaning up the temporary things it did. The
teardown API function is only called when the setup was performed fully.

(the only exception I'm aware of is the Qdisc API, but that's not
exactly the best model to follow)

> If I really needed to put that node in the realtek_smi_remove(), I
> would use a dedicated field in realtek_priv instead of reusing a
> reference for it inside another structure.
> 
> I'll add some notes to the commit message about all these but moving
> the of_node_put() to the same function that gets the node solved all
> the issues.

"Solved all the issues" - what are those issues, first of all?

The simple fact is: of_get_compatible_child() returns an OF node with an
elevated refcount. It passes it to of_mdiobus_register() which does not
take ownership of it per se, but assigns it to bus->dev.of_node, which
is accessible until device_del() from mdiobus_unregister().

The PHY library does not make the ownership rules of the of_node very
clear, but since it takes no reference on it, it will fail in subtle
ways if you pull the carpet from under its feet.

For example, I expect of_mdio_find_bus() to fail. That is used only
rarely, like by the MDIO mux driver which I suppose you haven't tested.

If you want, you could make the OF MDIO API get() and put() the reference,
instead of using something it doesn't fully own. But currently the code
doesn't do that. Try to acknowledge what exists, first.

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

* Re: [PATCH net-next 4/7] net: dsa: realtek: create realtek-common
  2023-12-11  9:24       ` Alvin Šipraga
@ 2023-12-11 17:19         ` Vladimir Oltean
  0 siblings, 0 replies; 34+ messages in thread
From: Vladimir Oltean @ 2023-12-11 17:19 UTC (permalink / raw)
  To: Alvin Šipraga
  Cc: Luiz Angelo Daros de Luca, netdev, linus.walleij, andrew,
	f.fainelli, davem, edumazet, kuba, pabeni, arinc.unal

On Mon, Dec 11, 2023 at 09:24:35AM +0000, Alvin Šipraga wrote:
> Yes, it is exhausting with this back and forth. Please just address what
> you are willing to address and I will review again. Thanks.

Alvin, I really appreciate the time you've put into reviewing this.
It is very helpful to have you around.

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-11 17:11         ` Vladimir Oltean
@ 2023-12-12  3:47           ` Luiz Angelo Daros de Luca
  2023-12-12 21:58             ` Vladimir Oltean
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-12  3:47 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew, f.fainelli,
	davem, edumazet, kuba, pabeni, arinc.unal

> > Reviewing the code again, I believe it was not just misplacing the
> > of_put_node() but probably calling it twice.
> >
> > devm_mdiobus_alloc() doesn't set the dev in mii_bus. So, dev is all
> > zeros. The dev.of_node normal place to be defined is:
> >
> > devm_of_mdiobus_register()
> >   __devm_of_mdiobus_register()
> >     __of_mdiobus_register()
> >       device_set_node()
> >
> > The only way for that value, set by the line I removed, to persist is
> > when the devm_of_mdiobus_register() fails before device_set_node().
>
> Did you consider that __of_mdiobus_register() -> device_set_node() is
> actually overwriting priv->user_mii_bus->dev.of_node with the same value?
> So the reference to mdio_np persists even if technically overwritten.
> The fact that the assignment looks redundant is another story.

Yes, I believe it is just redundant.

> > My guess is that it was set to be used by realtek_smi_remove() if it
> > is called when registration fails. However, in that case, both
> > realtek_smi_setup_mdio() and realtek_smi_setup_mdio() would put the
>
> You listed the same function name twice. You meant realtek_smi_remove()
> the second time?

yes

> > node. So, either the line is useless or it will effectively result in
> > calling of_node_put() twice.
>
> False logic, since realtek_smi_remove() is not called when probe() fails.
> ds->ops->setup() is called from probe() context. So no double of_node_put().
> That's a general rule with the kernel API. When a setup API function fails,
> it is responsible of cleaning up the temporary things it did. The
> teardown API function is only called when the setup was performed fully.

So, "the line is useless".

> (the only exception I'm aware of is the Qdisc API, but that's not
> exactly the best model to follow)
>
> > If I really needed to put that node in the realtek_smi_remove(), I
> > would use a dedicated field in realtek_priv instead of reusing a
> > reference for it inside another structure.
> >
> > I'll add some notes to the commit message about all these but moving
> > the of_node_put() to the same function that gets the node solved all
> > the issues.
>
> "Solved all the issues" - what are those issues, first of all?

1) the useless assignment
2) the (possible) double of_node_put(), which proved to be false.

> The simple fact is: of_get_compatible_child() returns an OF node with an
> elevated refcount. It passes it to of_mdiobus_register() which does not
> take ownership of it per se, but assigns it to bus->dev.of_node, which
> is accessible until device_del() from mdiobus_unregister().

Normally, when you have a refcount system, whenever you have a
reference to an object, you should increase the refcount. I thought
that every time you assign a kobject to a structure, you should get it
as well (and put it when you deallocate it). But that's just what I
would expect, not something I found in docs.

I see distinct behaviors with methods that assign the dev.of_node
using device_set_node() in OF MDIO API code and that's not good:

static int of_mdiobus_register_device(struct mii_bus *mdio,
                                     struct device_node *child, u32 addr)
{
       (...)
       fwnode_handle_get(fwnode);
       device_set_node(&mdiodev->dev, fwnode);
       (...)
}

int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
                                      struct phy_device *phy,
                                      struct fwnode_handle *child, u32 addr)
{
       (...)
       fwnode_handle_get(child);
       device_set_node(&phy->mdio.dev, child);
       (...)
}

int of_mdiobus_phy_device_register(struct mii_bus *mdio, struct phy_device *phy,
                                  struct device_node *child, u32 addr)
{
       return fwnode_mdiobus_phy_device_register(mdio, phy,
                                                 of_fwnode_handle(child),
}

int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
                         struct module *owner)
{
       (...)
       device_set_node(&mdio->dev, of_fwnode_handle(np));
       (...)
       for_each_available_child_of_node(np, child) {
                (...)
                if (of_mdiobus_child_is_phy(child))
                       rc = of_mdiobus_register_phy(mdio, child, addr);
               else
                       rc = of_mdiobus_register_device(mdio, child, addr);
       }
})

Each deals differently with the device_node it receives. Both
of_mdiobus_register_phy and of_mdiobus_register_device gets the child
before assigning it to the device but not __of_mdiobus_register. Why?

After some more study, I think it is just because, while an
of_node_get() just before device_set_node() fits nicely in
__of_mdiobus_register(), there is not a good place in of_mdio to put
it. We don't have an of_mdiobus_unregister(). The unregistration
happens only in mdiobus_unregister(), where, I guess, it should avoid
OF-specific code. Even if we put OF code there, we would need to know
during mdiobus_unregister() if the bus->dev.of_node was gotten by
of_mdio or someone else. I believe it is not nice to externally assign
dev.of_node directly to mdiobus but realtek switch driver is doing
just that and others might be doing the same thing.

The delegation of of_node_get/put to the caller seems to be just an
easy workaround the fact that there is no good place to put a node
that of_mdio would get. For devm functions, we could include the
get/put call creating a new devm_of_mdiobus_unregister() but I believe
devm and non-devm needs to be equivalent (except for the resource
deallocation).

> The PHY library does not make the ownership rules of the of_node very
> clear, but since it takes no reference on it, it will fail in subtle
> ways if you pull the carpet from under its feet.
>
> For example, I expect of_mdio_find_bus() to fail. That is used only
> rarely, like by the MDIO mux driver which I suppose you haven't tested.

No, I didn't test it. In fact, most embedded devices will not use
dynamic OF and all those of_node_get/put will be a noop.

> If you want, you could make the OF MDIO API get() and put() the reference,
> instead of using something it doesn't fully own. But currently the code
> doesn't do that. Try to acknowledge what exists, first.

What I saw in other drivers outside drivers/net is that one that
allocates the dev will get the node before assigning dev.of_node and
put it before freeing the device. The mdiobus case seems to be
different. I believe it would make the code more robust if we could
fix that inside OF MDIO API and not just document its behavior. It
will also not break existing uses as extra get/put's are OK.

I believe we could add an unregister callback to mii_bus. It wouldn't
be too complex:

From b5b059ea4491e9f745872220fb94d8105e2d7d43 Mon Sep 17 00:00:00 2001
From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Date: Tue, 12 Dec 2023 00:26:06 -0300
Subject: [PATCH] net: mdio: get/put device node during (un)registration

__of_mdiobus_register() was storing the device node in dev.of_node
without increasing its refcount. It was implicitly delegating to the
caller to maintain the node allocated until mdiobus was unregistered.

Now, the __of_mdiobus_register() will get the node before assigning it,
and of_mdiobus_unregister_callback() will be called at the end of
mdio_unregister().

Drivers can now put the node just after the MDIO registration.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
---
drivers/net/mdio/of_mdio.c | 12 +++++++++++-
drivers/net/phy/mdio_bus.c |  3 +++
include/linux/phy.h        |  3 +++
3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index 64ebcb6d235c..9b6cab6154e0 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -139,6 +139,11 @@ bool of_mdiobus_child_is_phy(struct device_node *child)
}
EXPORT_SYMBOL(of_mdiobus_child_is_phy);

+static void __of_mdiobus_unregister_callback(struct mii_bus *mdio)
+{
+       of_node_put(mdio->dev.of_node);
+}
+
/**
 * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree
 * @mdio: pointer to mii_bus structure
@@ -166,6 +171,8 @@ int __of_mdiobus_register(struct mii_bus *mdio,
struct device_node *np,
        * the device tree are populated after the bus has been registered */
       mdio->phy_mask = ~0;

+       mdio->__unregister_callback = __of_mdiobus_unregister_callback;
+       of_node_get(np);
       device_set_node(&mdio->dev, of_fwnode_handle(np));

       /* Get bus level PHY reset GPIO details */
@@ -177,7 +184,7 @@ int __of_mdiobus_register(struct mii_bus *mdio,
struct device_node *np,
       /* Register the MDIO bus */
       rc = __mdiobus_register(mdio, owner);
       if (rc)
-               return rc;
+               goto put_node;

       /* Loop over the child nodes and register a phy_device for each phy */
       for_each_available_child_of_node(np, child) {
@@ -237,6 +244,9 @@ int __of_mdiobus_register(struct mii_bus *mdio,
struct device_node *np,
unregister:
       of_node_put(child);
       mdiobus_unregister(mdio);
+
+put_node:
+       of_node_put(np);
       return rc;
}
EXPORT_SYMBOL(__of_mdiobus_register);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 25dcaa49ab8b..1229b8e4c53b 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -787,6 +787,9 @@ void mdiobus_unregister(struct mii_bus *bus)
               gpiod_set_value_cansleep(bus->reset_gpiod, 1);

       device_del(&bus->dev);
+
+       if (bus->__unregister_callback)
+               bus->__unregister_callback(bus);
}
EXPORT_SYMBOL(mdiobus_unregister);

diff --git a/include/linux/phy.h b/include/linux/phy.h
index e5f1f41e399c..2b383da4d825 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -433,6 +433,9 @@ struct mii_bus {

       /** @shared: shared state across different PHYs */
       struct phy_package_shared *shared[PHY_MAX_ADDR];
+
+       /** @__unregister_callback: called at the last step of unregistration */
+       void (*__unregister_callback)(struct mii_bus *bus);
};
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)

--
2.43.0

If we don't fix that in OF MDIO API, we would need to fix
fe7324b932222 as well, moving the put to the dsa_switch_teardown().

Regards,

Luiz

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-12  3:47           ` Luiz Angelo Daros de Luca
@ 2023-12-12 21:58             ` Vladimir Oltean
  2023-12-13  4:37               ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 34+ messages in thread
From: Vladimir Oltean @ 2023-12-12 21:58 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew, f.fainelli,
	davem, edumazet, kuba, pabeni, arinc.unal

On Tue, Dec 12, 2023 at 12:47:57AM -0300, Luiz Angelo Daros de Luca wrote:
> The unregistration happens only in mdiobus_unregister(), where, I
> guess, it should avoid OF-specific code. Even if we put OF code there,
> we would need to know during mdiobus_unregister() if the
> bus->dev.of_node was gotten by of_mdio or someone else.
> 
> I believe it is not nice to externally assign dev.of_node directly to
> mdiobus but realtek switch driver is doing just that and others might
> be doing the same thing.

Well, make up your mind: earlier you said the user_mii_bus->dev.of_node
assignment from the Realtek DSA driver is redundant, because
devm_of_mdiobus_register() -> ... -> __of_mdiobus_register() does it
anyway. So if it's redundant, you can remove it and nothing changes.
What's so "not nice" about it that's worth complaining?

Are you trying to say that you're concerned that some drivers might be
populating the mii_bus->dev.of_node manually, and then proceeding to
call the _non-OF_ mdiobus_register() variant?

Some drivers like bcm_sf2.c? :)

That will be a problem, yes. If a clean result is the goal, I guess some
consolidation needs to be done before any new rule could be added.
Otherwise, yeah, we can just snap on one more lazy layer of complexity,
no problem. My 2 cents.

> The delegation of of_node_get/put to the caller seems to be just an
> easy workaround the fact that there is no good place to put a node
> that of_mdio would get. For devm functions, we could include the
> get/put call creating a new devm_of_mdiobus_unregister() but I believe
> devm and non-devm needs to be equivalent (except for the resource
> deallocation).

How did we get here, who suggested to get and put the references to the
OF node outside of the OF MDIO API?

> > If you want, you could make the OF MDIO API get() and put() the reference,
> > instead of using something it doesn't fully own. But currently the code
> > doesn't do that. Try to acknowledge what exists, first.
> 
> What I saw in other drivers outside drivers/net is that one that
> allocates the dev will get the node before assigning dev.of_node and
> put it before freeing the device. The mdiobus case seems to be
> different. I believe it would make the code more robust if we could
> fix that inside OF MDIO API and not just document its behavior. It
> will also not break existing uses as extra get/put's are OK.
> 
> I believe we could add an unregister callback to mii_bus. It wouldn't
> be too complex:
> 
> From b5b059ea4491e9f745872220fb94d8105e2d7d43 Mon Sep 17 00:00:00 2001
> From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> Date: Tue, 12 Dec 2023 00:26:06 -0300
> Subject: [PATCH] net: mdio: get/put device node during (un)registration
> 
> __of_mdiobus_register() was storing the device node in dev.of_node
> without increasing its refcount. It was implicitly delegating to the
> caller to maintain the node allocated until mdiobus was unregistered.
> 
> Now, the __of_mdiobus_register() will get the node before assigning it,
> and of_mdiobus_unregister_callback() will be called at the end of
> mdio_unregister().
> 
> Drivers can now put the node just after the MDIO registration.
> 
> Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> ---
> drivers/net/mdio/of_mdio.c | 12 +++++++++++-
> drivers/net/phy/mdio_bus.c |  3 +++
> include/linux/phy.h        |  3 +++
> 3 files changed, 17 insertions(+), 1 deletion(-)

I don't mean to be rude, but I don't have the time to dig into this any
further, sorry. If you are truly committed to better the phylib API,
please bring it up with the phylib people instead. I literally only
care about the thing that Alvin pointed out, which is that you made
unjustified changes to a DSA driver.

> If we don't fix that in OF MDIO API, we would need to fix
> fe7324b932222 as well, moving the put to the dsa_switch_teardown().

Oh, couldn't we straight-up revert that instead? :) The user_mii_bus
is created by DSA for compatibility with non-OF. I cannot understand
why you insist to attach an OF node to it.

But otherwise, yes, it is the same situation: of_node_put(), called
before unregistering an MDIO bus registered with of_mdiobus_register(),
means that the full OF API on this MDIO bus may not work correctly.
I don't know the exact conditions though. It might be marginal or even
a bug that's impossible to trigger. I haven't tested anything.

In any case, while I encourage you to make OF node refcounting work in
the way that you think is intuitive, I want to be clear about one thing,
and that is that I'm not onboard with modifying phylib to make a non
use-case in DSA work, aka OF-aware user_mii_bus (an oxymoron).

I understand why a driver may want a ds->user_mii_bus. And I understand
why a driver may want an MDIO bus with an of_node. What I don't understand
is who might want both at the same time, and why.

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-12 21:58             ` Vladimir Oltean
@ 2023-12-13  4:37               ` Luiz Angelo Daros de Luca
  2023-12-13 13:04                 ` Vladimir Oltean
  0 siblings, 1 reply; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-13  4:37 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew, f.fainelli,
	davem, edumazet, kuba, pabeni, arinc.unal

> > The unregistration happens only in mdiobus_unregister(), where, I
> > guess, it should avoid OF-specific code. Even if we put OF code there,
> > we would need to know during mdiobus_unregister() if the
> > bus->dev.of_node was gotten by of_mdio or someone else.
> >
> > I believe it is not nice to externally assign dev.of_node directly to
> > mdiobus but realtek switch driver is doing just that and others might
> > be doing the same thing.
>
> Well, make up your mind: earlier you said the user_mii_bus->dev.of_node
> assignment from the Realtek DSA driver is redundant, because
> devm_of_mdiobus_register() -> ... -> __of_mdiobus_register() does it
> anyway. So if it's redundant, you can remove it and nothing changes.
> What's so "not nice" about it that's worth complaining?
>
> Are you trying to say that you're concerned that some drivers might be
> populating the mii_bus->dev.of_node manually, and then proceeding to
> call the _non-OF_ mdiobus_register() variant?

Yes. Just like that. :)

> Some drivers like bcm_sf2.c? :)

Yeah.

> That will be a problem, yes. If a clean result is the goal, I guess some
> consolidation needs to be done before any new rule could be added.
> Otherwise, yeah, we can just snap on one more lazy layer of complexity,
> no problem. My 2 cents.
>
> > The delegation of of_node_get/put to the caller seems to be just an
> > easy workaround the fact that there is no good place to put a node
> > that of_mdio would get. For devm functions, we could include the
> > get/put call creating a new devm_of_mdiobus_unregister() but I believe
> > devm and non-devm needs to be equivalent (except for the resource
> > deallocation).
>
> How did we get here, who suggested to get and put the references to the
> OF node outside of the OF MDIO API?

It is not a suggestion. If it was a suggestion (like in a comment), it
would be a little bit better. Some got it right and some didn't.

The OF API will only return you a node with the refcount incremented.
You need to put it in somewhere after that. That will happen no matter
how you use the node and that's OK. The problem is when I pass that
reference to another function, I need to somehow know if it keeps a
reference to that node and not increments the refconf. If it does not
keep the reference, it is OK. If it keeps the reference and gets it,
it is also OK.

The answer "just read (all the multiple level and different) code
(paths)" is fated to fail. The put after registration in DSA core code
is just an example of how it did not work.

> > > If you want, you could make the OF MDIO API get() and put() the reference,
> > > instead of using something it doesn't fully own. But currently the code
> > > doesn't do that. Try to acknowledge what exists, first.
> >
> > What I saw in other drivers outside drivers/net is that one that
> > allocates the dev will get the node before assigning dev.of_node and
> > put it before freeing the device. The mdiobus case seems to be
> > different. I believe it would make the code more robust if we could
> > fix that inside OF MDIO API and not just document its behavior. It
> > will also not break existing uses as extra get/put's are OK.
> >
> > I believe we could add an unregister callback to mii_bus. It wouldn't
> > be too complex:
> >
> > From b5b059ea4491e9f745872220fb94d8105e2d7d43 Mon Sep 17 00:00:00 2001
> > From: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > Date: Tue, 12 Dec 2023 00:26:06 -0300
> > Subject: [PATCH] net: mdio: get/put device node during (un)registration
> >
> > __of_mdiobus_register() was storing the device node in dev.of_node
> > without increasing its refcount. It was implicitly delegating to the
> > caller to maintain the node allocated until mdiobus was unregistered.
> >
> > Now, the __of_mdiobus_register() will get the node before assigning it,
> > and of_mdiobus_unregister_callback() will be called at the end of
> > mdio_unregister().
> >
> > Drivers can now put the node just after the MDIO registration.
> >
> > Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
> > ---
> > drivers/net/mdio/of_mdio.c | 12 +++++++++++-
> > drivers/net/phy/mdio_bus.c |  3 +++
> > include/linux/phy.h        |  3 +++
> > 3 files changed, 17 insertions(+), 1 deletion(-)
>
> I don't mean to be rude, but I don't have the time to dig into this any
> further, sorry. If you are truly committed to better the phylib API,
> please bring it up with the phylib people instead. I literally only
> care about the thing that Alvin pointed out, which is that you made
> unjustified changes to a DSA driver.

Sure, phylib is still for netdev, right?

I'll redo this patch to avoid putting the node before unregistration.

> > If we don't fix that in OF MDIO API, we would need to fix
> > fe7324b932222 as well, moving the put to the dsa_switch_teardown().
>
> Oh, couldn't we straight-up revert that instead? :) The user_mii_bus
> is created by DSA for compatibility with non-OF. I cannot understand
> why you insist to attach an OF node to it.

Please, not before this patch series gets merged or you'll break
MDIO-connected Realtek DSA switches, at least the IRQ handling.
I'll send the revert myself afterwards.

> But otherwise, yes, it is the same situation: of_node_put(), called
> before unregistering an MDIO bus registered with of_mdiobus_register(),
> means that the full OF API on this MDIO bus may not work correctly.
> I don't know the exact conditions though. It might be marginal or even
> a bug that's impossible to trigger. I haven't tested anything.

OK. I'll not try to fix that but revert it as soon as possible without
breaking existing code. You need too much conditions to make it
trigger a bug:
1) use dynamic OF
2) no other code also keep a reference to that node
3) a call that actually reads the of_node from user_mii.dev

But, as you pointed out, OF and user_mii should not work together.

> In any case, while I encourage you to make OF node refcounting work in
> the way that you think is intuitive, I want to be clear about one thing,
> and that is that I'm not onboard with modifying phylib to make a non
> use-case in DSA work, aka OF-aware user_mii_bus (an oxymoron).

The change to MDIO code would not be a requirement for this patch
series. I'll deal with each front independently.

> I understand why a driver may want a ds->user_mii_bus. And I understand
> why a driver may want an MDIO bus with an of_node. What I don't understand
> is who might want both at the same time, and why.

That one I might be novice enough to answer :).

When you start to write a new driver, you read the docs to get a
general idea. However, as code moves faster than docs, you mainly rely
on code. So, you just choose a driver (or a couple of them) to inspire
you. You normally prefer a small driver because it is less code to
read and it might be just enough to get started. As long as it is
mainline, nothing indicates it should not be used as a reference.

I wasn't the one that wrote most of the Realtek DSA driver but I see
the same OF + user_mii_bus pattern in more than one driver. If you
want to stop spreading, as rewriting all affected drivers might not be
an option, a nice /* TODO: convert to user YXZ */ comment might do the
trick. An updated doc suggesting a driver to be used as an example
would also be nice.

The doc update you sent about the "user MDIO bus documentation"
telling us we should not use user_mii_bus when we describe the
internal MDIO in the device-tree made me more confused. But I'll
comment on that thread.

Regards,

Luiz

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-13  4:37               ` Luiz Angelo Daros de Luca
@ 2023-12-13 13:04                 ` Vladimir Oltean
  2023-12-16  4:26                   ` Luiz Angelo Daros de Luca
  0 siblings, 1 reply; 34+ messages in thread
From: Vladimir Oltean @ 2023-12-13 13:04 UTC (permalink / raw)
  To: Luiz Angelo Daros de Luca
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew, f.fainelli,
	davem, edumazet, kuba, pabeni, arinc.unal

On Wed, Dec 13, 2023 at 01:37:27AM -0300, Luiz Angelo Daros de Luca wrote:
> The answer "just read (all the multiple level and different) code
> (paths)" is fated to fail. The put after registration in DSA core code
> is just an example of how it did not work.

If you try to think critically about the changes you make, you'll get
better at it with time. Reading code is what we all do, really, and
making educated guesses about what we saw. It's error prone for everyone
involved, which is why we use review to confront what we all understand.

This is not only an encouragement, but also a subtle hint that you will
endlessly frustrate those who have to read more than you did, in order
to review your proposals, only for you to complain that you have to read
too much when making changes.

Anyway.

> > I don't mean to be rude, but I don't have the time to dig into this any
> > further, sorry. If you are truly committed to better the phylib API,
> > please bring it up with the phylib people instead. I literally only
> > care about the thing that Alvin pointed out, which is that you made
> > unjustified changes to a DSA driver.
> 
> Sure, phylib is still for netdev, right?

ETHERNET PHY LIBRARY
M:	Andrew Lunn <andrew@lunn.ch>
M:	Heiner Kallweit <hkallweit1@gmail.com>
R:	Russell King <linux@armlinux.org.uk>
L:	netdev@vger.kernel.org
S:	Maintained
F:	Documentation/ABI/testing/sysfs-class-net-phydev
F:	Documentation/devicetree/bindings/net/ethernet-phy.yaml
F:	Documentation/devicetree/bindings/net/mdio*
F:	Documentation/devicetree/bindings/net/qca,ar803x.yaml
F:	Documentation/networking/phy.rst
F:	drivers/net/mdio/
F:	drivers/net/mdio/acpi_mdio.c
F:	drivers/net/mdio/fwnode_mdio.c
F:	drivers/net/mdio/of_mdio.c
F:	drivers/net/pcs/
F:	drivers/net/phy/
F:	include/dt-bindings/net/qca-ar803x.h
F:	include/linux/*mdio*.h
F:	include/linux/linkmode.h
F:	include/linux/mdio/*.h
F:	include/linux/mii.h
F:	include/linux/of_net.h
F:	include/linux/phy.h
F:	include/linux/phy_fixed.h
F:	include/linux/phylib_stubs.h
F:	include/linux/platform_data/mdio-bcm-unimac.h
F:	include/linux/platform_data/mdio-gpio.h
F:	include/trace/events/mdio.h
F:	include/uapi/linux/mdio.h
F:	include/uapi/linux/mii.h
F:	net/core/of_net.c

> > Oh, couldn't we straight-up revert that instead? :) The user_mii_bus
> > is created by DSA for compatibility with non-OF. I cannot understand
> > why you insist to attach an OF node to it.
> 
> Please, not before this patch series gets merged or you'll break
> MDIO-connected Realtek DSA switches, at least the IRQ handling.
> I'll send the revert myself afterwards.
> 
> > But otherwise, yes, it is the same situation: of_node_put(), called
> > before unregistering an MDIO bus registered with of_mdiobus_register(),
> > means that the full OF API on this MDIO bus may not work correctly.
> > I don't know the exact conditions though. It might be marginal or even
> > a bug that's impossible to trigger. I haven't tested anything.
> 
> OK. I'll not try to fix that but revert it as soon as possible without
> breaking existing code.

Ok, I'm not saying "revert it NOW". But it would be good if you could
revert it as part of the realtek-common series, as a last patch
(provided that you've done your homework and nobody else relies on it).
Or at least not forget about it.

> > I understand why a driver may want a ds->user_mii_bus. And I understand
> > why a driver may want an MDIO bus with an of_node. What I don't understand
> > is who might want both at the same time, and why.
> 
> That one I might be novice enough to answer :).
> 
> When you start to write a new driver, you read the docs to get a
> general idea. However, as code moves faster than docs, you mainly rely
> on code. So, you just choose a driver (or a couple of them) to inspire
> you. You normally prefer a small driver because it is less code to
> read and it might be just enough to get started. As long as it is
> mainline, nothing indicates it should not be used as a reference.

And when you consider that DSA has better documentation than most
subsystems out there....

Would it blow your mind away if I told you that the documentation is
written based on the code? The same code from which you draw a lazy
conclusion.

You have perfectly laid out why the code is not the problem, and why the
documentation is not the solution. The problem is the unwillingness to
spend time to understand, but to want to push your changes nonetheless.
The problem is on your end. I'm sorry, it has to be said.

> I wasn't the one that wrote most of the Realtek DSA driver but I see
> the same OF + user_mii_bus pattern in more than one driver. If you
> want to stop spreading, as rewriting all affected drivers might not be
> an option, a nice /* TODO: convert to user YXZ */ comment might do the
> trick. An updated doc suggesting a driver to be used as an example
> would also be nice.

I don't have time, Luiz. I spent 1 and a half hours today replying
to just your emails, and one and a half hours yesterday. I have a job.

You've made me see that I'm wasting my time writing documentation for
people who want instant gratification instead. I don't know how to get
to them. I'll think about it some more.

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

* Re: [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration
  2023-12-13 13:04                 ` Vladimir Oltean
@ 2023-12-16  4:26                   ` Luiz Angelo Daros de Luca
  0 siblings, 0 replies; 34+ messages in thread
From: Luiz Angelo Daros de Luca @ 2023-12-16  4:26 UTC (permalink / raw)
  To: Vladimir Oltean
  Cc: Alvin Šipraga, netdev, linus.walleij, andrew, f.fainelli,
	davem, edumazet, kuba, pabeni, arinc.unal

> On Wed, Dec 13, 2023 at 01:37:27AM -0300, Luiz Angelo Daros de Luca wrote:
> > The answer "just read (all the multiple level and different) code
> > (paths)" is fated to fail. The put after registration in DSA core code
> > is just an example of how it did not work.
>
> If you try to think critically about the changes you make, you'll get
> better at it with time. Reading code is what we all do, really, and
> making educated guesses about what we saw. It's error prone for everyone
> involved, which is why we use review to confront what we all understand.

I'm not trying to blame anyone. We all make mistakes. However, when we
have the same mistake happening in different situations, maybe we are
only dealing with the consequences and not the cause.

> This is not only an encouragement, but also a subtle hint that you will
> endlessly frustrate those who have to read more than you did, in order
> to review your proposals, only for you to complain that you have to read
> too much when making changes.

Sorry if that's what my words said. It really wasn't my intention. I'm
not complaining about reading the code. It is actually a pleasure. But
I'll bother the MDIO guys on that matter :)

> Anyway.
>
> > > I don't mean to be rude, but I don't have the time to dig into this any
> > > further, sorry. If you are truly committed to better the phylib API,
> > > please bring it up with the phylib people instead. I literally only
> > > care about the thing that Alvin pointed out, which is that you made
> > > unjustified changes to a DSA driver.
> >
> > Sure, phylib is still for netdev, right?
>
> ETHERNET PHY LIBRARY
> M:      Andrew Lunn <andrew@lunn.ch>
> M:      Heiner Kallweit <hkallweit1@gmail.com>
> R:      Russell King <linux@armlinux.org.uk>
> L:      netdev@vger.kernel.org
> S:      Maintained
> F:      Documentation/ABI/testing/sysfs-class-net-phydev
> F:      Documentation/devicetree/bindings/net/ethernet-phy.yaml
> F:      Documentation/devicetree/bindings/net/mdio*
> F:      Documentation/devicetree/bindings/net/qca,ar803x.yaml
> F:      Documentation/networking/phy.rst
> F:      drivers/net/mdio/
> F:      drivers/net/mdio/acpi_mdio.c
> F:      drivers/net/mdio/fwnode_mdio.c
> F:      drivers/net/mdio/of_mdio.c
> F:      drivers/net/pcs/
> F:      drivers/net/phy/
> F:      include/dt-bindings/net/qca-ar803x.h
> F:      include/linux/*mdio*.h
> F:      include/linux/linkmode.h
> F:      include/linux/mdio/*.h
> F:      include/linux/mii.h
> F:      include/linux/of_net.h
> F:      include/linux/phy.h
> F:      include/linux/phy_fixed.h
> F:      include/linux/phylib_stubs.h
> F:      include/linux/platform_data/mdio-bcm-unimac.h
> F:      include/linux/platform_data/mdio-gpio.h
> F:      include/trace/events/mdio.h
> F:      include/uapi/linux/mdio.h
> F:      include/uapi/linux/mii.h
> F:      net/core/of_net.c
>
> > > Oh, couldn't we straight-up revert that instead? :) The user_mii_bus
> > > is created by DSA for compatibility with non-OF. I cannot understand
> > > why you insist to attach an OF node to it.
> >
> > Please, not before this patch series gets merged or you'll break
> > MDIO-connected Realtek DSA switches, at least the IRQ handling.
> > I'll send the revert myself afterwards.
> >
> > > But otherwise, yes, it is the same situation: of_node_put(), called
> > > before unregistering an MDIO bus registered with of_mdiobus_register(),
> > > means that the full OF API on this MDIO bus may not work correctly.
> > > I don't know the exact conditions though. It might be marginal or even
> > > a bug that's impossible to trigger. I haven't tested anything.
> >
> > OK. I'll not try to fix that but revert it as soon as possible without
> > breaking existing code.
>
> Ok, I'm not saying "revert it NOW". But it would be good if you could
> revert it as part of the realtek-common series, as a last patch
> (provided that you've done your homework and nobody else relies on it).
> Or at least not forget about it.

I'll add the revert patch. I believe I just need to pay attention to
those cases where phy_read/phy_write are included in ds_ops.

> > > I understand why a driver may want a ds->user_mii_bus. And I understand
> > > why a driver may want an MDIO bus with an of_node. What I don't understand
> > > is who might want both at the same time, and why.
> >
> > That one I might be novice enough to answer :).
> >
> > When you start to write a new driver, you read the docs to get a
> > general idea. However, as code moves faster than docs, you mainly rely
> > on code. So, you just choose a driver (or a couple of them) to inspire
> > you. You normally prefer a small driver because it is less code to
> > read and it might be just enough to get started. As long as it is
> > mainline, nothing indicates it should not be used as a reference.
>
> And when you consider that DSA has better documentation than most
> subsystems out there....
>
> Would it blow your mind away if I told you that the documentation is
> written based on the code? The same code from which you draw a lazy
> conclusion.
>
> You have perfectly laid out why the code is not the problem, and why the
> documentation is not the solution. The problem is the unwillingness to
> spend time to understand, but to want to push your changes nonetheless.
> The problem is on your end. I'm sorry, it has to be said.

Oh, I did spend a lot of time on it, hundreds from my free and sleep
time :). Sometimes you just cannot understand by yourself. And yes, I
do believe in most cases I'm wrong.

> > I wasn't the one that wrote most of the Realtek DSA driver but I see
> > the same OF + user_mii_bus pattern in more than one driver. If you
> > want to stop spreading, as rewriting all affected drivers might not be
> > an option, a nice /* TODO: convert to user YXZ */ comment might do the
> > trick. An updated doc suggesting a driver to be used as an example
> > would also be nice.
>
> I don't have time, Luiz. I spent 1 and a half hours today replying
> to just your emails, and one and a half hours yesterday. I have a job.

Vladimir, I cannot thank you enough. I probably wouldn't get it (and
maybe I still didn't) without your help.

> You've made me see that I'm wasting my time writing documentation for
> people who want instant gratification instead. I don't know how to get
> to them. I'll think about it some more.

I wouldn't say submitting patches to the kernel brings some kind of
gratification (except if you are a type of masochist). I'm just trying
to help.

Probably you are spending more time answering my emails than you
should. ML are great but their knowledge tends to fade away with time.
The answer to some topics I brought should be there, not here. Save
your time for reviewing the code.

I normally work a lot more than I should just to avoid the chance of
reworking on it. A comment in code like /* This behavior is
deprecated. Please see https://kernel.org/doc/xxx */ would both avoid
the code to be spread and alert maintainers that there is some work to
be done. We all have nicer things to do instead but it could save some
future headaches. My 2 cents.

Regards,

Luiz

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

end of thread, other threads:[~2023-12-16  4:26 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-08  4:41 [PATCH net-next 0/7] net: dsa: realtek: variants to drivers, interfaces to a common module Luiz Angelo Daros de Luca
2023-12-08  4:41 ` [PATCH net-next 1/7] net: dsa: realtek: drop cleanup from realtek_priv Luiz Angelo Daros de Luca
2023-12-08  9:49   ` Alvin Šipraga
2023-12-08  4:41 ` [PATCH net-next 2/7] net: dsa: realtek: put of node after MDIO registration Luiz Angelo Daros de Luca
2023-12-08  5:13   ` Luiz Angelo Daros de Luca
2023-12-08  9:49     ` Alvin Šipraga
2023-12-08 18:05       ` Luiz Angelo Daros de Luca
2023-12-11 17:11         ` Vladimir Oltean
2023-12-12  3:47           ` Luiz Angelo Daros de Luca
2023-12-12 21:58             ` Vladimir Oltean
2023-12-13  4:37               ` Luiz Angelo Daros de Luca
2023-12-13 13:04                 ` Vladimir Oltean
2023-12-16  4:26                   ` Luiz Angelo Daros de Luca
2023-12-08  4:41 ` [PATCH net-next 3/7] net: dsa: realtek: convert variants into a real driver Luiz Angelo Daros de Luca
2023-12-08 10:23   ` Alvin Šipraga
2023-12-08  4:41 ` [PATCH net-next 4/7] net: dsa: realtek: create realtek-common Luiz Angelo Daros de Luca
2023-12-08  5:01   ` Luiz Angelo Daros de Luca
2023-12-08 10:52   ` Alvin Šipraga
2023-12-11  5:02     ` Luiz Angelo Daros de Luca
2023-12-11  9:44       ` Alvin Šipraga
2023-12-08 14:02   ` Alvin Šipraga
2023-12-11  5:02     ` Luiz Angelo Daros de Luca
2023-12-11  9:24       ` Alvin Šipraga
2023-12-11 17:19         ` Vladimir Oltean
2023-12-08  4:41 ` [PATCH net-next 5/7] net: dsa: realtek: merge interface modules into common Luiz Angelo Daros de Luca
2023-12-08 10:57   ` Alvin Šipraga
2023-12-11  5:13     ` Luiz Angelo Daros de Luca
2023-12-11  9:25       ` Alvin Šipraga
2023-12-08  4:41 ` [PATCH net-next 6/7] net: dsa: realtek: migrate user_mii setup to common Luiz Angelo Daros de Luca
2023-12-08 11:05   ` Alvin Šipraga
2023-12-11  5:16     ` Luiz Angelo Daros de Luca
2023-12-08  4:41 ` [PATCH net-next 7/7] net: dsa: realtek: always use the realtek user mdio driver Luiz Angelo Daros de Luca
2023-12-08 11:06   ` Alvin Šipraga
2023-12-11  5:29     ` 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.