Implement a mv88e6xxx_port_bridge_change function to factorize the
configuration needed when a port joins or leaves a bridge group.

This will simplify the implementation of cross-chip bridging.

Signed-off-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6xxx.c | 67 +++++++++++++++++++++++++++------------------
 1 file changed, 40 insertions(+), 27 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 8004d00..25852ee 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1150,6 +1150,24 @@ static int _mv88e6xxx_port_map_vlantable(struct 
dsa_switch *ds,
        return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg);
 }
 
+static int _mv88e6xxx_remap_vlantable(struct dsa_switch *ds,
+                                     struct net_device *bridge)
+{
+       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       struct dsa_port *intp;
+       int err;
+
+       dsa_switch_for_each_port(ds, intp, ps->info->num_ports) {
+               if (intp->br == bridge) {
+                       err = _mv88e6xxx_port_map_vlantable(ds, intp);
+                       if (err)
+                               return err;
+               }
+       }
+
+       return 0;
+}
+
 void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -2229,51 +2247,46 @@ unlock:
        return err;
 }
 
-int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, struct dsa_port *dp,
-                              struct net_device *bridge)
+int mv88e6xxx_port_bridge_change(struct dsa_switch *ds, struct dsa_port *dp,
+                                struct net_device *bridge)
 {
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       struct dsa_port *intp;
        int err;
 
-       if (dsa_port_is_external(dp, ds))
-               return -EOPNOTSUPP;
-
        mutex_lock(&ps->smi_mutex);
 
-       /* Remap each port's VLANTable */
-       dsa_switch_for_each_port(ds, intp, ps->info->num_ports) {
-               if (intp->br == bridge) {
-                       err = _mv88e6xxx_port_map_vlantable(ds, intp);
+       if (dsa_port_is_external(dp, ds)) {
+               err = -EOPNOTSUPP;
+       } else {
+               /* Remap VLANTable of concerned in-chip ports */
+               if (!dp->br) {
+                       err = _mv88e6xxx_port_map_vlantable(ds, dp);
                        if (err)
-                               break;
+                               goto unlock;
                }
+
+               err = _mv88e6xxx_remap_vlantable(ds, bridge);
+               if (err)
+                       goto unlock;
        }
 
+unlock:
        mutex_unlock(&ps->smi_mutex);
 
        return err;
 }
 
+int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, struct dsa_port *dp,
+                              struct net_device *bridge)
+{
+       return mv88e6xxx_port_bridge_change(ds, dp, bridge);
+}
+
 void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, struct dsa_port *dp,
                                 struct net_device *bridge)
 {
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
-       struct dsa_port *intp;
-
-       if (dsa_port_is_external(dp, ds))
-               return;
-
-       mutex_lock(&ps->smi_mutex);
-
-       /* Remap each port's VLANTable */
-       dsa_switch_for_each_port(ds, intp, ps->info->num_ports)
-               if (intp == dp || intp->br == bridge)
-                       if (_mv88e6xxx_port_map_vlantable(ds, intp))
-                               netdev_warn(ds->ports[intp->port],
-                                           "failed to remap\n");
-
-       mutex_unlock(&ps->smi_mutex);
+       if (mv88e6xxx_port_bridge_change(ds, dp, bridge))
+               netdev_err(ds->ports[dp->port], "failed to unbridge\n");
 }
 
 static void mv88e6xxx_bridge_work(struct work_struct *work)
-- 
2.8.0

Reply via email to