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 <tobias@waldekranz.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
281140a0a2
commit
836021a2d0
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue