From d80a52335374e484a4ff2afdc9af843e73273945 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Sat, 27 Jan 2024 14:25:09 +0100 Subject: ethtool: replace struct ethtool_eee with a new struct ethtool_keee on kernel side In order to pass EEE link modes beyond bit 32 to userspace we have to complement the 32 bit bitmaps in struct ethtool_eee with linkmode bitmaps. Therefore, similar to ethtool_link_settings and ethtool_link_ksettings, add a struct ethtool_keee. In a first step it's an identical copy of ethtool_eee. This patch simply does a s/ethtool_eee/ethtool_keee/g for all users. No functional change intended. Suggested-by: Andrew Lunn Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/dsa/microchip/ksz_common.c') diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 245dfb7a7a31..a7b5ddb8656e 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2852,7 +2852,7 @@ static int ksz_validate_eee(struct dsa_switch *ds, int port) } static int ksz_get_mac_eee(struct dsa_switch *ds, int port, - struct ethtool_eee *e) + struct ethtool_keee *e) { int ret; @@ -2872,7 +2872,7 @@ static int ksz_get_mac_eee(struct dsa_switch *ds, int port, } static int ksz_set_mac_eee(struct dsa_switch *ds, int port, - struct ethtool_eee *e) + struct ethtool_keee *e) { struct ksz_device *dev = ds->priv; int ret; -- cgit v1.2.3 From 3723b56d6f73f7c8c3b521a80556f129830f6fb9 Mon Sep 17 00:00:00 2001 From: Philippe Schenker Date: Tue, 30 Jan 2024 09:34:19 +0100 Subject: net: dsa: Add KSZ8567 switch support This commit introduces support for the KSZ8567, a robust 7-port Ethernet switch. The KSZ8567 features two RGMII/MII/RMII interfaces, each capable of gigabit speeds, complemented by five 10/100 Mbps MAC/PHYs. Signed-off-by: Philippe Schenker Acked-by: Arun Ramadoss Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20240130083419.135763-2-dev@pschenker.ch Signed-off-by: Paolo Abeni --- drivers/net/dsa/microchip/ksz9477_i2c.c | 4 +++ drivers/net/dsa/microchip/ksz_common.c | 43 ++++++++++++++++++++++++++++- drivers/net/dsa/microchip/ksz_common.h | 1 + drivers/net/dsa/microchip/ksz_spi.c | 5 ++++ include/linux/platform_data/microchip-ksz.h | 1 + 5 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers/net/dsa/microchip/ksz_common.c') diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index cac4a607e54a..82bebee4615c 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -103,6 +103,10 @@ static const struct of_device_id ksz9477_dt_ids[] = { .compatible = "microchip,ksz8563", .data = &ksz_switch_chips[KSZ8563] }, + { + .compatible = "microchip,ksz8567", + .data = &ksz_switch_chips[KSZ8567] + }, { .compatible = "microchip,ksz9567", .data = &ksz_switch_chips[KSZ9567] diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index a7b5ddb8656e..9ff5132f3ac6 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1476,6 +1476,39 @@ const struct ksz_chip_data ksz_switch_chips[] = { .gbit_capable = {true, true, true}, }, + [KSZ8567] = { + .chip_id = KSZ8567_CHIP_ID, + .dev_name = "KSZ8567", + .num_vlans = 4096, + .num_alus = 4096, + .num_statics = 16, + .cpu_ports = 0x7F, /* can be configured as cpu port */ + .port_cnt = 7, /* total port count */ + .port_nirqs = 3, + .num_tx_queues = 4, + .tc_cbs_supported = true, + .tc_ets_supported = true, + .ops = &ksz9477_dev_ops, + .mib_names = ksz9477_mib_names, + .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), + .reg_mib_cnt = MIB_COUNTER_NUM, + .regs = ksz9477_regs, + .masks = ksz9477_masks, + .shifts = ksz9477_shifts, + .xmii_ctrl0 = ksz9477_xmii_ctrl0, + .xmii_ctrl1 = ksz9477_xmii_ctrl1, + .supports_mii = {false, false, false, false, + false, true, true}, + .supports_rmii = {false, false, false, false, + false, true, true}, + .supports_rgmii = {false, false, false, false, + false, true, true}, + .internal_phy = {true, true, true, true, + true, false, false}, + .gbit_capable = {false, false, false, false, false, + true, true}, + }, + [KSZ9567] = { .chip_id = KSZ9567_CHIP_ID, .dev_name = "KSZ9567", @@ -2649,6 +2682,7 @@ static void ksz_port_teardown(struct dsa_switch *ds, int port) switch (dev->chip_id) { case KSZ8563_CHIP_ID: + case KSZ8567_CHIP_ID: case KSZ9477_CHIP_ID: case KSZ9563_CHIP_ID: case KSZ9567_CHIP_ID: @@ -2705,7 +2739,8 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, dev->chip_id == KSZ9563_CHIP_ID) proto = DSA_TAG_PROTO_KSZ9893; - if (dev->chip_id == KSZ9477_CHIP_ID || + if (dev->chip_id == KSZ8567_CHIP_ID || + dev->chip_id == KSZ9477_CHIP_ID || dev->chip_id == KSZ9896_CHIP_ID || dev->chip_id == KSZ9897_CHIP_ID || dev->chip_id == KSZ9567_CHIP_ID) @@ -2813,6 +2848,7 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) case KSZ8830_CHIP_ID: return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; case KSZ8563_CHIP_ID: + case KSZ8567_CHIP_ID: case KSZ9477_CHIP_ID: case KSZ9563_CHIP_ID: case KSZ9567_CHIP_ID: @@ -2839,6 +2875,7 @@ static int ksz_validate_eee(struct dsa_switch *ds, int port) switch (dev->chip_id) { case KSZ8563_CHIP_ID: + case KSZ8567_CHIP_ID: case KSZ9477_CHIP_ID: case KSZ9563_CHIP_ID: case KSZ9567_CHIP_ID: @@ -3183,6 +3220,7 @@ static int ksz_switch_detect(struct ksz_device *dev) case KSZ9896_CHIP_ID: case KSZ9897_CHIP_ID: case KSZ9567_CHIP_ID: + case KSZ8567_CHIP_ID: case LAN9370_CHIP_ID: case LAN9371_CHIP_ID: case LAN9372_CHIP_ID: @@ -3220,6 +3258,7 @@ static int ksz_cls_flower_add(struct dsa_switch *ds, int port, switch (dev->chip_id) { case KSZ8563_CHIP_ID: + case KSZ8567_CHIP_ID: case KSZ9477_CHIP_ID: case KSZ9563_CHIP_ID: case KSZ9567_CHIP_ID: @@ -3239,6 +3278,7 @@ static int ksz_cls_flower_del(struct dsa_switch *ds, int port, switch (dev->chip_id) { case KSZ8563_CHIP_ID: + case KSZ8567_CHIP_ID: case KSZ9477_CHIP_ID: case KSZ9563_CHIP_ID: case KSZ9567_CHIP_ID: @@ -4142,6 +4182,7 @@ static int ksz_parse_drive_strength(struct ksz_device *dev) case KSZ8794_CHIP_ID: case KSZ8765_CHIP_ID: case KSZ8563_CHIP_ID: + case KSZ8567_CHIP_ID: case KSZ9477_CHIP_ID: case KSZ9563_CHIP_ID: case KSZ9567_CHIP_ID: diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 15612101a155..060c5de9aa05 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -187,6 +187,7 @@ struct ksz_device { /* List of supported models */ enum ksz_model { KSZ8563, + KSZ8567, KSZ8795, KSZ8794, KSZ8765, diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index 6f6d878e742c..c8166fb440ab 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c @@ -164,6 +164,10 @@ static const struct of_device_id ksz_dt_ids[] = { .compatible = "microchip,ksz8563", .data = &ksz_switch_chips[KSZ8563] }, + { + .compatible = "microchip,ksz8567", + .data = &ksz_switch_chips[KSZ8567] + }, { .compatible = "microchip,ksz9567", .data = &ksz_switch_chips[KSZ9567] @@ -204,6 +208,7 @@ static const struct spi_device_id ksz_spi_ids[] = { { "ksz9893" }, { "ksz9563" }, { "ksz8563" }, + { "ksz8567" }, { "ksz9567" }, { "lan9370" }, { "lan9371" }, diff --git a/include/linux/platform_data/microchip-ksz.h b/include/linux/platform_data/microchip-ksz.h index f177416635a2..8c659db4da6b 100644 --- a/include/linux/platform_data/microchip-ksz.h +++ b/include/linux/platform_data/microchip-ksz.h @@ -33,6 +33,7 @@ enum ksz_chip_id { KSZ9897_CHIP_ID = 0x00989700, KSZ9893_CHIP_ID = 0x00989300, KSZ9563_CHIP_ID = 0x00956300, + KSZ8567_CHIP_ID = 0x00856700, KSZ9567_CHIP_ID = 0x00956700, LAN9370_CHIP_ID = 0x00937000, LAN9371_CHIP_ID = 0x00937100, -- cgit v1.2.3 From a7f08029e2e84ecafbfff50fcff976fafee72799 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 22 Feb 2024 08:51:13 +0100 Subject: net: dsa: microchip: Add support for bridge port isolation Implement bridge port isolation for KSZ switches. Enabling the isolation of switch ports from each other while maintaining connectivity with the CPU and other forwarding ports. For instance, to isolate swp1 and swp2 from each other, use the following commands: - bridge link set dev swp1 isolated on - bridge link set dev swp2 isolated on Signed-off-by: Oleksij Rempel Acked-by: Arun Ramadoss Signed-off-by: David S. Miller --- drivers/net/dsa/microchip/ksz_common.c | 55 ++++++++++++++++++++++++++++++---- drivers/net/dsa/microchip/ksz_common.h | 1 + 2 files changed, 51 insertions(+), 5 deletions(-) (limited to 'drivers/net/dsa/microchip/ksz_common.c') diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 9ff5132f3ac6..f799be868274 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1897,6 +1897,29 @@ static void ksz_get_strings(struct dsa_switch *ds, int port, } } +/** + * ksz_update_port_member - Adjust port forwarding rules based on STP state and + * isolation settings. + * @dev: A pointer to the struct ksz_device representing the device. + * @port: The port number to adjust. + * + * This function dynamically adjusts the port membership configuration for a + * specified port and other device ports, based on Spanning Tree Protocol (STP) + * states and port isolation settings. Each port, including the CPU port, has a + * membership register, represented as a bitfield, where each bit corresponds + * to a port number. A set bit indicates permission to forward frames to that + * port. This function iterates over all ports, updating the membership register + * to reflect current forwarding permissions: + * + * 1. Forwards frames only to ports that are part of the same bridge group and + * in the BR_STATE_FORWARDING state. + * 2. Takes into account the isolation status of ports; ports in the + * BR_STATE_FORWARDING state with BR_ISOLATED configuration will not forward + * frames to each other, even if they are in the same bridge group. + * 3. Ensures that the CPU port is included in the membership based on its + * upstream port configuration, allowing for management and control traffic + * to flow as required. + */ static void ksz_update_port_member(struct ksz_device *dev, int port) { struct ksz_port *p = &dev->ports[port]; @@ -1925,7 +1948,14 @@ static void ksz_update_port_member(struct ksz_device *dev, int port) if (other_p->stp_state != BR_STATE_FORWARDING) continue; - if (p->stp_state == BR_STATE_FORWARDING) { + /* At this point we know that "port" and "other" port [i] are in + * the same bridge group and that "other" port [i] is in + * forwarding stp state. If "port" is also in forwarding stp + * state, we can allow forwarding from port [port] to port [i]. + * Except if both ports are isolated. + */ + if (p->stp_state == BR_STATE_FORWARDING && + !(p->isolated && other_p->isolated)) { val |= BIT(port); port_member |= BIT(i); } @@ -1944,8 +1974,19 @@ static void ksz_update_port_member(struct ksz_device *dev, int port) third_p = &dev->ports[j]; if (third_p->stp_state != BR_STATE_FORWARDING) continue; + third_dp = dsa_to_port(ds, j); - if (dsa_port_bridge_same(other_dp, third_dp)) + + /* Now we updating relation of the "other" port [i] to + * the "third" port [j]. We already know that "other" + * port [i] is in forwarding stp state and that "third" + * port [j] is in forwarding stp state too. + * We need to check if "other" port [i] and "third" port + * [j] are in the same bridge group and not isolated + * before allowing forwarding from port [i] to port [j]. + */ + if (dsa_port_bridge_same(other_dp, third_dp) && + !(other_p->isolated && third_p->isolated)) val |= BIT(j); } @@ -2698,7 +2739,7 @@ static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, struct switchdev_brport_flags flags, struct netlink_ext_ack *extack) { - if (flags.mask & ~BR_LEARNING) + if (flags.mask & ~(BR_LEARNING | BR_ISOLATED)) return -EINVAL; return 0; @@ -2711,8 +2752,12 @@ static int ksz_port_bridge_flags(struct dsa_switch *ds, int port, struct ksz_device *dev = ds->priv; struct ksz_port *p = &dev->ports[port]; - if (flags.mask & BR_LEARNING) { - p->learning = !!(flags.val & BR_LEARNING); + if (flags.mask & (BR_LEARNING | BR_ISOLATED)) { + if (flags.mask & BR_LEARNING) + p->learning = !!(flags.val & BR_LEARNING); + + if (flags.mask & BR_ISOLATED) + p->isolated = !!(flags.val & BR_ISOLATED); /* Make the change take effect immediately */ ksz_port_stp_state_set(ds, port, p->stp_state); diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 060c5de9aa05..40c11b0d6b62 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -110,6 +110,7 @@ struct ksz_switch_macaddr { struct ksz_port { bool remove_tag; /* Remove Tag flag set, for ksz8795 only */ bool learning; + bool isolated; int stp_state; struct phy_device phydev; -- cgit v1.2.3 From e3fb8e8ba72b053d05ca2602acdd6b869f9f296f Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Mon, 4 Mar 2024 14:56:12 +0100 Subject: net: dsa: microchip: make sure drive strength configuration is not lost by soft reset This driver has two separate reset sequence in different places: - gpio/HW reset on start of ksz_switch_register() - SW reset on start of ksz_setup() The second one will overwrite drive strength configuration made in the ksz_switch_register(). To fix it, move ksz_parse_drive_strength() from ksz_switch_register() to ksz_setup(). Fixes: d67d7247f641 ("net: dsa: microchip: Add drive strength configuration") Signed-off-by: Oleksij Rempel Link: https://lore.kernel.org/r/20240304135612.814404-1-o.rempel@pengutronix.de Signed-off-by: Jakub Kicinski --- drivers/net/dsa/microchip/ksz_common.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/dsa/microchip/ksz_common.c') diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 245dfb7a7a31..25a49708f484 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -2185,6 +2185,8 @@ static int ksz_pirq_setup(struct ksz_device *dev, u8 p) return ksz_irq_common_setup(dev, pirq); } +static int ksz_parse_drive_strength(struct ksz_device *dev); + static int ksz_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; @@ -2206,6 +2208,10 @@ static int ksz_setup(struct dsa_switch *ds) return ret; } + ret = ksz_parse_drive_strength(dev); + if (ret) + return ret; + /* set broadcast storm protection 10% rate */ regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL], BROADCAST_STORM_RATE, @@ -4242,10 +4248,6 @@ int ksz_switch_register(struct ksz_device *dev) for (port_num = 0; port_num < dev->info->port_cnt; ++port_num) dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA; if (dev->dev->of_node) { - ret = ksz_parse_drive_strength(dev); - if (ret) - return ret; - ret = of_get_phy_mode(dev->dev->of_node, &interface); if (ret == 0) dev->compat_interface = interface; -- cgit v1.2.3