@@ -894,40 +894,18 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond)
return bond_mask;
}
-void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)
+static void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot)
{
- u32 port_cfg;
- int p;
-
- if (!(BIT(port) & ocelot->bridge_mask))
- return;
-
- port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, port);
-
- switch (state) {
- case BR_STATE_FORWARDING:
- ocelot->bridge_fwd_mask |= BIT(port);
- fallthrough;
- case BR_STATE_LEARNING:
- port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA;
- break;
-
- default:
- port_cfg &= ~ANA_PORT_PORT_CFG_LEARN_ENA;
- ocelot->bridge_fwd_mask &= ~BIT(port);
- break;
- }
-
- ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG, port);
+ int port;
/* Apply FWD mask. The loop is needed to add/remove the current port as
* a source for the other ports. If the source port is in a bond, then
* all the other ports from that bond need to be removed from this
* source port's forwarding mask.
*/
- for (p = 0; p < ocelot->num_phys_ports; p++) {
- if (ocelot->bridge_fwd_mask & BIT(p)) {
- unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(p);
+ for (port = 0; port < ocelot->num_phys_ports; port++) {
+ if (ocelot->bridge_fwd_mask & BIT(port)) {
+ unsigned long mask = ocelot->bridge_fwd_mask & ~BIT(port);
int lag;
for (lag = 0; lag < ocelot->num_phys_ports; lag++) {
@@ -936,20 +914,48 @@ void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)
if (!bond_mask)
continue;
- if (bond_mask & BIT(p)) {
+ if (bond_mask & BIT(port)) {
mask &= ~bond_mask;
break;
}
}
ocelot_write_rix(ocelot, mask,
- ANA_PGID_PGID, PGID_SRC + p);
+ ANA_PGID_PGID, PGID_SRC + port);
} else {
ocelot_write_rix(ocelot, 0,
- ANA_PGID_PGID, PGID_SRC + p);
+ ANA_PGID_PGID, PGID_SRC + port);
}
}
}
+
+void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)
+{
+ u32 port_cfg;
+
+ if (!(BIT(port) & ocelot->bridge_mask))
+ return;
+
+ port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, port);
+
+ switch (state) {
+ case BR_STATE_FORWARDING:
+ ocelot->bridge_fwd_mask |= BIT(port);
+ fallthrough;
+ case BR_STATE_LEARNING:
+ port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA;
+ break;
+
+ default:
+ port_cfg &= ~ANA_PORT_PORT_CFG_LEARN_ENA;
+ ocelot->bridge_fwd_mask &= ~BIT(port);
+ break;
+ }
+
+ ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG, port);
+
+ ocelot_apply_bridge_fwd_mask(ocelot);
+}
EXPORT_SYMBOL(ocelot_bridge_stp_state_set);
void ocelot_set_ageing_time(struct ocelot *ocelot, unsigned int msecs)
@@ -1300,6 +1306,7 @@ int ocelot_port_lag_join(struct ocelot *ocelot, int port,
}
ocelot_setup_lag(ocelot, lag);
+ ocelot_apply_bridge_fwd_mask(ocelot);
ocelot_set_aggr_pgids(ocelot);
return 0;
@@ -1335,6 +1342,7 @@ void ocelot_port_lag_leave(struct ocelot *ocelot, int port,
ocelot_write_gix(ocelot, port_cfg | ANA_PORT_PORT_CFG_PORTID_VAL(port),
ANA_PORT_PORT_CFG, port);
+ ocelot_apply_bridge_fwd_mask(ocelot);
ocelot_set_aggr_pgids(ocelot);
}
EXPORT_SYMBOL(ocelot_port_lag_leave);