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