Skip to content

Commit

Permalink
net/mlx5e: Eswitch, use state_lock to synchronize vlan change
Browse files Browse the repository at this point in the history
esw->state_lock is already used to protect vlan vport configuration change.
However, all preparation and correctness checks, and code that sets vport
data are not protected by this lock and assume external synchronization by
rtnl lock. In order to remove dependency on rtnl lock, extend
esw->state_lock protection to whole eswitch vlan add/del functions.

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Reviewed-by: Jianbo Liu <jianbol@mellanox.com>
Reviewed-by: Roi Dayan <roid@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
  • Loading branch information
w1ldptr authored and Saeed Mahameed committed Jul 29, 2019
1 parent 525e84b commit 0e18134
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 12 deletions.
15 changes: 8 additions & 7 deletions drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -2086,35 +2086,36 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
if (vlan > 4095 || qos > 7)
return -EINVAL;

mutex_lock(&esw->state_lock);

err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
if (err)
goto unlock;
return err;

evport->info.vlan = vlan;
evport->info.qos = qos;
if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) {
err = esw_vport_ingress_config(esw, evport);
if (err)
goto unlock;
return err;
err = esw_vport_egress_config(esw, evport);
}

unlock:
mutex_unlock(&esw->state_lock);
return err;
}

int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
u16 vport, u16 vlan, u8 qos)
{
u8 set_flags = 0;
int err;

if (vlan || qos)
set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;

return __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
mutex_lock(&esw->state_lock);
err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
mutex_unlock(&esw->state_lock);

return err;
}

int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
Expand Down
17 changes: 12 additions & 5 deletions drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,11 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
fwd = !!((attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
!attr->dest_chain);

mutex_lock(&esw->state_lock);

err = esw_add_vlan_action_check(attr, push, pop, fwd);
if (err)
return err;
goto unlock;

attr->vlan_handled = false;

Expand All @@ -457,11 +459,11 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
attr->vlan_handled = true;
}

return 0;
goto unlock;
}

if (!push && !pop)
return 0;
goto unlock;

if (!(offloads->vlan_push_pop_refcount)) {
/* it's the 1st vlan rule, apply global vlan pop policy */
Expand All @@ -486,6 +488,8 @@ int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
out:
if (!err)
attr->vlan_handled = true;
unlock:
mutex_unlock(&esw->state_lock);
return err;
}

Expand All @@ -508,14 +512,16 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
pop = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
fwd = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);

mutex_lock(&esw->state_lock);

vport = esw_vlan_action_get_vport(attr, push, pop);

if (!push && !pop && fwd) {
/* tracks VF --> wire rules without vlan push action */
if (attr->dests[0].rep->vport == MLX5_VPORT_UPLINK)
vport->vlan_refcount--;

return 0;
goto out;
}

if (push) {
Expand All @@ -533,12 +539,13 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw,
skip_unset_push:
offloads->vlan_push_pop_refcount--;
if (offloads->vlan_push_pop_refcount)
return 0;
goto out;

/* no more vlan rules, stop global vlan pop policy */
err = esw_set_global_vlan_pop(esw, 0);

out:
mutex_unlock(&esw->state_lock);
return err;
}

Expand Down

0 comments on commit 0e18134

Please sign in to comment.