Skip to content

Commit 635c8c8

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum: Remove reference count from VLAN entries
Commit b3529af ("spectrum: Reference count VLAN entries") started reference counting port-VLAN entries in a similar fashion to the 8021q driver. However, this is not actually needed and only complicates things. Instead, the driver should forbid the creation of a VLAN on a port if this VLAN already exists. This would also solve the issue fixed by the mentioned commit. Therefore, remove the get()/put() API and use create()/destroy() instead. One place that needs special attention is VLAN addition in a VLAN-aware bridge via switchdev operations. In case the VLAN flags (e.g., 'pvid') are toggled, then the VLAN entry already exists. To prevent the driver from wrongly returning EEXIST, the driver is changed to check in the prepare phase whether the entry already exists and only returns an error in case it is not associated with the correct bridge port. Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Petr Machata <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e149113 commit 635c8c8

File tree

3 files changed

+46
-58
lines changed

3 files changed

+46
-58
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,16 +1141,20 @@ static void mlxsw_sp_port_vlan_flush(struct mlxsw_sp_port *mlxsw_sp_port)
11411141

11421142
list_for_each_entry_safe(mlxsw_sp_port_vlan, tmp,
11431143
&mlxsw_sp_port->vlans_list, list)
1144-
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1144+
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
11451145
}
11461146

1147-
static struct mlxsw_sp_port_vlan *
1147+
struct mlxsw_sp_port_vlan *
11481148
mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
11491149
{
11501150
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
11511151
bool untagged = vid == 1;
11521152
int err;
11531153

1154+
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
1155+
if (mlxsw_sp_port_vlan)
1156+
return ERR_PTR(-EEXIST);
1157+
11541158
err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true, untagged);
11551159
if (err)
11561160
return ERR_PTR(err);
@@ -1162,7 +1166,6 @@ mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
11621166
}
11631167

11641168
mlxsw_sp_port_vlan->mlxsw_sp_port = mlxsw_sp_port;
1165-
mlxsw_sp_port_vlan->ref_count = 1;
11661169
mlxsw_sp_port_vlan->vid = vid;
11671170
list_add(&mlxsw_sp_port_vlan->list, &mlxsw_sp_port->vlans_list);
11681171

@@ -1173,44 +1176,19 @@ mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
11731176
return ERR_PTR(err);
11741177
}
11751178

1176-
static void
1177-
mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
1179+
void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
11781180
{
11791181
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
11801182
u16 vid = mlxsw_sp_port_vlan->vid;
11811183

1182-
list_del(&mlxsw_sp_port_vlan->list);
1183-
kfree(mlxsw_sp_port_vlan);
1184-
mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
1185-
}
1186-
1187-
struct mlxsw_sp_port_vlan *
1188-
mlxsw_sp_port_vlan_get(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
1189-
{
1190-
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
1191-
1192-
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
1193-
if (mlxsw_sp_port_vlan) {
1194-
mlxsw_sp_port_vlan->ref_count++;
1195-
return mlxsw_sp_port_vlan;
1196-
}
1197-
1198-
return mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid);
1199-
}
1200-
1201-
void mlxsw_sp_port_vlan_put(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
1202-
{
1203-
struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
1204-
1205-
if (--mlxsw_sp_port_vlan->ref_count != 0)
1206-
return;
1207-
12081184
if (mlxsw_sp_port_vlan->bridge_port)
12091185
mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
1210-
else if (fid)
1186+
else if (mlxsw_sp_port_vlan->fid)
12111187
mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
12121188

1213-
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
1189+
list_del(&mlxsw_sp_port_vlan->list);
1190+
kfree(mlxsw_sp_port_vlan);
1191+
mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
12141192
}
12151193

12161194
static int mlxsw_sp_port_add_vid(struct net_device *dev,
@@ -1224,7 +1202,7 @@ static int mlxsw_sp_port_add_vid(struct net_device *dev,
12241202
if (!vid)
12251203
return 0;
12261204

1227-
return PTR_ERR_OR_ZERO(mlxsw_sp_port_vlan_get(mlxsw_sp_port, vid));
1205+
return PTR_ERR_OR_ZERO(mlxsw_sp_port_vlan_create(mlxsw_sp_port, vid));
12281206
}
12291207

12301208
static int mlxsw_sp_port_kill_vid(struct net_device *dev,
@@ -1242,7 +1220,7 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
12421220
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
12431221
if (!mlxsw_sp_port_vlan)
12441222
return 0;
1245-
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1223+
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
12461224

12471225
return 0;
12481226
}
@@ -3198,12 +3176,12 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
31983176
goto err_port_nve_init;
31993177
}
32003178

3201-
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_get(mlxsw_sp_port, 1);
3179+
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port, 1);
32023180
if (IS_ERR(mlxsw_sp_port_vlan)) {
32033181
dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to create VID 1\n",
32043182
mlxsw_sp_port->local_port);
32053183
err = PTR_ERR(mlxsw_sp_port_vlan);
3206-
goto err_port_vlan_get;
3184+
goto err_port_vlan_create;
32073185
}
32083186

32093187
mlxsw_sp_port_switchdev_init(mlxsw_sp_port);
@@ -3224,8 +3202,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
32243202
err_register_netdev:
32253203
mlxsw_sp->ports[local_port] = NULL;
32263204
mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
3227-
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
3228-
err_port_vlan_get:
3205+
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
3206+
err_port_vlan_create:
32293207
mlxsw_sp_port_nve_fini(mlxsw_sp_port);
32303208
err_port_nve_init:
32313209
mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port);
@@ -4721,7 +4699,7 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
47214699
mlxsw_sp_port->lagged = 0;
47224700
lag->ref_count--;
47234701

4724-
mlxsw_sp_port_vlan_get(mlxsw_sp_port, 1);
4702+
mlxsw_sp_port_vlan_create(mlxsw_sp_port, 1);
47254703
/* Make sure untagged frames are allowed to ingress */
47264704
mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
47274705
}

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ struct mlxsw_sp_port_vlan {
190190
struct list_head list;
191191
struct mlxsw_sp_port *mlxsw_sp_port;
192192
struct mlxsw_sp_fid *fid;
193-
unsigned int ref_count;
194193
u16 vid;
195194
struct mlxsw_sp_bridge_port *bridge_port;
196195
struct list_head bridge_vlan_node;
@@ -410,8 +409,8 @@ int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid,
410409
bool learn_enable);
411410
int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
412411
struct mlxsw_sp_port_vlan *
413-
mlxsw_sp_port_vlan_get(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
414-
void mlxsw_sp_port_vlan_put(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
412+
mlxsw_sp_port_vlan_create(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
413+
void mlxsw_sp_port_vlan_destroy(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
415414
int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin,
416415
u16 vid_end, bool is_member, bool untagged);
417416
int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,

drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,10 +1021,8 @@ mlxsw_sp_port_vlan_bridge_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
10211021
int err;
10221022

10231023
/* No need to continue if only VLAN flags were changed */
1024-
if (mlxsw_sp_port_vlan->bridge_port) {
1025-
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1024+
if (mlxsw_sp_port_vlan->bridge_port)
10261025
return 0;
1027-
}
10281026

10291027
err = mlxsw_sp_port_vlan_fid_join(mlxsw_sp_port_vlan, bridge_port,
10301028
extack);
@@ -1105,16 +1103,32 @@ static int
11051103
mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
11061104
struct mlxsw_sp_bridge_port *bridge_port,
11071105
u16 vid, bool is_untagged, bool is_pvid,
1108-
struct netlink_ext_ack *extack)
1106+
struct netlink_ext_ack *extack,
1107+
struct switchdev_trans *trans)
11091108
{
11101109
u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
11111110
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
11121111
u16 old_pvid = mlxsw_sp_port->pvid;
11131112
int err;
11141113

1115-
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_get(mlxsw_sp_port, vid);
1116-
if (IS_ERR(mlxsw_sp_port_vlan))
1117-
return PTR_ERR(mlxsw_sp_port_vlan);
1114+
/* The only valid scenario in which a port-vlan already exists, is if
1115+
* the VLAN flags were changed and the port-vlan is associated with the
1116+
* correct bridge port
1117+
*/
1118+
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
1119+
if (mlxsw_sp_port_vlan &&
1120+
mlxsw_sp_port_vlan->bridge_port != bridge_port)
1121+
return -EEXIST;
1122+
1123+
if (switchdev_trans_ph_prepare(trans))
1124+
return 0;
1125+
1126+
if (!mlxsw_sp_port_vlan) {
1127+
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
1128+
vid);
1129+
if (IS_ERR(mlxsw_sp_port_vlan))
1130+
return PTR_ERR(mlxsw_sp_port_vlan);
1131+
}
11181132

11191133
err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true,
11201134
is_untagged);
@@ -1137,7 +1151,7 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
11371151
err_port_pvid_set:
11381152
mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
11391153
err_port_vlan_set:
1140-
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1154+
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
11411155
return err;
11421156
}
11431157

@@ -1199,9 +1213,6 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
11991213
return err;
12001214
}
12011215

1202-
if (switchdev_trans_ph_prepare(trans))
1203-
return 0;
1204-
12051216
bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
12061217
if (WARN_ON(!bridge_port))
12071218
return -EINVAL;
@@ -1214,7 +1225,7 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
12141225

12151226
err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port,
12161227
vid, flag_untagged,
1217-
flag_pvid, extack);
1228+
flag_pvid, extack, trans);
12181229
if (err)
12191230
return err;
12201231
}
@@ -1832,7 +1843,7 @@ mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port,
18321843
mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);
18331844
mlxsw_sp_port_pvid_set(mlxsw_sp_port, pvid);
18341845
mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false);
1835-
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
1846+
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
18361847
}
18371848

18381849
static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -2000,7 +2011,7 @@ mlxsw_sp_bridge_8021q_port_join(struct mlxsw_sp_bridge_device *bridge_device,
20002011
return -EINVAL;
20012012

20022013
/* Let VLAN-aware bridge take care of its own VLANs */
2003-
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
2014+
mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan);
20042015

20052016
return 0;
20062017
}
@@ -2010,7 +2021,7 @@ mlxsw_sp_bridge_8021q_port_leave(struct mlxsw_sp_bridge_device *bridge_device,
20102021
struct mlxsw_sp_bridge_port *bridge_port,
20112022
struct mlxsw_sp_port *mlxsw_sp_port)
20122023
{
2013-
mlxsw_sp_port_vlan_get(mlxsw_sp_port, 1);
2024+
mlxsw_sp_port_vlan_create(mlxsw_sp_port, 1);
20142025
/* Make sure untagged frames are allowed to ingress */
20152026
mlxsw_sp_port_pvid_set(mlxsw_sp_port, 1);
20162027
}

0 commit comments

Comments
 (0)