X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_utils.c;h=07373bff02392f32730d43f5a9b87ab34a25e99a;hb=9b9890e20dc4541fd06bc5666e5fb8a507dfb3e9;hp=13590dd0d1bce6bac2d8b731355828e203dc5c55;hpb=a12c188b858d99ab6ba4a33b79115c578e533f00;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_utils.c b/drivers/net/mlx5/mlx5_utils.c index 13590dd0d1..07373bff02 100644 --- a/drivers/net/mlx5/mlx5_utils.c +++ b/drivers/net/mlx5/mlx5_utils.c @@ -25,14 +25,6 @@ mlx5_hlist_default_remove_cb(struct mlx5_hlist *h __rte_unused, mlx5_free(entry); } -static int -mlx5_hlist_default_match_cb(struct mlx5_hlist *h __rte_unused, - struct mlx5_hlist_entry *entry, - uint64_t key, void *ctx __rte_unused) -{ - return entry->key != key; -} - struct mlx5_hlist * mlx5_hlist_create(const char *name, uint32_t size, uint32_t entry_size, uint32_t flags, mlx5_hlist_create_cb cb_create, @@ -41,8 +33,9 @@ mlx5_hlist_create(const char *name, uint32_t size, uint32_t entry_size, struct mlx5_hlist *h; uint32_t act_size; uint32_t alloc_size; + uint32_t i; - if (!size || (!cb_create ^ !cb_remove)) + if (!size || !cb_match || (!cb_create ^ !cb_remove)) return NULL; /* Align to the next power of 2, 32bits integer is enough now. */ if (!rte_is_power_of_2(size)) { @@ -53,7 +46,7 @@ mlx5_hlist_create(const char *name, uint32_t size, uint32_t entry_size, act_size = size; } alloc_size = sizeof(struct mlx5_hlist) + - sizeof(struct mlx5_hlist_head) * act_size; + sizeof(struct mlx5_hlist_bucket) * act_size; /* Using zmalloc, then no need to initialize the heads. */ h = mlx5_malloc(MLX5_MEM_ZERO, alloc_size, RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); @@ -70,27 +63,24 @@ mlx5_hlist_create(const char *name, uint32_t size, uint32_t entry_size, h->direct_key = !!(flags & MLX5_HLIST_DIRECT_KEY); h->write_most = !!(flags & MLX5_HLIST_WRITE_MOST); h->cb_create = cb_create ? cb_create : mlx5_hlist_default_create_cb; - h->cb_match = cb_match ? cb_match : mlx5_hlist_default_match_cb; + h->cb_match = cb_match; h->cb_remove = cb_remove ? cb_remove : mlx5_hlist_default_remove_cb; - rte_rwlock_init(&h->lock); + for (i = 0; i < act_size; i++) + rte_rwlock_init(&h->buckets[i].lock); DRV_LOG(DEBUG, "Hash list with %s size 0x%" PRIX32 " is created.", h->name, act_size); return h; } static struct mlx5_hlist_entry * -__hlist_lookup(struct mlx5_hlist *h, uint64_t key, void *ctx, bool reuse) +__hlist_lookup(struct mlx5_hlist *h, uint64_t key, uint32_t idx, + void *ctx, bool reuse) { - uint32_t idx; struct mlx5_hlist_head *first; struct mlx5_hlist_entry *node; MLX5_ASSERT(h); - if (h->direct_key) - idx = (uint32_t)(key & h->mask); - else - idx = rte_hash_crc_8byte(key, 0) & h->mask; - first = &h->heads[idx]; + first = &h->buckets[idx].head; LIST_FOREACH(node, first, next) { if (!h->cb_match(h, node, key, ctx)) { if (reuse) { @@ -107,21 +97,28 @@ __hlist_lookup(struct mlx5_hlist *h, uint64_t key, void *ctx, bool reuse) } static struct mlx5_hlist_entry * -hlist_lookup(struct mlx5_hlist *h, uint64_t key, void *ctx, bool reuse) +hlist_lookup(struct mlx5_hlist *h, uint64_t key, uint32_t idx, + void *ctx, bool reuse) { struct mlx5_hlist_entry *node; MLX5_ASSERT(h); - rte_rwlock_read_lock(&h->lock); - node = __hlist_lookup(h, key, ctx, reuse); - rte_rwlock_read_unlock(&h->lock); + rte_rwlock_read_lock(&h->buckets[idx].lock); + node = __hlist_lookup(h, key, idx, ctx, reuse); + rte_rwlock_read_unlock(&h->buckets[idx].lock); return node; } struct mlx5_hlist_entry * mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key, void *ctx) { - return hlist_lookup(h, key, ctx, false); + uint32_t idx; + + if (h->direct_key) + idx = (uint32_t)(key & h->mask); + else + idx = rte_hash_crc_8byte(key, 0) & h->mask; + return hlist_lookup(h, key, idx, ctx, false); } struct mlx5_hlist_entry* @@ -129,63 +126,67 @@ mlx5_hlist_register(struct mlx5_hlist *h, uint64_t key, void *ctx) { uint32_t idx; struct mlx5_hlist_head *first; + struct mlx5_hlist_bucket *b; struct mlx5_hlist_entry *entry; uint32_t prev_gen_cnt = 0; - MLX5_ASSERT(h && entry); + if (h->direct_key) + idx = (uint32_t)(key & h->mask); + else + idx = rte_hash_crc_8byte(key, 0) & h->mask; + MLX5_ASSERT(h); + b = &h->buckets[idx]; /* Use write lock directly for write-most list. */ if (!h->write_most) { - prev_gen_cnt = __atomic_load_n(&h->gen_cnt, __ATOMIC_ACQUIRE); - entry = hlist_lookup(h, key, ctx, true); + prev_gen_cnt = __atomic_load_n(&b->gen_cnt, __ATOMIC_ACQUIRE); + entry = hlist_lookup(h, key, idx, ctx, true); if (entry) return entry; } - rte_rwlock_write_lock(&h->lock); + rte_rwlock_write_lock(&b->lock); /* Check if the list changed by other threads. */ if (h->write_most || - prev_gen_cnt != __atomic_load_n(&h->gen_cnt, __ATOMIC_ACQUIRE)) { - entry = __hlist_lookup(h, key, ctx, true); + prev_gen_cnt != __atomic_load_n(&b->gen_cnt, __ATOMIC_ACQUIRE)) { + entry = __hlist_lookup(h, key, idx, ctx, true); if (entry) goto done; } - if (h->direct_key) - idx = (uint32_t)(key & h->mask); - else - idx = rte_hash_crc_8byte(key, 0) & h->mask; - first = &h->heads[idx]; + first = &b->head; entry = h->cb_create(h, key, ctx); if (!entry) { rte_errno = ENOMEM; - DRV_LOG(ERR, "Can't allocate hash list %s entry.", h->name); + DRV_LOG(DEBUG, "Can't allocate hash list %s entry.", h->name); goto done; } - entry->key = key; + entry->idx = idx; entry->ref_cnt = 1; LIST_INSERT_HEAD(first, entry, next); - __atomic_add_fetch(&h->gen_cnt, 1, __ATOMIC_ACQ_REL); + __atomic_add_fetch(&b->gen_cnt, 1, __ATOMIC_ACQ_REL); DRV_LOG(DEBUG, "Hash list %s entry %p new: %u.", h->name, (void *)entry, entry->ref_cnt); done: - rte_rwlock_write_unlock(&h->lock); + rte_rwlock_write_unlock(&b->lock); return entry; } int mlx5_hlist_unregister(struct mlx5_hlist *h, struct mlx5_hlist_entry *entry) { - rte_rwlock_write_lock(&h->lock); + uint32_t idx = entry->idx; + + rte_rwlock_write_lock(&h->buckets[idx].lock); MLX5_ASSERT(entry && entry->ref_cnt && entry->next.le_prev); DRV_LOG(DEBUG, "Hash list %s entry %p deref: %u.", h->name, (void *)entry, entry->ref_cnt); if (--entry->ref_cnt) { - rte_rwlock_write_unlock(&h->lock); + rte_rwlock_write_unlock(&h->buckets[idx].lock); return 1; } LIST_REMOVE(entry, next); /* Set to NULL to get rid of removing action for more than once. */ entry->next.le_prev = NULL; h->cb_remove(h, entry); - rte_rwlock_write_unlock(&h->lock); + rte_rwlock_write_unlock(&h->buckets[idx].lock); DRV_LOG(DEBUG, "Hash list %s entry %p removed.", h->name, (void *)entry); return 0; @@ -200,8 +201,8 @@ mlx5_hlist_destroy(struct mlx5_hlist *h) MLX5_ASSERT(h); for (idx = 0; idx < h->table_sz; ++idx) { /* No LIST_FOREACH_SAFE, using while instead. */ - while (!LIST_EMPTY(&h->heads[idx])) { - entry = LIST_FIRST(&h->heads[idx]); + while (!LIST_EMPTY(&h->buckets[idx].head)) { + entry = LIST_FIRST(&h->buckets[idx].head); LIST_REMOVE(entry, next); /* * The owner of whole element which contains data entry