net: dsa: mv88e6xxx: Offload bridge learning flag
Allow a user to control automatic learning per port. Many chips have an explicit "LearningDisable"-bit that can be used for this, but we opt for setting/clearing the PAV instead, as it works on all devices at least as far back as 6083. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
7b9f16fe40
Коммит
041bd545e1
|
@ -2740,15 +2740,20 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Port Association Vector: when learning source addresses
|
||||
* of packets, add the address to the address database using
|
||||
* a port bitmap that has only the bit for this port set and
|
||||
* the other bits clear.
|
||||
/* Port Association Vector: disable automatic address learning
|
||||
* on all user ports since they start out in standalone
|
||||
* mode. When joining a bridge, learning will be configured to
|
||||
* match the bridge port settings. Enable learning on all
|
||||
* DSA/CPU ports. NOTE: FROM_CPU frames always bypass the
|
||||
* learning process.
|
||||
*
|
||||
* Disable HoldAt1, IntOnAgeOut, LockedPort, IgnoreWrongData,
|
||||
* and RefreshLocked. I.e. setup standard automatic learning.
|
||||
*/
|
||||
reg = 1 << port;
|
||||
/* Disable learning for CPU port */
|
||||
if (dsa_is_cpu_port(ds, port))
|
||||
if (dsa_is_user_port(ds, port))
|
||||
reg = 0;
|
||||
else
|
||||
reg = 1 << port;
|
||||
|
||||
err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
|
||||
reg);
|
||||
|
@ -5604,7 +5609,7 @@ static int mv88e6xxx_port_pre_bridge_flags(struct dsa_switch *ds, int port,
|
|||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
const struct mv88e6xxx_ops *ops;
|
||||
|
||||
if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD))
|
||||
if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD))
|
||||
return -EINVAL;
|
||||
|
||||
ops = chip->info->ops;
|
||||
|
@ -5623,10 +5628,23 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
|
|||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
bool do_fast_age = false;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
|
||||
if (flags.mask & BR_LEARNING) {
|
||||
bool learning = !!(flags.val & BR_LEARNING);
|
||||
u16 pav = learning ? (1 << port) : 0;
|
||||
|
||||
err = mv88e6xxx_port_set_assoc_vector(chip, port, pav);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (!learning)
|
||||
do_fast_age = true;
|
||||
}
|
||||
|
||||
if (flags.mask & BR_FLOOD) {
|
||||
bool unicast = !!(flags.val & BR_FLOOD);
|
||||
|
||||
|
@ -5648,6 +5666,9 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,
|
|||
out:
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
if (do_fast_age)
|
||||
mv88e6xxx_port_fast_age(ds, port);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -1309,6 +1309,27 @@ int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
|
|||
0x0001);
|
||||
}
|
||||
|
||||
/* Offset 0x0B: Port Association Vector */
|
||||
|
||||
int mv88e6xxx_port_set_assoc_vector(struct mv88e6xxx_chip *chip, int port,
|
||||
u16 pav)
|
||||
{
|
||||
u16 reg, mask;
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
|
||||
®);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mask = mv88e6xxx_port_mask(chip);
|
||||
reg &= ~mask;
|
||||
reg |= pav & mask;
|
||||
|
||||
return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ASSOC_VECTOR,
|
||||
reg);
|
||||
}
|
||||
|
||||
/* Offset 0x0C: Port ATU Control */
|
||||
|
||||
int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
|
||||
|
|
|
@ -407,6 +407,8 @@ int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
|
|||
size_t size);
|
||||
int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
|
||||
int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
|
||||
int mv88e6xxx_port_set_assoc_vector(struct mv88e6xxx_chip *chip, int port,
|
||||
u16 pav);
|
||||
int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
|
||||
u8 out);
|
||||
int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
|
||||
|
|
Загрузка…
Ссылка в новой задаче