* [PATCH net-next 1/9] net: dsa: microchip: remove useless common cls_flower_{add/del} operations
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
2026-05-26 9:47 ` [PATCH net-next 2/9] net: dsa: microchip: remove VLAN operations for ksz8463 Bastien Curutchet
` (7 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
All the KSZ switches share a common implementation of the
cls_flower_{add/del} operations. These common implementations return
ksz9477-specific implementations for the KSZ9477 family and -EOPNOTSUPP
for the others. -EOPNOTSUPP is already returned by the DSA core when
the operation isn't implemented.
Remove the common implementations.
Directly link the ksz9477_cls_flower_{add/del}() to the KSZ9477 callback.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 6 -----
drivers/net/dsa/microchip/ksz9477.c | 4 +--
drivers/net/dsa/microchip/ksz_common.c | 42 --------------------------------
drivers/net/dsa/microchip/ksz_common.h | 4 ---
drivers/net/dsa/microchip/lan937x_main.c | 2 --
5 files changed, 2 insertions(+), 56 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index 0f84b2e7d25d..db08874eb025 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2462,8 +2462,6 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .cls_flower_add = ksz_cls_flower_add,
- .cls_flower_del = ksz_cls_flower_del,
.port_setup_tc = ksz_setup_tc,
.support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
@@ -2522,8 +2520,6 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .cls_flower_add = ksz_cls_flower_add,
- .cls_flower_del = ksz_cls_flower_del,
.port_setup_tc = ksz_setup_tc,
.support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
@@ -2582,8 +2578,6 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .cls_flower_add = ksz_cls_flower_add,
- .cls_flower_del = ksz_cls_flower_del,
.port_setup_tc = ksz_setup_tc,
.support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index c1395322e54b..c18bad08a508 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1996,8 +1996,8 @@ const struct dsa_switch_ops ksz9477_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .cls_flower_add = ksz_cls_flower_add,
- .cls_flower_del = ksz_cls_flower_del,
+ .cls_flower_add = ksz9477_cls_flower_add,
+ .cls_flower_del = ksz9477_cls_flower_del,
.port_setup_tc = ksz_setup_tc,
.support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 57c8abfe0147..81d3ec88e436 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3373,48 +3373,6 @@ static int ksz_switch_detect(struct ksz_device *dev)
return 0;
}
-int ksz_cls_flower_add(struct dsa_switch *ds, int port,
- struct flow_cls_offload *cls, bool ingress)
-{
- struct ksz_device *dev = ds->priv;
-
- switch (dev->chip_id) {
- case KSZ8563_CHIP_ID:
- case KSZ8567_CHIP_ID:
- case KSZ9477_CHIP_ID:
- case KSZ9563_CHIP_ID:
- case KSZ9567_CHIP_ID:
- case KSZ9893_CHIP_ID:
- case KSZ9896_CHIP_ID:
- case KSZ9897_CHIP_ID:
- case LAN9646_CHIP_ID:
- return ksz9477_cls_flower_add(ds, port, cls, ingress);
- }
-
- return -EOPNOTSUPP;
-}
-
-int ksz_cls_flower_del(struct dsa_switch *ds, int port,
- struct flow_cls_offload *cls, bool ingress)
-{
- struct ksz_device *dev = ds->priv;
-
- switch (dev->chip_id) {
- case KSZ8563_CHIP_ID:
- case KSZ8567_CHIP_ID:
- case KSZ9477_CHIP_ID:
- case KSZ9563_CHIP_ID:
- case KSZ9567_CHIP_ID:
- case KSZ9893_CHIP_ID:
- case KSZ9896_CHIP_ID:
- case KSZ9897_CHIP_ID:
- case LAN9646_CHIP_ID:
- return ksz9477_cls_flower_del(ds, port, cls, ingress);
- }
-
- return -EOPNOTSUPP;
-}
-
/* Bandwidth is calculated by idle slope/transmission speed. Then the Bandwidth
* is converted to Hex-decimal using the successive multiplication method. On
* every step, integer part is taken and decimal part is carry forwarded.
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index b67038cf1bd0..da62c1658aa8 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -483,10 +483,6 @@ bool ksz_support_eee(struct dsa_switch *ds, int port);
int ksz_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e);
-int ksz_cls_flower_add(struct dsa_switch *ds, int port,
- struct flow_cls_offload *cls, bool ingress);
-int ksz_cls_flower_del(struct dsa_switch *ds, int port,
- struct flow_cls_offload *cls, bool ingress);
int ksz_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type, void *type_data);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 536153886f7b..731737fd58d1 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -890,8 +890,6 @@ const struct dsa_switch_ops lan937x_switch_ops = {
.port_hwtstamp_set = ksz_hwtstamp_set,
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
- .cls_flower_add = ksz_cls_flower_add,
- .cls_flower_del = ksz_cls_flower_del,
.port_setup_tc = ksz_setup_tc,
.support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH net-next 2/9] net: dsa: microchip: remove VLAN operations for ksz8463
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
2026-05-26 9:47 ` [PATCH net-next 1/9] net: dsa: microchip: remove useless common cls_flower_{add/del} operations Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet
2026-05-26 9:47 ` [PATCH net-next 3/9] net: dsa: microchip: implement get_phy_flags only if needed Bastien Curutchet (Schneider Electric)
` (6 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric),
Vladimir Oltean
From: Vladimir Oltean <vladimir.oltean@nxp.com>
KSZ8463 uses the common KSZ8 implementation for its VLAN operations.
This implementation returns -ENOTSUPP for the KSZ8463 case, which is
pointless.
Remove the VLAN operations from the ksz8463_switch_ops so the core can
directly return -ENOTSUPP.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index db08874eb025..93e0b3f60448 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -1477,7 +1477,7 @@ static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
{
struct ksz_device *dev = ds->priv;
- if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
+ if (ksz_is_ksz88x3(dev))
return -ENOTSUPP;
/* Discard packets with VID not enabled on the switch */
@@ -1514,7 +1514,7 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
u16 data, new_pvid = 0;
u8 fid, member, valid;
- if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
+ if (ksz_is_ksz88x3(dev))
return -ENOTSUPP;
/* If a VLAN is added with untagged flag different from the
@@ -1584,7 +1584,7 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
u8 fid, member, valid;
u16 data, pvid;
- if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev))
+ if (ksz_is_ksz88x3(dev))
return -ENOTSUPP;
ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid);
@@ -2439,9 +2439,6 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
.port_pre_bridge_flags = ksz_port_pre_bridge_flags,
.port_bridge_flags = ksz_port_bridge_flags,
.port_fast_age = ksz8_flush_dyn_mac_table,
- .port_vlan_filtering = ksz8_port_vlan_filtering,
- .port_vlan_add = ksz8_port_vlan_add,
- .port_vlan_del = ksz8_port_vlan_del,
.port_fdb_dump = ksz8_fdb_dump,
.port_fdb_add = ksz8_fdb_add,
.port_fdb_del = ksz8_fdb_del,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH net-next 3/9] net: dsa: microchip: implement get_phy_flags only if needed
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
2026-05-26 9:47 ` [PATCH net-next 1/9] net: dsa: microchip: remove useless common cls_flower_{add/del} operations Bastien Curutchet (Schneider Electric)
2026-05-26 9:47 ` [PATCH net-next 2/9] net: dsa: microchip: remove VLAN operations for ksz8463 Bastien Curutchet
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
2026-05-26 9:47 ` [PATCH net-next 4/9] net: dsa: microchip: remove setup_rgmii_delay() KSZ operation Bastien Curutchet (Schneider Electric)
` (5 subsequent siblings)
8 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
The common ksz_get_phy_flags() is used by all the switches to implement
the optional .get_phy_flags DSA operation. It always returns 0 except
for KSZ88X3 switches where an errata has to be handled.
Make ksz_get_phy_flags() ksz88xx-specific.
Remove the get_phy_flags implementation for the switches that don't need
it.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 22 +++++++++++++++++++---
drivers/net/dsa/microchip/ksz9477.c | 1 -
drivers/net/dsa/microchip/ksz_common.c | 18 ------------------
drivers/net/dsa/microchip/ksz_common.h | 2 --
drivers/net/dsa/microchip/lan937x_main.c | 1 -
5 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index 93e0b3f60448..98cf7239057d 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2272,6 +2272,24 @@ static int ksz8463_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val
return 0;
}
+static u32 ksz88xx_get_phy_flags(struct dsa_switch *ds, int port)
+{
+ struct ksz_device *dev = ds->priv;
+
+ switch (dev->chip_id) {
+ case KSZ88X3_CHIP_ID:
+ /* Silicon Errata Sheet (DS80000830A):
+ * Port 1 does not work with LinkMD Cable-Testing.
+ * Port 1 does not respond to received PAUSE control frames.
+ */
+ if (!port)
+ return MICREL_KSZ8_P1_ERRATA;
+ break;
+ }
+
+ return 0;
+}
+
static int ksz8_switch_init(struct ksz_device *dev)
{
dev->cpu_port = fls(dev->info->cpu_ports) - 1;
@@ -2419,7 +2437,6 @@ const struct ksz_dev_ops ksz88xx_dev_ops = {
const struct dsa_switch_ops ksz8463_switch_ops = {
.get_tag_protocol = ksz8463_get_tag_protocol,
.connect_tag_protocol = ksz8463_connect_tag_protocol,
- .get_phy_flags = ksz_get_phy_flags,
.setup = ksz8_setup,
.teardown = ksz_teardown,
.phy_read = ksz8463_phy_read16,
@@ -2474,7 +2491,6 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
const struct dsa_switch_ops ksz87xx_switch_ops = {
.get_tag_protocol = ksz87xx_get_tag_protocol,
.connect_tag_protocol = ksz87xx_connect_tag_protocol,
- .get_phy_flags = ksz_get_phy_flags,
.setup = ksz8_setup,
.teardown = ksz_teardown,
.phy_read = ksz8_phy_read16,
@@ -2532,7 +2548,7 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
const struct dsa_switch_ops ksz88xx_switch_ops = {
.get_tag_protocol = ksz88xx_get_tag_protocol,
.connect_tag_protocol = ksz88xx_connect_tag_protocol,
- .get_phy_flags = ksz_get_phy_flags,
+ .get_phy_flags = ksz88xx_get_phy_flags,
.setup = ksz8_setup,
.teardown = ksz_teardown,
.phy_read = ksz8_phy_read16,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index c18bad08a508..a39541d29ad5 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1952,7 +1952,6 @@ const struct ksz_dev_ops ksz9477_dev_ops = {
const struct dsa_switch_ops ksz9477_switch_ops = {
.get_tag_protocol = ksz9477_get_tag_protocol,
.connect_tag_protocol = ksz9477_connect_tag_protocol,
- .get_phy_flags = ksz_get_phy_flags,
.setup = ksz9477_setup,
.teardown = ksz_teardown,
.phy_read = ksz9477_phy_read16,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 81d3ec88e436..5fb151fbf4f3 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2838,24 +2838,6 @@ void ksz_init_mib_timer(struct ksz_device *dev)
}
}
-u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
-{
- struct ksz_device *dev = ds->priv;
-
- switch (dev->chip_id) {
- case KSZ88X3_CHIP_ID:
- /* Silicon Errata Sheet (DS80000830A):
- * Port 1 does not work with LinkMD Cable-Testing.
- * Port 1 does not respond to received PAUSE control frames.
- */
- if (!port)
- return MICREL_KSZ8_P1_ERRATA;
- break;
- }
-
- return 0;
-}
-
void ksz_phylink_mac_link_down(struct phylink_config *config,
unsigned int mode,
phy_interface_t interface)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index da62c1658aa8..804912fdd2db 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -440,8 +440,6 @@ void ksz_switch_macaddr_put(struct dsa_switch *ds);
void ksz_switch_shutdown(struct ksz_device *dev);
int ksz_handle_wake_reason(struct ksz_device *dev, int port);
-u32 ksz_get_phy_flags(struct dsa_switch *ds, int port);
-
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *buf);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 731737fd58d1..57e289637193 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -846,7 +846,6 @@ const struct ksz_dev_ops lan937x_dev_ops = {
const struct dsa_switch_ops lan937x_switch_ops = {
.get_tag_protocol = lan937x_get_tag_protocol,
.connect_tag_protocol = lan937x_connect_tag_protocol,
- .get_phy_flags = ksz_get_phy_flags,
.setup = lan937x_setup,
.teardown = ksz_teardown,
.phy_read = lan937x_phy_read16,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH net-next 4/9] net: dsa: microchip: remove setup_rgmii_delay() KSZ operation
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
` (2 preceding siblings ...)
2026-05-26 9:47 ` [PATCH net-next 3/9] net: dsa: microchip: implement get_phy_flags only if needed Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
2026-06-01 8:49 ` Paolo Abeni
2026-05-26 9:47 ` [PATCH net-next 5/9] net: dsa: microchip: implement .support_eee() only if needed Bastien Curutchet (Schneider Electric)
` (4 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
setup_rgmii_delay() operation is only used once during the common phylink
MAC configuration. Only the lan937x switch implements this
setup_rgmii_delay().
Remove the setup_rgmii_delay operation from ksz_dev_ops.
Implement a lan937x-specific phylink MAC configuration that does this
RGMII delay setup.
Export ksz_set_xmii since it's needed by the lan937x implementation.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_common.c | 6 +-----
drivers/net/dsa/microchip/ksz_common.h | 2 +-
drivers/net/dsa/microchip/lan937x_main.c | 29 +++++++++++++++++++++++++++--
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 5fb151fbf4f3..d6511fcebcf2 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3127,8 +3127,7 @@ int ksz_set_mac_eee(struct dsa_switch *ds, int port,
return 0;
}
-static void ksz_set_xmii(struct ksz_device *dev, int port,
- phy_interface_t interface)
+void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface)
{
const u8 *bitval = dev->info->xmii_ctrl1;
struct ksz_port *p = &dev->ports[port];
@@ -3233,9 +3232,6 @@ void ksz_phylink_mac_config(struct phylink_config *config,
}
ksz_set_xmii(dev, port, state->interface);
-
- if (dev->dev_ops->setup_rgmii_delay)
- dev->dev_ops->setup_rgmii_delay(dev, port);
}
bool ksz_get_gbit(struct ksz_device *dev, int port)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 804912fdd2db..ab08c98ed257 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -410,7 +410,6 @@ struct ksz_dev_ops {
u8 data);
void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
void (*port_init_cnt)(struct ksz_device *dev, int port);
- void (*setup_rgmii_delay)(struct ksz_device *dev, int port);
int (*tc_cbs_set_cinc)(struct ksz_device *dev, int port, u32 val);
int (*init)(struct ksz_device *dev);
};
@@ -468,6 +467,7 @@ void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config);
int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
u32 timer, bool tx_clock_stop);
+void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface);
void ksz_phylink_mac_config(struct phylink_config *config,
unsigned int mode,
const struct phylink_link_state *state);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 57e289637193..f8f220242f7a 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -643,6 +643,32 @@ static void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port)
}
}
+static void lan937x_phylink_mac_config(struct phylink_config *config,
+ unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct dsa_port *dp = dsa_phylink_to_port(config);
+ struct ksz_device *dev = dp->ds->priv;
+ int port = dp->index;
+
+ /* Internal PHYs */
+ if (dev->info->internal_phy[port])
+ return;
+
+ /* No need to configure XMII control register when using SGMII. */
+ if (ksz_is_sgmii_port(dev, port))
+ return;
+
+ if (phylink_autoneg_inband(mode)) {
+ dev_err(dev->dev, "In-band AN not supported!\n");
+ return;
+ }
+
+ ksz_set_xmii(dev, port, state->interface);
+
+ lan937x_setup_rgmii_delay(dev, port);
+}
+
static int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
{
return ksz_pwrite32(dev, port, REG_PORT_MTI_CREDIT_INCREMENT, val);
@@ -821,7 +847,7 @@ static int lan937x_connect_tag_protocol(struct dsa_switch *ds,
}
const struct phylink_mac_ops lan937x_phylink_mac_ops = {
- .mac_config = ksz_phylink_mac_config,
+ .mac_config = lan937x_phylink_mac_config,
.mac_link_down = ksz_phylink_mac_link_down,
.mac_link_up = ksz9477_phylink_mac_link_up,
.mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
@@ -838,7 +864,6 @@ const struct ksz_dev_ops lan937x_dev_ops = {
.r_mib_stat64 = ksz_r_mib_stats64,
.freeze_mib = ksz9477_freeze_mib,
.port_init_cnt = ksz9477_port_init_cnt,
- .setup_rgmii_delay = lan937x_setup_rgmii_delay,
.tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc,
.init = lan937x_switch_init,
};
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 4/9] net: dsa: microchip: remove setup_rgmii_delay() KSZ operation
2026-05-26 9:47 ` [PATCH net-next 4/9] net: dsa: microchip: remove setup_rgmii_delay() KSZ operation Bastien Curutchet (Schneider Electric)
@ 2026-06-01 8:49 ` Paolo Abeni
2026-06-02 12:15 ` Bastien Curutchet
0 siblings, 1 reply; 19+ messages in thread
From: Paolo Abeni @ 2026-06-01 8:49 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric),
Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
> setup_rgmii_delay() operation is only used once during the common phylink
> MAC configuration. Only the lan937x switch implements this
> setup_rgmii_delay().
>
> Remove the setup_rgmii_delay operation from ksz_dev_ops.
> Implement a lan937x-specific phylink MAC configuration that does this
> RGMII delay setup.
> Export ksz_set_xmii since it's needed by the lan937x implementation.
>
> Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
> ---
> drivers/net/dsa/microchip/ksz_common.c | 6 +-----
> drivers/net/dsa/microchip/ksz_common.h | 2 +-
> drivers/net/dsa/microchip/lan937x_main.c | 29 +++++++++++++++++++++++++++--
> 3 files changed, 29 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
> index 5fb151fbf4f3..d6511fcebcf2 100644
> --- a/drivers/net/dsa/microchip/ksz_common.c
> +++ b/drivers/net/dsa/microchip/ksz_common.c
> @@ -3127,8 +3127,7 @@ int ksz_set_mac_eee(struct dsa_switch *ds, int port,
> return 0;
> }
>
> -static void ksz_set_xmii(struct ksz_device *dev, int port,
> - phy_interface_t interface)
> +void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface)
> {
> const u8 *bitval = dev->info->xmii_ctrl1;
> struct ksz_port *p = &dev->ports[port];
> @@ -3233,9 +3232,6 @@ void ksz_phylink_mac_config(struct phylink_config *config,
> }
>
> ksz_set_xmii(dev, port, state->interface);
> -
> - if (dev->dev_ops->setup_rgmii_delay)
> - dev->dev_ops->setup_rgmii_delay(dev, port);
> }
>
> bool ksz_get_gbit(struct ksz_device *dev, int port)
> diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
> index 804912fdd2db..ab08c98ed257 100644
> --- a/drivers/net/dsa/microchip/ksz_common.h
> +++ b/drivers/net/dsa/microchip/ksz_common.h
> @@ -410,7 +410,6 @@ struct ksz_dev_ops {
> u8 data);
> void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
> void (*port_init_cnt)(struct ksz_device *dev, int port);
> - void (*setup_rgmii_delay)(struct ksz_device *dev, int port);
> int (*tc_cbs_set_cinc)(struct ksz_device *dev, int port, u32 val);
> int (*init)(struct ksz_device *dev);
> };
> @@ -468,6 +467,7 @@ void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
> void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config);
> int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
> u32 timer, bool tx_clock_stop);
> +void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface);
> void ksz_phylink_mac_config(struct phylink_config *config,
> unsigned int mode,
> const struct phylink_link_state *state);
> diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
> index 57e289637193..f8f220242f7a 100644
> --- a/drivers/net/dsa/microchip/lan937x_main.c
> +++ b/drivers/net/dsa/microchip/lan937x_main.c
> @@ -643,6 +643,32 @@ static void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port)
> }
> }
>
> +static void lan937x_phylink_mac_config(struct phylink_config *config,
> + unsigned int mode,
> + const struct phylink_link_state *state)
> +{
> + struct dsa_port *dp = dsa_phylink_to_port(config);
> + struct ksz_device *dev = dp->ds->priv;
> + int port = dp->index;
> +
> + /* Internal PHYs */
> + if (dev->info->internal_phy[port])
> + return;
> +
> + /* No need to configure XMII control register when using SGMII. */
> + if (ksz_is_sgmii_port(dev, port))
> + return;
> +
> + if (phylink_autoneg_inband(mode)) {
> + dev_err(dev->dev, "In-band AN not supported!\n");
> + return;
> + }
> +
> + ksz_set_xmii(dev, port, state->interface);
> +
> + lan937x_setup_rgmii_delay(dev, port);
I think you can avoid some code duplication with something alike the
following:
- factor out of ksz_phylink_mac_config() a __ksz_phylink_mac_config(),
helper, with the latter doing all the work and returning true when
actually calling ksz_set_xmii()
- implement lan937x_phylink_mac_config() on top of
__ksz_phylink_mac_config():
if (__ksz_phylink_mac_config())
lan937x_setup_rgmii_delay(dev, port);
/P
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 4/9] net: dsa: microchip: remove setup_rgmii_delay() KSZ operation
2026-06-01 8:49 ` Paolo Abeni
@ 2026-06-02 12:15 ` Bastien Curutchet
0 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet @ 2026-06-02 12:15 UTC (permalink / raw)
To: Paolo Abeni, Woojung Huh, UNGLinuxDriver, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
Hi Paolo,
On 6/1/26 10:49 AM, Paolo Abeni wrote:
> On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
>> setup_rgmii_delay() operation is only used once during the common phylink
>> MAC configuration. Only the lan937x switch implements this
>> setup_rgmii_delay().
>>
>> Remove the setup_rgmii_delay operation from ksz_dev_ops.
>> Implement a lan937x-specific phylink MAC configuration that does this
>> RGMII delay setup.
>> Export ksz_set_xmii since it's needed by the lan937x implementation.
>>
>> Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
>> ---
>> drivers/net/dsa/microchip/ksz_common.c | 6 +-----
>> drivers/net/dsa/microchip/ksz_common.h | 2 +-
>> drivers/net/dsa/microchip/lan937x_main.c | 29 +++++++++++++++++++++++++++--
>> 3 files changed, 29 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
>> index 5fb151fbf4f3..d6511fcebcf2 100644
>> --- a/drivers/net/dsa/microchip/ksz_common.c
>> +++ b/drivers/net/dsa/microchip/ksz_common.c
>> @@ -3127,8 +3127,7 @@ int ksz_set_mac_eee(struct dsa_switch *ds, int port,
>> return 0;
>> }
>>
>> -static void ksz_set_xmii(struct ksz_device *dev, int port,
>> - phy_interface_t interface)
>> +void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface)
>> {
>> const u8 *bitval = dev->info->xmii_ctrl1;
>> struct ksz_port *p = &dev->ports[port];
>> @@ -3233,9 +3232,6 @@ void ksz_phylink_mac_config(struct phylink_config *config,
>> }
>>
>> ksz_set_xmii(dev, port, state->interface);
>> -
>> - if (dev->dev_ops->setup_rgmii_delay)
>> - dev->dev_ops->setup_rgmii_delay(dev, port);
>> }
>>
>> bool ksz_get_gbit(struct ksz_device *dev, int port)
>> diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
>> index 804912fdd2db..ab08c98ed257 100644
>> --- a/drivers/net/dsa/microchip/ksz_common.h
>> +++ b/drivers/net/dsa/microchip/ksz_common.h
>> @@ -410,7 +410,6 @@ struct ksz_dev_ops {
>> u8 data);
>> void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
>> void (*port_init_cnt)(struct ksz_device *dev, int port);
>> - void (*setup_rgmii_delay)(struct ksz_device *dev, int port);
>> int (*tc_cbs_set_cinc)(struct ksz_device *dev, int port, u32 val);
>> int (*init)(struct ksz_device *dev);
>> };
>> @@ -468,6 +467,7 @@ void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
>> void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config);
>> int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
>> u32 timer, bool tx_clock_stop);
>> +void ksz_set_xmii(struct ksz_device *dev, int port, phy_interface_t interface);
>> void ksz_phylink_mac_config(struct phylink_config *config,
>> unsigned int mode,
>> const struct phylink_link_state *state);
>> diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
>> index 57e289637193..f8f220242f7a 100644
>> --- a/drivers/net/dsa/microchip/lan937x_main.c
>> +++ b/drivers/net/dsa/microchip/lan937x_main.c
>> @@ -643,6 +643,32 @@ static void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port)
>> }
>> }
>>
>> +static void lan937x_phylink_mac_config(struct phylink_config *config,
>> + unsigned int mode,
>> + const struct phylink_link_state *state)
>> +{
>> + struct dsa_port *dp = dsa_phylink_to_port(config);
>> + struct ksz_device *dev = dp->ds->priv;
>> + int port = dp->index;
>> +
>> + /* Internal PHYs */
>> + if (dev->info->internal_phy[port])
>> + return;
>> +
>> + /* No need to configure XMII control register when using SGMII. */
>> + if (ksz_is_sgmii_port(dev, port))
>> + return;
>> +
>> + if (phylink_autoneg_inband(mode)) {
>> + dev_err(dev->dev, "In-band AN not supported!\n");
>> + return;
>> + }
>> +
>> + ksz_set_xmii(dev, port, state->interface);
>> +
>> + lan937x_setup_rgmii_delay(dev, port);
>
> I think you can avoid some code duplication with something alike the
> following:
>
> - factor out of ksz_phylink_mac_config() a __ksz_phylink_mac_config(),
> helper, with the latter doing all the work and returning true when
> actually calling ksz_set_xmii()
>
> - implement lan937x_phylink_mac_config() on top of
> __ksz_phylink_mac_config():
>
> if (__ksz_phylink_mac_config())
> lan937x_setup_rgmii_delay(dev, port);
>
Indeed, I'll do it in next iteration, thank you.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next 5/9] net: dsa: microchip: implement .support_eee() only if needed
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
` (3 preceding siblings ...)
2026-05-26 9:47 ` [PATCH net-next 4/9] net: dsa: microchip: remove setup_rgmii_delay() KSZ operation Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
2026-06-01 8:55 ` Paolo Abeni
2026-05-26 9:47 ` [PATCH net-next 6/9] net: dsa: microchip: implement .{get/set}_wol " Bastien Curutchet (Schneider Electric)
` (3 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
The .support_eee() operation is optional. Yet, it is implemented by the
KSZ switches through a common functon that reports false for every chip
except for KSZ8563, KSZ9563 and KSZ9893 from the KSZ9477 family.
Remove the implementation from the switches that don't support EEE.
Implement instead a ksz9477-specific suppor_eee for these three supported
switches.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 3 --
drivers/net/dsa/microchip/ksz9477.c | 50 +++++++++++++++++++++++++++-
drivers/net/dsa/microchip/ksz_common.c | 57 --------------------------------
drivers/net/dsa/microchip/ksz_common.h | 1 -
drivers/net/dsa/microchip/lan937x_main.c | 1 -
5 files changed, 49 insertions(+), 63 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index 98cf7239057d..f297aa03f42a 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2477,7 +2477,6 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
.port_setup_tc = ksz_setup_tc,
- .support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
@@ -2534,7 +2533,6 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
.port_setup_tc = ksz_setup_tc,
- .support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
@@ -2592,7 +2590,6 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
.port_setup_tc = ksz_setup_tc,
- .support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index a39541d29ad5..e0b3724a7558 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1909,6 +1909,54 @@ void ksz9477_phylink_mac_link_up(struct phylink_config *config,
ksz9477_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
}
+/**
+ * ksz9477_support_eee - Determine Energy Efficient Ethernet (EEE) support for a
+ * port
+ * @ds: Pointer to the DSA switch structure
+ * @port: Port number to check
+ *
+ * This function also documents devices where EEE was initially advertised but
+ * later withdrawn due to reliability issues, as described in official errata
+ * documents. These devices are explicitly listed to record known limitations,
+ * even if there is no technical necessity for runtime checks.
+ *
+ * Returns: true if the internal PHY on the given port supports fully
+ * operational EEE, false otherwise.
+ */
+static bool ksz9477_support_eee(struct dsa_switch *ds, int port)
+{
+ struct ksz_device *dev = ds->priv;
+
+ if (!dev->info->internal_phy[port])
+ return false;
+
+ switch (dev->chip_id) {
+ case KSZ8563_CHIP_ID:
+ case KSZ9563_CHIP_ID:
+ case KSZ9893_CHIP_ID:
+ return true;
+ default:
+ /* KSZ8567R Errata DS80000752C Module 4 */
+ /* KSZ9477S Errata DS80000754A Module 4 */
+ /* KSZ9567S Errata DS80000756A Module 4 */
+ /* KSZ9896C Errata DS80000757A Module 3 */
+ /* KSZ9897R Errata DS80000758C Module 4 */
+ /* Energy Efficient Ethernet (EEE) feature select must be
+ * manually disabled
+ * The EEE feature is enabled by default, but it is not fully
+ * operational. It must be manually disabled through register
+ * controls. If not disabled, the PHY ports can auto-negotiate
+ * to enable EEE, and this feature can cause link drops when
+ * linked to another device supporting EEE.
+ *
+ * The same item appears in the errata for all switches above.
+ */
+ break;
+ }
+
+ return false;
+}
+
static struct phylink_pcs *
ksz9477_phylink_mac_select_pcs(struct phylink_config *config,
phy_interface_t interface)
@@ -1998,7 +2046,7 @@ const struct dsa_switch_ops ksz9477_switch_ops = {
.cls_flower_add = ksz9477_cls_flower_add,
.cls_flower_del = ksz9477_cls_flower_del,
.port_setup_tc = ksz_setup_tc,
- .support_eee = ksz_support_eee,
+ .support_eee = ksz9477_support_eee,
.set_mac_eee = ksz_set_mac_eee,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index d6511fcebcf2..475886b8c255 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3052,63 +3052,6 @@ int ksz_max_mtu(struct dsa_switch *ds, int port)
return -EOPNOTSUPP;
}
-/**
- * ksz_support_eee - Determine Energy Efficient Ethernet (EEE) support for a
- * port
- * @ds: Pointer to the DSA switch structure
- * @port: Port number to check
- *
- * This function also documents devices where EEE was initially advertised but
- * later withdrawn due to reliability issues, as described in official errata
- * documents. These devices are explicitly listed to record known limitations,
- * even if there is no technical necessity for runtime checks.
- *
- * Returns: true if the internal PHY on the given port supports fully
- * operational EEE, false otherwise.
- */
-bool ksz_support_eee(struct dsa_switch *ds, int port)
-{
- struct ksz_device *dev = ds->priv;
-
- if (!dev->info->internal_phy[port])
- return false;
-
- switch (dev->chip_id) {
- case KSZ8563_CHIP_ID:
- case KSZ9563_CHIP_ID:
- case KSZ9893_CHIP_ID:
- return true;
- case KSZ8567_CHIP_ID:
- /* KSZ8567R Errata DS80000752C Module 4 */
- case KSZ8765_CHIP_ID:
- case KSZ8794_CHIP_ID:
- case KSZ8795_CHIP_ID:
- /* KSZ879x/KSZ877x/KSZ876x Errata DS80000687C Module 2 */
- case KSZ9477_CHIP_ID:
- /* KSZ9477S Errata DS80000754A Module 4 */
- case KSZ9567_CHIP_ID:
- /* KSZ9567S Errata DS80000756A Module 4 */
- case KSZ9896_CHIP_ID:
- /* KSZ9896C Errata DS80000757A Module 3 */
- case KSZ9897_CHIP_ID:
- case LAN9646_CHIP_ID:
- /* KSZ9897R Errata DS80000758C Module 4 */
- /* Energy Efficient Ethernet (EEE) feature select must be
- * manually disabled
- * The EEE feature is enabled by default, but it is not fully
- * operational. It must be manually disabled through register
- * controls. If not disabled, the PHY ports can auto-negotiate
- * to enable EEE, and this feature can cause link drops when
- * linked to another device supporting EEE.
- *
- * The same item appears in the errata for all switches above.
- */
- break;
- }
-
- return false;
-}
-
int ksz_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e)
{
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index ab08c98ed257..33cb2c44004b 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -477,7 +477,6 @@ void ksz_phylink_mac_link_down(struct phylink_config *config,
int ksz_max_mtu(struct dsa_switch *ds, int port);
-bool ksz_support_eee(struct dsa_switch *ds, int port);
int ksz_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index f8f220242f7a..4cbbcf7993c9 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -915,7 +915,6 @@ const struct dsa_switch_ops lan937x_switch_ops = {
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
.port_setup_tc = ksz_setup_tc,
- .support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 5/9] net: dsa: microchip: implement .support_eee() only if needed
2026-05-26 9:47 ` [PATCH net-next 5/9] net: dsa: microchip: implement .support_eee() only if needed Bastien Curutchet (Schneider Electric)
@ 2026-06-01 8:55 ` Paolo Abeni
2026-06-02 12:21 ` Bastien Curutchet
0 siblings, 1 reply; 19+ messages in thread
From: Paolo Abeni @ 2026-06-01 8:55 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric),
Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
> diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
> index a39541d29ad5..e0b3724a7558 100644
> --- a/drivers/net/dsa/microchip/ksz9477.c
> +++ b/drivers/net/dsa/microchip/ksz9477.c
> @@ -1909,6 +1909,54 @@ void ksz9477_phylink_mac_link_up(struct phylink_config *config,
> ksz9477_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
> }
>
> +/**
> + * ksz9477_support_eee - Determine Energy Efficient Ethernet (EEE) support for a
> + * port
> + * @ds: Pointer to the DSA switch structure
> + * @port: Port number to check
> + *
> + * This function also documents devices where EEE was initially advertised but
> + * later withdrawn due to reliability issues, as described in official errata
> + * documents. These devices are explicitly listed to record known limitations,
> + * even if there is no technical necessity for runtime checks.
> + *
> + * Returns: true if the internal PHY on the given port supports fully
> + * operational EEE, false otherwise.
> + */
> +static bool ksz9477_support_eee(struct dsa_switch *ds, int port)
> +{
> + struct ksz_device *dev = ds->priv;
> +
> + if (!dev->info->internal_phy[port])
> + return false;
> +
> + switch (dev->chip_id) {
> + case KSZ8563_CHIP_ID:
> + case KSZ9563_CHIP_ID:
> + case KSZ9893_CHIP_ID:
> + return true;
> + default:
> + /* KSZ8567R Errata DS80000752C Module 4 */
> + /* KSZ9477S Errata DS80000754A Module 4 */
> + /* KSZ9567S Errata DS80000756A Module 4 */
> + /* KSZ9896C Errata DS80000757A Module 3 */
> + /* KSZ9897R Errata DS80000758C Module 4 */
Sashiko noted that errata:
/* KSZ879x/KSZ877x/KSZ876x Errata DS80000687C Module 2 */
has been lost above.
> diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
> index f8f220242f7a..4cbbcf7993c9 100644
> --- a/drivers/net/dsa/microchip/lan937x_main.c
> +++ b/drivers/net/dsa/microchip/lan937x_main.c
> @@ -915,7 +915,6 @@ const struct dsa_switch_ops lan937x_switch_ops = {
> .port_txtstamp = ksz_port_txtstamp,
> .port_rxtstamp = ksz_port_rxtstamp,
> .port_setup_tc = ksz_setup_tc,
> - .support_eee = ksz_support_eee,
> .set_mac_eee = ksz_set_mac_eee,
Sashiko noted that `set_mac_eee` usage is gated by `support_eee` presence,
you may want to remove even the set callback.
/P
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 5/9] net: dsa: microchip: implement .support_eee() only if needed
2026-06-01 8:55 ` Paolo Abeni
@ 2026-06-02 12:21 ` Bastien Curutchet
0 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet @ 2026-06-02 12:21 UTC (permalink / raw)
To: Paolo Abeni, Woojung Huh, UNGLinuxDriver, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
Hi Paolo,
On 6/1/26 10:55 AM, Paolo Abeni wrote:
> On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
>> diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
>> index a39541d29ad5..e0b3724a7558 100644
>> --- a/drivers/net/dsa/microchip/ksz9477.c
>> +++ b/drivers/net/dsa/microchip/ksz9477.c
>> @@ -1909,6 +1909,54 @@ void ksz9477_phylink_mac_link_up(struct phylink_config *config,
>> ksz9477_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause);
>> }
>>
>> +/**
>> + * ksz9477_support_eee - Determine Energy Efficient Ethernet (EEE) support for a
>> + * port
>> + * @ds: Pointer to the DSA switch structure
>> + * @port: Port number to check
>> + *
>> + * This function also documents devices where EEE was initially advertised but
>> + * later withdrawn due to reliability issues, as described in official errata
>> + * documents. These devices are explicitly listed to record known limitations,
>> + * even if there is no technical necessity for runtime checks.
>> + *
>> + * Returns: true if the internal PHY on the given port supports fully
>> + * operational EEE, false otherwise.
>> + */
>> +static bool ksz9477_support_eee(struct dsa_switch *ds, int port)
>> +{
>> + struct ksz_device *dev = ds->priv;
>> +
>> + if (!dev->info->internal_phy[port])
>> + return false;
>> +
>> + switch (dev->chip_id) {
>> + case KSZ8563_CHIP_ID:
>> + case KSZ9563_CHIP_ID:
>> + case KSZ9893_CHIP_ID:
>> + return true;
>> + default:
>> + /* KSZ8567R Errata DS80000752C Module 4 */
>> + /* KSZ9477S Errata DS80000754A Module 4 */
>> + /* KSZ9567S Errata DS80000756A Module 4 */
>> + /* KSZ9896C Errata DS80000757A Module 3 */
>> + /* KSZ9897R Errata DS80000758C Module 4 */
>
> Sashiko noted that errata:
>
> /* KSZ879x/KSZ877x/KSZ876x Errata DS80000687C Module 2 */
>
> has been lost above.
Yes that was more or less intended because KSZ879x/KSZ877x/KSZ876x don't
belong to the KSZ9477 family. I haven't found a relevant place to move
this comment as .support_eee() is removed from ksz8.c, maybe I should
have mentioned it in the commit log.
>
>> diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
>> index f8f220242f7a..4cbbcf7993c9 100644
>> --- a/drivers/net/dsa/microchip/lan937x_main.c
>> +++ b/drivers/net/dsa/microchip/lan937x_main.c
>> @@ -915,7 +915,6 @@ const struct dsa_switch_ops lan937x_switch_ops = {
>> .port_txtstamp = ksz_port_txtstamp,
>> .port_rxtstamp = ksz_port_rxtstamp,
>> .port_setup_tc = ksz_setup_tc,
>> - .support_eee = ksz_support_eee,
>> .set_mac_eee = ksz_set_mac_eee,
>
> Sashiko noted that `set_mac_eee` usage is gated by `support_eee` presence,
> you may want to remove even the set callback.
>
True, will do.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next 6/9] net: dsa: microchip: implement .{get/set}_wol only if needed
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
` (4 preceding siblings ...)
2026-05-26 9:47 ` [PATCH net-next 5/9] net: dsa: microchip: implement .support_eee() only if needed Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
2026-06-01 8:59 ` Paolo Abeni
2026-05-26 9:47 ` [PATCH net-next 7/9] net: dsa: microchip: implement port_hsr_join for KSZ9477 only Bastien Curutchet (Schneider Electric)
` (2 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
All the KSZ switches use common {get/set}_wol operations while only the
ksz9477 and the ksz87xx families really support it. These operations are
optional so there is no point implementing them to return -EOPNOTSUPP.
Remove the {get/set}_wol callbacks from the switch operations for the
ksz88xx, the ksz8463 and the lan937x families.
Remove the family check from the common {get/set}_wol implementation.
Note that is_ksz9477() is only true for the KSZ9477 so this change will
also add WoL support for the other switches using the
ksz9477_switch_ops. I checked their datasheet, they implement the same
PME_WOL registers, at the same addresses, so this should go fine.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 4 ----
drivers/net/dsa/microchip/ksz_common.c | 9 ++-------
drivers/net/dsa/microchip/lan937x_main.c | 2 --
3 files changed, 2 insertions(+), 13 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index f297aa03f42a..38549dfdce7c 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2467,8 +2467,6 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
.get_pause_stats = ksz_get_pause_stats,
.port_change_mtu = ksz8_change_mtu,
.port_max_mtu = ksz_max_mtu,
- .get_wol = ksz_get_wol,
- .set_wol = ksz_set_wol,
.suspend = ksz_suspend,
.resume = ksz_resume,
.get_ts_info = ksz_get_ts_info,
@@ -2580,8 +2578,6 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
.get_pause_stats = ksz_get_pause_stats,
.port_change_mtu = ksz8_change_mtu,
.port_max_mtu = ksz_max_mtu,
- .get_wol = ksz_get_wol,
- .set_wol = ksz_set_wol,
.suspend = ksz_suspend,
.resume = ksz_resume,
.get_ts_info = ksz_get_ts_info,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 475886b8c255..2d0150b37a40 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -3745,9 +3745,6 @@ void ksz_get_wol(struct dsa_switch *ds, int port,
u8 pme_ctrl;
int ret;
- if (!is_ksz9477(dev) && !ksz_is_ksz87xx(dev))
- return;
-
if (!dev->wakeup_source)
return;
@@ -3798,9 +3795,6 @@ int ksz_set_wol(struct dsa_switch *ds, int port,
if (wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
return -EINVAL;
- if (!is_ksz9477(dev) && !ksz_is_ksz87xx(dev))
- return -EOPNOTSUPP;
-
if (!dev->wakeup_source)
return -EOPNOTSUPP;
@@ -3913,7 +3907,8 @@ int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
*/
wol.wolopts = 0;
- ksz_get_wol(ds, dp->index, &wol);
+ if (ds->ops->get_wol)
+ ds->ops->get_wol(ds, dp->index, &wol);
if (wol.wolopts & WAKE_MAGIC) {
dev_err(ds->dev,
"Cannot change MAC address on port %d with active Wake on Magic Packet\n",
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 4cbbcf7993c9..5e55f92fb0d4 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -905,8 +905,6 @@ const struct dsa_switch_ops lan937x_switch_ops = {
.get_pause_stats = ksz_get_pause_stats,
.port_change_mtu = lan937x_change_mtu,
.port_max_mtu = ksz_max_mtu,
- .get_wol = ksz_get_wol,
- .set_wol = ksz_set_wol,
.suspend = ksz_suspend,
.resume = ksz_resume,
.get_ts_info = ksz_get_ts_info,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 6/9] net: dsa: microchip: implement .{get/set}_wol only if needed
2026-05-26 9:47 ` [PATCH net-next 6/9] net: dsa: microchip: implement .{get/set}_wol " Bastien Curutchet (Schneider Electric)
@ 2026-06-01 8:59 ` Paolo Abeni
2026-06-02 12:34 ` Bastien Curutchet
0 siblings, 1 reply; 19+ messages in thread
From: Paolo Abeni @ 2026-06-01 8:59 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric),
Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
> @@ -3798,9 +3795,6 @@ int ksz_set_wol(struct dsa_switch *ds, int port,
> if (wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
> return -EINVAL;
>
> - if (!is_ksz9477(dev) && !ksz_is_ksz87xx(dev))
> - return -EOPNOTSUPP;
Sashiko noted there is still a ksz_is_ksz87xx(dev) check in
ksz_wol_pre_shutdown() which would probably keep WoL broken for the
newly enabled switches.
/P
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 6/9] net: dsa: microchip: implement .{get/set}_wol only if needed
2026-06-01 8:59 ` Paolo Abeni
@ 2026-06-02 12:34 ` Bastien Curutchet
0 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet @ 2026-06-02 12:34 UTC (permalink / raw)
To: Paolo Abeni, Woojung Huh, UNGLinuxDriver, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
Hi Paolo,
On 6/1/26 10:59 AM, Paolo Abeni wrote:
> On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
>> @@ -3798,9 +3795,6 @@ int ksz_set_wol(struct dsa_switch *ds, int port,
>> if (wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
>> return -EINVAL;
>>
>> - if (!is_ksz9477(dev) && !ksz_is_ksz87xx(dev))
>> - return -EOPNOTSUPP;
>
> Sashiko noted there is still a ksz_is_ksz87xx(dev) check in
> ksz_wol_pre_shutdown() which would probably keep WoL broken for the
> newly enabled switches.
>
Good catch from Sashiko here. I'm going to replace the is_ksz() checks
in ksz_wol_pre_shutdown() with a if (ds->ops->get_wol &&
ds->ops->set_wol) (as done here in ksz_port_set_mac_address()) to ensure
consistency in the WoL handling.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next 7/9] net: dsa: microchip: implement port_hsr_join for KSZ9477 only
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
` (5 preceding siblings ...)
2026-05-26 9:47 ` [PATCH net-next 6/9] net: dsa: microchip: implement .{get/set}_wol " Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
2026-06-01 9:03 ` Paolo Abeni
2026-05-26 9:47 ` [PATCH net-next 8/9] net: dsa: microchip: implement lan937x-specific MDIO registration Bastien Curutchet (Schneider Electric)
2026-05-26 9:47 ` [PATCH net-next 9/9] net: dsa: microchip: implement port_teardown only if needed Bastien Curutchet (Schneider Electric)
8 siblings, 1 reply; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
All switches implement the optional .port_hsr_join operation while only
the KSZ9477 truly supports it.
Remove the common port_hsr_join implementation.
Replace it with a specific implementation for the KSZ9477 case.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 6 ---
drivers/net/dsa/microchip/ksz9477.c | 64 ++++++++++++++++++++++++++++--
drivers/net/dsa/microchip/ksz9477.h | 2 -
drivers/net/dsa/microchip/ksz_common.c | 67 --------------------------------
drivers/net/dsa/microchip/ksz_common.h | 4 --
drivers/net/dsa/microchip/lan937x_main.c | 2 -
6 files changed, 60 insertions(+), 85 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index 38549dfdce7c..bea66183238e 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2448,8 +2448,6 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
.get_sset_count = ksz_sset_count,
.port_bridge_join = ksz_port_bridge_join,
.port_bridge_leave = ksz_port_bridge_leave,
- .port_hsr_join = ksz_hsr_join,
- .port_hsr_leave = ksz_hsr_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
.port_teardown = ksz_port_teardown,
@@ -2499,8 +2497,6 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
.get_sset_count = ksz_sset_count,
.port_bridge_join = ksz_port_bridge_join,
.port_bridge_leave = ksz_port_bridge_leave,
- .port_hsr_join = ksz_hsr_join,
- .port_hsr_leave = ksz_hsr_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
.port_teardown = ksz_port_teardown,
@@ -2556,8 +2552,6 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
.get_sset_count = ksz_sset_count,
.port_bridge_join = ksz_port_bridge_join,
.port_bridge_leave = ksz_port_bridge_leave,
- .port_hsr_join = ksz_hsr_join,
- .port_hsr_leave = ksz_hsr_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
.port_teardown = ksz_port_teardown,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index e0b3724a7558..d7903814a2a5 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -12,6 +12,7 @@
#include <linux/platform_data/microchip-ksz.h>
#include <linux/phy.h>
#include <linux/if_bridge.h>
+#include <linux/if_hsr.h>
#include <linux/if_vlan.h>
#include <net/dsa.h>
#include <net/switchdev.h>
@@ -1707,12 +1708,51 @@ static int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val)
*/
#define KSZ9477_SUPPORTED_HSR_FEATURES (NETIF_F_HW_HSR_DUP | NETIF_F_HW_HSR_FWD)
-void ksz9477_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr)
+static int ksz9477_hsr_join(struct dsa_switch *ds, int port,
+ struct net_device *hsr,
+ struct netlink_ext_ack *extack)
{
struct ksz_device *dev = ds->priv;
struct net_device *user;
struct dsa_port *hsr_dp;
u8 data, hsr_ports = 0;
+ enum hsr_version ver;
+ int ret;
+
+ ret = hsr_get_version(hsr, &ver);
+ if (ret)
+ return ret;
+
+ if (dev->chip_id != KSZ9477_CHIP_ID) {
+ NL_SET_ERR_MSG_MOD(extack, "Chip does not support HSR offload");
+ return -EOPNOTSUPP;
+ }
+
+ /* KSZ9477 can support HW offloading of only 1 HSR device */
+ if (dev->hsr_dev && hsr != dev->hsr_dev) {
+ NL_SET_ERR_MSG_MOD(extack, "Offload supported for a single HSR");
+ return -EOPNOTSUPP;
+ }
+
+ /* KSZ9477 only supports HSR v0 and v1 */
+ if (!(ver == HSR_V0 || ver == HSR_V1)) {
+ NL_SET_ERR_MSG_MOD(extack, "Only HSR v0 and v1 supported");
+ return -EOPNOTSUPP;
+ }
+
+ /* KSZ9477 can only perform HSR offloading for up to two ports */
+ if (hweight8(dev->hsr_ports) >= 2) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload more than two ports - using software HSR");
+ return -EOPNOTSUPP;
+ }
+
+ /* Self MAC address filtering, to avoid frames traversing
+ * the HSR ring more than once.
+ */
+ ret = ksz_switch_macaddr_get(ds, port, extack);
+ if (ret)
+ return ret;
/* Program which port(s) shall support HSR */
ksz_rmw32(dev, REG_HSR_PORT_MAP__4, BIT(port), BIT(port));
@@ -1744,12 +1784,20 @@ void ksz9477_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr)
/* Setup HW supported features for lan HSR ports */
user = dsa_to_port(ds, port)->user;
user->features |= KSZ9477_SUPPORTED_HSR_FEATURES;
+
+ dev->hsr_dev = hsr;
+ dev->hsr_ports |= BIT(port);
+
+ return 0;
}
-void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr)
+static int ksz9477_hsr_leave(struct dsa_switch *ds, int port,
+ struct net_device *hsr)
{
struct ksz_device *dev = ds->priv;
+ WARN_ON(dev->chip_id != KSZ9477_CHIP_ID);
+
/* Clear port HSR support */
ksz_rmw32(dev, REG_HSR_PORT_MAP__4, BIT(port), 0);
@@ -1758,6 +1806,14 @@ void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr)
/* Disable per port self-address filtering */
ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL, PORT_SRC_ADDR_FILTER, false);
+
+ dev->hsr_ports &= ~BIT(port);
+ if (!dev->hsr_ports)
+ dev->hsr_dev = NULL;
+
+ ksz_switch_macaddr_put(ds);
+
+ return 0;
}
static int ksz9477_switch_init(struct ksz_device *dev)
@@ -2012,8 +2068,8 @@ const struct dsa_switch_ops ksz9477_switch_ops = {
.get_sset_count = ksz_sset_count,
.port_bridge_join = ksz_port_bridge_join,
.port_bridge_leave = ksz_port_bridge_leave,
- .port_hsr_join = ksz_hsr_join,
- .port_hsr_leave = ksz_hsr_leave,
+ .port_hsr_join = ksz9477_hsr_join,
+ .port_hsr_leave = ksz9477_hsr_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
.port_teardown = ksz_port_teardown,
diff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h
index 599db0a6ba2e..92a1d889224d 100644
--- a/drivers/net/dsa/microchip/ksz9477.h
+++ b/drivers/net/dsa/microchip/ksz9477.h
@@ -45,8 +45,6 @@ int ksz9477_mdb_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_mdb *mdb, struct dsa_db db);
int ksz9477_enable_stp_addr(struct ksz_device *dev);
void ksz9477_port_queue_split(struct ksz_device *dev, int port);
-void ksz9477_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr);
-void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr);
int ksz9477_port_acl_init(struct ksz_device *dev, int port);
void ksz9477_port_acl_free(struct ksz_device *dev, int port);
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 2d0150b37a40..404399737cea 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -16,7 +16,6 @@
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/if_vlan.h>
-#include <linux/if_hsr.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
@@ -4043,72 +4042,6 @@ void ksz_switch_macaddr_put(struct dsa_switch *ds)
kfree(switch_macaddr);
}
-int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr,
- struct netlink_ext_ack *extack)
-{
- struct ksz_device *dev = ds->priv;
- enum hsr_version ver;
- int ret;
-
- ret = hsr_get_version(hsr, &ver);
- if (ret)
- return ret;
-
- if (dev->chip_id != KSZ9477_CHIP_ID) {
- NL_SET_ERR_MSG_MOD(extack, "Chip does not support HSR offload");
- return -EOPNOTSUPP;
- }
-
- /* KSZ9477 can support HW offloading of only 1 HSR device */
- if (dev->hsr_dev && hsr != dev->hsr_dev) {
- NL_SET_ERR_MSG_MOD(extack, "Offload supported for a single HSR");
- return -EOPNOTSUPP;
- }
-
- /* KSZ9477 only supports HSR v0 and v1 */
- if (!(ver == HSR_V0 || ver == HSR_V1)) {
- NL_SET_ERR_MSG_MOD(extack, "Only HSR v0 and v1 supported");
- return -EOPNOTSUPP;
- }
-
- /* KSZ9477 can only perform HSR offloading for up to two ports */
- if (hweight8(dev->hsr_ports) >= 2) {
- NL_SET_ERR_MSG_MOD(extack,
- "Cannot offload more than two ports - using software HSR");
- return -EOPNOTSUPP;
- }
-
- /* Self MAC address filtering, to avoid frames traversing
- * the HSR ring more than once.
- */
- ret = ksz_switch_macaddr_get(ds, port, extack);
- if (ret)
- return ret;
-
- ksz9477_hsr_join(ds, port, hsr);
- dev->hsr_dev = hsr;
- dev->hsr_ports |= BIT(port);
-
- return 0;
-}
-
-int ksz_hsr_leave(struct dsa_switch *ds, int port,
- struct net_device *hsr)
-{
- struct ksz_device *dev = ds->priv;
-
- WARN_ON(dev->chip_id != KSZ9477_CHIP_ID);
-
- ksz9477_hsr_leave(ds, port, hsr);
- dev->hsr_ports &= ~BIT(port);
- if (!dev->hsr_ports)
- dev->hsr_dev = NULL;
-
- ksz_switch_macaddr_put(ds);
-
- return 0;
-}
-
int ksz_suspend(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 33cb2c44004b..c8f9ac6c3a38 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -489,10 +489,6 @@ int ksz_set_wol(struct dsa_switch *ds, int port,
struct ethtool_wolinfo *wol);
int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
const unsigned char *addr);
-int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr,
- struct netlink_ext_ack *extack);
-int ksz_hsr_leave(struct dsa_switch *ds, int port,
- struct net_device *hsr);
int ksz_suspend(struct dsa_switch *ds);
int ksz_resume(struct dsa_switch *ds);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 5e55f92fb0d4..742b919ae4df 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -883,8 +883,6 @@ const struct dsa_switch_ops lan937x_switch_ops = {
.get_sset_count = ksz_sset_count,
.port_bridge_join = ksz_port_bridge_join,
.port_bridge_leave = ksz_port_bridge_leave,
- .port_hsr_join = ksz_hsr_join,
- .port_hsr_leave = ksz_hsr_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
.port_teardown = ksz_port_teardown,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 7/9] net: dsa: microchip: implement port_hsr_join for KSZ9477 only
2026-05-26 9:47 ` [PATCH net-next 7/9] net: dsa: microchip: implement port_hsr_join for KSZ9477 only Bastien Curutchet (Schneider Electric)
@ 2026-06-01 9:03 ` Paolo Abeni
2026-06-02 12:35 ` Bastien Curutchet
0 siblings, 1 reply; 19+ messages in thread
From: Paolo Abeni @ 2026-06-01 9:03 UTC (permalink / raw)
To: Bastien Curutchet (Schneider Electric),
Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
> @@ -1744,12 +1784,20 @@ void ksz9477_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr)
> /* Setup HW supported features for lan HSR ports */
> user = dsa_to_port(ds, port)->user;
> user->features |= KSZ9477_SUPPORTED_HSR_FEATURES;
> +
> + dev->hsr_dev = hsr;
> + dev->hsr_ports |= BIT(port);
> +
> + return 0;
> }
>
> -void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr)
> +static int ksz9477_hsr_leave(struct dsa_switch *ds, int port,
> + struct net_device *hsr)
> {
> struct ksz_device *dev = ds->priv;
>
> + WARN_ON(dev->chip_id != KSZ9477_CHIP_ID);
Since the new op is used only by the relevant switch version, I think
you could/should remove the above warning.
/P
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 7/9] net: dsa: microchip: implement port_hsr_join for KSZ9477 only
2026-06-01 9:03 ` Paolo Abeni
@ 2026-06-02 12:35 ` Bastien Curutchet
2026-06-02 14:06 ` Bastien Curutchet
0 siblings, 1 reply; 19+ messages in thread
From: Bastien Curutchet @ 2026-06-02 12:35 UTC (permalink / raw)
To: Paolo Abeni, Woojung Huh, UNGLinuxDriver, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
Hi Paolo,
On 6/1/26 11:03 AM, Paolo Abeni wrote:
> On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
>> @@ -1744,12 +1784,20 @@ void ksz9477_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr)
>> /* Setup HW supported features for lan HSR ports */
>> user = dsa_to_port(ds, port)->user;
>> user->features |= KSZ9477_SUPPORTED_HSR_FEATURES;
>> +
>> + dev->hsr_dev = hsr;
>> + dev->hsr_ports |= BIT(port);
>> +
>> + return 0;
>> }
>>
>> -void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr)
>> +static int ksz9477_hsr_leave(struct dsa_switch *ds, int port,
>> + struct net_device *hsr)
>> {
>> struct ksz_device *dev = ds->priv;
>>
>> + WARN_ON(dev->chip_id != KSZ9477_CHIP_ID);
>
> Since the new op is used only by the relevant switch version, I think
> you could/should remove the above warning.
>
Ack, will do.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH net-next 7/9] net: dsa: microchip: implement port_hsr_join for KSZ9477 only
2026-06-02 12:35 ` Bastien Curutchet
@ 2026-06-02 14:06 ` Bastien Curutchet
0 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet @ 2026-06-02 14:06 UTC (permalink / raw)
To: Paolo Abeni, Woojung Huh, UNGLinuxDriver, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel
Hi again Paolo,
On 6/2/26 2:35 PM, Bastien Curutchet wrote:
> Hi Paolo,
>
> On 6/1/26 11:03 AM, Paolo Abeni wrote:
>> On 5/26/26 11:47 AM, Bastien Curutchet (Schneider Electric) wrote:
>>> @@ -1744,12 +1784,20 @@ void ksz9477_hsr_join(struct dsa_switch *ds,
>>> int port, struct net_device *hsr)
>>> /* Setup HW supported features for lan HSR ports */
>>> user = dsa_to_port(ds, port)->user;
>>> user->features |= KSZ9477_SUPPORTED_HSR_FEATURES;
>>> +
>>> + dev->hsr_dev = hsr;
>>> + dev->hsr_ports |= BIT(port);
>>> +
>>> + return 0;
>>> }
>>> -void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct
>>> net_device *hsr)
>>> +static int ksz9477_hsr_leave(struct dsa_switch *ds, int port,
>>> + struct net_device *hsr)
>>> {
>>> struct ksz_device *dev = ds->priv;
>>> + WARN_ON(dev->chip_id != KSZ9477_CHIP_ID);
>>
>> Since the new op is used only by the relevant switch version, I think
>> you could/should remove the above warning.
>>
>
> Ack, will do.
>
I'm having second thoughts now that I'm about to do it.
This HSR feature is only supported by the KSZ9477 itself, not by all the
switches using ksz9477_switch_ops. A check is done against the
KSZ9477_CHIP_ID in ksz9477_hsr_join(). This WARN_ON is kind of symmetric
with the ksz9477_hsr_join()'s check so, IMHO, it makes sense to keep it.
Best regards,
Bastien
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next 8/9] net: dsa: microchip: implement lan937x-specific MDIO registration
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
` (6 preceding siblings ...)
2026-05-26 9:47 ` [PATCH net-next 7/9] net: dsa: microchip: implement port_hsr_join for KSZ9477 only Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
2026-05-26 9:47 ` [PATCH net-next 9/9] net: dsa: microchip: implement port_teardown only if needed Bastien Curutchet (Schneider Electric)
8 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
All the switches use a common mdio_register() function that uses two
ksz_dev_ops callbacks (.mdio_bus_preinit() and .create_phy_addr_map())
to handle the lan937x specific case. These two callbacks are used only
at this place in the code.
Implement a new lan937x-specific MDIO registration functions that uses
these two lan937x-specific functions. The lan937x bindings don't
have any 'interrupts' property so this lan937x_mdio_register() doesn't
call ksz_irq_phy_setup().
Expose the common ksz_*_mdio_{read/write} functions so they can be used
in lan937x.c
Remove the callbacks from ksz_dev_ops.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz_common.c | 30 +++-------
drivers/net/dsa/microchip/ksz_common.h | 42 ++------------
drivers/net/dsa/microchip/lan937x_main.c | 99 +++++++++++++++++++++++++++++++-
3 files changed, 110 insertions(+), 61 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 404399737cea..708dddf2c6cf 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2256,7 +2256,7 @@ static void ksz_update_port_member(struct ksz_device *dev, int port)
dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port);
}
-static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
+int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
{
struct ksz_device *dev = bus->priv;
struct dsa_switch *ds = dev->ds;
@@ -2264,8 +2264,7 @@ static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
return ds->ops->phy_read(ds, addr, regnum);
}
-static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
- u16 val)
+int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
{
struct ksz_device *dev = bus->priv;
struct dsa_switch *ds = dev->ds;
@@ -2286,7 +2285,7 @@ static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
*
* Return: Value of the PHY register, or a negative error code on failure.
*/
-static int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
+int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
{
struct ksz_device *dev = bus->priv;
@@ -2306,8 +2305,7 @@ static int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
*
* Return: 0 on success, or a negative error code on failure.
*/
-static int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum,
- u16 val)
+int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
{
struct ksz_device *dev = bus->priv;
@@ -2415,8 +2413,8 @@ static void ksz_irq_phy_free(struct ksz_device *dev)
*
* Return: 0 on success, or a negative error code on failure.
*/
-static int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
- struct device_node *mdio_np)
+int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
+ struct device_node *mdio_np)
{
struct device_node *phy_node, *phy_parent_node;
bool phys_are_valid = true;
@@ -2519,20 +2517,8 @@ int ksz_mdio_register(struct ksz_device *dev)
goto put_mdio_node;
}
- if (dev->dev_ops->mdio_bus_preinit) {
- ret = dev->dev_ops->mdio_bus_preinit(dev, !!parent_bus);
- if (ret)
- goto put_mdio_node;
- }
-
- if (dev->dev_ops->create_phy_addr_map) {
- ret = dev->dev_ops->create_phy_addr_map(dev, !!parent_bus);
- if (ret)
- goto put_mdio_node;
- } else {
- for (i = 0; i < dev->info->port_cnt; i++)
- dev->phy_addr_map[i] = i;
- }
+ for (i = 0; i < dev->info->port_cnt; i++)
+ dev->phy_addr_map[i] = i;
bus->priv = dev;
if (parent_bus) {
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index c8f9ac6c3a38..a7fc23ced38c 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -362,42 +362,6 @@ struct ksz_dev_ops {
u32 (*get_port_addr)(int port, int offset);
void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
- /**
- * @mdio_bus_preinit: Function pointer to pre-initialize the MDIO bus
- * for accessing PHYs.
- * @dev: Pointer to device structure.
- * @side_mdio: Boolean indicating if the PHYs are accessed over a side
- * MDIO bus.
- *
- * This function pointer is used to configure the MDIO bus for PHY
- * access before initiating regular PHY operations. It enables either
- * SPI/I2C or side MDIO access modes by unlocking necessary registers
- * and setting up access permissions for the selected mode.
- *
- * Return:
- * - 0 on success.
- * - Negative error code on failure.
- */
- int (*mdio_bus_preinit)(struct ksz_device *dev, bool side_mdio);
-
- /**
- * @create_phy_addr_map: Function pointer to create a port-to-PHY
- * address map.
- * @dev: Pointer to device structure.
- * @side_mdio: Boolean indicating if the PHYs are accessed over a side
- * MDIO bus.
- *
- * This function pointer is responsible for mapping switch ports to PHY
- * addresses according to the configured access mode (SPI or side MDIO)
- * and the device’s strap configuration. The mapping setup may vary
- * depending on the chip variant and configuration. Ensures the correct
- * address mapping for PHY communication.
- *
- * Return:
- * - 0 on success.
- * - Negative error code on failure (e.g., invalid configuration).
- */
- int (*create_phy_addr_map)(struct ksz_device *dev, bool side_mdio);
void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
u64 *cnt);
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
@@ -493,6 +457,12 @@ int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
int ksz_suspend(struct dsa_switch *ds);
int ksz_resume(struct dsa_switch *ds);
+int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
+ struct device_node *mdio_np);
+int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum);
+int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val);
+int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum);
+int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val);
int ksz_mdio_register(struct ksz_device *dev);
int ksz_pirq_setup(struct ksz_device *dev, u8 p);
int ksz_girq_setup(struct ksz_device *dev);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 742b919ae4df..73ad99dac72d 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/iopoll.h>
#include <linux/phy.h>
+#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/if_bridge.h>
#include <linux/if_vlan.h>
@@ -681,6 +682,100 @@ static int lan937x_switch_init(struct ksz_device *dev)
return 0;
}
+/**
+ * lan937x_mdio_register - Register and configure the MDIO bus for the LAN937x.
+ * @dev: Pointer to the KSZ device structure.
+ *
+ * This function sets up and registers an MDIO bus for a LAN937x switch,
+ * allowing access to its internal PHYs. If the device supports side MDIO,
+ * the function will configure the external MDIO controller specified by the
+ * "mdio-parent-bus" device tree property to directly manage internal PHYs.
+ * Otherwise, SPI or I2C access is set up for PHY access.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+static int lan937x_mdio_register(struct ksz_device *dev)
+{
+ struct device_node *parent_bus_node;
+ struct mii_bus *parent_bus = NULL;
+ struct dsa_switch *ds = dev->ds;
+ struct device_node *mdio_np;
+ struct mii_bus *bus;
+ int ret;
+
+ mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio");
+ if (!mdio_np)
+ return 0;
+
+ parent_bus_node = of_parse_phandle(mdio_np, "mdio-parent-bus", 0);
+ if (parent_bus_node && !dev->info->phy_side_mdio_supported) {
+ dev_err(dev->dev, "Side MDIO bus is not supported for this HW, ignoring 'mdio-parent-bus' property.\n");
+ ret = -EINVAL;
+
+ goto put_mdio_node;
+ } else if (parent_bus_node) {
+ parent_bus = of_mdio_find_bus(parent_bus_node);
+ if (!parent_bus) {
+ ret = -EPROBE_DEFER;
+
+ goto put_mdio_node;
+ }
+
+ dev->parent_mdio_bus = parent_bus;
+ }
+
+ bus = devm_mdiobus_alloc(ds->dev);
+ if (!bus) {
+ ret = -ENOMEM;
+ goto put_mdio_node;
+ }
+
+ ret = lan937x_mdio_bus_preinit(dev, !!parent_bus);
+ if (ret)
+ goto put_mdio_node;
+
+ ret = lan937x_create_phy_addr_map(dev, !!parent_bus);
+ if (ret)
+ goto put_mdio_node;
+
+ bus->priv = dev;
+ if (parent_bus) {
+ bus->read = ksz_parent_mdio_read;
+ bus->write = ksz_parent_mdio_write;
+ bus->name = "KSZ side MDIO";
+ snprintf(bus->id, MII_BUS_ID_SIZE, "ksz-side-mdio-%d",
+ ds->index);
+ } else {
+ bus->read = ksz_sw_mdio_read;
+ bus->write = ksz_sw_mdio_write;
+ bus->name = "ksz user smi";
+ if (ds->dst->index != 0)
+ snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d-%d", ds->dst->index, ds->index);
+ else
+ snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
+ }
+
+ ret = ksz_parse_dt_phy_config(dev, bus, mdio_np);
+ if (ret)
+ goto put_mdio_node;
+
+ ds->phys_mii_mask = bus->phy_mask;
+ bus->parent = ds->dev;
+
+ ds->user_mii_bus = bus;
+
+ ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np);
+ if (ret)
+ dev_err(ds->dev, "unable to register MDIO bus %s\n",
+ bus->id);
+
+put_mdio_node:
+ of_node_put(mdio_np);
+ of_node_put(parent_bus_node);
+
+ return ret;
+}
+
static int lan937x_setup(struct dsa_switch *ds)
{
struct ksz_device *dev = ds->priv;
@@ -794,7 +889,7 @@ static int lan937x_setup(struct dsa_switch *ds)
goto port_release;
}
- ret = ksz_mdio_register(dev);
+ ret = lan937x_mdio_register(dev);
if (ret < 0) {
dev_err(dev->dev, "failed to register the mdio");
goto out_ptp_clock_unregister;
@@ -857,8 +952,6 @@ const struct phylink_mac_ops lan937x_phylink_mac_ops = {
const struct ksz_dev_ops lan937x_dev_ops = {
.get_port_addr = ksz9477_get_port_addr,
.cfg_port_member = ksz9477_cfg_port_member,
- .mdio_bus_preinit = lan937x_mdio_bus_preinit,
- .create_phy_addr_map = lan937x_create_phy_addr_map,
.r_mib_cnt = ksz9477_r_mib_cnt,
.r_mib_pkt = ksz9477_r_mib_pkt,
.r_mib_stat64 = ksz_r_mib_stats64,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH net-next 9/9] net: dsa: microchip: implement port_teardown only if needed
2026-05-26 9:47 [PATCH net-next 0/9] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
` (7 preceding siblings ...)
2026-05-26 9:47 ` [PATCH net-next 8/9] net: dsa: microchip: implement lan937x-specific MDIO registration Bastien Curutchet (Schneider Electric)
@ 2026-05-26 9:47 ` Bastien Curutchet (Schneider Electric)
8 siblings, 0 replies; 19+ messages in thread
From: Bastien Curutchet (Schneider Electric) @ 2026-05-26 9:47 UTC (permalink / raw)
To: Woojung Huh, UNGLinuxDriver, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Russell King
Cc: Pascal Eberhard, Miquèl Raynal, Thomas Petazzoni,
Tristram Ha, netdev, linux-kernel,
Bastien Curutchet (Schneider Electric)
The port_teardown() operation is optional. Yet, it is implemented by all
the KSZ switches through a common function that doesn't do anything for
the switches that aren't part of the ksz9477 family
Remove the implementation from the switches that don't need it.
Implement instead a ksz9477-specific port_teardown.
Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
drivers/net/dsa/microchip/ksz8.c | 3 ---
drivers/net/dsa/microchip/ksz9477.c | 10 +++++++++-
drivers/net/dsa/microchip/ksz_common.c | 19 -------------------
drivers/net/dsa/microchip/ksz_common.h | 1 -
drivers/net/dsa/microchip/lan937x_main.c | 1 -
5 files changed, 9 insertions(+), 25 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index bea66183238e..e5d4ade0b29a 100644
--- a/drivers/net/dsa/microchip/ksz8.c
+++ b/drivers/net/dsa/microchip/ksz8.c
@@ -2450,7 +2450,6 @@ const struct dsa_switch_ops ksz8463_switch_ops = {
.port_bridge_leave = ksz_port_bridge_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
- .port_teardown = ksz_port_teardown,
.port_pre_bridge_flags = ksz_port_pre_bridge_flags,
.port_bridge_flags = ksz_port_bridge_flags,
.port_fast_age = ksz8_flush_dyn_mac_table,
@@ -2499,7 +2498,6 @@ const struct dsa_switch_ops ksz87xx_switch_ops = {
.port_bridge_leave = ksz_port_bridge_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
- .port_teardown = ksz_port_teardown,
.port_pre_bridge_flags = ksz_port_pre_bridge_flags,
.port_bridge_flags = ksz_port_bridge_flags,
.port_fast_age = ksz8_flush_dyn_mac_table,
@@ -2554,7 +2552,6 @@ const struct dsa_switch_ops ksz88xx_switch_ops = {
.port_bridge_leave = ksz_port_bridge_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
- .port_teardown = ksz_port_teardown,
.port_pre_bridge_flags = ksz_port_pre_bridge_flags,
.port_bridge_flags = ksz_port_bridge_flags,
.port_fast_age = ksz8_flush_dyn_mac_table,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index d7903814a2a5..c2220afd7466 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -1940,6 +1940,14 @@ static void ksz9477_duplex_flowctrl(struct ksz_device *dev, int port, int duplex
ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val);
}
+static void ksz9477_port_teardown(struct dsa_switch *ds, int port)
+{
+ struct ksz_device *dev = ds->priv;
+
+ if (dsa_is_user_port(ds, port))
+ ksz9477_port_acl_free(dev, port);
+}
+
void ksz9477_phylink_mac_link_up(struct phylink_config *config,
struct phy_device *phydev,
unsigned int mode,
@@ -2072,7 +2080,7 @@ const struct dsa_switch_ops ksz9477_switch_ops = {
.port_hsr_leave = ksz9477_hsr_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
- .port_teardown = ksz_port_teardown,
+ .port_teardown = ksz9477_port_teardown,
.port_pre_bridge_flags = ksz_port_pre_bridge_flags,
.port_bridge_flags = ksz_port_bridge_flags,
.port_fast_age = ksz9477_flush_dyn_mac_table,
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 708dddf2c6cf..3f5b1c4e7169 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2953,25 +2953,6 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
ksz_update_port_member(dev, port);
}
-void ksz_port_teardown(struct dsa_switch *ds, int port)
-{
- struct ksz_device *dev = ds->priv;
-
- switch (dev->chip_id) {
- case KSZ8563_CHIP_ID:
- case KSZ8567_CHIP_ID:
- case KSZ9477_CHIP_ID:
- case KSZ9563_CHIP_ID:
- case KSZ9567_CHIP_ID:
- case KSZ9893_CHIP_ID:
- case KSZ9896_CHIP_ID:
- case KSZ9897_CHIP_ID:
- case LAN9646_CHIP_ID:
- if (dsa_is_user_port(ds, port))
- ksz9477_port_acl_free(dev, port);
- }
-}
-
int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port,
struct switchdev_brport_flags flags,
struct netlink_ext_ack *extack)
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index a7fc23ced38c..80cb4265dbdc 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -387,7 +387,6 @@ int ksz_switch_suspend(struct device *dev);
int ksz_switch_resume(struct device *dev);
void ksz_teardown(struct dsa_switch *ds);
-void ksz_port_teardown(struct dsa_switch *ds, int port);
void ksz_init_mib_timer(struct ksz_device *dev);
bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index 73ad99dac72d..084ee811f6e2 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -978,7 +978,6 @@ const struct dsa_switch_ops lan937x_switch_ops = {
.port_bridge_leave = ksz_port_bridge_leave,
.port_set_mac_address = ksz_port_set_mac_address,
.port_stp_state_set = ksz_port_stp_state_set,
- .port_teardown = ksz_port_teardown,
.port_pre_bridge_flags = ksz_port_pre_bridge_flags,
.port_bridge_flags = ksz_port_bridge_flags,
.port_fast_age = ksz9477_flush_dyn_mac_table,
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread