The bridge can at runtime be configured with or without IGMP snooping enabled but we were not processing the switchdev attribute that notifies about that toggle, do this now.
Signed-off-by: Florian Fainelli <f.faine...@gmail.com> --- include/net/dsa.h | 2 ++ net/dsa/dsa_priv.h | 11 +++++++++++ net/dsa/port.c | 13 +++++++++++++ net/dsa/slave.c | 4 ++++ net/dsa/switch.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 58 insertions(+) diff --git a/include/net/dsa.h b/include/net/dsa.h index 7f2a668ef2cc..2ee1ede7df5c 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -425,6 +425,8 @@ struct dsa_switch_ops { /* * Multicast database */ + int (*port_multicast_toggle)(struct dsa_switch *ds, int port, + bool mc_disabled); int (*port_mdb_prepare)(struct dsa_switch *ds, int port, const struct switchdev_obj_port_mdb *mdb); void (*port_mdb_add)(struct dsa_switch *ds, int port, diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 1e3db5f2a699..221753777cf5 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -27,6 +27,7 @@ enum { DSA_NOTIFIER_VLAN_ADD, DSA_NOTIFIER_VLAN_DEL, DSA_NOTIFIER_VLAN_FILTERING, + DSA_NOTIFIER_MC_DISABLED, }; /* DSA_NOTIFIER_AGEING_TIME */ @@ -74,6 +75,14 @@ struct dsa_notifier_vlan_filtering_info { int port; }; +/* DSA_NOTIFIER_MC_DISABLED */ +struct dsa_notifier_mc_disabled_info { + bool mc_disabled; + 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, @@ -155,6 +164,8 @@ int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy); void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy); int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); +int dsa_port_multicast_toggle(struct dsa_port *dp, bool mc_disabled, + struct switchdev_trans *trans); int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans); int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, diff --git a/net/dsa/port.c b/net/dsa/port.c index d7b057d46460..148458941b51 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -143,6 +143,19 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) dsa_port_set_state_now(dp, BR_STATE_FORWARDING); } +int dsa_port_multicast_toggle(struct dsa_port *dp, bool mc_disabled, + struct switchdev_trans *trans) +{ + struct dsa_notifier_mc_disabled_info info = { + .sw_index = dp->ds->index, + .port = dp->index, + .trans = trans, + .mc_disabled = mc_disabled, + }; + + return dsa_port_notify(dp, DSA_NOTIFIER_MC_DISABLED, &info); +} + int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans) { diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 306fd1b45f0c..f3b3cf34804f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -337,6 +337,10 @@ static int dsa_slave_port_attr_set(struct net_device *dev, case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: ret = dsa_port_ageing_time(dp, attr->u.ageing_time, trans); break; + case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED: + ret = dsa_port_multicast_toggle(dp, attr->u.mc_disabled, + trans); + break; default: ret = -EOPNOTSUPP; break; diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 831334dc5e79..e095eb808434 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -261,6 +261,31 @@ static int dsa_switch_vlan_filtering(struct dsa_switch *ds, return 0; } +static int dsa_switch_mc_disabled(struct dsa_switch *ds, + struct dsa_notifier_mc_disabled_info *info) +{ + struct switchdev_trans *trans = info->trans; + bool mc_disabled = info->mc_disabled; + int port = info->port; + int err; + + if (switchdev_trans_ph_prepare(trans)) + return ds->ops->port_multicast_toggle ? 0 : -EOPNOTSUPP; + + /* 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_multicast_toggle(ds, port, mc_disabled); + if (err) + return err; + } + + return 0; +} + static int dsa_switch_event(struct notifier_block *nb, unsigned long event, void *info) { @@ -298,6 +323,9 @@ static int dsa_switch_event(struct notifier_block *nb, case DSA_NOTIFIER_VLAN_FILTERING: err = dsa_switch_vlan_filtering(ds, info); break; + case DSA_NOTIFIER_MC_DISABLED: + err = dsa_switch_mc_disabled(ds, info); + break; default: err = -EOPNOTSUPP; break; -- 2.17.1