mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
mlxsw: spectrum: Handle VLAN devices linking / unlinking
When a VLAN interface is configured on top of a physical port we should associate the VLAN device with the matching vPort. Likewise, when it's removed, we should revert back to the underlying port netdev. While not a must, this is consistent with port netdevs and also provides a more accurate error printing via netdev_err() and friends. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
aac78a4408
commit
9589a7b5d7
1 changed files with 51 additions and 3 deletions
|
@ -2259,6 +2259,40 @@ static int mlxsw_sp_port_lag_changed(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled);
|
return mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port, info->tx_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mlxsw_sp_port_vlan_link(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
struct net_device *vlan_dev)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp_port *mlxsw_sp_vport;
|
||||||
|
u16 vid = vlan_dev_vlan_id(vlan_dev);
|
||||||
|
|
||||||
|
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
|
||||||
|
if (!mlxsw_sp_vport) {
|
||||||
|
WARN_ON(!mlxsw_sp_vport);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mlxsw_sp_vport->dev = vlan_dev;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mlxsw_sp_port_vlan_unlink(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||||
|
struct net_device *vlan_dev)
|
||||||
|
{
|
||||||
|
struct mlxsw_sp_port *mlxsw_sp_vport;
|
||||||
|
u16 vid = vlan_dev_vlan_id(vlan_dev);
|
||||||
|
|
||||||
|
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
|
||||||
|
if (!mlxsw_sp_vport) {
|
||||||
|
WARN_ON(!mlxsw_sp_vport);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mlxsw_sp_vport->dev = mlxsw_sp_port->dev;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
|
static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
|
||||||
unsigned long event, void *ptr)
|
unsigned long event, void *ptr)
|
||||||
{
|
{
|
||||||
|
@ -2288,9 +2322,23 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *dev,
|
||||||
break;
|
break;
|
||||||
case NETDEV_CHANGEUPPER:
|
case NETDEV_CHANGEUPPER:
|
||||||
upper_dev = info->upper_dev;
|
upper_dev = info->upper_dev;
|
||||||
if (!info->master)
|
if (is_vlan_dev(upper_dev)) {
|
||||||
break;
|
if (info->linking) {
|
||||||
if (netif_is_bridge_master(upper_dev)) {
|
err = mlxsw_sp_port_vlan_link(mlxsw_sp_port,
|
||||||
|
upper_dev);
|
||||||
|
if (err) {
|
||||||
|
netdev_err(dev, "Failed to link VLAN device\n");
|
||||||
|
return NOTIFY_BAD;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = mlxsw_sp_port_vlan_unlink(mlxsw_sp_port,
|
||||||
|
upper_dev);
|
||||||
|
if (err) {
|
||||||
|
netdev_err(dev, "Failed to unlink VLAN device\n");
|
||||||
|
return NOTIFY_BAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (netif_is_bridge_master(upper_dev)) {
|
||||||
if (info->linking) {
|
if (info->linking) {
|
||||||
err = mlxsw_sp_port_bridge_join(mlxsw_sp_port);
|
err = mlxsw_sp_port_bridge_join(mlxsw_sp_port);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
Loading…
Reference in a new issue