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 size = ULP_BYTE_ROUND_OFF_8(size);
211 flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size,
212 ULP_BUFFER_ALIGN_64_BYTE);
213 if (!flow_tbl->active_reg_flows) {
214 BNXT_TF_DBG(ERR, "Failed to alloc memory active reg flows\n");
218 flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size,
219 ULP_BUFFER_ALIGN_64_BYTE);
220 if (!flow_tbl->active_dflt_flows) {
221 BNXT_TF_DBG(ERR, "Failed to alloc memory active dflt flows\n");
225 /* Initialize the stack table. */
226 for (idx = 0; idx < flow_tbl->num_resources; idx++)
227 flow_tbl->flow_tbl_stack[idx] = idx;
229 /* Ignore the first element in the list. */
230 flow_tbl->head_index = 1;
231 /* Tail points to the last entry in the list. */
232 flow_tbl->tail_index = flow_tbl->num_resources - 1;
237 * Helper function to deallocate the flow table.
239 * flow_db [in] Ptr to flow database structure
244 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db)
246 struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl;
248 /* Free all the allocated tables in the flow table. */
249 if (flow_tbl->active_reg_flows) {
250 rte_free(flow_tbl->active_reg_flows);
251 flow_tbl->active_reg_flows = NULL;
253 if (flow_tbl->active_dflt_flows) {
254 rte_free(flow_tbl->active_dflt_flows);
255 flow_tbl->active_dflt_flows = NULL;
258 if (flow_tbl->flow_tbl_stack) {
259 rte_free(flow_tbl->flow_tbl_stack);
260 flow_tbl->flow_tbl_stack = NULL;
263 if (flow_tbl->flow_resources) {
264 rte_free(flow_tbl->flow_resources);
265 flow_tbl->flow_resources = NULL;
270 * Helper function to add function id to the flow table
272 * flow_db [in] Ptr to flow table
273 * flow_id [in] The flow id of the flow
274 * func_id [in] The func_id to be set, for reset pass zero
279 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
283 /* set the function id in the function table */
284 if (flow_id < flow_db->func_id_tbl_size)
285 flow_db->func_id_tbl[flow_id] = func_id;
286 else /* This should never happen */
287 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
291 * Initialize the parent-child database. Memory is allocated in this
292 * call and assigned to the database
294 * flow_db [in] Ptr to flow table
295 * num_entries[in] - number of entries to allocate
297 * Returns 0 on success or negative number on failure.
300 ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db,
301 uint32_t num_entries)
303 struct ulp_fdb_parent_child_db *p_db;
306 /* update the sizes for the allocation */
307 p_db = &flow_db->parent_child_db;
308 p_db->child_bitset_size = (flow_db->flow_tbl.num_flows /
309 sizeof(uint64_t)) + 1; /* size in bytes */
310 p_db->child_bitset_size = ULP_BYTE_ROUND_OFF_8(p_db->child_bitset_size);
311 p_db->entries_count = num_entries;
313 /* allocate the memory */
314 p_db->parent_flow_tbl = rte_zmalloc("fdb parent flow tbl",
315 sizeof(struct ulp_fdb_parent_info) *
316 p_db->entries_count, 0);
317 if (!p_db->parent_flow_tbl) {
319 "Failed to allocate memory fdb parent flow tbl\n");
322 size = p_db->child_bitset_size * p_db->entries_count;
325 * allocate the big chunk of memory to be statically carved into
326 * child_fid_bitset pointer.
328 p_db->parent_flow_tbl_mem = rte_zmalloc("fdb parent flow tbl mem",
330 ULP_BUFFER_ALIGN_64_BYTE);
331 if (!p_db->parent_flow_tbl_mem) {
333 "Failed to allocate memory fdb parent flow mem\n");
337 /* set the pointers in parent table to their offsets */
338 for (idx = 0 ; idx < p_db->entries_count; idx++) {
339 p_db->parent_flow_tbl[idx].child_fid_bitset =
340 (uint64_t *)&p_db->parent_flow_tbl_mem[idx *
341 p_db->child_bitset_size];
348 * Deinitialize the parent-child database. Memory is deallocated in
349 * this call and all flows should have been purged before this
352 * flow_db [in] Ptr to flow table
357 ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db)
359 /* free the memory related to parent child database */
360 if (flow_db->parent_child_db.parent_flow_tbl_mem) {
361 rte_free(flow_db->parent_child_db.parent_flow_tbl_mem);
362 flow_db->parent_child_db.parent_flow_tbl_mem = NULL;
364 if (flow_db->parent_child_db.parent_flow_tbl) {
365 rte_free(flow_db->parent_child_db.parent_flow_tbl);
366 flow_db->parent_child_db.parent_flow_tbl = NULL;
371 * Initialize the flow database. Memory is allocated in this
372 * call and assigned to the flow database.
374 * ulp_ctxt [in] Ptr to ulp context
376 * Returns 0 on success or negative number on failure.
379 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
381 struct bnxt_ulp_device_params *dparms;
382 struct bnxt_ulp_flow_tbl *flow_tbl;
383 struct bnxt_ulp_flow_db *flow_db;
384 uint32_t dev_id, num_flows;
385 enum bnxt_ulp_flow_mem_type mtype;
387 /* Get the dev specific number of flows that needed to be supported. */
388 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
389 BNXT_TF_DBG(ERR, "Invalid device id\n");
393 dparms = bnxt_ulp_device_params_get(dev_id);
395 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
399 flow_db = rte_zmalloc("bnxt_ulp_flow_db",
400 sizeof(struct bnxt_ulp_flow_db), 0);
403 "Failed to allocate memory for flow table ptr\n");
407 /* Attach the flow database to the ulp context. */
408 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
410 /* Determine the number of flows based on EM type */
411 bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype);
412 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
413 num_flows = dparms->int_flow_db_num_entries;
415 num_flows = dparms->ext_flow_db_num_entries;
417 /* Populate the regular flow table limits. */
418 flow_tbl = &flow_db->flow_tbl;
419 flow_tbl->num_flows = num_flows + 1;
420 flow_tbl->num_resources = ((num_flows + 1) *
421 dparms->num_resources_per_flow);
423 /* Include the default flow table limits. */
424 flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
425 flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
426 BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
428 /* Allocate the resource for the flow table. */
429 if (ulp_flow_db_alloc_resource(flow_db))
432 /* add 1 since we are not using index 0 for flow id */
433 flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
434 /* Allocate the function Id table */
435 flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
436 flow_db->func_id_tbl_size *
437 sizeof(uint16_t), 0);
438 if (!flow_db->func_id_tbl) {
440 "Failed to allocate mem for flow table func id\n");
443 /* initialize the parent child database */
444 if (ulp_flow_db_parent_tbl_init(flow_db,
445 dparms->fdb_parent_flow_entries)) {
447 "Failed to allocate mem for parent child db\n");
451 /* All good so return. */
452 BNXT_TF_DBG(INFO, "FlowDB initialized with %d flows.\n",
453 flow_tbl->num_flows);
456 ulp_flow_db_deinit(ulp_ctxt);
461 * Deinitialize the flow database. Memory is deallocated in
462 * this call and all flows should have been purged before this
465 * ulp_ctxt [in] Ptr to ulp context
467 * Returns 0 on success.
470 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
472 struct bnxt_ulp_flow_db *flow_db;
474 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
478 /* Detach the flow database from the ulp context. */
479 bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
481 /* Free up all the memory. */
482 ulp_flow_db_parent_tbl_deinit(flow_db);
483 ulp_flow_db_dealloc_resource(flow_db);
484 rte_free(flow_db->func_id_tbl);
491 * Allocate the flow database entry
493 * ulp_ctxt [in] Ptr to ulp_context
494 * flow_type [in] - specify default or regular
495 * func_id [in].function id of the ingress port
496 * fid [out] The index to the flow entry
498 * returns 0 on success and negative on failure.
501 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
502 enum bnxt_ulp_fdb_type flow_type,
506 struct bnxt_ulp_flow_db *flow_db;
507 struct bnxt_ulp_flow_tbl *flow_tbl;
509 *fid = 0; /* Initialize fid to invalid value */
510 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
512 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
516 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
517 BNXT_TF_DBG(ERR, "Invalid flow type\n");
521 flow_tbl = &flow_db->flow_tbl;
522 /* check for max flows */
523 if (flow_tbl->num_flows <= flow_tbl->head_index) {
524 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
527 if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
528 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
531 *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
532 flow_tbl->head_index++;
534 /* Set the flow type */
535 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
537 /* function id update is only valid for regular flow table */
538 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
539 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
546 * Allocate the flow database entry.
547 * The params->critical_resource has to be set to 0 to allocate a new resource.
549 * ulp_ctxt [in] Ptr to ulp_context
550 * flow_type [in] Specify it is regular or default flow
551 * fid [in] The index to the flow entry
552 * params [in] The contents to be copied into resource
554 * returns 0 on success and negative on failure.
557 ulp_flow_db_resource_add(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 *resource, *fid_resource;
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 /* check for max resource */
592 if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
593 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
596 fid_resource = &flow_tbl->flow_resources[fid];
598 if (!params->critical_resource) {
599 /* Not the critical_resource so allocate a resource */
600 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
601 resource = &flow_tbl->flow_resources[idx];
602 flow_tbl->tail_index--;
604 /* Update the chain list of resource*/
605 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
606 fid_resource->nxt_resource_idx);
607 /* update the contents */
608 ulp_flow_db_res_params_to_info(resource, params);
609 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
610 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
613 /* critical resource. Just update the fid resource */
614 ulp_flow_db_res_params_to_info(fid_resource, params);
617 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
618 params->resource_sub_type ==
619 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
620 /* Store the first HW counter ID for this table */
621 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
622 ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
623 params->resource_hndl);
625 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
626 params->resource_hndl);
628 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
629 ulp_fc_mgr_thread_start(ulp_ctxt);
632 /* all good, return success */
637 * Free the flow database entry.
638 * The params->critical_resource has to be set to 1 to free the first resource.
640 * ulp_ctxt [in] Ptr to ulp_context
641 * flow_type [in] Specify it is regular or default flow
642 * fid [in] The index to the flow entry
643 * params [in/out] The contents to be copied into params.
644 * Onlythe critical_resource needs to be set by the caller.
646 * Returns 0 on success and negative on failure.
649 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
650 enum bnxt_ulp_fdb_type flow_type,
652 struct ulp_flow_db_res_params *params)
654 struct bnxt_ulp_flow_db *flow_db;
655 struct bnxt_ulp_flow_tbl *flow_tbl;
656 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
657 uint32_t nxt_idx = 0;
659 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
661 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
665 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
666 BNXT_TF_DBG(ERR, "Invalid flow type\n");
670 flow_tbl = &flow_db->flow_tbl;
671 /* check for max flows */
672 if (fid >= flow_tbl->num_flows || !fid) {
673 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
677 /* check if the flow is active or not */
678 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
679 BNXT_TF_DBG(ERR, "flow does not exist\n");
683 fid_resource = &flow_tbl->flow_resources[fid];
684 if (!params->critical_resource) {
685 /* Not the critical resource so free the resource */
686 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
687 fid_resource->nxt_resource_idx);
689 /* reached end of resources */
692 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
694 /* connect the fid resource to the next resource */
695 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
696 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
697 nxt_resource->nxt_resource_idx);
699 /* update the contents to be given to caller */
700 ulp_flow_db_res_info_to_params(nxt_resource, params);
702 /* Delete the nxt_resource */
703 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
705 /* add it to the free list */
706 flow_tbl->tail_index++;
707 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
708 BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
711 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
714 /* Critical resource. copy the contents and exit */
715 ulp_flow_db_res_info_to_params(fid_resource, params);
716 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
717 fid_resource->nxt_resource_idx);
718 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
719 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
723 /* Now that the HW Flow counter resource is deleted, reset it's
724 * corresponding slot in the SW accumulation table in the Flow Counter
727 if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
728 params->resource_sub_type ==
729 BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_INT_COUNT) {
730 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
731 params->resource_hndl);
734 /* all good, return success */
739 * Free the flow database entry
741 * ulp_ctxt [in] Ptr to ulp_context
742 * flow_type [in] - specify default or regular
743 * fid [in] The index to the flow entry
745 * returns 0 on success and negative on failure.
748 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
749 enum bnxt_ulp_fdb_type flow_type,
752 struct bnxt_ulp_flow_db *flow_db;
753 struct bnxt_ulp_flow_tbl *flow_tbl;
755 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
757 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
761 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
762 BNXT_TF_DBG(ERR, "Invalid flow type\n");
766 flow_tbl = &flow_db->flow_tbl;
768 /* check for limits of fid */
769 if (fid >= flow_tbl->num_flows || !fid) {
770 BNXT_TF_DBG(ERR, "Invalid flow index\n");
774 /* check if the flow is active or not */
775 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
776 BNXT_TF_DBG(ERR, "flow does not exist\n");
779 flow_tbl->head_index--;
780 if (!flow_tbl->head_index) {
781 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
784 flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
786 /* Clear the flows bitmap */
787 ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
789 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
790 ulp_flow_db_func_id_set(flow_db, fid, 0);
792 /* all good, return success */
797 * Get the flow database entry details
799 * ulp_ctxt [in] Ptr to ulp_context
800 * flow_type [in] - specify default or regular
801 * fid [in] The index to the flow entry
802 * nxt_idx [in/out] the index to the next entry
803 * params [out] The contents to be copied into params.
805 * returns 0 on success and negative on failure.
808 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
809 enum bnxt_ulp_fdb_type flow_type,
812 struct ulp_flow_db_res_params *params)
814 struct bnxt_ulp_flow_db *flow_db;
815 struct bnxt_ulp_flow_tbl *flow_tbl;
816 struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
818 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
820 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
824 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
825 BNXT_TF_DBG(ERR, "Invalid flow type\n");
829 flow_tbl = &flow_db->flow_tbl;
831 /* check for limits of fid */
832 if (fid >= flow_tbl->num_flows || !fid) {
833 BNXT_TF_DBG(ERR, "Invalid flow index\n");
837 /* check if the flow is active or not */
838 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
839 BNXT_TF_DBG(ERR, "flow does not exist\n");
844 fid_resource = &flow_tbl->flow_resources[fid];
845 ulp_flow_db_res_info_to_params(fid_resource, params);
846 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
847 fid_resource->nxt_resource_idx);
849 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
850 ulp_flow_db_res_info_to_params(nxt_resource, params);
852 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
853 nxt_resource->nxt_resource_idx);
856 /* all good, return success */
861 * Get the flow database entry iteratively
863 * flow_tbl [in] Ptr to flow table
864 * flow_type [in] - specify default or regular
865 * fid [in/out] The index to the flow entry
867 * returns 0 on success and negative on failure.
870 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
871 enum bnxt_ulp_fdb_type flow_type,
874 uint32_t lfid = *fid;
875 uint32_t idx, s_idx, mod_fid;
877 uint64_t *active_flows;
878 struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
880 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
881 active_flows = flowtbl->active_reg_flows;
883 active_flows = flowtbl->active_dflt_flows;
886 /* increment the flow id to find the next valid flow id */
888 if (lfid >= flowtbl->num_flows)
890 idx = lfid / ULP_INDEX_BITMAP_SIZE;
891 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
893 while (!(bs = active_flows[idx])) {
895 if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
899 * remove the previous bits in the bitset bs to find the
900 * next non zero bit in the bitset. This needs to be done
901 * only if the idx is same as he one you started.
904 bs &= (-1UL >> mod_fid);
905 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
907 BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
910 } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
913 /* all good, return success */
919 * Flush all flows in the flow database.
921 * ulp_ctxt [in] Ptr to ulp context
922 * flow_type [in] - specify default or regular
924 * returns 0 on success or negative number on failure
927 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
928 enum bnxt_ulp_fdb_type flow_type)
931 struct bnxt_ulp_flow_db *flow_db;
934 BNXT_TF_DBG(ERR, "Invalid Argument\n");
938 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
940 BNXT_TF_DBG(ERR, "Flow database not found\n");
943 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
944 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
948 while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
949 ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
951 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
957 * Flush all flows in the flow database that belong to a device function.
959 * ulp_ctxt [in] Ptr to ulp context
960 * func_id [in] - The port function id
962 * returns 0 on success or negative number on failure
965 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
968 uint32_t flow_id = 0;
969 struct bnxt_ulp_flow_db *flow_db;
971 if (!ulp_ctx || !func_id) {
972 BNXT_TF_DBG(ERR, "Invalid Argument\n");
976 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
978 BNXT_TF_DBG(ERR, "Flow database not found\n");
981 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
982 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
986 while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
988 if (flow_db->func_id_tbl[flow_id] == func_id)
989 ulp_mapper_resources_free(ulp_ctx,
990 BNXT_ULP_FDB_TYPE_REGULAR,
993 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
998 * Flush all flows in the flow database that are associated with the session.
1000 * ulp_ctxt [in] Ptr to ulp context
1002 * returns 0 on success or negative number on failure
1005 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
1008 * TBD: Tf core implementation of FW session flush shall change this
1011 return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1015 * Check that flow id matches the function id or not
1017 * ulp_ctxt [in] Ptr to ulp context
1018 * flow_db [in] Ptr to flow table
1019 * func_id [in] The func_id to be set, for reset pass zero.
1021 * returns true on success or false on failure
1024 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
1028 struct bnxt_ulp_flow_db *flow_db;
1030 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1032 BNXT_TF_DBG(ERR, "Flow database not found\n");
1036 /* set the function id in the function table */
1037 if (flow_id < flow_db->func_id_tbl_size && func_id &&
1038 flow_db->func_id_tbl[flow_id] == func_id)
1045 * Internal api to traverse the resource list within a flow
1046 * and match a resource based on resource func and resource
1047 * sub type. This api should be used only for resources that
1048 * are unique and do not have multiple instances of resource
1049 * func and sub type combination since it will return only
1053 ulp_flow_db_resource_hndl_get(struct bnxt_ulp_context *ulp_ctx,
1054 enum bnxt_ulp_fdb_type flow_type,
1056 uint32_t resource_func,
1057 uint32_t res_subtype,
1060 struct bnxt_ulp_flow_db *flow_db;
1061 struct bnxt_ulp_flow_tbl *flow_tbl;
1062 struct ulp_fdb_resource_info *fid_res;
1065 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1067 BNXT_TF_DBG(ERR, "Flow database not found\n");
1071 if (flow_type > BNXT_ULP_FDB_TYPE_DEFAULT) {
1072 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1076 flow_tbl = &flow_db->flow_tbl;
1078 /* check for limits of fid */
1079 if (flow_id >= flow_tbl->num_flows || !flow_id) {
1080 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1084 /* check if the flow is active or not */
1085 if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
1086 BNXT_TF_DBG(ERR, "flow does not exist\n");
1089 /* Iterate the resource to get the resource handle */
1092 fid_res = &flow_tbl->flow_resources[res_id];
1093 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
1094 if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
1095 if (res_subtype == fid_res->resource_sub_type) {
1096 *res_hndl = fid_res->resource_hndl;
1100 } else if (resource_func ==
1101 BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
1103 BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
1104 *res_hndl = fid_res->resource_em_handle;
1109 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1115 * Api to get the cfa action pointer from a flow.
1117 * ulp_ctxt [in] Ptr to ulp context
1118 * flow_id [in] flow id
1119 * cfa_action [out] The resource handle stored in the flow database
1121 * returns 0 on success
1124 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1126 uint16_t *cfa_action)
1128 uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_CFA_ACTION;
1132 rc = ulp_flow_db_resource_hndl_get(ulp_ctx,
1133 BNXT_ULP_FDB_TYPE_DEFAULT,
1135 BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1138 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
1147 * Allocate the entry in the parent-child database
1149 * ulp_ctxt [in] Ptr to ulp_context
1150 * fid [in] The flow id to the flow entry
1152 * returns index on success and negative on failure.
1155 ulp_flow_db_parent_flow_alloc(struct bnxt_ulp_context *ulp_ctxt,
1158 struct bnxt_ulp_flow_db *flow_db;
1159 struct ulp_fdb_parent_child_db *p_pdb;
1160 uint32_t idx, free_idx = 0;
1162 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1164 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1168 /* check for max flows */
1169 if (fid >= flow_db->flow_tbl.num_flows || !fid) {
1170 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1174 p_pdb = &flow_db->parent_child_db;
1175 for (idx = 0; idx <= p_pdb->entries_count; idx++) {
1176 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1177 BNXT_TF_DBG(ERR, "fid is already allocated\n");
1180 if (!p_pdb->parent_flow_tbl[idx].parent_fid && !free_idx)
1185 BNXT_TF_DBG(ERR, "parent child db is full\n");
1190 /* set the Fid in the parent child */
1191 p_pdb->parent_flow_tbl[free_idx].parent_fid = fid;
1196 * Free the entry in the parent-child database
1198 * ulp_ctxt [in] Ptr to ulp_context
1199 * fid [in] The flow id to the flow entry
1201 * returns 0 on success and negative on failure.
1204 ulp_flow_db_parent_flow_free(struct bnxt_ulp_context *ulp_ctxt,
1207 struct bnxt_ulp_flow_db *flow_db;
1208 struct ulp_fdb_parent_child_db *p_pdb;
1211 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1213 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1217 /* check for max flows */
1218 if (fid >= flow_db->flow_tbl.num_flows || !fid) {
1219 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1223 p_pdb = &flow_db->parent_child_db;
1224 for (idx = 0; idx <= p_pdb->entries_count; idx++) {
1225 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1226 /* free the contents */
1227 p_pdb->parent_flow_tbl[idx].parent_fid = 0;
1228 memset(p_pdb->parent_flow_tbl[idx].child_fid_bitset,
1229 0, p_pdb->child_bitset_size);
1233 BNXT_TF_DBG(ERR, "parent entry not found = %x\n", fid);
1238 * Set or reset the child flow in the parent-child database
1240 * ulp_ctxt [in] Ptr to ulp_context
1241 * parent_fid [in] The flow id of the parent flow entry
1242 * child_fid [in] The flow id of the child flow entry
1243 * set_flag [in] Use 1 for setting child, 0 to reset
1245 * returns zero on success and negative on failure.
1248 ulp_flow_db_parent_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1249 uint32_t parent_fid,
1253 struct bnxt_ulp_flow_db *flow_db;
1254 struct ulp_fdb_parent_child_db *p_pdb;
1255 uint32_t idx, a_idx;
1258 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1260 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1264 /* check for fid validity */
1265 if (parent_fid >= flow_db->flow_tbl.num_flows || !parent_fid) {
1266 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_fid);
1270 /* check for fid validity */
1271 if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) {
1272 BNXT_TF_DBG(ERR, "Invalid child flow index %x\n", child_fid);
1276 p_pdb = &flow_db->parent_child_db;
1277 a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
1278 for (idx = 0; idx <= p_pdb->entries_count; idx++) {
1279 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1280 t = p_pdb->parent_flow_tbl[idx].child_fid_bitset;
1282 ULP_INDEX_BITMAP_SET(t[a_idx], child_fid);
1284 ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid);
1288 BNXT_TF_DBG(ERR, "Unable to set the parent-child flow %x:%x\n",
1289 parent_fid, child_fid);
1294 * Get the parent index from the parent-child database
1296 * ulp_ctxt [in] Ptr to ulp_context
1297 * parent_fid [in] The flow id of the parent flow entry
1298 * parent_idx [out] The parent index of parent flow entry
1300 * returns zero on success and negative on failure.
1303 ulp_flow_db_parent_flow_idx_get(struct bnxt_ulp_context *ulp_ctxt,
1304 uint32_t parent_fid,
1305 uint32_t *parent_idx)
1307 struct bnxt_ulp_flow_db *flow_db;
1308 struct ulp_fdb_parent_child_db *p_pdb;
1311 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1313 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1317 /* check for fid validity */
1318 if (parent_fid >= flow_db->flow_tbl.num_flows || !parent_fid) {
1319 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_fid);
1323 p_pdb = &flow_db->parent_child_db;
1324 for (idx = 0; idx <= p_pdb->entries_count; idx++) {
1325 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1330 BNXT_TF_DBG(ERR, "Unable to get the parent flow %x\n", parent_fid);
1335 * Get the next child flow in the parent-child database
1337 * ulp_ctxt [in] Ptr to ulp_context
1338 * parent_fid [in] The flow id of the parent flow entry
1339 * child_fid [in/out] The flow id of the child flow entry
1341 * returns zero on success and negative on failure.
1342 * Pass child_fid as zero for first entry.
1345 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1346 uint32_t parent_idx,
1347 uint32_t *child_fid)
1349 struct ulp_fdb_parent_child_db *p_pdb;
1350 uint32_t idx, s_idx, mod_fid;
1351 uint32_t next_fid = *child_fid;
1352 uint64_t *child_bitset;
1355 /* check for fid validity */
1356 p_pdb = &flow_db->parent_child_db;
1357 if (parent_idx >= p_pdb->entries_count ||
1358 !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1359 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1363 child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset;
1365 /* increment the flow id to find the next valid flow id */
1367 if (next_fid >= flow_db->flow_tbl.num_flows)
1369 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1370 mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE;
1372 while (!(bs = child_bitset[idx])) {
1374 if ((idx * ULP_INDEX_BITMAP_SIZE) >=
1375 flow_db->flow_tbl.num_flows)
1379 * remove the previous bits in the bitset bs to find the
1380 * next non zero bit in the bitset. This needs to be done
1381 * only if the idx is same as he one you started.
1384 bs &= (-1UL >> mod_fid);
1385 next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
1386 if (*child_fid >= next_fid) {
1387 BNXT_TF_DBG(ERR, "Parent Child Database is corrupt\n");
1390 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1391 } while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid));
1392 *child_fid = next_fid;