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