net: dsa: mv88e6xxx: Add FID map cache
authorAryan Srivastava <aryan.srivastava@alliedtelesis.co.nz>
Sun, 6 Oct 2024 21:29:05 +0000 (10:29 +1300)
committerJakub Kicinski <kuba@kernel.org>
Tue, 8 Oct 2024 22:30:55 +0000 (15:30 -0700)
Add a cached FID bitmap. This mitigates the need to walk all VTU entries
to find the next free FID.

When flushing the VTU (during init), zero the FID bitmap. Use and
manipulate this bitmap from now on, instead of reading HW for the FID
map.

The repeated VTU walks are costly and can take ~40 mins if ~4000 vlans
are added. Caching the FID map reduces this time to <2 mins.

Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20241006212905.3142976-1-aryan.srivastava@alliedtelesis.co.nz
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/devlink.c
drivers/net/dsa/mv88e6xxx/global1_vtu.c

index ddc832e33f4bfb9590f954bc1e3221cb30735477..f68233d24f32beb50b30673fbd226a3d6f9c4b0d 100644 (file)
@@ -1930,36 +1930,9 @@ static int mv88e6xxx_vtu_loadpurge(struct mv88e6xxx_chip *chip,
        return chip->info->ops->vtu_loadpurge(chip, entry);
 }
 
-static int mv88e6xxx_fid_map_vlan(struct mv88e6xxx_chip *chip,
-                                 const struct mv88e6xxx_vtu_entry *entry,
-                                 void *_fid_bitmap)
-{
-       unsigned long *fid_bitmap = _fid_bitmap;
-
-       set_bit(entry->fid, fid_bitmap);
-       return 0;
-}
-
-int mv88e6xxx_fid_map(struct mv88e6xxx_chip *chip, unsigned long *fid_bitmap)
-{
-       bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
-
-       /* Every FID has an associated VID, so walking the VTU
-        * will discover the full set of FIDs in use.
-        */
-       return mv88e6xxx_vtu_walk(chip, mv88e6xxx_fid_map_vlan, fid_bitmap);
-}
-
 static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *chip, u16 *fid)
 {
-       DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
-       int err;
-
-       err = mv88e6xxx_fid_map(chip, fid_bitmap);
-       if (err)
-               return err;
-
-       *fid = find_first_zero_bit(fid_bitmap, MV88E6XXX_N_FID);
+       *fid = find_first_zero_bit(chip->fid_bitmap, MV88E6XXX_N_FID);
        if (unlikely(*fid >= mv88e6xxx_num_databases(chip)))
                return -ENOSPC;
 
@@ -2666,6 +2639,9 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port,
                         port, vid);
        }
 
+       /* Record FID used in SW FID map */
+       bitmap_set(chip->fid_bitmap, vlan.fid, 1);
+
        return 0;
 }
 
@@ -2771,6 +2747,9 @@ static int mv88e6xxx_port_vlan_leave(struct mv88e6xxx_chip *chip,
                err = mv88e6xxx_mst_put(chip, vlan.sid);
                if (err)
                        return err;
+
+               /* Record FID freed in SW FID map */
+               bitmap_clear(chip->fid_bitmap, vlan.fid, 1);
        }
 
        return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false);
index 8b07e7d83589a0737fd13785edb95885fe23b5a1..00aa59857b64fccea9cd78621cf233fa24ec95cc 100644 (file)
@@ -440,6 +440,9 @@ struct mv88e6xxx_chip {
 
        /* Bridge MST to SID mappings */
        struct list_head msts;
+
+       /* FID map */
+       DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
 };
 
 struct mv88e6xxx_bus_ops {
@@ -843,6 +846,4 @@ int mv88e6xxx_vtu_walk(struct mv88e6xxx_chip *chip,
                                 void *priv),
                       void *priv);
 
-int mv88e6xxx_fid_map(struct mv88e6xxx_chip *chip, unsigned long *bitmap);
-
 #endif /* _MV88E6XXX_CHIP_H */
index a08dab75e0c0c1b227842d09302161a77b34e762..ef3643bc43dbba819f31d662f81b3f6958ef8eff 100644 (file)
@@ -374,7 +374,6 @@ static int mv88e6xxx_region_atu_snapshot(struct devlink *dl,
                                         u8 **data)
 {
        struct dsa_switch *ds = dsa_devlink_to_ds(dl);
-       DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
        struct mv88e6xxx_devlink_atu_entry *table;
        struct mv88e6xxx_chip *chip = ds->priv;
        int fid = -1, count, err;
@@ -392,14 +391,8 @@ static int mv88e6xxx_region_atu_snapshot(struct devlink *dl,
 
        mv88e6xxx_reg_lock(chip);
 
-       err = mv88e6xxx_fid_map(chip, fid_bitmap);
-       if (err) {
-               kfree(table);
-               goto out;
-       }
-
        while (1) {
-               fid = find_next_bit(fid_bitmap, MV88E6XXX_N_FID, fid + 1);
+               fid = find_next_bit(chip->fid_bitmap, MV88E6XXX_N_FID, fid + 1);
                if (fid == MV88E6XXX_N_FID)
                        break;
 
index bcfb4a812055cbb5640f59f476acf6b85203933c..b524f27a2f0df0fba225a5621abb630f9b8f62ff 100644 (file)
@@ -471,6 +471,9 @@ int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
 {
        int err;
 
+       /* As part of the VTU flush, refresh FID map */
+       bitmap_zero(chip->fid_bitmap, MV88E6XXX_N_FID);
+
        err = mv88e6xxx_g1_vtu_op_wait(chip);
        if (err)
                return err;