Skip to content

Commit 6630e23

Browse files
viviendavem330
authored andcommitted
net: dsa: mv88e6xxx: rework FDB getnext operation
This commit adds a low level _mv88e6xxx_atu_getnext function and helpers to rewrite the mv88e6xxx_port_fdb_getnext operation. A mv88e6xxx_atu_entry structure is added for convenient access to the hardware, and GLOBAL_ATU_FID is defined instead of the raw 0x01 value. The previous implementation did not handle the eventual trunk mapping. If the related bit is set, then the ATU data register would contain the trunk ID, and not the port vector. Check this in the FDB getnext operation and do not handle it (yet). Signed-off-by: Vivien Didelot <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 395059f commit 6630e23

File tree

4 files changed

+87
-27
lines changed

4 files changed

+87
-27
lines changed

drivers/net/dsa/mv88e6171.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = {
116116
.port_join_bridge = mv88e6xxx_join_bridge,
117117
.port_leave_bridge = mv88e6xxx_leave_bridge,
118118
.port_stp_update = mv88e6xxx_port_stp_update,
119+
.port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
119120
};
120121

121122
MODULE_ALIAS("platform:mv88e6171");

drivers/net/dsa/mv88e6352.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = {
341341
.port_join_bridge = mv88e6xxx_join_bridge,
342342
.port_leave_bridge = mv88e6xxx_leave_bridge,
343343
.port_stp_update = mv88e6xxx_port_stp_update,
344+
.port_fdb_getnext = mv88e6xxx_port_fdb_getnext,
344345
};
345346

346347
MODULE_ALIAS("platform:mv88e6172");

drivers/net/dsa/mv88e6xxx.c

Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

drivers/net/dsa/mv88e6xxx.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
#define GLOBAL_MAC_01 0x01
172172
#define GLOBAL_MAC_23 0x02
173173
#define GLOBAL_MAC_45 0x03
174+
#define GLOBAL_ATU_FID 0x01 /* 6097 6165 6351 6352 */
174175
#define GLOBAL_CONTROL 0x04
175176
#define GLOBAL_CONTROL_SW_RESET BIT(15)
176177
#define GLOBAL_CONTROL_PPU_ENABLE BIT(14)
@@ -205,6 +206,8 @@
205206
#define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY)
206207
#define GLOBAL_ATU_DATA 0x0c
207208
#define GLOBAL_ATU_DATA_TRUNK BIT(15)
209+
#define GLOBAL_ATU_DATA_TRUNK_ID_MASK 0x00f0
210+
#define GLOBAL_ATU_DATA_TRUNK_ID_SHIFT 4
208211
#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3ff0
209212
#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4
210213
#define GLOBAL_ATU_DATA_STATE_MASK 0x0f
@@ -311,6 +314,14 @@
311314
#define GLOBAL2_QOS_WEIGHT 0x1c
312315
#define GLOBAL2_MISC 0x1d
313316

317+
struct mv88e6xxx_atu_entry {
318+
u16 fid;
319+
u8 state;
320+
bool trunk;
321+
u16 portv_trunkid;
322+
u8 mac[ETH_ALEN];
323+
};
324+
314325
struct mv88e6xxx_priv_state {
315326
/* When using multi-chip addressing, this mutex protects
316327
* access to the indirect access registers. (In single-chip
@@ -415,11 +426,11 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
415426
const unsigned char *addr, u16 vid);
416427
int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
417428
const unsigned char *addr, u16 vid);
418-
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
419-
unsigned char *addr, bool *is_static);
420429
int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg);
421430
int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
422431
int reg, int val);
432+
int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, u16 *vid,
433+
u8 addr[ETH_ALEN], bool *is_static);
423434

424435
extern struct dsa_switch_driver mv88e6131_switch_driver;
425436
extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;

0 commit comments

Comments
 (0)