1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2020 Broadcom
6 #include <rte_malloc.h>
8 #include "bnxt_tf_common.h"
9 #include "ulp_flow_db.h"
10 #include "ulp_utils.h"
11 #include "ulp_template_struct.h"
12 #include "ulp_mapper.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],
93 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
97 func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
98 ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
99 /* The reource func is split into upper and lower */
100 if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
101 return (func | res_info->resource_func_lower);
106 * Helper function to copy the resource params to resource info
107 * No validation being done in this function.
109 * resource_info [out] Ptr to resource information
110 * params [in] The input params from the caller
114 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
115 struct ulp_flow_db_res_params *params)
117 uint32_t resource_func;
119 resource_info->nxt_resource_idx |= ((params->direction <<
120 ULP_FLOW_DB_RES_DIR_BIT) &
121 ULP_FLOW_DB_RES_DIR_MASK);
122 resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
123 resource_info->nxt_resource_idx |= ((resource_func <<
124 ULP_FLOW_DB_RES_FUNC_BITS) &
125 ULP_FLOW_DB_RES_FUNC_MASK);
127 if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
128 /* Break the resource func into two parts */
129 resource_func = (params->resource_func &
130 ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
131 resource_info->resource_func_lower = resource_func;
134 /* Store the handle as 64bit only for EM table entries */
135 if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE &&
136 params->resource_func != BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
137 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
138 resource_info->resource_type = params->resource_type;
139 resource_info->resource_sub_type = params->resource_sub_type;
140 resource_info->reserved = params->reserved;
142 resource_info->resource_em_handle = params->resource_hndl;
147 * Helper function to copy the resource params to resource info
148 * No validation being done in this function.
150 * resource_info [in] Ptr to resource information
151 * params [out] The output params to the caller
156 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
157 struct ulp_flow_db_res_params *params)
159 memset(params, 0, sizeof(struct ulp_flow_db_res_params));
160 params->direction = ((resource_info->nxt_resource_idx &
161 ULP_FLOW_DB_RES_DIR_MASK) >>
162 ULP_FLOW_DB_RES_DIR_BIT);
164 /* use the helper function to get the resource func */
165 params->resource_func = ulp_flow_db_resource_func_get(resource_info);
167 if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
168 params->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
169 params->resource_hndl = resource_info->resource_em_handle;
170 } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
171 params->resource_hndl = resource_info->resource_hndl;
172 params->resource_type = resource_info->resource_type;
173 params->resource_sub_type = resource_info->resource_sub_type;
174 params->reserved = resource_info->reserved;
179 * Helper function to allocate the flow table and initialize
180 * the stack for allocation operations.
182 * flow_db [in] Ptr to flow database structure
184 * Returns 0 on success or negative number on failure.
187 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db)
190 struct bnxt_ulp_flow_tbl *flow_tbl;
193 flow_tbl = &flow_db->flow_tbl;
195 size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
196 flow_tbl->flow_resources =
197 rte_zmalloc("ulp_fdb_resource_info", size, 0);
199 if (!flow_tbl->flow_resources) {
200 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
203 size = sizeof(uint32_t) * flow_tbl->num_resources;
204 flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
205 if (!flow_tbl->flow_tbl_stack) {
206 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
209 size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
210 flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size, 0);
211 if (!flow_tbl->active_reg_flows) {
212 BNXT_TF_DBG(ERR, "Failed to alloc memory active reg flows\n");
216 flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size, 0);
217 if (!flow_tbl->active_dflt_flows) {
218 BNXT_TF_DBG(ERR, "Failed to alloc memory active dflt flows\n");
222 /* Initialize the stack table. */
223 for (idx = 0; idx < flow_tbl->num_resources; idx++)
224 flow_tbl->flow_tbl_stack[idx] = idx;
226 /* Ignore the first element in the list. */
227 flow_tbl->head_index = 1;
228 /* Tail points to the last entry in the list. */
229 flow_tbl->tail_index = flow_tbl->num_resources - 1;
234 * Helper function to deallocate the flow table.
236 * flow_db [in] Ptr to flow database structure
241 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db)
243 struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl;
245 /* Free all the allocated tables in the flow table. */
246 if (flow_tbl->active_reg_flows) {
247 rte_free(flow_tbl->active_reg_flows);
248 flow_tbl->active_reg_flows = NULL;
250 if (flow_tbl->active_dflt_flows) {
251 rte_free(flow_tbl->active_dflt_flows);
252 flow_tbl->active_dflt_flows = NULL;
255 if (flow_tbl->flow_tbl_stack) {
256 rte_free(flow_tbl->flow_tbl_stack);
257 flow_tbl->flow_tbl_stack = NULL;
260 if (flow_tbl->flow_resources) {
261 rte_free(flow_tbl->flow_resources);
262 flow_tbl->flow_resources = NULL;
267 * Helper function to add function id to the flow table
269 * flow_db [in] Ptr to flow table
270 * flow_id [in] The flow id of the flow
271 * func_id [in] The func_id to be set, for reset pass zero
276 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
280 /* set the function id in the function table */
281 if (flow_id < flow_db->func_id_tbl_size)
282 flow_db->func_id_tbl[flow_id] = func_id;
283 else /* This should never happen */
284 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
288 * Initialize the flow database. Memory is allocated in this
289 * call and assigned to the flow database.
291 * ulp_ctxt [in] Ptr to ulp context
293 * Returns 0 on success or negative number on failure.
296 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
298 struct bnxt_ulp_device_params *dparms;
299 struct bnxt_ulp_flow_tbl *flow_tbl;
300 struct bnxt_ulp_flow_db *flow_db;
301 uint32_t dev_id, num_flows;
302 enum bnxt_ulp_flow_mem_type mtype;
304 /* Get the dev specific number of flows that needed to be supported. */
305 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
306 BNXT_TF_DBG(ERR, "Invalid device id\n");
310 dparms = bnxt_ulp_device_params_get(dev_id);
312 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
316 flow_db = rte_zmalloc("bnxt_ulp_flow_db",
317 sizeof(struct bnxt_ulp_flow_db), 0);
320 "Failed to allocate memory for flow table ptr\n");
324 /* Attach the flow database to the ulp context. */
325 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
327 /* Determine the number of flows based on EM type */
328 bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype);
329 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
330 num_flows = dparms->int_flow_db_num_entries;
332 num_flows = dparms->ext_flow_db_num_entries;
334 /* Populate the regular flow table limits. */
335 flow_tbl = &flow_db->flow_tbl;
336 flow_tbl->num_flows = num_flows + 1;
337 flow_tbl->num_resources = ((num_flows + 1) *
338 dparms->num_resources_per_flow);
340 /* Include the default flow table limits. */
341 flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
342 flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
343 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
345 /* Allocate the resource for the flow table. */
346 if (ulp_flow_db_alloc_resource(flow_db))
349 /* add 1 since we are not using index 0 for flow id */
350 flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
351 /* Allocate the function Id table */
352 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
353 flow_db->func_id_tbl_size *
354 sizeof(uint16_t), 0);
355 if (!flow_db->func_id_tbl) {
357 "Failed to allocate mem for flow table func id\n");
360 /* All good so return. */
361 BNXT_TF_DBG(INFO, "FlowDB initialized with %d flows.\n",
362 flow_tbl->num_flows);
365 ulp_flow_db_deinit(ulp_ctxt);
370 * Deinitialize the flow database. Memory is deallocated in
371 * this call and all flows should have been purged before this
374 * ulp_ctxt [in] Ptr to ulp context
376 * Returns 0 on success.
379 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
381 struct bnxt_ulp_flow_db *flow_db;
383 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
387 /* Detach the flow database from the ulp context. */
388 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
390 /* Free up all the memory. */
391 ulp_flow_db_dealloc_resource(flow_db);
392 rte_free(flow_db->func_id_tbl);
399 * Allocate the flow database entry
401 * ulp_ctxt [in] Ptr to ulp_context
402 * flow_type [in] - specify default or regular
403 * func_id [in].function id of the ingress port
404 * fid [out] The index to the flow entry
406 * returns 0 on success and negative on failure.
409 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
410 enum bnxt_ulp_fdb_type flow_type,
414 struct bnxt_ulp_flow_db *flow_db;
415 struct bnxt_ulp_flow_tbl *flow_tbl;
417 *fid = 0; /* Initialize fid to invalid value */
418 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
420 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
424 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
425 BNXT_TF_DBG(ERR, "Invalid flow type\n");
429 flow_tbl = &flow_db->flow_tbl;
430 /* check for max flows */
431 if (flow_tbl->num_flows <= flow_tbl->head_index) {
432 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
435 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
436 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
439 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
440 flow_tbl->head_index++;
442 /* Set the flow type */
443 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
445 /* function id update is only valid for regular flow table */
446 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
447 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
454 * Allocate the flow database entry.
455 * The params->critical_resource has to be set to 0 to allocate a new resource.
457 * ulp_ctxt [in] Ptr to ulp_context
458 * flow_type [in] Specify it is regular or default flow
459 * fid [in] The index to the flow entry
460 * params [in] The contents to be copied into resource
462 * returns 0 on success and negative on failure.
465 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
466 enum bnxt_ulp_fdb_type flow_type,
468 struct ulp_flow_db_res_params *params)
470 struct bnxt_ulp_flow_db *flow_db;
471 struct bnxt_ulp_flow_tbl *flow_tbl;
472 struct ulp_fdb_resource_info *resource, *fid_resource;
475 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
477 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
481 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
482 BNXT_TF_DBG(ERR, "Invalid flow type\n");
486 flow_tbl = &flow_db->flow_tbl;
487 /* check for max flows */
488 if (fid >= flow_tbl->num_flows || !fid) {
489 BNXT_TF_DBG(ERR, "Invalid flow index\n");
493 /* check if the flow is active or not */
494 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
495 BNXT_TF_DBG(ERR, "flow does not exist\n");
499 /* check for max resource */
500 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
501 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
504 fid_resource = &flow_tbl->flow_resources[fid];
506 if (!params->critical_resource) {
507 /* Not the critical_resource so allocate a resource */
508 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
509 resource = &flow_tbl->flow_resources[idx];
510 flow_tbl->tail_index--;
512 /* Update the chain list of resource*/
513 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
514 fid_resource->nxt_resource_idx);
515 /* update the contents */
516 ulp_flow_db_res_params_to_info(resource, params);
517 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
518 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
521 /* critical resource. Just update the fid resource */
522 ulp_flow_db_res_params_to_info(fid_resource, params);
525 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
526 params->resource_sub_type ==
527 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
528 /* Store the first HW counter ID for this table */
529 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
530 ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
531 params->resource_hndl);
533 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
534 params->resource_hndl);
536 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
537 ulp_fc_mgr_thread_start(ulp_ctxt);
540 /* all good, return success */
545 * Free the flow database entry.
546 * The params->critical_resource has to be set to 1 to free the first resource.
548 * ulp_ctxt [in] Ptr to ulp_context
549 * flow_type [in] Specify it is regular or default flow
550 * fid [in] The index to the flow entry
551 * params [in/out] The contents to be copied into params.
552 * Onlythe critical_resource needs to be set by the caller.
554 * Returns 0 on success and negative on failure.
557 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
558 enum bnxt_ulp_fdb_type flow_type,
560 struct ulp_flow_db_res_params *params)
562 struct bnxt_ulp_flow_db *flow_db;
563 struct bnxt_ulp_flow_tbl *flow_tbl;
564 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
565 uint32_t nxt_idx = 0;
567 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
569 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
573 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
574 BNXT_TF_DBG(ERR, "Invalid flow type\n");
578 flow_tbl = &flow_db->flow_tbl;
579 /* check for max flows */
580 if (fid >= flow_tbl->num_flows || !fid) {
581 BNXT_TF_DBG(ERR, "Invalid flow index\n");
585 /* check if the flow is active or not */
586 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
587 BNXT_TF_DBG(ERR, "flow does not exist\n");
591 fid_resource = &flow_tbl->flow_resources[fid];
592 if (!params->critical_resource) {
593 /* Not the critical resource so free the resource */
594 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
595 fid_resource->nxt_resource_idx);
597 /* reached end of resources */
600 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
602 /* connect the fid resource to the next resource */
603 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
604 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
605 nxt_resource->nxt_resource_idx);
607 /* update the contents to be given to caller */
608 ulp_flow_db_res_info_to_params(nxt_resource, params);
610 /* Delete the nxt_resource */
611 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
613 /* add it to the free list */
614 flow_tbl->tail_index++;
615 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
616 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
619 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
622 /* Critical resource. copy the contents and exit */
623 ulp_flow_db_res_info_to_params(fid_resource, params);
624 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
625 fid_resource->nxt_resource_idx);
626 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
627 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
631 /* Now that the HW Flow counter resource is deleted, reset it's
632 * corresponding slot in the SW accumulation table in the Flow Counter
635 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
636 params->resource_sub_type ==
637 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
638 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
639 params->resource_hndl);
642 /* all good, return success */
647 * Free the flow database entry
649 * ulp_ctxt [in] Ptr to ulp_context
650 * flow_type [in] - specify default or regular
651 * fid [in] The index to the flow entry
653 * returns 0 on success and negative on failure.
656 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
657 enum bnxt_ulp_fdb_type flow_type,
660 struct bnxt_ulp_flow_db *flow_db;
661 struct bnxt_ulp_flow_tbl *flow_tbl;
663 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
665 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
669 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
670 BNXT_TF_DBG(ERR, "Invalid flow type\n");
674 flow_tbl = &flow_db->flow_tbl;
676 /* check for limits of fid */
677 if (fid >= flow_tbl->num_flows || !fid) {
678 BNXT_TF_DBG(ERR, "Invalid flow index\n");
682 /* check if the flow is active or not */
683 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
684 BNXT_TF_DBG(ERR, "flow does not exist\n");
687 flow_tbl->head_index--;
688 if (!flow_tbl->head_index) {
689 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
692 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
694 /* Clear the flows bitmap */
695 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
697 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
698 ulp_flow_db_func_id_set(flow_db, fid, 0);
700 /* all good, return success */
705 * Get the flow database entry details
707 * ulp_ctxt [in] Ptr to ulp_context
708 * flow_type [in] - specify default or regular
709 * fid [in] The index to the flow entry
710 * nxt_idx [in/out] the index to the next entry
711 * params [out] The contents to be copied into params.
713 * returns 0 on success and negative on failure.
716 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
717 enum bnxt_ulp_fdb_type flow_type,
720 struct ulp_flow_db_res_params *params)
722 struct bnxt_ulp_flow_db *flow_db;
723 struct bnxt_ulp_flow_tbl *flow_tbl;
724 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
726 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
728 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
732 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
733 BNXT_TF_DBG(ERR, "Invalid flow type\n");
737 flow_tbl = &flow_db->flow_tbl;
739 /* check for limits of fid */
740 if (fid >= flow_tbl->num_flows || !fid) {
741 BNXT_TF_DBG(ERR, "Invalid flow index\n");
745 /* check if the flow is active or not */
746 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
747 BNXT_TF_DBG(ERR, "flow does not exist\n");
752 fid_resource = &flow_tbl->flow_resources[fid];
753 ulp_flow_db_res_info_to_params(fid_resource, params);
754 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
755 fid_resource->nxt_resource_idx);
757 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
758 ulp_flow_db_res_info_to_params(nxt_resource, params);
760 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
761 nxt_resource->nxt_resource_idx);
764 /* all good, return success */
769 * Get the flow database entry iteratively
771 * flow_tbl [in] Ptr to flow table
772 * flow_type [in] - specify default or regular
773 * fid [in/out] The index to the flow entry
775 * returns 0 on success and negative on failure.
778 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
779 enum bnxt_ulp_fdb_type flow_type,
782 uint32_t lfid = *fid;
783 uint32_t idx, s_idx, mod_fid;
785 uint64_t *active_flows;
786 struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
788 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
789 active_flows = flowtbl->active_reg_flows;
791 active_flows = flowtbl->active_dflt_flows;
794 /* increment the flow id to find the next valid flow id */
796 if (lfid >= flowtbl->num_flows)
798 idx = lfid / ULP_INDEX_BITMAP_SIZE;
799 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
801 while (!(bs = active_flows[idx])) {
803 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
807 * remove the previous bits in the bitset bs to find the
808 * next non zero bit in the bitset. This needs to be done
809 * only if the idx is same as he one you started.
812 bs &= (-1UL >> mod_fid);
813 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
815 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
818 } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
821 /* all good, return success */
827 * Flush all flows in the flow database.
829 * ulp_ctxt [in] Ptr to ulp context
830 * flow_type [in] - specify default or regular
832 * returns 0 on success or negative number on failure
835 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
836 enum bnxt_ulp_fdb_type flow_type)
839 struct bnxt_ulp_flow_db *flow_db;
842 BNXT_TF_DBG(ERR, "Invalid Argument\n");
846 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
848 BNXT_TF_DBG(ERR, "Flow database not found\n");
851 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
852 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
856 while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
857 ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
859 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
865 * Flush all flows in the flow database that belong to a device function.
867 * ulp_ctxt [in] Ptr to ulp context
868 * func_id [in] - The port function id
870 * returns 0 on success or negative number on failure
873 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
876 uint32_t flow_id = 0;
877 struct bnxt_ulp_flow_db *flow_db;
879 if (!ulp_ctx || !func_id) {
880 BNXT_TF_DBG(ERR, "Invalid Argument\n");
884 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
886 BNXT_TF_DBG(ERR, "Flow database not found\n");
889 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
890 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
894 while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
896 if (flow_db->func_id_tbl[flow_id] == func_id)
897 ulp_mapper_resources_free(ulp_ctx,
898 BNXT_ULP_FDB_TYPE_REGULAR,
901 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
906 * Flush all flows in the flow database that are associated with the session.
908 * ulp_ctxt [in] Ptr to ulp context
910 * returns 0 on success or negative number on failure
913 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
916 * TBD: Tf core implementation of FW session flush shall change this
919 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
923 * Check that flow id matches the function id or not
925 * ulp_ctxt [in] Ptr to ulp context
926 * flow_db [in] Ptr to flow table
927 * func_id [in] The func_id to be set, for reset pass zero.
929 * returns true on success or false on failure
932 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
936 struct bnxt_ulp_flow_db *flow_db;
938 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
940 BNXT_TF_DBG(ERR, "Flow database not found\n");
944 /* set the function id in the function table */
945 if (flow_id < flow_db->func_id_tbl_size && func_id &&
946 flow_db->func_id_tbl[flow_id] == func_id)
953 * Internal api to traverse the resource list within a flow
954 * and match a resource based on resource func and resource
955 * sub type. This api should be used only for resources that
956 * are unique and do not have multiple instances of resource
957 * func and sub type combination since it will return only
961 ulp_flow_db_resource_hndl_get(struct bnxt_ulp_context *ulp_ctx,
962 enum bnxt_ulp_fdb_type flow_type,
964 uint32_t resource_func,
965 uint32_t res_subtype,
968 struct bnxt_ulp_flow_db *flow_db;
969 struct bnxt_ulp_flow_tbl *flow_tbl;
970 struct ulp_fdb_resource_info *fid_res;
973 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
975 BNXT_TF_DBG(ERR, "Flow database not found\n");
979 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
980 BNXT_TF_DBG(ERR, "Invalid flow type\n");
984 flow_tbl = &flow_db->flow_tbl;
986 /* check for limits of fid */
987 if (flow_id >= flow_tbl->num_flows || !flow_id) {
988 BNXT_TF_DBG(ERR, "Invalid flow index\n");
992 /* check if the flow is active or not */
993 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
994 BNXT_TF_DBG(ERR, "flow does not exist\n");
997 /* Iterate the resource to get the resource handle */
1000 fid_res = &flow_tbl->flow_resources[res_id];
1001 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
1002 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
1003 if (res_subtype == fid_res->resource_sub_type) {
1004 *res_hndl = fid_res->resource_hndl;
1008 } else if (resource_func ==
1009 BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
1011 BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
1012 *res_hndl = fid_res->resource_em_handle;
1017 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1023 * Api to get the cfa action pointer from a flow.
1025 * ulp_ctxt [in] Ptr to ulp context
1026 * flow_id [in] flow id
1027 * cfa_action [out] The resource handle stored in the flow database
1029 * returns 0 on success
1032 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1034 uint16_t *cfa_action)
1036 uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_CFA_ACTION;
1040 rc = ulp_flow_db_resource_hndl_get(ulp_ctx,
1041 BNXT_ULP_FDB_TYPE_DEFAULT,
1043 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1046 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",