Skip to content

Commit c366de8

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum_mr: Protect multicast table list with a lock
The multicast table list is traversed from a delayed work that periodically updates the kernel about packets and bytes statistics from each multicast route. The list is currently protected by RTNL, but subsequent patches will remove the driver's dependence on this contended lock. In order to be able to remove dependence on RTNL in the next patch, guard this list with a dedicated mutex. Signed-off-by: Ido Schimmel <[email protected]> Acked-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3e3c8da commit c366de8

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
22
/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
33

4+
#include <linux/mutex.h>
45
#include <linux/rhashtable.h>
56
#include <net/ipv6.h>
67

@@ -12,6 +13,7 @@ struct mlxsw_sp_mr {
1213
void *catchall_route_priv;
1314
struct delayed_work stats_update_dw;
1415
struct list_head table_list;
16+
struct mutex table_list_lock; /* Protects table_list */
1517
#define MLXSW_SP_MR_ROUTES_COUNTER_UPDATE_INTERVAL 5000 /* ms */
1618
unsigned long priv[0];
1719
/* priv has to be always the last item */
@@ -926,7 +928,9 @@ struct mlxsw_sp_mr_table *mlxsw_sp_mr_table_create(struct mlxsw_sp *mlxsw_sp,
926928
&catchall_route_params);
927929
if (err)
928930
goto err_ops_route_create;
931+
mutex_lock(&mr->table_list_lock);
929932
list_add_tail(&mr_table->node, &mr->table_list);
933+
mutex_unlock(&mr->table_list_lock);
930934
return mr_table;
931935

932936
err_ops_route_create:
@@ -942,7 +946,9 @@ void mlxsw_sp_mr_table_destroy(struct mlxsw_sp_mr_table *mr_table)
942946
struct mlxsw_sp_mr *mr = mlxsw_sp->mr;
943947

944948
WARN_ON(!mlxsw_sp_mr_table_empty(mr_table));
949+
mutex_lock(&mr->table_list_lock);
945950
list_del(&mr_table->node);
951+
mutex_unlock(&mr->table_list_lock);
946952
mr->mr_ops->route_destroy(mlxsw_sp, mr->priv,
947953
&mr_table->catchall_route_priv);
948954
rhashtable_destroy(&mr_table->route_ht);
@@ -1000,10 +1006,12 @@ static void mlxsw_sp_mr_stats_update(struct work_struct *work)
10001006
unsigned long interval;
10011007

10021008
rtnl_lock();
1009+
mutex_lock(&mr->table_list_lock);
10031010
list_for_each_entry(mr_table, &mr->table_list, node)
10041011
list_for_each_entry(mr_route, &mr_table->route_list, node)
10051012
mlxsw_sp_mr_route_stats_update(mr_table->mlxsw_sp,
10061013
mr_route);
1014+
mutex_unlock(&mr->table_list_lock);
10071015
rtnl_unlock();
10081016

10091017
interval = msecs_to_jiffies(MLXSW_SP_MR_ROUTES_COUNTER_UPDATE_INTERVAL);
@@ -1023,6 +1031,7 @@ int mlxsw_sp_mr_init(struct mlxsw_sp *mlxsw_sp,
10231031
mr->mr_ops = mr_ops;
10241032
mlxsw_sp->mr = mr;
10251033
INIT_LIST_HEAD(&mr->table_list);
1034+
mutex_init(&mr->table_list_lock);
10261035

10271036
err = mr_ops->init(mlxsw_sp, mr->priv);
10281037
if (err)
@@ -1034,6 +1043,7 @@ int mlxsw_sp_mr_init(struct mlxsw_sp *mlxsw_sp,
10341043
mlxsw_core_schedule_dw(&mr->stats_update_dw, interval);
10351044
return 0;
10361045
err:
1046+
mutex_destroy(&mr->table_list_lock);
10371047
kfree(mr);
10381048
return err;
10391049
}
@@ -1044,5 +1054,6 @@ void mlxsw_sp_mr_fini(struct mlxsw_sp *mlxsw_sp)
10441054

10451055
cancel_delayed_work_sync(&mr->stats_update_dw);
10461056
mr->mr_ops->fini(mlxsw_sp, mr->priv);
1057+
mutex_destroy(&mr->table_list_lock);
10471058
kfree(mr);
10481059
}

0 commit comments

Comments
 (0)