[PATCH net-next v2 08/10] net: dsa: microchip: implement port_hsr_join for KSZ9477 only
From: Bastien Curutchet (Schneider Electric) <hidden>
Date: 2026-06-08 14:10:33
Also in:
lkml
Subsystem:
microchip ksz series ethernet switch driver, networking drivers, networking [dsa], the rest · Maintainers:
Woojung Huh, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Linus Torvalds
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) <redacted> --- drivers/net/dsa/microchip/ksz8.c | 6 --- drivers/net/dsa/microchip/ksz9477.c | 65 +++++++++++++++++++++++++++++-- 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, 61 insertions(+), 85 deletions(-)
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c
index 690e1b275992..76b0f2ac8594 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,
@@ -2498,8 +2496,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,
@@ -2554,8 +2550,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..48813b0f4280 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,52 @@ 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 +1785,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 +1807,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 +2069,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 809a0bc3c01e..7dc8e4ffacdd 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>
@@ -4055,72 +4054,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 17b7ba77aaa9..2c118eaddd75 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h@@ -490,10 +490,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 6b1306e81558..d45798de4ce9 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c@@ -871,8 +871,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