Commit 05978481 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

mlxsw: spectrum: Create PVID vPort before registering netdevice

After registering a netdevice it's possible for user space applications
to configure an IP address on it. From the driver's perspective, this
means a router interface (RIF) should be created for the PVID vPort.

Therefore, we must create the PVID vPort before registering the
netdevice.

Fixes: 99724c18 ("mlxsw: spectrum: Introduce support for router interfaces")
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fa66d7e3
...@@ -942,8 +942,8 @@ static void mlxsw_sp_port_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_vport) ...@@ -942,8 +942,8 @@ static void mlxsw_sp_port_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_vport)
kfree(mlxsw_sp_vport); kfree(mlxsw_sp_vport);
} }
int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto, static int mlxsw_sp_port_add_vid(struct net_device *dev,
u16 vid) __be16 __always_unused proto, u16 vid)
{ {
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp_port *mlxsw_sp_vport; struct mlxsw_sp_port *mlxsw_sp_vport;
...@@ -2048,6 +2048,18 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port) ...@@ -2048,6 +2048,18 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
return 0; return 0;
} }
static int mlxsw_sp_port_pvid_vport_create(struct mlxsw_sp_port *mlxsw_sp_port)
{
mlxsw_sp_port->pvid = 1;
return mlxsw_sp_port_add_vid(mlxsw_sp_port->dev, 0, 1);
}
static int mlxsw_sp_port_pvid_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_port)
{
return mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
}
static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
bool split, u8 module, u8 width, u8 lane) bool split, u8 module, u8 width, u8 lane)
{ {
...@@ -2163,6 +2175,13 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, ...@@ -2163,6 +2175,13 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
goto err_port_dcb_init; goto err_port_dcb_init;
} }
err = mlxsw_sp_port_pvid_vport_create(mlxsw_sp_port);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to create PVID vPort\n",
mlxsw_sp_port->local_port);
goto err_port_pvid_vport_create;
}
mlxsw_sp_port_switchdev_init(mlxsw_sp_port); mlxsw_sp_port_switchdev_init(mlxsw_sp_port);
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
...@@ -2180,18 +2199,14 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, ...@@ -2180,18 +2199,14 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
goto err_core_port_init; goto err_core_port_init;
} }
err = mlxsw_sp_port_vlan_init(mlxsw_sp_port);
if (err)
goto err_port_vlan_init;
mlxsw_sp->ports[local_port] = mlxsw_sp_port; mlxsw_sp->ports[local_port] = mlxsw_sp_port;
return 0; return 0;
err_port_vlan_init:
mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
err_core_port_init: err_core_port_init:
unregister_netdev(dev); unregister_netdev(dev);
err_register_netdev: err_register_netdev:
mlxsw_sp_port_pvid_vport_destroy(mlxsw_sp_port);
err_port_pvid_vport_create:
mlxsw_sp_port_dcb_fini(mlxsw_sp_port); mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
err_port_dcb_init: err_port_dcb_init:
err_port_ets_init: err_port_ets_init:
...@@ -2221,8 +2236,8 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) ...@@ -2221,8 +2236,8 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
mlxsw_sp->ports[local_port] = NULL; mlxsw_sp->ports[local_port] = NULL;
mlxsw_core_port_fini(&mlxsw_sp_port->core_port); mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
mlxsw_sp_port_pvid_vport_destroy(mlxsw_sp_port);
mlxsw_sp_port_dcb_fini(mlxsw_sp_port); mlxsw_sp_port_dcb_fini(mlxsw_sp_port);
mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT); mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT);
mlxsw_sp_port_module_unmap(mlxsw_sp, mlxsw_sp_port->local_port); mlxsw_sp_port_module_unmap(mlxsw_sp, mlxsw_sp_port->local_port);
......
...@@ -536,8 +536,6 @@ int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -536,8 +536,6 @@ int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 vid); u16 vid);
int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin, int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin,
u16 vid_end, bool is_member, bool untagged); u16 vid_end, bool is_member, bool untagged);
int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto,
u16 vid);
int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid, int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 fid,
bool set); bool set);
void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port); void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);
......
...@@ -997,13 +997,13 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev, ...@@ -997,13 +997,13 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
} }
static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
u16 vid_begin, u16 vid_end, bool init) u16 vid_begin, u16 vid_end)
{ {
struct net_device *dev = mlxsw_sp_port->dev; struct net_device *dev = mlxsw_sp_port->dev;
u16 vid, pvid; u16 vid, pvid;
int err; int err;
if (!init && !mlxsw_sp_port->bridged) if (!mlxsw_sp_port->bridged)
return -EINVAL; return -EINVAL;
err = __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end, err = __mlxsw_sp_port_vlans_set(mlxsw_sp_port, vid_begin, vid_end,
...@@ -1014,9 +1014,6 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1014,9 +1014,6 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
return err; return err;
} }
if (init)
goto out;
pvid = mlxsw_sp_port->pvid; pvid = mlxsw_sp_port->pvid;
if (pvid >= vid_begin && pvid <= vid_end) { if (pvid >= vid_begin && pvid <= vid_end) {
err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0); err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, 0);
...@@ -1028,7 +1025,6 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1028,7 +1025,6 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port_fid_leave(mlxsw_sp_port, vid_begin, vid_end); mlxsw_sp_port_fid_leave(mlxsw_sp_port, vid_begin, vid_end);
out:
/* Changing activity bits only if HW operation succeded */ /* Changing activity bits only if HW operation succeded */
for (vid = vid_begin; vid <= vid_end; vid++) for (vid = vid_begin; vid <= vid_end; vid++)
clear_bit(vid, mlxsw_sp_port->active_vlans); clear_bit(vid, mlxsw_sp_port->active_vlans);
...@@ -1039,8 +1035,8 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1039,8 +1035,8 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
const struct switchdev_obj_port_vlan *vlan) const struct switchdev_obj_port_vlan *vlan)
{ {
return __mlxsw_sp_port_vlans_del(mlxsw_sp_port, return __mlxsw_sp_port_vlans_del(mlxsw_sp_port, vlan->vid_begin,
vlan->vid_begin, vlan->vid_end, false); vlan->vid_end);
} }
void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port) void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port)
...@@ -1048,7 +1044,7 @@ void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port) ...@@ -1048,7 +1044,7 @@ void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port)
u16 vid; u16 vid;
for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID)
__mlxsw_sp_port_vlans_del(mlxsw_sp_port, vid, vid, false); __mlxsw_sp_port_vlans_del(mlxsw_sp_port, vid, vid);
} }
static int static int
...@@ -1546,32 +1542,6 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp) ...@@ -1546,32 +1542,6 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
mlxsw_sp_fdb_fini(mlxsw_sp); mlxsw_sp_fdb_fini(mlxsw_sp);
} }
int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port)
{
struct net_device *dev = mlxsw_sp_port->dev;
int err;
/* Allow only untagged packets to ingress and tag them internally
* with VID 1.
*/
mlxsw_sp_port->pvid = 1;
err = __mlxsw_sp_port_vlans_del(mlxsw_sp_port, 0, VLAN_N_VID - 1,
true);
if (err) {
netdev_err(dev, "Unable to init VLANs\n");
return err;
}
/* Add implicit VLAN interface in the device, so that untagged
* packets will be classified to the default vFID.
*/
err = mlxsw_sp_port_add_vid(dev, 0, 1);
if (err)
netdev_err(dev, "Failed to configure default vFID\n");
return err;
}
void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port) void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port)
{ {
mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops; mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops;
......
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