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"
14 #define ULP_FLOW_DB_RES_DIR_BIT 31
15 #define ULP_FLOW_DB_RES_DIR_MASK 0x80000000
16 #define ULP_FLOW_DB_RES_FUNC_BITS 28
17 #define ULP_FLOW_DB_RES_FUNC_MASK 0x70000000
18 #define ULP_FLOW_DB_RES_NXT_MASK 0x0FFFFFFF
19 #define ULP_FLOW_DB_RES_FUNC_UPPER 5
20 #define ULP_FLOW_DB_RES_FUNC_NEED_LOWER 0x80
21 #define ULP_FLOW_DB_RES_FUNC_LOWER_MASK 0x1F
23 /* Macro to copy the nxt_resource_idx */
24 #define ULP_FLOW_DB_RES_NXT_SET(dst, src) {(dst) |= ((src) &\
25 ULP_FLOW_DB_RES_NXT_MASK); }
26 #define ULP_FLOW_DB_RES_NXT_RESET(dst) ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
29 * Helper function to set the bit in the active flow table
30 * No validation is done in this function.
32 * flow_tbl [in] Ptr to flow table
33 * idx [in] The index to bit to be set or reset.
34 * flag [in] 1 to set and 0 to reset.
39 ulp_flow_db_active_flow_set(struct bnxt_ulp_flow_tbl *flow_tbl,
43 uint32_t active_index;
45 active_index = idx / ULP_INDEX_BITMAP_SIZE;
47 ULP_INDEX_BITMAP_SET(flow_tbl->active_flow_tbl[active_index],
50 ULP_INDEX_BITMAP_RESET(flow_tbl->active_flow_tbl[active_index],
55 * Helper function to allocate the flow table and initialize
56 * is set.No validation being done in this function.
58 * flow_tbl [in] Ptr to flow table
59 * idx [in] The index to bit to be set or reset.
61 * returns 1 on set or 0 if not set.
64 ulp_flow_db_active_flow_is_set(struct bnxt_ulp_flow_tbl *flow_tbl,
67 uint32_t active_index;
69 active_index = idx / ULP_INDEX_BITMAP_SIZE;
70 return ULP_INDEX_BITMAP_GET(flow_tbl->active_flow_tbl[active_index],
75 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
79 func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
80 ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
81 /* The reource func is split into upper and lower */
82 if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
83 return (func | res_info->resource_func_lower);
88 * Helper function to copy the resource params to resource info
89 * No validation being done in this function.
91 * resource_info [out] Ptr to resource information
92 * params [in] The input params from the caller
96 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
97 struct ulp_flow_db_res_params *params)
99 uint32_t resource_func;
101 resource_info->nxt_resource_idx |= ((params->direction <<
102 ULP_FLOW_DB_RES_DIR_BIT) &
103 ULP_FLOW_DB_RES_DIR_MASK);
104 resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
105 resource_info->nxt_resource_idx |= ((resource_func <<
106 ULP_FLOW_DB_RES_FUNC_BITS) &
107 ULP_FLOW_DB_RES_FUNC_MASK);
109 if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
110 /* Break the resource func into two parts */
111 resource_func = (params->resource_func &
112 ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
113 resource_info->resource_func_lower = resource_func;
116 /* Store the handle as 64bit only for EM table entries */
117 if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE &&
118 params->resource_func != BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
119 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
120 resource_info->resource_type = params->resource_type;
121 resource_info->resource_sub_type = params->resource_sub_type;
122 resource_info->reserved = params->reserved;
124 resource_info->resource_em_handle = params->resource_hndl;
129 * Helper function to copy the resource params to resource info
130 * No validation being done in this function.
132 * resource_info [in] Ptr to resource information
133 * params [out] The output params to the caller
138 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
139 struct ulp_flow_db_res_params *params)
141 memset(params, 0, sizeof(struct ulp_flow_db_res_params));
142 params->direction = ((resource_info->nxt_resource_idx &
143 ULP_FLOW_DB_RES_DIR_MASK) >>
144 ULP_FLOW_DB_RES_DIR_BIT);
146 /* use the helper function to get the resource func */
147 params->resource_func = ulp_flow_db_resource_func_get(resource_info);
149 if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
150 params->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
151 params->resource_hndl = resource_info->resource_em_handle;
152 } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
153 params->resource_hndl = resource_info->resource_hndl;
154 params->resource_type = resource_info->resource_type;
155 params->resource_sub_type = resource_info->resource_sub_type;
156 params->reserved = resource_info->reserved;
161 * Helper function to allocate the flow table and initialize
162 * the stack for allocation operations.
164 * flow_db [in] Ptr to flow database structure
165 * tbl_idx [in] The index to table creation.
167 * Returns 0 on success or negative number on failure.
170 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db,
171 enum bnxt_ulp_flow_db_tables tbl_idx)
174 struct bnxt_ulp_flow_tbl *flow_tbl;
177 flow_tbl = &flow_db->flow_tbl[tbl_idx];
179 size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
180 flow_tbl->flow_resources =
181 rte_zmalloc("ulp_fdb_resource_info", size, 0);
183 if (!flow_tbl->flow_resources) {
184 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
187 size = sizeof(uint32_t) * flow_tbl->num_resources;
188 flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
189 if (!flow_tbl->flow_tbl_stack) {
190 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
193 size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
194 flow_tbl->active_flow_tbl = rte_zmalloc("active flow tbl", size, 0);
195 if (!flow_tbl->active_flow_tbl) {
196 BNXT_TF_DBG(ERR, "Failed to alloc memory active tbl\n");
200 /* Initialize the stack table. */
201 for (idx = 0; idx < flow_tbl->num_resources; idx++)
202 flow_tbl->flow_tbl_stack[idx] = idx;
204 /* Ignore the first element in the list. */
205 flow_tbl->head_index = 1;
206 /* Tail points to the last entry in the list. */
207 flow_tbl->tail_index = flow_tbl->num_resources - 1;
212 * Helper function to deallocate the flow table.
214 * flow_db [in] Ptr to flow database structure
215 * tbl_idx [in] The index to table creation.
220 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db,
221 enum bnxt_ulp_flow_db_tables tbl_idx)
223 struct bnxt_ulp_flow_tbl *flow_tbl;
225 flow_tbl = &flow_db->flow_tbl[tbl_idx];
227 /* Free all the allocated tables in the flow table. */
228 if (flow_tbl->active_flow_tbl) {
229 rte_free(flow_tbl->active_flow_tbl);
230 flow_tbl->active_flow_tbl = NULL;
233 if (flow_tbl->flow_tbl_stack) {
234 rte_free(flow_tbl->flow_tbl_stack);
235 flow_tbl->flow_tbl_stack = NULL;
238 if (flow_tbl->flow_resources) {
239 rte_free(flow_tbl->flow_resources);
240 flow_tbl->flow_resources = NULL;
245 * Helper function to add function id to the flow table
247 * flow_db [in] Ptr to flow table
248 * flow_id [in] The flow id of the flow
249 * func_id [in] The func_id to be set, for reset pass zero
254 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
258 /* set the function id in the function table */
259 if (flow_id < flow_db->func_id_tbl_size)
260 flow_db->func_id_tbl[flow_id] = func_id;
261 else /* This should never happen */
262 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
266 * Initialize the flow database. Memory is allocated in this
267 * call and assigned to the flow database.
269 * ulp_ctxt [in] Ptr to ulp context
271 * Returns 0 on success or negative number on failure.
273 int32_t ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
275 struct bnxt_ulp_device_params *dparms;
276 struct bnxt_ulp_flow_tbl *flow_tbl;
277 struct bnxt_ulp_flow_db *flow_db;
280 /* Get the dev specific number of flows that needed to be supported. */
281 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
282 BNXT_TF_DBG(ERR, "Invalid device id\n");
286 dparms = bnxt_ulp_device_params_get(dev_id);
288 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
292 flow_db = rte_zmalloc("bnxt_ulp_flow_db",
293 sizeof(struct bnxt_ulp_flow_db), 0);
296 "Failed to allocate memory for flow table ptr\n");
300 /* Attach the flow database to the ulp context. */
301 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
303 /* Populate the regular flow table limits. */
304 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
305 flow_tbl->num_flows = dparms->flow_db_num_entries + 1;
306 flow_tbl->num_resources = (flow_tbl->num_flows *
307 dparms->num_resources_per_flow);
309 /* Populate the default flow table limits. */
310 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_DEFAULT_FLOW_TABLE];
311 flow_tbl->num_flows = BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1;
312 flow_tbl->num_resources = (flow_tbl->num_flows *
313 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
315 /* Allocate the resource for the regular flow table. */
316 if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE))
318 if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE))
321 /* add 1 since we are not using index 0 for flow id */
322 flow_db->func_id_tbl_size = dparms->flow_db_num_entries + 1;
323 /* Allocate the function Id table */
324 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
325 flow_db->func_id_tbl_size *
326 sizeof(uint16_t), 0);
327 if (!flow_db->func_id_tbl) {
329 "Failed to allocate mem for flow table func id\n");
332 /* All good so return. */
335 ulp_flow_db_deinit(ulp_ctxt);
340 * Deinitialize the flow database. Memory is deallocated in
341 * this call and all flows should have been purged before this
344 * ulp_ctxt [in] Ptr to ulp context
346 * Returns 0 on success.
348 int32_t ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
350 struct bnxt_ulp_flow_db *flow_db;
352 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
354 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
358 /* Detach the flow database from the ulp context. */
359 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
361 /* Free up all the memory. */
362 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
363 ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
364 rte_free(flow_db->func_id_tbl);
371 * Allocate the flow database entry
373 * ulp_ctxt [in] Ptr to ulp_context
374 * tbl_idx [in] Specify it is regular or default flow
375 * fid [out] The index to the flow entry
377 * returns 0 on success and negative on failure.
379 int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
380 enum bnxt_ulp_flow_db_tables tbl_idx,
384 struct bnxt_ulp_flow_db *flow_db;
385 struct bnxt_ulp_flow_tbl *flow_tbl;
387 *fid = 0; /* Initialize fid to invalid value */
388 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
390 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
394 flow_tbl = &flow_db->flow_tbl[tbl_idx];
395 /* check for max flows */
396 if (flow_tbl->num_flows <= flow_tbl->head_index) {
397 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
400 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
401 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
404 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
405 flow_tbl->head_index++;
406 ulp_flow_db_active_flow_set(flow_tbl, *fid, 1);
408 /* The function id update is only valid for regular flow table */
409 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
410 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
412 /* all good, return success */
417 * Allocate the flow database entry.
418 * The params->critical_resource has to be set to 0 to allocate a new resource.
420 * ulp_ctxt [in] Ptr to ulp_context
421 * tbl_idx [in] Specify it is regular or default flow
422 * fid [in] The index to the flow entry
423 * params [in] The contents to be copied into resource
425 * returns 0 on success and negative on failure.
427 int32_t ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
428 enum bnxt_ulp_flow_db_tables tbl_idx,
430 struct ulp_flow_db_res_params *params)
432 struct bnxt_ulp_flow_db *flow_db;
433 struct bnxt_ulp_flow_tbl *flow_tbl;
434 struct ulp_fdb_resource_info *resource, *fid_resource;
437 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
439 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
443 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
444 BNXT_TF_DBG(ERR, "Invalid table index\n");
447 flow_tbl = &flow_db->flow_tbl[tbl_idx];
449 /* check for max flows */
450 if (fid >= flow_tbl->num_flows || !fid) {
451 BNXT_TF_DBG(ERR, "Invalid flow index\n");
455 /* check if the flow is active or not */
456 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
457 BNXT_TF_DBG(ERR, "flow does not exist\n");
461 /* check for max resource */
462 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
463 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
466 fid_resource = &flow_tbl->flow_resources[fid];
468 if (!params->critical_resource) {
469 /* Not the critical_resource so allocate a resource */
470 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
471 resource = &flow_tbl->flow_resources[idx];
472 flow_tbl->tail_index--;
474 /* Update the chain list of resource*/
475 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
476 fid_resource->nxt_resource_idx);
477 /* update the contents */
478 ulp_flow_db_res_params_to_info(resource, params);
479 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
480 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
483 /* critical resource. Just update the fid resource */
484 ulp_flow_db_res_params_to_info(fid_resource, params);
487 /* all good, return success */
492 * Free the flow database entry.
493 * The params->critical_resource has to be set to 1 to free the first resource.
495 * ulp_ctxt [in] Ptr to ulp_context
496 * tbl_idx [in] Specify it is regular or default flow
497 * fid [in] The index to the flow entry
498 * params [in/out] The contents to be copied into params.
499 * Onlythe critical_resource needs to be set by the caller.
501 * Returns 0 on success and negative on failure.
503 int32_t ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
504 enum bnxt_ulp_flow_db_tables tbl_idx,
506 struct ulp_flow_db_res_params *params)
508 struct bnxt_ulp_flow_db *flow_db;
509 struct bnxt_ulp_flow_tbl *flow_tbl;
510 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
511 uint32_t nxt_idx = 0;
513 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
515 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
519 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
520 BNXT_TF_DBG(ERR, "Invalid table index\n");
523 flow_tbl = &flow_db->flow_tbl[tbl_idx];
525 /* check for max flows */
526 if (fid >= flow_tbl->num_flows || !fid) {
527 BNXT_TF_DBG(ERR, "Invalid flow index\n");
531 /* check if the flow is active or not */
532 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
533 BNXT_TF_DBG(ERR, "flow does not exist\n");
537 fid_resource = &flow_tbl->flow_resources[fid];
538 if (!params->critical_resource) {
539 /* Not the critical resource so free the resource */
540 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
541 fid_resource->nxt_resource_idx);
543 /* reached end of resources */
546 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
548 /* connect the fid resource to the next resource */
549 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
550 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
551 nxt_resource->nxt_resource_idx);
553 /* update the contents to be given to caller */
554 ulp_flow_db_res_info_to_params(nxt_resource, params);
556 /* Delete the nxt_resource */
557 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
559 /* add it to the free list */
560 flow_tbl->tail_index++;
561 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
562 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
565 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
568 /* Critical resource. copy the contents and exit */
569 ulp_flow_db_res_info_to_params(fid_resource, params);
570 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
571 fid_resource->nxt_resource_idx);
572 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
573 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
577 /* all good, return success */
582 * Free the flow database entry
584 * ulp_ctxt [in] Ptr to ulp_context
585 * tbl_idx [in] Specify it is regular or default flow
586 * fid [in] The index to the flow entry
588 * returns 0 on success and negative on failure.
590 int32_t ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
591 enum bnxt_ulp_flow_db_tables tbl_idx,
594 struct bnxt_ulp_flow_db *flow_db;
595 struct bnxt_ulp_flow_tbl *flow_tbl;
597 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
599 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
603 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
604 BNXT_TF_DBG(ERR, "Invalid table index\n");
608 flow_tbl = &flow_db->flow_tbl[tbl_idx];
610 /* check for limits of fid */
611 if (fid >= flow_tbl->num_flows || !fid) {
612 BNXT_TF_DBG(ERR, "Invalid flow index\n");
616 /* check if the flow is active or not */
617 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
618 BNXT_TF_DBG(ERR, "flow does not exist\n");
621 flow_tbl->head_index--;
622 if (!flow_tbl->head_index) {
623 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
626 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
627 ulp_flow_db_active_flow_set(flow_tbl, fid, 0);
628 if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
629 ulp_flow_db_func_id_set(flow_db, fid, 0);
631 /* all good, return success */
636 * Get the flow database entry details
638 * ulp_ctxt [in] Ptr to ulp_context
639 * tbl_idx [in] Specify it is regular or default flow
640 * fid [in] The index to the flow entry
641 * nxt_idx [in/out] the index to the next entry
642 * params [out] The contents to be copied into params.
644 * returns 0 on success and negative on failure.
646 int32_t ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
647 enum bnxt_ulp_flow_db_tables tbl_idx,
650 struct ulp_flow_db_res_params *params)
652 struct bnxt_ulp_flow_db *flow_db;
653 struct bnxt_ulp_flow_tbl *flow_tbl;
654 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
656 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
658 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
662 if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
663 BNXT_TF_DBG(ERR, "Invalid table index\n");
667 flow_tbl = &flow_db->flow_tbl[tbl_idx];
669 /* check for limits of fid */
670 if (fid >= flow_tbl->num_flows || !fid) {
671 BNXT_TF_DBG(ERR, "Invalid flow index\n");
675 /* check if the flow is active or not */
676 if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
677 BNXT_TF_DBG(ERR, "flow does not exist\n");
682 fid_resource = &flow_tbl->flow_resources[fid];
683 ulp_flow_db_res_info_to_params(fid_resource, params);
684 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
685 fid_resource->nxt_resource_idx);
687 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
688 ulp_flow_db_res_info_to_params(nxt_resource, params);
690 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
691 nxt_resource->nxt_resource_idx);
694 /* all good, return success */
699 * Get the flow database entry iteratively
701 * flow_tbl [in] Ptr to flow table
702 * fid [in/out] The index to the flow entry
704 * returns 0 on success and negative on failure.
707 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_tbl *flowtbl,
710 uint32_t lfid = *fid;
711 uint32_t idx, s_idx, mod_fid;
715 /* increment the flow id to find the next valid flow id */
717 if (lfid >= flowtbl->num_flows)
719 idx = lfid / ULP_INDEX_BITMAP_SIZE;
720 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
722 while (!(bs = flowtbl->active_flow_tbl[idx])) {
724 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
728 * remove the previous bits in the bitset bs to find the
729 * next non zero bit in the bitset. This needs to be done
730 * only if the idx is same as he one you started.
733 bs &= (-1UL >> mod_fid);
734 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
736 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
739 } while (!ulp_flow_db_active_flow_is_set(flowtbl, lfid));
741 /* all good, return success */
747 * Flush all flows in the flow database.
749 * ulp_ctxt [in] Ptr to ulp context
750 * tbl_idx [in] The index to table
752 * returns 0 on success or negative number on failure
754 int32_t ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
758 struct bnxt_ulp_flow_db *flow_db;
759 struct bnxt_ulp_flow_tbl *flow_tbl;
762 BNXT_TF_DBG(ERR, "Invalid Argument\n");
766 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
768 BNXT_TF_DBG(ERR, "Flow database not found\n");
771 flow_tbl = &flow_db->flow_tbl[idx];
772 while (!ulp_flow_db_next_entry_get(flow_tbl, &fid))
773 ulp_mapper_resources_free(ulp_ctx, fid, idx);
779 * Flush all flows in the flow database that belong to a device function.
781 * ulp_ctxt [in] Ptr to ulp context
782 * tbl_idx [in] The index to table
784 * returns 0 on success or negative number on failure
787 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
790 uint32_t flow_id = 0;
791 struct bnxt_ulp_flow_db *flow_db;
792 struct bnxt_ulp_flow_tbl *flow_tbl;
794 if (!ulp_ctx || !func_id) {
795 BNXT_TF_DBG(ERR, "Invalid Argument\n");
799 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
801 BNXT_TF_DBG(ERR, "Flow database not found\n");
804 flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
805 while (!ulp_flow_db_next_entry_get(flow_tbl, &flow_id)) {
806 if (flow_db->func_id_tbl[flow_id] == func_id)
807 ulp_mapper_resources_free(ulp_ctx, flow_id,
808 BNXT_ULP_REGULAR_FLOW_TABLE);
815 * Flush all flows in the flow database that are associated with the session.
817 * ulp_ctxt [in] Ptr to ulp context
819 * returns 0 on success or negative number on failure
822 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
825 * TBD: Tf core implementation of FW session flush shall change this
828 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
832 * Check that flow id matches the function id or not
834 * ulp_ctxt [in] Ptr to ulp context
835 * flow_db [in] Ptr to flow table
836 * func_id [in] The func_id to be set, for reset pass zero.
838 * returns true on success or false on failure
841 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
845 struct bnxt_ulp_flow_db *flow_db;
847 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
849 BNXT_TF_DBG(ERR, "Flow database not found\n");
853 /* set the function id in the function table */
854 if (flow_id < flow_db->func_id_tbl_size && func_id &&
855 flow_db->func_id_tbl[flow_id] == func_id)
862 * Internal api to traverse the resource list within a flow
863 * and match a resource based on resource func and resource
864 * sub type. This api should be used only for resources that
865 * are unique and do not have multiple instances of resource
866 * func and sub type combination since it will return only
870 ulp_flow_db_resource_hndl_get(struct bnxt_ulp_context *ulp_ctx,
871 enum bnxt_ulp_flow_db_tables tbl_idx,
873 uint32_t resource_func,
874 uint32_t res_subtype,
877 struct bnxt_ulp_flow_db *flow_db;
878 struct bnxt_ulp_flow_tbl *flow_tbl;
879 struct ulp_fdb_resource_info *fid_res;
882 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
884 BNXT_TF_DBG(ERR, "Flow database not found\n");
888 flow_tbl = &flow_db->flow_tbl[tbl_idx];
890 /* check for limits of fid */
891 if (flow_id >= flow_tbl->num_flows || !flow_id) {
892 BNXT_TF_DBG(ERR, "Invalid flow index\n");
896 /* check if the flow is active or not */
897 if (!ulp_flow_db_active_flow_is_set(flow_tbl, flow_id)) {
898 BNXT_TF_DBG(ERR, "flow does not exist\n");
901 /* Iterate the resource to get the resource handle */
904 fid_res = &flow_tbl->flow_resources[res_id];
905 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
906 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
907 if (res_subtype == fid_res->resource_sub_type) {
908 *res_hndl = fid_res->resource_hndl;
912 } else if (resource_func ==
913 BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
915 BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
916 *res_hndl = fid_res->resource_em_handle;
921 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
927 * Api to get the cfa action pointer from a flow.
929 * ulp_ctxt [in] Ptr to ulp context
930 * flow_id [in] flow id
931 * cfa_action [out] The resource handle stored in the flow database
933 * returns 0 on success
936 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
938 uint32_t *cfa_action)
940 uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_CFA_ACTION;
944 rc = ulp_flow_db_resource_hndl_get(ulp_ctx,
945 BNXT_ULP_DEFAULT_FLOW_TABLE,
947 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
950 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
958 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
960 * Dump the entry details
962 * ulp_ctxt [in] Ptr to ulp_context
966 static void ulp_flow_db_res_dump(struct ulp_fdb_resource_info *r,
969 uint8_t res_func = ulp_flow_db_resource_func_get(r);
971 BNXT_TF_DBG(DEBUG, "Resource func = %x, nxt_resource_idx = %x\n",
972 res_func, (ULP_FLOW_DB_RES_NXT_MASK & r->nxt_resource_idx));
973 if (res_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
974 res_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE)
975 BNXT_TF_DBG(DEBUG, "EM Handle = 0x%016" PRIX64 "\n",
976 r->resource_em_handle);
978 BNXT_TF_DBG(DEBUG, "Handle = 0x%08x\n", r->resource_hndl);
981 ULP_FLOW_DB_RES_NXT_SET(*nxt_res,
982 r->nxt_resource_idx);
986 * Dump the flow database entry details
988 * ulp_ctxt [in] Ptr to ulp_context
992 int32_t ulp_flow_db_debug_dump(struct bnxt_ulp_context *ulp_ctxt)
994 struct bnxt_ulp_flow_db *flow_db;
995 struct bnxt_ulp_flow_tbl *flow_tbl;
996 struct ulp_fdb_resource_info *r;
997 uint32_t nxt_res = 0;
998 enum bnxt_ulp_flow_db_tables tbl_idx;
1001 if (!ulp_ctxt || !ulp_ctxt->cfg_data) {
1002 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1005 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1007 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1011 for (tbl_idx = 0; tbl_idx < BNXT_ULP_FLOW_TABLE_MAX; tbl_idx++) {
1012 flow_tbl = &flow_db->flow_tbl[tbl_idx];
1013 BNXT_TF_DBG(DEBUG, "Dump Tbl index = %u, flows = %u:%u\n",
1014 tbl_idx, flow_tbl->num_flows,
1015 flow_tbl->num_resources);
1016 BNXT_TF_DBG(DEBUG, "Head_index = %u, Tail_index = %u\n",
1017 flow_tbl->head_index, flow_tbl->tail_index);
1018 for (fid = 0; fid < flow_tbl->num_flows; fid++) {
1019 if (ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
1020 BNXT_TF_DBG(DEBUG, "fid = %u\n", fid);
1021 /* iterate the resource */
1024 r = &flow_tbl->flow_resources[nxt_res];
1025 ulp_flow_db_res_dump(r, &nxt_res);
1029 BNXT_TF_DBG(DEBUG, "Done.\n");