@@ -1051,39 +1051,49 @@ static int _mv88e6xxx_atu_remove(struct dsa_switch *ds, u16 fid, int port,
1051
1051
return _mv88e6xxx_atu_move (ds , fid , port , 0x0f , static_too );
1052
1052
}
1053
1053
1054
- static int mv88e6xxx_set_port_state (struct dsa_switch * ds , int port , u8 state )
1054
+ static const char * const mv88e6xxx_port_state_names [] = {
1055
+ [PORT_CONTROL_STATE_DISABLED ] = "Disabled" ,
1056
+ [PORT_CONTROL_STATE_BLOCKING ] = "Blocking/Listening" ,
1057
+ [PORT_CONTROL_STATE_LEARNING ] = "Learning" ,
1058
+ [PORT_CONTROL_STATE_FORWARDING ] = "Forwarding" ,
1059
+ };
1060
+
1061
+ static int _mv88e6xxx_port_state (struct dsa_switch * ds , int port , u8 state )
1055
1062
{
1056
- struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1057
1063
int reg , ret = 0 ;
1058
1064
u8 oldstate ;
1059
1065
1060
- mutex_lock (& ps -> smi_mutex );
1061
-
1062
1066
reg = _mv88e6xxx_reg_read (ds , REG_PORT (port ), PORT_CONTROL );
1063
- if (reg < 0 ) {
1064
- ret = reg ;
1065
- goto abort ;
1066
- }
1067
+ if (reg < 0 )
1068
+ return reg ;
1067
1069
1068
1070
oldstate = reg & PORT_CONTROL_STATE_MASK ;
1071
+
1069
1072
if (oldstate != state ) {
1070
1073
/* Flush forwarding database if we're moving a port
1071
1074
* from Learning or Forwarding state to Disabled or
1072
1075
* Blocking or Listening state.
1073
1076
*/
1074
- if (oldstate >= PORT_CONTROL_STATE_LEARNING &&
1075
- state <= PORT_CONTROL_STATE_BLOCKING ) {
1077
+ if ((oldstate == PORT_CONTROL_STATE_LEARNING ||
1078
+ oldstate == PORT_CONTROL_STATE_FORWARDING )
1079
+ && (state == PORT_CONTROL_STATE_DISABLED ||
1080
+ state == PORT_CONTROL_STATE_BLOCKING )) {
1076
1081
ret = _mv88e6xxx_atu_remove (ds , 0 , port , false);
1077
1082
if (ret )
1078
- goto abort ;
1083
+ return ret ;
1079
1084
}
1085
+
1080
1086
reg = (reg & ~PORT_CONTROL_STATE_MASK ) | state ;
1081
1087
ret = _mv88e6xxx_reg_write (ds , REG_PORT (port ), PORT_CONTROL ,
1082
1088
reg );
1089
+ if (ret )
1090
+ return ret ;
1091
+
1092
+ netdev_dbg (ds -> ports [port ], "PortState %s (was %s)\n" ,
1093
+ mv88e6xxx_port_state_names [state ],
1094
+ mv88e6xxx_port_state_names [oldstate ]);
1083
1095
}
1084
1096
1085
- abort :
1086
- mutex_unlock (& ps -> smi_mutex );
1087
1097
return ret ;
1088
1098
}
1089
1099
@@ -1146,13 +1156,11 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
1146
1156
break ;
1147
1157
}
1148
1158
1149
- netdev_dbg (ds -> ports [port ], "port state %d [%d]\n" , state , stp_state );
1150
-
1151
1159
/* mv88e6xxx_port_stp_update may be called with softirqs disabled,
1152
1160
* so we can not update the port state directly but need to schedule it.
1153
1161
*/
1154
1162
ps -> ports [port ].state = stp_state ;
1155
- set_bit (port , & ps -> port_state_update_mask );
1163
+ set_bit (port , ps -> port_state_update_mask );
1156
1164
schedule_work (& ps -> bridge_work );
1157
1165
1158
1166
return 0 ;
@@ -2228,11 +2236,15 @@ static void mv88e6xxx_bridge_work(struct work_struct *work)
2228
2236
ps = container_of (work , struct mv88e6xxx_priv_state , bridge_work );
2229
2237
ds = ((struct dsa_switch * )ps ) - 1 ;
2230
2238
2231
- while (ps -> port_state_update_mask ) {
2232
- port = __ffs (ps -> port_state_update_mask );
2233
- clear_bit (port , & ps -> port_state_update_mask );
2234
- mv88e6xxx_set_port_state (ds , port , ps -> ports [port ].state );
2235
- }
2239
+ mutex_lock (& ps -> smi_mutex );
2240
+
2241
+ for (port = 0 ; port < ps -> num_ports ; ++ port )
2242
+ if (test_and_clear_bit (port , ps -> port_state_update_mask ) &&
2243
+ _mv88e6xxx_port_state (ds , port , ps -> ports [port ].state ))
2244
+ netdev_warn (ds -> ports [port ], "failed to update state to %s\n" ,
2245
+ mv88e6xxx_port_state_names [ps -> ports [port ].state ]);
2246
+
2247
+ mutex_unlock (& ps -> smi_mutex );
2236
2248
}
2237
2249
2238
2250
static int mv88e6xxx_setup_port (struct dsa_switch * ds , int port )
0 commit comments