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 +++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 target/linux/generic/backport-5.10/890-v5.11-net-dsa-mv88e6xxx-Export-VTU-as-devlink-region.patch (limited to 'target/linux/generic/backport-5.10/890-v5.11-net-dsa-mv88e6xxx-Export-VTU-as-devlink-region.patch') 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; + -- cgit v1.2.3