@@ -1137,7 +1137,7 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
11371137 if (dsa_is_dsa_port (ds , i ) || dsa_is_cpu_port (ds , i ))
11381138 continue ;
11391139
1140- if (!ds -> ports [port ].slave )
1140+ if (!ds -> ports [i ].slave )
11411141 continue ;
11421142
11431143 if (vlan .member [i ] ==
@@ -1151,8 +1151,8 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
11511151 if (!dsa_to_port (ds , i )-> bridge_dev )
11521152 continue ;
11531153
1154- dev_err (ds -> dev , "p%d: hw VLAN %d already used by %s\n" ,
1155- port , vlan .vid ,
1154+ dev_err (ds -> dev , "p%d: hw VLAN %d already used by port %d in %s\n" ,
1155+ port , vlan .vid , i ,
11561156 netdev_name (dsa_to_port (ds , i )-> bridge_dev ));
11571157 err = - EOPNOTSUPP ;
11581158 goto unlock ;
@@ -1208,6 +1208,73 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
12081208 return 0 ;
12091209}
12101210
1211+ static int mv88e6xxx_port_db_load_purge (struct mv88e6xxx_chip * chip , int port ,
1212+ const unsigned char * addr , u16 vid ,
1213+ u8 state )
1214+ {
1215+ struct mv88e6xxx_vtu_entry vlan ;
1216+ struct mv88e6xxx_atu_entry entry ;
1217+ int err ;
1218+
1219+ /* Null VLAN ID corresponds to the port private database */
1220+ if (vid == 0 )
1221+ err = mv88e6xxx_port_get_fid (chip , port , & vlan .fid );
1222+ else
1223+ err = mv88e6xxx_vtu_get (chip , vid , & vlan , false);
1224+ if (err )
1225+ return err ;
1226+
1227+ entry .state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ;
1228+ ether_addr_copy (entry .mac , addr );
1229+ eth_addr_dec (entry .mac );
1230+
1231+ err = mv88e6xxx_g1_atu_getnext (chip , vlan .fid , & entry );
1232+ if (err )
1233+ return err ;
1234+
1235+ /* Initialize a fresh ATU entry if it isn't found */
1236+ if (entry .state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ||
1237+ !ether_addr_equal (entry .mac , addr )) {
1238+ memset (& entry , 0 , sizeof (entry ));
1239+ ether_addr_copy (entry .mac , addr );
1240+ }
1241+
1242+ /* Purge the ATU entry only if no port is using it anymore */
1243+ if (state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ) {
1244+ entry .portvec &= ~BIT (port );
1245+ if (!entry .portvec )
1246+ entry .state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ;
1247+ } else {
1248+ entry .portvec |= BIT (port );
1249+ entry .state = state ;
1250+ }
1251+
1252+ return mv88e6xxx_g1_atu_loadpurge (chip , vlan .fid , & entry );
1253+ }
1254+
1255+ static int mv88e6xxx_port_add_broadcast (struct mv88e6xxx_chip * chip , int port ,
1256+ u16 vid )
1257+ {
1258+ const char broadcast [6 ] = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff };
1259+ u8 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC ;
1260+
1261+ return mv88e6xxx_port_db_load_purge (chip , port , broadcast , vid , state );
1262+ }
1263+
1264+ static int mv88e6xxx_broadcast_setup (struct mv88e6xxx_chip * chip , u16 vid )
1265+ {
1266+ int port ;
1267+ int err ;
1268+
1269+ for (port = 0 ; port < mv88e6xxx_num_ports (chip ); port ++ ) {
1270+ err = mv88e6xxx_port_add_broadcast (chip , port , vid );
1271+ if (err )
1272+ return err ;
1273+ }
1274+
1275+ return 0 ;
1276+ }
1277+
12111278static int _mv88e6xxx_port_vlan_add (struct mv88e6xxx_chip * chip , int port ,
12121279 u16 vid , u8 member )
12131280{
@@ -1220,7 +1287,11 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
12201287
12211288 vlan .member [port ] = member ;
12221289
1223- return mv88e6xxx_vtu_loadpurge (chip , & vlan );
1290+ err = mv88e6xxx_vtu_loadpurge (chip , & vlan );
1291+ if (err )
1292+ return err ;
1293+
1294+ return mv88e6xxx_broadcast_setup (chip , vid );
12241295}
12251296
12261297static void mv88e6xxx_port_vlan_add (struct dsa_switch * ds , int port ,
@@ -1324,50 +1395,6 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port,
13241395 return err ;
13251396}
13261397
1327- static int mv88e6xxx_port_db_load_purge (struct mv88e6xxx_chip * chip , int port ,
1328- const unsigned char * addr , u16 vid ,
1329- u8 state )
1330- {
1331- struct mv88e6xxx_vtu_entry vlan ;
1332- struct mv88e6xxx_atu_entry entry ;
1333- int err ;
1334-
1335- /* Null VLAN ID corresponds to the port private database */
1336- if (vid == 0 )
1337- err = mv88e6xxx_port_get_fid (chip , port , & vlan .fid );
1338- else
1339- err = mv88e6xxx_vtu_get (chip , vid , & vlan , false);
1340- if (err )
1341- return err ;
1342-
1343- entry .state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ;
1344- ether_addr_copy (entry .mac , addr );
1345- eth_addr_dec (entry .mac );
1346-
1347- err = mv88e6xxx_g1_atu_getnext (chip , vlan .fid , & entry );
1348- if (err )
1349- return err ;
1350-
1351- /* Initialize a fresh ATU entry if it isn't found */
1352- if (entry .state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ||
1353- !ether_addr_equal (entry .mac , addr )) {
1354- memset (& entry , 0 , sizeof (entry ));
1355- ether_addr_copy (entry .mac , addr );
1356- }
1357-
1358- /* Purge the ATU entry only if no port is using it anymore */
1359- if (state == MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ) {
1360- entry .portvec &= ~BIT (port );
1361- if (!entry .portvec )
1362- entry .state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED ;
1363- } else {
1364- entry .portvec |= BIT (port );
1365- entry .state = state ;
1366- }
1367-
1368- return mv88e6xxx_g1_atu_loadpurge (chip , vlan .fid , & entry );
1369- }
1370-
13711398static int mv88e6xxx_port_fdb_add (struct dsa_switch * ds , int port ,
13721399 const unsigned char * addr , u16 vid )
13731400{
@@ -2049,6 +2076,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
20492076 if (err )
20502077 goto unlock ;
20512078
2079+ err = mv88e6xxx_broadcast_setup (chip , 0 );
2080+ if (err )
2081+ goto unlock ;
2082+
20522083 err = mv88e6xxx_pot_setup (chip );
20532084 if (err )
20542085 goto unlock ;
0 commit comments