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 flow table
31 * No validation is done in this function.
33 * flow_tbl [in] Ptr to flow table
34 * idx [in] The index to bit to be set or reset.
35 * flag [in] 1 to set and 0 to reset.
40 ulp_flow_db_active_flow_set(struct bnxt_ulp_flow_tbl *flow_tbl,
44 uint32_t active_index;
46 active_index = idx / ULP_INDEX_BITMAP_SIZE;
48 ULP_INDEX_BITMAP_SET(flow_tbl->active_flow_tbl[active_index],
51 ULP_INDEX_BITMAP_RESET(flow_tbl->active_flow_tbl[active_index],
56 * Helper function to allocate the flow table and initialize
57 * is set.No validation being done in this function.
59 * flow_tbl [in] Ptr to flow table
60 * idx [in] The index to bit to be set or reset.
62 * returns 1 on set or 0 if not set.
65 ulp_flow_db_active_flow_is_set(struct bnxt_ulp_flow_tbl *flow_tbl,
68 uint32_t active_index;
70 active_index = idx / ULP_INDEX_BITMAP_SIZE;
71 return ULP_INDEX_BITMAP_GET(flow_tbl->active_flow_tbl[active_index],
76 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
80 func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
81 ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
82 /* The reource func is split into upper and lower */
83 if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
84 return (func | res_info->resource_func_lower);
89 * Helper function to copy the resource params to resource info
90 * No validation being done in this function.
92 * resource_info [out] Ptr to resource information
93 * params [in] The input params from the caller
97 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
98 struct ulp_flow_db_res_params *params)
100 uint32_t resource_func;
102 resource_info->nxt_resource_idx |= ((params->direction <<
103 ULP_FLOW_DB_RES_DIR_BIT) &
104 ULP_FLOW_DB_RES_DIR_MASK);
105 resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
106 resource_info->nxt_resource_idx |= ((resource_func <<
107 ULP_FLOW_DB_RES_FUNC_BITS) &
108 ULP_FLOW_DB_RES_FUNC_MASK);
110 if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
111 /* Break the resource func into two parts */
112 resource_func = (params->resource_func &
113 ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
114 resource_info->resource_func_lower = resource_func;
117 /* Store the handle as 64bit only for EM table entries */
118 if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE &&
119 params->resource_func != BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
120 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
121 resource_info->resource_type = params->resource_type;
122 resource_info->resource_sub_type = params->resource_sub_type;
123 resource_info->reserved = params->reserved;
125 resource_info->resource_em_handle = params->resource_hndl;
130 * Helper function to copy the resource params to resource info
131 * No validation being done in this function.
133 * resource_info [in] Ptr to resource information
134 * params [out] The output params to the caller
139 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
140 struct ulp_flow_db_res_params *params)
142 memset(params, 0, sizeof(struct ulp_flow_db_res_params));
143 params->direction = ((resource_info->nxt_resource_idx &
144 ULP_FLOW_DB_RES_DIR_MASK) >>
145 ULP_FLOW_DB_RES_DIR_BIT);
147 /* use the helper function to get the resource func */
148 params->resource_func = ulp_flow_db_resource_func_get(resource_info);
150 if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
151 params->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
152 params->resource_hndl = resource_info->resource_em_handle;
153 } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
154 params->resource_hndl = resource_info->resource_hndl;
155 params->resource_type = resource_info->resource_type;
156 params->resource_sub_type = resource_info->resource_sub_type;
157 params->reserved = resource_info->reserved;
162 * Helper function to allocate the flow table and initialize
163 * the stack for allocation operations.
165 * flow_db [in] Ptr to flow database structure
166 * tbl_idx [in] The index to table creation.
168 * Returns 0 on success or negative number on failure.
171 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db,
172 enum bnxt_ulp_flow_db_tables tbl_idx)
175 struct bnxt_ulp_flow_tbl *flow_tbl;
178 flow_tbl = &flow_db->flow_tbl[tbl_idx];
180 size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
181 flow_tbl->flow_resources =
182 rte_zmalloc("ulp_fdb_resource_info", size, 0);
184 if (!flow_tbl->flow_resources) {
185 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
188 size = sizeof(uint32_t) * flow_tbl->num_resources;
189 flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
190 if (!flow_tbl->flow_tbl_stack) {
191 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
194 size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
195 flow_tbl->active_flow_tbl = rte_zmalloc("active flow tbl", size, 0);
196 if (!flow_tbl->active_flow_tbl) {
197 BNXT_TF_DBG(ERR, "Failed to alloc memory active tbl\n");
201 /* Initialize the stack table. */
202 for (idx = 0; idx < flow_tbl->num_resources; idx++)
203 flow_tbl->flow_tbl_stack[idx] = idx;
205 /* Ignore the first element in the list. */
206 flow_tbl->head_index = 1;
207 /* Tail points to the last entry in the list. */
208 flow_tbl->tail_index = flow_tbl->num_resources - 1;
213 * Helper function to deallocate the flow table.
215 * flow_db [in] Ptr to flow database structure
216 * tbl_idx [in] The index to table creation.
221 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db,
222 enum bnxt_ulp_flow_db_tables tbl_idx)
224 struct bnxt_ulp_flow_tbl *flow_tbl;
226 flow_tbl = &flow_db->flow_tbl[tbl_idx];
228 /* Free all the allocated tables in the flow table. */
229 if (flow_tbl->active_flow_tbl) {
230 rte_free(flow_tbl->active_flow_tbl);
231 flow_tbl->active_flow_tbl = NULL;
234 if (flow_tbl->flow_tbl_stack) {
235 rte_free(flow_tbl->flow_tbl_stack);
236 flow_tbl->flow_tbl_stack = NULL;
239 if (flow_tbl->flow_resources) {
240 rte_free(flow_tbl->flow_resources);
241 flow_tbl->flow_resources = NULL;
246 * Helper function to add function id to the flow table
248 * flow_db [in] Ptr to flow table
249 * flow_id [in] The flow id of the flow
250 * func_id [in] The func_id to be set, for reset pass zero
255 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
259 /* set the function id in the function table */
260 if (flow_id < flow_db->func_id_tbl_size)
261 flow_db->func_id_tbl[flow_id] = func_id;
262 else /* This should never happen */
263 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
267 * Initialize the flow database. Memory is allocated in this
268 * call and assigned to the flow database.
270 * ulp_ctxt [in] Ptr to ulp context
272 * Returns 0 on success or negative number on failure.
274 int32_t ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
276 struct bnxt_ulp_device_params *dparms;
277 struct bnxt_ulp_flow_tbl *flow_tbl;
278 struct bnxt_ulp_flow_db *flow_db;
281 /* Get the dev specific number of flows that needed to be supported. */
282 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
283 BNXT_TF_DBG(ERR, "Invalid device id\n");
287 dparms = bnxt_ulp_device_params_get(dev_id);
289 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
293 flow_db = rte_zmalloc("bnxt_ulp_flow_db",
294 sizeof(struct bnxt_ulp_flow_db), 0);
297 "Failed to allocate memory for flow table ptr\n");
301 /* Attach the flow database to the ulp context. */
302 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
304 /* Populate the regular flow table limits. */
305 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
306 flow_tbl->num_flows = dparms->flow_db_num_entries + 1;
307 flow_tbl->num_resources = (flow_tbl->num_flows *
308 dparms->num_resources_per_flow);
310 /* Populate the default flow table limits. */
311 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_DEFAULT_FLOW_TABLE];
312 flow_tbl->num_flows = BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1;
313 flow_tbl->num_resources = (flow_tbl->num_flows *
314 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
316 /* Allocate the resource for the regular flow table. */
317 if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE))
319 if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE))
322 /* add 1 since we are not using index 0 for flow id */
323 flow_db->func_id_tbl_size = dparms->flow_db_num_entries + 1;
324 /* Allocate the function Id table */
325 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
326 flow_db->func_id_tbl_size *
327 sizeof(uint16_t), 0);
328 if (!flow_db->func_id_tbl) {
330 "Failed to allocate mem for flow table func id\n");
333 /* All good so return. */
336 ulp_flow_db_deinit(ulp_ctxt);
341 * Deinitialize the flow database. Memory is deallocated in
342 * this call and all flows should have been purged before this
345 * ulp_ctxt [in] Ptr to ulp context
347 * Returns 0 on success.
349 int32_t ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
351 struct bnxt_ulp_flow_db *flow_db;
353 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
357 /* Detach the flow database from the ulp context. */
358 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
360 /* Free up all the memory. */
361 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
362 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
363 rte_free(flow_db->func_id_tbl);
370 * Allocate the flow database entry
372 * ulp_ctxt [in] Ptr to ulp_context
373 * tbl_idx [in] Specify it is regular or default flow
374 * fid [out] The index to the flow entry
376 * returns 0 on success and negative on failure.
378 int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
379 enum bnxt_ulp_flow_db_tables tbl_idx,
383 struct bnxt_ulp_flow_db *flow_db;
384 struct bnxt_ulp_flow_tbl *flow_tbl;
386 *fid = 0; /* Initialize fid to invalid value */
387 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
389 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
393 flow_tbl = &flow_db->flow_tbl[tbl_idx];
394 /* check for max flows */
395 if (flow_tbl->num_flows <= flow_tbl->head_index) {
396 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
399 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
400 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
403 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
404 flow_tbl->head_index++;
405 ulp_flow_db_active_flow_set(flow_tbl, *fid, 1);
407 /* The function id update is only valid for regular flow table */
408 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
409 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
411 /* all good, return success */
416 * Allocate the flow database entry.
417 * The params->critical_resource has to be set to 0 to allocate a new resource.
419 * ulp_ctxt [in] Ptr to ulp_context
420 * tbl_idx [in] Specify it is regular or default flow
421 * fid [in] The index to the flow entry
422 * params [in] The contents to be copied into resource
424 * returns 0 on success and negative on failure.
426 int32_t ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
427 enum bnxt_ulp_flow_db_tables tbl_idx,
429 struct ulp_flow_db_res_params *params)
431 struct bnxt_ulp_flow_db *flow_db;
432 struct bnxt_ulp_flow_tbl *flow_tbl;
433 struct ulp_fdb_resource_info *resource, *fid_resource;
436 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
438 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
442 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
443 BNXT_TF_DBG(ERR, "Invalid table index\n");
446 flow_tbl = &flow_db->flow_tbl[tbl_idx];
448 /* check for max flows */
449 if (fid >= flow_tbl->num_flows || !fid) {
450 BNXT_TF_DBG(ERR, "Invalid flow index\n");
454 /* check if the flow is active or not */
455 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
456 BNXT_TF_DBG(ERR, "flow does not exist\n");
460 /* check for max resource */
461 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
462 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
465 fid_resource = &flow_tbl->flow_resources[fid];
467 if (!params->critical_resource) {
468 /* Not the critical_resource so allocate a resource */
469 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
470 resource = &flow_tbl->flow_resources[idx];
471 flow_tbl->tail_index--;
473 /* Update the chain list of resource*/
474 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
475 fid_resource->nxt_resource_idx);
476 /* update the contents */
477 ulp_flow_db_res_params_to_info(resource, params);
478 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
479 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
482 /* critical resource. Just update the fid resource */
483 ulp_flow_db_res_params_to_info(fid_resource, params);
486 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
487 params->resource_sub_type ==
488 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
489 /* Store the first HW counter ID for this table */
490 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
491 ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
492 params->resource_hndl);
494 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
495 params->resource_hndl);
497 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
498 ulp_fc_mgr_thread_start(ulp_ctxt);
501 /* all good, return success */
506 * Free the flow database entry.
507 * The params->critical_resource has to be set to 1 to free the first resource.
509 * ulp_ctxt [in] Ptr to ulp_context
510 * tbl_idx [in] Specify it is regular or default flow
511 * fid [in] The index to the flow entry
512 * params [in/out] The contents to be copied into params.
513 * Onlythe critical_resource needs to be set by the caller.
515 * Returns 0 on success and negative on failure.
517 int32_t ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
518 enum bnxt_ulp_flow_db_tables tbl_idx,
520 struct ulp_flow_db_res_params *params)
522 struct bnxt_ulp_flow_db *flow_db;
523 struct bnxt_ulp_flow_tbl *flow_tbl;
524 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
525 uint32_t nxt_idx = 0;
527 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
529 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
533 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
534 BNXT_TF_DBG(ERR, "Invalid table index\n");
537 flow_tbl = &flow_db->flow_tbl[tbl_idx];
539 /* check for max flows */
540 if (fid >= flow_tbl->num_flows || !fid) {
541 BNXT_TF_DBG(ERR, "Invalid flow index\n");
545 /* check if the flow is active or not */
546 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
547 BNXT_TF_DBG(ERR, "flow does not exist\n");
551 fid_resource = &flow_tbl->flow_resources[fid];
552 if (!params->critical_resource) {
553 /* Not the critical resource so free the resource */
554 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
555 fid_resource->nxt_resource_idx);
557 /* reached end of resources */
560 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
562 /* connect the fid resource to the next resource */
563 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
564 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
565 nxt_resource->nxt_resource_idx);
567 /* update the contents to be given to caller */
568 ulp_flow_db_res_info_to_params(nxt_resource, params);
570 /* Delete the nxt_resource */
571 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
573 /* add it to the free list */
574 flow_tbl->tail_index++;
575 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
576 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
579 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
582 /* Critical resource. copy the contents and exit */
583 ulp_flow_db_res_info_to_params(fid_resource, params);
584 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
585 fid_resource->nxt_resource_idx);
586 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
587 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
591 /* Now that the HW Flow counter resource is deleted, reset it's
592 * corresponding slot in the SW accumulation table in the Flow Counter
595 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
596 params->resource_sub_type ==
597 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
598 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
599 params->resource_hndl);
602 /* all good, return success */
607 * Free the flow database entry
609 * ulp_ctxt [in] Ptr to ulp_context
610 * tbl_idx [in] Specify it is regular or default flow
611 * fid [in] The index to the flow entry
613 * returns 0 on success and negative on failure.
615 int32_t ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
616 enum bnxt_ulp_flow_db_tables tbl_idx,
619 struct bnxt_ulp_flow_db *flow_db;
620 struct bnxt_ulp_flow_tbl *flow_tbl;
622 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
624 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
628 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
629 BNXT_TF_DBG(ERR, "Invalid table index\n");
633 flow_tbl = &flow_db->flow_tbl[tbl_idx];
635 /* check for limits of fid */
636 if (fid >= flow_tbl->num_flows || !fid) {
637 BNXT_TF_DBG(ERR, "Invalid flow index\n");
641 /* check if the flow is active or not */
642 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
643 BNXT_TF_DBG(ERR, "flow does not exist\n");
646 flow_tbl->head_index--;
647 if (!flow_tbl->head_index) {
648 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
651 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
652 ulp_flow_db_active_flow_set(flow_tbl, fid, 0);
653 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
654 ulp_flow_db_func_id_set(flow_db, fid, 0);
656 /* all good, return success */
661 * Get the flow database entry details
663 * ulp_ctxt [in] Ptr to ulp_context
664 * tbl_idx [in] Specify it is regular or default flow
665 * fid [in] The index to the flow entry
666 * nxt_idx [in/out] the index to the next entry
667 * params [out] The contents to be copied into params.
669 * returns 0 on success and negative on failure.
671 int32_t ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
672 enum bnxt_ulp_flow_db_tables tbl_idx,
675 struct ulp_flow_db_res_params *params)
677 struct bnxt_ulp_flow_db *flow_db;
678 struct bnxt_ulp_flow_tbl *flow_tbl;
679 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
681 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
683 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
687 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
688 BNXT_TF_DBG(ERR, "Invalid table index\n");
692 flow_tbl = &flow_db->flow_tbl[tbl_idx];
694 /* check for limits of fid */
695 if (fid >= flow_tbl->num_flows || !fid) {
696 BNXT_TF_DBG(ERR, "Invalid flow index\n");
700 /* check if the flow is active or not */
701 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
702 BNXT_TF_DBG(ERR, "flow does not exist\n");
707 fid_resource = &flow_tbl->flow_resources[fid];
708 ulp_flow_db_res_info_to_params(fid_resource, params);
709 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
710 fid_resource->nxt_resource_idx);
712 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
713 ulp_flow_db_res_info_to_params(nxt_resource, params);
715 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
716 nxt_resource->nxt_resource_idx);
719 /* all good, return success */
724 * Get the flow database entry iteratively
726 * flow_tbl [in] Ptr to flow table
727 * fid [in/out] The index to the flow entry
729 * returns 0 on success and negative on failure.
732 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_tbl *flowtbl,
735 uint32_t lfid = *fid;
736 uint32_t idx, s_idx, mod_fid;
740 /* increment the flow id to find the next valid flow id */
742 if (lfid >= flowtbl->num_flows)
744 idx = lfid / ULP_INDEX_BITMAP_SIZE;
745 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
747 while (!(bs = flowtbl->active_flow_tbl[idx])) {
749 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
753 * remove the previous bits in the bitset bs to find the
754 * next non zero bit in the bitset. This needs to be done
755 * only if the idx is same as he one you started.
758 bs &= (-1UL >> mod_fid);
759 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
761 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
764 } while (!ulp_flow_db_active_flow_is_set(flowtbl, lfid));
766 /* all good, return success */
772 * Flush all flows in the flow database.
774 * ulp_ctxt [in] Ptr to ulp context
775 * tbl_idx [in] The index to table
777 * returns 0 on success or negative number on failure
779 int32_t ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
783 struct bnxt_ulp_flow_db *flow_db;
784 struct bnxt_ulp_flow_tbl *flow_tbl;
787 BNXT_TF_DBG(ERR, "Invalid Argument\n");
791 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
793 BNXT_TF_DBG(ERR, "Flow database not found\n");
796 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
797 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
801 flow_tbl = &flow_db->flow_tbl[idx];
802 while (!ulp_flow_db_next_entry_get(flow_tbl, &fid))
803 ulp_mapper_resources_free(ulp_ctx, fid, idx);
805 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
811 * Flush all flows in the flow database that belong to a device function.
813 * ulp_ctxt [in] Ptr to ulp context
814 * tbl_idx [in] The index to table
816 * returns 0 on success or negative number on failure
819 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
822 uint32_t flow_id = 0;
823 struct bnxt_ulp_flow_db *flow_db;
824 struct bnxt_ulp_flow_tbl *flow_tbl;
826 if (!ulp_ctx || !func_id) {
827 BNXT_TF_DBG(ERR, "Invalid Argument\n");
831 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
833 BNXT_TF_DBG(ERR, "Flow database not found\n");
836 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
837 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
840 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
841 while (!ulp_flow_db_next_entry_get(flow_tbl, &flow_id)) {
842 if (flow_db->func_id_tbl[flow_id] == func_id)
843 ulp_mapper_resources_free(ulp_ctx, flow_id,
844 BNXT_ULP_REGULAR_FLOW_TABLE);
846 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
851 * Flush all flows in the flow database that are associated with the session.
853 * ulp_ctxt [in] Ptr to ulp context
855 * returns 0 on success or negative number on failure
858 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
861 * TBD: Tf core implementation of FW session flush shall change this
864 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
868 * Check that flow id matches the function id or not
870 * ulp_ctxt [in] Ptr to ulp context
871 * flow_db [in] Ptr to flow table
872 * func_id [in] The func_id to be set, for reset pass zero.
874 * returns true on success or false on failure
877 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
881 struct bnxt_ulp_flow_db *flow_db;
883 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
885 BNXT_TF_DBG(ERR, "Flow database not found\n");
889 /* set the function id in the function table */
890 if (flow_id < flow_db->func_id_tbl_size && func_id &&
891 flow_db->func_id_tbl[flow_id] == func_id)
898 * Internal api to traverse the resource list within a flow
899 * and match a resource based on resource func and resource
900 * sub type. This api should be used only for resources that
901 * are unique and do not have multiple instances of resource
902 * func and sub type combination since it will return only
906 ulp_flow_db_resource_hndl_get(struct bnxt_ulp_context *ulp_ctx,
907 enum bnxt_ulp_flow_db_tables tbl_idx,
909 uint32_t resource_func,
910 uint32_t res_subtype,
913 struct bnxt_ulp_flow_db *flow_db;
914 struct bnxt_ulp_flow_tbl *flow_tbl;
915 struct ulp_fdb_resource_info *fid_res;
918 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
920 BNXT_TF_DBG(ERR, "Flow database not found\n");
924 flow_tbl = &flow_db->flow_tbl[tbl_idx];
926 /* check for limits of fid */
927 if (flow_id >= flow_tbl->num_flows || !flow_id) {
928 BNXT_TF_DBG(ERR, "Invalid flow index\n");
932 /* check if the flow is active or not */
933 if (!ulp_flow_db_active_flow_is_set(flow_tbl, flow_id)) {
934 BNXT_TF_DBG(ERR, "flow does not exist\n");
937 /* Iterate the resource to get the resource handle */
940 fid_res = &flow_tbl->flow_resources[res_id];
941 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
942 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
943 if (res_subtype == fid_res->resource_sub_type) {
944 *res_hndl = fid_res->resource_hndl;
948 } else if (resource_func ==
949 BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
951 BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
952 *res_hndl = fid_res->resource_em_handle;
957 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
963 * Api to get the cfa action pointer from a flow.
965 * ulp_ctxt [in] Ptr to ulp context
966 * flow_id [in] flow id
967 * cfa_action [out] The resource handle stored in the flow database
969 * returns 0 on success
972 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
974 uint16_t *cfa_action)
976 uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_CFA_ACTION;
980 rc = ulp_flow_db_resource_hndl_get(ulp_ctx,
981 BNXT_ULP_DEFAULT_FLOW_TABLE,
983 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
986 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
994 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
996 * Dump the entry details
998 * ulp_ctxt [in] Ptr to ulp_context
1002 static void ulp_flow_db_res_dump(struct ulp_fdb_resource_info *r,
1005 uint8_t res_func = ulp_flow_db_resource_func_get(r);
1007 BNXT_TF_DBG(DEBUG, "Resource func = %x, nxt_resource_idx = %x\n",
1008 res_func, (ULP_FLOW_DB_RES_NXT_MASK & r->nxt_resource_idx));
1009 if (res_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
1010 res_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1011 BNXT_TF_DBG(DEBUG, "EM Handle = 0x%016" PRIX64 "\n",
1012 r->resource_em_handle);
1014 BNXT_TF_DBG(DEBUG, "Handle = 0x%08x\n", r->resource_hndl);
1017 ULP_FLOW_DB_RES_NXT_SET(*nxt_res,
1018 r->nxt_resource_idx);
1022 * Dump the flow database entry details
1024 * ulp_ctxt [in] Ptr to ulp_context
1028 int32_t ulp_flow_db_debug_dump(struct bnxt_ulp_context *ulp_ctxt)
1030 struct bnxt_ulp_flow_db *flow_db;
1031 struct bnxt_ulp_flow_tbl *flow_tbl;
1032 struct ulp_fdb_resource_info *r;
1033 uint32_t nxt_res = 0;
1034 enum bnxt_ulp_flow_db_tables tbl_idx;
1037 if (!ulp_ctxt || !ulp_ctxt->cfg_data) {
1038 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1041 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1043 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1047 for (tbl_idx = 0; tbl_idx < BNXT_ULP_FLOW_TABLE_MAX; tbl_idx++) {
1048 flow_tbl = &flow_db->flow_tbl[tbl_idx];
1049 BNXT_TF_DBG(DEBUG, "Dump Tbl index = %u, flows = %u:%u\n",
1050 tbl_idx, flow_tbl->num_flows,
1051 flow_tbl->num_resources);
1052 BNXT_TF_DBG(DEBUG, "Head_index = %u, Tail_index = %u\n",
1053 flow_tbl->head_index, flow_tbl->tail_index);
1054 for (fid = 0; fid < flow_tbl->num_flows; fid++) {
1055 if (ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
1056 BNXT_TF_DBG(DEBUG, "fid = %u\n", fid);
1057 /* iterate the resource */
1060 r = &flow_tbl->flow_resources[nxt_res];
1061 ulp_flow_db_res_dump(r, &nxt_res);
1065 BNXT_TF_DBG(DEBUG, "Done.\n");