On 08/12/2020 14:07:56+0200, Vladimir Oltean wrote:
> Applying the bridge forwarding mask currently is done only on the STP
> state changes for any port. But it depends on both STP state changes,
> and bonding interface state changes. Export the bit that recalculates
> the forwarding mask so that it could be reused, and call it when a port
> starts and stops offloading a bonding interface.
> 
> Signed-off-by: Vladimir Oltean <vladimir.olt...@nxp.com>
Reviewed-by: Alexandre Belloni <alexandre.bell...@bootlin.com>

> ---
>  drivers/net/ethernet/mscc/ocelot.c | 68 +++++++++++++++++-------------
>  1 file changed, 38 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mscc/ocelot.c 
> b/drivers/net/ethernet/mscc/ocelot.c
> index c3c6682e6e79..ee0fcee8e09a 100644
> --- a/drivers/net/ethernet/mscc/ocelot.c
> +++ b/drivers/net/ethernet/mscc/ocelot.c
> @@ -899,11 +899,45 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, 
> struct net_device *bond)
>       return bond_mask;
>  }
>  
> +static void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot)
> +{
> +     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 (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++) {
> +                             unsigned long bond_mask = ocelot->lags[lag];
> +
> +                             if (!bond_mask)
> +                                     continue;
> +
> +                             if (bond_mask & BIT(port)) {
> +                                     mask &= ~bond_mask;
> +                                     break;
> +                             }
> +                     }
> +
> +                     ocelot_write_rix(ocelot, mask,
> +                                      ANA_PGID_PGID, PGID_SRC + port);
> +             } else {
> +                     ocelot_write_rix(ocelot, 0,
> +                                      ANA_PGID_PGID, PGID_SRC + port);
> +             }
> +     }
> +}
> +
>  void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state)
>  {
>       struct ocelot_port *ocelot_port = ocelot->ports[port];
>       u32 port_cfg;
> -     int p;
>  
>       if (!(BIT(port) & ocelot->bridge_mask))
>               return;
> @@ -927,35 +961,7 @@ void ocelot_bridge_stp_state_set(struct ocelot *ocelot, 
> int port, u8 state)
>  
>       ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG, 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);
> -                     int lag;
> -
> -                     for (lag = 0; lag < ocelot->num_phys_ports; lag++) {
> -                             unsigned long bond_mask = ocelot->lags[lag];
> -
> -                             if (!bond_mask)
> -                                     continue;
> -
> -                             if (bond_mask & BIT(p)) {
> -                                     mask &= ~bond_mask;
> -                                     break;
> -                             }
> -                     }
> -
> -                     ocelot_write_rix(ocelot, mask,
> -                                      ANA_PGID_PGID, PGID_SRC + p);
> -             } else {
> -                     ocelot_write_rix(ocelot, 0,
> -                                      ANA_PGID_PGID, PGID_SRC + p);
> -             }
> -     }
> +     ocelot_apply_bridge_fwd_mask(ocelot);
>  }
>  EXPORT_SYMBOL(ocelot_bridge_stp_state_set);
>  
> @@ -1315,6 +1321,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;
> @@ -1350,6 +1357,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);
> -- 
> 2.25.1
> 

-- 
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

Reply via email to