From 78e70dbcfd0334c0eaf61c09e2083107f4762506 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 21 Apr 2021 14:04:52 +0200 Subject: [PATCH 1/3] net: dsa: mv88e6xxx: Correct spelling of define "ADRR" -> "ADDR" Because ADRR is not a thing. Signed-off-by: Tobias Waldekranz Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 2 +- drivers/net/dsa/mv88e6xxx/global2.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9ff1a10993b1..eca285aaf72f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1440,7 +1440,7 @@ static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port) * the special "LAG device" in the PVT, using * the LAG ID as the port number. */ - dev = MV88E6XXX_G2_PVT_ADRR_DEV_TRUNK; + dev = MV88E6XXX_G2_PVT_ADDR_DEV_TRUNK; port = dsa_lag_id(dst, dp->lag_dev); } } diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index c78769cdbb59..8f85c23ec9c7 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -109,7 +109,7 @@ #define MV88E6XXX_G2_PVT_ADDR_OP_WRITE_PVLAN 0x3000 #define MV88E6XXX_G2_PVT_ADDR_OP_READ 0x4000 #define MV88E6XXX_G2_PVT_ADDR_PTR_MASK 0x01ff -#define MV88E6XXX_G2_PVT_ADRR_DEV_TRUNK 0x1f +#define MV88E6XXX_G2_PVT_ADDR_DEV_TRUNK 0x1f /* Offset 0x0C: Cross-chip Port VLAN Data Register */ #define MV88E6XXX_G2_PVT_DATA 0x0c From 281140a0a2ce4febf2c0ce5d29d0e7d961a826b1 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 21 Apr 2021 14:04:53 +0200 Subject: [PATCH 2/3] 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(-) diff --git a/drivers/net/dsa/mv88e6xxx/devlink.c b/drivers/net/dsa/mv88e6xxx/devlink.c index 21953d6d484c..ada7a38d4d31 100644 --- a/drivers/net/dsa/mv88e6xxx/devlink.c +++ b/drivers/net/dsa/mv88e6xxx/devlink.c @@ -678,7 +678,7 @@ static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds, 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; } From 836021a2d0e0e4c90b895a35bd9c0342071855fb Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 21 Apr 2021 14:04:54 +0200 Subject: [PATCH 3/3] net: dsa: mv88e6xxx: Export cross-chip PVT as devlink region Export the raw PVT data 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 Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.h | 3 ++ drivers/net/dsa/mv88e6xxx/devlink.c | 56 +++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/global2.c | 17 +++++++++ drivers/net/dsa/mv88e6xxx/global2.h | 2 ++ 4 files changed, 78 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index 4f116f73a74b..675b1f3e43b7 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -23,6 +23,8 @@ /* PVT limits for 4-bit port and 5-bit switch */ #define MV88E6XXX_MAX_PVT_SWITCHES 32 #define MV88E6XXX_MAX_PVT_PORTS 16 +#define MV88E6XXX_MAX_PVT_ENTRIES \ + (MV88E6XXX_MAX_PVT_SWITCHES * MV88E6XXX_MAX_PVT_PORTS) #define MV88E6XXX_MAX_GPIO 16 @@ -266,6 +268,7 @@ enum mv88e6xxx_region_id { MV88E6XXX_REGION_GLOBAL2, MV88E6XXX_REGION_ATU, MV88E6XXX_REGION_VTU, + MV88E6XXX_REGION_PVT, _MV88E6XXX_REGION_MAX, }; diff --git a/drivers/net/dsa/mv88e6xxx/devlink.c b/drivers/net/dsa/mv88e6xxx/devlink.c index ada7a38d4d31..0c0f5ea6680c 100644 --- a/drivers/net/dsa/mv88e6xxx/devlink.c +++ b/drivers/net/dsa/mv88e6xxx/devlink.c @@ -503,6 +503,44 @@ static int mv88e6xxx_region_vtu_snapshot(struct devlink *dl, return 0; } +static int mv88e6xxx_region_pvt_snapshot(struct devlink *dl, + const struct devlink_region_ops *ops, + struct netlink_ext_ack *extack, + u8 **data) +{ + struct dsa_switch *ds = dsa_devlink_to_ds(dl); + struct mv88e6xxx_chip *chip = ds->priv; + int dev, port, err; + u16 *pvt, *cur; + + pvt = kcalloc(MV88E6XXX_MAX_PVT_ENTRIES, sizeof(*pvt), GFP_KERNEL); + if (!pvt) + return -ENOMEM; + + mv88e6xxx_reg_lock(chip); + + cur = pvt; + for (dev = 0; dev < MV88E6XXX_MAX_PVT_SWITCHES; dev++) { + for (port = 0; port < MV88E6XXX_MAX_PVT_PORTS; port++) { + err = mv88e6xxx_g2_pvt_read(chip, dev, port, cur); + if (err) + break; + + cur++; + } + } + + mv88e6xxx_reg_unlock(chip); + + if (err) { + kfree(pvt); + return err; + } + + *data = (u8 *)pvt; + 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, @@ -567,6 +605,12 @@ static struct devlink_region_ops mv88e6xxx_region_vtu_ops = { .destructor = kfree, }; +static struct devlink_region_ops mv88e6xxx_region_pvt_ops = { + .name = "pvt", + .snapshot = mv88e6xxx_region_pvt_snapshot, + .destructor = kfree, +}; + static const struct devlink_port_region_ops mv88e6xxx_region_port_ops = { .name = "port", .snapshot = mv88e6xxx_region_port_snapshot, @@ -576,6 +620,8 @@ static const struct devlink_port_region_ops mv88e6xxx_region_port_ops = { struct mv88e6xxx_region { struct devlink_region_ops *ops; u64 size; + + bool (*cond)(struct mv88e6xxx_chip *chip); }; static struct mv88e6xxx_region mv88e6xxx_regions[] = { @@ -594,6 +640,11 @@ static struct mv88e6xxx_region mv88e6xxx_regions[] = { .ops = &mv88e6xxx_region_vtu_ops /* calculated at runtime */ }, + [MV88E6XXX_REGION_PVT] = { + .ops = &mv88e6xxx_region_pvt_ops, + .size = MV88E6XXX_MAX_PVT_ENTRIES * sizeof(u16), + .cond = mv88e6xxx_has_pvt, + }, }; static void @@ -663,6 +714,7 @@ out: static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds, struct mv88e6xxx_chip *chip) { + bool (*cond)(struct mv88e6xxx_chip *chip); struct devlink_region_ops *ops; struct devlink_region *region; u64 size; @@ -671,6 +723,10 @@ static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds, for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++) { ops = mv88e6xxx_regions[i].ops; size = mv88e6xxx_regions[i].size; + cond = mv88e6xxx_regions[i].cond; + + if (cond && !cond(chip)) + continue; switch (i) { case MV88E6XXX_REGION_ATU: diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index da8bac8813e1..fa65ecd9cb85 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -239,6 +239,23 @@ static int mv88e6xxx_g2_pvt_op(struct mv88e6xxx_chip *chip, int src_dev, return mv88e6xxx_g2_pvt_op_wait(chip); } +int mv88e6xxx_g2_pvt_read(struct mv88e6xxx_chip *chip, int src_dev, + int src_port, u16 *data) +{ + int err; + + err = mv88e6xxx_g2_pvt_op_wait(chip); + if (err) + return err; + + err = mv88e6xxx_g2_pvt_op(chip, src_dev, src_port, + MV88E6XXX_G2_PVT_ADDR_OP_READ); + if (err) + return err; + + return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_PVT_DATA, data); +} + int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, int src_port, u16 data) { diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h index 8f85c23ec9c7..f3e27573a386 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -330,6 +330,8 @@ int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip, int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip, struct ethtool_eeprom *eeprom, u8 *data); +int mv88e6xxx_g2_pvt_read(struct mv88e6xxx_chip *chip, int src_dev, + int src_port, u16 *data); int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev, int src_port, u16 data); int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip);