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);
355 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
359 /* Detach the flow database from the ulp context. */
360 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
362 /* Free up all the memory. */
363 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
364 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
365 rte_free(flow_db->func_id_tbl);
372 * Allocate the flow database entry
374 * ulp_ctxt [in] Ptr to ulp_context
375 * tbl_idx [in] Specify it is regular or default flow
376 * fid [out] The index to the flow entry
378 * returns 0 on success and negative on failure.
380 int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
381 enum bnxt_ulp_flow_db_tables tbl_idx,
385 struct bnxt_ulp_flow_db *flow_db;
386 struct bnxt_ulp_flow_tbl *flow_tbl;
388 *fid = 0; /* Initialize fid to invalid value */
389 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
391 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
395 flow_tbl = &flow_db->flow_tbl[tbl_idx];
396 /* check for max flows */
397 if (flow_tbl->num_flows <= flow_tbl->head_index) {
398 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
401 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
402 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
405 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
406 flow_tbl->head_index++;
407 ulp_flow_db_active_flow_set(flow_tbl, *fid, 1);
409 /* The function id update is only valid for regular flow table */
410 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
411 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
413 /* all good, return success */
418 * Allocate the flow database entry.
419 * The params->critical_resource has to be set to 0 to allocate a new resource.
421 * ulp_ctxt [in] Ptr to ulp_context
422 * tbl_idx [in] Specify it is regular or default flow
423 * fid [in] The index to the flow entry
424 * params [in] The contents to be copied into resource
426 * returns 0 on success and negative on failure.
428 int32_t ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
429 enum bnxt_ulp_flow_db_tables tbl_idx,
431 struct ulp_flow_db_res_params *params)
433 struct bnxt_ulp_flow_db *flow_db;
434 struct bnxt_ulp_flow_tbl *flow_tbl;
435 struct ulp_fdb_resource_info *resource, *fid_resource;
438 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
440 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
444 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
445 BNXT_TF_DBG(ERR, "Invalid table index\n");
448 flow_tbl = &flow_db->flow_tbl[tbl_idx];
450 /* check for max flows */
451 if (fid >= flow_tbl->num_flows || !fid) {
452 BNXT_TF_DBG(ERR, "Invalid flow index\n");
456 /* check if the flow is active or not */
457 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
458 BNXT_TF_DBG(ERR, "flow does not exist\n");
462 /* check for max resource */
463 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
464 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
467 fid_resource = &flow_tbl->flow_resources[fid];
469 if (!params->critical_resource) {
470 /* Not the critical_resource so allocate a resource */
471 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
472 resource = &flow_tbl->flow_resources[idx];
473 flow_tbl->tail_index--;
475 /* Update the chain list of resource*/
476 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
477 fid_resource->nxt_resource_idx);
478 /* update the contents */
479 ulp_flow_db_res_params_to_info(resource, params);
480 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
481 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
484 /* critical resource. Just update the fid resource */
485 ulp_flow_db_res_params_to_info(fid_resource, params);
488 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
489 params->resource_sub_type ==
490 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
491 /* Store the first HW counter ID for this table */
492 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
493 ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
494 params->resource_hndl);
496 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
497 params->resource_hndl);
499 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
500 ulp_fc_mgr_thread_start(ulp_ctxt);
503 /* all good, return success */
508 * Free the flow database entry.
509 * The params->critical_resource has to be set to 1 to free the first resource.
511 * ulp_ctxt [in] Ptr to ulp_context
512 * tbl_idx [in] Specify it is regular or default flow
513 * fid [in] The index to the flow entry
514 * params [in/out] The contents to be copied into params.
515 * Onlythe critical_resource needs to be set by the caller.
517 * Returns 0 on success and negative on failure.
519 int32_t ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
520 enum bnxt_ulp_flow_db_tables tbl_idx,
522 struct ulp_flow_db_res_params *params)
524 struct bnxt_ulp_flow_db *flow_db;
525 struct bnxt_ulp_flow_tbl *flow_tbl;
526 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
527 uint32_t nxt_idx = 0;
529 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
531 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
535 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
536 BNXT_TF_DBG(ERR, "Invalid table index\n");
539 flow_tbl = &flow_db->flow_tbl[tbl_idx];
541 /* check for max flows */
542 if (fid >= flow_tbl->num_flows || !fid) {
543 BNXT_TF_DBG(ERR, "Invalid flow index\n");
547 /* check if the flow is active or not */
548 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
549 BNXT_TF_DBG(ERR, "flow does not exist\n");
553 fid_resource = &flow_tbl->flow_resources[fid];
554 if (!params->critical_resource) {
555 /* Not the critical resource so free the resource */
556 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
557 fid_resource->nxt_resource_idx);
559 /* reached end of resources */
562 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
564 /* connect the fid resource to the next resource */
565 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
566 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
567 nxt_resource->nxt_resource_idx);
569 /* update the contents to be given to caller */
570 ulp_flow_db_res_info_to_params(nxt_resource, params);
572 /* Delete the nxt_resource */
573 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
575 /* add it to the free list */
576 flow_tbl->tail_index++;
577 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
578 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
581 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
584 /* Critical resource. copy the contents and exit */
585 ulp_flow_db_res_info_to_params(fid_resource, params);
586 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
587 fid_resource->nxt_resource_idx);
588 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
589 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
593 /* Now that the HW Flow counter resource is deleted, reset it's
594 * corresponding slot in the SW accumulation table in the Flow Counter
597 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
598 params->resource_sub_type ==
599 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
600 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
601 params->resource_hndl);
604 /* all good, return success */
609 * Free the flow database entry
611 * ulp_ctxt [in] Ptr to ulp_context
612 * tbl_idx [in] Specify it is regular or default flow
613 * fid [in] The index to the flow entry
615 * returns 0 on success and negative on failure.
617 int32_t ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
618 enum bnxt_ulp_flow_db_tables tbl_idx,
621 struct bnxt_ulp_flow_db *flow_db;
622 struct bnxt_ulp_flow_tbl *flow_tbl;
624 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
626 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
630 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
631 BNXT_TF_DBG(ERR, "Invalid table index\n");
635 flow_tbl = &flow_db->flow_tbl[tbl_idx];
637 /* check for limits of fid */
638 if (fid >= flow_tbl->num_flows || !fid) {
639 BNXT_TF_DBG(ERR, "Invalid flow index\n");
643 /* check if the flow is active or not */
644 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
645 BNXT_TF_DBG(ERR, "flow does not exist\n");
648 flow_tbl->head_index--;
649 if (!flow_tbl->head_index) {
650 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
653 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
654 ulp_flow_db_active_flow_set(flow_tbl, fid, 0);
655 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
656 ulp_flow_db_func_id_set(flow_db, fid, 0);
658 /* all good, return success */
663 * Get the flow database entry details
665 * ulp_ctxt [in] Ptr to ulp_context
666 * tbl_idx [in] Specify it is regular or default flow
667 * fid [in] The index to the flow entry
668 * nxt_idx [in/out] the index to the next entry
669 * params [out] The contents to be copied into params.
671 * returns 0 on success and negative on failure.
673 int32_t ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
674 enum bnxt_ulp_flow_db_tables tbl_idx,
677 struct ulp_flow_db_res_params *params)
679 struct bnxt_ulp_flow_db *flow_db;
680 struct bnxt_ulp_flow_tbl *flow_tbl;
681 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
683 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
685 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
689 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
690 BNXT_TF_DBG(ERR, "Invalid table index\n");
694 flow_tbl = &flow_db->flow_tbl[tbl_idx];
696 /* check for limits of fid */
697 if (fid >= flow_tbl->num_flows || !fid) {
698 BNXT_TF_DBG(ERR, "Invalid flow index\n");
702 /* check if the flow is active or not */
703 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
704 BNXT_TF_DBG(ERR, "flow does not exist\n");
709 fid_resource = &flow_tbl->flow_resources[fid];
710 ulp_flow_db_res_info_to_params(fid_resource, params);
711 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
712 fid_resource->nxt_resource_idx);
714 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
715 ulp_flow_db_res_info_to_params(nxt_resource, params);
717 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
718 nxt_resource->nxt_resource_idx);
721 /* all good, return success */
726 * Get the flow database entry iteratively
728 * flow_tbl [in] Ptr to flow table
729 * fid [in/out] The index to the flow entry
731 * returns 0 on success and negative on failure.
734 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_tbl *flowtbl,
737 uint32_t lfid = *fid;
738 uint32_t idx, s_idx, mod_fid;
742 /* increment the flow id to find the next valid flow id */
744 if (lfid >= flowtbl->num_flows)
746 idx = lfid / ULP_INDEX_BITMAP_SIZE;
747 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
749 while (!(bs = flowtbl->active_flow_tbl[idx])) {
751 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
755 * remove the previous bits in the bitset bs to find the
756 * next non zero bit in the bitset. This needs to be done
757 * only if the idx is same as he one you started.
760 bs &= (-1UL >> mod_fid);
761 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
763 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
766 } while (!ulp_flow_db_active_flow_is_set(flowtbl, lfid));
768 /* all good, return success */
774 * Flush all flows in the flow database.
776 * ulp_ctxt [in] Ptr to ulp context
777 * tbl_idx [in] The index to table
779 * returns 0 on success or negative number on failure
781 int32_t ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
785 struct bnxt_ulp_flow_db *flow_db;
786 struct bnxt_ulp_flow_tbl *flow_tbl;
789 BNXT_TF_DBG(ERR, "Invalid Argument\n");
793 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
795 BNXT_TF_DBG(ERR, "Flow database not found\n");
798 flow_tbl = &flow_db->flow_tbl[idx];
799 while (!ulp_flow_db_next_entry_get(flow_tbl, &fid))
800 ulp_mapper_resources_free(ulp_ctx, fid, idx);
806 * Flush all flows in the flow database that belong to a device function.
808 * ulp_ctxt [in] Ptr to ulp context
809 * tbl_idx [in] The index to table
811 * returns 0 on success or negative number on failure
814 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
817 uint32_t flow_id = 0;
818 struct bnxt_ulp_flow_db *flow_db;
819 struct bnxt_ulp_flow_tbl *flow_tbl;
821 if (!ulp_ctx || !func_id) {
822 BNXT_TF_DBG(ERR, "Invalid Argument\n");
826 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
828 BNXT_TF_DBG(ERR, "Flow database not found\n");
831 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
832 while (!ulp_flow_db_next_entry_get(flow_tbl, &flow_id)) {
833 if (flow_db->func_id_tbl[flow_id] == func_id)
834 ulp_mapper_resources_free(ulp_ctx, flow_id,
835 BNXT_ULP_REGULAR_FLOW_TABLE);
842 * Flush all flows in the flow database that are associated with the session.
844 * ulp_ctxt [in] Ptr to ulp context
846 * returns 0 on success or negative number on failure
849 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
852 * TBD: Tf core implementation of FW session flush shall change this
855 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
859 * Check that flow id matches the function id or not
861 * ulp_ctxt [in] Ptr to ulp context
862 * flow_db [in] Ptr to flow table
863 * func_id [in] The func_id to be set, for reset pass zero.
865 * returns true on success or false on failure
868 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
872 struct bnxt_ulp_flow_db *flow_db;
874 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
876 BNXT_TF_DBG(ERR, "Flow database not found\n");
880 /* set the function id in the function table */
881 if (flow_id < flow_db->func_id_tbl_size && func_id &&
882 flow_db->func_id_tbl[flow_id] == func_id)
889 * Internal api to traverse the resource list within a flow
890 * and match a resource based on resource func and resource
891 * sub type. This api should be used only for resources that
892 * are unique and do not have multiple instances of resource
893 * func and sub type combination since it will return only
897 ulp_flow_db_resource_hndl_get(struct bnxt_ulp_context *ulp_ctx,
898 enum bnxt_ulp_flow_db_tables tbl_idx,
900 uint32_t resource_func,
901 uint32_t res_subtype,
904 struct bnxt_ulp_flow_db *flow_db;
905 struct bnxt_ulp_flow_tbl *flow_tbl;
906 struct ulp_fdb_resource_info *fid_res;
909 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
911 BNXT_TF_DBG(ERR, "Flow database not found\n");
915 flow_tbl = &flow_db->flow_tbl[tbl_idx];
917 /* check for limits of fid */
918 if (flow_id >= flow_tbl->num_flows || !flow_id) {
919 BNXT_TF_DBG(ERR, "Invalid flow index\n");
923 /* check if the flow is active or not */
924 if (!ulp_flow_db_active_flow_is_set(flow_tbl, flow_id)) {
925 BNXT_TF_DBG(ERR, "flow does not exist\n");
928 /* Iterate the resource to get the resource handle */
931 fid_res = &flow_tbl->flow_resources[res_id];
932 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
933 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
934 if (res_subtype == fid_res->resource_sub_type) {
935 *res_hndl = fid_res->resource_hndl;
939 } else if (resource_func ==
940 BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
942 BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
943 *res_hndl = fid_res->resource_em_handle;
948 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
954 * Api to get the cfa action pointer from a flow.
956 * ulp_ctxt [in] Ptr to ulp context
957 * flow_id [in] flow id
958 * cfa_action [out] The resource handle stored in the flow database
960 * returns 0 on success
963 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
965 uint16_t *cfa_action)
967 uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_CFA_ACTION;
971 rc = ulp_flow_db_resource_hndl_get(ulp_ctx,
972 BNXT_ULP_DEFAULT_FLOW_TABLE,
974 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
977 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
985 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
987 * Dump the entry details
989 * ulp_ctxt [in] Ptr to ulp_context
993 static void ulp_flow_db_res_dump(struct ulp_fdb_resource_info *r,
996 uint8_t res_func = ulp_flow_db_resource_func_get(r);
998 BNXT_TF_DBG(DEBUG, "Resource func = %x, nxt_resource_idx = %x\n",
999 res_func, (ULP_FLOW_DB_RES_NXT_MASK & r->nxt_resource_idx));
1000 if (res_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
1001 res_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
1002 BNXT_TF_DBG(DEBUG, "EM Handle = 0x%016" PRIX64 "\n",
1003 r->resource_em_handle);
1005 BNXT_TF_DBG(DEBUG, "Handle = 0x%08x\n", r->resource_hndl);
1008 ULP_FLOW_DB_RES_NXT_SET(*nxt_res,
1009 r->nxt_resource_idx);
1013 * Dump the flow database entry details
1015 * ulp_ctxt [in] Ptr to ulp_context
1019 int32_t ulp_flow_db_debug_dump(struct bnxt_ulp_context *ulp_ctxt)
1021 struct bnxt_ulp_flow_db *flow_db;
1022 struct bnxt_ulp_flow_tbl *flow_tbl;
1023 struct ulp_fdb_resource_info *r;
1024 uint32_t nxt_res = 0;
1025 enum bnxt_ulp_flow_db_tables tbl_idx;
1028 if (!ulp_ctxt || !ulp_ctxt->cfg_data) {
1029 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1032 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1034 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1038 for (tbl_idx = 0; tbl_idx < BNXT_ULP_FLOW_TABLE_MAX; tbl_idx++) {
1039 flow_tbl = &flow_db->flow_tbl[tbl_idx];
1040 BNXT_TF_DBG(DEBUG, "Dump Tbl index = %u, flows = %u:%u\n",
1041 tbl_idx, flow_tbl->num_flows,
1042 flow_tbl->num_resources);
1043 BNXT_TF_DBG(DEBUG, "Head_index = %u, Tail_index = %u\n",
1044 flow_tbl->head_index, flow_tbl->tail_index);
1045 for (fid = 0; fid < flow_tbl->num_flows; fid++) {
1046 if (ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
1047 BNXT_TF_DBG(DEBUG, "fid = %u\n", fid);
1048 /* iterate the resource */
1051 r = &flow_tbl->flow_resources[nxt_res];
1052 ulp_flow_db_res_dump(r, &nxt_res);
1056 BNXT_TF_DBG(DEBUG, "Done.\n");