@@ -964,7 +964,7 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
964964{
965965 int ret ;
966966
967- ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , 0x01 , fid );
967+ ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_FID , fid );
968968 if (ret < 0 )
969969 return ret ;
970970
@@ -1091,7 +1091,7 @@ int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
10911091 ps -> bridge_mask [fid ] = br_port_mask ;
10921092
10931093 if (fid != ps -> fid [port ]) {
1094- ps -> fid_mask |= 1 << ps -> fid [port ];
1094+ clear_bit ( ps -> fid [port ], ps -> fid_bitmap ) ;
10951095 ps -> fid [port ] = fid ;
10961096 ret = _mv88e6xxx_update_bridge_config (ds , fid );
10971097 }
@@ -1125,16 +1125,24 @@ int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
11251125
11261126 mutex_lock (& ps -> smi_mutex );
11271127
1128- newfid = __ffs (ps -> fid_mask );
1128+ newfid = find_next_zero_bit (ps -> fid_bitmap , VLAN_N_VID , 1 );
1129+ if (unlikely (newfid > ps -> num_ports )) {
1130+ netdev_err (ds -> ports [port ], "all first %d FIDs are used\n" ,
1131+ ps -> num_ports );
1132+ ret = - ENOSPC ;
1133+ goto unlock ;
1134+ }
1135+
11291136 ps -> fid [port ] = newfid ;
1130- ps -> fid_mask &= ~( 1 << newfid );
1137+ set_bit ( newfid , ps -> fid_bitmap );
11311138 ps -> bridge_mask [fid ] &= ~(1 << port );
11321139 ps -> bridge_mask [newfid ] = 1 << port ;
11331140
11341141 ret = _mv88e6xxx_update_bridge_config (ds , fid );
11351142 if (!ret )
11361143 ret = _mv88e6xxx_update_bridge_config (ds , newfid );
11371144
1145+ unlock :
11381146 mutex_unlock (& ps -> smi_mutex );
11391147
11401148 return ret ;
@@ -1174,8 +1182,8 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
11741182 return 0 ;
11751183}
11761184
1177- static int __mv88e6xxx_write_addr (struct dsa_switch * ds ,
1178- const unsigned char * addr )
1185+ static int _mv88e6xxx_atu_mac_write (struct dsa_switch * ds ,
1186+ const u8 addr [ ETH_ALEN ] )
11791187{
11801188 int i , ret ;
11811189
@@ -1190,7 +1198,7 @@ static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
11901198 return 0 ;
11911199}
11921200
1193- static int __mv88e6xxx_read_addr (struct dsa_switch * ds , unsigned char * addr )
1201+ static int _mv88e6xxx_atu_mac_read (struct dsa_switch * ds , u8 addr [ ETH_ALEN ] )
11941202{
11951203 int i , ret ;
11961204
@@ -1206,109 +1214,190 @@ static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
12061214 return 0 ;
12071215}
12081216
1209- static int __mv88e6xxx_port_fdb_cmd (struct dsa_switch * ds , int port ,
1210- const unsigned char * addr , int state )
1217+ static int _mv88e6xxx_atu_load (struct dsa_switch * ds ,
1218+ struct mv88e6xxx_atu_entry * entry )
12111219{
1212- struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1213- u8 fid = ps -> fid [port ];
1220+ u16 reg = 0 ;
12141221 int ret ;
12151222
12161223 ret = _mv88e6xxx_atu_wait (ds );
12171224 if (ret < 0 )
12181225 return ret ;
12191226
1220- ret = __mv88e6xxx_write_addr (ds , addr );
1227+ ret = _mv88e6xxx_atu_mac_write (ds , entry -> mac );
12211228 if (ret < 0 )
12221229 return ret ;
12231230
1224- ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_DATA ,
1225- (0x10 << port ) | state );
1226- if (ret )
1231+ if (entry -> state != GLOBAL_ATU_DATA_STATE_UNUSED ) {
1232+ unsigned int mask , shift ;
1233+
1234+ if (entry -> trunk ) {
1235+ reg |= GLOBAL_ATU_DATA_TRUNK ;
1236+ mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK ;
1237+ shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT ;
1238+ } else {
1239+ mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK ;
1240+ shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT ;
1241+ }
1242+
1243+ reg |= (entry -> portv_trunkid << shift ) & mask ;
1244+ }
1245+
1246+ reg |= entry -> state & GLOBAL_ATU_DATA_STATE_MASK ;
1247+
1248+ ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_DATA , reg );
1249+ if (ret < 0 )
12271250 return ret ;
12281251
1229- ret = _mv88e6xxx_atu_cmd (ds , fid , GLOBAL_ATU_OP_LOAD_DB );
1252+ return _mv88e6xxx_atu_cmd (ds , entry -> fid , GLOBAL_ATU_OP_LOAD_DB );
1253+ }
12301254
1231- return ret ;
1255+ static int _mv88e6xxx_atu_getnext (struct dsa_switch * ds , u16 fid ,
1256+ const u8 addr [ETH_ALEN ],
1257+ struct mv88e6xxx_atu_entry * entry )
1258+ {
1259+ struct mv88e6xxx_atu_entry next = { 0 };
1260+ int ret ;
1261+
1262+ next .fid = fid ;
1263+
1264+ ret = _mv88e6xxx_atu_wait (ds );
1265+ if (ret < 0 )
1266+ return ret ;
1267+
1268+ ret = _mv88e6xxx_atu_mac_write (ds , addr );
1269+ if (ret < 0 )
1270+ return ret ;
1271+
1272+ ret = _mv88e6xxx_atu_cmd (ds , fid , GLOBAL_ATU_OP_GET_NEXT_DB );
1273+ if (ret < 0 )
1274+ return ret ;
1275+
1276+ ret = _mv88e6xxx_atu_mac_read (ds , next .mac );
1277+ if (ret < 0 )
1278+ return ret ;
1279+
1280+ ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL , GLOBAL_ATU_DATA );
1281+ if (ret < 0 )
1282+ return ret ;
1283+
1284+ next .state = ret & GLOBAL_ATU_DATA_STATE_MASK ;
1285+ if (next .state != GLOBAL_ATU_DATA_STATE_UNUSED ) {
1286+ unsigned int mask , shift ;
1287+
1288+ if (ret & GLOBAL_ATU_DATA_TRUNK ) {
1289+ next .trunk = true;
1290+ mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK ;
1291+ shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT ;
1292+ } else {
1293+ next .trunk = false;
1294+ mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK ;
1295+ shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT ;
1296+ }
1297+
1298+ next .portv_trunkid = (ret & mask ) >> shift ;
1299+ }
1300+
1301+ * entry = next ;
1302+ return 0 ;
12321303}
12331304
1234- int mv88e6xxx_port_fdb_add (struct dsa_switch * ds , int port ,
1235- const unsigned char * addr , u16 vid )
1305+ static int _mv88e6xxx_port_vid_to_fid (struct dsa_switch * ds , int port , u16 vid )
12361306{
1237- int state = is_multicast_ether_addr (addr ) ?
1307+ struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1308+
1309+ if (vid == 0 )
1310+ return ps -> fid [port ];
1311+
1312+ return - ENOENT ;
1313+ }
1314+
1315+ static int _mv88e6xxx_port_fdb_load (struct dsa_switch * ds , int port , u16 vid ,
1316+ const u8 addr [ETH_ALEN ], u8 state )
1317+ {
1318+ struct mv88e6xxx_atu_entry entry = { 0 };
1319+ int ret ;
1320+
1321+ ret = _mv88e6xxx_port_vid_to_fid (ds , port , vid );
1322+ if (ret < 0 )
1323+ return ret ;
1324+
1325+ entry .fid = ret ;
1326+ entry .state = state ;
1327+ ether_addr_copy (entry .mac , addr );
1328+ if (state != GLOBAL_ATU_DATA_STATE_UNUSED ) {
1329+ entry .trunk = false;
1330+ entry .portv_trunkid = BIT (port );
1331+ }
1332+
1333+ return _mv88e6xxx_atu_load (ds , & entry );
1334+ }
1335+
1336+ int mv88e6xxx_port_fdb_add (struct dsa_switch * ds , int port , u16 vid ,
1337+ const u8 addr [ETH_ALEN ])
1338+ {
1339+ struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1340+ u8 state = is_multicast_ether_addr (addr ) ?
12381341 GLOBAL_ATU_DATA_STATE_MC_STATIC :
12391342 GLOBAL_ATU_DATA_STATE_UC_STATIC ;
1240- struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
12411343 int ret ;
12421344
12431345 mutex_lock (& ps -> smi_mutex );
1244- ret = __mv88e6xxx_port_fdb_cmd (ds , port , addr , state );
1346+ ret = _mv88e6xxx_port_fdb_load (ds , port , vid , addr , state );
12451347 mutex_unlock (& ps -> smi_mutex );
12461348
12471349 return ret ;
12481350}
12491351
1250- int mv88e6xxx_port_fdb_del (struct dsa_switch * ds , int port ,
1251- const unsigned char * addr , u16 vid )
1352+ int mv88e6xxx_port_fdb_del (struct dsa_switch * ds , int port , u16 vid ,
1353+ const u8 addr [ ETH_ALEN ] )
12521354{
12531355 struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1356+ u8 state = GLOBAL_ATU_DATA_STATE_UNUSED ;
12541357 int ret ;
12551358
12561359 mutex_lock (& ps -> smi_mutex );
1257- ret = __mv88e6xxx_port_fdb_cmd (ds , port , addr ,
1258- GLOBAL_ATU_DATA_STATE_UNUSED );
1360+ ret = _mv88e6xxx_port_fdb_load (ds , port , vid , addr , state );
12591361 mutex_unlock (& ps -> smi_mutex );
12601362
12611363 return ret ;
12621364}
12631365
1264- static int __mv88e6xxx_port_getnext (struct dsa_switch * ds , int port ,
1265- unsigned char * addr , bool * is_static )
1366+ int mv88e6xxx_port_fdb_getnext (struct dsa_switch * ds , int port , u16 * vid ,
1367+ u8 addr [ ETH_ALEN ] , bool * is_static )
12661368{
12671369 struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1268- u8 fid = ps -> fid [port ];
1269- int ret , state ;
1370+ struct mv88e6xxx_atu_entry next ;
1371+ u16 fid ;
1372+ int ret ;
12701373
1271- ret = _mv88e6xxx_atu_wait (ds );
1272- if (ret < 0 )
1273- return ret ;
1374+ mutex_lock (& ps -> smi_mutex );
12741375
1275- ret = __mv88e6xxx_write_addr (ds , addr );
1376+ ret = _mv88e6xxx_port_vid_to_fid (ds , port , * vid );
12761377 if (ret < 0 )
1277- return ret ;
1378+ goto unlock ;
1379+ fid = ret ;
12781380
12791381 do {
1280- ret = _mv88e6xxx_atu_cmd (ds , fid , GLOBAL_ATU_OP_GET_NEXT_DB );
1281- if (ret < 0 )
1282- return ret ;
1382+ if (is_broadcast_ether_addr (addr )) {
1383+ ret = - ENOENT ;
1384+ goto unlock ;
1385+ }
12831386
1284- ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL , GLOBAL_ATU_DATA );
1387+ ret = _mv88e6xxx_atu_getnext (ds , fid , addr , & next );
12851388 if (ret < 0 )
1286- return ret ;
1287- state = ret & GLOBAL_ATU_DATA_STATE_MASK ;
1288- if (state == GLOBAL_ATU_DATA_STATE_UNUSED )
1289- return - ENOENT ;
1290- } while (!(((ret >> 4 ) & 0xff ) & (1 << port )));
1389+ goto unlock ;
12911390
1292- ret = __mv88e6xxx_read_addr (ds , addr );
1293- if (ret < 0 )
1294- return ret ;
1391+ ether_addr_copy (addr , next .mac );
12951392
1296- * is_static = state == (is_multicast_ether_addr (addr ) ?
1297- GLOBAL_ATU_DATA_STATE_MC_STATIC :
1298- GLOBAL_ATU_DATA_STATE_UC_STATIC );
1299-
1300- return 0 ;
1301- }
1302-
1303- /* get next entry for port */
1304- int mv88e6xxx_port_fdb_getnext (struct dsa_switch * ds , int port ,
1305- unsigned char * addr , bool * is_static )
1306- {
1307- struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1308- int ret ;
1393+ if (next .state == GLOBAL_ATU_DATA_STATE_UNUSED )
1394+ continue ;
1395+ } while (next .trunk || (next .portv_trunkid & BIT (port )) == 0 );
13091396
1310- mutex_lock (& ps -> smi_mutex );
1311- ret = __mv88e6xxx_port_getnext (ds , port , addr , is_static );
1397+ * is_static = next .state == (is_multicast_ether_addr (addr ) ?
1398+ GLOBAL_ATU_DATA_STATE_MC_STATIC :
1399+ GLOBAL_ATU_DATA_STATE_UC_STATIC );
1400+ unlock :
13121401 mutex_unlock (& ps -> smi_mutex );
13131402
13141403 return ret ;
@@ -1552,9 +1641,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
15521641 * ports, and allow each of the 'real' ports to only talk to
15531642 * the upstream port.
15541643 */
1555- fid = __ffs ( ps -> fid_mask ) ;
1644+ fid = port + 1 ;
15561645 ps -> fid [port ] = fid ;
1557- ps -> fid_mask &= ~( 1 << fid );
1646+ set_bit ( fid , ps -> fid_bitmap );
15581647
15591648 if (!dsa_is_cpu_port (ds , port ))
15601649 ps -> bridge_mask [fid ] = 1 << port ;
@@ -1651,7 +1740,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds,
16511740 unsigned char addr [6 ];
16521741 int ret , data , state ;
16531742
1654- ret = __mv88e6xxx_write_addr (ds , bcast );
1743+ ret = _mv88e6xxx_atu_mac_write (ds , bcast );
16551744 if (ret < 0 )
16561745 return ret ;
16571746
@@ -1666,7 +1755,7 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds,
16661755 state = data & GLOBAL_ATU_DATA_STATE_MASK ;
16671756 if (state == GLOBAL_ATU_DATA_STATE_UNUSED )
16681757 break ;
1669- ret = __mv88e6xxx_read_addr (ds , addr );
1758+ ret = _mv88e6xxx_atu_mac_read (ds , addr );
16701759 if (ret < 0 )
16711760 return ret ;
16721761 mv88e6xxx_atu_show_entry (s , dbnum , addr , data );
@@ -1853,8 +1942,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
18531942
18541943 ps -> id = REG_READ (REG_PORT (0 ), PORT_SWITCH_ID ) & 0xfff0 ;
18551944
1856- ps -> fid_mask = (1 << DSA_MAX_PORTS ) - 1 ;
1857-
18581945 INIT_WORK (& ps -> bridge_work , mv88e6xxx_bridge_work );
18591946
18601947 name = kasprintf (GFP_KERNEL , "dsa%d" , ds -> index );
0 commit comments