FAILED: patch "[PATCH] net: dsa: microchip: make learning configurable and keep it" failed to apply to 4.19-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 15f7cfae912ea1739c8844b7edf3621ba981a37a Mon Sep 17 00:00:00 2001
From: Vladimir Oltean <[email protected]>
Date: Thu, 18 Aug 2022 19:48:09 +0300
Subject: [PATCH] net: dsa: microchip: make learning configurable and keep it
off while standalone
Address learning should initially be turned off by the driver for port operation in standalone mode, then the DSA core handles changes to it via ds->ops->port_bridge_flags().
Leaving address learning enabled while ports are standalone breaks any kind of communication which involves port B receiving what port A has sent. Notably it breaks the ksz9477 driver used with a (non offloaded, ports act as if standalone) bonding interface in active-backup mode, when the ports are connected together through external switches, for redundancy purposes.
This fixes a major design flaw in the ksz9477 and ksz8795 drivers, which unconditionally leave address learning enabled even while ports operate as standalone.
drivers/net/dsa/microchip/ksz_common.c +44 -1
@@ -968,6 +968,7 @@ static void ksz_update_port_member(struct ksz_device *dev, int port)static int ksz_setup (struct dsa_switch *ds) {struct ksz_device *dev = ds->priv; +struct ksz_port *p;const u16 *regs;int ret;
@@ -1007,6 +1008,14 @@ static int ksz_setup(struct dsa_switch *ds)return ret; } +/* Start with learning disabled on standalone user ports, and enabled +* on the CPU port. In lack of other finer mechanisms, learning on the +* CPU port will avoid flooding bridge local addresses on the network +* in some cases. +*/ + p = &dev->ports[dev->cpu_port]; + p->learning = true; +/* start switch */ regmap_update_bits (dev->regmap[0 ], regs[S_START_CTRL ],SW_START ,SW_START );
@@ -1283,6 +1292,8 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)ksz_pread8 (dev, port, regs[P_STP_CTRL ], &data); data &= ~(PORT_TX_ENABLE |PORT_RX_ENABLE |PORT_LEARN_DISABLE ); + p = &dev->ports[port]; +switch (state) {case BR_STATE_DISABLED : data |=PORT_LEARN_DISABLE ;
@@ -1292,9 +1303,13 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)break ;case BR_STATE_LEARNING : data |=PORT_RX_ENABLE ; +if (!p->learning) + data |=PORT_LEARN_DISABLE ;break ;case BR_STATE_FORWARDING : data |= (PORT_TX_ENABLE |PORT_RX_ENABLE ); +if (!p->learning) + data |=PORT_LEARN_DISABLE ;break ;case BR_STATE_BLOCKING : data |=PORT_LEARN_DISABLE ;
@@ -1306,12 +1321,38 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)ksz_pwrite8 (dev, port, regs[P_STP_CTRL ], data); - p = &dev->ports[port]; p->stp_state = state;ksz_update_port_member (dev, port); } +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 ) +return -EINVAL ; + +return 0 ; +} + +static int ksz_port_bridge_flags (struct dsa_switch *ds,int port, +struct switchdev_brport_flags flags, +struct netlink_ext_ack *extack) +{ +struct ksz_device *dev = ds->priv; +struct ksz_port *p = &dev->ports[port]; + +if (flags.mask &BR_LEARNING ) { + p->learning = !!(flags.val &BR_LEARNING ); + +/* Make the change take effect immediately */ +ksz_port_stp_state_set (ds, port, p->stp_state); + } + +return 0 ; +} +static enum dsa_tag_protocol ksz_get_tag_protocol (struct dsa_switch *ds,int port,enum dsa_tag_protocol mp)
@@ -1725,6 +1766,8 @@ static const struct dsa_switch_ops ksz_switch_ops = { .port_bridge_join = ksz_port_bridge_join, .port_bridge_leave = ksz_port_bridge_leave, .port_stp_state_set = ksz_port_stp_state_set, + .port_pre_bridge_flags = ksz_port_pre_bridge_flags, + .port_bridge_flags = ksz_port_bridge_flags, .port_fast_age = ksz_port_fast_age, .port_vlan_filtering = ksz_port_vlan_filtering, .port_vlan_add = ksz_port_vlan_add,
drivers/net/dsa/microchip/ksz_common.h +1 -0
@@ -65,6 +65,7 @@ struct ksz_chip_data {struct ksz_port {bool remove_tag;/* Remove Tag flag set, for ksz8795 only */ +bool learning;int stp_state;struct phy_device phydev;