@@ -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
@@ -1269,12 +1269,14 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
12691269 return ret ;
12701270}
12711271
1272- static int __mv88e6xxx_port_getnext (struct dsa_switch * ds , int port ,
1273- unsigned char * addr , bool * is_static )
1272+ static int _mv88e6xxx_atu_getnext (struct dsa_switch * ds , u16 fid ,
1273+ const u8 addr [ETH_ALEN ],
1274+ struct mv88e6xxx_atu_entry * entry )
12741275{
1275- struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1276- u8 fid = ps -> fid [port ];
1277- int ret , state ;
1276+ struct mv88e6xxx_atu_entry next = { 0 };
1277+ int ret ;
1278+
1279+ next .fid = fid ;
12781280
12791281 ret = _mv88e6xxx_atu_wait (ds );
12801282 if (ret < 0 )
@@ -1284,39 +1286,84 @@ static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port,
12841286 if (ret < 0 )
12851287 return ret ;
12861288
1287- do {
1288- ret = _mv88e6xxx_atu_cmd (ds , fid , GLOBAL_ATU_OP_GET_NEXT_DB );
1289- if (ret < 0 )
1290- return ret ;
1289+ ret = _mv88e6xxx_atu_cmd (ds , fid , GLOBAL_ATU_OP_GET_NEXT_DB );
1290+ if (ret < 0 )
1291+ return ret ;
12911292
1292- ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL , GLOBAL_ATU_DATA );
1293- if (ret < 0 )
1294- return ret ;
1295- state = ret & GLOBAL_ATU_DATA_STATE_MASK ;
1296- if (state == GLOBAL_ATU_DATA_STATE_UNUSED )
1297- return - ENOENT ;
1298- } while (!(((ret >> 4 ) & 0xff ) & (1 << port )));
1293+ ret = _mv88e6xxx_atu_mac_read (ds , next .mac );
1294+ if (ret < 0 )
1295+ return ret ;
12991296
1300- ret = _mv88e6xxx_atu_mac_read (ds , addr );
1297+ ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL , GLOBAL_ATU_DATA );
13011298 if (ret < 0 )
13021299 return ret ;
13031300
1304- * is_static = state == (is_multicast_ether_addr (addr ) ?
1305- GLOBAL_ATU_DATA_STATE_MC_STATIC :
1306- GLOBAL_ATU_DATA_STATE_UC_STATIC );
1301+ next .state = ret & GLOBAL_ATU_DATA_STATE_MASK ;
1302+ if (next .state != GLOBAL_ATU_DATA_STATE_UNUSED ) {
1303+ unsigned int mask , shift ;
1304+
1305+ if (ret & GLOBAL_ATU_DATA_TRUNK ) {
1306+ next .trunk = true;
1307+ mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK ;
1308+ shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT ;
1309+ } else {
1310+ next .trunk = false;
1311+ mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK ;
1312+ shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT ;
1313+ }
1314+
1315+ next .portv_trunkid = (ret & mask ) >> shift ;
1316+ }
13071317
1318+ * entry = next ;
13081319 return 0 ;
13091320}
13101321
1311- /* get next entry for port */
1312- int mv88e6xxx_port_fdb_getnext (struct dsa_switch * ds , int port ,
1313- unsigned char * addr , bool * is_static )
1322+ static int _mv88e6xxx_port_vid_to_fid (struct dsa_switch * ds , int port , u16 vid )
13141323{
13151324 struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1325+
1326+ if (vid == 0 )
1327+ return ps -> fid [port ];
1328+
1329+ return - ENOENT ;
1330+ }
1331+
1332+ int mv88e6xxx_port_fdb_getnext (struct dsa_switch * ds , int port , u16 * vid ,
1333+ u8 addr [ETH_ALEN ], bool * is_static )
1334+ {
1335+ struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
1336+ struct mv88e6xxx_atu_entry next ;
1337+ u16 fid ;
13161338 int ret ;
13171339
13181340 mutex_lock (& ps -> smi_mutex );
1319- ret = __mv88e6xxx_port_getnext (ds , port , addr , is_static );
1341+
1342+ ret = _mv88e6xxx_port_vid_to_fid (ds , port , * vid );
1343+ if (ret < 0 )
1344+ goto unlock ;
1345+ fid = ret ;
1346+
1347+ do {
1348+ if (is_broadcast_ether_addr (addr )) {
1349+ ret = - ENOENT ;
1350+ goto unlock ;
1351+ }
1352+
1353+ ret = _mv88e6xxx_atu_getnext (ds , fid , addr , & next );
1354+ if (ret < 0 )
1355+ goto unlock ;
1356+
1357+ ether_addr_copy (addr , next .mac );
1358+
1359+ if (next .state == GLOBAL_ATU_DATA_STATE_UNUSED )
1360+ continue ;
1361+ } while (next .trunk || (next .portv_trunkid & BIT (port )) == 0 );
1362+
1363+ * is_static = next .state == (is_multicast_ether_addr (addr ) ?
1364+ GLOBAL_ATU_DATA_STATE_MC_STATIC :
1365+ GLOBAL_ATU_DATA_STATE_UC_STATIC );
1366+ unlock :
13201367 mutex_unlock (& ps -> smi_mutex );
13211368
13221369 return ret ;
0 commit comments