OSDN Git Service

mlxsw: spectrum_acl: Introduce vregion mutex
authorJiri Pirko <jiri@mellanox.com>
Sun, 24 Feb 2019 06:46:26 +0000 (06:46 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 25 Feb 2019 04:25:29 +0000 (20:25 -0800)
In order to remove dependency on RTNL, introduce a mutex
to guard vregion structure, list of chunks and list of entries in
chunks.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c

index e100b14..54c0519 100644 (file)
@@ -178,6 +178,9 @@ struct mlxsw_sp_acl_tcam_vgroup {
 };
 
 struct mlxsw_sp_acl_tcam_vregion {
+       struct mutex lock; /* Protects consistency of region, region2 pointers
+                           * and vchunk_list.
+                           */
        struct mlxsw_sp_acl_tcam_region *region;
        struct mlxsw_sp_acl_tcam_region *region2; /* Used during migration */
        struct list_head list; /* Member of a TCAM group */
@@ -747,6 +750,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
        if (!vregion)
                return ERR_PTR(-ENOMEM);
        INIT_LIST_HEAD(&vregion->vchunk_list);
+       mutex_init(&vregion->lock);
        vregion->tcam = tcam;
        vregion->mlxsw_sp = mlxsw_sp;
        vregion->ref_count = 1;
@@ -803,6 +807,7 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
                mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region2);
        mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, vregion->region);
        mlxsw_afk_key_info_put(vregion->key_info);
+       mutex_destroy(&vregion->lock);
        kfree(vregion);
 }
 
@@ -947,14 +952,17 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
        if (err)
                goto err_rhashtable_insert;
 
+       mutex_lock(&vregion->lock);
        vchunk->chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk,
                                                       vchunk->vregion->region);
        if (IS_ERR(vchunk->chunk)) {
+               mutex_unlock(&vregion->lock);
                err = PTR_ERR(vchunk->chunk);
                goto err_chunk_create;
        }
 
        list_add_tail(&vchunk->list, &vregion->vchunk_list);
+       mutex_unlock(&vregion->lock);
 
        return vchunk;
 
@@ -972,12 +980,15 @@ static void
 mlxsw_sp_acl_tcam_vchunk_destroy(struct mlxsw_sp *mlxsw_sp,
                                 struct mlxsw_sp_acl_tcam_vchunk *vchunk)
 {
+       struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
        struct mlxsw_sp_acl_tcam_vgroup *vgroup = vchunk->vgroup;
 
+       mutex_lock(&vregion->lock);
        list_del(&vchunk->list);
        if (vchunk->chunk2)
                mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
        mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk);
+       mutex_unlock(&vregion->lock);
        rhashtable_remove_fast(&vgroup->vchunk_ht, &vchunk->ht_node,
                               mlxsw_sp_acl_tcam_vchunk_ht_params);
        mlxsw_sp_acl_tcam_vregion_put(mlxsw_sp, vchunk->vregion);
@@ -1079,6 +1090,7 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp,
                                        struct mlxsw_sp_acl_tcam_ventry *ventry,
                                        struct mlxsw_sp_acl_rule_info *rulei)
 {
+       struct mlxsw_sp_acl_tcam_vregion *vregion;
        struct mlxsw_sp_acl_tcam_vchunk *vchunk;
        int err;
 
@@ -1089,14 +1101,19 @@ static int mlxsw_sp_acl_tcam_ventry_add(struct mlxsw_sp *mlxsw_sp,
 
        ventry->vchunk = vchunk;
        ventry->rulei = rulei;
+       vregion = vchunk->vregion;
+
+       mutex_lock(&vregion->lock);
        ventry->entry = mlxsw_sp_acl_tcam_entry_create(mlxsw_sp, ventry,
                                                       vchunk->chunk);
        if (IS_ERR(ventry->entry)) {
+               mutex_unlock(&vregion->lock);
                err = PTR_ERR(ventry->entry);
                goto err_entry_create;
        }
 
        list_add_tail(&ventry->list, &vchunk->ventry_list);
+       mutex_unlock(&vregion->lock);
 
        return 0;
 
@@ -1109,9 +1126,12 @@ static void mlxsw_sp_acl_tcam_ventry_del(struct mlxsw_sp *mlxsw_sp,
                                         struct mlxsw_sp_acl_tcam_ventry *ventry)
 {
        struct mlxsw_sp_acl_tcam_vchunk *vchunk = ventry->vchunk;
+       struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
 
+       mutex_lock(&vregion->lock);
        list_del(&ventry->list);
        mlxsw_sp_acl_tcam_entry_destroy(mlxsw_sp, ventry->entry);
+       mutex_unlock(&vregion->lock);
        mlxsw_sp_acl_tcam_vchunk_put(mlxsw_sp, vchunk);
 }
 
@@ -1256,6 +1276,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
        if (err)
                goto err_group_region_attach;
 
+       mutex_lock(&vregion->lock);
+
        err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion);
        if (!vregion->failed_rollback) {
                if (!err) {
@@ -1270,10 +1292,14 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
                         */
                        unused_region = vregion->region2;
                }
+               mutex_unlock(&vregion->lock);
                vregion->region2 = NULL;
                mlxsw_sp_acl_tcam_group_region_detach(mlxsw_sp, unused_region);
                mlxsw_sp_acl_tcam_region_destroy(mlxsw_sp, unused_region);
+       } else {
+               mutex_unlock(&vregion->lock);
        }
+
        return err;
 
 err_group_region_attach: