In preparation for allowing for global checks that would apply to the entire switch and not just on a per-port basis, make the VLAN filtering attribute follow other switchdev attributes/objects and make it use the DSA notifier infrastructure.
Signed-off-by: Florian Fainelli <f.faine...@gmail.com> --- net/dsa/dsa_priv.h | 11 ++++++++++- net/dsa/port.c | 17 +++++++---------- net/dsa/switch.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 1f4972dab9f2..1e3db5f2a699 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -26,6 +26,7 @@ enum { DSA_NOTIFIER_MDB_DEL, DSA_NOTIFIER_VLAN_ADD, DSA_NOTIFIER_VLAN_DEL, + DSA_NOTIFIER_VLAN_FILTERING, }; /* DSA_NOTIFIER_AGEING_TIME */ @@ -57,7 +58,7 @@ struct dsa_notifier_mdb_info { int port; }; -/* DSA_NOTIFIER_VLAN_* */ +/* DSA_NOTIFIER_VLAN_{ADD,DEL} */ struct dsa_notifier_vlan_info { const struct switchdev_obj_port_vlan *vlan; struct switchdev_trans *trans; @@ -65,6 +66,14 @@ struct dsa_notifier_vlan_info { int port; }; +/* DSA_NOTIFIER_VLAN_FILTERING */ +struct dsa_notifier_vlan_filtering_info { + bool vlan_filtering; + struct switchdev_trans *trans; + int sw_index; + int port; +}; + struct dsa_slave_priv { /* Copy of CPU port xmit for faster access in slave transmit hot path */ struct sk_buff * (*xmit)(struct sk_buff *skb, diff --git a/net/dsa/port.c b/net/dsa/port.c index 185e85a4f5f0..d7b057d46460 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -146,17 +146,14 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans) { - struct dsa_switch *ds = dp->ds; - - /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ - if (switchdev_trans_ph_prepare(trans)) - return 0; - - if (ds->ops->port_vlan_filtering) - return ds->ops->port_vlan_filtering(ds, dp->index, - vlan_filtering); + struct dsa_notifier_vlan_filtering_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .trans = trans, + .vlan_filtering = vlan_filtering, + }; - return 0; + return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_FILTERING, &info); } int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 142b294d3446..831334dc5e79 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -235,6 +235,32 @@ static int dsa_switch_vlan_del(struct dsa_switch *ds, return 0; } +static int dsa_switch_vlan_filtering(struct dsa_switch *ds, + struct dsa_notifier_vlan_filtering_info *info) +{ + struct switchdev_trans *trans = info->trans; + bool vlan_filtering = info->vlan_filtering; + int port = info->port; + int err; + + /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ + if (switchdev_trans_ph_prepare(trans)) + return 0; + + /* Build a mask of port members */ + bitmap_zero(ds->bitmap, ds->num_ports); + if (ds->index == info->sw_index) + set_bit(port, ds->bitmap); + + for_each_set_bit(port, ds->bitmap, ds->num_ports) { + err = ds->ops->port_vlan_filtering(ds, port, vlan_filtering); + if (err) + return err; + } + + return 0; +} + static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { @@ -269,6 +295,9 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_VLAN_DEL: err = dsa_switch_vlan_del(ds, info); break; + case DSA_NOTIFIER_VLAN_FILTERING: + err = dsa_switch_vlan_filtering(ds, info); + break; default: err = -EOPNOTSUPP; break; -- 2.17.1