|
@@ -261,12 +261,40 @@ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid,
|
|
|
false);
|
|
|
}
|
|
|
|
|
|
+static int mlxsw_sp_port_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
|
|
+ bool set)
|
|
|
+{
|
|
|
+ u16 vid;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
|
|
|
+ vid = mlxsw_sp_vport_vid_get(mlxsw_sp_port);
|
|
|
+
|
|
|
+ return __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
|
|
|
+ set);
|
|
|
+ }
|
|
|
+
|
|
|
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) {
|
|
|
+ err = __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid,
|
|
|
+ set);
|
|
|
+ if (err)
|
|
|
+ goto err_port_vid_learning_set;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_port_vid_learning_set:
|
|
|
+ for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
|
|
|
+ __mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, vid, !set);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
|
|
struct switchdev_trans *trans,
|
|
|
unsigned long brport_flags)
|
|
|
{
|
|
|
+ unsigned long learning = mlxsw_sp_port->learning ? BR_LEARNING : 0;
|
|
|
unsigned long uc_flood = mlxsw_sp_port->uc_flood ? BR_FLOOD : 0;
|
|
|
- bool set;
|
|
|
int err;
|
|
|
|
|
|
if (!mlxsw_sp_port->bridged)
|
|
@@ -276,17 +304,30 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
|
|
return 0;
|
|
|
|
|
|
if ((uc_flood ^ brport_flags) & BR_FLOOD) {
|
|
|
- set = mlxsw_sp_port->uc_flood ? false : true;
|
|
|
- err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port, set);
|
|
|
+ err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port,
|
|
|
+ !mlxsw_sp_port->uc_flood);
|
|
|
if (err)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+ if ((learning ^ brport_flags) & BR_LEARNING) {
|
|
|
+ err = mlxsw_sp_port_learning_set(mlxsw_sp_port,
|
|
|
+ !mlxsw_sp_port->learning);
|
|
|
+ if (err)
|
|
|
+ goto err_port_learning_set;
|
|
|
+ }
|
|
|
+
|
|
|
mlxsw_sp_port->uc_flood = brport_flags & BR_FLOOD ? 1 : 0;
|
|
|
mlxsw_sp_port->learning = brport_flags & BR_LEARNING ? 1 : 0;
|
|
|
mlxsw_sp_port->learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0;
|
|
|
|
|
|
return 0;
|
|
|
+
|
|
|
+err_port_learning_set:
|
|
|
+ if ((uc_flood ^ brport_flags) & BR_FLOOD)
|
|
|
+ mlxsw_sp_port_uc_flood_set(mlxsw_sp_port,
|
|
|
+ mlxsw_sp_port->uc_flood);
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time)
|