xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_gen_tbl.c (revision 0c036a1485b9d9163a8fa8059ed5272d060c05e0)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2023 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include "bnxt_ulp_utils.h"
9 #include "tf_core.h"
10 #include "tfp.h"
11 #include "ulp_mapper.h"
12 #include "ulp_flow_db.h"
13 
14 /* Retrieve the generic table  initialization parameters for the tbl_idx */
15 static const struct bnxt_ulp_generic_tbl_params*
16 ulp_mapper_gen_tbl_params_get(struct bnxt_ulp_context *ulp_ctx,
17 			      uint32_t tbl_idx)
18 {
19 	struct bnxt_ulp_device_params *dparms;
20 	const struct bnxt_ulp_generic_tbl_params *gen_tbl;
21 	uint32_t dev_id;
22 
23 	if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ) {
24 		BNXT_DRV_DBG(ERR, "Gen table out of bounds %d\n", tbl_idx);
25 		return NULL;
26 	}
27 
28 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id))
29 		return NULL;
30 
31 	dparms = bnxt_ulp_device_params_get(dev_id);
32 	if (!dparms) {
33 		BNXT_DRV_DBG(ERR, "Failed to get device parms\n");
34 		return NULL;
35 	}
36 
37 	gen_tbl = &dparms->gen_tbl_params[tbl_idx];
38 	return gen_tbl;
39 }
40 
41 /*
42  * Initialize the generic table list
43  *
44  * mapper_data [in] Pointer to the mapper data and the generic table is
45  * part of it
46  *
47  * returns 0 on success
48  */
49 int32_t
50 ulp_mapper_generic_tbl_list_init(struct bnxt_ulp_context *ulp_ctx,
51 				 struct bnxt_ulp_mapper_data *mapper_data)
52 {
53 	const struct bnxt_ulp_generic_tbl_params *tbl;
54 	struct ulp_mapper_gen_tbl_list *entry;
55 	struct ulp_hash_create_params cparams;
56 	uint32_t idx, size, key_sz;
57 
58 	/* Allocate the generic tables. */
59 	for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) {
60 		tbl = ulp_mapper_gen_tbl_params_get(ulp_ctx, idx);
61 		if (!tbl) {
62 			BNXT_DRV_DBG(ERR, "Failed to get gen table parms %d\n",
63 				     idx);
64 			return -EINVAL;
65 		}
66 		entry = &mapper_data->gen_tbl_list[idx];
67 
68 		/* For simple list allocate memory for key storage*/
69 		if (tbl->gen_tbl_type == BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST &&
70 		    tbl->key_num_bytes) {
71 			key_sz = tbl->key_num_bytes +
72 				tbl->partial_key_num_bytes;
73 			entry->container.byte_key_ex_size = tbl->key_num_bytes;
74 			entry->container.byte_key_par_size =
75 				tbl->partial_key_num_bytes;
76 		} else {
77 			key_sz = 0;
78 		}
79 
80 		/* Allocate memory for result data and key data */
81 		if (tbl->result_num_entries != 0) {
82 			/* assign the name */
83 			entry->gen_tbl_name = tbl->name;
84 			entry->tbl_type = tbl->gen_tbl_type;
85 			/* add 4 bytes for reference count */
86 			entry->mem_data_size = (tbl->result_num_entries + 1) *
87 				(tbl->result_num_bytes + sizeof(uint32_t) +
88 				 key_sz);
89 
90 			/* allocate the big chunk of memory */
91 			entry->mem_data = rte_zmalloc("ulp mapper gen tbl",
92 						      entry->mem_data_size, 0);
93 			if (!entry->mem_data) {
94 				BNXT_DRV_DBG(ERR,
95 					    "%s:Failed to alloc gen table %d\n",
96 					     tbl->name, idx);
97 				return -ENOMEM;
98 			}
99 			/* Populate the generic table container */
100 			entry->container.num_elem = tbl->result_num_entries;
101 			entry->container.byte_data_size = tbl->result_num_bytes;
102 			entry->container.ref_count =
103 				(uint32_t *)entry->mem_data;
104 			size = sizeof(uint32_t) * (tbl->result_num_entries + 1);
105 			entry->container.byte_data = &entry->mem_data[size];
106 			entry->container.byte_order = tbl->result_byte_order;
107 		} else {
108 			BNXT_DRV_DBG(DEBUG, "%s: Unused Gen tbl entry is %d\n",
109 				     tbl->name, idx);
110 			continue;
111 		}
112 
113 		/* assign the memory for key data */
114 		if (tbl->gen_tbl_type == BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST &&
115 		    key_sz) {
116 			size += tbl->result_num_bytes *
117 				(tbl->result_num_entries + 1);
118 			entry->container.byte_key =
119 				&entry->mem_data[size];
120 		}
121 
122 		/* Initialize Hash list for hash based generic table */
123 		if (tbl->gen_tbl_type == BNXT_ULP_GEN_TBL_TYPE_HASH_LIST &&
124 		    tbl->hash_tbl_entries) {
125 			cparams.key_size = tbl->key_num_bytes;
126 			cparams.num_buckets = tbl->num_buckets;
127 			cparams.num_hash_tbl_entries = tbl->hash_tbl_entries;
128 			cparams.num_key_entries = tbl->result_num_entries;
129 			if (ulp_gen_hash_tbl_list_init(&cparams,
130 						       &entry->hash_tbl)) {
131 				BNXT_DRV_DBG(ERR,
132 					    "%s: Failed to alloc hash tbl %d\n",
133 					     tbl->name, idx);
134 				return -ENOMEM;
135 			}
136 		}
137 	}
138 	return 0;
139 }
140 
141 /*
142  * Free the generic table list
143  *
144  * mapper_data [in] Pointer to the mapper data and the generic table is
145  * part of it
146  *
147  * returns 0 on success
148  */
149 int32_t
150 ulp_mapper_generic_tbl_list_deinit(struct bnxt_ulp_mapper_data *mapper_data)
151 {
152 	struct ulp_mapper_gen_tbl_list *tbl_list;
153 	uint32_t idx;
154 
155 	/* iterate the generic table. */
156 	for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) {
157 		tbl_list = &mapper_data->gen_tbl_list[idx];
158 		if (tbl_list->mem_data) {
159 			rte_free(tbl_list->mem_data);
160 			tbl_list->mem_data = NULL;
161 			tbl_list->container.byte_data = NULL;
162 			tbl_list->container.byte_key = NULL;
163 			tbl_list->container.ref_count = NULL;
164 		}
165 		if (tbl_list->hash_tbl) {
166 			ulp_gen_hash_tbl_list_deinit(tbl_list->hash_tbl);
167 			tbl_list->hash_tbl = NULL;
168 		}
169 	}
170 	/* success */
171 	return 0;
172 }
173 
174 /*
175  * Get the generic table list entry
176  *
177  * tbl_list [in] - Ptr to generic table
178  * key [in] - Key index to the table
179  * entry [out] - output will include the entry if found
180  *
181  * returns 0 on success.
182  */
183 int32_t
184 ulp_mapper_gen_tbl_entry_get(struct ulp_mapper_gen_tbl_list *tbl_list,
185 			     uint32_t key,
186 			     struct ulp_mapper_gen_tbl_entry *entry)
187 {
188 	/* populate the output and return the values */
189 	if (key > tbl_list->container.num_elem) {
190 		BNXT_DRV_DBG(ERR, "%s: invalid key %x:%x\n",
191 			     tbl_list->gen_tbl_name, key,
192 			     tbl_list->container.num_elem);
193 		return -EINVAL;
194 	}
195 	entry->ref_count = &tbl_list->container.ref_count[key];
196 	entry->byte_data_size = tbl_list->container.byte_data_size;
197 	entry->byte_data = &tbl_list->container.byte_data[key *
198 		entry->byte_data_size];
199 	entry->byte_order = tbl_list->container.byte_order;
200 	if (tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST) {
201 		entry->byte_key_size = tbl_list->container.byte_key_ex_size +
202 			tbl_list->container.byte_key_par_size;
203 		entry->byte_key = &tbl_list->container.byte_key[key *
204 			entry->byte_key_size];
205 	} else {
206 		entry->byte_key = NULL;
207 		entry->byte_key_size = 0;
208 	}
209 	return 0;
210 }
211 
212 /*
213  * utility function to calculate the table idx
214  *
215  * res_sub_type [in] - Resource sub type
216  * dir [in] - Direction
217  *
218  * returns None
219  */
220 int32_t
221 ulp_mapper_gen_tbl_idx_calculate(uint32_t res_sub_type, uint32_t dir)
222 {
223 	int32_t tbl_idx;
224 
225 	/* Validate for direction */
226 	if (dir >= TF_DIR_MAX) {
227 		BNXT_DRV_DBG(ERR, "invalid argument %x\n", dir);
228 		return -EINVAL;
229 	}
230 	tbl_idx = (res_sub_type << 1) | (dir & 0x1);
231 	if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ) {
232 		BNXT_DRV_DBG(ERR, "invalid table index %x\n", tbl_idx);
233 		return -EINVAL;
234 	}
235 	return tbl_idx;
236 }
237 
238 /*
239  * Set the data in the generic table entry, Data is in Big endian format
240  *
241  * entry [in] - generic table entry
242  * key [in] - pointer to the key to be used for setting the value.
243  * key_size [in] - The length of the key in bytess to be set
244  * data [in] - pointer to the data to be used for setting the value.
245  * data_size [in] - length of the data pointer in bytes.
246  *
247  * returns 0 on success
248  */
249 int32_t
250 ulp_mapper_gen_tbl_entry_data_set(struct ulp_mapper_gen_tbl_list *tbl_list,
251 				  struct ulp_mapper_gen_tbl_entry *entry,
252 				  uint8_t *key, uint32_t key_size,
253 				  uint8_t *data, uint32_t data_size)
254 {
255 	/* validate the null arguments */
256 	if (!entry || !key || !data) {
257 		BNXT_DRV_DBG(ERR, "invalid argument\n");
258 		return -EINVAL;
259 	}
260 
261 	/* check the size of the buffer for validation */
262 	if (data_size > entry->byte_data_size) {
263 		BNXT_DRV_DBG(ERR, "invalid offset or length %x:%x\n",
264 			     data_size, entry->byte_data_size);
265 		return -EINVAL;
266 	}
267 	memcpy(entry->byte_data, data, data_size);
268 	if (tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST) {
269 		if (key_size > entry->byte_key_size) {
270 			BNXT_DRV_DBG(ERR, "invalid offset or length %x:%x\n",
271 				     key_size, entry->byte_key_size);
272 		return -EINVAL;
273 		}
274 		memcpy(entry->byte_key, key, key_size);
275 	}
276 	tbl_list->container.seq_cnt++;
277 	return 0;
278 }
279 
280 /*
281  * Get the data in the generic table entry, Data is in Big endian format
282  *
283  * entry [in] - generic table entry
284  * offset [in] - The offset in bits where the data has to get
285  * len [in] - The length of the data in bits to be get
286  * data [out] - pointer to the data to be used for setting the value.
287  * data_size [in] - The size of data in bytes
288  *
289  * returns 0 on success
290  */
291 int32_t
292 ulp_mapper_gen_tbl_entry_data_get(struct ulp_mapper_gen_tbl_entry *entry,
293 				  uint32_t offset, uint32_t len, uint8_t *data,
294 				  uint32_t data_size)
295 {
296 	/* validate the null arguments */
297 	if (!entry || !data) {
298 		BNXT_DRV_DBG(ERR, "invalid argument\n");
299 		return -EINVAL;
300 	}
301 
302 	/* check the size of the buffer for validation */
303 	if ((offset + len) > ULP_BYTE_2_BITS(entry->byte_data_size) ||
304 	    len > ULP_BYTE_2_BITS(data_size)) {
305 		BNXT_DRV_DBG(ERR, "invalid offset or length %x:%x:%x\n",
306 			     offset, len, entry->byte_data_size);
307 		return -EINVAL;
308 	}
309 	if (entry->byte_order == BNXT_ULP_BYTE_ORDER_LE)
310 		ulp_bs_pull_lsb(entry->byte_data, data, data_size, offset, len);
311 	else
312 		ulp_bs_pull_msb(entry->byte_data, data, offset, len);
313 
314 	return 0;
315 }
316 
317 /* Free the generic table list entry
318  *
319  * ulp_ctx [in] - Pointer to the ulp context
320  * tbl_idx [in] - Index of the generic table
321  * ckey [in] - Key for the entry in the table
322  *
323  * returns 0 on success
324  */
325 int32_t
326 ulp_mapper_gen_tbl_entry_free(struct bnxt_ulp_context *ulp_ctx,
327 			      uint32_t tbl_idx, uint32_t ckey)
328 {
329 	struct ulp_flow_db_res_params res;
330 	uint32_t fid = 0; /* not using for this case */
331 
332 	res.direction = tbl_idx & 0x1;
333 	res.resource_sub_type = tbl_idx >> 1;
334 	res.resource_hndl = ckey;
335 
336 	return ulp_mapper_gen_tbl_res_free(ulp_ctx, fid, &res);
337 }
338 
339 /* Free the generic table list resource
340  *
341  * ulp_ctx [in] - Pointer to the ulp context
342  * fid [in] - The fid the generic table is associated with
343  * res [in] - Pointer to flow db resource entry
344  *
345  * returns 0 on success
346  */
347 int32_t
348 ulp_mapper_gen_tbl_res_free(struct bnxt_ulp_context *ulp_ctx,
349 			    uint32_t fid,
350 			    struct ulp_flow_db_res_params *res)
351 {
352 	struct bnxt_ulp_mapper_data *mapper_data;
353 	struct ulp_mapper_gen_tbl_list *gen_tbl_list;
354 	struct ulp_mapper_gen_tbl_entry entry;
355 	struct ulp_gen_hash_entry_params hash_entry;
356 	int32_t tbl_idx;
357 	uint32_t rid = 0;
358 	uint32_t key_idx;
359 
360 	/* Extract the resource sub type and direction */
361 	tbl_idx = ulp_mapper_gen_tbl_idx_calculate(res->resource_sub_type,
362 						   res->direction);
363 	if (tbl_idx < 0) {
364 		BNXT_DRV_DBG(ERR, "invalid argument %x:%x\n",
365 			     res->resource_sub_type, res->direction);
366 		return -EINVAL;
367 	}
368 
369 	mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
370 	if (!mapper_data) {
371 		BNXT_DRV_DBG(ERR, "invalid ulp context %x\n", tbl_idx);
372 		return -EINVAL;
373 	}
374 	/* get the generic table  */
375 	gen_tbl_list = &mapper_data->gen_tbl_list[tbl_idx];
376 
377 	/* Get the generic table entry*/
378 	if (gen_tbl_list->hash_tbl) {
379 		/* use the hash index to get the value */
380 		hash_entry.hash_index = (uint32_t)res->resource_hndl;
381 		if (ulp_gen_hash_tbl_list_index_search(gen_tbl_list->hash_tbl,
382 						       &hash_entry)) {
383 			BNXT_DRV_DBG(ERR, "Unable to find has entry %x:%x\n",
384 				     tbl_idx, hash_entry.hash_index);
385 			return -EINVAL;
386 		}
387 		key_idx = hash_entry.key_idx;
388 
389 	} else {
390 		key_idx =  (uint32_t)res->resource_hndl;
391 	}
392 	if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_idx, &entry)) {
393 		BNXT_DRV_DBG(ERR, "Gen tbl entry get failed %x:%" PRIX64 "\n",
394 			     tbl_idx, res->resource_hndl);
395 		return -EINVAL;
396 	}
397 
398 	/* Decrement the reference count */
399 	if (!ULP_GEN_TBL_REF_CNT(&entry)) {
400 		BNXT_DRV_DBG(DEBUG,
401 			    "generic table entry already free %x:%" PRIX64 "\n",
402 			     tbl_idx, res->resource_hndl);
403 		return 0;
404 	}
405 	ULP_GEN_TBL_REF_CNT_DEC(&entry);
406 
407 	/* retain the details since there are other users */
408 	if (ULP_GEN_TBL_REF_CNT(&entry))
409 		return 0;
410 
411 	/* Delete the generic table entry. First extract the rid */
412 	if (ulp_mapper_gen_tbl_entry_data_get(&entry, ULP_GEN_TBL_FID_OFFSET,
413 					      ULP_GEN_TBL_FID_SIZE_BITS,
414 					      (uint8_t *)&rid,
415 					      sizeof(rid))) {
416 		BNXT_DRV_DBG(ERR, "Unable to get rid %x:%" PRIX64 "\n",
417 			     tbl_idx, res->resource_hndl);
418 		return -EINVAL;
419 	}
420 	rid = tfp_be_to_cpu_32(rid);
421 	/* no need to del if rid is 0 since there is no associated resource
422 	 * if rid from the entry is equal to the incoming fid, then we have a
423 	 * recursive delete, so don't follow the rid.
424 	 */
425 	if (rid && rid != fid) {
426 		/* Destroy the flow associated with the shared flow id */
427 		if (ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_RID,
428 					    rid, NULL))
429 			BNXT_DRV_DBG(ERR,
430 				    "Error in deleting shared resource id %x\n",
431 				     rid);
432 	}
433 
434 	/* Delete the entry from the hash table */
435 	if (gen_tbl_list->hash_tbl)
436 		ulp_gen_hash_tbl_list_del(gen_tbl_list->hash_tbl, &hash_entry);
437 
438 	/* decrement the count */
439 	if (gen_tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST &&
440 	    gen_tbl_list->container.seq_cnt > 0)
441 		gen_tbl_list->container.seq_cnt--;
442 
443 	/* clear the byte data of the generic table entry */
444 	memset(entry.byte_data, 0, entry.byte_data_size);
445 
446 	return 0;
447 }
448 
449 /*
450  * Write the generic table list hash entry
451  *
452  * tbl_list [in] - pointer to the generic table list
453  * hash_entry [in] -  Hash table entry
454  * gen_tbl_ent [out] - generic table entry
455  *
456  * returns 0 on success.
457  */
458 int32_t
459 ulp_mapper_gen_tbl_hash_entry_add(struct ulp_mapper_gen_tbl_list *tbl_list,
460 				  struct ulp_gen_hash_entry_params *hash_entry,
461 				  struct ulp_mapper_gen_tbl_entry *gen_tbl_ent)
462 {
463 	uint32_t key;
464 	int32_t rc = 0;
465 
466 	switch (hash_entry->search_flag) {
467 	case ULP_GEN_HASH_SEARCH_FOUND:
468 		BNXT_DRV_DBG(ERR, "%s: gen hash entry already present\n",
469 			     tbl_list->gen_tbl_name);
470 		return -EINVAL;
471 	case ULP_GEN_HASH_SEARCH_FULL:
472 		BNXT_DRV_DBG(ERR, "%s: gen hash table is full\n",
473 			     tbl_list->gen_tbl_name);
474 		return -EINVAL;
475 	case ULP_GEN_HASH_SEARCH_MISSED:
476 		rc = ulp_gen_hash_tbl_list_add(tbl_list->hash_tbl, hash_entry);
477 		if (rc) {
478 			BNXT_DRV_DBG(ERR, "%s: gen hash table add failed\n",
479 				     tbl_list->gen_tbl_name);
480 			return -EINVAL;
481 		}
482 		key = hash_entry->key_idx;
483 		gen_tbl_ent->ref_count = &tbl_list->container.ref_count[key];
484 		gen_tbl_ent->byte_data_size =
485 			tbl_list->container.byte_data_size;
486 		gen_tbl_ent->byte_data = &tbl_list->container.byte_data[key *
487 			gen_tbl_ent->byte_data_size];
488 		gen_tbl_ent->byte_order = tbl_list->container.byte_order;
489 		break;
490 	default:
491 		BNXT_DRV_DBG(ERR, "%s: invalid search flag\n",
492 			     tbl_list->gen_tbl_name);
493 		return -EINVAL;
494 	}
495 
496 	return rc;
497 }
498 
499 /*
500  * Perform add entry in the simple list
501  *
502  * tbl_list [in] - pointer to the generic table list
503  * key [in] -  Key added as index
504  * data [in] -  data added as result
505  * key_index [out] - index to the entry
506  * gen_tbl_ent [out] - write the output to the entry
507  *
508  * returns 0 on success.
509  */
510 int32_t
511 ulp_gen_tbl_simple_list_add_entry(struct ulp_mapper_gen_tbl_list *tbl_list,
512 				  uint8_t *key,
513 				  uint8_t *data,
514 				  uint32_t *key_index,
515 				  struct ulp_mapper_gen_tbl_entry *ent)
516 {
517 	struct ulp_mapper_gen_tbl_cont	*cont;
518 	uint32_t key_size, idx;
519 	uint8_t *entry_key;
520 
521 	/* sequentially search for the matching key */
522 	cont = &tbl_list->container;
523 	for (idx = 0; idx < cont->num_elem; idx++) {
524 		ent->ref_count = &cont->ref_count[idx];
525 		if (ULP_GEN_TBL_REF_CNT(ent) == 0) {
526 			/* add the entry */
527 			key_size = cont->byte_key_ex_size +
528 				cont->byte_key_par_size;
529 			entry_key = &cont->byte_key[idx * key_size];
530 			ent->byte_data_size = cont->byte_data_size;
531 			ent->byte_data = &cont->byte_data[idx *
532 				cont->byte_data_size];
533 			memcpy(entry_key, key, key_size);
534 			memcpy(ent->byte_data, data, ent->byte_data_size);
535 			ent->byte_order = cont->byte_order;
536 			*key_index = idx;
537 			cont->seq_cnt++;
538 			return 0;
539 		}
540 	}
541 	/* No more memory */
542 	return -ENOMEM;
543 }
544 
545 /* perform the subset and superset. len should be 64bit multiple*/
546 static enum ulp_gen_list_search_flag
547 ulp_gen_tbl_overlap_check(uint8_t *key1, uint8_t *key2, uint32_t len)
548 {
549 	uint32_t sz = 0, superset = 0, subset = 0;
550 	uint64_t src, dst;
551 
552 	while (sz  < len) {
553 		memcpy(&dst, key2, sizeof(dst));
554 		memcpy(&src, key1, sizeof(src));
555 		sz += sizeof(src);
556 		if (dst == src)
557 			continue;
558 		else if (dst == (dst | src))
559 			superset = 1;
560 		else if (src == (dst | src))
561 			subset = 1;
562 		else
563 			return ULP_GEN_LIST_SEARCH_MISSED;
564 	}
565 	if (superset && !subset)
566 		return ULP_GEN_LIST_SEARCH_FOUND_SUPERSET;
567 	if (!superset && subset)
568 		return ULP_GEN_LIST_SEARCH_FOUND_SUBSET;
569 	return ULP_GEN_LIST_SEARCH_FOUND;
570 }
571 
572 uint32_t
573 ulp_gen_tbl_simple_list_search(struct ulp_mapper_gen_tbl_list *tbl_list,
574 			       uint8_t *match_key,
575 			       uint32_t *key_idx)
576 {
577 	enum ulp_gen_list_search_flag rc = ULP_GEN_LIST_SEARCH_FULL;
578 	uint32_t idx = 0, key_idx_set = 0, sz = 0, key_size = 0;
579 	struct ulp_mapper_gen_tbl_entry ent = { 0 };
580 	struct ulp_mapper_gen_tbl_cont	*cont = &tbl_list->container;
581 	uint8_t *k1 = NULL, *k2, *entry_key;
582 	uint32_t valid_ent = 0;
583 
584 	key_size = cont->byte_key_ex_size + cont->byte_key_par_size;
585 	if (cont->byte_key_par_size)
586 		k1 = match_key + cont->byte_key_ex_size;
587 
588 	/* sequentially search for the matching key */
589 	while (idx < cont->num_elem) {
590 		ent.ref_count = &cont->ref_count[idx];
591 		entry_key = &cont->byte_key[idx * key_size];
592 		/* check ref count not zero and exact key matches */
593 		if (ULP_GEN_TBL_REF_CNT(&ent)) {
594 			/* compare the exact match */
595 			if (!memcmp(match_key, entry_key,
596 				    cont->byte_key_ex_size)) {
597 				/* Match the partial key*/
598 				if (cont->byte_key_par_size) {
599 					k2 = entry_key + cont->byte_key_ex_size;
600 					sz = cont->byte_key_par_size;
601 					rc = ulp_gen_tbl_overlap_check(k1, k2,
602 								       sz);
603 					if (rc != ULP_GEN_LIST_SEARCH_MISSED) {
604 						*key_idx = idx;
605 						return rc;
606 					}
607 				} else {
608 					/* found the entry return */
609 					rc = ULP_GEN_LIST_SEARCH_FOUND;
610 					*key_idx = idx;
611 					return rc;
612 				}
613 			}
614 			++valid_ent;
615 		} else {
616 			/* empty slot */
617 			if (!key_idx_set) {
618 				*key_idx = idx;
619 				key_idx_set = 1;
620 				rc = ULP_GEN_LIST_SEARCH_MISSED;
621 			}
622 			if (valid_ent >= cont->seq_cnt)
623 				return rc;
624 		}
625 		idx++;
626 	}
627 	return rc;
628 }
629