Skip to content

Commit 28a01d2

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum: Allow for PVID deletion
When PVID is toggled off on a port member in a VLAN filtering bridge or the PVID VLAN is deleted, make the port drop untagged packets. Reverse the operation when PVID is toggled back on. Set the PVID back to the default (1), when leaving the bridge so that untagged traffic will be directed to the CPU. Fixes: 56ade8f ("mlxsw: spectrum: Add initial support for Spectrum ASIC") Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 148f472 commit 28a01d2

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2123,6 +2123,8 @@ static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
21232123
if (flush_fdb && mlxsw_sp_port_fdb_flush(mlxsw_sp_port))
21242124
netdev_err(mlxsw_sp_port->dev, "Failed to flush FDB\n");
21252125

2126+
mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
2127+
21262128
mlxsw_sp_port->learning = 0;
21272129
mlxsw_sp_port->learning_sync = 0;
21282130
mlxsw_sp_port->uc_flood = 0;

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,5 +254,6 @@ int mlxsw_sp_port_kill_vid(struct net_device *dev,
254254
int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
255255
bool set, bool only_uc);
256256
void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);
257+
int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
257258

258259
#endif

drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
370370
return err;
371371
}
372372

373-
static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
373+
static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port,
374+
u16 vid)
374375
{
375376
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
376377
char spvid_pl[MLXSW_REG_SPVID_LEN];
@@ -379,6 +380,53 @@ static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
379380
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl);
380381
}
381382

383+
static int mlxsw_sp_port_allow_untagged_set(struct mlxsw_sp_port *mlxsw_sp_port,
384+
bool allow)
385+
{
386+
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
387+
char spaft_pl[MLXSW_REG_SPAFT_LEN];
388+
389+
mlxsw_reg_spaft_pack(spaft_pl, mlxsw_sp_port->local_port, allow);
390+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spaft), spaft_pl);
391+
}
392+
393+
int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
394+
{
395+
struct net_device *dev = mlxsw_sp_port->dev;
396+
int err;
397+
398+
if (!vid) {
399+
err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, false);
400+
if (err) {
401+
netdev_err(dev, "Failed to disallow untagged traffic\n");
402+
return err;
403+
}
404+
} else {
405+
err = __mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid);
406+
if (err) {
407+
netdev_err(dev, "Failed to set PVID\n");
408+
return err;
409+
}
410+
411+
/* Only allow if not already allowed. */
412+
if (!mlxsw_sp_port->pvid) {
413+
err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port,
414+
true);
415+
if (err) {
416+
netdev_err(dev, "Failed to allow untagged traffic\n");
417+
goto err_port_allow_untagged_set;
418+
}
419+
}
420+
}
421+
422+
mlxsw_sp_port->pvid = vid;
423+
return 0;
424+
425+
err_port_allow_untagged_set:
426+
__mlxsw_sp_port_pvid_set(mlxsw_sp_port, mlxsw_sp_port->pvid);
427+
return err;
428+
}
429+
382430
static int mlxsw_sp_fid_create(struct mlxsw_sp *mlxsw_sp, u16 fid)
383431
{
384432
char sfmr_pl[MLXSW_REG_SFMR_LEN];
@@ -540,7 +588,12 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
540588
netdev_err(dev, "Unable to add PVID %d\n", vid_begin);
541589
goto err_port_pvid_set;
542590
}
543-
mlxsw_sp_port->pvid = vid_begin;
591+
} else if (!flag_pvid && old_pvid >= vid_begin && old_pvid <= vid_end) {
592+
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
593+
if (err) {
594+
netdev_err(dev, "Unable to del PVID\n");
595+
goto err_port_pvid_set;
596+
}
544597
}
545598

546599
/* Changing activity bits only if HW operation succeded */
@@ -892,20 +945,18 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
892945
return err;
893946
}
894947

948+
if (init)
949+
goto out;
950+
895951
pvid = mlxsw_sp_port->pvid;
896-
if (pvid >= vid_begin && pvid <= vid_end && pvid != 1) {
897-
/* Default VLAN is always 1 */
898-
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
952+
if (pvid >= vid_begin && pvid <= vid_end) {
953+
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
899954
if (err) {
900955
netdev_err(dev, "Unable to del PVID %d\n", pvid);
901956
return err;
902957
}
903-
mlxsw_sp_port->pvid = 1;
904958
}
905959

906-
if (init)
907-
goto out;
908-
909960
err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end,
910961
false, false);
911962
if (err) {

0 commit comments

Comments
 (0)