1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2020 Broadcom
6 #include <rte_malloc.h>
8 #include "bnxt_tf_common.h"
10 #include "ulp_template_struct.h"
11 #include "ulp_mapper.h"
12 #include "ulp_flow_db.h"
13 #include "ulp_fc_mgr.h"
15 #define ULP_FLOW_DB_RES_DIR_BIT 31
16 #define ULP_FLOW_DB_RES_DIR_MASK 0x80000000
17 #define ULP_FLOW_DB_RES_FUNC_BITS 28
18 #define ULP_FLOW_DB_RES_FUNC_MASK 0x70000000
19 #define ULP_FLOW_DB_RES_NXT_MASK 0x0FFFFFFF
20 #define ULP_FLOW_DB_RES_FUNC_UPPER 5
21 #define ULP_FLOW_DB_RES_FUNC_NEED_LOWER 0x80
22 #define ULP_FLOW_DB_RES_FUNC_LOWER_MASK 0x1F
24 /* Macro to copy the nxt_resource_idx */
25 #define ULP_FLOW_DB_RES_NXT_SET(dst, src) {(dst) |= ((src) &\
26 ULP_FLOW_DB_RES_NXT_MASK); }
27 #define ULP_FLOW_DB_RES_NXT_RESET(dst) ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
30 * Helper function to set the bit in the active flows
31 * No validation is done in this function.
33 * flow_db [in] Ptr to flow database
34 * flow_type [in] - specify default or regular
35 * idx [in] The index to bit to be set or reset.
36 * flag [in] 1 to set and 0 to reset.
41 ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db,
42 enum bnxt_ulp_fdb_type flow_type,
46 struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
47 uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
50 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
51 ULP_INDEX_BITMAP_SET(f_tbl->active_reg_flows[a_idx],
54 ULP_INDEX_BITMAP_SET(f_tbl->active_dflt_flows[a_idx],
57 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
58 ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx],
61 ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx],
67 * Helper function to check if given fid is active flow.
68 * No validation being done in this function.
70 * flow_db [in] Ptr to flow database
71 * flow_type [in] - specify default or regular
72 * idx [in] The index to bit to be set or reset.
74 * returns 1 on set or 0 if not set.
77 ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db,
78 enum bnxt_ulp_fdb_type flow_type,
81 struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
82 uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
84 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
85 return ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx],
88 return ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx],
92 static inline enum tf_dir
93 ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info)
95 return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >>
96 ULP_FLOW_DB_RES_DIR_BIT);
100 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
104 func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
105 ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
106 /* The reource func is split into upper and lower */
107 if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
108 return (func | res_info->resource_func_lower);
113 * Helper function to copy the resource params to resource info
114 * No validation being done in this function.
116 * resource_info [out] Ptr to resource information
117 * params [in] The input params from the caller
121 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
122 struct ulp_flow_db_res_params *params)
124 uint32_t resource_func;
126 resource_info->nxt_resource_idx |= ((params->direction <<
127 ULP_FLOW_DB_RES_DIR_BIT) &
128 ULP_FLOW_DB_RES_DIR_MASK);
129 resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
130 resource_info->nxt_resource_idx |= ((resource_func <<
131 ULP_FLOW_DB_RES_FUNC_BITS) &
132 ULP_FLOW_DB_RES_FUNC_MASK);
134 if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
135 /* Break the resource func into two parts */
136 resource_func = (params->resource_func &
137 ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
138 resource_info->resource_func_lower = resource_func;
141 /* Store the handle as 64bit only for EM table entries */
142 if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE &&
143 params->resource_func != BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
144 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
145 resource_info->resource_type = params->resource_type;
146 resource_info->resource_sub_type = params->resource_sub_type;
147 resource_info->reserved = params->reserved;
149 resource_info->resource_em_handle = params->resource_hndl;
154 * Helper function to copy the resource params to resource info
155 * No validation being done in this function.
157 * resource_info [in] Ptr to resource information
158 * params [out] The output params to the caller
163 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
164 struct ulp_flow_db_res_params *params)
166 memset(params, 0, sizeof(struct ulp_flow_db_res_params));
168 /* use the helper function to get the resource func */
169 params->direction = ulp_flow_db_resource_dir_get(resource_info);
170 params->resource_func = ulp_flow_db_resource_func_get(resource_info);
172 if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
173 params->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
174 params->resource_hndl = resource_info->resource_em_handle;
175 } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
176 params->resource_hndl = resource_info->resource_hndl;
177 params->resource_type = resource_info->resource_type;
178 params->resource_sub_type = resource_info->resource_sub_type;
179 params->reserved = resource_info->reserved;
184 * Helper function to allocate the flow table and initialize
185 * the stack for allocation operations.
187 * flow_db [in] Ptr to flow database structure
189 * Returns 0 on success or negative number on failure.
192 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db)
195 struct bnxt_ulp_flow_tbl *flow_tbl;
198 flow_tbl = &flow_db->flow_tbl;
200 size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
201 flow_tbl->flow_resources =
202 rte_zmalloc("ulp_fdb_resource_info", size, 0);
204 if (!flow_tbl->flow_resources) {
205 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
208 size = sizeof(uint32_t) * flow_tbl->num_resources;
209 flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
210 if (!flow_tbl->flow_tbl_stack) {
211 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
214 size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
215 size = ULP_BYTE_ROUND_OFF_8(size);
216 flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size,
217 ULP_BUFFER_ALIGN_64_BYTE);
218 if (!flow_tbl->active_reg_flows) {
219 BNXT_TF_DBG(ERR, "Failed to alloc memory active reg flows\n");
223 flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size,
224 ULP_BUFFER_ALIGN_64_BYTE);
225 if (!flow_tbl->active_dflt_flows) {
226 BNXT_TF_DBG(ERR, "Failed to alloc memory active dflt flows\n");
230 /* Initialize the stack table. */
231 for (idx = 0; idx < flow_tbl->num_resources; idx++)
232 flow_tbl->flow_tbl_stack[idx] = idx;
234 /* Ignore the first element in the list. */
235 flow_tbl->head_index = 1;
236 /* Tail points to the last entry in the list. */
237 flow_tbl->tail_index = flow_tbl->num_resources - 1;
242 * Helper function to deallocate the flow table.
244 * flow_db [in] Ptr to flow database structure
249 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db)
251 struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl;
253 /* Free all the allocated tables in the flow table. */
254 if (flow_tbl->active_reg_flows) {
255 rte_free(flow_tbl->active_reg_flows);
256 flow_tbl->active_reg_flows = NULL;
258 if (flow_tbl->active_dflt_flows) {
259 rte_free(flow_tbl->active_dflt_flows);
260 flow_tbl->active_dflt_flows = NULL;
263 if (flow_tbl->flow_tbl_stack) {
264 rte_free(flow_tbl->flow_tbl_stack);
265 flow_tbl->flow_tbl_stack = NULL;
268 if (flow_tbl->flow_resources) {
269 rte_free(flow_tbl->flow_resources);
270 flow_tbl->flow_resources = NULL;
275 * Helper function to add function id to the flow table
277 * flow_db [in] Ptr to flow table
278 * flow_id [in] The flow id of the flow
279 * func_id [in] The func_id to be set, for reset pass zero
284 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
288 /* set the function id in the function table */
289 if (flow_id < flow_db->func_id_tbl_size)
290 flow_db->func_id_tbl[flow_id] = func_id;
291 else /* This should never happen */
292 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
296 * Initialize the parent-child database. Memory is allocated in this
297 * call and assigned to the database
299 * flow_db [in] Ptr to flow table
300 * num_entries[in] - number of entries to allocate
302 * Returns 0 on success or negative number on failure.
305 ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db,
306 uint32_t num_entries)
308 struct ulp_fdb_parent_child_db *p_db;
314 /* update the sizes for the allocation */
315 p_db = &flow_db->parent_child_db;
316 p_db->child_bitset_size = (flow_db->flow_tbl.num_flows /
317 sizeof(uint64_t)) + 1; /* size in bytes */
318 p_db->child_bitset_size = ULP_BYTE_ROUND_OFF_8(p_db->child_bitset_size);
319 p_db->entries_count = num_entries;
321 /* allocate the memory */
322 p_db->parent_flow_tbl = rte_zmalloc("fdb parent flow tbl",
323 sizeof(struct ulp_fdb_parent_info) *
324 p_db->entries_count, 0);
325 if (!p_db->parent_flow_tbl) {
327 "Failed to allocate memory fdb parent flow tbl\n");
330 size = p_db->child_bitset_size * p_db->entries_count;
333 * allocate the big chunk of memory to be statically carved into
334 * child_fid_bitset pointer.
336 p_db->parent_flow_tbl_mem = rte_zmalloc("fdb parent flow tbl mem",
338 ULP_BUFFER_ALIGN_64_BYTE);
339 if (!p_db->parent_flow_tbl_mem) {
341 "Failed to allocate memory fdb parent flow mem\n");
345 /* set the pointers in parent table to their offsets */
346 for (idx = 0 ; idx < p_db->entries_count; idx++) {
347 p_db->parent_flow_tbl[idx].child_fid_bitset =
348 (uint64_t *)&p_db->parent_flow_tbl_mem[idx *
349 p_db->child_bitset_size];
356 * Deinitialize the parent-child database. Memory is deallocated in
357 * this call and all flows should have been purged before this
360 * flow_db [in] Ptr to flow table
365 ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db)
367 /* free the memory related to parent child database */
368 if (flow_db->parent_child_db.parent_flow_tbl_mem) {
369 rte_free(flow_db->parent_child_db.parent_flow_tbl_mem);
370 flow_db->parent_child_db.parent_flow_tbl_mem = NULL;
372 if (flow_db->parent_child_db.parent_flow_tbl) {
373 rte_free(flow_db->parent_child_db.parent_flow_tbl);
374 flow_db->parent_child_db.parent_flow_tbl = NULL;
379 * Initialize the flow database. Memory is allocated in this
380 * call and assigned to the flow database.
382 * ulp_ctxt [in] Ptr to ulp context
384 * Returns 0 on success or negative number on failure.
387 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
389 struct bnxt_ulp_device_params *dparms;
390 struct bnxt_ulp_flow_tbl *flow_tbl;
391 struct bnxt_ulp_flow_db *flow_db;
392 uint32_t dev_id, num_flows;
393 enum bnxt_ulp_flow_mem_type mtype;
395 /* Get the dev specific number of flows that needed to be supported. */
396 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
397 BNXT_TF_DBG(ERR, "Invalid device id\n");
401 dparms = bnxt_ulp_device_params_get(dev_id);
403 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
407 flow_db = rte_zmalloc("bnxt_ulp_flow_db",
408 sizeof(struct bnxt_ulp_flow_db), 0);
411 "Failed to allocate memory for flow table ptr\n");
415 /* Attach the flow database to the ulp context. */
416 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
418 /* Determine the number of flows based on EM type */
419 bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype);
420 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
421 num_flows = dparms->int_flow_db_num_entries;
423 num_flows = dparms->ext_flow_db_num_entries;
425 /* Populate the regular flow table limits. */
426 flow_tbl = &flow_db->flow_tbl;
427 flow_tbl->num_flows = num_flows + 1;
428 flow_tbl->num_resources = ((num_flows + 1) *
429 dparms->num_resources_per_flow);
431 /* Include the default flow table limits. */
432 flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
433 flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
434 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
436 /* Allocate the resource for the flow table. */
437 if (ulp_flow_db_alloc_resource(flow_db))
440 /* add 1 since we are not using index 0 for flow id */
441 flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
442 /* Allocate the function Id table */
443 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
444 flow_db->func_id_tbl_size *
445 sizeof(uint16_t), 0);
446 if (!flow_db->func_id_tbl) {
448 "Failed to allocate mem for flow table func id\n");
451 /* initialize the parent child database */
452 if (ulp_flow_db_parent_tbl_init(flow_db,
453 dparms->fdb_parent_flow_entries)) {
455 "Failed to allocate mem for parent child db\n");
459 /* All good so return. */
460 BNXT_TF_DBG(INFO, "FlowDB initialized with %d flows.\n",
461 flow_tbl->num_flows);
464 ulp_flow_db_deinit(ulp_ctxt);
469 * Deinitialize the flow database. Memory is deallocated in
470 * this call and all flows should have been purged before this
473 * ulp_ctxt [in] Ptr to ulp context
475 * Returns 0 on success.
478 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
480 struct bnxt_ulp_flow_db *flow_db;
482 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
486 /* Detach the flow database from the ulp context. */
487 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
489 /* Free up all the memory. */
490 ulp_flow_db_parent_tbl_deinit(flow_db);
491 ulp_flow_db_dealloc_resource(flow_db);
492 rte_free(flow_db->func_id_tbl);
499 * Allocate the flow database entry
501 * ulp_ctxt [in] Ptr to ulp_context
502 * flow_type [in] - specify default or regular
503 * func_id [in].function id of the ingress port
504 * fid [out] The index to the flow entry
506 * returns 0 on success and negative on failure.
509 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
510 enum bnxt_ulp_fdb_type flow_type,
514 struct bnxt_ulp_flow_db *flow_db;
515 struct bnxt_ulp_flow_tbl *flow_tbl;
517 *fid = 0; /* Initialize fid to invalid value */
518 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
520 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
524 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
525 BNXT_TF_DBG(ERR, "Invalid flow type\n");
529 flow_tbl = &flow_db->flow_tbl;
530 /* check for max flows */
531 if (flow_tbl->num_flows <= flow_tbl->head_index) {
532 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
535 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
536 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
539 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
540 flow_tbl->head_index++;
542 /* Set the flow type */
543 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
545 /* function id update is only valid for regular flow table */
546 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
547 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
554 * Allocate the flow database entry.
555 * The params->critical_resource has to be set to 0 to allocate a new resource.
557 * ulp_ctxt [in] Ptr to ulp_context
558 * flow_type [in] Specify it is regular or default flow
559 * fid [in] The index to the flow entry
560 * params [in] The contents to be copied into resource
562 * returns 0 on success and negative on failure.
565 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
566 enum bnxt_ulp_fdb_type flow_type,
568 struct ulp_flow_db_res_params *params)
570 struct bnxt_ulp_flow_db *flow_db;
571 struct bnxt_ulp_flow_tbl *flow_tbl;
572 struct ulp_fdb_resource_info *resource, *fid_resource;
575 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
577 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
581 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
582 BNXT_TF_DBG(ERR, "Invalid flow type\n");
586 flow_tbl = &flow_db->flow_tbl;
587 /* check for max flows */
588 if (fid >= flow_tbl->num_flows || !fid) {
589 BNXT_TF_DBG(ERR, "Invalid flow index\n");
593 /* check if the flow is active or not */
594 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
595 BNXT_TF_DBG(ERR, "flow does not exist\n");
599 /* check for max resource */
600 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
601 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
604 fid_resource = &flow_tbl->flow_resources[fid];
606 if (!params->critical_resource) {
607 /* Not the critical_resource so allocate a resource */
608 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
609 resource = &flow_tbl->flow_resources[idx];
610 flow_tbl->tail_index--;
612 /* Update the chain list of resource*/
613 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
614 fid_resource->nxt_resource_idx);
615 /* update the contents */
616 ulp_flow_db_res_params_to_info(resource, params);
617 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
618 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
621 /* critical resource. Just update the fid resource */
622 ulp_flow_db_res_params_to_info(fid_resource, params);
625 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
626 params->resource_sub_type ==
627 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
628 /* Store the first HW counter ID for this table */
629 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
630 ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
631 params->resource_hndl);
633 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
634 params->resource_hndl);
636 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
637 ulp_fc_mgr_thread_start(ulp_ctxt);
640 /* all good, return success */
645 * Free the flow database entry.
646 * The params->critical_resource has to be set to 1 to free the first resource.
648 * ulp_ctxt [in] Ptr to ulp_context
649 * flow_type [in] Specify it is regular or default flow
650 * fid [in] The index to the flow entry
651 * params [in/out] The contents to be copied into params.
652 * Onlythe critical_resource needs to be set by the caller.
654 * Returns 0 on success and negative on failure.
657 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
658 enum bnxt_ulp_fdb_type flow_type,
660 struct ulp_flow_db_res_params *params)
662 struct bnxt_ulp_flow_db *flow_db;
663 struct bnxt_ulp_flow_tbl *flow_tbl;
664 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
665 uint32_t nxt_idx = 0;
667 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
669 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
673 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
674 BNXT_TF_DBG(ERR, "Invalid flow type\n");
678 flow_tbl = &flow_db->flow_tbl;
679 /* check for max flows */
680 if (fid >= flow_tbl->num_flows || !fid) {
681 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
685 /* check if the flow is active or not */
686 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
687 BNXT_TF_DBG(ERR, "flow does not exist\n");
691 fid_resource = &flow_tbl->flow_resources[fid];
692 if (!params->critical_resource) {
693 /* Not the critical resource so free the resource */
694 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
695 fid_resource->nxt_resource_idx);
697 /* reached end of resources */
700 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
702 /* connect the fid resource to the next resource */
703 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
704 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
705 nxt_resource->nxt_resource_idx);
707 /* update the contents to be given to caller */
708 ulp_flow_db_res_info_to_params(nxt_resource, params);
710 /* Delete the nxt_resource */
711 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
713 /* add it to the free list */
714 flow_tbl->tail_index++;
715 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
716 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
719 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
722 /* Critical resource. copy the contents and exit */
723 ulp_flow_db_res_info_to_params(fid_resource, params);
724 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
725 fid_resource->nxt_resource_idx);
726 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
727 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
731 /* Now that the HW Flow counter resource is deleted, reset it's
732 * corresponding slot in the SW accumulation table in the Flow Counter
735 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
736 params->resource_sub_type ==
737 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
738 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
739 params->resource_hndl);
742 /* all good, return success */
747 * Free the flow database entry
749 * ulp_ctxt [in] Ptr to ulp_context
750 * flow_type [in] - specify default or regular
751 * fid [in] The index to the flow entry
753 * returns 0 on success and negative on failure.
756 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
757 enum bnxt_ulp_fdb_type flow_type,
760 struct bnxt_ulp_flow_db *flow_db;
761 struct bnxt_ulp_flow_tbl *flow_tbl;
763 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
765 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
769 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
770 BNXT_TF_DBG(ERR, "Invalid flow type\n");
774 flow_tbl = &flow_db->flow_tbl;
776 /* check for limits of fid */
777 if (fid >= flow_tbl->num_flows || !fid) {
778 BNXT_TF_DBG(ERR, "Invalid flow index\n");
782 /* check if the flow is active or not */
783 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
784 BNXT_TF_DBG(ERR, "flow does not exist\n");
787 flow_tbl->head_index--;
788 if (!flow_tbl->head_index) {
789 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
792 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
794 /* Clear the flows bitmap */
795 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
797 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
798 ulp_flow_db_func_id_set(flow_db, fid, 0);
800 /* all good, return success */
805 * Get the flow database entry details
807 * ulp_ctxt [in] Ptr to ulp_context
808 * flow_type [in] - specify default or regular
809 * fid [in] The index to the flow entry
810 * nxt_idx [in/out] the index to the next entry
811 * params [out] The contents to be copied into params.
813 * returns 0 on success and negative on failure.
816 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
817 enum bnxt_ulp_fdb_type flow_type,
820 struct ulp_flow_db_res_params *params)
822 struct bnxt_ulp_flow_db *flow_db;
823 struct bnxt_ulp_flow_tbl *flow_tbl;
824 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
826 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
828 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
832 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
833 BNXT_TF_DBG(ERR, "Invalid flow type\n");
837 flow_tbl = &flow_db->flow_tbl;
839 /* check for limits of fid */
840 if (fid >= flow_tbl->num_flows || !fid) {
841 BNXT_TF_DBG(ERR, "Invalid flow index\n");
845 /* check if the flow is active or not */
846 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
847 BNXT_TF_DBG(ERR, "flow does not exist\n");
852 fid_resource = &flow_tbl->flow_resources[fid];
853 ulp_flow_db_res_info_to_params(fid_resource, params);
854 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
855 fid_resource->nxt_resource_idx);
857 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
858 ulp_flow_db_res_info_to_params(nxt_resource, params);
860 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
861 nxt_resource->nxt_resource_idx);
864 /* all good, return success */
869 * Get the flow database entry iteratively
871 * flow_tbl [in] Ptr to flow table
872 * flow_type [in] - specify default or regular
873 * fid [in/out] The index to the flow entry
875 * returns 0 on success and negative on failure.
878 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
879 enum bnxt_ulp_fdb_type flow_type,
882 uint32_t lfid = *fid;
883 uint32_t idx, s_idx, mod_fid;
885 uint64_t *active_flows;
886 struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
888 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
889 active_flows = flowtbl->active_reg_flows;
891 active_flows = flowtbl->active_dflt_flows;
894 /* increment the flow id to find the next valid flow id */
896 if (lfid >= flowtbl->num_flows)
898 idx = lfid / ULP_INDEX_BITMAP_SIZE;
899 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
901 while (!(bs = active_flows[idx])) {
903 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
907 * remove the previous bits in the bitset bs to find the
908 * next non zero bit in the bitset. This needs to be done
909 * only if the idx is same as he one you started.
912 bs &= (-1UL >> mod_fid);
913 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
915 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
918 } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
921 /* all good, return success */
927 * Flush all flows in the flow database.
929 * ulp_ctxt [in] Ptr to ulp context
930 * flow_type [in] - specify default or regular
932 * returns 0 on success or negative number on failure
935 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
936 enum bnxt_ulp_fdb_type flow_type)
939 struct bnxt_ulp_flow_db *flow_db;
942 BNXT_TF_DBG(ERR, "Invalid Argument\n");
946 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
948 BNXT_TF_DBG(ERR, "Flow database not found\n");
951 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
952 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
956 while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
957 ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
959 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
965 * Flush all flows in the flow database that belong to a device function.
967 * ulp_ctxt [in] Ptr to ulp context
968 * func_id [in] - The port function id
970 * returns 0 on success or negative number on failure
973 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
976 uint32_t flow_id = 0;
977 struct bnxt_ulp_flow_db *flow_db;
979 if (!ulp_ctx || !func_id) {
980 BNXT_TF_DBG(ERR, "Invalid Argument\n");
984 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
986 BNXT_TF_DBG(ERR, "Flow database not found\n");
989 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
990 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
994 while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
996 if (flow_db->func_id_tbl[flow_id] == func_id)
997 ulp_mapper_resources_free(ulp_ctx,
998 BNXT_ULP_FDB_TYPE_REGULAR,
1001 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
1006 * Flush all flows in the flow database that are associated with the session.
1008 * ulp_ctxt [in] Ptr to ulp context
1010 * returns 0 on success or negative number on failure
1013 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
1016 * TBD: Tf core implementation of FW session flush shall change this
1019 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1023 * Check that flow id matches the function id or not
1025 * ulp_ctxt [in] Ptr to ulp context
1026 * flow_db [in] Ptr to flow table
1027 * func_id [in] The func_id to be set, for reset pass zero.
1029 * returns true on success or false on failure
1032 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
1036 struct bnxt_ulp_flow_db *flow_db;
1038 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1040 BNXT_TF_DBG(ERR, "Flow database not found\n");
1044 /* set the function id in the function table */
1045 if (flow_id < flow_db->func_id_tbl_size && func_id &&
1046 flow_db->func_id_tbl[flow_id] == func_id)
1053 * Internal api to traverse the resource list within a flow
1054 * and match a resource based on resource func and resource
1055 * sub type. This api should be used only for resources that
1056 * are unique and do not have multiple instances of resource
1057 * func and sub type combination since it will return only
1061 ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,
1062 enum bnxt_ulp_fdb_type flow_type,
1064 uint32_t resource_func,
1065 uint32_t res_subtype,
1066 struct ulp_flow_db_res_params *params)
1068 struct bnxt_ulp_flow_db *flow_db;
1069 struct bnxt_ulp_flow_tbl *flow_tbl;
1070 struct ulp_fdb_resource_info *fid_res;
1073 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1075 BNXT_TF_DBG(ERR, "Flow database not found\n");
1080 BNXT_TF_DBG(ERR, "invalid argument\n");
1084 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
1085 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1089 flow_tbl = &flow_db->flow_tbl;
1091 /* check for limits of fid */
1092 if (flow_id >= flow_tbl->num_flows || !flow_id) {
1093 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1097 /* check if the flow is active or not */
1098 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
1099 BNXT_TF_DBG(ERR, "flow does not exist\n");
1102 /* Iterate the resource to get the resource handle */
1104 memset(params, 0, sizeof(struct ulp_flow_db_res_params));
1106 fid_res = &flow_tbl->flow_resources[res_id];
1107 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
1108 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
1109 if (res_subtype == fid_res->resource_sub_type) {
1110 ulp_flow_db_res_info_to_params(fid_res,
1115 } else if (resource_func ==
1116 BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
1118 BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
1119 ulp_flow_db_res_info_to_params(fid_res,
1125 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1131 * Api to get the cfa action pointer from a flow.
1133 * ulp_ctxt [in] Ptr to ulp context
1134 * flow_id [in] flow id
1135 * cfa_action [out] The resource handle stored in the flow database
1137 * returns 0 on success
1140 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1142 uint16_t *cfa_action)
1144 uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_CFA_ACTION;
1145 struct ulp_flow_db_res_params params;
1148 rc = ulp_flow_db_resource_params_get(ulp_ctx,
1149 BNXT_ULP_FDB_TYPE_DEFAULT,
1151 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1154 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
1158 *cfa_action = params.resource_hndl;
1162 /* internal validation function for parent flow tbl */
1163 static struct bnxt_ulp_flow_db *
1164 ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt,
1167 struct bnxt_ulp_flow_db *flow_db;
1169 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1171 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1175 /* check for max flows */
1176 if (fid >= flow_db->flow_tbl.num_flows || !fid) {
1177 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1181 /* No support for parent child db then just exit */
1182 if (!flow_db->parent_child_db.entries_count) {
1183 BNXT_TF_DBG(ERR, "parent child db not supported\n");
1191 * Allocate the entry in the parent-child database
1193 * ulp_ctxt [in] Ptr to ulp_context
1194 * fid [in] The flow id to the flow entry
1196 * returns index on success and negative on failure.
1199 ulp_flow_db_parent_flow_alloc(struct bnxt_ulp_context *ulp_ctxt,
1202 struct bnxt_ulp_flow_db *flow_db;
1203 struct ulp_fdb_parent_child_db *p_pdb;
1204 uint32_t idx, free_idx = 0;
1206 /* validate the arguments */
1207 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid);
1209 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1213 p_pdb = &flow_db->parent_child_db;
1214 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1215 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1216 BNXT_TF_DBG(ERR, "fid is already allocated\n");
1219 if (!p_pdb->parent_flow_tbl[idx].parent_fid && !free_idx)
1224 BNXT_TF_DBG(ERR, "parent child db is full\n");
1229 /* set the Fid in the parent child */
1230 p_pdb->parent_flow_tbl[free_idx].parent_fid = fid;
1235 * Free the entry in the parent-child database
1237 * ulp_ctxt [in] Ptr to ulp_context
1238 * fid [in] The flow id to the flow entry
1240 * returns 0 on success and negative on failure.
1243 ulp_flow_db_parent_flow_free(struct bnxt_ulp_context *ulp_ctxt,
1246 struct bnxt_ulp_flow_db *flow_db;
1247 struct ulp_fdb_parent_child_db *p_pdb;
1250 /* validate the arguments */
1251 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid);
1253 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1257 p_pdb = &flow_db->parent_child_db;
1258 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1259 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1260 /* free the contents */
1261 p_pdb->parent_flow_tbl[idx].parent_fid = 0;
1262 memset(p_pdb->parent_flow_tbl[idx].child_fid_bitset,
1263 0, p_pdb->child_bitset_size);
1267 BNXT_TF_DBG(ERR, "parent entry not found = %x\n", fid);
1272 * Set or reset the child flow in the parent-child database
1274 * ulp_ctxt [in] Ptr to ulp_context
1275 * parent_fid [in] The flow id of the parent flow entry
1276 * child_fid [in] The flow id of the child flow entry
1277 * set_flag [in] Use 1 for setting child, 0 to reset
1279 * returns zero on success and negative on failure.
1282 ulp_flow_db_parent_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1283 uint32_t parent_fid,
1287 struct bnxt_ulp_flow_db *flow_db;
1288 struct ulp_fdb_parent_child_db *p_pdb;
1289 uint32_t idx, a_idx;
1292 /* validate the arguments */
1293 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1295 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1299 /* check for fid validity */
1300 if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) {
1301 BNXT_TF_DBG(ERR, "Invalid child flow index %x\n", child_fid);
1305 p_pdb = &flow_db->parent_child_db;
1306 a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
1307 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1308 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1309 t = p_pdb->parent_flow_tbl[idx].child_fid_bitset;
1311 ULP_INDEX_BITMAP_SET(t[a_idx], child_fid);
1313 ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid);
1317 BNXT_TF_DBG(ERR, "Unable to set the parent-child flow %x:%x\n",
1318 parent_fid, child_fid);
1323 * Get the parent index from the parent-child database
1325 * ulp_ctxt [in] Ptr to ulp_context
1326 * parent_fid [in] The flow id of the parent flow entry
1327 * parent_idx [out] The parent index of parent flow entry
1329 * returns zero on success and negative on failure.
1332 ulp_flow_db_parent_flow_idx_get(struct bnxt_ulp_context *ulp_ctxt,
1333 uint32_t parent_fid,
1334 uint32_t *parent_idx)
1336 struct bnxt_ulp_flow_db *flow_db;
1337 struct ulp_fdb_parent_child_db *p_pdb;
1340 /* validate the arguments */
1341 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1343 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1347 p_pdb = &flow_db->parent_child_db;
1348 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1349 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1354 BNXT_TF_DBG(ERR, "Unable to get the parent flow %x\n", parent_fid);
1359 * Get the next child flow in the parent-child database
1361 * ulp_ctxt [in] Ptr to ulp_context
1362 * parent_fid [in] The flow id of the parent flow entry
1363 * child_fid [in/out] The flow id of the child flow entry
1365 * returns zero on success and negative on failure.
1366 * Pass child_fid as zero for first entry.
1369 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1370 uint32_t parent_idx,
1371 uint32_t *child_fid)
1373 struct ulp_fdb_parent_child_db *p_pdb;
1374 uint32_t idx, s_idx, mod_fid;
1375 uint32_t next_fid = *child_fid;
1376 uint64_t *child_bitset;
1379 /* check for fid validity */
1380 p_pdb = &flow_db->parent_child_db;
1381 if (parent_idx >= p_pdb->entries_count ||
1382 !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1383 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1387 child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset;
1389 /* increment the flow id to find the next valid flow id */
1391 if (next_fid >= flow_db->flow_tbl.num_flows)
1393 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1394 mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE;
1396 while (!(bs = child_bitset[idx])) {
1398 if ((idx * ULP_INDEX_BITMAP_SIZE) >=
1399 flow_db->flow_tbl.num_flows)
1403 * remove the previous bits in the bitset bs to find the
1404 * next non zero bit in the bitset. This needs to be done
1405 * only if the idx is same as he one you started.
1408 bs &= (-1UL >> mod_fid);
1409 next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
1410 if (*child_fid >= next_fid) {
1411 BNXT_TF_DBG(ERR, "Parent Child Database is corrupt\n");
1414 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1415 } while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid));
1416 *child_fid = next_fid;
1421 * Set the counter accumulation in the parent flow
1423 * ulp_ctxt [in] Ptr to ulp_context
1424 * parent_idx [in] The parent index of the parent flow entry
1426 * returns index on success and negative on failure.
1429 ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt,
1430 uint32_t parent_idx)
1432 struct bnxt_ulp_flow_db *flow_db;
1433 struct ulp_fdb_parent_child_db *p_pdb;
1435 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1437 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1441 /* check for parent idx validity */
1442 p_pdb = &flow_db->parent_child_db;
1443 if (parent_idx >= p_pdb->entries_count ||
1444 !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1445 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1449 p_pdb->parent_flow_tbl[parent_idx].counter_acc = 1;
1454 * Get the counter accumulation in the parent flow
1456 * ulp_ctxt [in] Ptr to ulp_context
1457 * parent_fid [in] The flow id of the parent flow entry
1459 * returns 0 if counter accum is set else -1.
1462 ulp_flow_db_parent_flow_count_accum_get(struct bnxt_ulp_context *ulp_ctxt,
1463 uint32_t parent_fid)
1465 struct bnxt_ulp_flow_db *flow_db;
1466 struct ulp_fdb_parent_child_db *p_pdb;
1469 /* validate the arguments */
1470 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1472 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1476 p_pdb = &flow_db->parent_child_db;
1477 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1478 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1479 if (p_pdb->parent_flow_tbl[idx].counter_acc)
1488 * Orphan the child flow entry
1489 * This is called only for child flows that have
1490 * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
1492 * ulp_ctxt [in] Ptr to ulp_context
1493 * flow_type [in] Specify it is regular or default flow
1494 * fid [in] The index to the flow entry
1496 * Returns 0 on success and negative on failure.
1499 ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
1500 enum bnxt_ulp_fdb_type flow_type,
1503 struct bnxt_ulp_flow_db *flow_db;
1504 struct bnxt_ulp_flow_tbl *flow_tbl;
1505 struct ulp_fdb_resource_info *fid_res;
1506 uint32_t res_id = 0;
1508 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1510 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1514 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
1515 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1519 flow_tbl = &flow_db->flow_tbl;
1520 /* check for max flows */
1521 if (fid >= flow_tbl->num_flows || !fid) {
1522 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
1526 /* check if the flow is active or not */
1527 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
1528 BNXT_TF_DBG(ERR, "flow does not exist\n");
1532 /* Iterate the resource to get the resource handle */
1535 fid_res = &flow_tbl->flow_resources[res_id];
1536 if (ulp_flow_db_resource_func_get(fid_res) ==
1537 BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) {
1538 /* invalidate the resource details */
1539 fid_res->resource_hndl = 0;
1543 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1550 * Create parent flow in the parent flow tbl
1552 * parms [in] Ptr to mapper params
1554 * Returns 0 on success and negative on failure.
1557 ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)
1559 struct ulp_flow_db_res_params fid_parms;
1560 uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT_ACC;
1561 struct ulp_flow_db_res_params res_params;
1564 /* create the child flow entry in parent flow table */
1565 fid_idx = ulp_flow_db_parent_flow_alloc(parms->ulp_ctx, parms->fid);
1567 BNXT_TF_DBG(ERR, "Error in creating parent flow fid %x\n",
1572 /* Add the parent details in the resource list of the flow */
1573 memset(&fid_parms, 0, sizeof(fid_parms));
1574 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW;
1575 fid_parms.resource_hndl = fid_idx;
1576 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1577 if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
1578 parms->fid, &fid_parms)) {
1579 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1584 /* check of the flow has internal counter accumulation enabled */
1585 if (!ulp_flow_db_resource_params_get(parms->ulp_ctx,
1586 BNXT_ULP_FDB_TYPE_REGULAR,
1588 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1591 /* Enable the counter accumulation in parent entry */
1592 if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx,
1594 BNXT_TF_DBG(ERR, "Error in setting counter acc %x\n",
1603 * Create child flow in the parent flow tbl
1605 * parms [in] Ptr to mapper params
1607 * Returns 0 on success and negative on failure.
1610 ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms)
1612 struct ulp_flow_db_res_params fid_parms;
1613 uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT;
1614 enum bnxt_ulp_resource_func res_fun;
1615 struct ulp_flow_db_res_params res_p;
1616 uint32_t parent_fid = parms->parent_fid;
1619 /* create the parent flow entry in parent flow table */
1620 rc = ulp_flow_db_parent_child_flow_set(parms->ulp_ctx,
1624 BNXT_TF_DBG(ERR, "Error in setting child fid %x\n", parms->fid);
1628 /* Add the parent details in the resource list of the flow */
1629 memset(&fid_parms, 0, sizeof(fid_parms));
1630 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW;
1631 fid_parms.resource_hndl = parms->parent_fid;
1632 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1633 rc = ulp_flow_db_resource_add(parms->ulp_ctx,
1634 BNXT_ULP_FDB_TYPE_REGULAR,
1635 parms->fid, &fid_parms);
1637 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1642 /* check if accumulation count is set for parent flow */
1643 rc = ulp_flow_db_parent_flow_count_accum_get(parms->ulp_ctx,
1646 /* check if internal count action included for this flow.*/
1647 res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE;
1648 rc = ulp_flow_db_resource_params_get(parms->ulp_ctx,
1649 BNXT_ULP_FDB_TYPE_REGULAR,
1655 /* update the counter manager to include parent fid */
1656 if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx,
1658 res_p.resource_hndl,
1660 BNXT_TF_DBG(ERR, "Error in setting child %x\n",
1666 /* return success */
1671 * Update the parent counters
1673 * ulp_ctxt [in] Ptr to ulp_context
1674 * parent_fid [in] The flow id of the parent flow entry
1675 * packet_count [in] - packet count
1676 * byte_count [in] - byte count
1678 * returns 0 on success
1681 ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt,
1682 uint32_t parent_fid,
1683 uint64_t packet_count,
1684 uint64_t byte_count)
1686 struct bnxt_ulp_flow_db *flow_db;
1687 struct ulp_fdb_parent_child_db *p_pdb;
1690 /* validate the arguments */
1691 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1693 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1697 p_pdb = &flow_db->parent_child_db;
1698 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1699 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1700 if (p_pdb->parent_flow_tbl[idx].counter_acc) {
1701 p_pdb->parent_flow_tbl[idx].pkt_count +=
1703 p_pdb->parent_flow_tbl[idx].byte_count +=
1713 * Get the parent accumulation counters
1715 * ulp_ctxt [in] Ptr to ulp_context
1716 * parent_fid [in] The flow id of the parent flow entry
1717 * packet_count [out] - packet count
1718 * byte_count [out] - byte count
1720 * returns 0 on success
1723 ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,
1724 uint32_t parent_fid,
1725 uint64_t *packet_count,
1726 uint64_t *byte_count)
1728 struct bnxt_ulp_flow_db *flow_db;
1729 struct ulp_fdb_parent_child_db *p_pdb;
1732 /* validate the arguments */
1733 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1735 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1739 p_pdb = &flow_db->parent_child_db;
1740 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1741 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1742 if (p_pdb->parent_flow_tbl[idx].counter_acc) {
1744 p_pdb->parent_flow_tbl[idx].pkt_count;
1746 p_pdb->parent_flow_tbl[idx].byte_count;
1755 * reset the parent accumulation counters
1757 * ulp_ctxt [in] Ptr to ulp_context
1762 ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt)
1764 struct bnxt_ulp_flow_db *flow_db;
1765 struct ulp_fdb_parent_child_db *p_pdb;
1768 /* validate the arguments */
1769 flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, 1);
1771 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1775 p_pdb = &flow_db->parent_child_db;
1776 for (idx = 0; idx < p_pdb->entries_count; idx++) {
1777 if (p_pdb->parent_flow_tbl[idx].parent_fid &&
1778 p_pdb->parent_flow_tbl[idx].counter_acc) {
1779 p_pdb->parent_flow_tbl[idx].pkt_count = 0;
1780 p_pdb->parent_flow_tbl[idx].byte_count = 0;