diff options
author | Ido Schimmel <idosch@mellanox.com> | 2017-05-26 08:37:26 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-05-26 15:18:45 -0400 |
commit | 31a08a523ae453f7eaf5ad6c1da99d6199141b14 (patch) | |
tree | d6c9568f10472172e083880730ba7725402a2e6d | |
parent | 4aafc368daac7781576ca6144622254adf469a15 (diff) |
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: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 48 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 23 |
2 files changed, 68 insertions, 3 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 5d673363154b..6f5f01151c49 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1480,10 +1480,34 @@ static void mlxsw_sp_port_vport_destroy(struct mlxsw_sp_port *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, __be16 __always_unused proto, u16 vid) { 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; bool untagged = vid == 1; int err; @@ -1494,12 +1518,19 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev, if (!vid) 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; + 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); - if (!mlxsw_sp_vport) - return -ENOMEM; + if (!mlxsw_sp_vport) { + err = -ENOMEM; + goto err_port_vport_create; + } err = mlxsw_sp_port_vlan_set(mlxsw_sp_vport, vid, vid, true, untagged); if (err) @@ -1509,6 +1540,8 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev, err_port_add_vid: mlxsw_sp_port_vport_destroy(mlxsw_sp_vport); +err_port_vport_create: + mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan); return err; } @@ -1516,6 +1549,7 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, __be16 __always_unused proto, u16 vid) { 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_fid *f; @@ -1525,6 +1559,10 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev, if (!vid) 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); if (WARN_ON(!mlxsw_sp_vport)) return 0; @@ -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_vlan_destroy(mlxsw_sp_port_vlan); + return 0; } @@ -2720,6 +2760,7 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err = -ENOMEM; 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->mall_tc_list); @@ -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->active_vlans); 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); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 277a432af319..c4ac648f39bf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -203,6 +203,13 @@ struct mlxsw_sp_port_sample { 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 net_device *dev; struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats; @@ -254,6 +261,7 @@ struct mlxsw_sp_port { } hw_stats; struct mlxsw_sp_port_sample *sample; 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); @@ -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; } +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 mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port *mlxsw_sp_vport) { |