[v8,net-next,11/12] net: dsa: mv88e6xxx: add blackhole ATU entries
Commit Message
Blackhole FDB entries can now be added, deleted or replaced in the
driver ATU.
Signed-off-by: Hans J. Schultz <netdev@kapio-technology.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 62 +++++++++++++++++++++++++++++---
1 file changed, 58 insertions(+), 4 deletions(-)
Comments
On Tue, Oct 18, 2022 at 06:56:18PM +0200, Hans J. Schultz wrote:
> Blackhole FDB entries can now be added, deleted or replaced in the
> driver ATU.
Why is this necessary, why is it useful?
>
> Signed-off-by: Hans J. Schultz <netdev@kapio-technology.com>
> ---
> static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
> const unsigned char *addr, u16 vid,
> u16 fdb_flags, struct dsa_db db)
> @@ -2742,9 +2794,10 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
> struct mv88e6xxx_chip *chip = ds->priv;
> int err;
>
> - /* Ignore entries with flags set */
> - if (fdb_flags)
> + if (fdb_flags & DSA_FDB_FLAG_LOCKED)
> return 0;
I don't understand this. If no driver looks at DSA_FDB_FLAG_LOCKED
(not even mv88e6xxx, up until the end of the series), then why was it
propagated all the way in the first place?
> + if (fdb_flags & DSA_FDB_FLAG_BLACKHOLE)
> + return mv88e6xxx_blackhole_fdb_add(ds, addr, vid);
>
> if (mv88e6xxx_port_is_locked(chip, port))
> mv88e6xxx_atu_locked_entry_find_purge(ds, port, addr, vid);
> @@ -2765,9 +2818,10 @@ static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
> bool locked_found = false;
> int err = 0;
>
> - /* Ignore entries with flags set */
> - if (fdb_flags)
> + if (fdb_flags & DSA_FDB_FLAG_LOCKED)
> return 0;
> + if (fdb_flags & DSA_FDB_FLAG_BLACKHOLE)
> + return mv88e6xxx_blackhole_fdb_del(ds, addr, vid);
>
> if (mv88e6xxx_port_is_locked(chip, port))
> locked_found = mv88e6xxx_atu_locked_entry_find_purge(ds, port, addr, vid);
> --
> 2.34.1
>
@@ -2735,6 +2735,58 @@ static int mv88e6xxx_vlan_msti_set(struct dsa_switch *ds,
return err;
}
+static int mv88e6xxx_blackhole_fdb_loadpurge(struct dsa_switch *ds,
+ const unsigned char *addr, u16 vid, u8 state)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ struct mv88e6xxx_atu_entry entry;
+ struct mv88e6xxx_vtu_entry vlan;
+
+ u16 fid = 0;
+ int err;
+
+ if (vid == 0) {
+ fid = MV88E6XXX_FID_BRIDGED;
+ } else {
+ mv88e6xxx_reg_lock(chip);
+ err = mv88e6xxx_vtu_get(chip, vid, &vlan);
+ mv88e6xxx_reg_unlock(chip);
+ if (err)
+ return err;
+
+ /* switchdev expects -EOPNOTSUPP to honor software VLANs */
+ if (!vlan.valid)
+ return -EOPNOTSUPP;
+
+ fid = vlan.fid;
+ }
+
+ ether_addr_copy(entry.mac, addr);
+ entry.portvec = MV88E6XXX_G1_ATU_DATA_PORT_VECTOR_NO_EGRESS;
+ entry.state = state;
+ entry.trunk = false;
+
+ mv88e6xxx_reg_lock(chip);
+ err = mv88e6xxx_g1_atu_loadpurge(chip, fid, &entry);
+ mv88e6xxx_reg_unlock(chip);
+
+ return err;
+}
+
+static int mv88e6xxx_blackhole_fdb_add(struct dsa_switch *ds,
+ const unsigned char *addr, u16 vid)
+{
+ return mv88e6xxx_blackhole_fdb_loadpurge(ds, addr, vid,
+ MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC);
+}
+
+static int mv88e6xxx_blackhole_fdb_del(struct dsa_switch *ds,
+ const unsigned char *addr, u16 vid)
+{
+ return mv88e6xxx_blackhole_fdb_loadpurge(ds, addr, vid,
+ MV88E6XXX_G1_ATU_DATA_STATE_UC_UNUSED);
+}
+
static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
const unsigned char *addr, u16 vid,
u16 fdb_flags, struct dsa_db db)
@@ -2742,9 +2794,10 @@ static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
struct mv88e6xxx_chip *chip = ds->priv;
int err;
- /* Ignore entries with flags set */
- if (fdb_flags)
+ if (fdb_flags & DSA_FDB_FLAG_LOCKED)
return 0;
+ if (fdb_flags & DSA_FDB_FLAG_BLACKHOLE)
+ return mv88e6xxx_blackhole_fdb_add(ds, addr, vid);
if (mv88e6xxx_port_is_locked(chip, port))
mv88e6xxx_atu_locked_entry_find_purge(ds, port, addr, vid);
@@ -2765,9 +2818,10 @@ static int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
bool locked_found = false;
int err = 0;
- /* Ignore entries with flags set */
- if (fdb_flags)
+ if (fdb_flags & DSA_FDB_FLAG_LOCKED)
return 0;
+ if (fdb_flags & DSA_FDB_FLAG_BLACKHOLE)
+ return mv88e6xxx_blackhole_fdb_del(ds, addr, vid);
if (mv88e6xxx_port_is_locked(chip, port))
locked_found = mv88e6xxx_atu_locked_entry_find_purge(ds, port, addr, vid);