@@ -482,6 +482,50 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
482
482
return false;
483
483
}
484
484
485
+ static unsigned int mv88e6xxx_num_databases (struct dsa_switch * ds )
486
+ {
487
+ struct mv88e6xxx_priv_state * ps = ds_to_priv (ds );
488
+
489
+ /* The following devices have 4-bit identifiers for 16 databases */
490
+ if (ps -> id == PORT_SWITCH_ID_6061 )
491
+ return 16 ;
492
+
493
+ /* The following devices have 6-bit identifiers for 64 databases */
494
+ if (ps -> id == PORT_SWITCH_ID_6065 )
495
+ return 64 ;
496
+
497
+ /* The following devices have 8-bit identifiers for 256 databases */
498
+ if (mv88e6xxx_6095_family (ds ) || mv88e6xxx_6185_family (ds ))
499
+ return 256 ;
500
+
501
+ /* The following devices have 12-bit identifiers for 4096 databases */
502
+ if (mv88e6xxx_6097_family (ds ) || mv88e6xxx_6165_family (ds ) ||
503
+ mv88e6xxx_6351_family (ds ) || mv88e6xxx_6352_family (ds ))
504
+ return 4096 ;
505
+
506
+ return 0 ;
507
+ }
508
+
509
+ static bool mv88e6xxx_has_fid_reg (struct dsa_switch * ds )
510
+ {
511
+ /* Does the device have dedicated FID registers for ATU and VTU ops? */
512
+ if (mv88e6xxx_6097_family (ds ) || mv88e6xxx_6165_family (ds ) ||
513
+ mv88e6xxx_6351_family (ds ) || mv88e6xxx_6352_family (ds ))
514
+ return true;
515
+
516
+ return false;
517
+ }
518
+
519
+ static bool mv88e6xxx_has_stu (struct dsa_switch * ds )
520
+ {
521
+ /* Does the device have STU and dedicated SID registers for VTU ops? */
522
+ if (mv88e6xxx_6097_family (ds ) || mv88e6xxx_6165_family (ds ) ||
523
+ mv88e6xxx_6351_family (ds ) || mv88e6xxx_6352_family (ds ))
524
+ return true;
525
+
526
+ return false;
527
+ }
528
+
485
529
/* We expect the switch to perform auto negotiation if there is a real
486
530
* phy. However, in the case of a fixed link phy, we force the port
487
531
* settings from the fixed link settings.
@@ -951,10 +995,30 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
951
995
return ret ;
952
996
}
953
997
954
- static int _mv88e6xxx_atu_cmd (struct dsa_switch * ds , u16 cmd )
998
+ static int _mv88e6xxx_atu_cmd (struct dsa_switch * ds , u16 fid , u16 cmd )
955
999
{
956
1000
int ret ;
957
1001
1002
+ if (mv88e6xxx_has_fid_reg (ds )) {
1003
+ ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_FID , fid );
1004
+ if (ret < 0 )
1005
+ return ret ;
1006
+ } else if (mv88e6xxx_num_databases (ds ) == 256 ) {
1007
+ /* ATU DBNum[7:4] are located in ATU Control 15:12 */
1008
+ ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL , GLOBAL_ATU_CONTROL );
1009
+ if (ret < 0 )
1010
+ return ret ;
1011
+
1012
+ ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_CONTROL ,
1013
+ (ret & 0xfff ) |
1014
+ ((fid << 8 ) & 0xf000 ));
1015
+ if (ret < 0 )
1016
+ return ret ;
1017
+
1018
+ /* ATU DBNum[3:0] are located in ATU Operation 3:0 */
1019
+ cmd |= fid & 0xf ;
1020
+ }
1021
+
958
1022
ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_OP , cmd );
959
1023
if (ret < 0 )
960
1024
return ret ;
@@ -1001,19 +1065,14 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds,
1001
1065
return err ;
1002
1066
1003
1067
if (entry -> fid ) {
1004
- err = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_FID ,
1005
- entry -> fid );
1006
- if (err )
1007
- return err ;
1008
-
1009
1068
op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB :
1010
1069
GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB ;
1011
1070
} else {
1012
1071
op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL :
1013
1072
GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC ;
1014
1073
}
1015
1074
1016
- return _mv88e6xxx_atu_cmd (ds , op );
1075
+ return _mv88e6xxx_atu_cmd (ds , entry -> fid , op );
1017
1076
}
1018
1077
1019
1078
static int _mv88e6xxx_atu_flush (struct dsa_switch * ds , u16 fid , bool static_too )
@@ -1321,15 +1380,27 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds,
1321
1380
if (ret < 0 )
1322
1381
return ret ;
1323
1382
1324
- if (mv88e6xxx_6097_family (ds ) || mv88e6xxx_6165_family (ds ) ||
1325
- mv88e6xxx_6351_family (ds ) || mv88e6xxx_6352_family (ds )) {
1383
+ if (mv88e6xxx_has_fid_reg (ds )) {
1326
1384
ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL ,
1327
1385
GLOBAL_VTU_FID );
1328
1386
if (ret < 0 )
1329
1387
return ret ;
1330
1388
1331
1389
next .fid = ret & GLOBAL_VTU_FID_MASK ;
1390
+ } else if (mv88e6xxx_num_databases (ds ) == 256 ) {
1391
+ /* VTU DBNum[7:4] are located in VTU Operation 11:8, and
1392
+ * VTU DBNum[3:0] are located in VTU Operation 3:0
1393
+ */
1394
+ ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL ,
1395
+ GLOBAL_VTU_OP );
1396
+ if (ret < 0 )
1397
+ return ret ;
1398
+
1399
+ next .fid = (ret & 0xf00 ) >> 4 ;
1400
+ next .fid |= ret & 0xf ;
1401
+ }
1332
1402
1403
+ if (mv88e6xxx_has_stu (ds )) {
1333
1404
ret = _mv88e6xxx_reg_read (ds , REG_GLOBAL ,
1334
1405
GLOBAL_VTU_SID );
1335
1406
if (ret < 0 )
@@ -1397,6 +1468,7 @@ int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
1397
1468
static int _mv88e6xxx_vtu_loadpurge (struct dsa_switch * ds ,
1398
1469
struct mv88e6xxx_vtu_stu_entry * entry )
1399
1470
{
1471
+ u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE ;
1400
1472
u16 reg = 0 ;
1401
1473
int ret ;
1402
1474
@@ -1412,17 +1484,24 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
1412
1484
if (ret < 0 )
1413
1485
return ret ;
1414
1486
1415
- if (mv88e6xxx_6097_family (ds ) || mv88e6xxx_6165_family (ds ) ||
1416
- mv88e6xxx_6351_family (ds ) || mv88e6xxx_6352_family (ds )) {
1487
+ if (mv88e6xxx_has_stu (ds )) {
1417
1488
reg = entry -> sid & GLOBAL_VTU_SID_MASK ;
1418
1489
ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_VTU_SID , reg );
1419
1490
if (ret < 0 )
1420
1491
return ret ;
1492
+ }
1421
1493
1494
+ if (mv88e6xxx_has_fid_reg (ds )) {
1422
1495
reg = entry -> fid & GLOBAL_VTU_FID_MASK ;
1423
1496
ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_VTU_FID , reg );
1424
1497
if (ret < 0 )
1425
1498
return ret ;
1499
+ } else if (mv88e6xxx_num_databases (ds ) == 256 ) {
1500
+ /* VTU DBNum[7:4] are located in VTU Operation 11:8, and
1501
+ * VTU DBNum[3:0] are located in VTU Operation 3:0
1502
+ */
1503
+ op |= (entry -> fid & 0xf0 ) << 8 ;
1504
+ op |= entry -> fid & 0xf ;
1426
1505
}
1427
1506
1428
1507
reg = GLOBAL_VTU_VID_VALID ;
@@ -1432,7 +1511,7 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
1432
1511
if (ret < 0 )
1433
1512
return ret ;
1434
1513
1435
- return _mv88e6xxx_vtu_cmd (ds , GLOBAL_VTU_OP_VTU_LOAD_PURGE );
1514
+ return _mv88e6xxx_vtu_cmd (ds , op );
1436
1515
}
1437
1516
1438
1517
static int _mv88e6xxx_stu_getnext (struct dsa_switch * ds , u8 sid ,
@@ -1511,9 +1590,17 @@ static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds,
1511
1590
static int _mv88e6xxx_port_fid (struct dsa_switch * ds , int port , u16 * new ,
1512
1591
u16 * old )
1513
1592
{
1593
+ u16 upper_mask ;
1514
1594
u16 fid ;
1515
1595
int ret ;
1516
1596
1597
+ if (mv88e6xxx_num_databases (ds ) == 4096 )
1598
+ upper_mask = 0xff ;
1599
+ else if (mv88e6xxx_num_databases (ds ) == 256 )
1600
+ upper_mask = 0xf ;
1601
+ else
1602
+ return - EOPNOTSUPP ;
1603
+
1517
1604
/* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
1518
1605
ret = _mv88e6xxx_reg_read (ds , REG_PORT (port ), PORT_BASE_VLAN );
1519
1606
if (ret < 0 )
@@ -1536,11 +1623,11 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
1536
1623
if (ret < 0 )
1537
1624
return ret ;
1538
1625
1539
- fid |= (ret & PORT_CONTROL_1_FID_11_4_MASK ) << 4 ;
1626
+ fid |= (ret & upper_mask ) << 4 ;
1540
1627
1541
1628
if (new ) {
1542
- ret &= ~PORT_CONTROL_1_FID_11_4_MASK ;
1543
- ret |= (* new >> 4 ) & PORT_CONTROL_1_FID_11_4_MASK ;
1629
+ ret &= ~upper_mask ;
1630
+ ret |= (* new >> 4 ) & upper_mask ;
1544
1631
1545
1632
ret = _mv88e6xxx_reg_write (ds , REG_PORT (port ), PORT_CONTROL_1 ,
1546
1633
ret );
@@ -1604,7 +1691,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
1604
1691
* databases are not needed. Return the next positive available.
1605
1692
*/
1606
1693
* fid = find_next_zero_bit (fid_bitmap , MV88E6XXX_N_FID , 1 );
1607
- if (unlikely (* fid == MV88E6XXX_N_FID ))
1694
+ if (unlikely (* fid >= mv88e6xxx_num_databases ( ds ) ))
1608
1695
return - ENOSPC ;
1609
1696
1610
1697
/* Clear the database */
@@ -1965,11 +2052,7 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
1965
2052
if (ret < 0 )
1966
2053
return ret ;
1967
2054
1968
- ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_FID , entry -> fid );
1969
- if (ret < 0 )
1970
- return ret ;
1971
-
1972
- return _mv88e6xxx_atu_cmd (ds , GLOBAL_ATU_OP_LOAD_DB );
2055
+ return _mv88e6xxx_atu_cmd (ds , entry -> fid , GLOBAL_ATU_OP_LOAD_DB );
1973
2056
}
1974
2057
1975
2058
static int _mv88e6xxx_port_fdb_load (struct dsa_switch * ds , int port ,
@@ -2052,11 +2135,7 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid,
2052
2135
if (ret < 0 )
2053
2136
return ret ;
2054
2137
2055
- ret = _mv88e6xxx_reg_write (ds , REG_GLOBAL , GLOBAL_ATU_FID , fid );
2056
- if (ret < 0 )
2057
- return ret ;
2058
-
2059
- ret = _mv88e6xxx_atu_cmd (ds , GLOBAL_ATU_OP_GET_NEXT_DB );
2138
+ ret = _mv88e6xxx_atu_cmd (ds , fid , GLOBAL_ATU_OP_GET_NEXT_DB );
2060
2139
if (ret < 0 )
2061
2140
return ret ;
2062
2141
@@ -2444,7 +2523,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
2444
2523
reg = 0 ;
2445
2524
if (mv88e6xxx_6352_family (ds ) || mv88e6xxx_6351_family (ds ) ||
2446
2525
mv88e6xxx_6165_family (ds ) || mv88e6xxx_6097_family (ds ) ||
2447
- mv88e6xxx_6095_family (ds ) || mv88e6xxx_6320_family (ds ))
2526
+ mv88e6xxx_6095_family (ds ) || mv88e6xxx_6320_family (ds ) ||
2527
+ mv88e6xxx_6185_family (ds ))
2448
2528
reg = PORT_CONTROL_2_MAP_DA ;
2449
2529
2450
2530
if (mv88e6xxx_6352_family (ds ) || mv88e6xxx_6351_family (ds ) ||
0 commit comments