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 8*83c2047cSSuanming Mou #include <mlx5_malloc.h> 9*83c2047cSSuanming Mou 1046287eacSBing Zhao #include "mlx5_utils.h" 1146287eacSBing Zhao 1246287eacSBing Zhao struct mlx5_hlist * 1346287eacSBing Zhao mlx5_hlist_create(const char *name, uint32_t size) 1446287eacSBing Zhao { 1546287eacSBing Zhao struct mlx5_hlist *h; 1646287eacSBing Zhao uint32_t act_size; 1746287eacSBing Zhao uint32_t alloc_size; 1846287eacSBing Zhao 1946287eacSBing Zhao if (!size) 2046287eacSBing Zhao return NULL; 2146287eacSBing Zhao /* Align to the next power of 2, 32bits integer is enough now. */ 2246287eacSBing Zhao if (!rte_is_power_of_2(size)) { 2346287eacSBing Zhao act_size = rte_align32pow2(size); 2446287eacSBing Zhao DRV_LOG(WARNING, "Size 0x%" PRIX32 " is not power of 2, will " 2563783b01SDavid Marchand "be aligned to 0x%" PRIX32 ".", size, act_size); 2646287eacSBing Zhao } else { 2746287eacSBing Zhao act_size = size; 2846287eacSBing Zhao } 2946287eacSBing Zhao alloc_size = sizeof(struct mlx5_hlist) + 3046287eacSBing Zhao sizeof(struct mlx5_hlist_head) * act_size; 3146287eacSBing Zhao /* Using zmalloc, then no need to initialize the heads. */ 32*83c2047cSSuanming Mou h = mlx5_malloc(MLX5_MEM_ZERO, alloc_size, RTE_CACHE_LINE_SIZE, 33*83c2047cSSuanming Mou SOCKET_ID_ANY); 3446287eacSBing Zhao if (!h) { 3563783b01SDavid Marchand DRV_LOG(ERR, "No memory for hash list %s creation", 3646287eacSBing Zhao name ? name : "None"); 3746287eacSBing Zhao return NULL; 3846287eacSBing Zhao } 3946287eacSBing Zhao if (name) 4046287eacSBing Zhao snprintf(h->name, MLX5_HLIST_NAMESIZE, "%s", name); 4146287eacSBing Zhao h->table_sz = act_size; 4246287eacSBing Zhao h->mask = act_size - 1; 4363783b01SDavid Marchand DRV_LOG(DEBUG, "Hash list with %s size 0x%" PRIX32 " is created.", 4446287eacSBing Zhao h->name, act_size); 4546287eacSBing Zhao return h; 4646287eacSBing Zhao } 4746287eacSBing Zhao 4846287eacSBing Zhao struct mlx5_hlist_entry * 4946287eacSBing Zhao mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key) 5046287eacSBing Zhao { 5146287eacSBing Zhao uint32_t idx; 5246287eacSBing Zhao struct mlx5_hlist_head *first; 5346287eacSBing Zhao struct mlx5_hlist_entry *node; 5446287eacSBing Zhao 558e46d4e1SAlexander Kozyrev MLX5_ASSERT(h); 5646287eacSBing Zhao idx = rte_hash_crc_8byte(key, 0) & h->mask; 5746287eacSBing Zhao first = &h->heads[idx]; 5846287eacSBing Zhao LIST_FOREACH(node, first, next) { 5946287eacSBing Zhao if (node->key == key) 6046287eacSBing Zhao return node; 6146287eacSBing Zhao } 6246287eacSBing Zhao return NULL; 6346287eacSBing Zhao } 6446287eacSBing Zhao 6546287eacSBing Zhao int 6646287eacSBing Zhao mlx5_hlist_insert(struct mlx5_hlist *h, struct mlx5_hlist_entry *entry) 6746287eacSBing Zhao { 6846287eacSBing Zhao uint32_t idx; 6946287eacSBing Zhao struct mlx5_hlist_head *first; 7046287eacSBing Zhao struct mlx5_hlist_entry *node; 7146287eacSBing Zhao 728e46d4e1SAlexander Kozyrev MLX5_ASSERT(h && entry); 7346287eacSBing Zhao idx = rte_hash_crc_8byte(entry->key, 0) & h->mask; 7446287eacSBing Zhao first = &h->heads[idx]; 7546287eacSBing Zhao /* No need to reuse the lookup function. */ 7646287eacSBing Zhao LIST_FOREACH(node, first, next) { 7746287eacSBing Zhao if (node->key == entry->key) 7846287eacSBing Zhao return -EEXIST; 7946287eacSBing Zhao } 8046287eacSBing Zhao LIST_INSERT_HEAD(first, entry, next); 8146287eacSBing Zhao return 0; 8246287eacSBing Zhao } 8346287eacSBing Zhao 8446287eacSBing Zhao void 8546287eacSBing Zhao mlx5_hlist_remove(struct mlx5_hlist *h __rte_unused, 8646287eacSBing Zhao struct mlx5_hlist_entry *entry) 8746287eacSBing Zhao { 888e46d4e1SAlexander Kozyrev MLX5_ASSERT(entry && entry->next.le_prev); 8946287eacSBing Zhao LIST_REMOVE(entry, next); 9046287eacSBing Zhao /* Set to NULL to get rid of removing action for more than once. */ 9146287eacSBing Zhao entry->next.le_prev = NULL; 9246287eacSBing Zhao } 9346287eacSBing Zhao 9446287eacSBing Zhao void 9546287eacSBing Zhao mlx5_hlist_destroy(struct mlx5_hlist *h, 9646287eacSBing Zhao mlx5_hlist_destroy_callback_fn cb, void *ctx) 9746287eacSBing Zhao { 9846287eacSBing Zhao uint32_t idx; 9946287eacSBing Zhao struct mlx5_hlist_entry *entry; 10046287eacSBing Zhao 1018e46d4e1SAlexander Kozyrev MLX5_ASSERT(h); 10246287eacSBing Zhao for (idx = 0; idx < h->table_sz; ++idx) { 10346287eacSBing Zhao /* no LIST_FOREACH_SAFE, using while instead */ 10446287eacSBing Zhao while (!LIST_EMPTY(&h->heads[idx])) { 10546287eacSBing Zhao entry = LIST_FIRST(&h->heads[idx]); 10646287eacSBing Zhao LIST_REMOVE(entry, next); 10746287eacSBing Zhao /* 10846287eacSBing Zhao * The owner of whole element which contains data entry 10946287eacSBing Zhao * is the user, so it's the user's duty to do the clean 11046287eacSBing Zhao * up and the free work because someone may not put the 11146287eacSBing Zhao * hlist entry at the beginning(suggested to locate at 11246287eacSBing Zhao * the beginning). Or else the default free function 11346287eacSBing Zhao * will be used. 11446287eacSBing Zhao */ 11546287eacSBing Zhao if (cb) 11646287eacSBing Zhao cb(entry, ctx); 11746287eacSBing Zhao else 118*83c2047cSSuanming Mou mlx5_free(entry); 11946287eacSBing Zhao } 12046287eacSBing Zhao } 121*83c2047cSSuanming Mou mlx5_free(h); 12246287eacSBing Zhao } 123a3cf59f5SSuanming Mou 124a3cf59f5SSuanming Mou static inline void 125a3cf59f5SSuanming Mou mlx5_ipool_lock(struct mlx5_indexed_pool *pool) 126a3cf59f5SSuanming Mou { 127a3cf59f5SSuanming Mou if (pool->cfg.need_lock) 128a3cf59f5SSuanming Mou rte_spinlock_lock(&pool->lock); 129a3cf59f5SSuanming Mou } 130a3cf59f5SSuanming Mou 131a3cf59f5SSuanming Mou static inline void 132a3cf59f5SSuanming Mou mlx5_ipool_unlock(struct mlx5_indexed_pool *pool) 133a3cf59f5SSuanming Mou { 134a3cf59f5SSuanming Mou if (pool->cfg.need_lock) 135a3cf59f5SSuanming Mou rte_spinlock_unlock(&pool->lock); 136a3cf59f5SSuanming Mou } 137a3cf59f5SSuanming Mou 13862d7d519SSuanming Mou static inline uint32_t 13962d7d519SSuanming Mou mlx5_trunk_idx_get(struct mlx5_indexed_pool *pool, uint32_t entry_idx) 14062d7d519SSuanming Mou { 14162d7d519SSuanming Mou struct mlx5_indexed_pool_config *cfg = &pool->cfg; 14262d7d519SSuanming Mou uint32_t trunk_idx = 0; 14362d7d519SSuanming Mou uint32_t i; 14462d7d519SSuanming Mou 14562d7d519SSuanming Mou if (!cfg->grow_trunk) 14662d7d519SSuanming Mou return entry_idx / cfg->trunk_size; 14762d7d519SSuanming Mou if (entry_idx >= pool->grow_tbl[cfg->grow_trunk - 1]) { 14862d7d519SSuanming Mou trunk_idx = (entry_idx - pool->grow_tbl[cfg->grow_trunk - 1]) / 14962d7d519SSuanming Mou (cfg->trunk_size << (cfg->grow_shift * 15062d7d519SSuanming Mou cfg->grow_trunk)) + cfg->grow_trunk; 15162d7d519SSuanming Mou } else { 15262d7d519SSuanming Mou for (i = 0; i < cfg->grow_trunk; i++) { 15362d7d519SSuanming Mou if (entry_idx < pool->grow_tbl[i]) 15462d7d519SSuanming Mou break; 15562d7d519SSuanming Mou } 15662d7d519SSuanming Mou trunk_idx = i; 15762d7d519SSuanming Mou } 15862d7d519SSuanming Mou return trunk_idx; 15962d7d519SSuanming Mou } 16062d7d519SSuanming Mou 16162d7d519SSuanming Mou static inline uint32_t 16262d7d519SSuanming Mou mlx5_trunk_size_get(struct mlx5_indexed_pool *pool, uint32_t trunk_idx) 16362d7d519SSuanming Mou { 16462d7d519SSuanming Mou struct mlx5_indexed_pool_config *cfg = &pool->cfg; 16562d7d519SSuanming Mou 16662d7d519SSuanming Mou return cfg->trunk_size << (cfg->grow_shift * 16762d7d519SSuanming Mou (trunk_idx > cfg->grow_trunk ? cfg->grow_trunk : trunk_idx)); 16862d7d519SSuanming Mou } 16962d7d519SSuanming Mou 17062d7d519SSuanming Mou static inline uint32_t 17162d7d519SSuanming Mou mlx5_trunk_idx_offset_get(struct mlx5_indexed_pool *pool, uint32_t trunk_idx) 17262d7d519SSuanming Mou { 17362d7d519SSuanming Mou struct mlx5_indexed_pool_config *cfg = &pool->cfg; 17462d7d519SSuanming Mou uint32_t offset = 0; 17562d7d519SSuanming Mou 17662d7d519SSuanming Mou if (!trunk_idx) 17762d7d519SSuanming Mou return 0; 17862d7d519SSuanming Mou if (!cfg->grow_trunk) 17962d7d519SSuanming Mou return cfg->trunk_size * trunk_idx; 18062d7d519SSuanming Mou if (trunk_idx < cfg->grow_trunk) 18162d7d519SSuanming Mou offset = pool->grow_tbl[trunk_idx - 1]; 18262d7d519SSuanming Mou else 18362d7d519SSuanming Mou offset = pool->grow_tbl[cfg->grow_trunk - 1] + 18462d7d519SSuanming Mou (cfg->trunk_size << (cfg->grow_shift * 18562d7d519SSuanming Mou cfg->grow_trunk)) * (trunk_idx - cfg->grow_trunk); 18662d7d519SSuanming Mou return offset; 18762d7d519SSuanming Mou } 18862d7d519SSuanming Mou 189a3cf59f5SSuanming Mou struct mlx5_indexed_pool * 190a3cf59f5SSuanming Mou mlx5_ipool_create(struct mlx5_indexed_pool_config *cfg) 191a3cf59f5SSuanming Mou { 192a3cf59f5SSuanming Mou struct mlx5_indexed_pool *pool; 19362d7d519SSuanming Mou uint32_t i; 194a3cf59f5SSuanming Mou 195a3cf59f5SSuanming Mou if (!cfg || !cfg->size || (!cfg->malloc ^ !cfg->free) || 196a3cf59f5SSuanming Mou (cfg->trunk_size && ((cfg->trunk_size & (cfg->trunk_size - 1)) || 197a3cf59f5SSuanming Mou ((__builtin_ffs(cfg->trunk_size) + TRUNK_IDX_BITS) > 32)))) 198a3cf59f5SSuanming Mou return NULL; 199*83c2047cSSuanming Mou pool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*pool) + cfg->grow_trunk * 200*83c2047cSSuanming Mou sizeof(pool->grow_tbl[0]), RTE_CACHE_LINE_SIZE, 201*83c2047cSSuanming Mou SOCKET_ID_ANY); 202a3cf59f5SSuanming Mou if (!pool) 203a3cf59f5SSuanming Mou return NULL; 204a3cf59f5SSuanming Mou pool->cfg = *cfg; 205a3cf59f5SSuanming Mou if (!pool->cfg.trunk_size) 206a3cf59f5SSuanming Mou pool->cfg.trunk_size = MLX5_IPOOL_DEFAULT_TRUNK_SIZE; 207a3cf59f5SSuanming Mou if (!cfg->malloc && !cfg->free) { 208*83c2047cSSuanming Mou pool->cfg.malloc = mlx5_malloc; 209*83c2047cSSuanming Mou pool->cfg.free = mlx5_free; 210a3cf59f5SSuanming Mou } 211a3cf59f5SSuanming Mou pool->free_list = TRUNK_INVALID; 212a3cf59f5SSuanming Mou if (pool->cfg.need_lock) 213a3cf59f5SSuanming Mou rte_spinlock_init(&pool->lock); 21462d7d519SSuanming Mou /* 21562d7d519SSuanming Mou * Initialize the dynamic grow trunk size lookup table to have a quick 21662d7d519SSuanming Mou * lookup for the trunk entry index offset. 21762d7d519SSuanming Mou */ 21862d7d519SSuanming Mou for (i = 0; i < cfg->grow_trunk; i++) { 21962d7d519SSuanming Mou pool->grow_tbl[i] = cfg->trunk_size << (cfg->grow_shift * i); 22062d7d519SSuanming Mou if (i > 0) 22162d7d519SSuanming Mou pool->grow_tbl[i] += pool->grow_tbl[i - 1]; 22262d7d519SSuanming Mou } 223a3cf59f5SSuanming Mou return pool; 224a3cf59f5SSuanming Mou } 225a3cf59f5SSuanming Mou 226a3cf59f5SSuanming Mou static int 227a3cf59f5SSuanming Mou mlx5_ipool_grow(struct mlx5_indexed_pool *pool) 228a3cf59f5SSuanming Mou { 229a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 230a3cf59f5SSuanming Mou struct mlx5_indexed_trunk **trunk_tmp; 231a3cf59f5SSuanming Mou struct mlx5_indexed_trunk **p; 232a3cf59f5SSuanming Mou size_t trunk_size = 0; 23362d7d519SSuanming Mou size_t data_size; 234a3cf59f5SSuanming Mou size_t bmp_size; 235a3cf59f5SSuanming Mou uint32_t idx; 236a3cf59f5SSuanming Mou 237a3cf59f5SSuanming Mou if (pool->n_trunk_valid == TRUNK_MAX_IDX) 238a3cf59f5SSuanming Mou return -ENOMEM; 239a3cf59f5SSuanming Mou if (pool->n_trunk_valid == pool->n_trunk) { 240a3cf59f5SSuanming Mou /* No free trunk flags, expand trunk list. */ 241a3cf59f5SSuanming Mou int n_grow = pool->n_trunk_valid ? pool->n_trunk : 242a3cf59f5SSuanming Mou RTE_CACHE_LINE_SIZE / sizeof(void *); 243a3cf59f5SSuanming Mou 244*83c2047cSSuanming Mou p = pool->cfg.malloc(0, (pool->n_trunk_valid + n_grow) * 245a3cf59f5SSuanming Mou sizeof(struct mlx5_indexed_trunk *), 246a3cf59f5SSuanming Mou RTE_CACHE_LINE_SIZE, rte_socket_id()); 247a3cf59f5SSuanming Mou if (!p) 248a3cf59f5SSuanming Mou return -ENOMEM; 249a3cf59f5SSuanming Mou if (pool->trunks) 250a3cf59f5SSuanming Mou memcpy(p, pool->trunks, pool->n_trunk_valid * 251a3cf59f5SSuanming Mou sizeof(struct mlx5_indexed_trunk *)); 252a3cf59f5SSuanming Mou memset(RTE_PTR_ADD(p, pool->n_trunk_valid * sizeof(void *)), 0, 253a3cf59f5SSuanming Mou n_grow * sizeof(void *)); 254a3cf59f5SSuanming Mou trunk_tmp = pool->trunks; 255a3cf59f5SSuanming Mou pool->trunks = p; 256a3cf59f5SSuanming Mou if (trunk_tmp) 257a3cf59f5SSuanming Mou pool->cfg.free(trunk_tmp); 258a3cf59f5SSuanming Mou pool->n_trunk += n_grow; 259a3cf59f5SSuanming Mou } 2601fd4bb67SSuanming Mou if (!pool->cfg.release_mem_en) { 261a3cf59f5SSuanming Mou idx = pool->n_trunk_valid; 2621fd4bb67SSuanming Mou } else { 2631fd4bb67SSuanming Mou /* Find the first available slot in trunk list */ 2641fd4bb67SSuanming Mou for (idx = 0; idx < pool->n_trunk; idx++) 2651fd4bb67SSuanming Mou if (pool->trunks[idx] == NULL) 2661fd4bb67SSuanming Mou break; 2671fd4bb67SSuanming Mou } 268a3cf59f5SSuanming Mou trunk_size += sizeof(*trunk); 26962d7d519SSuanming Mou data_size = mlx5_trunk_size_get(pool, idx); 27062d7d519SSuanming Mou bmp_size = rte_bitmap_get_memory_footprint(data_size); 271691b3d3eSSuanming Mou /* rte_bitmap requires memory cacheline aligned. */ 272691b3d3eSSuanming Mou trunk_size += RTE_CACHE_LINE_ROUNDUP(data_size * pool->cfg.size); 273691b3d3eSSuanming Mou trunk_size += bmp_size; 274*83c2047cSSuanming Mou trunk = pool->cfg.malloc(0, trunk_size, 275a3cf59f5SSuanming Mou RTE_CACHE_LINE_SIZE, rte_socket_id()); 276a3cf59f5SSuanming Mou if (!trunk) 277a3cf59f5SSuanming Mou return -ENOMEM; 278a3cf59f5SSuanming Mou pool->trunks[idx] = trunk; 279a3cf59f5SSuanming Mou trunk->idx = idx; 28062d7d519SSuanming Mou trunk->free = data_size; 281a3cf59f5SSuanming Mou trunk->prev = TRUNK_INVALID; 282a3cf59f5SSuanming Mou trunk->next = TRUNK_INVALID; 283a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list == TRUNK_INVALID); 284a3cf59f5SSuanming Mou pool->free_list = idx; 285a3cf59f5SSuanming Mou /* Mark all entries as available. */ 286691b3d3eSSuanming Mou trunk->bmp = rte_bitmap_init_with_all_set(data_size, &trunk->data 287691b3d3eSSuanming Mou [RTE_CACHE_LINE_ROUNDUP(data_size * pool->cfg.size)], 288691b3d3eSSuanming Mou bmp_size); 289691b3d3eSSuanming Mou MLX5_ASSERT(trunk->bmp); 290a3cf59f5SSuanming Mou pool->n_trunk_valid++; 291a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 292a3cf59f5SSuanming Mou pool->trunk_new++; 293a3cf59f5SSuanming Mou pool->trunk_avail++; 294a3cf59f5SSuanming Mou #endif 295a3cf59f5SSuanming Mou return 0; 296a3cf59f5SSuanming Mou } 297a3cf59f5SSuanming Mou 298a3cf59f5SSuanming Mou void * 299a3cf59f5SSuanming Mou mlx5_ipool_malloc(struct mlx5_indexed_pool *pool, uint32_t *idx) 300a3cf59f5SSuanming Mou { 301a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 302a3cf59f5SSuanming Mou uint64_t slab = 0; 303a3cf59f5SSuanming Mou uint32_t iidx = 0; 304a3cf59f5SSuanming Mou void *p; 305a3cf59f5SSuanming Mou 306a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 307a3cf59f5SSuanming Mou if (pool->free_list == TRUNK_INVALID) { 308a3cf59f5SSuanming Mou /* If no available trunks, grow new. */ 309a3cf59f5SSuanming Mou if (mlx5_ipool_grow(pool)) { 310a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 311a3cf59f5SSuanming Mou return NULL; 312a3cf59f5SSuanming Mou } 313a3cf59f5SSuanming Mou } 314a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list != TRUNK_INVALID); 315a3cf59f5SSuanming Mou trunk = pool->trunks[pool->free_list]; 316a3cf59f5SSuanming Mou MLX5_ASSERT(trunk->free); 317a3cf59f5SSuanming Mou if (!rte_bitmap_scan(trunk->bmp, &iidx, &slab)) { 318a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 319a3cf59f5SSuanming Mou return NULL; 320a3cf59f5SSuanming Mou } 321a3cf59f5SSuanming Mou MLX5_ASSERT(slab); 322a3cf59f5SSuanming Mou iidx += __builtin_ctzll(slab); 323a3cf59f5SSuanming Mou MLX5_ASSERT(iidx != UINT32_MAX); 32462d7d519SSuanming Mou MLX5_ASSERT(iidx < mlx5_trunk_size_get(pool, trunk->idx)); 325a3cf59f5SSuanming Mou rte_bitmap_clear(trunk->bmp, iidx); 326a3cf59f5SSuanming Mou p = &trunk->data[iidx * pool->cfg.size]; 32762d7d519SSuanming Mou iidx += mlx5_trunk_idx_offset_get(pool, trunk->idx); 328a3cf59f5SSuanming Mou iidx += 1; /* non-zero index. */ 329a3cf59f5SSuanming Mou trunk->free--; 330a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 331a3cf59f5SSuanming Mou pool->n_entry++; 332a3cf59f5SSuanming Mou #endif 333a3cf59f5SSuanming Mou if (!trunk->free) { 334a3cf59f5SSuanming Mou /* Full trunk will be removed from free list in imalloc. */ 335a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list == trunk->idx); 336a3cf59f5SSuanming Mou pool->free_list = trunk->next; 337a3cf59f5SSuanming Mou if (trunk->next != TRUNK_INVALID) 338a3cf59f5SSuanming Mou pool->trunks[trunk->next]->prev = TRUNK_INVALID; 339a3cf59f5SSuanming Mou trunk->prev = TRUNK_INVALID; 340a3cf59f5SSuanming Mou trunk->next = TRUNK_INVALID; 341a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 342a3cf59f5SSuanming Mou pool->trunk_empty++; 343a3cf59f5SSuanming Mou pool->trunk_avail--; 344a3cf59f5SSuanming Mou #endif 345a3cf59f5SSuanming Mou } 346a3cf59f5SSuanming Mou *idx = iidx; 347a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 348a3cf59f5SSuanming Mou return p; 349a3cf59f5SSuanming Mou } 350a3cf59f5SSuanming Mou 351a3cf59f5SSuanming Mou void * 352a3cf59f5SSuanming Mou mlx5_ipool_zmalloc(struct mlx5_indexed_pool *pool, uint32_t *idx) 353a3cf59f5SSuanming Mou { 354a3cf59f5SSuanming Mou void *entry = mlx5_ipool_malloc(pool, idx); 355a3cf59f5SSuanming Mou 356a3cf59f5SSuanming Mou if (entry) 357a3cf59f5SSuanming Mou memset(entry, 0, pool->cfg.size); 358a3cf59f5SSuanming Mou return entry; 359a3cf59f5SSuanming Mou } 360a3cf59f5SSuanming Mou 361a3cf59f5SSuanming Mou void 362a3cf59f5SSuanming Mou mlx5_ipool_free(struct mlx5_indexed_pool *pool, uint32_t idx) 363a3cf59f5SSuanming Mou { 364a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 365a3cf59f5SSuanming Mou uint32_t trunk_idx; 36662d7d519SSuanming Mou uint32_t entry_idx; 367a3cf59f5SSuanming Mou 368a3cf59f5SSuanming Mou if (!idx) 369a3cf59f5SSuanming Mou return; 370a3cf59f5SSuanming Mou idx -= 1; 371a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 37262d7d519SSuanming Mou trunk_idx = mlx5_trunk_idx_get(pool, idx); 3731fd4bb67SSuanming Mou if ((!pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk_valid) || 3741fd4bb67SSuanming Mou (pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk)) 375a3cf59f5SSuanming Mou goto out; 376a3cf59f5SSuanming Mou trunk = pool->trunks[trunk_idx]; 37762d7d519SSuanming Mou if (!trunk) 378a3cf59f5SSuanming Mou goto out; 37962d7d519SSuanming Mou entry_idx = idx - mlx5_trunk_idx_offset_get(pool, trunk->idx); 38062d7d519SSuanming Mou if (trunk_idx != trunk->idx || 38162d7d519SSuanming Mou rte_bitmap_get(trunk->bmp, entry_idx)) 38262d7d519SSuanming Mou goto out; 38362d7d519SSuanming Mou rte_bitmap_set(trunk->bmp, entry_idx); 384a3cf59f5SSuanming Mou trunk->free++; 3851fd4bb67SSuanming Mou if (pool->cfg.release_mem_en && trunk->free == mlx5_trunk_size_get 3861fd4bb67SSuanming Mou (pool, trunk->idx)) { 3871fd4bb67SSuanming Mou if (pool->free_list == trunk->idx) 3881fd4bb67SSuanming Mou pool->free_list = trunk->next; 3891fd4bb67SSuanming Mou if (trunk->next != TRUNK_INVALID) 3901fd4bb67SSuanming Mou pool->trunks[trunk->next]->prev = trunk->prev; 3911fd4bb67SSuanming Mou if (trunk->prev != TRUNK_INVALID) 3921fd4bb67SSuanming Mou pool->trunks[trunk->prev]->next = trunk->next; 3931fd4bb67SSuanming Mou pool->cfg.free(trunk); 3941fd4bb67SSuanming Mou pool->trunks[trunk_idx] = NULL; 3951fd4bb67SSuanming Mou pool->n_trunk_valid--; 3961fd4bb67SSuanming Mou #ifdef POOL_DEBUG 3971fd4bb67SSuanming Mou pool->trunk_avail--; 3981fd4bb67SSuanming Mou pool->trunk_free++; 3991fd4bb67SSuanming Mou #endif 4001fd4bb67SSuanming Mou if (pool->n_trunk_valid == 0) { 4011fd4bb67SSuanming Mou pool->cfg.free(pool->trunks); 4021fd4bb67SSuanming Mou pool->trunks = NULL; 4031fd4bb67SSuanming Mou pool->n_trunk = 0; 4041fd4bb67SSuanming Mou } 4051fd4bb67SSuanming Mou } else if (trunk->free == 1) { 406a3cf59f5SSuanming Mou /* Put into free trunk list head. */ 407a3cf59f5SSuanming Mou MLX5_ASSERT(pool->free_list != trunk->idx); 408a3cf59f5SSuanming Mou trunk->next = pool->free_list; 409a3cf59f5SSuanming Mou trunk->prev = TRUNK_INVALID; 410a3cf59f5SSuanming Mou if (pool->free_list != TRUNK_INVALID) 411a3cf59f5SSuanming Mou pool->trunks[pool->free_list]->prev = trunk->idx; 412a3cf59f5SSuanming Mou pool->free_list = trunk->idx; 413a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 414a3cf59f5SSuanming Mou pool->trunk_empty--; 415a3cf59f5SSuanming Mou pool->trunk_avail++; 416a3cf59f5SSuanming Mou #endif 417a3cf59f5SSuanming Mou } 418a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 419a3cf59f5SSuanming Mou pool->n_entry--; 420a3cf59f5SSuanming Mou #endif 421a3cf59f5SSuanming Mou out: 422a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 423a3cf59f5SSuanming Mou } 424a3cf59f5SSuanming Mou 425a3cf59f5SSuanming Mou void * 426a3cf59f5SSuanming Mou mlx5_ipool_get(struct mlx5_indexed_pool *pool, uint32_t idx) 427a3cf59f5SSuanming Mou { 428a3cf59f5SSuanming Mou struct mlx5_indexed_trunk *trunk; 429a3cf59f5SSuanming Mou void *p = NULL; 430a3cf59f5SSuanming Mou uint32_t trunk_idx; 43162d7d519SSuanming Mou uint32_t entry_idx; 432a3cf59f5SSuanming Mou 433a3cf59f5SSuanming Mou if (!idx) 434a3cf59f5SSuanming Mou return NULL; 435a3cf59f5SSuanming Mou idx -= 1; 436a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 43762d7d519SSuanming Mou trunk_idx = mlx5_trunk_idx_get(pool, idx); 4381fd4bb67SSuanming Mou if ((!pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk_valid) || 4391fd4bb67SSuanming Mou (pool->cfg.release_mem_en && trunk_idx >= pool->n_trunk)) 440a3cf59f5SSuanming Mou goto out; 441a3cf59f5SSuanming Mou trunk = pool->trunks[trunk_idx]; 44262d7d519SSuanming Mou if (!trunk) 443a3cf59f5SSuanming Mou goto out; 44462d7d519SSuanming Mou entry_idx = idx - mlx5_trunk_idx_offset_get(pool, trunk->idx); 44562d7d519SSuanming Mou if (trunk_idx != trunk->idx || 44662d7d519SSuanming Mou rte_bitmap_get(trunk->bmp, entry_idx)) 44762d7d519SSuanming Mou goto out; 44862d7d519SSuanming Mou p = &trunk->data[entry_idx * pool->cfg.size]; 449a3cf59f5SSuanming Mou out: 450a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 451a3cf59f5SSuanming Mou return p; 452a3cf59f5SSuanming Mou } 453a3cf59f5SSuanming Mou 454a3cf59f5SSuanming Mou int 455a3cf59f5SSuanming Mou mlx5_ipool_destroy(struct mlx5_indexed_pool *pool) 456a3cf59f5SSuanming Mou { 457a3cf59f5SSuanming Mou struct mlx5_indexed_trunk **trunks; 458a3cf59f5SSuanming Mou uint32_t i; 459a3cf59f5SSuanming Mou 460a3cf59f5SSuanming Mou MLX5_ASSERT(pool); 461a3cf59f5SSuanming Mou mlx5_ipool_lock(pool); 462a3cf59f5SSuanming Mou trunks = pool->trunks; 463a3cf59f5SSuanming Mou for (i = 0; i < pool->n_trunk; i++) { 464a3cf59f5SSuanming Mou if (trunks[i]) 465a3cf59f5SSuanming Mou pool->cfg.free(trunks[i]); 466a3cf59f5SSuanming Mou } 467a3cf59f5SSuanming Mou if (!pool->trunks) 468a3cf59f5SSuanming Mou pool->cfg.free(pool->trunks); 469a3cf59f5SSuanming Mou mlx5_ipool_unlock(pool); 470*83c2047cSSuanming Mou mlx5_free(pool); 471a3cf59f5SSuanming Mou return 0; 472a3cf59f5SSuanming Mou } 473a3cf59f5SSuanming Mou 474a3cf59f5SSuanming Mou void 475a3cf59f5SSuanming Mou mlx5_ipool_dump(struct mlx5_indexed_pool *pool) 476a3cf59f5SSuanming Mou { 477a3cf59f5SSuanming Mou printf("Pool %s entry size %u, trunks %u, %d entry per trunk, " 478a3cf59f5SSuanming Mou "total: %d\n", 479a3cf59f5SSuanming Mou pool->cfg.type, pool->cfg.size, pool->n_trunk_valid, 480a3cf59f5SSuanming Mou pool->cfg.trunk_size, pool->n_trunk_valid); 481a3cf59f5SSuanming Mou #ifdef POOL_DEBUG 482a3cf59f5SSuanming Mou printf("Pool %s entry %u, trunk alloc %u, empty: %u, " 483a3cf59f5SSuanming Mou "available %u free %u\n", 484a3cf59f5SSuanming Mou pool->cfg.type, pool->n_entry, pool->trunk_new, 485a3cf59f5SSuanming Mou pool->trunk_empty, pool->trunk_avail, pool->trunk_free); 486a3cf59f5SSuanming Mou #endif 487a3cf59f5SSuanming Mou } 488bd81eaebSSuanming Mou 489bd81eaebSSuanming Mou struct mlx5_l3t_tbl * 490bd81eaebSSuanming Mou mlx5_l3t_create(enum mlx5_l3t_type type) 491bd81eaebSSuanming Mou { 492bd81eaebSSuanming Mou struct mlx5_l3t_tbl *tbl; 493bd81eaebSSuanming Mou struct mlx5_indexed_pool_config l3t_ip_cfg = { 494bd81eaebSSuanming Mou .trunk_size = 16, 495bd81eaebSSuanming Mou .grow_trunk = 6, 496bd81eaebSSuanming Mou .grow_shift = 1, 497bd81eaebSSuanming Mou .need_lock = 0, 498bd81eaebSSuanming Mou .release_mem_en = 1, 499*83c2047cSSuanming Mou .malloc = mlx5_malloc, 500*83c2047cSSuanming Mou .free = mlx5_free, 501bd81eaebSSuanming Mou }; 502bd81eaebSSuanming Mou 503bd81eaebSSuanming Mou if (type >= MLX5_L3T_TYPE_MAX) { 504bd81eaebSSuanming Mou rte_errno = EINVAL; 505bd81eaebSSuanming Mou return NULL; 506bd81eaebSSuanming Mou } 507*83c2047cSSuanming Mou tbl = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_l3t_tbl), 1, 508*83c2047cSSuanming Mou SOCKET_ID_ANY); 509bd81eaebSSuanming Mou if (!tbl) { 510bd81eaebSSuanming Mou rte_errno = ENOMEM; 511bd81eaebSSuanming Mou return NULL; 512bd81eaebSSuanming Mou } 513bd81eaebSSuanming Mou tbl->type = type; 514bd81eaebSSuanming Mou switch (type) { 515bd81eaebSSuanming Mou case MLX5_L3T_TYPE_WORD: 516bd81eaebSSuanming Mou l3t_ip_cfg.size = sizeof(struct mlx5_l3t_entry_word) + 517bd81eaebSSuanming Mou sizeof(uint16_t) * MLX5_L3T_ET_SIZE; 518bd81eaebSSuanming Mou l3t_ip_cfg.type = "mlx5_l3t_e_tbl_w"; 519bd81eaebSSuanming Mou break; 520bd81eaebSSuanming Mou case MLX5_L3T_TYPE_DWORD: 521bd81eaebSSuanming Mou l3t_ip_cfg.size = sizeof(struct mlx5_l3t_entry_dword) + 522bd81eaebSSuanming Mou sizeof(uint32_t) * MLX5_L3T_ET_SIZE; 523bd81eaebSSuanming Mou l3t_ip_cfg.type = "mlx5_l3t_e_tbl_dw"; 524bd81eaebSSuanming Mou break; 525bd81eaebSSuanming Mou case MLX5_L3T_TYPE_QWORD: 526bd81eaebSSuanming Mou l3t_ip_cfg.size = sizeof(struct mlx5_l3t_entry_qword) + 527bd81eaebSSuanming Mou sizeof(uint64_t) * MLX5_L3T_ET_SIZE; 528bd81eaebSSuanming Mou l3t_ip_cfg.type = "mlx5_l3t_e_tbl_qw"; 529bd81eaebSSuanming Mou break; 530bd81eaebSSuanming Mou default: 531bd81eaebSSuanming Mou l3t_ip_cfg.size = sizeof(struct mlx5_l3t_entry_ptr) + 532bd81eaebSSuanming Mou sizeof(void *) * MLX5_L3T_ET_SIZE; 533bd81eaebSSuanming Mou l3t_ip_cfg.type = "mlx5_l3t_e_tbl_tpr"; 534bd81eaebSSuanming Mou break; 535bd81eaebSSuanming Mou } 536bd81eaebSSuanming Mou tbl->eip = mlx5_ipool_create(&l3t_ip_cfg); 537bd81eaebSSuanming Mou if (!tbl->eip) { 538bd81eaebSSuanming Mou rte_errno = ENOMEM; 539*83c2047cSSuanming Mou mlx5_free(tbl); 540bd81eaebSSuanming Mou tbl = NULL; 541bd81eaebSSuanming Mou } 542bd81eaebSSuanming Mou return tbl; 543bd81eaebSSuanming Mou } 544bd81eaebSSuanming Mou 545bd81eaebSSuanming Mou void 546bd81eaebSSuanming Mou mlx5_l3t_destroy(struct mlx5_l3t_tbl *tbl) 547bd81eaebSSuanming Mou { 548bd81eaebSSuanming Mou struct mlx5_l3t_level_tbl *g_tbl, *m_tbl; 549bd81eaebSSuanming Mou uint32_t i, j; 550bd81eaebSSuanming Mou 551bd81eaebSSuanming Mou if (!tbl) 552bd81eaebSSuanming Mou return; 553bd81eaebSSuanming Mou g_tbl = tbl->tbl; 554bd81eaebSSuanming Mou if (g_tbl) { 555bd81eaebSSuanming Mou for (i = 0; i < MLX5_L3T_GT_SIZE; i++) { 556bd81eaebSSuanming Mou m_tbl = g_tbl->tbl[i]; 557bd81eaebSSuanming Mou if (!m_tbl) 558bd81eaebSSuanming Mou continue; 559bd81eaebSSuanming Mou for (j = 0; j < MLX5_L3T_MT_SIZE; j++) { 560bd81eaebSSuanming Mou if (!m_tbl->tbl[j]) 561bd81eaebSSuanming Mou continue; 562bd81eaebSSuanming Mou MLX5_ASSERT(!((struct mlx5_l3t_entry_word *) 563bd81eaebSSuanming Mou m_tbl->tbl[j])->ref_cnt); 564bd81eaebSSuanming Mou mlx5_ipool_free(tbl->eip, 565bd81eaebSSuanming Mou ((struct mlx5_l3t_entry_word *) 566bd81eaebSSuanming Mou m_tbl->tbl[j])->idx); 567bd81eaebSSuanming Mou m_tbl->tbl[j] = 0; 568bd81eaebSSuanming Mou if (!(--m_tbl->ref_cnt)) 569bd81eaebSSuanming Mou break; 570bd81eaebSSuanming Mou } 571bd81eaebSSuanming Mou MLX5_ASSERT(!m_tbl->ref_cnt); 572*83c2047cSSuanming Mou mlx5_free(g_tbl->tbl[i]); 573bd81eaebSSuanming Mou g_tbl->tbl[i] = 0; 574bd81eaebSSuanming Mou if (!(--g_tbl->ref_cnt)) 575bd81eaebSSuanming Mou break; 576bd81eaebSSuanming Mou } 577bd81eaebSSuanming Mou MLX5_ASSERT(!g_tbl->ref_cnt); 578*83c2047cSSuanming Mou mlx5_free(tbl->tbl); 579bd81eaebSSuanming Mou tbl->tbl = 0; 580bd81eaebSSuanming Mou } 581bd81eaebSSuanming Mou mlx5_ipool_destroy(tbl->eip); 582*83c2047cSSuanming Mou mlx5_free(tbl); 583bd81eaebSSuanming Mou } 584bd81eaebSSuanming Mou 585bd81eaebSSuanming Mou uint32_t 586bd81eaebSSuanming Mou mlx5_l3t_get_entry(struct mlx5_l3t_tbl *tbl, uint32_t idx, 587bd81eaebSSuanming Mou union mlx5_l3t_data *data) 588bd81eaebSSuanming Mou { 589bd81eaebSSuanming Mou struct mlx5_l3t_level_tbl *g_tbl, *m_tbl; 590bd81eaebSSuanming Mou void *e_tbl; 591bd81eaebSSuanming Mou uint32_t entry_idx; 592bd81eaebSSuanming Mou 593bd81eaebSSuanming Mou g_tbl = tbl->tbl; 594bd81eaebSSuanming Mou if (!g_tbl) 595bd81eaebSSuanming Mou return -1; 596bd81eaebSSuanming Mou m_tbl = g_tbl->tbl[(idx >> MLX5_L3T_GT_OFFSET) & MLX5_L3T_GT_MASK]; 597bd81eaebSSuanming Mou if (!m_tbl) 598bd81eaebSSuanming Mou return -1; 599bd81eaebSSuanming Mou e_tbl = m_tbl->tbl[(idx >> MLX5_L3T_MT_OFFSET) & MLX5_L3T_MT_MASK]; 600bd81eaebSSuanming Mou if (!e_tbl) 601bd81eaebSSuanming Mou return -1; 602bd81eaebSSuanming Mou entry_idx = idx & MLX5_L3T_ET_MASK; 603bd81eaebSSuanming Mou switch (tbl->type) { 604bd81eaebSSuanming Mou case MLX5_L3T_TYPE_WORD: 605bd81eaebSSuanming Mou data->word = ((struct mlx5_l3t_entry_word *)e_tbl)->entry 606bd81eaebSSuanming Mou [entry_idx]; 607bd81eaebSSuanming Mou break; 608bd81eaebSSuanming Mou case MLX5_L3T_TYPE_DWORD: 609bd81eaebSSuanming Mou data->dword = ((struct mlx5_l3t_entry_dword *)e_tbl)->entry 610bd81eaebSSuanming Mou [entry_idx]; 611bd81eaebSSuanming Mou break; 612bd81eaebSSuanming Mou case MLX5_L3T_TYPE_QWORD: 613bd81eaebSSuanming Mou data->qword = ((struct mlx5_l3t_entry_qword *)e_tbl)->entry 614bd81eaebSSuanming Mou [entry_idx]; 615bd81eaebSSuanming Mou break; 616bd81eaebSSuanming Mou default: 617bd81eaebSSuanming Mou data->ptr = ((struct mlx5_l3t_entry_ptr *)e_tbl)->entry 618bd81eaebSSuanming Mou [entry_idx]; 619bd81eaebSSuanming Mou break; 620bd81eaebSSuanming Mou } 621bd81eaebSSuanming Mou return 0; 622bd81eaebSSuanming Mou } 623bd81eaebSSuanming Mou 624bd81eaebSSuanming Mou void 625bd81eaebSSuanming Mou mlx5_l3t_clear_entry(struct mlx5_l3t_tbl *tbl, uint32_t idx) 626bd81eaebSSuanming Mou { 627bd81eaebSSuanming Mou struct mlx5_l3t_level_tbl *g_tbl, *m_tbl; 628bd81eaebSSuanming Mou struct mlx5_l3t_entry_word *w_e_tbl; 629bd81eaebSSuanming Mou struct mlx5_l3t_entry_dword *dw_e_tbl; 630bd81eaebSSuanming Mou struct mlx5_l3t_entry_qword *qw_e_tbl; 631bd81eaebSSuanming Mou struct mlx5_l3t_entry_ptr *ptr_e_tbl; 632bd81eaebSSuanming Mou void *e_tbl; 633bd81eaebSSuanming Mou uint32_t entry_idx; 634bd81eaebSSuanming Mou uint64_t ref_cnt; 635bd81eaebSSuanming Mou 636bd81eaebSSuanming Mou g_tbl = tbl->tbl; 637bd81eaebSSuanming Mou if (!g_tbl) 638bd81eaebSSuanming Mou return; 639bd81eaebSSuanming Mou m_tbl = g_tbl->tbl[(idx >> MLX5_L3T_GT_OFFSET) & MLX5_L3T_GT_MASK]; 640bd81eaebSSuanming Mou if (!m_tbl) 641bd81eaebSSuanming Mou return; 642bd81eaebSSuanming Mou e_tbl = m_tbl->tbl[(idx >> MLX5_L3T_MT_OFFSET) & MLX5_L3T_MT_MASK]; 643bd81eaebSSuanming Mou if (!e_tbl) 644bd81eaebSSuanming Mou return; 645bd81eaebSSuanming Mou entry_idx = idx & MLX5_L3T_ET_MASK; 646bd81eaebSSuanming Mou switch (tbl->type) { 647bd81eaebSSuanming Mou case MLX5_L3T_TYPE_WORD: 648bd81eaebSSuanming Mou w_e_tbl = (struct mlx5_l3t_entry_word *)e_tbl; 649bd81eaebSSuanming Mou w_e_tbl->entry[entry_idx] = 0; 650bd81eaebSSuanming Mou ref_cnt = --w_e_tbl->ref_cnt; 651bd81eaebSSuanming Mou break; 652bd81eaebSSuanming Mou case MLX5_L3T_TYPE_DWORD: 653bd81eaebSSuanming Mou dw_e_tbl = (struct mlx5_l3t_entry_dword *)e_tbl; 654bd81eaebSSuanming Mou dw_e_tbl->entry[entry_idx] = 0; 655bd81eaebSSuanming Mou ref_cnt = --dw_e_tbl->ref_cnt; 656bd81eaebSSuanming Mou break; 657bd81eaebSSuanming Mou case MLX5_L3T_TYPE_QWORD: 658bd81eaebSSuanming Mou qw_e_tbl = (struct mlx5_l3t_entry_qword *)e_tbl; 659bd81eaebSSuanming Mou qw_e_tbl->entry[entry_idx] = 0; 660bd81eaebSSuanming Mou ref_cnt = --qw_e_tbl->ref_cnt; 661bd81eaebSSuanming Mou break; 662bd81eaebSSuanming Mou default: 663bd81eaebSSuanming Mou ptr_e_tbl = (struct mlx5_l3t_entry_ptr *)e_tbl; 664bd81eaebSSuanming Mou ptr_e_tbl->entry[entry_idx] = NULL; 665bd81eaebSSuanming Mou ref_cnt = --ptr_e_tbl->ref_cnt; 666bd81eaebSSuanming Mou break; 667bd81eaebSSuanming Mou } 668bd81eaebSSuanming Mou if (!ref_cnt) { 669bd81eaebSSuanming Mou mlx5_ipool_free(tbl->eip, 670bd81eaebSSuanming Mou ((struct mlx5_l3t_entry_word *)e_tbl)->idx); 671bd81eaebSSuanming Mou m_tbl->tbl[(idx >> MLX5_L3T_MT_OFFSET) & MLX5_L3T_MT_MASK] = 672bd81eaebSSuanming Mou NULL; 673bd81eaebSSuanming Mou if (!(--m_tbl->ref_cnt)) { 674*83c2047cSSuanming Mou mlx5_free(m_tbl); 675bd81eaebSSuanming Mou g_tbl->tbl 676bd81eaebSSuanming Mou [(idx >> MLX5_L3T_GT_OFFSET) & MLX5_L3T_GT_MASK] = NULL; 677bd81eaebSSuanming Mou if (!(--g_tbl->ref_cnt)) { 678*83c2047cSSuanming Mou mlx5_free(g_tbl); 679bd81eaebSSuanming Mou tbl->tbl = 0; 680bd81eaebSSuanming Mou } 681bd81eaebSSuanming Mou } 682bd81eaebSSuanming Mou } 683bd81eaebSSuanming Mou } 684bd81eaebSSuanming Mou 685bd81eaebSSuanming Mou uint32_t 686bd81eaebSSuanming Mou mlx5_l3t_set_entry(struct mlx5_l3t_tbl *tbl, uint32_t idx, 687bd81eaebSSuanming Mou union mlx5_l3t_data *data) 688bd81eaebSSuanming Mou { 689bd81eaebSSuanming Mou struct mlx5_l3t_level_tbl *g_tbl, *m_tbl; 690bd81eaebSSuanming Mou struct mlx5_l3t_entry_word *w_e_tbl; 691bd81eaebSSuanming Mou struct mlx5_l3t_entry_dword *dw_e_tbl; 692bd81eaebSSuanming Mou struct mlx5_l3t_entry_qword *qw_e_tbl; 693bd81eaebSSuanming Mou struct mlx5_l3t_entry_ptr *ptr_e_tbl; 694bd81eaebSSuanming Mou void *e_tbl; 695bd81eaebSSuanming Mou uint32_t entry_idx, tbl_idx = 0; 696bd81eaebSSuanming Mou 697bd81eaebSSuanming Mou /* Check the global table, create it if empty. */ 698bd81eaebSSuanming Mou g_tbl = tbl->tbl; 699bd81eaebSSuanming Mou if (!g_tbl) { 700*83c2047cSSuanming Mou g_tbl = mlx5_malloc(MLX5_MEM_ZERO, 701*83c2047cSSuanming Mou sizeof(struct mlx5_l3t_level_tbl) + 702*83c2047cSSuanming Mou sizeof(void *) * MLX5_L3T_GT_SIZE, 1, 703*83c2047cSSuanming Mou SOCKET_ID_ANY); 704bd81eaebSSuanming Mou if (!g_tbl) { 705bd81eaebSSuanming Mou rte_errno = ENOMEM; 706bd81eaebSSuanming Mou return -1; 707bd81eaebSSuanming Mou } 708bd81eaebSSuanming Mou tbl->tbl = g_tbl; 709bd81eaebSSuanming Mou } 710bd81eaebSSuanming Mou /* 711bd81eaebSSuanming Mou * Check the middle table, create it if empty. Ref_cnt will be 712bd81eaebSSuanming Mou * increased if new sub table created. 713bd81eaebSSuanming Mou */ 714bd81eaebSSuanming Mou m_tbl = g_tbl->tbl[(idx >> MLX5_L3T_GT_OFFSET) & MLX5_L3T_GT_MASK]; 715bd81eaebSSuanming Mou if (!m_tbl) { 716*83c2047cSSuanming Mou m_tbl = mlx5_malloc(MLX5_MEM_ZERO, 717*83c2047cSSuanming Mou sizeof(struct mlx5_l3t_level_tbl) + 718*83c2047cSSuanming Mou sizeof(void *) * MLX5_L3T_MT_SIZE, 1, 719*83c2047cSSuanming Mou SOCKET_ID_ANY); 720bd81eaebSSuanming Mou if (!m_tbl) { 721bd81eaebSSuanming Mou rte_errno = ENOMEM; 722bd81eaebSSuanming Mou return -1; 723bd81eaebSSuanming Mou } 724bd81eaebSSuanming Mou g_tbl->tbl[(idx >> MLX5_L3T_GT_OFFSET) & MLX5_L3T_GT_MASK] = 725bd81eaebSSuanming Mou m_tbl; 726bd81eaebSSuanming Mou g_tbl->ref_cnt++; 727bd81eaebSSuanming Mou } 728bd81eaebSSuanming Mou /* 729bd81eaebSSuanming Mou * Check the entry table, create it if empty. Ref_cnt will be 730bd81eaebSSuanming Mou * increased if new sub entry table created. 731bd81eaebSSuanming Mou */ 732bd81eaebSSuanming Mou e_tbl = m_tbl->tbl[(idx >> MLX5_L3T_MT_OFFSET) & MLX5_L3T_MT_MASK]; 733bd81eaebSSuanming Mou if (!e_tbl) { 734bd81eaebSSuanming Mou e_tbl = mlx5_ipool_zmalloc(tbl->eip, &tbl_idx); 735bd81eaebSSuanming Mou if (!e_tbl) { 736bd81eaebSSuanming Mou rte_errno = ENOMEM; 737bd81eaebSSuanming Mou return -1; 738bd81eaebSSuanming Mou } 739bd81eaebSSuanming Mou ((struct mlx5_l3t_entry_word *)e_tbl)->idx = tbl_idx; 740bd81eaebSSuanming Mou m_tbl->tbl[(idx >> MLX5_L3T_MT_OFFSET) & MLX5_L3T_MT_MASK] = 741bd81eaebSSuanming Mou e_tbl; 742bd81eaebSSuanming Mou m_tbl->ref_cnt++; 743bd81eaebSSuanming Mou } 744bd81eaebSSuanming Mou entry_idx = idx & MLX5_L3T_ET_MASK; 745bd81eaebSSuanming Mou switch (tbl->type) { 746bd81eaebSSuanming Mou case MLX5_L3T_TYPE_WORD: 747bd81eaebSSuanming Mou w_e_tbl = (struct mlx5_l3t_entry_word *)e_tbl; 748bd81eaebSSuanming Mou w_e_tbl->entry[entry_idx] = data->word; 749bd81eaebSSuanming Mou w_e_tbl->ref_cnt++; 750bd81eaebSSuanming Mou break; 751bd81eaebSSuanming Mou case MLX5_L3T_TYPE_DWORD: 752bd81eaebSSuanming Mou dw_e_tbl = (struct mlx5_l3t_entry_dword *)e_tbl; 753bd81eaebSSuanming Mou dw_e_tbl->entry[entry_idx] = data->dword; 754bd81eaebSSuanming Mou dw_e_tbl->ref_cnt++; 755bd81eaebSSuanming Mou break; 756bd81eaebSSuanming Mou case MLX5_L3T_TYPE_QWORD: 757bd81eaebSSuanming Mou qw_e_tbl = (struct mlx5_l3t_entry_qword *)e_tbl; 758bd81eaebSSuanming Mou qw_e_tbl->entry[entry_idx] = data->qword; 759bd81eaebSSuanming Mou qw_e_tbl->ref_cnt++; 760bd81eaebSSuanming Mou break; 761bd81eaebSSuanming Mou default: 762bd81eaebSSuanming Mou ptr_e_tbl = (struct mlx5_l3t_entry_ptr *)e_tbl; 763bd81eaebSSuanming Mou ptr_e_tbl->entry[entry_idx] = data->ptr; 764bd81eaebSSuanming Mou ptr_e_tbl->ref_cnt++; 765bd81eaebSSuanming Mou break; 766bd81eaebSSuanming Mou } 767bd81eaebSSuanming Mou return 0; 768bd81eaebSSuanming Mou } 769