Commit ba2d1c28 authored by Kurt Kanzenbach's avatar Kurt Kanzenbach Committed by David S. Miller

net: dsa: hellcreek: Add devlink VLAN region

Allow to dump the VLAN table via devlink. This especially useful, because the
driver internally leverages VLANs for the port separation. These are not visible
via the bridge utility.
Signed-off-by: default avatarKurt Kanzenbach <kurt@kmk-computers.de>
Reviewed-by: default avatarVladimir Oltean <olteanv@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ebc71a38
......@@ -1082,6 +1082,67 @@ static int hellcreek_setup_devlink_resources(struct dsa_switch *ds)
return err;
}
static int hellcreek_devlink_region_vlan_snapshot(struct devlink *dl,
const struct devlink_region_ops *ops,
struct netlink_ext_ack *extack,
u8 **data)
{
struct hellcreek_devlink_vlan_entry *table, *entry;
struct dsa_switch *ds = dsa_devlink_to_ds(dl);
struct hellcreek *hellcreek = ds->priv;
int i;
table = kcalloc(VLAN_N_VID, sizeof(*entry), GFP_KERNEL);
if (!table)
return -ENOMEM;
entry = table;
mutex_lock(&hellcreek->reg_lock);
for (i = 0; i < VLAN_N_VID; ++i, ++entry) {
entry->member = hellcreek->vidmbrcfg[i];
entry->vid = i;
}
mutex_unlock(&hellcreek->reg_lock);
*data = (u8 *)table;
return 0;
}
static struct devlink_region_ops hellcreek_region_vlan_ops = {
.name = "vlan",
.snapshot = hellcreek_devlink_region_vlan_snapshot,
.destructor = kfree,
};
static int hellcreek_setup_devlink_regions(struct dsa_switch *ds)
{
struct hellcreek *hellcreek = ds->priv;
struct devlink_region_ops *ops;
struct devlink_region *region;
u64 size;
/* VLAN table */
size = VLAN_N_VID * sizeof(struct hellcreek_devlink_vlan_entry);
ops = &hellcreek_region_vlan_ops;
region = dsa_devlink_region_create(ds, ops, 1, size);
if (IS_ERR(region))
return PTR_ERR(region);
hellcreek->vlan_region = region;
return 0;
}
static void hellcreek_teardown_devlink_regions(struct dsa_switch *ds)
{
struct hellcreek *hellcreek = ds->priv;
dsa_devlink_region_destroy(hellcreek->vlan_region);
}
static int hellcreek_setup(struct dsa_switch *ds)
{
struct hellcreek *hellcreek = ds->priv;
......@@ -1143,11 +1204,24 @@ static int hellcreek_setup(struct dsa_switch *ds)
return ret;
}
ret = hellcreek_setup_devlink_regions(ds);
if (ret) {
dev_err(hellcreek->dev,
"Failed to setup devlink regions!\n");
goto err_regions;
}
return 0;
err_regions:
dsa_devlink_resources_unregister(ds);
return ret;
}
static void hellcreek_teardown(struct dsa_switch *ds)
{
hellcreek_teardown_devlink_regions(ds);
dsa_devlink_resources_unregister(ds);
}
......
......@@ -278,6 +278,7 @@ struct hellcreek {
struct mutex reg_lock; /* Switch IP register lock */
struct mutex vlan_lock; /* VLAN bitmaps lock */
struct mutex ptp_lock; /* PTP IP register lock */
struct devlink_region *vlan_region;
void __iomem *base;
void __iomem *ptp_base;
u16 swcfg; /* swcfg shadow */
......@@ -304,4 +305,9 @@ enum hellcreek_devlink_resource_id {
HELLCREEK_DEVLINK_PARAM_ID_FDB_TABLE,
};
struct hellcreek_devlink_vlan_entry {
u16 vid;
u16 member;
};
#endif /* _HELLCREEK_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment