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

mlxsw: spectrum: Introduce Port-VLAN structure

This is the first step in the transition from the vPort model to a
unified Port-VLAN structure. The new structure is defined and created /
destroyed upon invocation of the 8021q ndos, but it's not actually used
throughout the code.

Subsequent patches will initialize it correctly and also create /
destroy it upon switchdev's VLAN object.
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 4aafc368
...@@ -1480,10 +1480,34 @@ static void mlxsw_sp_port_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_vport) ...@@ -1480,10 +1480,34 @@ static void mlxsw_sp_port_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_vport)
kfree(mlxsw_sp_vport); kfree(mlxsw_sp_vport);
} }
static struct mlxsw_sp_port_vlan *
mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
{
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
mlxsw_sp_port_vlan = kzalloc(sizeof(*mlxsw_sp_port_vlan), GFP_KERNEL);
if (!mlxsw_sp_port_vlan)
return ERR_PTR(-ENOMEM);
mlxsw_sp_port_vlan->mlxsw_sp_port = mlxsw_sp_port;
mlxsw_sp_port_vlan->vid = vid;
list_add(&mlxsw_sp_port_vlan->list, &mlxsw_sp_port->vlans_list);
return mlxsw_sp_port_vlan;
}
static void
mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
{
list_del(&mlxsw_sp_port_vlan->list);
kfree(mlxsw_sp_port_vlan);
}
static int mlxsw_sp_port_add_vid(struct net_device *dev, static int mlxsw_sp_port_add_vid(struct net_device *dev,
__be16 __always_unused proto, 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_vlan *mlxsw_sp_port_vlan;
struct mlxsw_sp_port *mlxsw_sp_vport; struct mlxsw_sp_port *mlxsw_sp_vport;
bool untagged = vid == 1; bool untagged = vid == 1;
int err; int err;
...@@ -1494,12 +1518,19 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev, ...@@ -1494,12 +1518,19 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
if (!vid) if (!vid)
return 0; return 0;
if (mlxsw_sp_port_vport_find(mlxsw_sp_port, vid)) mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
if (mlxsw_sp_port_vlan)
return 0; return 0;
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid);
if (IS_ERR(mlxsw_sp_port_vlan))
return PTR_ERR(mlxsw_sp_port_vlan);
mlxsw_sp_vport = mlxsw_sp_port_vport_create(mlxsw_sp_port, vid); mlxsw_sp_vport = mlxsw_sp_port_vport_create(mlxsw_sp_port, vid);
if (!mlxsw_sp_vport) if (!mlxsw_sp_vport) {
return -ENOMEM; err = -ENOMEM;
goto err_port_vport_create;
}
err = mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, true, untagged); err = mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, true, untagged);
if (err) if (err)
...@@ -1509,6 +1540,8 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev, ...@@ -1509,6 +1540,8 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
err_port_add_vid: err_port_add_vid:
mlxsw_sp_port_vport_destroy(mlxsw_sp_vport); mlxsw_sp_port_vport_destroy(mlxsw_sp_vport);
err_port_vport_create:
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
return err; return err;
} }
...@@ -1516,6 +1549,7 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, ...@@ -1516,6 +1549,7 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
__be16 __always_unused proto, 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_vlan *mlxsw_sp_port_vlan;
struct mlxsw_sp_port *mlxsw_sp_vport; struct mlxsw_sp_port *mlxsw_sp_vport;
struct mlxsw_sp_fid *f; struct mlxsw_sp_fid *f;
...@@ -1525,6 +1559,10 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, ...@@ -1525,6 +1559,10 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
if (!vid) if (!vid)
return 0; return 0;
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
if (WARN_ON(!mlxsw_sp_port_vlan))
return 0;
mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid); mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, vid);
if (WARN_ON(!mlxsw_sp_vport)) if (WARN_ON(!mlxsw_sp_vport))
return 0; return 0;
...@@ -1540,6 +1578,8 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, ...@@ -1540,6 +1578,8 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
mlxsw_sp_port_vport_destroy(mlxsw_sp_vport); mlxsw_sp_port_vport_destroy(mlxsw_sp_vport);
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
return 0; return 0;
} }
...@@ -2720,6 +2760,7 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, ...@@ -2720,6 +2760,7 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
err = -ENOMEM; err = -ENOMEM;
goto err_port_untagged_vlans_alloc; goto err_port_untagged_vlans_alloc;
} }
INIT_LIST_HEAD(&mlxsw_sp_port->vlans_list);
INIT_LIST_HEAD(&mlxsw_sp_port->vports_list); INIT_LIST_HEAD(&mlxsw_sp_port->vports_list);
INIT_LIST_HEAD(&mlxsw_sp_port->mall_tc_list); INIT_LIST_HEAD(&mlxsw_sp_port->mall_tc_list);
...@@ -2926,6 +2967,7 @@ static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) ...@@ -2926,6 +2967,7 @@ static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
kfree(mlxsw_sp_port->untagged_vlans); kfree(mlxsw_sp_port->untagged_vlans);
kfree(mlxsw_sp_port->active_vlans); kfree(mlxsw_sp_port->active_vlans);
WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vports_list)); WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vports_list));
WARN_ON_ONCE(!list_empty(&mlxsw_sp_port->vlans_list));
free_netdev(mlxsw_sp_port->dev); free_netdev(mlxsw_sp_port->dev);
} }
......
...@@ -203,6 +203,13 @@ struct mlxsw_sp_port_sample { ...@@ -203,6 +203,13 @@ struct mlxsw_sp_port_sample {
bool truncate; bool truncate;
}; };
struct mlxsw_sp_port_vlan {
struct list_head list;
struct mlxsw_sp_port *mlxsw_sp_port;
struct mlxsw_sp_fid *fid;
u16 vid;
};
struct mlxsw_sp_port { struct mlxsw_sp_port {
struct net_device *dev; struct net_device *dev;
struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats; struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats;
...@@ -254,6 +261,7 @@ struct mlxsw_sp_port { ...@@ -254,6 +261,7 @@ struct mlxsw_sp_port {
} hw_stats; } hw_stats;
struct mlxsw_sp_port_sample *sample; struct mlxsw_sp_port_sample *sample;
unsigned int nr_port_vid_map; /* {Port, VID} => FID mappings */ unsigned int nr_port_vid_map; /* {Port, VID} => FID mappings */
struct list_head vlans_list;
}; };
bool mlxsw_sp_port_dev_check(const struct net_device *dev); bool mlxsw_sp_port_dev_check(const struct net_device *dev);
...@@ -279,6 +287,21 @@ mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id, u8 port_index) ...@@ -279,6 +287,21 @@ mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id, u8 port_index)
return mlxsw_sp_port && mlxsw_sp_port->lagged ? mlxsw_sp_port : NULL; return mlxsw_sp_port && mlxsw_sp_port->lagged ? mlxsw_sp_port : NULL;
} }
static inline struct mlxsw_sp_port_vlan *
mlxsw_sp_port_vlan_find_by_vid(const struct mlxsw_sp_port *mlxsw_sp_port,
u16 vid)
{
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
list_for_each_entry(mlxsw_sp_port_vlan, &mlxsw_sp_port->vlans_list,
list) {
if (mlxsw_sp_port_vlan->vid == vid)
return mlxsw_sp_port_vlan;
}
return NULL;
}
static inline u16 static inline u16
mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port *mlxsw_sp_vport) mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
{ {
......
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