mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 02:19:51 +00:00
net: dsa: microchip: fix bridging with more than two member ports
Commitb3612ccdf2
("net: dsa: microchip: implement multi-bridge support") plugged a packet leak between ports that were members of different bridges. Unfortunately, this broke another use case, namely that of more than two ports that are members of the same bridge. After that commit, when a port is added to a bridge, hardware bridging between other member ports of that bridge will be cleared, preventing packet exchange between them. Fix by ensuring that the Port VLAN Membership bitmap includes any existing ports in the bridge, not just the port being added. Fixes:b3612ccdf2
("net: dsa: microchip: implement multi-bridge support") Signed-off-by: Svenning Sørensen <sss@secomea.com> Tested-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5486f5bf79
commit
3d00827a90
1 changed files with 23 additions and 3 deletions
|
@ -26,7 +26,7 @@ void ksz_update_port_member(struct ksz_device *dev, int port)
|
|||
struct dsa_switch *ds = dev->ds;
|
||||
u8 port_member = 0, cpu_port;
|
||||
const struct dsa_port *dp;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
if (!dsa_is_user_port(ds, port))
|
||||
return;
|
||||
|
@ -45,13 +45,33 @@ void ksz_update_port_member(struct ksz_device *dev, int port)
|
|||
continue;
|
||||
if (!dsa_port_bridge_same(dp, other_dp))
|
||||
continue;
|
||||
if (other_p->stp_state != BR_STATE_FORWARDING)
|
||||
continue;
|
||||
|
||||
if (other_p->stp_state == BR_STATE_FORWARDING &&
|
||||
p->stp_state == BR_STATE_FORWARDING) {
|
||||
if (p->stp_state == BR_STATE_FORWARDING) {
|
||||
val |= BIT(port);
|
||||
port_member |= BIT(i);
|
||||
}
|
||||
|
||||
/* Retain port [i]'s relationship to other ports than [port] */
|
||||
for (j = 0; j < ds->num_ports; j++) {
|
||||
const struct dsa_port *third_dp;
|
||||
struct ksz_port *third_p;
|
||||
|
||||
if (j == i)
|
||||
continue;
|
||||
if (j == port)
|
||||
continue;
|
||||
if (!dsa_is_user_port(ds, j))
|
||||
continue;
|
||||
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))
|
||||
val |= BIT(j);
|
||||
}
|
||||
|
||||
dev->dev_ops->cfg_port_member(dev, i, val | cpu_port);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue