xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_flow_db.c (revision a089734a026a316994674e3f405ee4d56a114efc)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2023 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <rte_bitops.h>
7 #include <rte_malloc.h>
8 
9 #include "bnxt.h"
10 #include "bnxt_tf_common.h"
11 #include "bnxt_ulp_utils.h"
12 #include "ulp_template_struct.h"
13 #include "ulp_mapper.h"
14 #include "ulp_flow_db.h"
15 #include "ulp_fc_mgr.h"
16 #include "ulp_sc_mgr.h"
17 #include "ulp_tun.h"
18 #ifdef TF_FLOW_SCALE_QUERY
19 #include "tf_resources.h"
20 #include "tfc_resources.h"
21 #endif /* TF_FLOW_SCALE_QUERY */
22 
23 #define ULP_FLOW_DB_RES_DIR_BIT		31
24 #define ULP_FLOW_DB_RES_DIR_MASK	0x80000000
25 #define ULP_FLOW_DB_RES_NXT_MASK	0x7FFFFFFF
26 
27 /* Macro to copy the nxt_resource_idx */
28 #define ULP_FLOW_DB_RES_NXT_SET(dst, src)	{(dst) |= ((src) &\
29 					 ULP_FLOW_DB_RES_NXT_MASK); }
30 #define ULP_FLOW_DB_RES_NXT_RESET(dst)	((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
31 
32 /*
33  * Helper function to set the bit in the active flows
34  * No validation is done in this function.
35  *
36  * flow_db [in] Ptr to flow database
37  * flow_type [in] - specify default or regular
38  * idx [in] The index to bit to be set or reset.
39  * flag [in] 1 to set and 0 to reset.
40  *
41  * returns none
42  */
43 static void
44 ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db,
45 				 enum bnxt_ulp_fdb_type flow_type,
46 				 uint32_t idx,
47 				 uint32_t flag)
48 {
49 	struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
50 	uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
51 
52 	if (flag) {
53 		if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==
54 		    BNXT_ULP_FDB_TYPE_RID)
55 			ULP_INDEX_BITMAP_SET(f_tbl->active_reg_flows[a_idx],
56 					     idx);
57 		if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==
58 		    BNXT_ULP_FDB_TYPE_RID)
59 			ULP_INDEX_BITMAP_SET(f_tbl->active_dflt_flows[a_idx],
60 					     idx);
61 	} else {
62 		if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==
63 		    BNXT_ULP_FDB_TYPE_RID)
64 			ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx],
65 					       idx);
66 		if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==
67 		    BNXT_ULP_FDB_TYPE_RID)
68 			ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx],
69 					       idx);
70 	}
71 }
72 
73 /*
74  * Helper function to check if given fid is active flow.
75  * No validation being done in this function.
76  *
77  * flow_db [in] Ptr to flow database
78  * flow_type [in] - specify default or regular
79  * idx [in] The index to bit to be set or reset.
80  *
81  * returns 1 on set or 0 if not set.
82  */
83 static int32_t
84 ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db,
85 				    enum bnxt_ulp_fdb_type flow_type,
86 				    uint32_t idx)
87 {
88 	struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
89 	uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
90 	uint32_t reg, dflt;
91 
92 	reg = ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx], idx);
93 	dflt = ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx], idx);
94 
95 	switch (flow_type) {
96 	case BNXT_ULP_FDB_TYPE_REGULAR:
97 		return (reg && !dflt);
98 	case BNXT_ULP_FDB_TYPE_DEFAULT:
99 		return (!reg && dflt);
100 	case BNXT_ULP_FDB_TYPE_RID:
101 		return (reg && dflt);
102 	default:
103 		return 0;
104 	}
105 }
106 
107 static inline enum tf_dir
108 ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info)
109 {
110 	return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >>
111 		ULP_FLOW_DB_RES_DIR_BIT);
112 }
113 
114 static inline uint8_t
115 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
116 {
117 	return res_info->resource_func;
118 }
119 
120 /*
121  * Helper function to copy the resource params to resource info
122  *  No validation being done in this function.
123  *
124  * resource_info [out] Ptr to resource information
125  * params [in] The input params from the caller
126  * returns none
127  */
128 static void
129 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
130 			       struct ulp_flow_db_res_params *params)
131 {
132 	resource_info->nxt_resource_idx |= ((params->direction <<
133 				      ULP_FLOW_DB_RES_DIR_BIT) &
134 				     ULP_FLOW_DB_RES_DIR_MASK);
135 	resource_info->resource_func = params->resource_func;
136 	resource_info->resource_type = params->resource_type;
137 	resource_info->resource_sub_type = params->resource_sub_type;
138 	resource_info->fdb_flags = params->fdb_flags;
139 	resource_info->resource_hndl = params->resource_hndl;
140 }
141 
142 /*
143  * Helper function to copy the resource params to resource info
144  *  No validation being done in this function.
145  *
146  * resource_info [in] Ptr to resource information
147  * params [out] The output params to the caller
148  *
149  * returns none
150  */
151 static void
152 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
153 			       struct ulp_flow_db_res_params *params)
154 {
155 	memset(params, 0, sizeof(struct ulp_flow_db_res_params));
156 	/* use the helper function to get the resource func */
157 	params->direction = ulp_flow_db_resource_dir_get(resource_info);
158 	params->resource_func = ulp_flow_db_resource_func_get(resource_info);
159 	params->resource_type = resource_info->resource_type;
160 	params->resource_sub_type = resource_info->resource_sub_type;
161 	params->fdb_flags = resource_info->fdb_flags;
162 	params->resource_hndl = resource_info->resource_hndl;
163 }
164 
165 /*
166  * Helper function to allocate the flow table and initialize
167  * the stack for allocation operations.
168  *
169  * flow_db [in] Ptr to flow database structure
170  *
171  * Returns 0 on success or negative number on failure.
172  */
173 static int32_t
174 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db)
175 {
176 	uint32_t			idx = 0;
177 	struct bnxt_ulp_flow_tbl	*flow_tbl;
178 	uint32_t			size;
179 
180 	flow_tbl = &flow_db->flow_tbl;
181 
182 	size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
183 	flow_tbl->flow_resources =
184 			rte_zmalloc("ulp_fdb_resource_info", size, 0);
185 
186 	if (!flow_tbl->flow_resources) {
187 		BNXT_DRV_DBG(ERR, "Failed to alloc memory for flow table\n");
188 		return -ENOMEM;
189 	}
190 	size = sizeof(uint32_t) * flow_tbl->num_resources;
191 	flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
192 	if (!flow_tbl->flow_tbl_stack) {
193 		BNXT_DRV_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
194 		return -ENOMEM;
195 	}
196 	size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
197 	size = ULP_BYTE_ROUND_OFF_8(size);
198 	flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size,
199 						 ULP_BUFFER_ALIGN_64_BYTE);
200 	if (!flow_tbl->active_reg_flows) {
201 		BNXT_DRV_DBG(ERR, "Failed to alloc memory active reg flows\n");
202 		return -ENOMEM;
203 	}
204 
205 	flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size,
206 						  ULP_BUFFER_ALIGN_64_BYTE);
207 	if (!flow_tbl->active_dflt_flows) {
208 		BNXT_DRV_DBG(ERR, "Failed to alloc memory active dflt flows\n");
209 		return -ENOMEM;
210 	}
211 
212 	/* Initialize the stack table. */
213 	for (idx = 0; idx < flow_tbl->num_resources; idx++)
214 		flow_tbl->flow_tbl_stack[idx] = idx;
215 
216 	/* Ignore the first element in the list. */
217 	flow_tbl->head_index = 1;
218 	/* Tail points to the last entry in the list. */
219 	flow_tbl->tail_index = flow_tbl->num_resources - 1;
220 	return 0;
221 }
222 
223 /*
224  * Helper function to deallocate the flow table.
225  *
226  * flow_db [in] Ptr to flow database structure
227  *
228  * Returns none.
229  */
230 static void
231 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db)
232 {
233 	struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl;
234 
235 	/* Free all the allocated tables in the flow table. */
236 	if (flow_tbl->active_reg_flows) {
237 		rte_free(flow_tbl->active_reg_flows);
238 		flow_tbl->active_reg_flows = NULL;
239 	}
240 	if (flow_tbl->active_dflt_flows) {
241 		rte_free(flow_tbl->active_dflt_flows);
242 		flow_tbl->active_dflt_flows = NULL;
243 	}
244 
245 	if (flow_tbl->flow_tbl_stack) {
246 		rte_free(flow_tbl->flow_tbl_stack);
247 		flow_tbl->flow_tbl_stack = NULL;
248 	}
249 
250 	if (flow_tbl->flow_resources) {
251 		rte_free(flow_tbl->flow_resources);
252 		flow_tbl->flow_resources = NULL;
253 	}
254 }
255 
256 /*
257  * Helper function to add function id to the flow table
258  *
259  * flow_db [in] Ptr to flow table
260  * flow_id [in] The flow id of the flow
261  * func_id [in] The func_id to be set, for reset pass zero
262  *
263  * returns none
264  */
265 static void
266 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
267 			uint32_t flow_id,
268 			uint32_t func_id)
269 {
270 	/* set the function id in the function table */
271 	if (flow_id < flow_db->func_id_tbl_size)
272 		flow_db->func_id_tbl[flow_id] = func_id;
273 	else /* This should never happen */
274 		BNXT_DRV_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
275 }
276 
277 /*
278  * Initialize the parent-child database. Memory is allocated in this
279  * call and assigned to the database
280  *
281  * flow_db [in] Ptr to flow table
282  * num_entries[in] - number of entries to allocate
283  *
284  * Returns 0 on success or negative number on failure.
285  */
286 static int32_t
287 ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db,
288 			    uint32_t num_entries)
289 {
290 	struct ulp_fdb_parent_child_db *p_db;
291 	uint32_t size, idx;
292 
293 	if (!num_entries)
294 		return 0;
295 
296 	/* update the sizes for the allocation */
297 	p_db = &flow_db->parent_child_db;
298 	p_db->child_bitset_size = (flow_db->flow_tbl.num_flows /
299 				   sizeof(uint64_t)) + 1; /* size in bytes */
300 	p_db->child_bitset_size = ULP_BYTE_ROUND_OFF_8(p_db->child_bitset_size);
301 	p_db->entries_count = num_entries;
302 
303 	/* allocate the memory */
304 	p_db->parent_flow_tbl = rte_zmalloc("fdb parent flow tbl",
305 					    sizeof(struct ulp_fdb_parent_info) *
306 					    p_db->entries_count, 0);
307 	if (!p_db->parent_flow_tbl) {
308 		BNXT_DRV_DBG(ERR,
309 			     "Failed to allocate memory fdb parent flow tbl\n");
310 		return -ENOMEM;
311 	}
312 	size = p_db->child_bitset_size * p_db->entries_count;
313 
314 	/*
315 	 * allocate the big chunk of memory to be statically carved into
316 	 * child_fid_bitset pointer.
317 	 */
318 	p_db->parent_flow_tbl_mem = rte_zmalloc("fdb parent flow tbl mem",
319 						size,
320 						ULP_BUFFER_ALIGN_64_BYTE);
321 	if (!p_db->parent_flow_tbl_mem) {
322 		BNXT_DRV_DBG(ERR,
323 			     "Failed to allocate memory fdb parent flow mem\n");
324 		return -ENOMEM;
325 	}
326 
327 	/* set the pointers in parent table to their offsets */
328 	for (idx = 0 ; idx < p_db->entries_count; idx++) {
329 		p_db->parent_flow_tbl[idx].child_fid_bitset =
330 			(uint64_t *)&p_db->parent_flow_tbl_mem[idx *
331 			p_db->child_bitset_size];
332 	}
333 	/* success */
334 	return 0;
335 }
336 
337 /*
338  * Deinitialize the parent-child database. Memory is deallocated in
339  * this call and all flows should have been purged before this
340  * call.
341  *
342  * flow_db [in] Ptr to flow table
343  *
344  * Returns none
345  */
346 static void
347 ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db)
348 {
349 	/* free the memory related to parent child database */
350 	if (flow_db->parent_child_db.parent_flow_tbl_mem) {
351 		rte_free(flow_db->parent_child_db.parent_flow_tbl_mem);
352 		flow_db->parent_child_db.parent_flow_tbl_mem = NULL;
353 	}
354 	if (flow_db->parent_child_db.parent_flow_tbl) {
355 		rte_free(flow_db->parent_child_db.parent_flow_tbl);
356 		flow_db->parent_child_db.parent_flow_tbl = NULL;
357 	}
358 }
359 
360 /*
361  * Initialize the flow database. Memory is allocated in this
362  * call and assigned to the flow database.
363  *
364  * ulp_ctxt [in] Ptr to ulp context
365  *
366  * Returns 0 on success or negative number on failure.
367  */
368 int32_t
369 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
370 {
371 	struct bnxt_ulp_device_params *dparms;
372 	struct bnxt_ulp_flow_tbl *flow_tbl;
373 	struct bnxt_ulp_flow_db *flow_db;
374 	uint32_t dev_id, num_flows;
375 	enum bnxt_ulp_flow_mem_type mtype;
376 
377 	/* Get the dev specific number of flows that needed to be supported. */
378 	if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
379 		BNXT_DRV_DBG(ERR, "Invalid device id\n");
380 		return -EINVAL;
381 	}
382 
383 	dparms = bnxt_ulp_device_params_get(dev_id);
384 	if (!dparms) {
385 		BNXT_DRV_DBG(ERR, "could not fetch the device params\n");
386 		return -ENODEV;
387 	}
388 
389 	flow_db = rte_zmalloc("bnxt_ulp_flow_db",
390 			      sizeof(struct bnxt_ulp_flow_db), 0);
391 	if (!flow_db) {
392 		BNXT_DRV_DBG(ERR,
393 			     "Failed to allocate memory for flow table ptr\n");
394 		return -ENOMEM;
395 	}
396 
397 	/* Attach the flow database to the ulp context. */
398 	bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
399 
400 	/* Determine the number of flows based on EM type */
401 	if (bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype))
402 		goto error_free;
403 
404 	if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
405 		num_flows = dparms->int_flow_db_num_entries;
406 	else
407 		num_flows = dparms->ext_flow_db_num_entries;
408 
409 	/* Populate the regular flow table limits. */
410 	flow_tbl = &flow_db->flow_tbl;
411 	flow_tbl->num_flows = num_flows + 1;
412 	flow_tbl->num_resources = ((num_flows + 1) *
413 				   dparms->num_resources_per_flow);
414 
415 	/* Include the default flow table limits. */
416 	flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
417 	flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
418 				    BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
419 
420 	/* Allocate the resource for the flow table. */
421 	if (ulp_flow_db_alloc_resource(flow_db))
422 		goto error_free;
423 
424 	/* add 1 since we are not using index 0 for flow id */
425 	flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
426 	/* Allocate the function Id table */
427 	flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
428 					   flow_db->func_id_tbl_size *
429 					   sizeof(uint16_t), 0);
430 	if (!flow_db->func_id_tbl) {
431 		BNXT_DRV_DBG(ERR,
432 			     "Failed to allocate mem for flow table func id\n");
433 		goto error_free;
434 	}
435 	/* initialize the parent child database */
436 	if (ulp_flow_db_parent_tbl_init(flow_db,
437 					dparms->fdb_parent_flow_entries)) {
438 		BNXT_DRV_DBG(ERR,
439 			     "Failed to allocate mem for parent child db\n");
440 		goto error_free;
441 	}
442 
443 	/* All good so return. */
444 	BNXT_DRV_DBG(DEBUG, "FlowDB initialized with %d flows.\n",
445 		     flow_tbl->num_flows);
446 	return 0;
447 error_free:
448 	ulp_flow_db_deinit(ulp_ctxt);
449 	return -ENOMEM;
450 }
451 
452 /*
453  * Deinitialize the flow database. Memory is deallocated in
454  * this call and all flows should have been purged before this
455  * call.
456  *
457  * ulp_ctxt [in] Ptr to ulp context
458  *
459  * Returns 0 on success.
460  */
461 int32_t
462 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
463 {
464 	struct bnxt_ulp_flow_db *flow_db;
465 
466 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
467 	if (!flow_db)
468 		return -EINVAL;
469 
470 	/* Detach the flow database from the ulp context. */
471 	bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
472 
473 	/* Free up all the memory. */
474 	ulp_flow_db_parent_tbl_deinit(flow_db);
475 	ulp_flow_db_dealloc_resource(flow_db);
476 	rte_free(flow_db->func_id_tbl);
477 	rte_free(flow_db);
478 
479 	return 0;
480 }
481 
482 /*
483  * Allocate the flow database entry
484  *
485  * ulp_ctxt [in] Ptr to ulp_context
486  * flow_type [in] - specify default or regular
487  * func_id [in].function id of the ingress port
488  * fid [out] The index to the flow entry
489  *
490  * returns 0 on success and negative on failure.
491  */
492 int32_t
493 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
494 		      enum bnxt_ulp_fdb_type flow_type,
495 		      uint16_t func_id,
496 		      uint32_t *fid)
497 {
498 	struct bnxt_ulp_flow_db *flow_db;
499 	struct bnxt_ulp_flow_tbl *flow_tbl;
500 
501 	*fid = 0; /* Initialize fid to invalid value */
502 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
503 	if (!flow_db) {
504 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
505 		return -EINVAL;
506 	}
507 
508 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
509 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
510 		return -EINVAL;
511 	}
512 
513 	flow_tbl = &flow_db->flow_tbl;
514 	/* check for max flows */
515 	if (flow_tbl->num_flows <= flow_tbl->head_index) {
516 		BNXT_DRV_DBG(ERR, "Flow database has reached max flows\n");
517 		return -ENOMEM;
518 	}
519 	if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
520 		BNXT_DRV_DBG(ERR, "Flow database has reached max resources\n");
521 		return -ENOMEM;
522 	}
523 	*fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
524 	flow_tbl->head_index++;
525 
526 	/* Set the flow type */
527 	ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
528 
529 	/* function id update is only valid for regular flow table */
530 	if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
531 		ulp_flow_db_func_id_set(flow_db, *fid, func_id);
532 
533 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
534 	BNXT_DRV_DBG(DEBUG, "flow_id = %u:%u allocated\n", flow_type, *fid);
535 #endif
536 	/* return success */
537 	return 0;
538 }
539 
540 /*
541  * Allocate the flow database entry.
542  * The params->critical_resource has to be set to 0 to allocate a new resource.
543  *
544  * ulp_ctxt [in] Ptr to ulp_context
545  * flow_type [in] Specify it is regular or default flow
546  * fid [in] The index to the flow entry
547  * params [in] The contents to be copied into resource
548  *
549  * returns 0 on success and negative on failure.
550  */
551 int32_t
552 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
553 			 enum bnxt_ulp_fdb_type flow_type,
554 			 uint32_t fid,
555 			 struct ulp_flow_db_res_params *params)
556 {
557 	struct bnxt_ulp_flow_db *flow_db;
558 	struct bnxt_ulp_flow_tbl *flow_tbl;
559 	struct ulp_fdb_resource_info *resource, *fid_resource;
560 	struct bnxt_ulp_fc_info *ulp_fc_info;
561 	uint32_t idx;
562 
563 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
564 	if (!flow_db) {
565 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
566 		return -EINVAL;
567 	}
568 
569 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
570 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
571 		return -EINVAL;
572 	}
573 
574 	flow_tbl = &flow_db->flow_tbl;
575 	/* check for max flows */
576 	if (fid >= flow_tbl->num_flows || !fid) {
577 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
578 		return -EINVAL;
579 	}
580 
581 	/* check if the flow is active or not */
582 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
583 		BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type,
584 			     fid);
585 		return -EINVAL;
586 	}
587 
588 	/* check for max resource */
589 	if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
590 		BNXT_DRV_DBG(ERR, "Flow db has reached max resources\n");
591 		return -ENOMEM;
592 	}
593 	fid_resource = &flow_tbl->flow_resources[fid];
594 
595 	if (params->critical_resource && (fid_resource->fdb_flags &
596 					  ULP_FDB_FLAG_CRITICAL_RES)) {
597 		BNXT_DRV_DBG(DEBUG, "Ignore multiple critical resources\n");
598 		/* Ignore the multiple critical resources */
599 		params->critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
600 	}
601 
602 	if (!params->critical_resource) {
603 		/* Not the critical_resource so allocate a resource */
604 		idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
605 		resource = &flow_tbl->flow_resources[idx];
606 		flow_tbl->tail_index--;
607 
608 		/* Update the chain list of resource*/
609 		ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
610 					fid_resource->nxt_resource_idx);
611 		/* update the contents */
612 		ulp_flow_db_res_params_to_info(resource, params);
613 		ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
614 		ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
615 					idx);
616 	} else {
617 		/* critical resource. Just update the fid resource */
618 		ulp_flow_db_res_params_to_info(fid_resource, params);
619 		fid_resource->fdb_flags |= ULP_FDB_FLAG_CRITICAL_RES;
620 	}
621 
622 	ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ulp_ctxt);
623 	if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
624 	    params->resource_sub_type ==
625 	    BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT &&
626 	    ulp_fc_info && ulp_fc_info->num_counters) {
627 		/* Store the first HW counter ID for this table */
628 		if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
629 			ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
630 						 params->resource_hndl);
631 
632 		ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
633 				    params->resource_hndl,
634 				    ulp_flow_db_shared_session_get(params));
635 
636 		if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
637 			ulp_fc_mgr_thread_start(ulp_ctxt);
638 
639 		if (!ulp_sc_mgr_thread_isstarted(ulp_ctxt))
640 			ulp_sc_mgr_thread_start(ulp_ctxt);
641 	}
642 
643 	/* all good, return success */
644 	return 0;
645 }
646 
647 /*
648  * Free the flow database entry.
649  * The params->critical_resource has to be set to 1 to free the first resource.
650  *
651  * ulp_ctxt [in] Ptr to ulp_context
652  * flow_type [in] Specify it is regular or default flow
653  * fid [in] The index to the flow entry
654  * params [in/out] The contents to be copied into params.
655  * Only the critical_resource needs to be set by the caller.
656  *
657  * Returns 0 on success and negative on failure.
658  */
659 int32_t
660 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
661 			 enum bnxt_ulp_fdb_type flow_type,
662 			 uint32_t fid,
663 			 struct ulp_flow_db_res_params *params)
664 {
665 	struct bnxt_ulp_flow_db *flow_db;
666 	struct bnxt_ulp_flow_tbl *flow_tbl;
667 	struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
668 	uint32_t nxt_idx = 0;
669 
670 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
671 	if (!flow_db) {
672 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
673 		return -EINVAL;
674 	}
675 
676 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
677 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
678 		return -EINVAL;
679 	}
680 
681 	flow_tbl = &flow_db->flow_tbl;
682 	/* check for max flows */
683 	if (fid >= flow_tbl->num_flows || !fid) {
684 		BNXT_DRV_DBG(ERR, "Invalid flow index %x\n", fid);
685 		return -EINVAL;
686 	}
687 
688 	/* check if the flow is active or not */
689 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
690 		BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type,
691 			     fid);
692 		return -EINVAL;
693 	}
694 
695 	fid_resource = &flow_tbl->flow_resources[fid];
696 	if (!params->critical_resource) {
697 		/* Not the critical resource so free the resource */
698 		ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
699 					fid_resource->nxt_resource_idx);
700 		if (!nxt_idx) {
701 			/* reached end of resources */
702 			return -ENOENT;
703 		}
704 		nxt_resource = &flow_tbl->flow_resources[nxt_idx];
705 
706 		/* connect the fid resource to the next resource */
707 		ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
708 		ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
709 					nxt_resource->nxt_resource_idx);
710 
711 		/* update the contents to be given to caller */
712 		ulp_flow_db_res_info_to_params(nxt_resource, params);
713 
714 		/* Delete the nxt_resource */
715 		memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
716 
717 		/* add it to the free list */
718 		flow_tbl->tail_index++;
719 		if (flow_tbl->tail_index >= flow_tbl->num_resources) {
720 			BNXT_DRV_DBG(ERR, "FlowDB:Tail reached max\n");
721 			return -ENOENT;
722 		}
723 		flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
724 
725 	} else {
726 		/* Critical resource. copy the contents and exit */
727 		ulp_flow_db_res_info_to_params(fid_resource, params);
728 		ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
729 					fid_resource->nxt_resource_idx);
730 		memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
731 		ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
732 					nxt_idx);
733 	}
734 
735 	/* Now that the HW Flow counter resource is deleted, reset it's
736 	 * corresponding slot in the SW accumulation table in the Flow Counter
737 	 * manager
738 	 */
739 	if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
740 	    params->resource_sub_type ==
741 	    BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) {
742 		ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
743 				      params->resource_hndl);
744 	}
745 
746 	/* all good, return success */
747 	return 0;
748 }
749 
750 /*
751  * Free the flow database entry
752  *
753  * ulp_ctxt [in] Ptr to ulp_context
754  * flow_type [in] - specify default or regular
755  * fid [in] The index to the flow entry
756  *
757  * returns 0 on success and negative on failure.
758  */
759 int32_t
760 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
761 		     enum bnxt_ulp_fdb_type flow_type,
762 		     uint32_t fid)
763 {
764 	struct bnxt_ulp_flow_tbl *flow_tbl;
765 	struct bnxt_ulp_flow_db *flow_db;
766 
767 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
768 	if (!flow_db) {
769 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
770 		return -EINVAL;
771 	}
772 
773 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
774 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
775 		return -EINVAL;
776 	}
777 
778 	flow_tbl = &flow_db->flow_tbl;
779 
780 	/* check for limits of fid */
781 	if (fid >= flow_tbl->num_flows || !fid) {
782 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
783 		return -EINVAL;
784 	}
785 
786 	/* check if the flow is active or not */
787 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
788 		BNXT_DRV_DBG(ERR, "flow does not exist %x:%x\n", flow_type,
789 			     fid);
790 		return -EINVAL;
791 	}
792 	flow_tbl->head_index--;
793 	if (!flow_tbl->head_index) {
794 		BNXT_DRV_DBG(ERR, "FlowDB: Head Ptr is zero\n");
795 		return -ENOENT;
796 	}
797 
798 	flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
799 
800 	/* Clear the flows bitmap */
801 	ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
802 
803 	if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
804 		ulp_flow_db_func_id_set(flow_db, fid, 0);
805 
806 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
807 	BNXT_DRV_DBG(DEBUG, "flow_id = %u:%u freed\n", flow_type, fid);
808 #endif
809 	/* all good, return success */
810 	return 0;
811 }
812 
813 /*
814  *Get the flow database entry details
815  *
816  * ulp_ctxt [in] Ptr to ulp_context
817  * flow_type [in] - specify default or regular
818  * fid [in] The index to the flow entry
819  * nxt_idx [in/out] the index to the next entry
820  * params [out] The contents to be copied into params.
821  *
822  * returns 0 on success and negative on failure.
823  */
824 int32_t
825 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
826 			 enum bnxt_ulp_fdb_type flow_type,
827 			 uint32_t fid,
828 			 uint32_t *nxt_idx,
829 			 struct ulp_flow_db_res_params *params)
830 {
831 	struct bnxt_ulp_flow_db *flow_db;
832 	struct bnxt_ulp_flow_tbl *flow_tbl;
833 	struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
834 
835 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
836 	if (!flow_db) {
837 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
838 		return -EINVAL;
839 	}
840 
841 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
842 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
843 		return -EINVAL;
844 	}
845 
846 	flow_tbl = &flow_db->flow_tbl;
847 
848 	/* check for limits of fid */
849 	if (fid >= flow_tbl->num_flows || !fid) {
850 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
851 		return -EINVAL;
852 	}
853 
854 	/* check if the flow is active or not */
855 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
856 		BNXT_DRV_DBG(ERR, "flow does not exist\n");
857 		return -EINVAL;
858 	}
859 
860 	if (!*nxt_idx) {
861 		fid_resource = &flow_tbl->flow_resources[fid];
862 		ulp_flow_db_res_info_to_params(fid_resource, params);
863 		ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
864 					fid_resource->nxt_resource_idx);
865 	} else {
866 		nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
867 		ulp_flow_db_res_info_to_params(nxt_resource, params);
868 		*nxt_idx = 0;
869 		ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
870 					nxt_resource->nxt_resource_idx);
871 	}
872 
873 	/* all good, return success */
874 	return 0;
875 }
876 
877 /*
878  * Get the flow database entry iteratively
879  *
880  * flow_tbl [in] Ptr to flow table
881  * flow_type [in] - specify default or regular
882  * fid [in/out] The index to the flow entry
883  *
884  * returns 0 on success and negative on failure.
885  */
886 static int32_t
887 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
888 			   enum bnxt_ulp_fdb_type flow_type,
889 			   uint32_t *fid)
890 {
891 	uint32_t lfid = *fid;
892 	uint32_t idx, s_idx, mod_fid;
893 	uint64_t bs;
894 	uint64_t *active_flows;
895 	struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
896 
897 	if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) {
898 		active_flows = flowtbl->active_reg_flows;
899 	} else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) {
900 		active_flows = flowtbl->active_dflt_flows;
901 	} else {
902 		BNXT_DRV_DBG(ERR, "Invalid flow type %x\n", flow_type);
903 			return -EINVAL;
904 	}
905 
906 	do {
907 		/* increment the flow id to find the next valid flow id */
908 		lfid++;
909 		if (lfid >= flowtbl->num_flows)
910 			return -ENOENT;
911 		idx = lfid / ULP_INDEX_BITMAP_SIZE;
912 		mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
913 		s_idx = idx;
914 		while (!(bs = active_flows[idx])) {
915 			idx++;
916 			if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
917 				return -ENOENT;
918 		}
919 		/*
920 		 * remove the previous bits in the bitset bs to find the
921 		 * next non zero bit in the bitset. This needs to be done
922 		 * only if the idx is same as he one you started.
923 		 */
924 		if (s_idx == idx)
925 			bs &= (-1UL >> mod_fid);
926 		lfid = (idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs);
927 		if (*fid >= lfid) {
928 			BNXT_DRV_DBG(ERR, "Flow Database is corrupt\n");
929 			return -ENOENT;
930 		}
931 	} while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
932 						      lfid));
933 
934 	/* all good, return success */
935 	*fid = lfid;
936 	return 0;
937 }
938 
939 /*
940  * Flush all flows in the flow database.
941  *
942  * ulp_ctxt [in] Ptr to ulp context
943  * flow_type [in] - specify default or regular
944  *
945  * returns 0 on success or negative number on failure
946  */
947 int32_t
948 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
949 			enum bnxt_ulp_fdb_type flow_type)
950 {
951 	uint32_t fid = 0;
952 	struct bnxt_ulp_flow_db *flow_db;
953 
954 	if (!ulp_ctx) {
955 		BNXT_DRV_DBG(ERR, "Invalid Argument\n");
956 		return -EINVAL;
957 	}
958 
959 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
960 	if (!flow_db) {
961 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
962 		return -EINVAL;
963 	}
964 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
965 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
966 		return -EINVAL;
967 	}
968 
969 #ifdef TF_FLOW_SCALE_QUERY
970 	tf_resc_pause_usage_update();
971 #endif
972 
973 	while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
974 		ulp_mapper_resources_free(ulp_ctx, flow_type, fid, NULL);
975 
976 #ifdef TF_FLOW_SCALE_QUERY
977 	ulp_resc_usage_sync(ulp_ctx);
978 #endif
979 
980 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
981 
982 	return 0;
983 }
984 
985 /*
986  * Flush all flows in the flow database that belong to a device function.
987  *
988  * ulp_ctxt [in] Ptr to ulp context
989  * func_id [in] - The port function id
990  *
991  * returns 0 on success or negative number on failure
992  */
993 int32_t
994 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
995 				uint16_t func_id)
996 {
997 	uint32_t flow_id = 0;
998 	struct bnxt_ulp_flow_db *flow_db;
999 
1000 	if (!ulp_ctx || !func_id) {
1001 		BNXT_DRV_DBG(ERR, "Invalid Argument\n");
1002 		return -EINVAL;
1003 	}
1004 
1005 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1006 	if (!flow_db) {
1007 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
1008 		return -EINVAL;
1009 	}
1010 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
1011 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
1012 		return -EINVAL;
1013 	}
1014 
1015 #ifdef TF_FLOW_SCALE_QUERY
1016 	tf_resc_pause_usage_update();
1017 #endif
1018 	while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
1019 					   &flow_id)) {
1020 		if (flow_db->func_id_tbl[flow_id] == func_id)
1021 			ulp_mapper_resources_free(ulp_ctx,
1022 						  BNXT_ULP_FDB_TYPE_REGULAR,
1023 						  flow_id,
1024 						  NULL);
1025 	}
1026 #ifdef TF_FLOW_SCALE_QUERY
1027 	ulp_resc_usage_sync(ulp_ctx);
1028 #endif
1029 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
1030 	return 0;
1031 }
1032 
1033 /*
1034  * Flush all flows in the flow database that are associated with the session.
1035  *
1036  * ulp_ctxt [in] Ptr to ulp context
1037  *
1038  * returns 0 on success or negative number on failure
1039  */
1040 int32_t
1041 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
1042 {
1043 	/*
1044 	 * TBD: Tf core implementation of FW session flush shall change this
1045 	 * implementation.
1046 	 */
1047 	return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1048 }
1049 
1050 /*
1051  * Check that flow id matches the function id or not
1052  *
1053  * ulp_ctxt [in] Ptr to ulp context
1054  * flow_db [in] Ptr to flow table
1055  * func_id [in] The func_id to be set, for reset pass zero.
1056  *
1057  * returns true on success or false on failure
1058  */
1059 bool
1060 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
1061 			       uint32_t flow_id,
1062 			       uint32_t func_id)
1063 {
1064 	struct bnxt_ulp_flow_db *flow_db;
1065 
1066 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1067 	if (!flow_db) {
1068 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
1069 		return false;
1070 	}
1071 
1072 	/* set the function id in the function table */
1073 	if (flow_id < flow_db->func_id_tbl_size && func_id &&
1074 	    flow_db->func_id_tbl[flow_id] == func_id)
1075 		return true;
1076 
1077 	return false;
1078 }
1079 
1080 /*
1081  * Internal api to traverse the resource list within a flow
1082  * and match a resource based on resource func and resource
1083  * sub type. This api should be used only for resources that
1084  * are unique and do not have multiple instances of resource
1085  * func and sub type combination since it will return only
1086  * the first match.
1087  */
1088 static int32_t
1089 ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,
1090 				enum bnxt_ulp_fdb_type flow_type,
1091 				uint32_t flow_id,
1092 				uint32_t resource_func,
1093 				uint32_t res_subtype,
1094 				struct ulp_flow_db_res_params *params)
1095 {
1096 	struct bnxt_ulp_flow_db *flow_db;
1097 	struct bnxt_ulp_flow_tbl *flow_tbl;
1098 	struct ulp_fdb_resource_info *fid_res;
1099 	uint32_t res_id;
1100 
1101 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1102 	if (!flow_db) {
1103 		BNXT_DRV_DBG(ERR, "Flow database not found\n");
1104 		return -EINVAL;
1105 	}
1106 
1107 	if (!params) {
1108 		BNXT_DRV_DBG(ERR, "invalid argument\n");
1109 		return -EINVAL;
1110 	}
1111 
1112 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1113 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
1114 		return -EINVAL;
1115 	}
1116 
1117 	flow_tbl = &flow_db->flow_tbl;
1118 
1119 	/* check for limits of fid */
1120 	if (flow_id >= flow_tbl->num_flows || !flow_id) {
1121 		BNXT_DRV_DBG(ERR, "Invalid flow index\n");
1122 		return -EINVAL;
1123 	}
1124 
1125 	/* check if the flow is active or not */
1126 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
1127 		BNXT_DRV_DBG(ERR, "flow does not exist\n");
1128 		return -EINVAL;
1129 	}
1130 	/* Iterate the resource to get the resource handle */
1131 	res_id =  flow_id;
1132 	memset(params, 0, sizeof(struct ulp_flow_db_res_params));
1133 	while (res_id) {
1134 		fid_res = &flow_tbl->flow_resources[res_id];
1135 		if (ulp_flow_db_resource_func_get(fid_res) == resource_func &&
1136 		    fid_res->resource_sub_type == res_subtype) {
1137 			ulp_flow_db_res_info_to_params(fid_res, params);
1138 			return 0;
1139 		}
1140 		res_id = 0;
1141 		ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1142 	}
1143 	return -ENOENT;
1144 }
1145 
1146 /*
1147  * Api to get the cfa action pointer from a flow.
1148  *
1149  * ulp_ctxt [in] Ptr to ulp context
1150  * flow_id [in] flow id
1151  * cfa_action [out] The resource handle stored in the flow database
1152  *
1153  * returns 0 on success
1154  */
1155 int32_t
1156 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1157 				   uint32_t flow_id,
1158 				   uint32_t *cfa_action)
1159 {
1160 	uint8_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_VFR_CFA_ACTION;
1161 	struct ulp_flow_db_res_params params;
1162 	int32_t rc;
1163 
1164 	rc = ulp_flow_db_resource_params_get(ulp_ctx,
1165 					     BNXT_ULP_FDB_TYPE_DEFAULT,
1166 					     flow_id,
1167 					     BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1168 					     sub_typ, &params);
1169 	if (rc) {
1170 		BNXT_DRV_DBG(DEBUG, "CFA Action ptr not found for flow id %u\n",
1171 			     flow_id);
1172 		return -ENOENT;
1173 	}
1174 	*cfa_action = params.resource_hndl;
1175 	return 0;
1176 }
1177 
1178 /* internal validation function for parent flow tbl */
1179 struct ulp_fdb_parent_info *
1180 ulp_flow_db_pc_db_entry_get(struct bnxt_ulp_context *ulp_ctxt,
1181 			    uint32_t pc_idx)
1182 {
1183 	struct bnxt_ulp_flow_db *flow_db;
1184 
1185 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1186 	if (!flow_db) {
1187 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1188 		return NULL;
1189 	}
1190 
1191 	/* check for max flows */
1192 	if (pc_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) {
1193 		BNXT_DRV_DBG(ERR, "Invalid tunnel index\n");
1194 		return NULL;
1195 	}
1196 
1197 	/* No support for parent child db then just exit */
1198 	if (!flow_db->parent_child_db.entries_count) {
1199 		BNXT_DRV_DBG(ERR, "parent child db not supported\n");
1200 		return NULL;
1201 	}
1202 	if (!flow_db->parent_child_db.parent_flow_tbl[pc_idx].valid) {
1203 		BNXT_DRV_DBG(ERR, "Not a valid tunnel index\n");
1204 		return NULL;
1205 	}
1206 
1207 	return &flow_db->parent_child_db.parent_flow_tbl[pc_idx];
1208 }
1209 
1210 /* internal validation function for parent flow tbl */
1211 static struct bnxt_ulp_flow_db *
1212 ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt,
1213 				  uint32_t tun_idx)
1214 {
1215 	struct bnxt_ulp_flow_db *flow_db;
1216 
1217 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1218 	if (!flow_db) {
1219 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1220 		return NULL;
1221 	}
1222 
1223 	/* check for max flows */
1224 	if (tun_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) {
1225 		BNXT_DRV_DBG(ERR, "Invalid tunnel index\n");
1226 		return NULL;
1227 	}
1228 
1229 	/* No support for parent child db then just exit */
1230 	if (!flow_db->parent_child_db.entries_count) {
1231 		BNXT_DRV_DBG(ERR, "parent child db not supported\n");
1232 		return NULL;
1233 	}
1234 
1235 	return flow_db;
1236 }
1237 
1238 /*
1239  * Allocate the entry in the parent-child database
1240  *
1241  * ulp_ctxt [in] Ptr to ulp_context
1242  * tun_idx [in] The tunnel index of the flow entry
1243  *
1244  * returns index on success and negative on failure.
1245  */
1246 static int32_t
1247 ulp_flow_db_pc_db_idx_alloc(struct bnxt_ulp_context *ulp_ctxt,
1248 			    uint32_t tun_idx)
1249 {
1250 	struct bnxt_ulp_flow_db *flow_db;
1251 	struct ulp_fdb_parent_child_db *p_pdb;
1252 	uint32_t idx, free_idx = 0;
1253 
1254 	/* validate the arguments */
1255 	flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, tun_idx);
1256 	if (!flow_db) {
1257 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1258 		return -EINVAL;
1259 	}
1260 
1261 	p_pdb = &flow_db->parent_child_db;
1262 	for (idx = 0; idx < p_pdb->entries_count; idx++) {
1263 		if (p_pdb->parent_flow_tbl[idx].valid &&
1264 		    p_pdb->parent_flow_tbl[idx].tun_idx == tun_idx) {
1265 			return idx;
1266 		}
1267 		if (!p_pdb->parent_flow_tbl[idx].valid && !free_idx)
1268 			free_idx = idx + 1;
1269 	}
1270 	/* no free slots */
1271 	if (!free_idx) {
1272 		BNXT_DRV_DBG(ERR, "parent child db is full\n");
1273 		return -ENOMEM;
1274 	}
1275 
1276 	free_idx -= 1;
1277 	/* set the Fid in the parent child */
1278 	p_pdb->parent_flow_tbl[free_idx].tun_idx = tun_idx;
1279 	p_pdb->parent_flow_tbl[free_idx].valid = 1;
1280 	return free_idx;
1281 }
1282 
1283 /*
1284  * Free the entry in the parent-child database
1285  *
1286  * pc_entry [in] Ptr to parent child db entry
1287  *
1288  * returns none.
1289  */
1290 static void
1291 ulp_flow_db_pc_db_entry_free(struct bnxt_ulp_context *ulp_ctxt,
1292 			     struct ulp_fdb_parent_info *pc_entry)
1293 {
1294 	struct bnxt_tun_cache_entry *tun_tbl;
1295 	struct bnxt_ulp_flow_db *flow_db;
1296 	uint64_t *tmp_bitset;
1297 
1298 	/* free the tunnel entry */
1299 	tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);
1300 	if (tun_tbl)
1301 		ulp_tunnel_offload_entry_clear(tun_tbl, pc_entry->tun_idx);
1302 
1303 	/* free the child bitset*/
1304 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1305 	if (flow_db)
1306 		memset(pc_entry->child_fid_bitset, 0,
1307 		       flow_db->parent_child_db.child_bitset_size);
1308 
1309 	/* free the contents */
1310 	tmp_bitset = pc_entry->child_fid_bitset;
1311 	memset(pc_entry, 0, sizeof(struct ulp_fdb_parent_info));
1312 	pc_entry->child_fid_bitset = tmp_bitset;
1313 }
1314 
1315 /*
1316  * Set or reset the parent flow in the parent-child database
1317  *
1318  * ulp_ctxt [in] Ptr to ulp_context
1319  * pc_idx [in] The index to parent child db
1320  * parent_fid [in] The flow id of the parent flow entry
1321  * set_flag [in] Use 1 for setting child, 0 to reset
1322  *
1323  * returns zero on success and negative on failure.
1324  */
1325 int32_t
1326 ulp_flow_db_pc_db_parent_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1327 				  uint32_t pc_idx,
1328 				  uint32_t parent_fid,
1329 				  uint32_t set_flag)
1330 {
1331 	struct ulp_fdb_parent_info *pc_entry;
1332 	struct bnxt_ulp_flow_db *flow_db;
1333 
1334 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1335 	if (!flow_db) {
1336 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1337 		return -EINVAL;
1338 	}
1339 
1340 	/* check for fid validity */
1341 	if (parent_fid >= flow_db->flow_tbl.num_flows || !parent_fid) {
1342 		BNXT_DRV_DBG(ERR, "Invalid parent flow index %x\n", parent_fid);
1343 		return -EINVAL;
1344 	}
1345 
1346 	/* validate the arguments and parent child entry */
1347 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1348 	if (!pc_entry) {
1349 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1350 		return -EINVAL;
1351 	}
1352 
1353 	if (set_flag) {
1354 		pc_entry->parent_fid = parent_fid;
1355 		pc_entry->parent_ref_cnt++;
1356 	} else {
1357 		if (pc_entry->parent_ref_cnt > 0)
1358 			pc_entry->parent_ref_cnt--;
1359 		/* Free the parent child db entry if no user present */
1360 		if (!pc_entry->parent_ref_cnt && !pc_entry->f2_cnt)
1361 			ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry);
1362 	}
1363 	return 0;
1364 }
1365 
1366 /*
1367  * Set or reset the child flow in the parent-child database
1368  *
1369  * ulp_ctxt [in] Ptr to ulp_context
1370  * pc_idx [in] The index to parent child db
1371  * child_fid [in] The flow id of the child flow entry
1372  * set_flag [in] Use 1 for setting child, 0 to reset
1373  *
1374  * returns zero on success and negative on failure.
1375  */
1376 int32_t
1377 ulp_flow_db_pc_db_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1378 				 uint32_t pc_idx,
1379 				 uint32_t child_fid,
1380 				 uint32_t set_flag)
1381 {
1382 	struct ulp_fdb_parent_info *pc_entry;
1383 	struct bnxt_ulp_flow_db *flow_db;
1384 	uint32_t a_idx;
1385 	uint64_t *t;
1386 
1387 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1388 	if (!flow_db) {
1389 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1390 		return -EINVAL;
1391 	}
1392 
1393 	/* check for fid validity */
1394 	if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) {
1395 		BNXT_DRV_DBG(ERR, "Invalid child flow index %x\n", child_fid);
1396 		return -EINVAL;
1397 	}
1398 
1399 	/* validate the arguments and parent child entry */
1400 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1401 	if (!pc_entry) {
1402 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1403 		return -EINVAL;
1404 	}
1405 
1406 	a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
1407 	t = pc_entry->child_fid_bitset;
1408 	if (set_flag) {
1409 		ULP_INDEX_BITMAP_SET(t[a_idx], child_fid);
1410 		pc_entry->f2_cnt++;
1411 	} else {
1412 		ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid);
1413 		if (pc_entry->f2_cnt)
1414 			pc_entry->f2_cnt--;
1415 		if (!pc_entry->f2_cnt && !pc_entry->parent_ref_cnt)
1416 			ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry);
1417 	}
1418 	return 0;
1419 }
1420 
1421 /*
1422  * Get the next child flow in the parent-child database
1423  *
1424  * ulp_ctxt [in] Ptr to ulp_context
1425  * parent_fid [in] The flow id of the parent flow entry
1426  * child_fid [in/out] The flow id of the child flow entry
1427  *
1428  * returns zero on success and negative on failure.
1429  * Pass child_fid as zero for first entry.
1430  */
1431 int32_t
1432 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1433 					     uint32_t parent_idx,
1434 					     uint32_t *child_fid)
1435 {
1436 	struct ulp_fdb_parent_child_db *p_pdb;
1437 	uint32_t idx, s_idx, mod_fid;
1438 	uint32_t next_fid = *child_fid;
1439 	uint64_t *child_bitset;
1440 	uint64_t bs;
1441 
1442 	/* check for fid validity */
1443 	p_pdb = &flow_db->parent_child_db;
1444 	if (parent_idx >= p_pdb->entries_count ||
1445 	    !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1446 		BNXT_DRV_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1447 		return -EINVAL;
1448 	}
1449 
1450 	child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset;
1451 	do {
1452 		/* increment the flow id to find the next valid flow id */
1453 		next_fid++;
1454 		if (next_fid >= flow_db->flow_tbl.num_flows)
1455 			return -ENOENT;
1456 		idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1457 		mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE;
1458 		s_idx = idx;
1459 		while (!(bs = child_bitset[idx])) {
1460 			idx++;
1461 			if ((idx * ULP_INDEX_BITMAP_SIZE) >=
1462 			    flow_db->flow_tbl.num_flows)
1463 				return -ENOENT;
1464 		}
1465 		/*
1466 		 * remove the previous bits in the bitset bs to find the
1467 		 * next non zero bit in the bitset. This needs to be done
1468 		 * only if the idx is same as he one you started.
1469 		 */
1470 		if (s_idx == idx)
1471 			bs &= (-1UL >> mod_fid);
1472 		next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + rte_clz64(bs);
1473 		if (*child_fid >= next_fid) {
1474 			BNXT_DRV_DBG(ERR, "Parent Child Database is corrupt\n");
1475 			return -ENOENT;
1476 		}
1477 		idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1478 	} while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid));
1479 	*child_fid = next_fid;
1480 	return 0;
1481 }
1482 
1483 /*
1484  * Set the counter accumulation in the parent flow
1485  *
1486  * ulp_ctxt [in] Ptr to ulp_context
1487  * pc_idx [in] The parent child index of the parent flow entry
1488  *
1489  * returns index on success and negative on failure.
1490  */
1491 static int32_t
1492 ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt,
1493 					uint32_t pc_idx)
1494 {
1495 	struct bnxt_ulp_flow_db *flow_db;
1496 	struct ulp_fdb_parent_child_db *p_pdb;
1497 
1498 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1499 	if (!flow_db) {
1500 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1501 		return -EINVAL;
1502 	}
1503 
1504 	/* check for parent idx validity */
1505 	p_pdb = &flow_db->parent_child_db;
1506 	if (pc_idx >= p_pdb->entries_count ||
1507 	    !p_pdb->parent_flow_tbl[pc_idx].parent_ref_cnt) {
1508 		BNXT_DRV_DBG(ERR, "Invalid parent child index %x\n", pc_idx);
1509 		return -EINVAL;
1510 	}
1511 
1512 	p_pdb->parent_flow_tbl[pc_idx].counter_acc = 1;
1513 	return 0;
1514 }
1515 
1516 /*
1517  * Orphan the child flow entry
1518  * This is called only for child flows that have
1519  * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
1520  *
1521  * ulp_ctxt [in] Ptr to ulp_context
1522  * flow_type [in] Specify it is regular or default flow
1523  * fid [in] The index to the flow entry
1524  *
1525  * Returns 0 on success and negative on failure.
1526  */
1527 int32_t
1528 ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
1529 			     enum bnxt_ulp_fdb_type flow_type,
1530 			     uint32_t fid)
1531 {
1532 	struct bnxt_ulp_flow_db *flow_db;
1533 	struct bnxt_ulp_flow_tbl *flow_tbl;
1534 	struct ulp_fdb_resource_info *fid_res;
1535 	uint32_t res_id = 0;
1536 
1537 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1538 	if (!flow_db) {
1539 		BNXT_DRV_DBG(ERR, "Invalid Arguments\n");
1540 		return -EINVAL;
1541 	}
1542 
1543 	if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1544 		BNXT_DRV_DBG(ERR, "Invalid flow type\n");
1545 		return -EINVAL;
1546 	}
1547 
1548 	flow_tbl = &flow_db->flow_tbl;
1549 	/* check for max flows */
1550 	if (fid >= flow_tbl->num_flows || !fid) {
1551 		BNXT_DRV_DBG(ERR, "Invalid flow index %x\n", fid);
1552 		return -EINVAL;
1553 	}
1554 
1555 	/* check if the flow is active or not */
1556 	if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
1557 		BNXT_DRV_DBG(ERR, "flow does not exist\n");
1558 		return -EINVAL;
1559 	}
1560 
1561 	/* Iterate the resource to get the resource handle */
1562 	res_id =  fid;
1563 	while (res_id) {
1564 		fid_res = &flow_tbl->flow_resources[res_id];
1565 		if (ulp_flow_db_resource_func_get(fid_res) ==
1566 		    BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) {
1567 			/* invalidate the resource details */
1568 			fid_res->resource_hndl = 0;
1569 			return 0;
1570 		}
1571 		res_id = 0;
1572 		ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1573 	}
1574 	/* failed */
1575 	return -1;
1576 }
1577 
1578 /*
1579  * Create parent flow in the parent flow tbl
1580  *
1581  * parms [in] Ptr to mapper params
1582  *
1583  * Returns 0 on success and negative on failure.
1584  */
1585 int32_t
1586 ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)
1587 {
1588 	struct ulp_flow_db_res_params fid_parms;
1589 	uint32_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1590 	struct ulp_flow_db_res_params res_params;
1591 	int32_t pc_idx;
1592 
1593 	/* create or get the parent child database */
1594 	pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx);
1595 	if (pc_idx < 0) {
1596 		BNXT_DRV_DBG(ERR, "Error in getting parent child db %x\n",
1597 			     parms->tun_idx);
1598 		return -EINVAL;
1599 	}
1600 
1601 	/* Update the parent fid */
1602 	if (ulp_flow_db_pc_db_parent_flow_set(parms->ulp_ctx, pc_idx,
1603 					      parms->flow_id, 1)) {
1604 		BNXT_DRV_DBG(ERR, "Error in setting parent fid %x\n",
1605 			     parms->tun_idx);
1606 		return -EINVAL;
1607 	}
1608 
1609 	/* Add the parent details in the resource list of the flow */
1610 	memset(&fid_parms, 0, sizeof(fid_parms));
1611 	fid_parms.resource_func	= BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW;
1612 	fid_parms.resource_hndl	= pc_idx;
1613 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1614 	if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
1615 				     parms->flow_id, &fid_parms)) {
1616 		BNXT_DRV_DBG(ERR, "Error in adding flow res for flow id %x\n",
1617 			     parms->flow_id);
1618 		return -1;
1619 	}
1620 
1621 	/* check of the flow has internal counter accumulation enabled */
1622 	if (!ulp_flow_db_resource_params_get(parms->ulp_ctx,
1623 					     BNXT_ULP_FDB_TYPE_REGULAR,
1624 					     parms->flow_id,
1625 					     BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1626 					     sub_typ,
1627 					     &res_params)) {
1628 		/* Enable the counter accumulation in parent entry */
1629 		if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx,
1630 							    pc_idx)) {
1631 			BNXT_DRV_DBG(ERR, "Error in setting counter acc %x\n",
1632 				     parms->flow_id);
1633 			return -1;
1634 		}
1635 	}
1636 
1637 	/* Set parent flow entry idx in stats cache entry */
1638 	ulp_sc_mgr_set_pc_idx(parms->ulp_ctx, parms->flow_id, pc_idx);
1639 	return 0;
1640 }
1641 
1642 /*
1643  * Create child flow in the parent flow tbl
1644  *
1645  * parms [in] Ptr to mapper params
1646  *
1647  * Returns 0 on success and negative on failure.
1648  */
1649 int32_t
1650 ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms)
1651 {
1652 	struct ulp_flow_db_res_params fid_parms;
1653 	uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1654 	enum bnxt_ulp_resource_func res_fun;
1655 	struct ulp_flow_db_res_params res_p;
1656 	int32_t rc, pc_idx;
1657 
1658 	/* create or get the parent child database */
1659 	pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx);
1660 	if (pc_idx < 0) {
1661 		BNXT_DRV_DBG(ERR, "Error in getting parent child db %x\n",
1662 			     parms->tun_idx);
1663 		return -1;
1664 	}
1665 
1666 	/* create the parent flow entry in parent flow table */
1667 	rc = ulp_flow_db_pc_db_child_flow_set(parms->ulp_ctx, pc_idx,
1668 					      parms->flow_id, 1);
1669 	if (rc) {
1670 		BNXT_DRV_DBG(ERR, "Error in setting child fid %x\n",
1671 			     parms->flow_id);
1672 		return rc;
1673 	}
1674 
1675 	/* Add the parent details in the resource list of the flow */
1676 	memset(&fid_parms, 0, sizeof(fid_parms));
1677 	fid_parms.resource_func	= BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW;
1678 	fid_parms.resource_hndl	= pc_idx;
1679 	fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1680 	rc  = ulp_flow_db_resource_add(parms->ulp_ctx,
1681 				       BNXT_ULP_FDB_TYPE_REGULAR,
1682 				       parms->flow_id, &fid_parms);
1683 	if (rc) {
1684 		BNXT_DRV_DBG(ERR, "Error in adding flow res for flow id %x\n",
1685 			     parms->flow_id);
1686 		return rc;
1687 	}
1688 
1689 	/* check if internal count action included for this flow.*/
1690 	res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE;
1691 	rc = ulp_flow_db_resource_params_get(parms->ulp_ctx,
1692 					     BNXT_ULP_FDB_TYPE_REGULAR,
1693 					     parms->flow_id,
1694 					     res_fun,
1695 					     sub_type,
1696 					     &res_p);
1697 	if (!rc) {
1698 		/* update the counter manager to include parent fid */
1699 		if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx,
1700 						    res_p.direction,
1701 						    res_p.resource_hndl,
1702 						    pc_idx)) {
1703 			BNXT_DRV_DBG(ERR, "Error in setting child %x\n",
1704 				     parms->flow_id);
1705 			return -1;
1706 		}
1707 	}
1708 
1709 	/* return success */
1710 	return 0;
1711 }
1712 
1713 /*
1714  * Update the parent counters
1715  *
1716  * ulp_ctxt [in] Ptr to ulp_context
1717  * pc_idx [in] The parent flow entry idx
1718  * packet_count [in] - packet count
1719  * byte_count [in] - byte count
1720  *
1721  * returns 0 on success
1722  */
1723 int32_t
1724 ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt,
1725 				     uint32_t pc_idx,
1726 				     uint64_t packet_count,
1727 				     uint64_t byte_count)
1728 {
1729 	struct ulp_fdb_parent_info *pc_entry;
1730 
1731 	/* validate the arguments and get parent child entry */
1732 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1733 	if (!pc_entry) {
1734 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1735 		return -EINVAL;
1736 	}
1737 
1738 	if (pc_entry->counter_acc) {
1739 		pc_entry->pkt_count += packet_count;
1740 		pc_entry->byte_count += byte_count;
1741 	}
1742 	return 0;
1743 }
1744 
1745 /*
1746  * Get the parent accumulation counters
1747  *
1748  * ulp_ctxt [in] Ptr to ulp_context
1749  * pc_idx [in] The parent flow entry idx
1750  * packet_count [out] - packet count
1751  * byte_count [out] - byte count
1752  *
1753  * returns 0 on success
1754  */
1755 int32_t
1756 ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,
1757 				  uint32_t flow_id,
1758 				  uint32_t pc_idx, uint64_t *packet_count,
1759 				  uint64_t *byte_count, uint8_t count_reset)
1760 {
1761 	struct ulp_fdb_parent_info *pc_entry;
1762 
1763 	/* validate the arguments and get parent child entry */
1764 	pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1765 	if (!pc_entry) {
1766 		BNXT_DRV_DBG(ERR, "failed to get the parent child entry\n");
1767 		return -EINVAL;
1768 	}
1769 
1770 	/* stale parent fid */
1771 	if (flow_id != pc_entry->parent_fid) {
1772 		*packet_count = 0;
1773 		*byte_count = 0;
1774 		return 0;
1775 	}
1776 
1777 	if (pc_entry->counter_acc) {
1778 		*packet_count = pc_entry->pkt_count;
1779 		*byte_count = pc_entry->byte_count;
1780 		if (count_reset) {
1781 			pc_entry->pkt_count = 0;
1782 			pc_entry->byte_count = 0;
1783 		}
1784 	}
1785 	return 0;
1786 }
1787 
1788 /*
1789  * reset the parent accumulation counters
1790  *
1791  * ulp_ctxt [in] Ptr to ulp_context
1792  *
1793  * returns none
1794  */
1795 void
1796 ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt)
1797 {
1798 	struct bnxt_ulp_flow_db *flow_db;
1799 	struct ulp_fdb_parent_child_db *p_pdb;
1800 	uint32_t idx;
1801 
1802 	/* validate the arguments */
1803 	flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1804 	if (!flow_db) {
1805 		BNXT_DRV_DBG(ERR, "parent child db validation failed\n");
1806 		return;
1807 	}
1808 
1809 	p_pdb = &flow_db->parent_child_db;
1810 	for (idx = 0; idx < p_pdb->entries_count; idx++) {
1811 		if (p_pdb->parent_flow_tbl[idx].valid &&
1812 		    p_pdb->parent_flow_tbl[idx].counter_acc) {
1813 			p_pdb->parent_flow_tbl[idx].pkt_count = 0;
1814 			p_pdb->parent_flow_tbl[idx].byte_count = 0;
1815 		}
1816 	}
1817 }
1818 
1819 /*
1820  * Set the shared bit for the flow db entry
1821  *
1822  * res [in] Ptr to fdb entry
1823  * shared [in] shared flag
1824  *
1825  * returns none
1826  */
1827 void ulp_flow_db_shared_session_set(struct ulp_flow_db_res_params *res,
1828 				    enum bnxt_ulp_session_type s_type)
1829 {
1830 	if (res && (s_type & BNXT_ULP_SESSION_TYPE_SHARED))
1831 		res->fdb_flags |= ULP_FDB_FLAG_SHARED_SESSION;
1832 	else if (res && (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC))
1833 		res->fdb_flags |= ULP_FDB_FLAG_SHARED_WC_SESSION;
1834 }
1835 
1836 /*
1837  * get the shared bit for the flow db entry
1838  *
1839  * res [in] Ptr to fdb entry
1840  *
1841  * returns session type
1842  */
1843 enum bnxt_ulp_session_type
1844 ulp_flow_db_shared_session_get(struct ulp_flow_db_res_params *res)
1845 {
1846 	enum bnxt_ulp_session_type stype = BNXT_ULP_SESSION_TYPE_DEFAULT;
1847 
1848 	if (res && (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION))
1849 		stype = BNXT_ULP_SESSION_TYPE_SHARED;
1850 	else if (res && (res->fdb_flags & ULP_FDB_FLAG_SHARED_WC_SESSION))
1851 		stype = BNXT_ULP_SESSION_TYPE_SHARED_WC;
1852 
1853 	return stype;
1854 }
1855