hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
....@@ -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 @@
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 */
....@@ -66,9 +68,10 @@
6668 u32 vr_id;
6769 struct mlxsw_sp_mr_vif vifs[MAXVIFS];
6870 struct list_head route_list;
71
+ struct mutex route_list_lock; /* Protects route_list */
6972 struct rhashtable route_ht;
7073 const struct mlxsw_sp_mr_table_ops *ops;
71
- char catchall_route_priv[0];
74
+ char catchall_route_priv[];
7275 /* catchall_route_priv has to be always the last item */
7376 };
7477
....@@ -370,11 +373,13 @@
370373 static void __mlxsw_sp_mr_route_del(struct mlxsw_sp_mr_table *mr_table,
371374 struct mlxsw_sp_mr_route *mr_route)
372375 {
376
+ WARN_ON_ONCE(!mutex_is_locked(&mr_table->route_list_lock));
377
+
373378 mlxsw_sp_mr_mfc_offload_set(mr_route, false);
374
- mlxsw_sp_mr_route_erase(mr_table, mr_route);
375379 rhashtable_remove_fast(&mr_table->route_ht, &mr_route->ht_node,
376380 mlxsw_sp_mr_route_ht_params);
377381 list_del(&mr_route->node);
382
+ mlxsw_sp_mr_route_erase(mr_table, mr_route);
378383 mlxsw_sp_mr_route_destroy(mr_table, mr_route);
379384 }
380385
....@@ -415,18 +420,20 @@
415420 goto err_duplicate_route;
416421 }
417422
423
+ /* Write the route to the hardware */
424
+ err = mlxsw_sp_mr_route_write(mr_table, mr_route, replace);
425
+ if (err)
426
+ goto err_mr_route_write;
427
+
418428 /* Put it in the table data-structures */
429
+ mutex_lock(&mr_table->route_list_lock);
419430 list_add_tail(&mr_route->node, &mr_table->route_list);
431
+ mutex_unlock(&mr_table->route_list_lock);
420432 err = rhashtable_insert_fast(&mr_table->route_ht,
421433 &mr_route->ht_node,
422434 mlxsw_sp_mr_route_ht_params);
423435 if (err)
424436 goto err_rhashtable_insert;
425
-
426
- /* Write the route to the hardware */
427
- err = mlxsw_sp_mr_route_write(mr_table, mr_route, replace);
428
- if (err)
429
- goto err_mr_route_write;
430437
431438 /* Destroy the original route */
432439 if (replace) {
....@@ -440,11 +447,12 @@
440447 mlxsw_sp_mr_mfc_offload_update(mr_route);
441448 return 0;
442449
443
-err_mr_route_write:
444
- rhashtable_remove_fast(&mr_table->route_ht, &mr_route->ht_node,
445
- mlxsw_sp_mr_route_ht_params);
446450 err_rhashtable_insert:
451
+ mutex_lock(&mr_table->route_list_lock);
447452 list_del(&mr_route->node);
453
+ mutex_unlock(&mr_table->route_list_lock);
454
+ mlxsw_sp_mr_route_erase(mr_table, mr_route);
455
+err_mr_route_write:
448456 err_no_orig_route:
449457 err_duplicate_route:
450458 mlxsw_sp_mr_route_destroy(mr_table, mr_route);
....@@ -460,8 +468,11 @@
460468 mr_table->ops->key_create(mr_table, &key, mfc);
461469 mr_route = rhashtable_lookup_fast(&mr_table->route_ht, &key,
462470 mlxsw_sp_mr_route_ht_params);
463
- if (mr_route)
471
+ if (mr_route) {
472
+ mutex_lock(&mr_table->route_list_lock);
464473 __mlxsw_sp_mr_route_del(mr_table, mr_route);
474
+ mutex_unlock(&mr_table->route_list_lock);
475
+ }
465476 }
466477
467478 /* Should be called after the VIF struct is updated */
....@@ -910,6 +921,7 @@
910921 mr_table->proto = proto;
911922 mr_table->ops = &mlxsw_sp_mr_table_ops_arr[proto];
912923 INIT_LIST_HEAD(&mr_table->route_list);
924
+ mutex_init(&mr_table->route_list_lock);
913925
914926 err = rhashtable_init(&mr_table->route_ht,
915927 &mlxsw_sp_mr_route_ht_params);
....@@ -927,12 +939,15 @@
927939 &catchall_route_params);
928940 if (err)
929941 goto err_ops_route_create;
942
+ mutex_lock(&mr->table_list_lock);
930943 list_add_tail(&mr_table->node, &mr->table_list);
944
+ mutex_unlock(&mr->table_list_lock);
931945 return mr_table;
932946
933947 err_ops_route_create:
934948 rhashtable_destroy(&mr_table->route_ht);
935949 err_route_rhashtable_init:
950
+ mutex_destroy(&mr_table->route_list_lock);
936951 kfree(mr_table);
937952 return ERR_PTR(err);
938953 }
....@@ -943,10 +958,13 @@
943958 struct mlxsw_sp_mr *mr = mlxsw_sp->mr;
944959
945960 WARN_ON(!mlxsw_sp_mr_table_empty(mr_table));
961
+ mutex_lock(&mr->table_list_lock);
946962 list_del(&mr_table->node);
963
+ mutex_unlock(&mr->table_list_lock);
947964 mr->mr_ops->route_destroy(mlxsw_sp, mr->priv,
948965 &mr_table->catchall_route_priv);
949966 rhashtable_destroy(&mr_table->route_ht);
967
+ mutex_destroy(&mr_table->route_list_lock);
950968 kfree(mr_table);
951969 }
952970
....@@ -955,8 +973,10 @@
955973 struct mlxsw_sp_mr_route *mr_route, *tmp;
956974 int i;
957975
976
+ mutex_lock(&mr_table->route_list_lock);
958977 list_for_each_entry_safe(mr_route, tmp, &mr_table->route_list, node)
959978 __mlxsw_sp_mr_route_del(mr_table, mr_route);
979
+ mutex_unlock(&mr_table->route_list_lock);
960980
961981 for (i = 0; i < MAXVIFS; i++) {
962982 mr_table->vifs[i].dev = NULL;
....@@ -1000,12 +1020,15 @@
10001020 struct mlxsw_sp_mr_route *mr_route;
10011021 unsigned long interval;
10021022
1003
- rtnl_lock();
1004
- list_for_each_entry(mr_table, &mr->table_list, node)
1023
+ mutex_lock(&mr->table_list_lock);
1024
+ list_for_each_entry(mr_table, &mr->table_list, node) {
1025
+ mutex_lock(&mr_table->route_list_lock);
10051026 list_for_each_entry(mr_route, &mr_table->route_list, node)
10061027 mlxsw_sp_mr_route_stats_update(mr_table->mlxsw_sp,
10071028 mr_route);
1008
- rtnl_unlock();
1029
+ mutex_unlock(&mr_table->route_list_lock);
1030
+ }
1031
+ mutex_unlock(&mr->table_list_lock);
10091032
10101033 interval = msecs_to_jiffies(MLXSW_SP_MR_ROUTES_COUNTER_UPDATE_INTERVAL);
10111034 mlxsw_core_schedule_dw(&mr->stats_update_dw, interval);
....@@ -1024,6 +1047,7 @@
10241047 mr->mr_ops = mr_ops;
10251048 mlxsw_sp->mr = mr;
10261049 INIT_LIST_HEAD(&mr->table_list);
1050
+ mutex_init(&mr->table_list_lock);
10271051
10281052 err = mr_ops->init(mlxsw_sp, mr->priv);
10291053 if (err)
....@@ -1035,6 +1059,7 @@
10351059 mlxsw_core_schedule_dw(&mr->stats_update_dw, interval);
10361060 return 0;
10371061 err:
1062
+ mutex_destroy(&mr->table_list_lock);
10381063 kfree(mr);
10391064 return err;
10401065 }
....@@ -1045,5 +1070,6 @@
10451070
10461071 cancel_delayed_work_sync(&mr->stats_update_dw);
10471072 mr->mr_ops->fini(mlxsw_sp, mr->priv);
1073
+ mutex_destroy(&mr->table_list_lock);
10481074 kfree(mr);
10491075 }