net/mlx5e: Eswitch, change offloads num_flows type to atomic64
authorVlad Buslov <vladbu@mellanox.com>
Sun, 18 Nov 2018 11:12:59 +0000 (13:12 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 29 Jul 2019 23:40:25 +0000 (16:40 -0700)
Eswitch implements its own locking by means of state_lock mutex and
multiple fine-grained lock in containing data structures, and is supposed
to not rely on rtnl lock. However, eswitch offloads num_flows type is a
regular long long integer and cannot be modified concurrently. This is an
implicit assumptions that mlx5 tc is serialized (by rtnl lock or any other
means). In order to remove implicit dependency on rtnl lock, change
num_flows type to atomic64 to allow concurrent modifications.

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>
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

index 1f3891fde2eb171be76294b45aefcfab57f9990e..d365551d2f10aa377458320bc6a75a52a594a4db 100644 (file)
@@ -1933,6 +1933,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
 
        hash_init(esw->offloads.encap_tbl);
        hash_init(esw->offloads.mod_hdr_tbl);
+       atomic64_set(&esw->offloads.num_flows, 0);
        mutex_init(&esw->state_lock);
 
        mlx5_esw_for_all_vports(esw, i, vport) {
index a38e8a3c7c9a3b71b6a51c9f440b25878508340f..60f0c62b447b9a4a9af2dcfa90754f69b3467a0e 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/if_ether.h>
 #include <linux/if_link.h>
+#include <linux/atomic.h>
 #include <net/devlink.h>
 #include <linux/mlx5/device.h>
 #include <linux/mlx5/eswitch.h>
@@ -179,7 +180,7 @@ struct mlx5_esw_offload {
        struct mutex termtbl_mutex; /* protects termtbl hash */
        const struct mlx5_eswitch_rep_ops *rep_ops[NUM_REP_TYPES];
        u8 inline_mode;
-       u64 num_flows;
+       atomic64_t num_flows;
        enum devlink_eswitch_encap_mode encap;
 };
 
index 089ae4d48a82dda15e47c49530f9a4e513577acb..244ad1893691242e9efaaf2b7cb0efc9d2d14546 100644 (file)
@@ -233,7 +233,7 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
        if (IS_ERR(rule))
                goto err_add_rule;
        else
-               esw->offloads.num_flows++;
+               atomic64_inc(&esw->offloads.num_flows);
 
        return rule;
 
@@ -298,7 +298,7 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
        if (IS_ERR(rule))
                goto add_err;
 
-       esw->offloads.num_flows++;
+       atomic64_inc(&esw->offloads.num_flows);
 
        return rule;
 add_err:
@@ -326,7 +326,7 @@ __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw,
                        mlx5_eswitch_termtbl_put(esw, attr->dests[i].termtbl);
        }
 
-       esw->offloads.num_flows--;
+       atomic64_dec(&esw->offloads.num_flows);
 
        if (fwd_rule)  {
                esw_put_prio_table(esw, attr->chain, attr->prio, 1);
@@ -2349,7 +2349,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
                break;
        }
 
-       if (esw->offloads.num_flows > 0) {
+       if (atomic64_read(&esw->offloads.num_flows) > 0) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "Can't set inline mode when flows are configured");
                return -EOPNOTSUPP;
@@ -2459,7 +2459,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
        if (esw->offloads.encap == encap)
                return 0;
 
-       if (esw->offloads.num_flows > 0) {
+       if (atomic64_read(&esw->offloads.num_flows) > 0) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "Can't set encapsulation when flows are configured");
                return -EOPNOTSUPP;