@@ -68,6 +68,7 @@ struct mlxsw_sp_mr_table {
6868 u32 vr_id ;
6969 struct mlxsw_sp_mr_vif vifs [MAXVIFS ];
7070 struct list_head route_list ;
71+ struct mutex route_list_lock ; /* Protects route_list */
7172 struct rhashtable route_ht ;
7273 const struct mlxsw_sp_mr_table_ops * ops ;
7374 char catchall_route_priv [];
@@ -372,6 +373,8 @@ static void mlxsw_sp_mr_mfc_offload_update(struct mlxsw_sp_mr_route *mr_route)
372373static void __mlxsw_sp_mr_route_del (struct mlxsw_sp_mr_table * mr_table ,
373374 struct mlxsw_sp_mr_route * mr_route )
374375{
376+ WARN_ON_ONCE (!mutex_is_locked (& mr_table -> route_list_lock ));
377+
375378 mlxsw_sp_mr_mfc_offload_set (mr_route , false);
376379 rhashtable_remove_fast (& mr_table -> route_ht , & mr_route -> ht_node ,
377380 mlxsw_sp_mr_route_ht_params );
@@ -423,7 +426,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table,
423426 goto err_mr_route_write ;
424427
425428 /* Put it in the table data-structures */
429+ mutex_lock (& mr_table -> route_list_lock );
426430 list_add_tail (& mr_route -> node , & mr_table -> route_list );
431+ mutex_unlock (& mr_table -> route_list_lock );
427432 err = rhashtable_insert_fast (& mr_table -> route_ht ,
428433 & mr_route -> ht_node ,
429434 mlxsw_sp_mr_route_ht_params );
@@ -443,7 +448,9 @@ int mlxsw_sp_mr_route_add(struct mlxsw_sp_mr_table *mr_table,
443448 return 0 ;
444449
445450err_rhashtable_insert :
451+ mutex_lock (& mr_table -> route_list_lock );
446452 list_del (& mr_route -> node );
453+ mutex_unlock (& mr_table -> route_list_lock );
447454 mlxsw_sp_mr_route_erase (mr_table , mr_route );
448455err_mr_route_write :
449456err_no_orig_route :
@@ -461,8 +468,11 @@ void mlxsw_sp_mr_route_del(struct mlxsw_sp_mr_table *mr_table,
461468 mr_table -> ops -> key_create (mr_table , & key , mfc );
462469 mr_route = rhashtable_lookup_fast (& mr_table -> route_ht , & key ,
463470 mlxsw_sp_mr_route_ht_params );
464- if (mr_route )
471+ if (mr_route ) {
472+ mutex_lock (& mr_table -> route_list_lock );
465473 __mlxsw_sp_mr_route_del (mr_table , mr_route );
474+ mutex_unlock (& mr_table -> route_list_lock );
475+ }
466476}
467477
468478/* Should be called after the VIF struct is updated */
@@ -911,6 +921,7 @@ struct mlxsw_sp_mr_table *mlxsw_sp_mr_table_create(struct mlxsw_sp *mlxsw_sp,
911921 mr_table -> proto = proto ;
912922 mr_table -> ops = & mlxsw_sp_mr_table_ops_arr [proto ];
913923 INIT_LIST_HEAD (& mr_table -> route_list );
924+ mutex_init (& mr_table -> route_list_lock );
914925
915926 err = rhashtable_init (& mr_table -> route_ht ,
916927 & mlxsw_sp_mr_route_ht_params );
@@ -936,6 +947,7 @@ struct mlxsw_sp_mr_table *mlxsw_sp_mr_table_create(struct mlxsw_sp *mlxsw_sp,
936947err_ops_route_create :
937948 rhashtable_destroy (& mr_table -> route_ht );
938949err_route_rhashtable_init :
950+ mutex_destroy (& mr_table -> route_list_lock );
939951 kfree (mr_table );
940952 return ERR_PTR (err );
941953}
@@ -952,6 +964,7 @@ void mlxsw_sp_mr_table_destroy(struct mlxsw_sp_mr_table *mr_table)
952964 mr -> mr_ops -> route_destroy (mlxsw_sp , mr -> priv ,
953965 & mr_table -> catchall_route_priv );
954966 rhashtable_destroy (& mr_table -> route_ht );
967+ mutex_destroy (& mr_table -> route_list_lock );
955968 kfree (mr_table );
956969}
957970
@@ -960,8 +973,10 @@ void mlxsw_sp_mr_table_flush(struct mlxsw_sp_mr_table *mr_table)
960973 struct mlxsw_sp_mr_route * mr_route , * tmp ;
961974 int i ;
962975
976+ mutex_lock (& mr_table -> route_list_lock );
963977 list_for_each_entry_safe (mr_route , tmp , & mr_table -> route_list , node )
964978 __mlxsw_sp_mr_route_del (mr_table , mr_route );
979+ mutex_unlock (& mr_table -> route_list_lock );
965980
966981 for (i = 0 ; i < MAXVIFS ; i ++ ) {
967982 mr_table -> vifs [i ].dev = NULL ;
@@ -1005,14 +1020,15 @@ static void mlxsw_sp_mr_stats_update(struct work_struct *work)
10051020 struct mlxsw_sp_mr_route * mr_route ;
10061021 unsigned long interval ;
10071022
1008- rtnl_lock ();
10091023 mutex_lock (& mr -> table_list_lock );
1010- list_for_each_entry (mr_table , & mr -> table_list , node )
1024+ list_for_each_entry (mr_table , & mr -> table_list , node ) {
1025+ mutex_lock (& mr_table -> route_list_lock );
10111026 list_for_each_entry (mr_route , & mr_table -> route_list , node )
10121027 mlxsw_sp_mr_route_stats_update (mr_table -> mlxsw_sp ,
10131028 mr_route );
1029+ mutex_unlock (& mr_table -> route_list_lock );
1030+ }
10141031 mutex_unlock (& mr -> table_list_lock );
1015- rtnl_unlock ();
10161032
10171033 interval = msecs_to_jiffies (MLXSW_SP_MR_ROUTES_COUNTER_UPDATE_INTERVAL );
10181034 mlxsw_core_schedule_dw (& mr -> stats_update_dw , interval );
0 commit comments