Skip to content

Commit 6e33804

Browse files
committed
Merge branch 'mv88e6131-hw-bridging-6185'
Vivien Didelot says: ==================== net: dsa: mv88e6131: HW bridging support for 6185 All packets passing through a switch of the 6185 family are currently all directed to the CPU port. This means that port bridging is software driven. To enable hardware bridging for this switch family, we need to implement the port mapping operations, the FDB operations, and optionally the VLAN operations (for 802.1Q and VLAN filtering aware systems). However this family only has 256 FDBs indexed by 8-bit identifiers, opposed to 4096 FDBs with 12-bit identifiers for other families such as 6352. It also doesn't have dedicated FID registers for ATU and VTU operations. This patchset fixes these differences, and enable hardware bridging for 6185. Changes v1 -> v2: - Describe the different numbers of databases and prefer a feature-based logic over the current ID/family-based logic. ==================== Tested-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
2 parents 9ef280c + 26892ff commit 6e33804

File tree

2 files changed

+118
-27
lines changed

2 files changed

+118
-27
lines changed

drivers/net/dsa/mv88e6131.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,17 @@ struct dsa_switch_driver mv88e6131_switch_driver = {
169169
.get_ethtool_stats = mv88e6xxx_get_ethtool_stats,
170170
.get_sset_count = mv88e6xxx_get_sset_count,
171171
.adjust_link = mv88e6xxx_adjust_link,
172+
.port_bridge_join = mv88e6xxx_port_bridge_join,
173+
.port_bridge_leave = mv88e6xxx_port_bridge_leave,
174+
.port_vlan_filtering = mv88e6xxx_port_vlan_filtering,
175+
.port_vlan_prepare = mv88e6xxx_port_vlan_prepare,
176+
.port_vlan_add = mv88e6xxx_port_vlan_add,
177+
.port_vlan_del = mv88e6xxx_port_vlan_del,
178+
.port_vlan_dump = mv88e6xxx_port_vlan_dump,
179+
.port_fdb_prepare = mv88e6xxx_port_fdb_prepare,
180+
.port_fdb_add = mv88e6xxx_port_fdb_add,
181+
.port_fdb_del = mv88e6xxx_port_fdb_del,
182+
.port_fdb_dump = mv88e6xxx_port_fdb_dump,
172183
};
173184

174185
MODULE_ALIAS("platform:mv88e6085");

drivers/net/dsa/mv88e6xxx.c

Lines changed: 107 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,50 @@ static bool mv88e6xxx_6352_family(struct dsa_switch *ds)
482482
return false;
483483
}
484484

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+
485529
/* We expect the switch to perform auto negotiation if there is a real
486530
* phy. However, in the case of a fixed link phy, we force the port
487531
* settings from the fixed link settings.
@@ -951,10 +995,30 @@ int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
951995
return ret;
952996
}
953997

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)
955999
{
9561000
int ret;
9571001

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+
9581022
ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd);
9591023
if (ret < 0)
9601024
return ret;
@@ -1001,19 +1065,14 @@ static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds,
10011065
return err;
10021066

10031067
if (entry->fid) {
1004-
err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID,
1005-
entry->fid);
1006-
if (err)
1007-
return err;
1008-
10091068
op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB :
10101069
GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB;
10111070
} else {
10121071
op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL :
10131072
GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC;
10141073
}
10151074

1016-
return _mv88e6xxx_atu_cmd(ds, op);
1075+
return _mv88e6xxx_atu_cmd(ds, entry->fid, op);
10171076
}
10181077

10191078
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,
13211380
if (ret < 0)
13221381
return ret;
13231382

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)) {
13261384
ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
13271385
GLOBAL_VTU_FID);
13281386
if (ret < 0)
13291387
return ret;
13301388

13311389
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+
}
13321402

1403+
if (mv88e6xxx_has_stu(ds)) {
13331404
ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL,
13341405
GLOBAL_VTU_SID);
13351406
if (ret < 0)
@@ -1397,6 +1468,7 @@ int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port,
13971468
static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
13981469
struct mv88e6xxx_vtu_stu_entry *entry)
13991470
{
1471+
u16 op = GLOBAL_VTU_OP_VTU_LOAD_PURGE;
14001472
u16 reg = 0;
14011473
int ret;
14021474

@@ -1412,17 +1484,24 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
14121484
if (ret < 0)
14131485
return ret;
14141486

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)) {
14171488
reg = entry->sid & GLOBAL_VTU_SID_MASK;
14181489
ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_SID, reg);
14191490
if (ret < 0)
14201491
return ret;
1492+
}
14211493

1494+
if (mv88e6xxx_has_fid_reg(ds)) {
14221495
reg = entry->fid & GLOBAL_VTU_FID_MASK;
14231496
ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_FID, reg);
14241497
if (ret < 0)
14251498
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;
14261505
}
14271506

14281507
reg = GLOBAL_VTU_VID_VALID;
@@ -1432,7 +1511,7 @@ static int _mv88e6xxx_vtu_loadpurge(struct dsa_switch *ds,
14321511
if (ret < 0)
14331512
return ret;
14341513

1435-
return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_VTU_LOAD_PURGE);
1514+
return _mv88e6xxx_vtu_cmd(ds, op);
14361515
}
14371516

14381517
static int _mv88e6xxx_stu_getnext(struct dsa_switch *ds, u8 sid,
@@ -1511,9 +1590,17 @@ static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds,
15111590
static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
15121591
u16 *old)
15131592
{
1593+
u16 upper_mask;
15141594
u16 fid;
15151595
int ret;
15161596

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+
15171604
/* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
15181605
ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
15191606
if (ret < 0)
@@ -1536,11 +1623,11 @@ static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
15361623
if (ret < 0)
15371624
return ret;
15381625

1539-
fid |= (ret & PORT_CONTROL_1_FID_11_4_MASK) << 4;
1626+
fid |= (ret & upper_mask) << 4;
15401627

15411628
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;
15441631

15451632
ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1,
15461633
ret);
@@ -1604,7 +1691,7 @@ static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
16041691
* databases are not needed. Return the next positive available.
16051692
*/
16061693
*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)))
16081695
return -ENOSPC;
16091696

16101697
/* Clear the database */
@@ -1965,11 +2052,7 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds,
19652052
if (ret < 0)
19662053
return ret;
19672054

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);
19732056
}
19742057

19752058
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,
20522135
if (ret < 0)
20532136
return ret;
20542137

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);
20602139
if (ret < 0)
20612140
return ret;
20622141

@@ -2444,7 +2523,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
24442523
reg = 0;
24452524
if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
24462525
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))
24482528
reg = PORT_CONTROL_2_MAP_DA;
24492529

24502530
if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||

0 commit comments

Comments
 (0)