xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_gen_hash.c (revision b14da6540294be2ecae13b69dbe0b00f93bcc597)
10001cc58SKishore Padmanabha /* SPDX-License-Identifier: BSD-3-Clause
2e6e8f03eSRandy Schacher  * Copyright(c) 2014-2023 Broadcom
30001cc58SKishore Padmanabha  * All rights reserved.
40001cc58SKishore Padmanabha  */
50001cc58SKishore Padmanabha 
6191128d7SDavid Marchand #include <rte_bitops.h>
70001cc58SKishore Padmanabha #include <rte_log.h>
80001cc58SKishore Padmanabha #include <rte_malloc.h>
9*b14da654SPeter Spreadborough #include <rte_hash_crc.h>
10191128d7SDavid Marchand 
110001cc58SKishore Padmanabha #include "bnxt_tf_common.h"
120001cc58SKishore Padmanabha #include "ulp_gen_hash.h"
130001cc58SKishore Padmanabha #include "ulp_utils.h"
140001cc58SKishore Padmanabha 
150001cc58SKishore Padmanabha static
160001cc58SKishore Padmanabha int32_t ulp_bit_alloc_list_alloc(struct bit_alloc_list *blist,
170001cc58SKishore Padmanabha 				 uint32_t *index)
180001cc58SKishore Padmanabha {
190001cc58SKishore Padmanabha 	uint64_t bentry;
200001cc58SKishore Padmanabha 	uint32_t idx = 0, jdx = 0;
21a738cbfeSKishore Padmanabha 	uint32_t bsize_64 = blist->bsize / ULP_64B_IN_BYTES;
220001cc58SKishore Padmanabha 
230001cc58SKishore Padmanabha 	/* Iterate all numbers that have all 1's */
240001cc58SKishore Padmanabha 	do {
250001cc58SKishore Padmanabha 		bentry = blist->bdata[idx++];
26a738cbfeSKishore Padmanabha 	} while (bentry == -1UL && idx <= bsize_64);
270001cc58SKishore Padmanabha 
28a738cbfeSKishore Padmanabha 	if (idx <= bsize_64) {
290001cc58SKishore Padmanabha 		if (bentry)
30191128d7SDavid Marchand 			jdx = rte_clz64(~bentry);
310001cc58SKishore Padmanabha 		*index = ((idx - 1) * ULP_INDEX_BITMAP_SIZE) + jdx;
320001cc58SKishore Padmanabha 		ULP_INDEX_BITMAP_SET(blist->bdata[(idx - 1)], jdx);
330001cc58SKishore Padmanabha 		return 0;
340001cc58SKishore Padmanabha 	}
35a738cbfeSKishore Padmanabha 	jdx = (uint32_t)(bsize_64 * ULP_INDEX_BITMAP_SIZE);
36dd0191d5SShuanglin Wang 	BNXT_DRV_DBG(ERR, "bit allocator is full reached max:%x\n", jdx);
370001cc58SKishore Padmanabha 	return -1;
380001cc58SKishore Padmanabha }
390001cc58SKishore Padmanabha 
400001cc58SKishore Padmanabha static
410001cc58SKishore Padmanabha int32_t ulp_bit_alloc_list_dealloc(struct bit_alloc_list *blist,
420001cc58SKishore Padmanabha 				   uint32_t index)
430001cc58SKishore Padmanabha {
440001cc58SKishore Padmanabha 	uint32_t idx = 0, jdx;
45a738cbfeSKishore Padmanabha 	uint32_t bsize_64 = blist->bsize / ULP_64B_IN_BYTES;
460001cc58SKishore Padmanabha 
470001cc58SKishore Padmanabha 	idx = index / ULP_INDEX_BITMAP_SIZE;
48a738cbfeSKishore Padmanabha 	if (idx >= bsize_64) {
49dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid bit index %x:%x\n", idx,
500001cc58SKishore Padmanabha 			     blist->bsize);
510001cc58SKishore Padmanabha 		return -EINVAL;
520001cc58SKishore Padmanabha 	}
530001cc58SKishore Padmanabha 	jdx = index % ULP_INDEX_BITMAP_SIZE;
540001cc58SKishore Padmanabha 	ULP_INDEX_BITMAP_RESET(blist->bdata[idx], jdx);
550001cc58SKishore Padmanabha 	return 0;
560001cc58SKishore Padmanabha }
570001cc58SKishore Padmanabha 
580001cc58SKishore Padmanabha /*
590001cc58SKishore Padmanabha  * Initialize the Generic Hash table
600001cc58SKishore Padmanabha  *
610001cc58SKishore Padmanabha  * cparams [in] Pointer to hash create params list
620001cc58SKishore Padmanabha  * hash_tbl [out] the pointer to created hash table
630001cc58SKishore Padmanabha  *
640001cc58SKishore Padmanabha  * returns 0 on success
650001cc58SKishore Padmanabha  */
660001cc58SKishore Padmanabha int32_t
670001cc58SKishore Padmanabha ulp_gen_hash_tbl_list_init(struct ulp_hash_create_params *cparams,
680001cc58SKishore Padmanabha 			   struct ulp_gen_hash_tbl **hash_table)
690001cc58SKishore Padmanabha {
700001cc58SKishore Padmanabha 	struct ulp_gen_hash_tbl *hash_tbl = NULL;
710001cc58SKishore Padmanabha 	int32_t rc = 0;
720001cc58SKishore Padmanabha 	uint32_t size = 0;
730001cc58SKishore Padmanabha 
740001cc58SKishore Padmanabha 	/* validate the arguments */
750001cc58SKishore Padmanabha 	if (!hash_table || !cparams) {
76dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid arguments\n");
770001cc58SKishore Padmanabha 		return -EINVAL;
780001cc58SKishore Padmanabha 	}
790001cc58SKishore Padmanabha 
800001cc58SKishore Padmanabha 	/* validate the size parameters */
810001cc58SKishore Padmanabha 	if (ulp_util_is_power_of_2(cparams->num_hash_tbl_entries) ||
820001cc58SKishore Padmanabha 	    ulp_util_is_power_of_2(cparams->num_key_entries) ||
830001cc58SKishore Padmanabha 	    (cparams->num_buckets % ULP_HASH_BUCKET_ROW_SZ)) {
84dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid arguments for hash tbl\n");
850001cc58SKishore Padmanabha 		return -EINVAL;
860001cc58SKishore Padmanabha 	}
870001cc58SKishore Padmanabha 
880001cc58SKishore Padmanabha 	/* validate the size of the hash table size */
890001cc58SKishore Padmanabha 	if (cparams->num_hash_tbl_entries >= ULP_GEN_HASH_MAX_TBL_SIZE) {
90dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid size for hash tbl\n");
910001cc58SKishore Padmanabha 		return -EINVAL;
920001cc58SKishore Padmanabha 	}
930001cc58SKishore Padmanabha 
940001cc58SKishore Padmanabha 	hash_tbl = rte_zmalloc("Generic hash table",
950001cc58SKishore Padmanabha 			       sizeof(struct ulp_gen_hash_tbl), 0);
960001cc58SKishore Padmanabha 	if (!hash_tbl) {
97dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to alloc mem for hash tbl\n");
980001cc58SKishore Padmanabha 		return -ENOMEM;
990001cc58SKishore Padmanabha 	}
1000001cc58SKishore Padmanabha 	*hash_table = hash_tbl;
1010001cc58SKishore Padmanabha 	/* allocate the memory for the hash key table */
1020001cc58SKishore Padmanabha 	hash_tbl->num_key_entries = cparams->num_key_entries;
1030001cc58SKishore Padmanabha 	hash_tbl->key_tbl.data_size = cparams->key_size;
1040001cc58SKishore Padmanabha 	hash_tbl->key_tbl.mem_size = cparams->key_size *
1050001cc58SKishore Padmanabha 		(cparams->num_key_entries + 1);
1060001cc58SKishore Padmanabha 	hash_tbl->key_tbl.key_data = rte_zmalloc("Generic hash keys",
1070001cc58SKishore Padmanabha 						 hash_tbl->key_tbl.mem_size, 0);
1080001cc58SKishore Padmanabha 	if (!hash_tbl->key_tbl.key_data) {
109dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to alloc mem for hash key\n");
1100001cc58SKishore Padmanabha 		rc = -ENOMEM;
1110001cc58SKishore Padmanabha 		goto init_error;
1120001cc58SKishore Padmanabha 	}
1130001cc58SKishore Padmanabha 
1140001cc58SKishore Padmanabha 	/* allocate the memory for the hash table */
1150001cc58SKishore Padmanabha 	hash_tbl->hash_bkt_num = cparams->num_buckets / ULP_HASH_BUCKET_ROW_SZ;
1160001cc58SKishore Padmanabha 	hash_tbl->hash_tbl_size = cparams->num_hash_tbl_entries;
1170001cc58SKishore Padmanabha 	size = hash_tbl->hash_tbl_size * hash_tbl->hash_bkt_num *
1180001cc58SKishore Padmanabha 		sizeof(struct ulp_hash_bucket_entry);
1190001cc58SKishore Padmanabha 	hash_tbl->hash_list = rte_zmalloc("Generic hash table list", size,
1200001cc58SKishore Padmanabha 					  ULP_BUFFER_ALIGN_64_BYTE);
1210001cc58SKishore Padmanabha 	if (!hash_tbl->hash_list) {
122dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to alloc mem for hash tbl\n");
1230001cc58SKishore Padmanabha 		rc = -ENOMEM;
1240001cc58SKishore Padmanabha 		goto init_error;
1250001cc58SKishore Padmanabha 	}
1260001cc58SKishore Padmanabha 
1270001cc58SKishore Padmanabha 	/* calculate the hash_mask based on the tbl size */
1280001cc58SKishore Padmanabha 	size = 1;
1290001cc58SKishore Padmanabha 	while (size < hash_tbl->hash_tbl_size)
1300001cc58SKishore Padmanabha 		size = size << 1;
1310001cc58SKishore Padmanabha 	hash_tbl->hash_mask = size - 1;
1320001cc58SKishore Padmanabha 
1330001cc58SKishore Padmanabha 	/* allocate the memory for the bit allocator */
134a738cbfeSKishore Padmanabha 	size = (cparams->num_key_entries / sizeof(uint64_t));
135a738cbfeSKishore Padmanabha 	size = ULP_BYTE_ROUND_OFF_8(size);
1360001cc58SKishore Padmanabha 	hash_tbl->bit_list.bsize = size;
1370001cc58SKishore Padmanabha 	hash_tbl->bit_list.bdata = rte_zmalloc("Generic hash bit alloc", size,
1380001cc58SKishore Padmanabha 					       ULP_BUFFER_ALIGN_64_BYTE);
1390001cc58SKishore Padmanabha 	if (!hash_tbl->bit_list.bdata) {
140dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "failed to alloc mem for hash bit list\n");
1410001cc58SKishore Padmanabha 		rc = -ENOMEM;
1420001cc58SKishore Padmanabha 		goto init_error;
1430001cc58SKishore Padmanabha 	}
1440001cc58SKishore Padmanabha 	return rc;
1450001cc58SKishore Padmanabha 
1460001cc58SKishore Padmanabha init_error:
1470001cc58SKishore Padmanabha 	if (hash_tbl)
1480001cc58SKishore Padmanabha 		ulp_gen_hash_tbl_list_deinit(hash_tbl);
1490001cc58SKishore Padmanabha 	return rc;
1500001cc58SKishore Padmanabha }
1510001cc58SKishore Padmanabha 
1520001cc58SKishore Padmanabha /*
1530001cc58SKishore Padmanabha  * Free the generic hash table
1540001cc58SKishore Padmanabha  *
1550001cc58SKishore Padmanabha  * hash_tbl [in] the pointer to hash table
1560001cc58SKishore Padmanabha  *
1570001cc58SKishore Padmanabha  * returns 0 on success
1580001cc58SKishore Padmanabha  */
1590001cc58SKishore Padmanabha int32_t
1600001cc58SKishore Padmanabha ulp_gen_hash_tbl_list_deinit(struct ulp_gen_hash_tbl *hash_tbl)
1610001cc58SKishore Padmanabha {
1620001cc58SKishore Padmanabha 	if (!hash_tbl)
1630001cc58SKishore Padmanabha 		return -EINVAL;
1640001cc58SKishore Padmanabha 
1650001cc58SKishore Padmanabha 	if (hash_tbl->key_tbl.key_data) {
1660001cc58SKishore Padmanabha 		rte_free(hash_tbl->key_tbl.key_data);
1670001cc58SKishore Padmanabha 		hash_tbl->key_tbl.key_data = NULL;
1680001cc58SKishore Padmanabha 	}
1690001cc58SKishore Padmanabha 
1700001cc58SKishore Padmanabha 	if (hash_tbl->hash_list) {
1710001cc58SKishore Padmanabha 		rte_free(hash_tbl->hash_list);
1720001cc58SKishore Padmanabha 		hash_tbl->hash_list = NULL;
1730001cc58SKishore Padmanabha 	}
1740001cc58SKishore Padmanabha 
1750001cc58SKishore Padmanabha 	if (hash_tbl->bit_list.bdata) {
1760001cc58SKishore Padmanabha 		rte_free(hash_tbl->bit_list.bdata);
1770001cc58SKishore Padmanabha 		hash_tbl->bit_list.bdata = NULL;
1780001cc58SKishore Padmanabha 	}
1790001cc58SKishore Padmanabha 
1800001cc58SKishore Padmanabha 	rte_free(hash_tbl);
1810001cc58SKishore Padmanabha 	return 0;
1820001cc58SKishore Padmanabha }
1830001cc58SKishore Padmanabha 
1840001cc58SKishore Padmanabha /*
1850001cc58SKishore Padmanabha  * Search the generic hash table using key data
1860001cc58SKishore Padmanabha  *
1870001cc58SKishore Padmanabha  * hash_tbl [in] the pointer to hash table
1880001cc58SKishore Padmanabha  * entry [in/out] pointer to hash entry details.
1890001cc58SKishore Padmanabha  *
1900001cc58SKishore Padmanabha  * returns 0 on success and marks search flag as found.
1910001cc58SKishore Padmanabha  */
1920001cc58SKishore Padmanabha int32_t
1930001cc58SKishore Padmanabha ulp_gen_hash_tbl_list_key_search(struct ulp_gen_hash_tbl *hash_tbl,
1940001cc58SKishore Padmanabha 				 struct ulp_gen_hash_entry_params *entry)
1950001cc58SKishore Padmanabha {
1960001cc58SKishore Padmanabha 	uint32_t hash_id, key_idx, idx;
1970001cc58SKishore Padmanabha 	uint16_t *bucket;
1980001cc58SKishore Padmanabha 	int32_t miss_idx = ULP_HASH_BUCKET_INVAL;
1990001cc58SKishore Padmanabha 
2000001cc58SKishore Padmanabha 	/* validate the arguments */
2010001cc58SKishore Padmanabha 	if (!hash_tbl || !entry || !entry->key_data || entry->key_length !=
2020001cc58SKishore Padmanabha 	    hash_tbl->key_tbl.data_size) {
203dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid arguments\n");
2040001cc58SKishore Padmanabha 		return -EINVAL;
2050001cc58SKishore Padmanabha 	}
2060001cc58SKishore Padmanabha 
2070001cc58SKishore Padmanabha 	/* calculate the hash */
208*b14da654SPeter Spreadborough 	switch (hash_tbl->key_tbl.data_size) {
209*b14da654SPeter Spreadborough 	case 1:
210*b14da654SPeter Spreadborough 		hash_id = rte_hash_crc_1byte(*entry->key_data,
211*b14da654SPeter Spreadborough 					     ~0U);
212*b14da654SPeter Spreadborough 		break;
213*b14da654SPeter Spreadborough 	case 2:
214*b14da654SPeter Spreadborough 		hash_id = rte_hash_crc_2byte(*((uint16_t *)entry->key_data),
215*b14da654SPeter Spreadborough 					     ~0U);
216*b14da654SPeter Spreadborough 		break;
217*b14da654SPeter Spreadborough 	case 4:
218*b14da654SPeter Spreadborough 		hash_id = rte_hash_crc_4byte(*((uint32_t *)entry->key_data),
219*b14da654SPeter Spreadborough 					     ~0U);
220*b14da654SPeter Spreadborough 		break;
221*b14da654SPeter Spreadborough 	case 8:
222*b14da654SPeter Spreadborough 		hash_id = rte_hash_crc_8byte(*((uint64_t *)entry->key_data),
223*b14da654SPeter Spreadborough 					     ~0U);
224*b14da654SPeter Spreadborough 		break;
225*b14da654SPeter Spreadborough 	default:
226*b14da654SPeter Spreadborough 		hash_id = rte_hash_crc(entry->key_data,
227*b14da654SPeter Spreadborough 				       hash_tbl->key_tbl.data_size,
228*b14da654SPeter Spreadborough 				       ~0U);
229*b14da654SPeter Spreadborough 		break;
230*b14da654SPeter Spreadborough 	}
2310001cc58SKishore Padmanabha 	hash_id = (uint16_t)(((hash_id >> 16) & 0xffff) ^ (hash_id & 0xffff));
2320001cc58SKishore Padmanabha 	hash_id &= hash_tbl->hash_mask;
2330001cc58SKishore Padmanabha 	hash_id = hash_id * hash_tbl->hash_bkt_num;
2340001cc58SKishore Padmanabha 
2350001cc58SKishore Padmanabha 	/* Iterate the bucket list */
2360001cc58SKishore Padmanabha 	bucket = (uint16_t *)&hash_tbl->hash_list[hash_id];
2370001cc58SKishore Padmanabha 	for (idx = 0; idx < (hash_tbl->hash_bkt_num * ULP_HASH_BUCKET_ROW_SZ);
2380001cc58SKishore Padmanabha 	      idx++, bucket++) {
2390001cc58SKishore Padmanabha 		if (ULP_HASH_BUCKET_INUSE(bucket)) {
2400001cc58SKishore Padmanabha 			/* compare the key contents */
2410001cc58SKishore Padmanabha 			key_idx = ULP_HASH_BUCKET_INDEX(bucket);
2420001cc58SKishore Padmanabha 			if (key_idx >= hash_tbl->num_key_entries) {
243dd0191d5SShuanglin Wang 				BNXT_DRV_DBG(ERR, "Hash table corruption\n");
2440001cc58SKishore Padmanabha 				return -EINVAL;
2450001cc58SKishore Padmanabha 			}
2460001cc58SKishore Padmanabha 			if (!memcmp(entry->key_data,
2470001cc58SKishore Padmanabha 				    &hash_tbl->key_tbl.key_data[key_idx *
2480001cc58SKishore Padmanabha 				    hash_tbl->key_tbl.data_size],
2490001cc58SKishore Padmanabha 				    hash_tbl->key_tbl.data_size)) {
2500001cc58SKishore Padmanabha 				/* Found the entry */
2510001cc58SKishore Padmanabha 				entry->search_flag = ULP_GEN_HASH_SEARCH_FOUND;
2520001cc58SKishore Padmanabha 				entry->hash_index = ULP_HASH_INDEX_CALC(hash_id,
2530001cc58SKishore Padmanabha 									idx);
2540001cc58SKishore Padmanabha 				entry->key_idx = key_idx;
2550001cc58SKishore Padmanabha 				return 0;
2560001cc58SKishore Padmanabha 			}
2570001cc58SKishore Padmanabha 		} else if (miss_idx == ULP_HASH_BUCKET_INVAL) {
2580001cc58SKishore Padmanabha 			miss_idx = idx;
2590001cc58SKishore Padmanabha 		}
2600001cc58SKishore Padmanabha 	}
2610001cc58SKishore Padmanabha 
2620001cc58SKishore Padmanabha 	if (miss_idx == ULP_HASH_BUCKET_INVAL) {
2630001cc58SKishore Padmanabha 		entry->search_flag = ULP_GEN_HASH_SEARCH_FULL;
2640001cc58SKishore Padmanabha 	} else {
2650001cc58SKishore Padmanabha 		entry->search_flag = ULP_GEN_HASH_SEARCH_MISSED;
2660001cc58SKishore Padmanabha 		entry->hash_index = ULP_HASH_INDEX_CALC(hash_id, miss_idx);
2670001cc58SKishore Padmanabha 	}
2680001cc58SKishore Padmanabha 	return 0;
2690001cc58SKishore Padmanabha }
2700001cc58SKishore Padmanabha 
2710001cc58SKishore Padmanabha /*
2720001cc58SKishore Padmanabha  * Search the generic hash table using hash index
2730001cc58SKishore Padmanabha  *
2740001cc58SKishore Padmanabha  * hash_tbl [in] the pointer to hash table
2750001cc58SKishore Padmanabha  * entry [in/out] pointer to hash entry details.
2760001cc58SKishore Padmanabha  *
2770001cc58SKishore Padmanabha  * returns 0 on success and marks search flag as found.
2780001cc58SKishore Padmanabha  */
2790001cc58SKishore Padmanabha int32_t
2800001cc58SKishore Padmanabha ulp_gen_hash_tbl_list_index_search(struct ulp_gen_hash_tbl *hash_tbl,
2810001cc58SKishore Padmanabha 				   struct ulp_gen_hash_entry_params *entry)
2820001cc58SKishore Padmanabha {
2830001cc58SKishore Padmanabha 	uint32_t idx;
2840001cc58SKishore Padmanabha 	uint16_t *bucket;
2850001cc58SKishore Padmanabha 
2860001cc58SKishore Padmanabha 	/* validate the arguments */
2870001cc58SKishore Padmanabha 	if (!hash_tbl || !entry) {
288dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid arguments\n");
2890001cc58SKishore Padmanabha 		return -EINVAL;
2900001cc58SKishore Padmanabha 	}
2910001cc58SKishore Padmanabha 
2920001cc58SKishore Padmanabha 	idx = ULP_HASH_GET_H_INDEX(entry->hash_index);
2930001cc58SKishore Padmanabha 	if (idx > (hash_tbl->hash_tbl_size * hash_tbl->hash_bkt_num)) {
294dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid hash index %x\n", idx);
2950001cc58SKishore Padmanabha 		return -EINVAL;
2960001cc58SKishore Padmanabha 	}
2970001cc58SKishore Padmanabha 	bucket = (uint16_t *)&hash_tbl->hash_list[idx];
2980001cc58SKishore Padmanabha 	idx  = ULP_HASH_GET_B_INDEX(entry->hash_index);
2990001cc58SKishore Padmanabha 	if (idx >= (hash_tbl->hash_bkt_num * ULP_HASH_BUCKET_ROW_SZ)) {
300dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "invalid bucket index %x\n", idx);
3010001cc58SKishore Padmanabha 		return -EINVAL;
3020001cc58SKishore Padmanabha 	}
3030001cc58SKishore Padmanabha 	bucket += idx;
3040001cc58SKishore Padmanabha 	if (ULP_HASH_BUCKET_INUSE(bucket)) {
3050001cc58SKishore Padmanabha 		entry->key_idx = ULP_HASH_BUCKET_INDEX(bucket);
3060001cc58SKishore Padmanabha 		entry->search_flag = ULP_GEN_HASH_SEARCH_FOUND;
3070001cc58SKishore Padmanabha 	} else {
3080001cc58SKishore Padmanabha 		entry->search_flag = ULP_GEN_HASH_SEARCH_MISSED;
3090001cc58SKishore Padmanabha 		return -ENOENT;
3100001cc58SKishore Padmanabha 	}
3110001cc58SKishore Padmanabha 	return 0;
3120001cc58SKishore Padmanabha }
3130001cc58SKishore Padmanabha 
3140001cc58SKishore Padmanabha /*
3150001cc58SKishore Padmanabha  * Add the entry to the generic hash table
3160001cc58SKishore Padmanabha  *
3170001cc58SKishore Padmanabha  * hash_tbl [in] the pointer to hash table
3180001cc58SKishore Padmanabha  * entry [in/out] pointer to hash entry details. Fill the hash index and
3190001cc58SKishore Padmanabha  * key data details to be added.
3200001cc58SKishore Padmanabha  *
3210001cc58SKishore Padmanabha  * returns 0 on success
3220001cc58SKishore Padmanabha  *
3230001cc58SKishore Padmanabha  */
3240001cc58SKishore Padmanabha int32_t
3250001cc58SKishore Padmanabha ulp_gen_hash_tbl_list_add(struct ulp_gen_hash_tbl *hash_tbl,
3260001cc58SKishore Padmanabha 			  struct ulp_gen_hash_entry_params *entry)
3270001cc58SKishore Padmanabha {
3280001cc58SKishore Padmanabha 	int32_t rc = 0;
3290001cc58SKishore Padmanabha 	uint16_t *bucket;
3300001cc58SKishore Padmanabha 	uint32_t idx, key_index;
3310001cc58SKishore Padmanabha 
3320001cc58SKishore Padmanabha 	/* add the entry */
3330001cc58SKishore Padmanabha 	idx = ULP_HASH_GET_H_INDEX(entry->hash_index);
3340001cc58SKishore Padmanabha 	bucket = (uint16_t *)&hash_tbl->hash_list[idx];
3350001cc58SKishore Padmanabha 	bucket += ULP_HASH_GET_B_INDEX(entry->hash_index);
3360001cc58SKishore Padmanabha 	if (ulp_bit_alloc_list_alloc(&hash_tbl->bit_list, &key_index)) {
337dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error in bit list alloc\n");
3380001cc58SKishore Padmanabha 		return -ENOMEM;
3390001cc58SKishore Padmanabha 	}
340a738cbfeSKishore Padmanabha 	if (key_index > hash_tbl->num_key_entries) {
341dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "reached max size %u:%u\n", key_index,
342a738cbfeSKishore Padmanabha 			     hash_tbl->num_key_entries);
343a738cbfeSKishore Padmanabha 		ulp_bit_alloc_list_dealloc(&hash_tbl->bit_list, key_index);
344a738cbfeSKishore Padmanabha 		return -ENOMEM;
345a738cbfeSKishore Padmanabha 	}
3460001cc58SKishore Padmanabha 	/* Update the hash entry */
3470001cc58SKishore Padmanabha 	ULP_HASH_BUCKET_MARK_INUSE(bucket, (uint16_t)key_index);
3480001cc58SKishore Padmanabha 
3490001cc58SKishore Padmanabha 	/* update the hash key and key index */
3500001cc58SKishore Padmanabha 	entry->key_idx = key_index;
3510001cc58SKishore Padmanabha 	key_index = key_index * hash_tbl->key_tbl.data_size;
3520001cc58SKishore Padmanabha 	memcpy(&hash_tbl->key_tbl.key_data[key_index], entry->key_data,
3530001cc58SKishore Padmanabha 	       hash_tbl->key_tbl.data_size);
3540001cc58SKishore Padmanabha 
3550001cc58SKishore Padmanabha 	return rc;
3560001cc58SKishore Padmanabha }
3570001cc58SKishore Padmanabha 
3580001cc58SKishore Padmanabha /*
3590001cc58SKishore Padmanabha  * Delete the entry in the generic hash table
3600001cc58SKishore Padmanabha  *
3610001cc58SKishore Padmanabha  * hash_tbl [in] the pointer to hash table
3620001cc58SKishore Padmanabha  * entry [in] pointer to hash entry details. Fill the hash index details to be
3630001cc58SKishore Padmanabha  * deleted.
3640001cc58SKishore Padmanabha  *
3650001cc58SKishore Padmanabha  * returns 0 on success
3660001cc58SKishore Padmanabha  */
3670001cc58SKishore Padmanabha int32_t
3680001cc58SKishore Padmanabha ulp_gen_hash_tbl_list_del(struct ulp_gen_hash_tbl *hash_tbl,
3690001cc58SKishore Padmanabha 			  struct ulp_gen_hash_entry_params *entry)
3700001cc58SKishore Padmanabha {
3710001cc58SKishore Padmanabha 	uint16_t *bucket;
3720001cc58SKishore Padmanabha 	uint32_t idx, key_index;
3730001cc58SKishore Padmanabha 
3740001cc58SKishore Padmanabha 	/* delete the entry */
3750001cc58SKishore Padmanabha 	idx = ULP_HASH_GET_H_INDEX(entry->hash_index);
3760001cc58SKishore Padmanabha 	bucket = (uint16_t *)&hash_tbl->hash_list[idx];
3770001cc58SKishore Padmanabha 	bucket += ULP_HASH_GET_B_INDEX(entry->hash_index);
3780001cc58SKishore Padmanabha 
3790001cc58SKishore Padmanabha 	/* Get the hash entry */
3800001cc58SKishore Padmanabha 	key_index = ULP_HASH_BUCKET_INDEX(bucket);
3810001cc58SKishore Padmanabha 	if (key_index >= hash_tbl->num_key_entries) {
382dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Hash table corruption\n");
3830001cc58SKishore Padmanabha 		return -EINVAL;
3840001cc58SKishore Padmanabha 	}
3850001cc58SKishore Padmanabha 
3860001cc58SKishore Padmanabha 	/* reset the bit in the bit allocator */
3870001cc58SKishore Padmanabha 	if (ulp_bit_alloc_list_dealloc(&hash_tbl->bit_list,
3880001cc58SKishore Padmanabha 				       key_index)) {
389dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error is bit list dealloc\n");
3900001cc58SKishore Padmanabha 		return -EINVAL;
3910001cc58SKishore Padmanabha 	}
3920001cc58SKishore Padmanabha 
3930001cc58SKishore Padmanabha 	/* erase key details and bucket details */
3940001cc58SKishore Padmanabha 	key_index = key_index * hash_tbl->key_tbl.data_size;
3950001cc58SKishore Padmanabha 	memset(&hash_tbl->key_tbl.key_data[key_index], 0,
3960001cc58SKishore Padmanabha 	       hash_tbl->key_tbl.data_size);
3970001cc58SKishore Padmanabha 	ULP_HASH_BUCKET_CLEAR(bucket);
3980001cc58SKishore Padmanabha 
3990001cc58SKishore Padmanabha 	return 0;
4000001cc58SKishore Padmanabha }
401