mlxsw: spectrum: Centralize VLAN-aware bridge ref counting
authorIdo Schimmel <idosch@mellanox.com>
Mon, 20 Jun 2016 21:04:06 +0000 (23:04 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jun 2016 09:02:49 +0000 (05:02 -0400)
We hold a reference count on the number of ports member in the
VLAN-aware bridge, as we only support one.

Instead of always incrementing / decrementing the reference count after
joining / leaving the bridge, simply do this accounting in the join /
leave functions.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c

index cd853166d5182c53035ed8d7f5129f778fff70f2..b9998025f66a37c4d41fcfd656aa78a43efc7d73 100644 (file)
@@ -2651,7 +2651,28 @@ static bool mlxsw_sp_port_dev_check(const struct net_device *dev)
        return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
 }
 
-static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port)
+static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
+                                        struct net_device *br_dev)
+{
+       return !mlxsw_sp->master_bridge.dev ||
+              mlxsw_sp->master_bridge.dev == br_dev;
+}
+
+static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp,
+                                      struct net_device *br_dev)
+{
+       mlxsw_sp->master_bridge.dev = br_dev;
+       mlxsw_sp->master_bridge.ref_count++;
+}
+
+static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp)
+{
+       if (--mlxsw_sp->master_bridge.ref_count == 0)
+               mlxsw_sp->master_bridge.dev = NULL;
+}
+
+static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
+                                    struct net_device *br_dev)
 {
        struct net_device *dev = mlxsw_sp_port->dev;
        int err;
@@ -2665,6 +2686,8 @@ static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port)
        if (err)
                return err;
 
+       mlxsw_sp_master_bridge_inc(mlxsw_sp_port->mlxsw_sp, br_dev);
+
        mlxsw_sp_port->learning = 1;
        mlxsw_sp_port->learning_sync = 1;
        mlxsw_sp_port->uc_flood = 1;
@@ -2683,6 +2706,8 @@ static void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
 
        mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
 
+       mlxsw_sp_master_bridge_dec(mlxsw_sp_port->mlxsw_sp);
+
        mlxsw_sp_port->learning = 0;
        mlxsw_sp_port->learning_sync = 0;
        mlxsw_sp_port->uc_flood = 0;
@@ -2694,26 +2719,6 @@ static void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
        mlxsw_sp_port_add_vid(dev, 0, 1);
 }
 
-static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp,
-                                        struct net_device *br_dev)
-{
-       return !mlxsw_sp->master_bridge.dev ||
-              mlxsw_sp->master_bridge.dev == br_dev;
-}
-
-static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp,
-                                      struct net_device *br_dev)
-{
-       mlxsw_sp->master_bridge.dev = br_dev;
-       mlxsw_sp->master_bridge.ref_count++;
-}
-
-static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp)
-{
-       if (--mlxsw_sp->master_bridge.ref_count == 0)
-               mlxsw_sp->master_bridge.dev = NULL;
-}
-
 static int mlxsw_sp_lag_create(struct mlxsw_sp *mlxsw_sp, u16 lag_id)
 {
        char sldr_pl[MLXSW_REG_SLDR_LEN];
@@ -2910,7 +2915,6 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
        if (mlxsw_sp_port->bridged) {
                mlxsw_sp_port_active_vlans_del(mlxsw_sp_port);
                mlxsw_sp_port_bridge_leave(mlxsw_sp_port, false);
-               mlxsw_sp_master_bridge_dec(mlxsw_sp);
        }
 
        if (lag->ref_count == 1) {
@@ -3049,13 +3053,11 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
                                 mlxsw_sp_port_vlan_unlink(mlxsw_sp_port,
                                                           upper_dev);
                } else if (netif_is_bridge_master(upper_dev)) {
-                       if (info->linking) {
-                               err = mlxsw_sp_port_bridge_join(mlxsw_sp_port);
-                               mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev);
-                       } else {
+                       if (info->linking)
+                               err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
+                                                               upper_dev);
+                       else
                                mlxsw_sp_port_bridge_leave(mlxsw_sp_port, true);
-                               mlxsw_sp_master_bridge_dec(mlxsw_sp);
-                       }
                } else if (netif_is_lag_master(upper_dev)) {
                        if (info->linking)
                                err = mlxsw_sp_port_lag_join(mlxsw_sp_port,