diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2022-02-23 17:00:49 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-02-25 08:31:43 +0300 |
commit | dedd6a009f4191989bee83c1faf66728648a223f (patch) | |
tree | 125b63ccd396fec13f6a6874b3e6bbd3a6b10ac6 /drivers/net/dsa/mv88e6xxx | |
parent | b99dbdf00bc13ea6aff9c9bba8919a15c2a510df (diff) | |
download | linux-dedd6a009f4191989bee83c1faf66728648a223f.tar.xz |
net: dsa: create a dsa_lag structure
The main purpose of this change is to create a data structure for a LAG
as seen by DSA. This is similar to what we have for bridging - we pass a
copy of this structure by value to ->port_lag_join and ->port_lag_leave.
For now we keep the lag_dev, id and a reference count in it. Future
patches will add a list of FDB entries for the LAG (these also need to
be refcounted to work properly).
The LAG structure is created using dsa_port_lag_create() and destroyed
using dsa_port_lag_destroy(), just like we have for bridging.
Because now, the dsa_lag itself is refcounted, we can simplify
dsa_lag_map() and dsa_lag_unmap(). These functions need to keep a LAG in
the dst->lags array only as long as at least one port uses it. The
refcounting logic inside those functions can be removed now - they are
called only when we should perform the operation.
dsa_lag_dev() is renamed to dsa_lag_by_id() and now returns the dsa_lag
structure instead of the lag_dev net_device.
dsa_lag_foreach_port() now takes the dsa_lag structure as argument.
dst->lags holds an array of dsa_lag structures.
dsa_lag_map() now also saves the dsa_lag->id value, so that linear
walking of dst->lags in drivers using dsa_lag_id() is no longer
necessary. They can just look at lag.id.
dsa_port_lag_id_get() is a helper, similar to dsa_port_bridge_num_get(),
which can be used by drivers to get the LAG ID assigned by DSA to a
given port.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 60 |
1 files changed, 29 insertions, 31 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 8868110fcc9c..1b9a20bf1bd6 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1625,7 +1625,7 @@ static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port) ds = dsa_switch_find(dst->index, dev); dp = ds ? dsa_to_port(ds, port) : NULL; - if (dp && dp->lag_dev) { + if (dp && dp->lag) { /* As the PVT is used to limit flooding of * FORWARD frames, which use the LAG ID as the * source port, we must translate dev/port to @@ -1634,7 +1634,7 @@ static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port) * (zero-based). */ dev = MV88E6XXX_G2_PVT_ADDR_DEV_TRUNK; - port = dsa_lag_id(dst, dp->lag_dev) - 1; + port = dsa_port_lag_id_get(dp) - 1; } } @@ -1672,7 +1672,7 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) struct mv88e6xxx_chip *chip = ds->priv; int err; - if (dsa_to_port(ds, port)->lag_dev) + if (dsa_to_port(ds, port)->lag) /* Hardware is incapable of fast-aging a LAG through a * regular ATU move operation. Until we have something * more fancy in place this is a no-op. @@ -6176,21 +6176,20 @@ out: } static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds, - struct net_device *lag_dev, + struct dsa_lag lag, struct netdev_lag_upper_info *info) { struct mv88e6xxx_chip *chip = ds->priv; struct dsa_port *dp; - int id, members = 0; + int members = 0; if (!mv88e6xxx_has_lag(chip)) return false; - id = dsa_lag_id(ds->dst, lag_dev); - if (id <= 0 || id > ds->num_lag_ids) + if (!lag.id) return false; - dsa_lag_foreach_port(dp, ds->dst, lag_dev) + dsa_lag_foreach_port(dp, ds->dst, &lag) /* Includes the port joining the LAG */ members++; @@ -6210,8 +6209,7 @@ static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds, return true; } -static int mv88e6xxx_lag_sync_map(struct dsa_switch *ds, - struct net_device *lag_dev) +static int mv88e6xxx_lag_sync_map(struct dsa_switch *ds, struct dsa_lag lag) { struct mv88e6xxx_chip *chip = ds->priv; struct dsa_port *dp; @@ -6219,13 +6217,13 @@ static int mv88e6xxx_lag_sync_map(struct dsa_switch *ds, int id; /* DSA LAG IDs are one-based, hardware is zero-based */ - id = dsa_lag_id(ds->dst, lag_dev) - 1; + id = lag.id - 1; /* Build the map of all ports to distribute flows destined for * this LAG. This can be either a local user port, or a DSA * port if the LAG port is on a remote chip. */ - dsa_lag_foreach_port(dp, ds->dst, lag_dev) + dsa_lag_foreach_port(dp, ds->dst, &lag) map |= BIT(dsa_towards_port(ds, dp->ds->index, dp->index)); return mv88e6xxx_g2_trunk_mapping_write(chip, id, map); @@ -6269,9 +6267,9 @@ static void mv88e6xxx_lag_set_port_mask(u16 *mask, int port, static int mv88e6xxx_lag_sync_masks(struct dsa_switch *ds) { struct mv88e6xxx_chip *chip = ds->priv; - struct net_device *lag_dev; unsigned int id, num_tx; struct dsa_port *dp; + struct dsa_lag *lag; int i, err, nth; u16 mask[8]; u16 ivec; @@ -6281,7 +6279,7 @@ static int mv88e6xxx_lag_sync_masks(struct dsa_switch *ds) /* Disable all masks for ports that _are_ members of a LAG. */ dsa_switch_for_each_port(dp, ds) { - if (!dp->lag_dev) + if (!dp->lag) continue; ivec &= ~BIT(dp->index); @@ -6294,12 +6292,12 @@ static int mv88e6xxx_lag_sync_masks(struct dsa_switch *ds) * are in the Tx set. */ dsa_lags_foreach_id(id, ds->dst) { - lag_dev = dsa_lag_dev(ds->dst, id); - if (!lag_dev) + lag = dsa_lag_by_id(ds->dst, id); + if (!lag) continue; num_tx = 0; - dsa_lag_foreach_port(dp, ds->dst, lag_dev) { + dsa_lag_foreach_port(dp, ds->dst, lag) { if (dp->lag_tx_enabled) num_tx++; } @@ -6308,7 +6306,7 @@ static int mv88e6xxx_lag_sync_masks(struct dsa_switch *ds) continue; nth = 0; - dsa_lag_foreach_port(dp, ds->dst, lag_dev) { + dsa_lag_foreach_port(dp, ds->dst, lag) { if (!dp->lag_tx_enabled) continue; @@ -6330,14 +6328,14 @@ static int mv88e6xxx_lag_sync_masks(struct dsa_switch *ds) } static int mv88e6xxx_lag_sync_masks_map(struct dsa_switch *ds, - struct net_device *lag_dev) + struct dsa_lag lag) { int err; err = mv88e6xxx_lag_sync_masks(ds); if (!err) - err = mv88e6xxx_lag_sync_map(ds, lag_dev); + err = mv88e6xxx_lag_sync_map(ds, lag); return err; } @@ -6354,17 +6352,17 @@ static int mv88e6xxx_port_lag_change(struct dsa_switch *ds, int port) } static int mv88e6xxx_port_lag_join(struct dsa_switch *ds, int port, - struct net_device *lag_dev, + struct dsa_lag lag, struct netdev_lag_upper_info *info) { struct mv88e6xxx_chip *chip = ds->priv; int err, id; - if (!mv88e6xxx_lag_can_offload(ds, lag_dev, info)) + if (!mv88e6xxx_lag_can_offload(ds, lag, info)) return -EOPNOTSUPP; /* DSA LAG IDs are one-based */ - id = dsa_lag_id(ds->dst, lag_dev) - 1; + id = lag.id - 1; mv88e6xxx_reg_lock(chip); @@ -6372,7 +6370,7 @@ static int mv88e6xxx_port_lag_join(struct dsa_switch *ds, int port, if (err) goto err_unlock; - err = mv88e6xxx_lag_sync_masks_map(ds, lag_dev); + err = mv88e6xxx_lag_sync_masks_map(ds, lag); if (err) goto err_clear_trunk; @@ -6387,13 +6385,13 @@ err_unlock: } static int mv88e6xxx_port_lag_leave(struct dsa_switch *ds, int port, - struct net_device *lag_dev) + struct dsa_lag lag) { struct mv88e6xxx_chip *chip = ds->priv; int err_sync, err_trunk; mv88e6xxx_reg_lock(chip); - err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag_dev); + err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag); err_trunk = mv88e6xxx_port_set_trunk(chip, port, false, 0); mv88e6xxx_reg_unlock(chip); return err_sync ? : err_trunk; @@ -6412,18 +6410,18 @@ static int mv88e6xxx_crosschip_lag_change(struct dsa_switch *ds, int sw_index, } static int mv88e6xxx_crosschip_lag_join(struct dsa_switch *ds, int sw_index, - int port, struct net_device *lag_dev, + int port, struct dsa_lag lag, struct netdev_lag_upper_info *info) { struct mv88e6xxx_chip *chip = ds->priv; int err; - if (!mv88e6xxx_lag_can_offload(ds, lag_dev, info)) + if (!mv88e6xxx_lag_can_offload(ds, lag, info)) return -EOPNOTSUPP; mv88e6xxx_reg_lock(chip); - err = mv88e6xxx_lag_sync_masks_map(ds, lag_dev); + err = mv88e6xxx_lag_sync_masks_map(ds, lag); if (err) goto unlock; @@ -6435,13 +6433,13 @@ unlock: } static int mv88e6xxx_crosschip_lag_leave(struct dsa_switch *ds, int sw_index, - int port, struct net_device *lag_dev) + int port, struct dsa_lag lag) { struct mv88e6xxx_chip *chip = ds->priv; int err_sync, err_pvt; mv88e6xxx_reg_lock(chip); - err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag_dev); + err_sync = mv88e6xxx_lag_sync_masks_map(ds, lag); err_pvt = mv88e6xxx_pvt_map(chip, sw_index, port); mv88e6xxx_reg_unlock(chip); return err_sync ? : err_pvt; |