125245d5dSShiri Kuzin /* SPDX-License-Identifier: BSD-3-Clause 225245d5dSShiri Kuzin * Copyright 2019 Mellanox Technologies, Ltd 325245d5dSShiri Kuzin */ 425245d5dSShiri Kuzin 525245d5dSShiri Kuzin #include <rte_malloc.h> 625245d5dSShiri Kuzin #include <rte_hash_crc.h> 725245d5dSShiri Kuzin #include <rte_errno.h> 825245d5dSShiri Kuzin 925245d5dSShiri Kuzin #include <mlx5_malloc.h> 1025245d5dSShiri Kuzin 1125245d5dSShiri Kuzin #include "mlx5_common_utils.h" 1225245d5dSShiri Kuzin #include "mlx5_common_log.h" 1325245d5dSShiri Kuzin 149c373c52SSuanming Mou /********************* mlx5 list ************************/ 159c373c52SSuanming Mou 16961b6774SMatan Azrad static int 17961b6774SMatan Azrad mlx5_list_init(struct mlx5_list *list, const char *name, void *ctx, 18*25481e50SSuanming Mou bool lcores_share, struct mlx5_list_cache *gc, 19*25481e50SSuanming Mou mlx5_list_create_cb cb_create, 209c373c52SSuanming Mou mlx5_list_match_cb cb_match, 219c373c52SSuanming Mou mlx5_list_remove_cb cb_remove, 229c373c52SSuanming Mou mlx5_list_clone_cb cb_clone, 239c373c52SSuanming Mou mlx5_list_clone_free_cb cb_clone_free) 249c373c52SSuanming Mou { 259c373c52SSuanming Mou if (!cb_match || !cb_create || !cb_remove || !cb_clone || 269c373c52SSuanming Mou !cb_clone_free) { 279c373c52SSuanming Mou rte_errno = EINVAL; 28961b6774SMatan Azrad return -EINVAL; 299c373c52SSuanming Mou } 309c373c52SSuanming Mou if (name) 319c373c52SSuanming Mou snprintf(list->name, sizeof(list->name), "%s", name); 329c373c52SSuanming Mou list->ctx = ctx; 33d03b7860SSuanming Mou list->lcores_share = lcores_share; 349c373c52SSuanming Mou list->cb_create = cb_create; 359c373c52SSuanming Mou list->cb_match = cb_match; 369c373c52SSuanming Mou list->cb_remove = cb_remove; 379c373c52SSuanming Mou list->cb_clone = cb_clone; 389c373c52SSuanming Mou list->cb_clone_free = cb_clone_free; 399c373c52SSuanming Mou rte_rwlock_init(&list->lock); 40*25481e50SSuanming Mou if (lcores_share) { 41*25481e50SSuanming Mou list->cache[RTE_MAX_LCORE] = gc; 42*25481e50SSuanming Mou LIST_INIT(&list->cache[RTE_MAX_LCORE]->h); 43*25481e50SSuanming Mou } 449c373c52SSuanming Mou DRV_LOG(DEBUG, "mlx5 list %s initialized.", list->name); 45961b6774SMatan Azrad return 0; 46961b6774SMatan Azrad } 47961b6774SMatan Azrad 48961b6774SMatan Azrad struct mlx5_list * 49961b6774SMatan Azrad mlx5_list_create(const char *name, void *ctx, bool lcores_share, 50961b6774SMatan Azrad mlx5_list_create_cb cb_create, 51961b6774SMatan Azrad mlx5_list_match_cb cb_match, 52961b6774SMatan Azrad mlx5_list_remove_cb cb_remove, 53961b6774SMatan Azrad mlx5_list_clone_cb cb_clone, 54961b6774SMatan Azrad mlx5_list_clone_free_cb cb_clone_free) 55961b6774SMatan Azrad { 56961b6774SMatan Azrad struct mlx5_list *list; 57*25481e50SSuanming Mou struct mlx5_list_cache *gc = NULL; 58961b6774SMatan Azrad 59*25481e50SSuanming Mou list = mlx5_malloc(MLX5_MEM_ZERO, 60*25481e50SSuanming Mou sizeof(*list) + (lcores_share ? sizeof(*gc) : 0), 61*25481e50SSuanming Mou 0, SOCKET_ID_ANY); 62961b6774SMatan Azrad if (!list) 63961b6774SMatan Azrad return NULL; 64*25481e50SSuanming Mou if (lcores_share) 65*25481e50SSuanming Mou gc = (struct mlx5_list_cache *)(list + 1); 66*25481e50SSuanming Mou if (mlx5_list_init(list, name, ctx, lcores_share, gc, 67961b6774SMatan Azrad cb_create, cb_match, cb_remove, cb_clone, 68961b6774SMatan Azrad cb_clone_free) != 0) { 69961b6774SMatan Azrad mlx5_free(list); 70961b6774SMatan Azrad return NULL; 71961b6774SMatan Azrad } 729c373c52SSuanming Mou return list; 739c373c52SSuanming Mou } 749c373c52SSuanming Mou 759c373c52SSuanming Mou static struct mlx5_list_entry * 769c373c52SSuanming Mou __list_lookup(struct mlx5_list *list, int lcore_index, void *ctx, bool reuse) 779c373c52SSuanming Mou { 78*25481e50SSuanming Mou struct mlx5_list_entry *entry = 79*25481e50SSuanming Mou LIST_FIRST(&list->cache[lcore_index]->h); 809c373c52SSuanming Mou uint32_t ret; 819c373c52SSuanming Mou 829c373c52SSuanming Mou while (entry != NULL) { 836507c9f5SSuanming Mou if (list->cb_match(list->ctx, entry, ctx) == 0) { 849c373c52SSuanming Mou if (reuse) { 859c373c52SSuanming Mou ret = __atomic_add_fetch(&entry->ref_cnt, 1, 869c373c52SSuanming Mou __ATOMIC_RELAXED) - 1; 879c373c52SSuanming Mou DRV_LOG(DEBUG, "mlx5 list %s entry %p ref: %u.", 889c373c52SSuanming Mou list->name, (void *)entry, 899c373c52SSuanming Mou entry->ref_cnt); 909c373c52SSuanming Mou } else if (lcore_index < RTE_MAX_LCORE) { 919c373c52SSuanming Mou ret = __atomic_load_n(&entry->ref_cnt, 929c373c52SSuanming Mou __ATOMIC_RELAXED); 939c373c52SSuanming Mou } 949c373c52SSuanming Mou if (likely(ret != 0 || lcore_index == RTE_MAX_LCORE)) 959c373c52SSuanming Mou return entry; 969c373c52SSuanming Mou if (reuse && ret == 0) 979c373c52SSuanming Mou entry->ref_cnt--; /* Invalid entry. */ 989c373c52SSuanming Mou } 999c373c52SSuanming Mou entry = LIST_NEXT(entry, next); 1009c373c52SSuanming Mou } 1019c373c52SSuanming Mou return NULL; 1029c373c52SSuanming Mou } 1039c373c52SSuanming Mou 1049c373c52SSuanming Mou struct mlx5_list_entry * 1059c373c52SSuanming Mou mlx5_list_lookup(struct mlx5_list *list, void *ctx) 1069c373c52SSuanming Mou { 1079c373c52SSuanming Mou struct mlx5_list_entry *entry = NULL; 1089c373c52SSuanming Mou int i; 1099c373c52SSuanming Mou 1109c373c52SSuanming Mou rte_rwlock_read_lock(&list->lock); 1119c373c52SSuanming Mou for (i = 0; i < RTE_MAX_LCORE; i++) { 1129c373c52SSuanming Mou entry = __list_lookup(list, i, ctx, false); 1139c373c52SSuanming Mou if (entry) 1149c373c52SSuanming Mou break; 1159c373c52SSuanming Mou } 1169c373c52SSuanming Mou rte_rwlock_read_unlock(&list->lock); 1179c373c52SSuanming Mou return entry; 1189c373c52SSuanming Mou } 1199c373c52SSuanming Mou 1209c373c52SSuanming Mou static struct mlx5_list_entry * 1219c373c52SSuanming Mou mlx5_list_cache_insert(struct mlx5_list *list, int lcore_index, 1229c373c52SSuanming Mou struct mlx5_list_entry *gentry, void *ctx) 1239c373c52SSuanming Mou { 1246507c9f5SSuanming Mou struct mlx5_list_entry *lentry = list->cb_clone(list->ctx, gentry, ctx); 1259c373c52SSuanming Mou 1269c373c52SSuanming Mou if (unlikely(!lentry)) 1279c373c52SSuanming Mou return NULL; 1289c373c52SSuanming Mou lentry->ref_cnt = 1u; 1299c373c52SSuanming Mou lentry->gentry = gentry; 1309c373c52SSuanming Mou lentry->lcore_idx = (uint32_t)lcore_index; 131*25481e50SSuanming Mou LIST_INSERT_HEAD(&list->cache[lcore_index]->h, lentry, next); 1329c373c52SSuanming Mou return lentry; 1339c373c52SSuanming Mou } 1349c373c52SSuanming Mou 1359c373c52SSuanming Mou static void 1369c373c52SSuanming Mou __list_cache_clean(struct mlx5_list *list, int lcore_index) 1379c373c52SSuanming Mou { 138*25481e50SSuanming Mou struct mlx5_list_cache *c = list->cache[lcore_index]; 1399c373c52SSuanming Mou struct mlx5_list_entry *entry = LIST_FIRST(&c->h); 1409c373c52SSuanming Mou uint32_t inv_cnt = __atomic_exchange_n(&c->inv_cnt, 0, 1419c373c52SSuanming Mou __ATOMIC_RELAXED); 1429c373c52SSuanming Mou 1439c373c52SSuanming Mou while (inv_cnt != 0 && entry != NULL) { 1449c373c52SSuanming Mou struct mlx5_list_entry *nentry = LIST_NEXT(entry, next); 1459c373c52SSuanming Mou 1469c373c52SSuanming Mou if (__atomic_load_n(&entry->ref_cnt, __ATOMIC_RELAXED) == 0) { 1479c373c52SSuanming Mou LIST_REMOVE(entry, next); 148d03b7860SSuanming Mou if (list->lcores_share) 1496507c9f5SSuanming Mou list->cb_clone_free(list->ctx, entry); 150d03b7860SSuanming Mou else 1516507c9f5SSuanming Mou list->cb_remove(list->ctx, entry); 1529c373c52SSuanming Mou inv_cnt--; 1539c373c52SSuanming Mou } 1549c373c52SSuanming Mou entry = nentry; 1559c373c52SSuanming Mou } 1569c373c52SSuanming Mou } 1579c373c52SSuanming Mou 1589c373c52SSuanming Mou struct mlx5_list_entry * 1599c373c52SSuanming Mou mlx5_list_register(struct mlx5_list *list, void *ctx) 1609c373c52SSuanming Mou { 161d03b7860SSuanming Mou struct mlx5_list_entry *entry = NULL, *local_entry; 1629c373c52SSuanming Mou volatile uint32_t prev_gen_cnt = 0; 1639c373c52SSuanming Mou int lcore_index = rte_lcore_index(rte_lcore_id()); 1649c373c52SSuanming Mou 1659c373c52SSuanming Mou MLX5_ASSERT(list); 1669c373c52SSuanming Mou MLX5_ASSERT(lcore_index < RTE_MAX_LCORE); 1679c373c52SSuanming Mou if (unlikely(lcore_index == -1)) { 1689c373c52SSuanming Mou rte_errno = ENOTSUP; 1699c373c52SSuanming Mou return NULL; 1709c373c52SSuanming Mou } 171*25481e50SSuanming Mou if (unlikely(!list->cache[lcore_index])) { 172*25481e50SSuanming Mou list->cache[lcore_index] = mlx5_malloc(0, 173*25481e50SSuanming Mou sizeof(struct mlx5_list_cache), 174*25481e50SSuanming Mou RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 175*25481e50SSuanming Mou if (!list->cache[lcore_index]) { 176*25481e50SSuanming Mou rte_errno = ENOMEM; 177*25481e50SSuanming Mou return NULL; 178*25481e50SSuanming Mou } 179*25481e50SSuanming Mou list->cache[lcore_index]->inv_cnt = 0; 180*25481e50SSuanming Mou LIST_INIT(&list->cache[lcore_index]->h); 181*25481e50SSuanming Mou } 1829c373c52SSuanming Mou /* 0. Free entries that was invalidated by other lcores. */ 1839c373c52SSuanming Mou __list_cache_clean(list, lcore_index); 1849c373c52SSuanming Mou /* 1. Lookup in local cache. */ 1859c373c52SSuanming Mou local_entry = __list_lookup(list, lcore_index, ctx, true); 1869c373c52SSuanming Mou if (local_entry) 1879c373c52SSuanming Mou return local_entry; 188d03b7860SSuanming Mou if (list->lcores_share) { 1899c373c52SSuanming Mou /* 2. Lookup with read lock on global list, reuse if found. */ 1909c373c52SSuanming Mou rte_rwlock_read_lock(&list->lock); 1919c373c52SSuanming Mou entry = __list_lookup(list, RTE_MAX_LCORE, ctx, true); 1929c373c52SSuanming Mou if (likely(entry)) { 1939c373c52SSuanming Mou rte_rwlock_read_unlock(&list->lock); 194d03b7860SSuanming Mou return mlx5_list_cache_insert(list, lcore_index, entry, 195d03b7860SSuanming Mou ctx); 1969c373c52SSuanming Mou } 1979c373c52SSuanming Mou prev_gen_cnt = list->gen_cnt; 1989c373c52SSuanming Mou rte_rwlock_read_unlock(&list->lock); 199d03b7860SSuanming Mou } 2009c373c52SSuanming Mou /* 3. Prepare new entry for global list and for cache. */ 2016507c9f5SSuanming Mou entry = list->cb_create(list->ctx, ctx); 2029c373c52SSuanming Mou if (unlikely(!entry)) 2039c373c52SSuanming Mou return NULL; 204d03b7860SSuanming Mou entry->ref_cnt = 1u; 205d03b7860SSuanming Mou if (!list->lcores_share) { 206d03b7860SSuanming Mou entry->lcore_idx = (uint32_t)lcore_index; 207*25481e50SSuanming Mou LIST_INSERT_HEAD(&list->cache[lcore_index]->h, entry, next); 208d03b7860SSuanming Mou __atomic_add_fetch(&list->count, 1, __ATOMIC_RELAXED); 209d03b7860SSuanming Mou DRV_LOG(DEBUG, "MLX5 list %s c%d entry %p new: %u.", 210d03b7860SSuanming Mou list->name, lcore_index, (void *)entry, entry->ref_cnt); 211d03b7860SSuanming Mou return entry; 212d03b7860SSuanming Mou } 2136507c9f5SSuanming Mou local_entry = list->cb_clone(list->ctx, entry, ctx); 2149c373c52SSuanming Mou if (unlikely(!local_entry)) { 2156507c9f5SSuanming Mou list->cb_remove(list->ctx, entry); 2169c373c52SSuanming Mou return NULL; 2179c373c52SSuanming Mou } 2189c373c52SSuanming Mou local_entry->ref_cnt = 1u; 2199c373c52SSuanming Mou local_entry->gentry = entry; 2209c373c52SSuanming Mou local_entry->lcore_idx = (uint32_t)lcore_index; 2219c373c52SSuanming Mou rte_rwlock_write_lock(&list->lock); 2229c373c52SSuanming Mou /* 4. Make sure the same entry was not created before the write lock. */ 2239c373c52SSuanming Mou if (unlikely(prev_gen_cnt != list->gen_cnt)) { 2249c373c52SSuanming Mou struct mlx5_list_entry *oentry = __list_lookup(list, 2259c373c52SSuanming Mou RTE_MAX_LCORE, 2269c373c52SSuanming Mou ctx, true); 2279c373c52SSuanming Mou 2289c373c52SSuanming Mou if (unlikely(oentry)) { 2299c373c52SSuanming Mou /* 4.5. Found real race!!, reuse the old entry. */ 2309c373c52SSuanming Mou rte_rwlock_write_unlock(&list->lock); 2316507c9f5SSuanming Mou list->cb_remove(list->ctx, entry); 2326507c9f5SSuanming Mou list->cb_clone_free(list->ctx, local_entry); 2339c373c52SSuanming Mou return mlx5_list_cache_insert(list, lcore_index, oentry, 2349c373c52SSuanming Mou ctx); 2359c373c52SSuanming Mou } 2369c373c52SSuanming Mou } 2379c373c52SSuanming Mou /* 5. Update lists. */ 238*25481e50SSuanming Mou LIST_INSERT_HEAD(&list->cache[RTE_MAX_LCORE]->h, entry, next); 2399c373c52SSuanming Mou list->gen_cnt++; 2409c373c52SSuanming Mou rte_rwlock_write_unlock(&list->lock); 241*25481e50SSuanming Mou LIST_INSERT_HEAD(&list->cache[lcore_index]->h, local_entry, next); 2429c373c52SSuanming Mou __atomic_add_fetch(&list->count, 1, __ATOMIC_RELAXED); 2439c373c52SSuanming Mou DRV_LOG(DEBUG, "mlx5 list %s entry %p new: %u.", list->name, 2449c373c52SSuanming Mou (void *)entry, entry->ref_cnt); 2459c373c52SSuanming Mou return local_entry; 2469c373c52SSuanming Mou } 2479c373c52SSuanming Mou 2489c373c52SSuanming Mou int 2499c373c52SSuanming Mou mlx5_list_unregister(struct mlx5_list *list, 2509c373c52SSuanming Mou struct mlx5_list_entry *entry) 2519c373c52SSuanming Mou { 2529c373c52SSuanming Mou struct mlx5_list_entry *gentry = entry->gentry; 2539c373c52SSuanming Mou int lcore_idx; 2549c373c52SSuanming Mou 2559c373c52SSuanming Mou if (__atomic_sub_fetch(&entry->ref_cnt, 1, __ATOMIC_RELAXED) != 0) 2569c373c52SSuanming Mou return 1; 2579c373c52SSuanming Mou lcore_idx = rte_lcore_index(rte_lcore_id()); 2589c373c52SSuanming Mou MLX5_ASSERT(lcore_idx < RTE_MAX_LCORE); 2599c373c52SSuanming Mou if (entry->lcore_idx == (uint32_t)lcore_idx) { 2609c373c52SSuanming Mou LIST_REMOVE(entry, next); 261d03b7860SSuanming Mou if (list->lcores_share) 2626507c9f5SSuanming Mou list->cb_clone_free(list->ctx, entry); 263d03b7860SSuanming Mou else 2646507c9f5SSuanming Mou list->cb_remove(list->ctx, entry); 2659c373c52SSuanming Mou } else if (likely(lcore_idx != -1)) { 266*25481e50SSuanming Mou __atomic_add_fetch(&list->cache[entry->lcore_idx]->inv_cnt, 1, 2679c373c52SSuanming Mou __ATOMIC_RELAXED); 2689c373c52SSuanming Mou } else { 2699c373c52SSuanming Mou return 0; 2709c373c52SSuanming Mou } 271d03b7860SSuanming Mou if (!list->lcores_share) { 272d03b7860SSuanming Mou __atomic_sub_fetch(&list->count, 1, __ATOMIC_RELAXED); 273d03b7860SSuanming Mou DRV_LOG(DEBUG, "mlx5 list %s entry %p removed.", 274d03b7860SSuanming Mou list->name, (void *)entry); 275d03b7860SSuanming Mou return 0; 276d03b7860SSuanming Mou } 2779c373c52SSuanming Mou if (__atomic_sub_fetch(&gentry->ref_cnt, 1, __ATOMIC_RELAXED) != 0) 2789c373c52SSuanming Mou return 1; 2799c373c52SSuanming Mou rte_rwlock_write_lock(&list->lock); 2809c373c52SSuanming Mou if (likely(gentry->ref_cnt == 0)) { 2819c373c52SSuanming Mou LIST_REMOVE(gentry, next); 2829c373c52SSuanming Mou rte_rwlock_write_unlock(&list->lock); 2836507c9f5SSuanming Mou list->cb_remove(list->ctx, gentry); 2849c373c52SSuanming Mou __atomic_sub_fetch(&list->count, 1, __ATOMIC_RELAXED); 2859c373c52SSuanming Mou DRV_LOG(DEBUG, "mlx5 list %s entry %p removed.", 2869c373c52SSuanming Mou list->name, (void *)gentry); 2879c373c52SSuanming Mou return 0; 2889c373c52SSuanming Mou } 2899c373c52SSuanming Mou rte_rwlock_write_unlock(&list->lock); 2909c373c52SSuanming Mou return 1; 2919c373c52SSuanming Mou } 2929c373c52SSuanming Mou 293961b6774SMatan Azrad static void 294961b6774SMatan Azrad mlx5_list_uninit(struct mlx5_list *list) 2959c373c52SSuanming Mou { 2969c373c52SSuanming Mou struct mlx5_list_entry *entry; 2979c373c52SSuanming Mou int i; 2989c373c52SSuanming Mou 2999c373c52SSuanming Mou MLX5_ASSERT(list); 3009c373c52SSuanming Mou for (i = 0; i <= RTE_MAX_LCORE; i++) { 301*25481e50SSuanming Mou if (!list->cache[i]) 302*25481e50SSuanming Mou continue; 303*25481e50SSuanming Mou while (!LIST_EMPTY(&list->cache[i]->h)) { 304*25481e50SSuanming Mou entry = LIST_FIRST(&list->cache[i]->h); 3059c373c52SSuanming Mou LIST_REMOVE(entry, next); 3069c373c52SSuanming Mou if (i == RTE_MAX_LCORE) { 307961b6774SMatan Azrad list->cb_remove(list->ctx, entry); 3089c373c52SSuanming Mou DRV_LOG(DEBUG, "mlx5 list %s entry %p " 3099c373c52SSuanming Mou "destroyed.", list->name, 3109c373c52SSuanming Mou (void *)entry); 3119c373c52SSuanming Mou } else { 312961b6774SMatan Azrad list->cb_clone_free(list->ctx, entry); 3139c373c52SSuanming Mou } 3149c373c52SSuanming Mou } 315*25481e50SSuanming Mou if (i != RTE_MAX_LCORE) 316*25481e50SSuanming Mou mlx5_free(list->cache[i]); 3179c373c52SSuanming Mou } 318961b6774SMatan Azrad } 319961b6774SMatan Azrad 320961b6774SMatan Azrad void 321961b6774SMatan Azrad mlx5_list_destroy(struct mlx5_list *list) 322961b6774SMatan Azrad { 323961b6774SMatan Azrad mlx5_list_uninit(list); 3249c373c52SSuanming Mou mlx5_free(list); 3259c373c52SSuanming Mou } 3269c373c52SSuanming Mou 3279c373c52SSuanming Mou uint32_t 3289c373c52SSuanming Mou mlx5_list_get_entry_num(struct mlx5_list *list) 3299c373c52SSuanming Mou { 3309c373c52SSuanming Mou MLX5_ASSERT(list); 3319c373c52SSuanming Mou return __atomic_load_n(&list->count, __ATOMIC_RELAXED); 3329c373c52SSuanming Mou } 3339c373c52SSuanming Mou 33425245d5dSShiri Kuzin /********************* Hash List **********************/ 33525245d5dSShiri Kuzin 33625245d5dSShiri Kuzin struct mlx5_hlist * 337961b6774SMatan Azrad mlx5_hlist_create(const char *name, uint32_t size, bool direct_key, 338961b6774SMatan Azrad bool lcores_share, void *ctx, mlx5_list_create_cb cb_create, 339961b6774SMatan Azrad mlx5_list_match_cb cb_match, 340961b6774SMatan Azrad mlx5_list_remove_cb cb_remove, 341961b6774SMatan Azrad mlx5_list_clone_cb cb_clone, 342961b6774SMatan Azrad mlx5_list_clone_free_cb cb_clone_free) 34325245d5dSShiri Kuzin { 34425245d5dSShiri Kuzin struct mlx5_hlist *h; 345*25481e50SSuanming Mou struct mlx5_list_cache *gc; 34625245d5dSShiri Kuzin uint32_t act_size; 34725245d5dSShiri Kuzin uint32_t alloc_size; 34825245d5dSShiri Kuzin uint32_t i; 34925245d5dSShiri Kuzin 35025245d5dSShiri Kuzin /* Align to the next power of 2, 32bits integer is enough now. */ 35125245d5dSShiri Kuzin if (!rte_is_power_of_2(size)) { 35225245d5dSShiri Kuzin act_size = rte_align32pow2(size); 353961b6774SMatan Azrad DRV_LOG(WARNING, "Size 0x%" PRIX32 " is not power of 2, will " 354961b6774SMatan Azrad "be aligned to 0x%" PRIX32 ".", size, act_size); 35525245d5dSShiri Kuzin } else { 35625245d5dSShiri Kuzin act_size = size; 35725245d5dSShiri Kuzin } 35825245d5dSShiri Kuzin alloc_size = sizeof(struct mlx5_hlist) + 35925245d5dSShiri Kuzin sizeof(struct mlx5_hlist_bucket) * act_size; 360*25481e50SSuanming Mou if (lcores_share) 361*25481e50SSuanming Mou alloc_size += sizeof(struct mlx5_list_cache) * act_size; 36225245d5dSShiri Kuzin /* Using zmalloc, then no need to initialize the heads. */ 36325245d5dSShiri Kuzin h = mlx5_malloc(MLX5_MEM_ZERO, alloc_size, RTE_CACHE_LINE_SIZE, 36425245d5dSShiri Kuzin SOCKET_ID_ANY); 36525245d5dSShiri Kuzin if (!h) { 36625245d5dSShiri Kuzin DRV_LOG(ERR, "No memory for hash list %s creation", 36725245d5dSShiri Kuzin name ? name : "None"); 36825245d5dSShiri Kuzin return NULL; 36925245d5dSShiri Kuzin } 37025245d5dSShiri Kuzin h->mask = act_size - 1; 371961b6774SMatan Azrad h->lcores_share = lcores_share; 372961b6774SMatan Azrad h->direct_key = direct_key; 373*25481e50SSuanming Mou gc = (struct mlx5_list_cache *)&h->buckets[act_size]; 374961b6774SMatan Azrad for (i = 0; i < act_size; i++) { 375961b6774SMatan Azrad if (mlx5_list_init(&h->buckets[i].l, name, ctx, lcores_share, 376*25481e50SSuanming Mou lcores_share ? &gc[i] : NULL, 377961b6774SMatan Azrad cb_create, cb_match, cb_remove, cb_clone, 378961b6774SMatan Azrad cb_clone_free) != 0) { 379961b6774SMatan Azrad mlx5_free(h); 380961b6774SMatan Azrad return NULL; 381961b6774SMatan Azrad } 382961b6774SMatan Azrad } 383961b6774SMatan Azrad DRV_LOG(DEBUG, "Hash list %s with size 0x%" PRIX32 " was created.", 384961b6774SMatan Azrad name, act_size); 38525245d5dSShiri Kuzin return h; 38625245d5dSShiri Kuzin } 38725245d5dSShiri Kuzin 388961b6774SMatan Azrad struct mlx5_list_entry * 38925245d5dSShiri Kuzin mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key, void *ctx) 39025245d5dSShiri Kuzin { 39125245d5dSShiri Kuzin uint32_t idx; 39225245d5dSShiri Kuzin 39325245d5dSShiri Kuzin if (h->direct_key) 39425245d5dSShiri Kuzin idx = (uint32_t)(key & h->mask); 39525245d5dSShiri Kuzin else 39625245d5dSShiri Kuzin idx = rte_hash_crc_8byte(key, 0) & h->mask; 397961b6774SMatan Azrad return mlx5_list_lookup(&h->buckets[idx].l, ctx); 39825245d5dSShiri Kuzin } 39925245d5dSShiri Kuzin 400961b6774SMatan Azrad struct mlx5_list_entry* 40125245d5dSShiri Kuzin mlx5_hlist_register(struct mlx5_hlist *h, uint64_t key, void *ctx) 40225245d5dSShiri Kuzin { 40325245d5dSShiri Kuzin uint32_t idx; 404961b6774SMatan Azrad struct mlx5_list_entry *entry; 40525245d5dSShiri Kuzin 40625245d5dSShiri Kuzin if (h->direct_key) 40725245d5dSShiri Kuzin idx = (uint32_t)(key & h->mask); 40825245d5dSShiri Kuzin else 40925245d5dSShiri Kuzin idx = rte_hash_crc_8byte(key, 0) & h->mask; 410961b6774SMatan Azrad entry = mlx5_list_register(&h->buckets[idx].l, ctx); 411961b6774SMatan Azrad if (likely(entry)) { 412961b6774SMatan Azrad if (h->lcores_share) 413961b6774SMatan Azrad entry->gentry->bucket_idx = idx; 414961b6774SMatan Azrad else 415961b6774SMatan Azrad entry->bucket_idx = idx; 41625245d5dSShiri Kuzin } 41725245d5dSShiri Kuzin return entry; 41825245d5dSShiri Kuzin } 41925245d5dSShiri Kuzin 42025245d5dSShiri Kuzin int 421961b6774SMatan Azrad mlx5_hlist_unregister(struct mlx5_hlist *h, struct mlx5_list_entry *entry) 42225245d5dSShiri Kuzin { 423961b6774SMatan Azrad uint32_t idx = h->lcores_share ? entry->gentry->bucket_idx : 424961b6774SMatan Azrad entry->bucket_idx; 42525245d5dSShiri Kuzin 426961b6774SMatan Azrad return mlx5_list_unregister(&h->buckets[idx].l, entry); 42725245d5dSShiri Kuzin } 42825245d5dSShiri Kuzin 42925245d5dSShiri Kuzin void 43025245d5dSShiri Kuzin mlx5_hlist_destroy(struct mlx5_hlist *h) 43125245d5dSShiri Kuzin { 432961b6774SMatan Azrad uint32_t i; 43325245d5dSShiri Kuzin 434961b6774SMatan Azrad for (i = 0; i <= h->mask; i++) 435961b6774SMatan Azrad mlx5_list_uninit(&h->buckets[i].l); 43625245d5dSShiri Kuzin mlx5_free(h); 43725245d5dSShiri Kuzin } 438