146287eacSBing Zhao /* SPDX-License-Identifier: BSD-3-Clause 246287eacSBing Zhao * Copyright 2019 Mellanox Technologies, Ltd 346287eacSBing Zhao */ 446287eacSBing Zhao 546287eacSBing Zhao #include <rte_malloc.h> 646287eacSBing Zhao #include <rte_hash_crc.h> 746287eacSBing Zhao 846287eacSBing Zhao #include "mlx5_utils.h" 946287eacSBing Zhao 1046287eacSBing Zhao struct mlx5_hlist * 1146287eacSBing Zhao mlx5_hlist_create(const char *name, uint32_t size) 1246287eacSBing Zhao { 1346287eacSBing Zhao struct mlx5_hlist *h; 1446287eacSBing Zhao uint32_t act_size; 1546287eacSBing Zhao uint32_t alloc_size; 1646287eacSBing Zhao 1746287eacSBing Zhao if (!size) 1846287eacSBing Zhao return NULL; 1946287eacSBing Zhao /* Align to the next power of 2, 32bits integer is enough now. */ 2046287eacSBing Zhao if (!rte_is_power_of_2(size)) { 2146287eacSBing Zhao act_size = rte_align32pow2(size); 2246287eacSBing Zhao DRV_LOG(WARNING, "Size 0x%" PRIX32 " is not power of 2, will " 2346287eacSBing Zhao "be aligned to 0x%" PRIX32 ".\n", size, act_size); 2446287eacSBing Zhao } else { 2546287eacSBing Zhao act_size = size; 2646287eacSBing Zhao } 2746287eacSBing Zhao alloc_size = sizeof(struct mlx5_hlist) + 2846287eacSBing Zhao sizeof(struct mlx5_hlist_head) * act_size; 2946287eacSBing Zhao /* Using zmalloc, then no need to initialize the heads. */ 3046287eacSBing Zhao h = rte_zmalloc(name, alloc_size, RTE_CACHE_LINE_SIZE); 3146287eacSBing Zhao if (!h) { 3246287eacSBing Zhao DRV_LOG(ERR, "No memory for hash list %s creation\n", 3346287eacSBing Zhao name ? name : "None"); 3446287eacSBing Zhao return NULL; 3546287eacSBing Zhao } 3646287eacSBing Zhao if (name) 3746287eacSBing Zhao snprintf(h->name, MLX5_HLIST_NAMESIZE, "%s", name); 3846287eacSBing Zhao h->table_sz = act_size; 3946287eacSBing Zhao h->mask = act_size - 1; 4046287eacSBing Zhao DRV_LOG(DEBUG, "Hash list with %s size 0x%" PRIX32 " is created.\n", 4146287eacSBing Zhao h->name, act_size); 4246287eacSBing Zhao return h; 4346287eacSBing Zhao } 4446287eacSBing Zhao 4546287eacSBing Zhao struct mlx5_hlist_entry * 4646287eacSBing Zhao mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key) 4746287eacSBing Zhao { 4846287eacSBing Zhao uint32_t idx; 4946287eacSBing Zhao struct mlx5_hlist_head *first; 5046287eacSBing Zhao struct mlx5_hlist_entry *node; 5146287eacSBing Zhao 528e46d4e1SAlexander Kozyrev MLX5_ASSERT(h); 5346287eacSBing Zhao idx = rte_hash_crc_8byte(key, 0) & h->mask; 5446287eacSBing Zhao first = &h->heads[idx]; 5546287eacSBing Zhao LIST_FOREACH(node, first, next) { 5646287eacSBing Zhao if (node->key == key) 5746287eacSBing Zhao return node; 5846287eacSBing Zhao } 5946287eacSBing Zhao return NULL; 6046287eacSBing Zhao } 6146287eacSBing Zhao 6246287eacSBing Zhao int 6346287eacSBing Zhao mlx5_hlist_insert(struct mlx5_hlist *h, struct mlx5_hlist_entry *entry) 6446287eacSBing Zhao { 6546287eacSBing Zhao uint32_t idx; 6646287eacSBing Zhao struct mlx5_hlist_head *first; 6746287eacSBing Zhao struct mlx5_hlist_entry *node; 6846287eacSBing Zhao 698e46d4e1SAlexander Kozyrev MLX5_ASSERT(h && entry); 7046287eacSBing Zhao idx = rte_hash_crc_8byte(entry->key, 0) & h->mask; 7146287eacSBing Zhao first = &h->heads[idx]; 7246287eacSBing Zhao /* No need to reuse the lookup function. */ 7346287eacSBing Zhao LIST_FOREACH(node, first, next) { 7446287eacSBing Zhao if (node->key == entry->key) 7546287eacSBing Zhao return -EEXIST; 7646287eacSBing Zhao } 7746287eacSBing Zhao LIST_INSERT_HEAD(first, entry, next); 7846287eacSBing Zhao return 0; 7946287eacSBing Zhao } 8046287eacSBing Zhao 8146287eacSBing Zhao void 8246287eacSBing Zhao mlx5_hlist_remove(struct mlx5_hlist *h __rte_unused, 8346287eacSBing Zhao struct mlx5_hlist_entry *entry) 8446287eacSBing Zhao { 858e46d4e1SAlexander Kozyrev MLX5_ASSERT(entry && entry->next.le_prev); 8646287eacSBing Zhao LIST_REMOVE(entry, next); 8746287eacSBing Zhao /* Set to NULL to get rid of removing action for more than once. */ 8846287eacSBing Zhao entry->next.le_prev = NULL; 8946287eacSBing Zhao } 9046287eacSBing Zhao 9146287eacSBing Zhao void 9246287eacSBing Zhao mlx5_hlist_destroy(struct mlx5_hlist *h, 9346287eacSBing Zhao mlx5_hlist_destroy_callback_fn cb, void *ctx) 9446287eacSBing Zhao { 9546287eacSBing Zhao uint32_t idx; 9646287eacSBing Zhao struct mlx5_hlist_entry *entry; 9746287eacSBing Zhao 988e46d4e1SAlexander Kozyrev MLX5_ASSERT(h); 9946287eacSBing Zhao for (idx = 0; idx < h->table_sz; ++idx) { 10046287eacSBing Zhao /* no LIST_FOREACH_SAFE, using while instead */ 10146287eacSBing Zhao while (!LIST_EMPTY(&h->heads[idx])) { 10246287eacSBing Zhao entry = LIST_FIRST(&h->heads[idx]); 10346287eacSBing Zhao LIST_REMOVE(entry, next); 10446287eacSBing Zhao /* 10546287eacSBing Zhao * The owner of whole element which contains data entry 10646287eacSBing Zhao * is the user, so it's the user's duty to do the clean 10746287eacSBing Zhao * up and the free work because someone may not put the 10846287eacSBing Zhao * hlist entry at the beginning(suggested to locate at 10946287eacSBing Zhao * the beginning). Or else the default free function 11046287eacSBing Zhao * will be used. 11146287eacSBing Zhao */ 11246287eacSBing Zhao if (cb) 11346287eacSBing Zhao cb(entry, ctx); 11446287eacSBing Zhao else 11546287eacSBing Zhao rte_free(entry); 11646287eacSBing Zhao } 11746287eacSBing Zhao } 11846287eacSBing Zhao rte_free(h); 11946287eacSBing Zhao } 120a3cf59f5SSuanming Mou 121a3cf59f5SSuanming Mou static inline void 122a3cf59f5SSuanming Mou mlx5_ipool_lock(struct mlx5_indexed_pool *pool) 123a3cf59f5SSuanming Mou { 124a3cf59f5SSuanming Mou if (pool->cfg.need_lock) 125a3cf59f5SSuanming Mou rte_spinlock_lock(&pool->lock); 126a3cf59f5SSuanming Mou } 127a3cf59f5SSuanming Mou 128a3cf59f5SSuanming Mou static inline void 129a3cf59f5SSuanming Mou mlx5_ipool_unlock(struct mlx5_indexed_pool *pool) 130a3cf59f5SSuanming Mou { 131a3cf59f5SSuanming Mou if (pool->cfg.need_lock) 132a3cf59f5SSuanming Mou rte_spinlock_unlock(&pool->lock); 133a3cf59f5SSuanming Mou } 134a3cf59f5SSuanming Mou 13562d7d519SSuanming Mou static inline uint32_t 13662d7d519SSuanming Mou mlx5_trunk_idx_get(struct mlx5_indexed_pool *pool, uint32_t entry_idx) 13762d7d519SSuanming Mou { 13862d7d519SSuanming Mou struct mlx5_indexed_pool_config *cfg = &pool->cfg; 13962d7d519SSuanming Mou uint32_t trunk_idx = 0; 14062d7d519SSuanming Mou uint32_t i; 14162d7d519SSuanming Mou 14262d7d519SSuanming Mou if (!cfg->grow_trunk) 14362d7d519SSuanming Mou return entry_idx / cfg->trunk_size; 14462d7d519SSuanming Mou if (entry_idx >= pool->grow_tbl[cfg->grow_trunk - 1]) { 14562d7d519SSuanming Mou trunk_idx = (entry_idx - pool->grow_tbl[cfg->grow_trunk - 1]) / 14662d7d519SSuanming Mou (cfg->trunk_size << (cfg->grow_shift * 14762d7d519SSuanming Mou cfg->grow_trunk)) + cfg->grow_trunk; 14862d7d519SSuanming Mou } else { 14962d7d519SSuanming Mou for (i = 0; i < cfg->grow_trunk; i++) { 15062d7d519SSuanming Mou if (entry_idx < pool->grow_tbl[i]) 15162d7d519SSuanming Mou break; 15262d7d519SSuanming Mou } 15362d7d519SSuanming Mou trunk_idx = i; 15462d7d519SSuanming Mou } 15562d7d519SSuanming Mou return trunk_idx; 15662d7d519SSuanming Mou } 15762d7d519SSuanming Mou 15862d7d519SSuanming Mou static inline uint32_t 15962d7d519SSuanming Mou mlx5_trunk_size_get(struct mlx5_indexed_pool *pool, uint32_t trunk_idx) 16062d7d519SSuanming Mou { 16162d7d519SSuanming Mou struct mlx5_indexed_pool_config *cfg = &pool->cfg; 16262d7d519SSuanming Mou 16362d7d519SSuanming Mou return cfg->trunk_size << (cfg->grow_shift * 16462d7d519SSuanming Mou (trunk_idx > cfg->grow_trunk ? cfg->grow_trunk : trunk_idx)); 16562d7d519SSuanming Mou } 16662d7d519SSuanming Mou 16762d7d519SSuanming Mou static inline uint32_t 16862d7d519SSuanming Mou mlx5_trunk_idx_offset_get(struct mlx5_indexed_pool *pool, uint32_t trunk_idx) 16962d7d519SSuanming Mou { 17062d7d519SSuanming Mou struct mlx5_indexed_pool_config *cfg = &pool->cfg; 17162d7d519SSuanming Mou uint32_t offset = 0; 17262d7d519SSuanming Mou 17362d7d519SSuanming Mou if (!trunk_idx) 17462d7d519SSuanming Mou return 0; 17562d7d519SSuanming Mou if (!cfg->grow_trunk) 17662d7d519SSuanming Mou return cfg->trunk_size * trunk_idx; 17762d7d519SSuanming Mou if (trunk_idx < cfg->grow_trunk) 17862d7d519SSuanming Mou offset = pool->grow_tbl[trunk_idx - 1]; 17962d7d519SSuanming Mou else 18062d7d519SSuanming Mou offset = pool->grow_tbl[cfg->grow_trunk - 1] + 18162d7d519SSuanming Mou (cfg->trunk_size << (cfg->grow_shift * 18262d7d519SSuanming Mou cfg->grow_trunk)) * (trunk_idx - cfg->grow_trunk); 18362d7d519SSuanming Mou return offset; 18462d7d519SSuanming Mou } 18562d7d519SSuanming Mou 186a3cf59f5SSuanming Mou struct mlx5_indexed_pool * 187a3cf59f5SSuanming Mou mlx5_ipool_create(struct mlx5_indexed_pool_config *cfg) 188a3cf59f5SSuanming Mou { 189a3cf59f5SSuanming Mou struct mlx5_indexed_pool *pool; 19062d7d519SSuanming Mou uint32_t i; 191a3cf59f5SSuanming Mou 192a3cf59f5SSuanming Mou if (!cfg || !cfg->size || (!cfg->malloc ^ !cfg->free) || 193a3cf59f5SSuanming Mou (cfg->trunk_size && ((cfg->trunk_size & (cfg->trunk_size - 1)) || 194a3cf59f5SSuanming Mou ((__builtin_ffs(cfg->trunk_size) + TRUNK_IDX_BITS) > 32)))) 195a3cf59f5SSuanming Mou return NULL; 19662d7d519SSuanming Mou pool = rte_zmalloc("mlx5_ipool", sizeof(*pool) + cfg->grow_trunk * 19762d7d519SSuanming Mou sizeof(pool->grow_tbl[0]), RTE_CACHE_LINE_SIZE); 198a3cf59f5SSuanming Mou if (!pool) 199a3cf59f5SSuanming Mou return NULL; 200a3cf59f5SSuanming Mou pool->cfg = *cfg; 201a3cf59f5SSuanming Mou if (!pool->cfg.trunk_size) 202a3cf59f5SSuanming Mou pool->cfg.trunk_size = MLX5_IPOOL_DEFAULT_TRUNK_SIZE; 203a3cf59f5SSuanming Mou if (!cfg->malloc && !cfg->free) { 204a3cf59f5SSuanming Mou pool->cfg.malloc = rte_malloc_socket; 205a3cf59f5SSuanming Mou pool->cfg.free = rte_free; 206a3cf59f5SSuanming Mou } 207a3cf59f5SSuanming Mou pool->free_list = TRUNK_INVALID; 208a3cf59f5SSuanming Mou if (pool->cfg.need_lock) 209a3cf59f5SSuanming Mou rte_spinlock_init(&pool->lock); 21062d7d519SSuanming Mou /* 21162d7d519SSuanming Mou * Initialize the dynamic grow trunk size lookup table to have a quick 21262d7d519SSuanming Mou * lookup for the trunk entry index offset. 21362d7d519SSuanming Mou */ 21462d7d519SSuanming Mou for (i = 0; i < cfg->grow_trunk; i++) { 21562d7d519SSuanming Mou pool->grow_tbl[i] = cfg->trunk_size << (cfg->grow_shift * i); 21662d7d519SSuanming Mou if (i > 0) 21762d7d519SSuanming Mou pool->grow_tbl[i] += pool->grow_tbl[i - 1]; 21862d7d519SSuanming Mou } 219a3cf59f5SSuanming Mou return pool; 220a3cf59f5SSuanming Mou } 221a3cf59f5SSuanming Mou 222a3cf59f5SSuanming Mou static int 223a3cf59f5SSuanming Mou mlx5_ipool_grow(struct mlx5_indexed_pool *pool) 224a3cf59f5SSuanming Mou { 225a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 226a3cf59f5SSuanming Mou struct mlx5_indexed_trunk **trunk_tmp; 227a3cf59f5SSuanming Mou struct mlx5_indexed_trunk **p; 228a3cf59f5SSuanming Mou size_t trunk_size = 0; 22962d7d519SSuanming Mou size_t data_size; 230a3cf59f5SSuanming Mou size_t bmp_size; 231a3cf59f5SSuanming Mou uint32_t idx; 232a3cf59f5SSuanming Mou 233a3cf59f5SSuanming Mou if (pool->n_trunk_valid == TRUNK_MAX_IDX) 234a3cf59f5SSuanming Mou return -ENOMEM; 235a3cf59f5SSuanming Mou if (pool->n_trunk_valid == pool->n_trunk) { 236a3cf59f5SSuanming Mou /* No free trunk flags, expand trunk list. */ 237a3cf59f5SSuanming Mou int n_grow = pool->n_trunk_valid ? pool->n_trunk : 238a3cf59f5SSuanming Mou RTE_CACHE_LINE_SIZE / sizeof(void *); 239a3cf59f5SSuanming Mou 240a3cf59f5SSuanming Mou p = pool->cfg.malloc(pool->cfg.type, 241a3cf59f5SSuanming Mou (pool->n_trunk_valid + n_grow) * 242a3cf59f5SSuanming Mou sizeof(struct mlx5_indexed_trunk *), 243a3cf59f5SSuanming Mou RTE_CACHE_LINE_SIZE, rte_socket_id()); 244a3cf59f5SSuanming Mou if (!p) 245a3cf59f5SSuanming Mou return -ENOMEM; 246a3cf59f5SSuanming Mou if (pool->trunks) 247a3cf59f5SSuanming Mou memcpy(p, pool->trunks, pool->n_trunk_valid * 248a3cf59f5SSuanming Mou sizeof(struct mlx5_indexed_trunk *)); 249a3cf59f5SSuanming Mou memset(RTE_PTR_ADD(p, pool->n_trunk_valid * sizeof(void *)), 0, 250a3cf59f5SSuanming Mou n_grow * sizeof(void *)); 251a3cf59f5SSuanming Mou trunk_tmp = pool->trunks; 252a3cf59f5SSuanming Mou pool->trunks = p; 253a3cf59f5SSuanming Mou if (trunk_tmp) 254a3cf59f5SSuanming Mou pool->cfg.free(trunk_tmp); 255a3cf59f5SSuanming Mou pool->n_trunk += n_grow; 256a3cf59f5SSuanming Mou } 257*1fd4bb67SSuanming Mou if (!pool->cfg.release_mem_en) { 258a3cf59f5SSuanming Mou idx = pool->n_trunk_valid; 259*1fd4bb67SSuanming Mou } else { 260*1fd4bb67SSuanming Mou /* Find the first available slot in trunk list */ 261*1fd4bb67SSuanming Mou for (idx = 0; idx < pool->n_trunk; idx++) 262*1fd4bb67SSuanming Mou if (pool->trunks[idx] == NULL) 263*1fd4bb67SSuanming Mou break; 264*1fd4bb67SSuanming Mou } 265a3cf59f5SSuanming Mou trunk_size += sizeof(*trunk); 26662d7d519SSuanming Mou data_size = mlx5_trunk_size_get(pool, idx); 26762d7d519SSuanming Mou bmp_size = rte_bitmap_get_memory_footprint(data_size); 26862d7d519SSuanming Mou trunk_size += data_size * pool->cfg.size + bmp_size; 269a3cf59f5SSuanming Mou trunk = pool->cfg.malloc(pool->cfg.type, trunk_size, 270a3cf59f5SSuanming Mou RTE_CACHE_LINE_SIZE, rte_socket_id()); 271a3cf59f5SSuanming Mou if (!trunk) 272a3cf59f5SSuanming Mou return -ENOMEM; 273a3cf59f5SSuanming Mou pool->trunks[idx] = trunk; 274a3cf59f5SSuanming Mou trunk->idx = idx; 27562d7d519SSuanming Mou trunk->free = data_size; 276a3cf59f5SSuanming Mou trunk->prev = TRUNK_INVALID; 277a3cf59f5SSuanming Mou trunk->next = TRUNK_INVALID; 278a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list == TRUNK_INVALID); 279a3cf59f5SSuanming Mou pool->free_list = idx; 280a3cf59f5SSuanming Mou /* Mark all entries as available. */ 28162d7d519SSuanming Mou trunk->bmp = rte_bitmap_init_with_all_set(data_size, 28262d7d519SSuanming Mou &trunk->data[data_size * pool->cfg.size], bmp_size); 283a3cf59f5SSuanming Mou pool->n_trunk_valid++; 284a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 285a3cf59f5SSuanming Mou pool->trunk_new++; 286a3cf59f5SSuanming Mou pool->trunk_avail++; 287a3cf59f5SSuanming Mou #endif 288a3cf59f5SSuanming Mou return 0; 289a3cf59f5SSuanming Mou } 290a3cf59f5SSuanming Mou 291a3cf59f5SSuanming Mou void * 292a3cf59f5SSuanming Mou mlx5_ipool_malloc(struct mlx5_indexed_pool *pool, uint32_t *idx) 293a3cf59f5SSuanming Mou { 294a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 295a3cf59f5SSuanming Mou uint64_t slab = 0; 296a3cf59f5SSuanming Mou uint32_t iidx = 0; 297a3cf59f5SSuanming Mou void *p; 298a3cf59f5SSuanming Mou 299a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 300a3cf59f5SSuanming Mou if (pool->free_list == TRUNK_INVALID) { 301a3cf59f5SSuanming Mou /* If no available trunks, grow new. */ 302a3cf59f5SSuanming Mou if (mlx5_ipool_grow(pool)) { 303a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 304a3cf59f5SSuanming Mou return NULL; 305a3cf59f5SSuanming Mou } 306a3cf59f5SSuanming Mou } 307a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list != TRUNK_INVALID); 308a3cf59f5SSuanming Mou trunk = pool->trunks[pool->free_list]; 309a3cf59f5SSuanming Mou MLX5_ASSERT(trunk->free); 310a3cf59f5SSuanming Mou if (!rte_bitmap_scan(trunk->bmp, &iidx, &slab)) { 311a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 312a3cf59f5SSuanming Mou return NULL; 313a3cf59f5SSuanming Mou } 314a3cf59f5SSuanming Mou MLX5_ASSERT(slab); 315a3cf59f5SSuanming Mou iidx += __builtin_ctzll(slab); 316a3cf59f5SSuanming Mou MLX5_ASSERT(iidx != UINT32_MAX); 31762d7d519SSuanming Mou MLX5_ASSERT(iidx < mlx5_trunk_size_get(pool, trunk->idx)); 318a3cf59f5SSuanming Mou rte_bitmap_clear(trunk->bmp, iidx); 319a3cf59f5SSuanming Mou p = &trunk->data[iidx * pool->cfg.size]; 32062d7d519SSuanming Mou iidx += mlx5_trunk_idx_offset_get(pool, trunk->idx); 321a3cf59f5SSuanming Mou iidx += 1; /* non-zero index. */ 322a3cf59f5SSuanming Mou trunk->free--; 323a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 324a3cf59f5SSuanming Mou pool->n_entry++; 325a3cf59f5SSuanming Mou #endif 326a3cf59f5SSuanming Mou if (!trunk->free) { 327a3cf59f5SSuanming Mou /* Full trunk will be removed from free list in imalloc. */ 328a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list == trunk->idx); 329a3cf59f5SSuanming Mou pool->free_list = trunk->next; 330a3cf59f5SSuanming Mou if (trunk->next != TRUNK_INVALID) 331a3cf59f5SSuanming Mou pool->trunks[trunk->next]->prev = TRUNK_INVALID; 332a3cf59f5SSuanming Mou trunk->prev = TRUNK_INVALID; 333a3cf59f5SSuanming Mou trunk->next = TRUNK_INVALID; 334a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 335a3cf59f5SSuanming Mou pool->trunk_empty++; 336a3cf59f5SSuanming Mou pool->trunk_avail--; 337a3cf59f5SSuanming Mou #endif 338a3cf59f5SSuanming Mou } 339a3cf59f5SSuanming Mou *idx = iidx; 340a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 341a3cf59f5SSuanming Mou return p; 342a3cf59f5SSuanming Mou } 343a3cf59f5SSuanming Mou 344a3cf59f5SSuanming Mou void * 345a3cf59f5SSuanming Mou mlx5_ipool_zmalloc(struct mlx5_indexed_pool *pool, uint32_t *idx) 346a3cf59f5SSuanming Mou { 347a3cf59f5SSuanming Mou void *entry = mlx5_ipool_malloc(pool, idx); 348a3cf59f5SSuanming Mou 349a3cf59f5SSuanming Mou if (entry) 350a3cf59f5SSuanming Mou memset(entry, 0, pool->cfg.size); 351a3cf59f5SSuanming Mou return entry; 352a3cf59f5SSuanming Mou } 353a3cf59f5SSuanming Mou 354a3cf59f5SSuanming Mou void 355a3cf59f5SSuanming Mou mlx5_ipool_free(struct mlx5_indexed_pool *pool, uint32_t idx) 356a3cf59f5SSuanming Mou { 357a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 358a3cf59f5SSuanming Mou uint32_t trunk_idx; 35962d7d519SSuanming Mou uint32_t entry_idx; 360a3cf59f5SSuanming Mou 361a3cf59f5SSuanming Mou if (!idx) 362a3cf59f5SSuanming Mou return; 363a3cf59f5SSuanming Mou idx -= 1; 364a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 36562d7d519SSuanming Mou trunk_idx = mlx5_trunk_idx_get(pool, idx); 366*1fd4bb67SSuanming Mou if ((!pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk_valid) || 367*1fd4bb67SSuanming Mou (pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk)) 368a3cf59f5SSuanming Mou goto out; 369a3cf59f5SSuanming Mou trunk = pool->trunks[trunk_idx]; 37062d7d519SSuanming Mou if (!trunk) 371a3cf59f5SSuanming Mou goto out; 37262d7d519SSuanming Mou entry_idx = idx - mlx5_trunk_idx_offset_get(pool, trunk->idx); 37362d7d519SSuanming Mou if (trunk_idx != trunk->idx || 37462d7d519SSuanming Mou rte_bitmap_get(trunk->bmp, entry_idx)) 37562d7d519SSuanming Mou goto out; 37662d7d519SSuanming Mou rte_bitmap_set(trunk->bmp, entry_idx); 377a3cf59f5SSuanming Mou trunk->free++; 378*1fd4bb67SSuanming Mou if (pool->cfg.release_mem_en && trunk->free == mlx5_trunk_size_get 379*1fd4bb67SSuanming Mou (pool, trunk->idx)) { 380*1fd4bb67SSuanming Mou if (pool->free_list == trunk->idx) 381*1fd4bb67SSuanming Mou pool->free_list = trunk->next; 382*1fd4bb67SSuanming Mou if (trunk->next != TRUNK_INVALID) 383*1fd4bb67SSuanming Mou pool->trunks[trunk->next]->prev = trunk->prev; 384*1fd4bb67SSuanming Mou if (trunk->prev != TRUNK_INVALID) 385*1fd4bb67SSuanming Mou pool->trunks[trunk->prev]->next = trunk->next; 386*1fd4bb67SSuanming Mou pool->cfg.free(trunk); 387*1fd4bb67SSuanming Mou pool->trunks[trunk_idx] = NULL; 388*1fd4bb67SSuanming Mou pool->n_trunk_valid--; 389*1fd4bb67SSuanming Mou #ifdef POOL_DEBUG 390*1fd4bb67SSuanming Mou pool->trunk_avail--; 391*1fd4bb67SSuanming Mou pool->trunk_free++; 392*1fd4bb67SSuanming Mou #endif 393*1fd4bb67SSuanming Mou if (pool->n_trunk_valid == 0) { 394*1fd4bb67SSuanming Mou pool->cfg.free(pool->trunks); 395*1fd4bb67SSuanming Mou pool->trunks = NULL; 396*1fd4bb67SSuanming Mou pool->n_trunk = 0; 397*1fd4bb67SSuanming Mou } 398*1fd4bb67SSuanming Mou } else if (trunk->free == 1) { 399a3cf59f5SSuanming Mou /* Put into free trunk list head. */ 400a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list != trunk->idx); 401a3cf59f5SSuanming Mou trunk->next = pool->free_list; 402a3cf59f5SSuanming Mou trunk->prev = TRUNK_INVALID; 403a3cf59f5SSuanming Mou if (pool->free_list != TRUNK_INVALID) 404a3cf59f5SSuanming Mou pool->trunks[pool->free_list]->prev = trunk->idx; 405a3cf59f5SSuanming Mou pool->free_list = trunk->idx; 406a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 407a3cf59f5SSuanming Mou pool->trunk_empty--; 408a3cf59f5SSuanming Mou pool->trunk_avail++; 409a3cf59f5SSuanming Mou #endif 410a3cf59f5SSuanming Mou } 411a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 412a3cf59f5SSuanming Mou pool->n_entry--; 413a3cf59f5SSuanming Mou #endif 414a3cf59f5SSuanming Mou out: 415a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 416a3cf59f5SSuanming Mou } 417a3cf59f5SSuanming Mou 418a3cf59f5SSuanming Mou void * 419a3cf59f5SSuanming Mou mlx5_ipool_get(struct mlx5_indexed_pool *pool, uint32_t idx) 420a3cf59f5SSuanming Mou { 421a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 422a3cf59f5SSuanming Mou void *p = NULL; 423a3cf59f5SSuanming Mou uint32_t trunk_idx; 42462d7d519SSuanming Mou uint32_t entry_idx; 425a3cf59f5SSuanming Mou 426a3cf59f5SSuanming Mou if (!idx) 427a3cf59f5SSuanming Mou return NULL; 428a3cf59f5SSuanming Mou idx -= 1; 429a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 43062d7d519SSuanming Mou trunk_idx = mlx5_trunk_idx_get(pool, idx); 431*1fd4bb67SSuanming Mou if ((!pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk_valid) || 432*1fd4bb67SSuanming Mou (pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk)) 433a3cf59f5SSuanming Mou goto out; 434a3cf59f5SSuanming Mou trunk = pool->trunks[trunk_idx]; 43562d7d519SSuanming Mou if (!trunk) 436a3cf59f5SSuanming Mou goto out; 43762d7d519SSuanming Mou entry_idx = idx - mlx5_trunk_idx_offset_get(pool, trunk->idx); 43862d7d519SSuanming Mou if (trunk_idx != trunk->idx || 43962d7d519SSuanming Mou rte_bitmap_get(trunk->bmp, entry_idx)) 44062d7d519SSuanming Mou goto out; 44162d7d519SSuanming Mou p = &trunk->data[entry_idx * pool->cfg.size]; 442a3cf59f5SSuanming Mou out: 443a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 444a3cf59f5SSuanming Mou return p; 445a3cf59f5SSuanming Mou } 446a3cf59f5SSuanming Mou 447a3cf59f5SSuanming Mou int 448a3cf59f5SSuanming Mou mlx5_ipool_destroy(struct mlx5_indexed_pool *pool) 449a3cf59f5SSuanming Mou { 450a3cf59f5SSuanming Mou struct mlx5_indexed_trunk **trunks; 451a3cf59f5SSuanming Mou uint32_t i; 452a3cf59f5SSuanming Mou 453a3cf59f5SSuanming Mou MLX5_ASSERT(pool); 454a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 455a3cf59f5SSuanming Mou trunks = pool->trunks; 456a3cf59f5SSuanming Mou for (i = 0; i < pool->n_trunk; i++) { 457a3cf59f5SSuanming Mou if (trunks[i]) 458a3cf59f5SSuanming Mou pool->cfg.free(trunks[i]); 459a3cf59f5SSuanming Mou } 460a3cf59f5SSuanming Mou if (!pool->trunks) 461a3cf59f5SSuanming Mou pool->cfg.free(pool->trunks); 462a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 463a3cf59f5SSuanming Mou rte_free(pool); 464a3cf59f5SSuanming Mou return 0; 465a3cf59f5SSuanming Mou } 466a3cf59f5SSuanming Mou 467a3cf59f5SSuanming Mou void 468a3cf59f5SSuanming Mou mlx5_ipool_dump(struct mlx5_indexed_pool *pool) 469a3cf59f5SSuanming Mou { 470a3cf59f5SSuanming Mou printf("Pool %s entry size %u, trunks %u, %d entry per trunk, " 471a3cf59f5SSuanming Mou "total: %d\n", 472a3cf59f5SSuanming Mou pool->cfg.type, pool->cfg.size, pool->n_trunk_valid, 473a3cf59f5SSuanming Mou pool->cfg.trunk_size, pool->n_trunk_valid); 474a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 475a3cf59f5SSuanming Mou printf("Pool %s entry %u, trunk alloc %u, empty: %u, " 476a3cf59f5SSuanming Mou "available %u free %u\n", 477a3cf59f5SSuanming Mou pool->cfg.type, pool->n_entry, pool->trunk_new, 478a3cf59f5SSuanming Mou pool->trunk_empty, pool->trunk_avail, pool->trunk_free); 479a3cf59f5SSuanming Mou #endif 480a3cf59f5SSuanming Mou } 481