@@ -2755,6 +2755,140 @@ static void mlxsw_sp_parsing_fini(struct mlxsw_sp *mlxsw_sp)
27552755 mutex_destroy (& mlxsw_sp -> parsing .lock );
27562756}
27572757
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+
27582892static int mlxsw_sp_init (struct mlxsw_core * mlxsw_core ,
27592893 const struct mlxsw_bus_info * mlxsw_bus_info ,
27602894 struct netlink_ext_ack * extack )
@@ -2843,6 +2977,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
28432977 goto err_afa_init ;
28442978 }
28452979
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+
28462986 err = mlxsw_sp_nve_init (mlxsw_sp );
28472987 if (err ) {
28482988 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,
29443084err_acl_init :
29453085 mlxsw_sp_nve_fini (mlxsw_sp );
29463086err_nve_init :
3087+ mlxsw_sp_ipv6_addr_ht_fini (mlxsw_sp );
3088+ err_ipv6_addr_ht_init :
29473089 mlxsw_sp_afa_fini (mlxsw_sp );
29483090err_afa_init :
29493091 mlxsw_sp_counter_pool_fini (mlxsw_sp );
@@ -3075,6 +3217,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
30753217 mlxsw_sp_router_fini (mlxsw_sp );
30763218 mlxsw_sp_acl_fini (mlxsw_sp );
30773219 mlxsw_sp_nve_fini (mlxsw_sp );
3220+ mlxsw_sp_ipv6_addr_ht_fini (mlxsw_sp );
30783221 mlxsw_sp_afa_fini (mlxsw_sp );
30793222 mlxsw_sp_counter_pool_fini (mlxsw_sp );
30803223 mlxsw_sp_switchdev_fini (mlxsw_sp );
0 commit comments