From b80af659699d212cf8cec6593f6551905c4ae86f Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 6 Feb 2021 00:02:14 +0200 Subject: [PATCH] net: mscc: ocelot: set up the bonding mask in a way that avoids a net_device Since this code should be called from pure switchdev as well as from DSA, we must find a way to determine the bonding mask not by looking directly at the net_device lowers of the bonding interface, since those could have different private structures. We keep a pointer to the bonding upper interface, if present, in struct ocelot_port. Then the bonding mask becomes the bitwise OR of all ports that have the same bonding upper interface. This adds a duplication of functionality with the current "lags" array, but the duplication will be short-lived, since further patches will remove the latter completely. Signed-off-by: Vladimir Oltean Reviewed-by: Alexandre Belloni Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mscc/ocelot.c | 29 ++++++++++++++++++++++------- include/soc/mscc/ocelot.h | 2 ++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index ef3f10f1e54f..127beedcccde 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -889,6 +889,24 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port, } EXPORT_SYMBOL(ocelot_get_ts_info); +static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond) +{ + u32 mask = 0; + int port; + + for (port = 0; port < ocelot->num_phys_ports; port++) { + struct ocelot_port *ocelot_port = ocelot->ports[port]; + + if (!ocelot_port) + continue; + + if (ocelot_port->bond == bond) + mask |= BIT(port); + } + + return mask; +} + static u32 ocelot_get_dsa_8021q_cpu_mask(struct ocelot *ocelot) { u32 mask = 0; @@ -1319,20 +1337,15 @@ int ocelot_port_lag_join(struct ocelot *ocelot, int port, struct net_device *bond, struct netdev_lag_upper_info *info) { - struct net_device *ndev; u32 bond_mask = 0; int lag, lp; if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) return -EOPNOTSUPP; - rcu_read_lock(); - for_each_netdev_in_bond_rcu(bond, ndev) { - struct ocelot_port_private *priv = netdev_priv(ndev); + ocelot->ports[port]->bond = bond; - bond_mask |= BIT(priv->chip_port); - } - rcu_read_unlock(); + bond_mask = ocelot_get_bond_mask(ocelot, bond); lp = __ffs(bond_mask); @@ -1366,6 +1379,8 @@ void ocelot_port_lag_leave(struct ocelot *ocelot, int port, u32 port_cfg; int i; + ocelot->ports[port]->bond = NULL; + /* Remove port from any lag */ for (i = 0; i < ocelot->num_phys_ports; i++) ocelot->lags[i] &= ~BIT(port); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 6a61c499a30d..e36a1ed29c01 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -611,6 +611,8 @@ struct ocelot_port { u8 *xmit_template; bool is_dsa_8021q_cpu; + + struct net_device *bond; }; struct ocelot { -- 2.11.0