Commit 3ae7a65b authored by Amit Cohen's avatar Amit Cohen Committed by Jakub Kicinski

mlxsw: Make EtherType configurable when pushing VLAN at ingress

Currently, when pushing a PVID at ingress, mlxsw always uses 802.1q
EtherType.

Make this EtherType configurable by extending mlxsw_sp_port_pvid_set()
with an EtherType argument.

This is a preparation for QinQ support, that needs to push a PVID with
802.1ad EtherType.
Signed-off-by: default avatarAmit Cohen <amcohen@nvidia.com>
Reviewed-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a2ef3ae1
...@@ -851,11 +851,13 @@ MLXSW_ITEM32(reg, spvid, et_vlan, 0x04, 16, 2); ...@@ -851,11 +851,13 @@ MLXSW_ITEM32(reg, spvid, et_vlan, 0x04, 16, 2);
*/ */
MLXSW_ITEM32(reg, spvid, pvid, 0x04, 0, 12); MLXSW_ITEM32(reg, spvid, pvid, 0x04, 0, 12);
static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid) static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid,
u8 et_vlan)
{ {
MLXSW_REG_ZERO(spvid, payload); MLXSW_REG_ZERO(spvid, payload);
mlxsw_reg_spvid_local_port_set(payload, local_port); mlxsw_reg_spvid_local_port_set(payload, local_port);
mlxsw_reg_spvid_pvid_set(payload, pvid); mlxsw_reg_spvid_pvid_set(payload, pvid);
mlxsw_reg_spvid_et_vlan_set(payload, et_vlan);
} }
/* SPVM - Switch Port VLAN Membership /* SPVM - Switch Port VLAN Membership
......
...@@ -384,13 +384,37 @@ int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, ...@@ -384,13 +384,37 @@ int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
return err; return err;
} }
static int mlxsw_sp_ethtype_to_sver_type(u16 ethtype, u8 *p_sver_type)
{
switch (ethtype) {
case ETH_P_8021Q:
*p_sver_type = 0;
break;
case ETH_P_8021AD:
*p_sver_type = 1;
break;
default:
return -EINVAL;
}
return 0;
}
static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, static int __mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 vid) u16 vid, u16 ethtype)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char spvid_pl[MLXSW_REG_SPVID_LEN]; char spvid_pl[MLXSW_REG_SPVID_LEN];
u8 sver_type;
int err;
err = mlxsw_sp_ethtype_to_sver_type(ethtype, &sver_type);
if (err)
return err;
mlxsw_reg_spvid_pack(spvid_pl, mlxsw_sp_port->local_port, vid,
sver_type);
mlxsw_reg_spvid_pack(spvid_pl, mlxsw_sp_port->local_port, vid);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl);
} }
...@@ -404,7 +428,8 @@ static int mlxsw_sp_port_allow_untagged_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -404,7 +428,8 @@ static int mlxsw_sp_port_allow_untagged_set(struct mlxsw_sp_port *mlxsw_sp_port,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spaft), spaft_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spaft), spaft_pl);
} }
int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
u16 ethtype)
{ {
int err; int err;
...@@ -413,7 +438,7 @@ int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) ...@@ -413,7 +438,7 @@ int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
if (err) if (err)
return err; return err;
} else { } else {
err = __mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid); err = __mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid, ethtype);
if (err) if (err)
return err; return err;
err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, true); err = mlxsw_sp_port_allow_untagged_set(mlxsw_sp_port, true);
...@@ -425,7 +450,7 @@ int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) ...@@ -425,7 +450,7 @@ int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
return 0; return 0;
err_port_allow_untagged_set: err_port_allow_untagged_set:
__mlxsw_sp_port_pvid_set(mlxsw_sp_port, mlxsw_sp_port->pvid); __mlxsw_sp_port_pvid_set(mlxsw_sp_port, mlxsw_sp_port->pvid, ethtype);
return err; return err;
} }
...@@ -1588,7 +1613,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, ...@@ -1588,7 +1613,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
goto err_port_nve_init; goto err_port_nve_init;
} }
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID); err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID,
ETH_P_8021Q);
if (err) { if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set PVID\n", dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set PVID\n",
mlxsw_sp_port->local_port); mlxsw_sp_port->local_port);
...@@ -3644,7 +3670,8 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -3644,7 +3670,8 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
lag->ref_count--; lag->ref_count--;
/* Make sure untagged frames are allowed to ingress */ /* Make sure untagged frames are allowed to ingress */
mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID); mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID,
ETH_P_8021Q);
} }
static int mlxsw_sp_lag_dist_port_add(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_lag_dist_port_add(struct mlxsw_sp_port *mlxsw_sp_port,
......
...@@ -580,7 +580,8 @@ int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, ...@@ -580,7 +580,8 @@ int mlxsw_sp_port_vid_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable); int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, bool enable);
int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid, int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
bool learn_enable); bool learn_enable);
int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid); int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
u16 ethtype);
struct mlxsw_sp_port_vlan * struct mlxsw_sp_port_vlan *
mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid); mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan); void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
......
...@@ -1129,6 +1129,7 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1129,6 +1129,7 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid); u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
u16 old_pvid = mlxsw_sp_port->pvid; u16 old_pvid = mlxsw_sp_port->pvid;
u16 proto;
int err; int err;
/* The only valid scenario in which a port-vlan already exists, is if /* The only valid scenario in which a port-vlan already exists, is if
...@@ -1152,7 +1153,8 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1152,7 +1153,8 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
if (err) if (err)
goto err_port_vlan_set; goto err_port_vlan_set;
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, pvid); br_vlan_get_proto(bridge_port->bridge_device->dev, &proto);
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, pvid, proto);
if (err) if (err)
goto err_port_pvid_set; goto err_port_pvid_set;
...@@ -1164,7 +1166,7 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1164,7 +1166,7 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
return 0; return 0;
err_port_vlan_bridge_join: err_port_vlan_bridge_join:
mlxsw_sp_port_pvid_set(mlxsw_sp_port, old_pvid); mlxsw_sp_port_pvid_set(mlxsw_sp_port, old_pvid, proto);
err_port_pvid_set: err_port_pvid_set:
mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false); mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
err_port_vlan_set: err_port_vlan_set:
...@@ -1821,13 +1823,15 @@ mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1821,13 +1823,15 @@ mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port,
{ {
u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid; u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid;
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan; struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
u16 proto;
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid); mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
if (WARN_ON(!mlxsw_sp_port_vlan)) if (WARN_ON(!mlxsw_sp_port_vlan))
return; return;
mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan); mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
mlxsw_sp_port_pvid_set(mlxsw_sp_port, pvid); br_vlan_get_proto(bridge_port->bridge_device->dev, &proto);
mlxsw_sp_port_pvid_set(mlxsw_sp_port, pvid, proto);
mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false); mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan); mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
} }
...@@ -1998,7 +2002,8 @@ mlxsw_sp_bridge_8021q_port_leave(struct mlxsw_sp_bridge_device *bridge_device, ...@@ -1998,7 +2002,8 @@ mlxsw_sp_bridge_8021q_port_leave(struct mlxsw_sp_bridge_device *bridge_device,
struct mlxsw_sp_port *mlxsw_sp_port) struct mlxsw_sp_port *mlxsw_sp_port)
{ {
/* Make sure untagged frames are allowed to ingress */ /* Make sure untagged frames are allowed to ingress */
mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID); mlxsw_sp_port_pvid_set(mlxsw_sp_port, MLXSW_SP_DEFAULT_VID,
ETH_P_8021Q);
} }
static int static int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment