Skip to content

Commit

Permalink
net: microchip: sparx5: Add VCAP locking to protect rules
Browse files Browse the repository at this point in the history
This ensures that the VCAP cache and the lists maintained in the VCAP
instance is protected when accessed by different clients.

Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Steen Hegelund authored and David S. Miller committed Nov 21, 2022
1 parent 72d84dd commit 71c9de9
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 0 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/microchip/sparx5/sparx5_vcap_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ static void sparx5_vcap_admin_free(struct vcap_admin *admin)
{
if (!admin)
return;
mutex_destroy(&admin->lock);
kfree(admin->cache.keystream);
kfree(admin->cache.maskstream);
kfree(admin->cache.actionstream);
Expand All @@ -598,6 +599,7 @@ sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl,
INIT_LIST_HEAD(&admin->list);
INIT_LIST_HEAD(&admin->rules);
INIT_LIST_HEAD(&admin->enabled);
mutex_init(&admin->lock);
admin->vtype = cfg->vtype;
admin->vinst = cfg->vinst;
admin->lookups = cfg->lookups;
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/ethernet/microchip/vcap/vcap_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,7 @@ int vcap_add_rule(struct vcap_rule *rule)
if (ret)
return ret;
/* Insert the new rule in the list of vcap rules */
mutex_lock(&ri->admin->lock);
ret = vcap_insert_rule(ri, &move);
if (ret < 0) {
pr_err("%s:%d: could not insert rule in vcap list: %d\n",
Expand All @@ -1072,6 +1073,7 @@ int vcap_add_rule(struct vcap_rule *rule)
if (ret)
pr_err("%s:%d: rule write error: %d\n", __func__, __LINE__, ret);
out:
mutex_unlock(&ri->admin->lock);
return ret;
}
EXPORT_SYMBOL_GPL(vcap_add_rule);
Expand Down Expand Up @@ -1221,9 +1223,11 @@ int vcap_del_rule(struct vcap_control *vctrl, struct net_device *ndev, u32 id)
gap = vcap_fill_rule_gap(ri);

/* Delete the rule from the list of rules and the cache */
mutex_lock(&admin->lock);
list_del(&ri->list);
vctrl->ops->init(ndev, admin, admin->last_used_addr, ri->size + gap);
kfree(ri);
mutex_unlock(&admin->lock);

/* Update the last used address, set to default when no rules */
if (list_empty(&admin->rules)) {
Expand All @@ -1246,6 +1250,8 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin)

if (ret)
return ret;

mutex_lock(&admin->lock);
list_for_each_entry_safe(ri, next_ri, &admin->rules, list) {
vctrl->ops->init(ri->ndev, admin, ri->addr, ri->size);
list_del(&ri->list);
Expand All @@ -1258,6 +1264,7 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin)
list_del(&eport->list);
kfree(eport);
}
mutex_unlock(&admin->lock);

return 0;
}
Expand Down Expand Up @@ -1687,10 +1694,13 @@ int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
if (chain_id) {
if (vcap_is_enabled(admin, ndev, cookie))
return -EADDRINUSE;
mutex_lock(&admin->lock);
vcap_enable(admin, ndev, cookie);
} else {
mutex_lock(&admin->lock);
vcap_disable(admin, ndev, cookie);
}
mutex_unlock(&admin->lock);

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/microchip/vcap/vcap_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ struct vcap_admin {
struct list_head list; /* for insertion in vcap_control */
struct list_head rules; /* list of rules */
struct list_head enabled; /* list of enabled ports */
struct mutex lock; /* control access to rules */
enum vcap_type vtype; /* type of vcap */
int vinst; /* instance number within the same type */
int first_cid; /* first chain id in this vcap */
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/microchip/vcap/vcap_api_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ static int vcap_show_admin(struct vcap_control *vctrl,
int ret = 0;

vcap_show_admin_info(vctrl, admin, out);
mutex_lock(&admin->lock);
list_for_each_entry(elem, &admin->rules, list) {
ri = vcap_dup_rule(elem);
if (IS_ERR(ri))
Expand All @@ -638,6 +639,7 @@ static int vcap_show_admin(struct vcap_control *vctrl,
free_rule:
vcap_free_rule((struct vcap_rule *)ri);
}
mutex_unlock(&admin->lock);
return ret;
}

Expand Down

0 comments on commit 71c9de9

Please sign in to comment.