1*46287eacSBing Zhao /* SPDX-License-Identifier: BSD-3-Clause 2*46287eacSBing Zhao * Copyright 2019 Mellanox Technologies, Ltd 3*46287eacSBing Zhao */ 4*46287eacSBing Zhao 5*46287eacSBing Zhao #include <rte_malloc.h> 6*46287eacSBing Zhao #include <rte_hash_crc.h> 7*46287eacSBing Zhao 8*46287eacSBing Zhao #include "mlx5_utils.h" 9*46287eacSBing Zhao 10*46287eacSBing Zhao struct mlx5_hlist * 11*46287eacSBing Zhao mlx5_hlist_create(const char *name, uint32_t size) 12*46287eacSBing Zhao { 13*46287eacSBing Zhao struct mlx5_hlist *h; 14*46287eacSBing Zhao uint32_t act_size; 15*46287eacSBing Zhao uint32_t alloc_size; 16*46287eacSBing Zhao 17*46287eacSBing Zhao if (!size) 18*46287eacSBing Zhao return NULL; 19*46287eacSBing Zhao /* Align to the next power of 2, 32bits integer is enough now. */ 20*46287eacSBing Zhao if (!rte_is_power_of_2(size)) { 21*46287eacSBing Zhao act_size = rte_align32pow2(size); 22*46287eacSBing Zhao DRV_LOG(WARNING, "Size 0x%" PRIX32 " is not power of 2, will " 23*46287eacSBing Zhao "be aligned to 0x%" PRIX32 ".\n", size, act_size); 24*46287eacSBing Zhao } else { 25*46287eacSBing Zhao act_size = size; 26*46287eacSBing Zhao } 27*46287eacSBing Zhao alloc_size = sizeof(struct mlx5_hlist) + 28*46287eacSBing Zhao sizeof(struct mlx5_hlist_head) * act_size; 29*46287eacSBing Zhao /* Using zmalloc, then no need to initialize the heads. */ 30*46287eacSBing Zhao h = rte_zmalloc(name, alloc_size, RTE_CACHE_LINE_SIZE); 31*46287eacSBing Zhao if (!h) { 32*46287eacSBing Zhao DRV_LOG(ERR, "No memory for hash list %s creation\n", 33*46287eacSBing Zhao name ? name : "None"); 34*46287eacSBing Zhao return NULL; 35*46287eacSBing Zhao } 36*46287eacSBing Zhao if (name) 37*46287eacSBing Zhao snprintf(h->name, MLX5_HLIST_NAMESIZE, "%s", name); 38*46287eacSBing Zhao h->table_sz = act_size; 39*46287eacSBing Zhao h->mask = act_size - 1; 40*46287eacSBing Zhao DRV_LOG(DEBUG, "Hash list with %s size 0x%" PRIX32 " is created.\n", 41*46287eacSBing Zhao h->name, act_size); 42*46287eacSBing Zhao return h; 43*46287eacSBing Zhao } 44*46287eacSBing Zhao 45*46287eacSBing Zhao struct mlx5_hlist_entry * 46*46287eacSBing Zhao mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key) 47*46287eacSBing Zhao { 48*46287eacSBing Zhao uint32_t idx; 49*46287eacSBing Zhao struct mlx5_hlist_head *first; 50*46287eacSBing Zhao struct mlx5_hlist_entry *node; 51*46287eacSBing Zhao 52*46287eacSBing Zhao assert(h); 53*46287eacSBing Zhao idx = rte_hash_crc_8byte(key, 0) & h->mask; 54*46287eacSBing Zhao first = &h->heads[idx]; 55*46287eacSBing Zhao LIST_FOREACH(node, first, next) { 56*46287eacSBing Zhao if (node->key == key) 57*46287eacSBing Zhao return node; 58*46287eacSBing Zhao } 59*46287eacSBing Zhao return NULL; 60*46287eacSBing Zhao } 61*46287eacSBing Zhao 62*46287eacSBing Zhao int 63*46287eacSBing Zhao mlx5_hlist_insert(struct mlx5_hlist *h, struct mlx5_hlist_entry *entry) 64*46287eacSBing Zhao { 65*46287eacSBing Zhao uint32_t idx; 66*46287eacSBing Zhao struct mlx5_hlist_head *first; 67*46287eacSBing Zhao struct mlx5_hlist_entry *node; 68*46287eacSBing Zhao 69*46287eacSBing Zhao assert(h && entry); 70*46287eacSBing Zhao idx = rte_hash_crc_8byte(entry->key, 0) & h->mask; 71*46287eacSBing Zhao first = &h->heads[idx]; 72*46287eacSBing Zhao /* No need to reuse the lookup function. */ 73*46287eacSBing Zhao LIST_FOREACH(node, first, next) { 74*46287eacSBing Zhao if (node->key == entry->key) 75*46287eacSBing Zhao return -EEXIST; 76*46287eacSBing Zhao } 77*46287eacSBing Zhao LIST_INSERT_HEAD(first, entry, next); 78*46287eacSBing Zhao return 0; 79*46287eacSBing Zhao } 80*46287eacSBing Zhao 81*46287eacSBing Zhao void 82*46287eacSBing Zhao mlx5_hlist_remove(struct mlx5_hlist *h __rte_unused, 83*46287eacSBing Zhao struct mlx5_hlist_entry *entry) 84*46287eacSBing Zhao { 85*46287eacSBing Zhao assert(entry && entry->next.le_prev); 86*46287eacSBing Zhao LIST_REMOVE(entry, next); 87*46287eacSBing Zhao /* Set to NULL to get rid of removing action for more than once. */ 88*46287eacSBing Zhao entry->next.le_prev = NULL; 89*46287eacSBing Zhao } 90*46287eacSBing Zhao 91*46287eacSBing Zhao void 92*46287eacSBing Zhao mlx5_hlist_destroy(struct mlx5_hlist *h, 93*46287eacSBing Zhao mlx5_hlist_destroy_callback_fn cb, void *ctx) 94*46287eacSBing Zhao { 95*46287eacSBing Zhao uint32_t idx; 96*46287eacSBing Zhao struct mlx5_hlist_entry *entry; 97*46287eacSBing Zhao 98*46287eacSBing Zhao assert(h); 99*46287eacSBing Zhao for (idx = 0; idx < h->table_sz; ++idx) { 100*46287eacSBing Zhao /* no LIST_FOREACH_SAFE, using while instead */ 101*46287eacSBing Zhao while (!LIST_EMPTY(&h->heads[idx])) { 102*46287eacSBing Zhao entry = LIST_FIRST(&h->heads[idx]); 103*46287eacSBing Zhao LIST_REMOVE(entry, next); 104*46287eacSBing Zhao /* 105*46287eacSBing Zhao * The owner of whole element which contains data entry 106*46287eacSBing Zhao * is the user, so it's the user's duty to do the clean 107*46287eacSBing Zhao * up and the free work because someone may not put the 108*46287eacSBing Zhao * hlist entry at the beginning(suggested to locate at 109*46287eacSBing Zhao * the beginning). Or else the default free function 110*46287eacSBing Zhao * will be used. 111*46287eacSBing Zhao */ 112*46287eacSBing Zhao if (cb) 113*46287eacSBing Zhao cb(entry, ctx); 114*46287eacSBing Zhao else 115*46287eacSBing Zhao rte_free(entry); 116*46287eacSBing Zhao } 117*46287eacSBing Zhao } 118*46287eacSBing Zhao rte_free(h); 119*46287eacSBing Zhao } 120