Allocate the struct dsa_port the first time it is accessed with dsa_port_touch, and remove the static dsa_port array from the dsa_switch structure.
Signed-off-by: Vivien Didelot <vivien.dide...@gmail.com> --- include/net/dsa.h | 2 -- net/dsa/dsa2.c | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 020f5db8666b..d28ac54cb8c4 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -277,9 +277,7 @@ struct dsa_switch { */ bool vlan_filtering; - /* Dynamically allocated ports, keep last */ size_t num_ports; - struct dsa_port ports[]; }; static inline struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 772deacc33d3..7669a6278c40 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -596,7 +596,13 @@ static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index) struct dsa_switch_tree *dst = ds->dst; struct dsa_port *dp; - dp = &ds->ports[index]; + list_for_each_entry(dp, &dst->ports, list) + if (dp->ds == ds && dp->index == index) + return dp; + + dp = kzalloc(sizeof(*dp), GFP_KERNEL); + if (!dp) + return NULL; dp->ds = ds; dp->index = index; @@ -865,7 +871,7 @@ struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n) { struct dsa_switch *ds; - ds = devm_kzalloc(dev, struct_size(ds, ports, n), GFP_KERNEL); + ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); if (!ds) return NULL; @@ -893,6 +899,12 @@ static void dsa_switch_remove(struct dsa_switch *ds) { struct dsa_switch_tree *dst = ds->dst; unsigned int index = ds->index; + struct dsa_port *dp, *next; + + list_for_each_entry_safe(dp, next, &dst->ports, list) { + list_del(&dp->list); + kfree(dp); + } dsa_tree_remove_switch(dst, index); } -- 2.23.0