@@ -1480,10 +1480,34 @@ static void mlxsw_sp_port_vport_destroy(struct mlxsw_sp_port *mlxsw_sp_vport)
14801480 kfree (mlxsw_sp_vport );
14811481}
14821482
1483+ static struct mlxsw_sp_port_vlan *
1484+ mlxsw_sp_port_vlan_create (struct mlxsw_sp_port * mlxsw_sp_port , u16 vid )
1485+ {
1486+ struct mlxsw_sp_port_vlan * mlxsw_sp_port_vlan ;
1487+
1488+ mlxsw_sp_port_vlan = kzalloc (sizeof (* mlxsw_sp_port_vlan ), GFP_KERNEL );
1489+ if (!mlxsw_sp_port_vlan )
1490+ return ERR_PTR (- ENOMEM );
1491+
1492+ mlxsw_sp_port_vlan -> mlxsw_sp_port = mlxsw_sp_port ;
1493+ mlxsw_sp_port_vlan -> vid = vid ;
1494+ list_add (& mlxsw_sp_port_vlan -> list , & mlxsw_sp_port -> vlans_list );
1495+
1496+ return mlxsw_sp_port_vlan ;
1497+ }
1498+
1499+ static void
1500+ mlxsw_sp_port_vlan_destroy (struct mlxsw_sp_port_vlan * mlxsw_sp_port_vlan )
1501+ {
1502+ list_del (& mlxsw_sp_port_vlan -> list );
1503+ kfree (mlxsw_sp_port_vlan );
1504+ }
1505+
14831506static int mlxsw_sp_port_add_vid (struct net_device * dev ,
14841507 __be16 __always_unused proto , u16 vid )
14851508{
14861509 struct mlxsw_sp_port * mlxsw_sp_port = netdev_priv (dev );
1510+ struct mlxsw_sp_port_vlan * mlxsw_sp_port_vlan ;
14871511 struct mlxsw_sp_port * mlxsw_sp_vport ;
14881512 bool untagged = vid == 1 ;
14891513 int err ;
@@ -1494,12 +1518,19 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
14941518 if (!vid )
14951519 return 0 ;
14961520
1497- if (mlxsw_sp_port_vport_find (mlxsw_sp_port , vid ))
1521+ mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid (mlxsw_sp_port , vid );
1522+ if (mlxsw_sp_port_vlan )
14981523 return 0 ;
14991524
1525+ mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create (mlxsw_sp_port , vid );
1526+ if (IS_ERR (mlxsw_sp_port_vlan ))
1527+ return PTR_ERR (mlxsw_sp_port_vlan );
1528+
15001529 mlxsw_sp_vport = mlxsw_sp_port_vport_create (mlxsw_sp_port , vid );
1501- if (!mlxsw_sp_vport )
1502- return - ENOMEM ;
1530+ if (!mlxsw_sp_vport ) {
1531+ err = - ENOMEM ;
1532+ goto err_port_vport_create ;
1533+ }
15031534
15041535 err = mlxsw_sp_port_vlan_set (mlxsw_sp_vport , vid , vid , true, untagged );
15051536 if (err )
@@ -1509,13 +1540,16 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
15091540
15101541err_port_add_vid :
15111542 mlxsw_sp_port_vport_destroy (mlxsw_sp_vport );
1543+ err_port_vport_create :
1544+ mlxsw_sp_port_vlan_destroy (mlxsw_sp_port_vlan );
15121545 return err ;
15131546}
15141547
15151548static int mlxsw_sp_port_kill_vid (struct net_device * dev ,
15161549 __be16 __always_unused proto , u16 vid )
15171550{
15181551 struct mlxsw_sp_port * mlxsw_sp_port = netdev_priv (dev );
1552+ struct mlxsw_sp_port_vlan * mlxsw_sp_port_vlan ;
15191553 struct mlxsw_sp_port * mlxsw_sp_vport ;
15201554 struct mlxsw_sp_fid * f ;
15211555
@@ -1525,6 +1559,10 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
15251559 if (!vid )
15261560 return 0 ;
15271561
1562+ mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid (mlxsw_sp_port , vid );
1563+ if (WARN_ON (!mlxsw_sp_port_vlan ))
1564+ return 0 ;
1565+
15281566 mlxsw_sp_vport = mlxsw_sp_port_vport_find (mlxsw_sp_port , vid );
15291567 if (WARN_ON (!mlxsw_sp_vport ))
15301568 return 0 ;
@@ -1540,6 +1578,8 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
15401578
15411579 mlxsw_sp_port_vport_destroy (mlxsw_sp_vport );
15421580
1581+ mlxsw_sp_port_vlan_destroy (mlxsw_sp_port_vlan );
1582+
15431583 return 0 ;
15441584}
15451585
@@ -2720,6 +2760,7 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
27202760 err = - ENOMEM ;
27212761 goto err_port_untagged_vlans_alloc ;
27222762 }
2763+ INIT_LIST_HEAD (& mlxsw_sp_port -> vlans_list );
27232764 INIT_LIST_HEAD (& mlxsw_sp_port -> vports_list );
27242765 INIT_LIST_HEAD (& mlxsw_sp_port -> mall_tc_list );
27252766
@@ -2926,6 +2967,7 @@ static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
29262967 kfree (mlxsw_sp_port -> untagged_vlans );
29272968 kfree (mlxsw_sp_port -> active_vlans );
29282969 WARN_ON_ONCE (!list_empty (& mlxsw_sp_port -> vports_list ));
2970+ WARN_ON_ONCE (!list_empty (& mlxsw_sp_port -> vlans_list ));
29292971 free_netdev (mlxsw_sp_port -> dev );
29302972}
29312973
0 commit comments