Skip to content

Commit

Permalink
net: dsa: mv88e6xxx: Add ATU occupancy via devlink resources
Browse files Browse the repository at this point in the history
The ATU can report how many entries it contains. It does this per bin,
there being 4 bins in total. Export the ATU as a devlink resource, and
provide a method the needed callback to get the resource occupancy.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Andrew Lunn authored and David S. Miller committed Nov 6, 2019
1 parent c5f299d commit e0c69ca
Showing 1 changed file with 186 additions and 4 deletions.
190 changes: 186 additions & 4 deletions drivers/net/dsa/mv88e6xxx/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -2720,9 +2720,179 @@ static void mv88e6xxx_teardown_devlink_params(struct dsa_switch *ds)
ARRAY_SIZE(mv88e6xxx_devlink_params));
}

enum mv88e6xxx_devlink_resource_id {
MV88E6XXX_RESOURCE_ID_ATU,
MV88E6XXX_RESOURCE_ID_ATU_BIN_0,
MV88E6XXX_RESOURCE_ID_ATU_BIN_1,
MV88E6XXX_RESOURCE_ID_ATU_BIN_2,
MV88E6XXX_RESOURCE_ID_ATU_BIN_3,
};

static u64 mv88e6xxx_devlink_atu_bin_get(struct mv88e6xxx_chip *chip,
u16 bin)
{
u16 occupancy = 0;
int err;

mv88e6xxx_reg_lock(chip);

err = mv88e6xxx_g2_atu_stats_set(chip, MV88E6XXX_G2_ATU_STATS_MODE_ALL,
bin);
if (err) {
dev_err(chip->dev, "failed to set ATU stats kind/bin\n");
goto unlock;
}

err = mv88e6xxx_g1_atu_get_next(chip, 0);
if (err) {
dev_err(chip->dev, "failed to perform ATU get next\n");
goto unlock;
}

err = mv88e6xxx_g2_atu_stats_get(chip, &occupancy);
if (err) {
dev_err(chip->dev, "failed to get ATU stats\n");
goto unlock;
}

unlock:
mv88e6xxx_reg_unlock(chip);

return occupancy;
}

static u64 mv88e6xxx_devlink_atu_bin_0_get(void *priv)
{
struct mv88e6xxx_chip *chip = priv;

return mv88e6xxx_devlink_atu_bin_get(chip,
MV88E6XXX_G2_ATU_STATS_BIN_0);
}

static u64 mv88e6xxx_devlink_atu_bin_1_get(void *priv)
{
struct mv88e6xxx_chip *chip = priv;

return mv88e6xxx_devlink_atu_bin_get(chip,
MV88E6XXX_G2_ATU_STATS_BIN_1);
}

static u64 mv88e6xxx_devlink_atu_bin_2_get(void *priv)
{
struct mv88e6xxx_chip *chip = priv;

return mv88e6xxx_devlink_atu_bin_get(chip,
MV88E6XXX_G2_ATU_STATS_BIN_2);
}

static u64 mv88e6xxx_devlink_atu_bin_3_get(void *priv)
{
struct mv88e6xxx_chip *chip = priv;

return mv88e6xxx_devlink_atu_bin_get(chip,
MV88E6XXX_G2_ATU_STATS_BIN_3);
}

static u64 mv88e6xxx_devlink_atu_get(void *priv)
{
return mv88e6xxx_devlink_atu_bin_0_get(priv) +
mv88e6xxx_devlink_atu_bin_1_get(priv) +
mv88e6xxx_devlink_atu_bin_2_get(priv) +
mv88e6xxx_devlink_atu_bin_3_get(priv);
}

static int mv88e6xxx_setup_devlink_resources(struct dsa_switch *ds)
{
struct devlink_resource_size_params size_params;
struct mv88e6xxx_chip *chip = ds->priv;
int err;

devlink_resource_size_params_init(&size_params,
mv88e6xxx_num_macs(chip),
mv88e6xxx_num_macs(chip),
1, DEVLINK_RESOURCE_UNIT_ENTRY);

err = dsa_devlink_resource_register(ds, "ATU",
mv88e6xxx_num_macs(chip),
MV88E6XXX_RESOURCE_ID_ATU,
DEVLINK_RESOURCE_ID_PARENT_TOP,
&size_params);
if (err)
goto out;

devlink_resource_size_params_init(&size_params,
mv88e6xxx_num_macs(chip) / 4,
mv88e6xxx_num_macs(chip) / 4,
1, DEVLINK_RESOURCE_UNIT_ENTRY);

err = dsa_devlink_resource_register(ds, "ATU_bin_0",
mv88e6xxx_num_macs(chip) / 4,
MV88E6XXX_RESOURCE_ID_ATU_BIN_0,
MV88E6XXX_RESOURCE_ID_ATU,
&size_params);
if (err)
goto out;

err = dsa_devlink_resource_register(ds, "ATU_bin_1",
mv88e6xxx_num_macs(chip) / 4,
MV88E6XXX_RESOURCE_ID_ATU_BIN_1,
MV88E6XXX_RESOURCE_ID_ATU,
&size_params);
if (err)
goto out;

err = dsa_devlink_resource_register(ds, "ATU_bin_2",
mv88e6xxx_num_macs(chip) / 4,
MV88E6XXX_RESOURCE_ID_ATU_BIN_2,
MV88E6XXX_RESOURCE_ID_ATU,
&size_params);
if (err)
goto out;

err = dsa_devlink_resource_register(ds, "ATU_bin_3",
mv88e6xxx_num_macs(chip) / 4,
MV88E6XXX_RESOURCE_ID_ATU_BIN_3,
MV88E6XXX_RESOURCE_ID_ATU,
&size_params);
if (err)
goto out;

dsa_devlink_resource_occ_get_register(ds,
MV88E6XXX_RESOURCE_ID_ATU,
mv88e6xxx_devlink_atu_get,
chip);

dsa_devlink_resource_occ_get_register(ds,
MV88E6XXX_RESOURCE_ID_ATU_BIN_0,
mv88e6xxx_devlink_atu_bin_0_get,
chip);

dsa_devlink_resource_occ_get_register(ds,
MV88E6XXX_RESOURCE_ID_ATU_BIN_1,
mv88e6xxx_devlink_atu_bin_1_get,
chip);

dsa_devlink_resource_occ_get_register(ds,
MV88E6XXX_RESOURCE_ID_ATU_BIN_2,
mv88e6xxx_devlink_atu_bin_2_get,
chip);

dsa_devlink_resource_occ_get_register(ds,
MV88E6XXX_RESOURCE_ID_ATU_BIN_3,
mv88e6xxx_devlink_atu_bin_3_get,
chip);

return 0;

out:
dsa_devlink_resources_unregister(ds);
return err;
}

static void mv88e6xxx_teardown(struct dsa_switch *ds)
{
mv88e6xxx_teardown_devlink_params(ds);
dsa_devlink_resources_unregister(ds);
}

static int mv88e6xxx_setup(struct dsa_switch *ds)
Expand Down Expand Up @@ -2841,11 +3011,23 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
unlock:
mv88e6xxx_reg_unlock(chip);

/* Has to be called without holding the register lock, since
* it takes the devlink lock, and we later take the locks in
* the reverse order when getting/setting parameters.
if (err)
return err;

/* Have to be called without holding the register lock, since
* they take the devlink lock, and we later take the locks in
* the reverse order when getting/setting parameters or
* resource occupancy.
*/
return mv88e6xxx_setup_devlink_params(ds);
err = mv88e6xxx_setup_devlink_resources(ds);
if (err)
return err;

err = mv88e6xxx_setup_devlink_params(ds);
if (err)
dsa_devlink_resources_unregister(ds);

return err;
}

static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
Expand Down

0 comments on commit e0c69ca

Please sign in to comment.