Skip to content

Commit 2db9ce1

Browse files
viviendavem330
authored andcommitted
net: dsa: mv88e6xxx: assign default FDB to ports
Restore per-port FDB. Assign them on setup, allow adding and deleting addresses into them, and dump them. Signed-off-by: Vivien Didelot <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3285f9e commit 2db9ce1

File tree

2 files changed

+91
-7
lines changed

2 files changed

+91
-7
lines changed

drivers/net/dsa/mv88e6xxx.c

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,14 +1458,82 @@ static int _mv88e6xxx_stu_loadpurge(struct dsa_switch *ds,
14581458
return _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_STU_LOAD_PURGE);
14591459
}
14601460

1461+
static int _mv88e6xxx_port_fid(struct dsa_switch *ds, int port, u16 *new,
1462+
u16 *old)
1463+
{
1464+
u16 fid;
1465+
int ret;
1466+
1467+
/* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
1468+
ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN);
1469+
if (ret < 0)
1470+
return ret;
1471+
1472+
fid = (ret & PORT_BASE_VLAN_FID_3_0_MASK) >> 12;
1473+
1474+
if (new) {
1475+
ret &= ~PORT_BASE_VLAN_FID_3_0_MASK;
1476+
ret |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK;
1477+
1478+
ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN,
1479+
ret);
1480+
if (ret < 0)
1481+
return ret;
1482+
}
1483+
1484+
/* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */
1485+
ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_CONTROL_1);
1486+
if (ret < 0)
1487+
return ret;
1488+
1489+
fid |= (ret & PORT_CONTROL_1_FID_11_4_MASK) << 4;
1490+
1491+
if (new) {
1492+
ret &= ~PORT_CONTROL_1_FID_11_4_MASK;
1493+
ret |= (*new >> 4) & PORT_CONTROL_1_FID_11_4_MASK;
1494+
1495+
ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1,
1496+
ret);
1497+
if (ret < 0)
1498+
return ret;
1499+
1500+
netdev_dbg(ds->ports[port], "FID %d (was %d)\n", *new, fid);
1501+
}
1502+
1503+
if (old)
1504+
*old = fid;
1505+
1506+
return 0;
1507+
}
1508+
1509+
static int _mv88e6xxx_port_fid_get(struct dsa_switch *ds, int port, u16 *fid)
1510+
{
1511+
return _mv88e6xxx_port_fid(ds, port, NULL, fid);
1512+
}
1513+
1514+
static int _mv88e6xxx_port_fid_set(struct dsa_switch *ds, int port, u16 fid)
1515+
{
1516+
return _mv88e6xxx_port_fid(ds, port, &fid, NULL);
1517+
}
1518+
14611519
static int _mv88e6xxx_fid_new(struct dsa_switch *ds, u16 *fid)
14621520
{
1521+
struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
14631522
DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
14641523
struct mv88e6xxx_vtu_stu_entry vlan;
1465-
int err;
1524+
int i, err;
14661525

14671526
bitmap_zero(fid_bitmap, MV88E6XXX_N_FID);
14681527

1528+
/* Set every FID bit used by the (un)bridged ports */
1529+
for (i = 0; i < ps->num_ports; ++i) {
1530+
err = _mv88e6xxx_port_fid_get(ds, i, fid);
1531+
if (err)
1532+
return err;
1533+
1534+
set_bit(*fid, fid_bitmap);
1535+
}
1536+
14691537
/* Set every FID bit used by the VLAN entries */
14701538
err = _mv88e6xxx_vtu_vid_write(ds, GLOBAL_VTU_VID_MASK);
14711539
if (err)
@@ -1824,7 +1892,11 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port,
18241892
struct mv88e6xxx_vtu_stu_entry vlan;
18251893
int err;
18261894

1827-
err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false);
1895+
/* Null VLAN ID corresponds to the port private database */
1896+
if (vid == 0)
1897+
err = _mv88e6xxx_port_fid_get(ds, port, &vlan.fid);
1898+
else
1899+
err = _mv88e6xxx_vtu_get(ds, vid, &vlan, false);
18281900
if (err)
18291901
return err;
18301902

@@ -1843,10 +1915,6 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port,
18431915
const struct switchdev_obj_port_fdb *fdb,
18441916
struct switchdev_trans *trans)
18451917
{
1846-
/* We don't use per-port FDB */
1847-
if (fdb->vid == 0)
1848-
return -EOPNOTSUPP;
1849-
18501918
/* We don't need any dynamic resource from the kernel (yet),
18511919
* so skip the prepare phase.
18521920
*/
@@ -1982,10 +2050,20 @@ int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
19822050
struct mv88e6xxx_vtu_stu_entry vlan = {
19832051
.vid = GLOBAL_VTU_VID_MASK, /* all ones */
19842052
};
2053+
u16 fid;
19852054
int err;
19862055

19872056
mutex_lock(&ps->smi_mutex);
19882057

2058+
/* Dump port's default Filtering Information Database (VLAN ID 0) */
2059+
err = _mv88e6xxx_port_fid_get(ds, port, &fid);
2060+
if (err)
2061+
goto unlock;
2062+
2063+
err = _mv88e6xxx_port_fdb_dump_one(ds, fid, 0, port, fdb, cb);
2064+
if (err)
2065+
goto unlock;
2066+
19892067
/* Dump VLANs' Filtering Information Databases */
19902068
err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid);
19912069
if (err)
@@ -2286,9 +2364,13 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
22862364
if (ret)
22872365
goto abort;
22882366

2289-
/* Port based VLAN map: do not give each port its own address
2367+
/* Port based VLAN map: give each port its own address
22902368
* database, and allow every port to egress frames on all other ports.
22912369
*/
2370+
ret = _mv88e6xxx_port_fid_set(ds, port, port + 1);
2371+
if (ret)
2372+
goto abort;
2373+
22922374
reg = BIT(ps->num_ports) - 1; /* all ports */
22932375
reg &= ~BIT(port); /* except itself */
22942376
ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg);

drivers/net/dsa/mv88e6xxx.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@
133133
#define PORT_CONTROL_STATE_LEARNING 0x02
134134
#define PORT_CONTROL_STATE_FORWARDING 0x03
135135
#define PORT_CONTROL_1 0x05
136+
#define PORT_CONTROL_1_FID_11_4_MASK (0xff << 0)
136137
#define PORT_BASE_VLAN 0x06
138+
#define PORT_BASE_VLAN_FID_3_0_MASK (0xf << 12)
137139
#define PORT_DEFAULT_VLAN 0x07
138140
#define PORT_DEFAULT_VLAN_MASK 0xfff
139141
#define PORT_CONTROL_2 0x08

0 commit comments

Comments
 (0)