From 428d720c7f90715aa535b42f24cbe0293966ec15 Mon Sep 17 00:00:00 2001 From: Etienne Champetier Date: Mon, 30 Jan 2023 23:43:00 +0200 Subject: kernel: backport some mv88e6xxx devlink patches This should help debug mv88e6xxx issues Signed-off-by: Etienne Champetier --- ...sa-mv88e6xxx-Export-VTU-as-devlink-region.patch | 191 +++++++++++++++++++++ ...8e6xxx-Add-helper-to-get-a-chip-s-max_vid.patch | 153 +++++++++++++++++ ...8e6xxx-Fix-off-by-one-in-VTU-devlink-regi.patch | 30 ++++ 3 files changed, 374 insertions(+) create mode 100644 target/linux/generic/backport-5.10/890-v5.11-net-dsa-mv88e6xxx-Export-VTU-as-devlink-region.patch create mode 100644 target/linux/generic/backport-5.10/891-v5.11-net-dsa-mv88e6xxx-Add-helper-to-get-a-chip-s-max_vid.patch create mode 100644 target/linux/generic/backport-5.10/891-v5.13-net-dsa-mv88e6xxx-Fix-off-by-one-in-VTU-devlink-regi.patch (limited to 'target') diff --git a/target/linux/generic/backport-5.10/890-v5.11-net-dsa-mv88e6xxx-Export-VTU-as-devlink-region.patch b/target/linux/generic/backport-5.10/890-v5.11-net-dsa-mv88e6xxx-Export-VTU-as-devlink-region.patch new file mode 100644 index 0000000000..a753be340d --- /dev/null +++ b/target/linux/generic/backport-5.10/890-v5.11-net-dsa-mv88e6xxx-Export-VTU-as-devlink-region.patch @@ -0,0 +1,191 @@ +From ca4d632aef031c7946c42a6eb873d24ab6474f17 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Mon, 9 Nov 2020 09:29:27 +0100 +Subject: [PATCH] net: dsa: mv88e6xxx: Export VTU as devlink region + +Export the raw VTU data and related registers in a devlink region so +that it can be inspected from userspace and compared to the current +bridge configuration. + +Signed-off-by: Tobias Waldekranz +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20201109082927.8684-1-tobias@waldekranz.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.h | 1 + + drivers/net/dsa/mv88e6xxx/devlink.c | 105 +++++++++++++++++++++++- + drivers/net/dsa/mv88e6xxx/global1.h | 2 + + drivers/net/dsa/mv88e6xxx/global1_vtu.c | 4 +- + 4 files changed, 109 insertions(+), 3 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -246,6 +246,7 @@ enum mv88e6xxx_region_id { + MV88E6XXX_REGION_GLOBAL1 = 0, + MV88E6XXX_REGION_GLOBAL2, + MV88E6XXX_REGION_ATU, ++ MV88E6XXX_REGION_VTU, + + _MV88E6XXX_REGION_MAX, + }; +--- a/drivers/net/dsa/mv88e6xxx/devlink.c ++++ b/drivers/net/dsa/mv88e6xxx/devlink.c +@@ -417,6 +417,92 @@ out: + return err; + } + ++/** ++ * struct mv88e6xxx_devlink_vtu_entry - Devlink VTU entry ++ * @fid: Global1/2: FID and VLAN policy. ++ * @sid: Global1/3: SID, unknown filters and learning. ++ * @op: Global1/5: FID (old chipsets). ++ * @vid: Global1/6: VID, valid, and page. ++ * @data: Global1/7-9: Membership data and priority override. ++ * @resvd: Reserved. Also happens to align the size to 16B. ++ * ++ * The VTU entry format varies between chipset generations, the ++ * descriptions above represent the superset of all possible ++ * information, not all fields are valid on all devices. Since this is ++ * a low-level debug interface, copy all data verbatim and defer ++ * parsing to the consumer. ++ */ ++struct mv88e6xxx_devlink_vtu_entry { ++ u16 fid; ++ u16 sid; ++ u16 op; ++ u16 vid; ++ u16 data[3]; ++ u16 resvd; ++}; ++ ++static int mv88e6xxx_region_vtu_snapshot(struct devlink *dl, ++ const struct devlink_region_ops *ops, ++ struct netlink_ext_ack *extack, ++ u8 **data) ++{ ++ struct mv88e6xxx_devlink_vtu_entry *table, *entry; ++ struct dsa_switch *ds = dsa_devlink_to_ds(dl); ++ struct mv88e6xxx_chip *chip = ds->priv; ++ struct mv88e6xxx_vtu_entry vlan; ++ int err; ++ ++ table = kcalloc(chip->info->max_vid + 1, ++ sizeof(struct mv88e6xxx_devlink_vtu_entry), ++ GFP_KERNEL); ++ if (!table) ++ return -ENOMEM; ++ ++ entry = table; ++ vlan.vid = chip->info->max_vid; ++ vlan.valid = false; ++ ++ mv88e6xxx_reg_lock(chip); ++ ++ do { ++ err = mv88e6xxx_g1_vtu_getnext(chip, &vlan); ++ if (err) ++ break; ++ ++ if (!vlan.valid) ++ break; ++ ++ err = err ? : mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, ++ &entry->fid); ++ err = err ? : mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, ++ &entry->sid); ++ err = err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, ++ &entry->op); ++ err = err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, ++ &entry->vid); ++ err = err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1, ++ &entry->data[0]); ++ err = err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA2, ++ &entry->data[1]); ++ err = err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA3, ++ &entry->data[2]); ++ if (err) ++ break; ++ ++ entry++; ++ } while (vlan.vid < chip->info->max_vid); ++ ++ mv88e6xxx_reg_unlock(chip); ++ ++ if (err) { ++ kfree(table); ++ return err; ++ } ++ ++ *data = (u8 *)table; ++ return 0; ++} ++ + static int mv88e6xxx_region_port_snapshot(struct devlink_port *devlink_port, + const struct devlink_port_region_ops *ops, + struct netlink_ext_ack *extack, +@@ -475,6 +561,12 @@ static struct devlink_region_ops mv88e6x + .destructor = kfree, + }; + ++static struct devlink_region_ops mv88e6xxx_region_vtu_ops = { ++ .name = "vtu", ++ .snapshot = mv88e6xxx_region_vtu_snapshot, ++ .destructor = kfree, ++}; ++ + static const struct devlink_port_region_ops mv88e6xxx_region_port_ops = { + .name = "port", + .snapshot = mv88e6xxx_region_port_snapshot, +@@ -498,6 +590,10 @@ static struct mv88e6xxx_region mv88e6xxx + .ops = &mv88e6xxx_region_atu_ops + /* calculated at runtime */ + }, ++ [MV88E6XXX_REGION_VTU] = { ++ .ops = &mv88e6xxx_region_vtu_ops ++ /* calculated at runtime */ ++ }, + }; + + static void +@@ -576,9 +672,16 @@ static int mv88e6xxx_setup_devlink_regio + ops = mv88e6xxx_regions[i].ops; + size = mv88e6xxx_regions[i].size; + +- if (i == MV88E6XXX_REGION_ATU) ++ switch (i) { ++ case MV88E6XXX_REGION_ATU: + size = mv88e6xxx_num_databases(chip) * + sizeof(struct mv88e6xxx_devlink_atu_entry); ++ break; ++ case MV88E6XXX_REGION_VTU: ++ size = chip->info->max_vid * ++ sizeof(struct mv88e6xxx_devlink_vtu_entry); ++ break; ++ } + + region = dsa_devlink_region_create(ds, ops, 1, size); + if (IS_ERR(region)) +--- a/drivers/net/dsa/mv88e6xxx/global1.h ++++ b/drivers/net/dsa/mv88e6xxx/global1.h +@@ -330,6 +330,8 @@ void mv88e6xxx_g1_atu_prob_irq_free(stru + int mv88e6165_g1_atu_get_hash(struct mv88e6xxx_chip *chip, u8 *hash); + int mv88e6165_g1_atu_set_hash(struct mv88e6xxx_chip *chip, u8 hash); + ++int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip, ++ struct mv88e6xxx_vtu_entry *entry); + int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_vtu_entry *entry); + int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, +--- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c ++++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c +@@ -307,8 +307,8 @@ static int mv88e6xxx_g1_vtu_stu_get(stru + return 0; + } + +-static int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip, +- struct mv88e6xxx_vtu_entry *entry) ++int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip, ++ struct mv88e6xxx_vtu_entry *entry) + { + int err; + diff --git a/target/linux/generic/backport-5.10/891-v5.11-net-dsa-mv88e6xxx-Add-helper-to-get-a-chip-s-max_vid.patch b/target/linux/generic/backport-5.10/891-v5.11-net-dsa-mv88e6xxx-Add-helper-to-get-a-chip-s-max_vid.patch new file mode 100644 index 0000000000..c24f9854ff --- /dev/null +++ b/target/linux/generic/backport-5.10/891-v5.11-net-dsa-mv88e6xxx-Add-helper-to-get-a-chip-s-max_vid.patch @@ -0,0 +1,153 @@ +From e545f86573937142b8a90bd65d476b9f001088cf Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Tue, 10 Nov 2020 19:57:20 +0100 +Subject: [PATCH] net: dsa: mv88e6xxx: Add helper to get a chip's max_vid + +Most of the other chip info constants have helpers to get at them; add +one for max_vid to keep things consistent. + +Suggested-by: Andrew Lunn +Signed-off-by: Tobias Waldekranz +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20201110185720.18228-1-tobias@waldekranz.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mv88e6xxx/chip.c | 18 +++++++++--------- + drivers/net/dsa/mv88e6xxx/chip.h | 5 +++++ + drivers/net/dsa/mv88e6xxx/devlink.c | 8 ++++---- + 3 files changed, 18 insertions(+), 13 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -1455,7 +1455,7 @@ static void mv88e6xxx_port_fast_age(stru + + static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip) + { +- if (!chip->info->max_vid) ++ if (!mv88e6xxx_max_vid(chip)) + return 0; + + return mv88e6xxx_g1_vtu_flush(chip); +@@ -1497,7 +1497,7 @@ int mv88e6xxx_fid_map(struct mv88e6xxx_c + } + + /* Set every FID bit used by the VLAN entries */ +- vlan.vid = chip->info->max_vid; ++ vlan.vid = mv88e6xxx_max_vid(chip); + vlan.valid = false; + + do { +@@ -1509,7 +1509,7 @@ int mv88e6xxx_fid_map(struct mv88e6xxx_c + break; + + set_bit(vlan.fid, fid_bitmap); +- } while (vlan.vid < chip->info->max_vid); ++ } while (vlan.vid < mv88e6xxx_max_vid(chip)); + + return 0; + } +@@ -1600,7 +1600,7 @@ static int mv88e6xxx_port_vlan_filtering + int err; + + if (switchdev_trans_ph_prepare(trans)) +- return chip->info->max_vid ? 0 : -EOPNOTSUPP; ++ return mv88e6xxx_max_vid(chip) ? 0 : -EOPNOTSUPP; + + mv88e6xxx_reg_lock(chip); + err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); +@@ -1616,7 +1616,7 @@ mv88e6xxx_port_vlan_prepare(struct dsa_s + struct mv88e6xxx_chip *chip = ds->priv; + int err; + +- if (!chip->info->max_vid) ++ if (!mv88e6xxx_max_vid(chip)) + return -EOPNOTSUPP; + + /* If the requested port doesn't belong to the same bridge as the VLAN +@@ -1990,7 +1990,7 @@ static void mv88e6xxx_port_vlan_add(stru + u8 member; + u16 vid; + +- if (!chip->info->max_vid) ++ if (!mv88e6xxx_max_vid(chip)) + return; + + if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) +@@ -2068,7 +2068,7 @@ static int mv88e6xxx_port_vlan_del(struc + u16 pvid, vid; + int err = 0; + +- if (!chip->info->max_vid) ++ if (!mv88e6xxx_max_vid(chip)) + return -EOPNOTSUPP; + + mv88e6xxx_reg_lock(chip); +@@ -2174,7 +2174,7 @@ static int mv88e6xxx_port_db_dump(struct + return err; + + /* Dump VLANs' Filtering Information Databases */ +- vlan.vid = chip->info->max_vid; ++ vlan.vid = mv88e6xxx_max_vid(chip); + vlan.valid = false; + + do { +@@ -2189,7 +2189,7 @@ static int mv88e6xxx_port_db_dump(struct + cb, data); + if (err) + return err; +- } while (vlan.vid < chip->info->max_vid); ++ } while (vlan.vid < mv88e6xxx_max_vid(chip)); + + return err; + } +--- a/drivers/net/dsa/mv88e6xxx/chip.h ++++ b/drivers/net/dsa/mv88e6xxx/chip.h +@@ -674,6 +674,11 @@ static inline unsigned int mv88e6xxx_num + return chip->info->num_ports; + } + ++static inline unsigned int mv88e6xxx_max_vid(struct mv88e6xxx_chip *chip) ++{ ++ return chip->info->max_vid; ++} ++ + static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip) + { + return GENMASK((s32)mv88e6xxx_num_ports(chip) - 1, 0); +--- a/drivers/net/dsa/mv88e6xxx/devlink.c ++++ b/drivers/net/dsa/mv88e6xxx/devlink.c +@@ -452,14 +452,14 @@ static int mv88e6xxx_region_vtu_snapshot + struct mv88e6xxx_vtu_entry vlan; + int err; + +- table = kcalloc(chip->info->max_vid + 1, ++ table = kcalloc(mv88e6xxx_max_vid(chip) + 1, + sizeof(struct mv88e6xxx_devlink_vtu_entry), + GFP_KERNEL); + if (!table) + return -ENOMEM; + + entry = table; +- vlan.vid = chip->info->max_vid; ++ vlan.vid = mv88e6xxx_max_vid(chip); + vlan.valid = false; + + mv88e6xxx_reg_lock(chip); +@@ -490,7 +490,7 @@ static int mv88e6xxx_region_vtu_snapshot + break; + + entry++; +- } while (vlan.vid < chip->info->max_vid); ++ } while (vlan.vid < mv88e6xxx_max_vid(chip)); + + mv88e6xxx_reg_unlock(chip); + +@@ -678,7 +678,7 @@ static int mv88e6xxx_setup_devlink_regio + sizeof(struct mv88e6xxx_devlink_atu_entry); + break; + case MV88E6XXX_REGION_VTU: +- size = chip->info->max_vid * ++ size = mv88e6xxx_max_vid(chip) * + sizeof(struct mv88e6xxx_devlink_vtu_entry); + break; + } diff --git a/target/linux/generic/backport-5.10/891-v5.13-net-dsa-mv88e6xxx-Fix-off-by-one-in-VTU-devlink-regi.patch b/target/linux/generic/backport-5.10/891-v5.13-net-dsa-mv88e6xxx-Fix-off-by-one-in-VTU-devlink-regi.patch new file mode 100644 index 0000000000..5c9cbd8192 --- /dev/null +++ b/target/linux/generic/backport-5.10/891-v5.13-net-dsa-mv88e6xxx-Fix-off-by-one-in-VTU-devlink-regi.patch @@ -0,0 +1,30 @@ +From 281140a0a2ce4febf2c0ce5d29d0e7d961a826b1 Mon Sep 17 00:00:00 2001 +From: Tobias Waldekranz +Date: Wed, 21 Apr 2021 14:04:53 +0200 +Subject: [PATCH] net: dsa: mv88e6xxx: Fix off-by-one in VTU devlink region + size + +In the unlikely event of the VTU being loaded to the brim with 4k +entries, the last one was placed in the buffer, but the size reported +to devlink was off-by-one. Make sure that the final entry is available +to the caller. + +Fixes: ca4d632aef03 ("net: dsa: mv88e6xxx: Export VTU as devlink region") +Signed-off-by: Tobias Waldekranz +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mv88e6xxx/devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/dsa/mv88e6xxx/devlink.c ++++ b/drivers/net/dsa/mv88e6xxx/devlink.c +@@ -678,7 +678,7 @@ static int mv88e6xxx_setup_devlink_regio + sizeof(struct mv88e6xxx_devlink_atu_entry); + break; + case MV88E6XXX_REGION_VTU: +- size = mv88e6xxx_max_vid(chip) * ++ size = (mv88e6xxx_max_vid(chip) + 1) * + sizeof(struct mv88e6xxx_devlink_vtu_entry); + break; + } -- cgit v1.2.3