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

Reply via email to