@@ -2755,6 +2755,140 @@ static void mlxsw_sp_parsing_fini(struct mlxsw_sp *mlxsw_sp)
2755
2755
mutex_destroy (& mlxsw_sp -> parsing .lock );
2756
2756
}
2757
2757
2758
+ struct mlxsw_sp_ipv6_addr_node {
2759
+ struct in6_addr key ;
2760
+ struct rhash_head ht_node ;
2761
+ u32 kvdl_index ;
2762
+ refcount_t refcount ;
2763
+ };
2764
+
2765
+ static const struct rhashtable_params mlxsw_sp_ipv6_addr_ht_params = {
2766
+ .key_offset = offsetof(struct mlxsw_sp_ipv6_addr_node , key ),
2767
+ .head_offset = offsetof(struct mlxsw_sp_ipv6_addr_node , ht_node ),
2768
+ .key_len = sizeof (struct in6_addr ),
2769
+ .automatic_shrinking = true,
2770
+ };
2771
+
2772
+ static int
2773
+ mlxsw_sp_ipv6_addr_init (struct mlxsw_sp * mlxsw_sp , const struct in6_addr * addr6 ,
2774
+ u32 * p_kvdl_index )
2775
+ {
2776
+ struct mlxsw_sp_ipv6_addr_node * node ;
2777
+ char rips_pl [MLXSW_REG_RIPS_LEN ];
2778
+ int err ;
2779
+
2780
+ err = mlxsw_sp_kvdl_alloc (mlxsw_sp ,
2781
+ MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS , 1 ,
2782
+ p_kvdl_index );
2783
+ if (err )
2784
+ return err ;
2785
+
2786
+ mlxsw_reg_rips_pack (rips_pl , * p_kvdl_index , addr6 );
2787
+ err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (rips ), rips_pl );
2788
+ if (err )
2789
+ goto err_rips_write ;
2790
+
2791
+ node = kzalloc (sizeof (* node ), GFP_KERNEL );
2792
+ if (!node ) {
2793
+ err = - ENOMEM ;
2794
+ goto err_node_alloc ;
2795
+ }
2796
+
2797
+ node -> key = * addr6 ;
2798
+ node -> kvdl_index = * p_kvdl_index ;
2799
+ refcount_set (& node -> refcount , 1 );
2800
+
2801
+ err = rhashtable_insert_fast (& mlxsw_sp -> ipv6_addr_ht ,
2802
+ & node -> ht_node ,
2803
+ mlxsw_sp_ipv6_addr_ht_params );
2804
+ if (err )
2805
+ goto err_rhashtable_insert ;
2806
+
2807
+ return 0 ;
2808
+
2809
+ err_rhashtable_insert :
2810
+ kfree (node );
2811
+ err_node_alloc :
2812
+ err_rips_write :
2813
+ mlxsw_sp_kvdl_free (mlxsw_sp , MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS , 1 ,
2814
+ * p_kvdl_index );
2815
+ return err ;
2816
+ }
2817
+
2818
+ static void mlxsw_sp_ipv6_addr_fini (struct mlxsw_sp * mlxsw_sp ,
2819
+ struct mlxsw_sp_ipv6_addr_node * node )
2820
+ {
2821
+ u32 kvdl_index = node -> kvdl_index ;
2822
+
2823
+ rhashtable_remove_fast (& mlxsw_sp -> ipv6_addr_ht , & node -> ht_node ,
2824
+ mlxsw_sp_ipv6_addr_ht_params );
2825
+ kfree (node );
2826
+ mlxsw_sp_kvdl_free (mlxsw_sp , MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS , 1 ,
2827
+ kvdl_index );
2828
+ }
2829
+
2830
+ int mlxsw_sp_ipv6_addr_kvdl_index_get (struct mlxsw_sp * mlxsw_sp ,
2831
+ const struct in6_addr * addr6 ,
2832
+ u32 * p_kvdl_index )
2833
+ {
2834
+ struct mlxsw_sp_ipv6_addr_node * node ;
2835
+ int err = 0 ;
2836
+
2837
+ mutex_lock (& mlxsw_sp -> ipv6_addr_ht_lock );
2838
+ node = rhashtable_lookup_fast (& mlxsw_sp -> ipv6_addr_ht , addr6 ,
2839
+ mlxsw_sp_ipv6_addr_ht_params );
2840
+ if (node ) {
2841
+ refcount_inc (& node -> refcount );
2842
+ * p_kvdl_index = node -> kvdl_index ;
2843
+ goto out_unlock ;
2844
+ }
2845
+
2846
+ err = mlxsw_sp_ipv6_addr_init (mlxsw_sp , addr6 , p_kvdl_index );
2847
+
2848
+ out_unlock :
2849
+ mutex_unlock (& mlxsw_sp -> ipv6_addr_ht_lock );
2850
+ return err ;
2851
+ }
2852
+
2853
+ void
2854
+ mlxsw_sp_ipv6_addr_put (struct mlxsw_sp * mlxsw_sp , const struct in6_addr * addr6 )
2855
+ {
2856
+ struct mlxsw_sp_ipv6_addr_node * node ;
2857
+
2858
+ mutex_lock (& mlxsw_sp -> ipv6_addr_ht_lock );
2859
+ node = rhashtable_lookup_fast (& mlxsw_sp -> ipv6_addr_ht , addr6 ,
2860
+ mlxsw_sp_ipv6_addr_ht_params );
2861
+ if (WARN_ON (!node ))
2862
+ goto out_unlock ;
2863
+
2864
+ if (!refcount_dec_and_test (& node -> refcount ))
2865
+ goto out_unlock ;
2866
+
2867
+ mlxsw_sp_ipv6_addr_fini (mlxsw_sp , node );
2868
+
2869
+ out_unlock :
2870
+ mutex_unlock (& mlxsw_sp -> ipv6_addr_ht_lock );
2871
+ }
2872
+
2873
+ static int mlxsw_sp_ipv6_addr_ht_init (struct mlxsw_sp * mlxsw_sp )
2874
+ {
2875
+ int err ;
2876
+
2877
+ err = rhashtable_init (& mlxsw_sp -> ipv6_addr_ht ,
2878
+ & mlxsw_sp_ipv6_addr_ht_params );
2879
+ if (err )
2880
+ return err ;
2881
+
2882
+ mutex_init (& mlxsw_sp -> ipv6_addr_ht_lock );
2883
+ return 0 ;
2884
+ }
2885
+
2886
+ static void mlxsw_sp_ipv6_addr_ht_fini (struct mlxsw_sp * mlxsw_sp )
2887
+ {
2888
+ mutex_destroy (& mlxsw_sp -> ipv6_addr_ht_lock );
2889
+ rhashtable_destroy (& mlxsw_sp -> ipv6_addr_ht );
2890
+ }
2891
+
2758
2892
static int mlxsw_sp_init (struct mlxsw_core * mlxsw_core ,
2759
2893
const struct mlxsw_bus_info * mlxsw_bus_info ,
2760
2894
struct netlink_ext_ack * extack )
@@ -2843,6 +2977,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
2843
2977
goto err_afa_init ;
2844
2978
}
2845
2979
2980
+ err = mlxsw_sp_ipv6_addr_ht_init (mlxsw_sp );
2981
+ if (err ) {
2982
+ dev_err (mlxsw_sp -> bus_info -> dev , "Failed to initialize hash table for IPv6 addresses\n" );
2983
+ goto err_ipv6_addr_ht_init ;
2984
+ }
2985
+
2846
2986
err = mlxsw_sp_nve_init (mlxsw_sp );
2847
2987
if (err ) {
2848
2988
dev_err (mlxsw_sp -> bus_info -> dev , "Failed to initialize NVE\n" );
@@ -2944,6 +3084,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
2944
3084
err_acl_init :
2945
3085
mlxsw_sp_nve_fini (mlxsw_sp );
2946
3086
err_nve_init :
3087
+ mlxsw_sp_ipv6_addr_ht_fini (mlxsw_sp );
3088
+ err_ipv6_addr_ht_init :
2947
3089
mlxsw_sp_afa_fini (mlxsw_sp );
2948
3090
err_afa_init :
2949
3091
mlxsw_sp_counter_pool_fini (mlxsw_sp );
@@ -3075,6 +3217,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
3075
3217
mlxsw_sp_router_fini (mlxsw_sp );
3076
3218
mlxsw_sp_acl_fini (mlxsw_sp );
3077
3219
mlxsw_sp_nve_fini (mlxsw_sp );
3220
+ mlxsw_sp_ipv6_addr_ht_fini (mlxsw_sp );
3078
3221
mlxsw_sp_afa_fini (mlxsw_sp );
3079
3222
mlxsw_sp_counter_pool_fini (mlxsw_sp );
3080
3223
mlxsw_sp_switchdev_fini (mlxsw_sp );
0 commit comments