net: dsa: mv88e6xxx: call vtu_getnext directly in db load/purge
authorVivien Didelot <vivien.didelot@gmail.com>
Thu, 1 Aug 2019 18:36:35 +0000 (14:36 -0400)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Aug 2019 20:43:09 +0000 (16:43 -0400)
mv88e6xxx_vtu_getnext is simple enough to call it directly in the
mv88e6xxx_port_db_load_purge function and explicit the return code
expected by switchdev for software VLANs when an hardware VLAN does
not exist.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/chip.c

index c825fa3477fa8e4e658f2142642fb321af2e3820..42ab57dbc790d277198ddcf09d0f51ec5c836cc6 100644 (file)
@@ -1540,23 +1540,36 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
                                        const unsigned char *addr, u16 vid,
                                        u8 state)
 {
-       struct mv88e6xxx_vtu_entry vlan;
        struct mv88e6xxx_atu_entry entry;
+       struct mv88e6xxx_vtu_entry vlan;
+       u16 fid;
        int err;
 
        /* Null VLAN ID corresponds to the port private database */
-       if (vid == 0)
-               err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
-       else
-               err = mv88e6xxx_vtu_get(chip, vid, &vlan, false);
-       if (err)
-               return err;
+       if (vid == 0) {
+               err = mv88e6xxx_port_get_fid(chip, port, &fid);
+               if (err)
+                       return err;
+       } else {
+               vlan.vid = vid - 1;
+               vlan.valid = false;
+
+               err = mv88e6xxx_vtu_getnext(chip, &vlan);
+               if (err)
+                       return err;
+
+               /* switchdev expects -EOPNOTSUPP to honor software VLANs */
+               if (vlan.vid != vid || !vlan.valid)
+                       return -EOPNOTSUPP;
+
+               fid = vlan.fid;
+       }
 
        entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED;
        ether_addr_copy(entry.mac, addr);
        eth_addr_dec(entry.mac);
 
-       err = mv88e6xxx_g1_atu_getnext(chip, vlan.fid, &entry);
+       err = mv88e6xxx_g1_atu_getnext(chip, fid, &entry);
        if (err)
                return err;
 
@@ -1577,7 +1590,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port,
                entry.state = state;
        }
 
-       return mv88e6xxx_g1_atu_loadpurge(chip, vlan.fid, &entry);
+       return mv88e6xxx_g1_atu_loadpurge(chip, fid, &entry);
 }
 
 static int mv88e6xxx_port_add_broadcast(struct mv88e6xxx_chip *chip, int port,