net/virtio: remove blank lines in log
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_flow_db.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_malloc.h>
7 #include "bnxt.h"
8 #include "bnxt_tf_common.h"
9 #include "ulp_utils.h"
10 #include "ulp_template_struct.h"
11 #include "ulp_mapper.h"
12 #include "ulp_flow_db.h"
13 #include "ulp_fc_mgr.h"
14 #include "ulp_tun.h"
15
16 #define ULP_FLOW_DB_RES_DIR_BIT         31
17 #define ULP_FLOW_DB_RES_DIR_MASK        0x80000000
18 #define ULP_FLOW_DB_RES_FUNC_BITS       28
19 #define ULP_FLOW_DB_RES_FUNC_MASK       0x70000000
20 #define ULP_FLOW_DB_RES_NXT_MASK        0x0FFFFFFF
21 #define ULP_FLOW_DB_RES_FUNC_UPPER      5
22 #define ULP_FLOW_DB_RES_FUNC_NEED_LOWER 0x80
23 #define ULP_FLOW_DB_RES_FUNC_LOWER_MASK 0x1F
24
25 /* Macro to copy the nxt_resource_idx */
26 #define ULP_FLOW_DB_RES_NXT_SET(dst, src)       {(dst) |= ((src) &\
27                                          ULP_FLOW_DB_RES_NXT_MASK); }
28 #define ULP_FLOW_DB_RES_NXT_RESET(dst)  ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
29
30 /*
31  * Helper function to set the bit in the active flows
32  * No validation is done in this function.
33  *
34  * flow_db [in] Ptr to flow database
35  * flow_type [in] - specify default or regular
36  * idx [in] The index to bit to be set or reset.
37  * flag [in] 1 to set and 0 to reset.
38  *
39  * returns none
40  */
41 static void
42 ulp_flow_db_active_flows_bit_set(struct bnxt_ulp_flow_db *flow_db,
43                                  enum bnxt_ulp_fdb_type flow_type,
44                                  uint32_t idx,
45                                  uint32_t flag)
46 {
47         struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
48         uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
49
50         if (flag) {
51                 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==
52                     BNXT_ULP_FDB_TYPE_RID)
53                         ULP_INDEX_BITMAP_SET(f_tbl->active_reg_flows[a_idx],
54                                              idx);
55                 if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==
56                     BNXT_ULP_FDB_TYPE_RID)
57                         ULP_INDEX_BITMAP_SET(f_tbl->active_dflt_flows[a_idx],
58                                              idx);
59         } else {
60                 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR || flow_type ==
61                     BNXT_ULP_FDB_TYPE_RID)
62                         ULP_INDEX_BITMAP_RESET(f_tbl->active_reg_flows[a_idx],
63                                                idx);
64                 if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT || flow_type ==
65                     BNXT_ULP_FDB_TYPE_RID)
66                         ULP_INDEX_BITMAP_RESET(f_tbl->active_dflt_flows[a_idx],
67                                                idx);
68         }
69 }
70
71 /*
72  * Helper function to check if given fid is active flow.
73  * No validation being done in this function.
74  *
75  * flow_db [in] Ptr to flow database
76  * flow_type [in] - specify default or regular
77  * idx [in] The index to bit to be set or reset.
78  *
79  * returns 1 on set or 0 if not set.
80  */
81 static int32_t
82 ulp_flow_db_active_flows_bit_is_set(struct bnxt_ulp_flow_db *flow_db,
83                                     enum bnxt_ulp_fdb_type flow_type,
84                                     uint32_t idx)
85 {
86         struct bnxt_ulp_flow_tbl *f_tbl = &flow_db->flow_tbl;
87         uint32_t a_idx = idx / ULP_INDEX_BITMAP_SIZE;
88         uint32_t reg, dflt;
89
90         reg = ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx], idx);
91         dflt = ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx], idx);
92
93         switch (flow_type) {
94         case BNXT_ULP_FDB_TYPE_REGULAR:
95                 return (reg && !dflt);
96         case BNXT_ULP_FDB_TYPE_DEFAULT:
97                 return (!reg && dflt);
98         case BNXT_ULP_FDB_TYPE_RID:
99                 return (reg && dflt);
100         default:
101                 return 0;
102         }
103 }
104
105 static inline enum tf_dir
106 ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info)
107 {
108         return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >>
109                 ULP_FLOW_DB_RES_DIR_BIT);
110 }
111
112 static uint8_t
113 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
114 {
115         uint8_t func;
116
117         func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
118                  ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
119         /* The resource func is split into upper and lower */
120         if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
121                 return (func | res_info->resource_func_lower);
122         return func;
123 }
124
125 /*
126  * Helper function to copy the resource params to resource info
127  *  No validation being done in this function.
128  *
129  * resource_info [out] Ptr to resource information
130  * params [in] The input params from the caller
131  * returns none
132  */
133 static void
134 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
135                                struct ulp_flow_db_res_params *params)
136 {
137         uint32_t resource_func;
138
139         resource_info->nxt_resource_idx |= ((params->direction <<
140                                       ULP_FLOW_DB_RES_DIR_BIT) &
141                                      ULP_FLOW_DB_RES_DIR_MASK);
142         resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
143         resource_info->nxt_resource_idx |= ((resource_func <<
144                                              ULP_FLOW_DB_RES_FUNC_BITS) &
145                                             ULP_FLOW_DB_RES_FUNC_MASK);
146
147         if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
148                 /* Break the resource func into two parts */
149                 resource_func = (params->resource_func &
150                                  ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
151                 resource_info->resource_func_lower = resource_func;
152         }
153
154         /* Store the handle as 64bit only for EM table entries */
155         if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
156                 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
157                 resource_info->resource_type = params->resource_type;
158                 resource_info->resource_sub_type = params->resource_sub_type;
159                 resource_info->fdb_flags = params->fdb_flags;
160         } else {
161                 resource_info->resource_em_handle = params->resource_hndl;
162         }
163 }
164
165 /*
166  * Helper function to copy the resource params to resource info
167  *  No validation being done in this function.
168  *
169  * resource_info [in] Ptr to resource information
170  * params [out] The output params to the caller
171  *
172  * returns none
173  */
174 static void
175 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
176                                struct ulp_flow_db_res_params *params)
177 {
178         memset(params, 0, sizeof(struct ulp_flow_db_res_params));
179
180         /* use the helper function to get the resource func */
181         params->direction = ulp_flow_db_resource_dir_get(resource_info);
182         params->resource_func = ulp_flow_db_resource_func_get(resource_info);
183
184         if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
185                 params->resource_hndl = resource_info->resource_em_handle;
186         } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
187                 params->resource_hndl = resource_info->resource_hndl;
188                 params->resource_type = resource_info->resource_type;
189                 params->resource_sub_type = resource_info->resource_sub_type;
190                 params->fdb_flags = resource_info->fdb_flags;
191         }
192 }
193
194 /*
195  * Helper function to allocate the flow table and initialize
196  * the stack for allocation operations.
197  *
198  * flow_db [in] Ptr to flow database structure
199  *
200  * Returns 0 on success or negative number on failure.
201  */
202 static int32_t
203 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db)
204 {
205         uint32_t                        idx = 0;
206         struct bnxt_ulp_flow_tbl        *flow_tbl;
207         uint32_t                        size;
208
209         flow_tbl = &flow_db->flow_tbl;
210
211         size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
212         flow_tbl->flow_resources =
213                         rte_zmalloc("ulp_fdb_resource_info", size, 0);
214
215         if (!flow_tbl->flow_resources) {
216                 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
217                 return -ENOMEM;
218         }
219         size = sizeof(uint32_t) * flow_tbl->num_resources;
220         flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
221         if (!flow_tbl->flow_tbl_stack) {
222                 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
223                 return -ENOMEM;
224         }
225         size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
226         size = ULP_BYTE_ROUND_OFF_8(size);
227         flow_tbl->active_reg_flows = rte_zmalloc("active reg flows", size,
228                                                  ULP_BUFFER_ALIGN_64_BYTE);
229         if (!flow_tbl->active_reg_flows) {
230                 BNXT_TF_DBG(ERR, "Failed to alloc memory active reg flows\n");
231                 return -ENOMEM;
232         }
233
234         flow_tbl->active_dflt_flows = rte_zmalloc("active dflt flows", size,
235                                                   ULP_BUFFER_ALIGN_64_BYTE);
236         if (!flow_tbl->active_dflt_flows) {
237                 BNXT_TF_DBG(ERR, "Failed to alloc memory active dflt flows\n");
238                 return -ENOMEM;
239         }
240
241         /* Initialize the stack table. */
242         for (idx = 0; idx < flow_tbl->num_resources; idx++)
243                 flow_tbl->flow_tbl_stack[idx] = idx;
244
245         /* Ignore the first element in the list. */
246         flow_tbl->head_index = 1;
247         /* Tail points to the last entry in the list. */
248         flow_tbl->tail_index = flow_tbl->num_resources - 1;
249         return 0;
250 }
251
252 /*
253  * Helper function to deallocate the flow table.
254  *
255  * flow_db [in] Ptr to flow database structure
256  *
257  * Returns none.
258  */
259 static void
260 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db)
261 {
262         struct bnxt_ulp_flow_tbl *flow_tbl = &flow_db->flow_tbl;
263
264         /* Free all the allocated tables in the flow table. */
265         if (flow_tbl->active_reg_flows) {
266                 rte_free(flow_tbl->active_reg_flows);
267                 flow_tbl->active_reg_flows = NULL;
268         }
269         if (flow_tbl->active_dflt_flows) {
270                 rte_free(flow_tbl->active_dflt_flows);
271                 flow_tbl->active_dflt_flows = NULL;
272         }
273
274         if (flow_tbl->flow_tbl_stack) {
275                 rte_free(flow_tbl->flow_tbl_stack);
276                 flow_tbl->flow_tbl_stack = NULL;
277         }
278
279         if (flow_tbl->flow_resources) {
280                 rte_free(flow_tbl->flow_resources);
281                 flow_tbl->flow_resources = NULL;
282         }
283 }
284
285 /*
286  * Helper function to add function id to the flow table
287  *
288  * flow_db [in] Ptr to flow table
289  * flow_id [in] The flow id of the flow
290  * func_id [in] The func_id to be set, for reset pass zero
291  *
292  * returns none
293  */
294 static void
295 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
296                         uint32_t flow_id,
297                         uint32_t func_id)
298 {
299         /* set the function id in the function table */
300         if (flow_id < flow_db->func_id_tbl_size)
301                 flow_db->func_id_tbl[flow_id] = func_id;
302         else /* This should never happen */
303                 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
304 }
305
306 /*
307  * Initialize the parent-child database. Memory is allocated in this
308  * call and assigned to the database
309  *
310  * flow_db [in] Ptr to flow table
311  * num_entries[in] - number of entries to allocate
312  *
313  * Returns 0 on success or negative number on failure.
314  */
315 static int32_t
316 ulp_flow_db_parent_tbl_init(struct bnxt_ulp_flow_db *flow_db,
317                             uint32_t num_entries)
318 {
319         struct ulp_fdb_parent_child_db *p_db;
320         uint32_t size, idx;
321
322         if (!num_entries)
323                 return 0;
324
325         /* update the sizes for the allocation */
326         p_db = &flow_db->parent_child_db;
327         p_db->child_bitset_size = (flow_db->flow_tbl.num_flows /
328                                    sizeof(uint64_t)) + 1; /* size in bytes */
329         p_db->child_bitset_size = ULP_BYTE_ROUND_OFF_8(p_db->child_bitset_size);
330         p_db->entries_count = num_entries;
331
332         /* allocate the memory */
333         p_db->parent_flow_tbl = rte_zmalloc("fdb parent flow tbl",
334                                             sizeof(struct ulp_fdb_parent_info) *
335                                             p_db->entries_count, 0);
336         if (!p_db->parent_flow_tbl) {
337                 BNXT_TF_DBG(ERR,
338                             "Failed to allocate memory fdb parent flow tbl\n");
339                 return -ENOMEM;
340         }
341         size = p_db->child_bitset_size * p_db->entries_count;
342
343         /*
344          * allocate the big chunk of memory to be statically carved into
345          * child_fid_bitset pointer.
346          */
347         p_db->parent_flow_tbl_mem = rte_zmalloc("fdb parent flow tbl mem",
348                                                 size,
349                                                 ULP_BUFFER_ALIGN_64_BYTE);
350         if (!p_db->parent_flow_tbl_mem) {
351                 BNXT_TF_DBG(ERR,
352                             "Failed to allocate memory fdb parent flow mem\n");
353                 return -ENOMEM;
354         }
355
356         /* set the pointers in parent table to their offsets */
357         for (idx = 0 ; idx < p_db->entries_count; idx++) {
358                 p_db->parent_flow_tbl[idx].child_fid_bitset =
359                         (uint64_t *)&p_db->parent_flow_tbl_mem[idx *
360                         p_db->child_bitset_size];
361         }
362         /* success */
363         return 0;
364 }
365
366 /*
367  * Deinitialize the parent-child database. Memory is deallocated in
368  * this call and all flows should have been purged before this
369  * call.
370  *
371  * flow_db [in] Ptr to flow table
372  *
373  * Returns none
374  */
375 static void
376 ulp_flow_db_parent_tbl_deinit(struct bnxt_ulp_flow_db *flow_db)
377 {
378         /* free the memory related to parent child database */
379         if (flow_db->parent_child_db.parent_flow_tbl_mem) {
380                 rte_free(flow_db->parent_child_db.parent_flow_tbl_mem);
381                 flow_db->parent_child_db.parent_flow_tbl_mem = NULL;
382         }
383         if (flow_db->parent_child_db.parent_flow_tbl) {
384                 rte_free(flow_db->parent_child_db.parent_flow_tbl);
385                 flow_db->parent_child_db.parent_flow_tbl = NULL;
386         }
387 }
388
389 /*
390  * Initialize the flow database. Memory is allocated in this
391  * call and assigned to the flow database.
392  *
393  * ulp_ctxt [in] Ptr to ulp context
394  *
395  * Returns 0 on success or negative number on failure.
396  */
397 int32_t
398 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
399 {
400         struct bnxt_ulp_device_params *dparms;
401         struct bnxt_ulp_flow_tbl *flow_tbl;
402         struct bnxt_ulp_flow_db *flow_db;
403         uint32_t dev_id, num_flows;
404         enum bnxt_ulp_flow_mem_type mtype;
405
406         /* Get the dev specific number of flows that needed to be supported. */
407         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
408                 BNXT_TF_DBG(ERR, "Invalid device id\n");
409                 return -EINVAL;
410         }
411
412         dparms = bnxt_ulp_device_params_get(dev_id);
413         if (!dparms) {
414                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
415                 return -ENODEV;
416         }
417
418         flow_db = rte_zmalloc("bnxt_ulp_flow_db",
419                               sizeof(struct bnxt_ulp_flow_db), 0);
420         if (!flow_db) {
421                 BNXT_TF_DBG(ERR,
422                             "Failed to allocate memory for flow table ptr\n");
423                 return -ENOMEM;
424         }
425
426         /* Attach the flow database to the ulp context. */
427         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
428
429         /* Determine the number of flows based on EM type */
430         if (bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype))
431                 goto error_free;
432
433         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
434                 num_flows = dparms->int_flow_db_num_entries;
435         else
436                 num_flows = dparms->ext_flow_db_num_entries;
437
438         /* Populate the regular flow table limits. */
439         flow_tbl = &flow_db->flow_tbl;
440         flow_tbl->num_flows = num_flows + 1;
441         flow_tbl->num_resources = ((num_flows + 1) *
442                                    dparms->num_resources_per_flow);
443
444         /* Include the default flow table limits. */
445         flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
446         flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
447                                     BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
448
449         /* Allocate the resource for the flow table. */
450         if (ulp_flow_db_alloc_resource(flow_db))
451                 goto error_free;
452
453         /* add 1 since we are not using index 0 for flow id */
454         flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
455         /* Allocate the function Id table */
456         flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
457                                            flow_db->func_id_tbl_size *
458                                            sizeof(uint16_t), 0);
459         if (!flow_db->func_id_tbl) {
460                 BNXT_TF_DBG(ERR,
461                             "Failed to allocate mem for flow table func id\n");
462                 goto error_free;
463         }
464         /* initialize the parent child database */
465         if (ulp_flow_db_parent_tbl_init(flow_db,
466                                         dparms->fdb_parent_flow_entries)) {
467                 BNXT_TF_DBG(ERR,
468                             "Failed to allocate mem for parent child db\n");
469                 goto error_free;
470         }
471
472         /* All good so return. */
473         BNXT_TF_DBG(INFO, "FlowDB initialized with %d flows.\n",
474                     flow_tbl->num_flows);
475         return 0;
476 error_free:
477         ulp_flow_db_deinit(ulp_ctxt);
478         return -ENOMEM;
479 }
480
481 /*
482  * Deinitialize the flow database. Memory is deallocated in
483  * this call and all flows should have been purged before this
484  * call.
485  *
486  * ulp_ctxt [in] Ptr to ulp context
487  *
488  * Returns 0 on success.
489  */
490 int32_t
491 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
492 {
493         struct bnxt_ulp_flow_db *flow_db;
494
495         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
496         if (!flow_db)
497                 return -EINVAL;
498
499         /* Detach the flow database from the ulp context. */
500         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
501
502         /* Free up all the memory. */
503         ulp_flow_db_parent_tbl_deinit(flow_db);
504         ulp_flow_db_dealloc_resource(flow_db);
505         rte_free(flow_db->func_id_tbl);
506         rte_free(flow_db);
507
508         return 0;
509 }
510
511 /*
512  * Allocate the flow database entry
513  *
514  * ulp_ctxt [in] Ptr to ulp_context
515  * flow_type [in] - specify default or regular
516  * func_id [in].function id of the ingress port
517  * fid [out] The index to the flow entry
518  *
519  * returns 0 on success and negative on failure.
520  */
521 int32_t
522 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
523                       enum bnxt_ulp_fdb_type flow_type,
524                       uint16_t func_id,
525                       uint32_t *fid)
526 {
527         struct bnxt_ulp_flow_db *flow_db;
528         struct bnxt_ulp_flow_tbl *flow_tbl;
529
530         *fid = 0; /* Initialize fid to invalid value */
531         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
532         if (!flow_db) {
533                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
534                 return -EINVAL;
535         }
536
537         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
538                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
539                 return -EINVAL;
540         }
541
542         flow_tbl = &flow_db->flow_tbl;
543         /* check for max flows */
544         if (flow_tbl->num_flows <= flow_tbl->head_index) {
545                 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
546                 return -ENOMEM;
547         }
548         if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
549                 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
550                 return -ENOMEM;
551         }
552         *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
553         flow_tbl->head_index++;
554
555         /* Set the flow type */
556         ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
557
558         /* function id update is only valid for regular flow table */
559         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
560                 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
561
562 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
563         BNXT_TF_DBG(ERR, "flow_id = %u:%u allocated\n", flow_type, *fid);
564 #endif
565         /* return success */
566         return 0;
567 }
568
569 /*
570  * Allocate the flow database entry.
571  * The params->critical_resource has to be set to 0 to allocate a new resource.
572  *
573  * ulp_ctxt [in] Ptr to ulp_context
574  * flow_type [in] Specify it is regular or default flow
575  * fid [in] The index to the flow entry
576  * params [in] The contents to be copied into resource
577  *
578  * returns 0 on success and negative on failure.
579  */
580 int32_t
581 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
582                          enum bnxt_ulp_fdb_type flow_type,
583                          uint32_t fid,
584                          struct ulp_flow_db_res_params *params)
585 {
586         struct bnxt_ulp_flow_db *flow_db;
587         struct bnxt_ulp_flow_tbl *flow_tbl;
588         struct ulp_fdb_resource_info *resource, *fid_resource;
589         struct bnxt_ulp_fc_info *ulp_fc_info;
590         uint32_t idx;
591
592         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
593         if (!flow_db) {
594                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
595                 return -EINVAL;
596         }
597
598         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
599                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
600                 return -EINVAL;
601         }
602
603         flow_tbl = &flow_db->flow_tbl;
604         /* check for max flows */
605         if (fid >= flow_tbl->num_flows || !fid) {
606                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
607                 return -EINVAL;
608         }
609
610         /* check if the flow is active or not */
611         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
612                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
613                 return -EINVAL;
614         }
615
616         /* check for max resource */
617         if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
618                 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
619                 return -ENOMEM;
620         }
621         fid_resource = &flow_tbl->flow_resources[fid];
622
623         if (params->critical_resource && fid_resource->resource_em_handle) {
624                 BNXT_TF_DBG(DEBUG, "Ignore multiple critical resources\n");
625                 /* Ignore the multiple critical resources */
626                 params->critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
627         }
628
629         if (!params->critical_resource) {
630                 /* Not the critical_resource so allocate a resource */
631                 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
632                 resource = &flow_tbl->flow_resources[idx];
633                 flow_tbl->tail_index--;
634
635                 /* Update the chain list of resource*/
636                 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
637                                         fid_resource->nxt_resource_idx);
638                 /* update the contents */
639                 ulp_flow_db_res_params_to_info(resource, params);
640                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
641                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
642                                         idx);
643         } else {
644                 /* critical resource. Just update the fid resource */
645                 ulp_flow_db_res_params_to_info(fid_resource, params);
646         }
647
648         ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ulp_ctxt);
649         if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
650             params->resource_sub_type ==
651             BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT &&
652             ulp_fc_info && ulp_fc_info->num_counters) {
653                 /* Store the first HW counter ID for this table */
654                 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
655                         ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
656                                                  params->resource_hndl);
657
658                 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
659                                     params->resource_hndl);
660
661                 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
662                         ulp_fc_mgr_thread_start(ulp_ctxt);
663         }
664
665         /* all good, return success */
666         return 0;
667 }
668
669 /*
670  * Free the flow database entry.
671  * The params->critical_resource has to be set to 1 to free the first resource.
672  *
673  * ulp_ctxt [in] Ptr to ulp_context
674  * flow_type [in] Specify it is regular or default flow
675  * fid [in] The index to the flow entry
676  * params [in/out] The contents to be copied into params.
677  * Only the critical_resource needs to be set by the caller.
678  *
679  * Returns 0 on success and negative on failure.
680  */
681 int32_t
682 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
683                          enum bnxt_ulp_fdb_type flow_type,
684                          uint32_t fid,
685                          struct ulp_flow_db_res_params *params)
686 {
687         struct bnxt_ulp_flow_db *flow_db;
688         struct bnxt_ulp_flow_tbl *flow_tbl;
689         struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
690         uint32_t nxt_idx = 0;
691
692         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
693         if (!flow_db) {
694                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
695                 return -EINVAL;
696         }
697
698         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
699                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
700                 return -EINVAL;
701         }
702
703         flow_tbl = &flow_db->flow_tbl;
704         /* check for max flows */
705         if (fid >= flow_tbl->num_flows || !fid) {
706                 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
707                 return -EINVAL;
708         }
709
710         /* check if the flow is active or not */
711         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
712                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
713                 return -EINVAL;
714         }
715
716         fid_resource = &flow_tbl->flow_resources[fid];
717         if (!params->critical_resource) {
718                 /* Not the critical resource so free the resource */
719                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
720                                         fid_resource->nxt_resource_idx);
721                 if (!nxt_idx) {
722                         /* reached end of resources */
723                         return -ENOENT;
724                 }
725                 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
726
727                 /* connect the fid resource to the next resource */
728                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
729                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
730                                         nxt_resource->nxt_resource_idx);
731
732                 /* update the contents to be given to caller */
733                 ulp_flow_db_res_info_to_params(nxt_resource, params);
734
735                 /* Delete the nxt_resource */
736                 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
737
738                 /* add it to the free list */
739                 flow_tbl->tail_index++;
740                 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
741                         BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
742                         return -ENOENT;
743                 }
744                 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
745
746         } else {
747                 /* Critical resource. copy the contents and exit */
748                 ulp_flow_db_res_info_to_params(fid_resource, params);
749                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
750                                         fid_resource->nxt_resource_idx);
751                 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
752                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
753                                         nxt_idx);
754         }
755
756         /* Now that the HW Flow counter resource is deleted, reset it's
757          * corresponding slot in the SW accumulation table in the Flow Counter
758          * manager
759          */
760         if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
761             params->resource_sub_type ==
762             BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) {
763                 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
764                                       params->resource_hndl);
765         }
766
767         /* all good, return success */
768         return 0;
769 }
770
771 /*
772  * Free the flow database entry
773  *
774  * ulp_ctxt [in] Ptr to ulp_context
775  * flow_type [in] - specify default or regular
776  * fid [in] The index to the flow entry
777  *
778  * returns 0 on success and negative on failure.
779  */
780 int32_t
781 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
782                      enum bnxt_ulp_fdb_type flow_type,
783                      uint32_t fid)
784 {
785         struct bnxt_ulp_flow_tbl *flow_tbl;
786         struct bnxt_ulp_flow_db *flow_db;
787
788         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
789         if (!flow_db) {
790                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
791                 return -EINVAL;
792         }
793
794         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
795                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
796                 return -EINVAL;
797         }
798
799         flow_tbl = &flow_db->flow_tbl;
800
801         /* check for limits of fid */
802         if (fid >= flow_tbl->num_flows || !fid) {
803                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
804                 return -EINVAL;
805         }
806
807         /* check if the flow is active or not */
808         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
809                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
810                 return -EINVAL;
811         }
812         flow_tbl->head_index--;
813         if (!flow_tbl->head_index) {
814                 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
815                 return -ENOENT;
816         }
817
818         flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
819
820         /* Clear the flows bitmap */
821         ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
822
823         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
824                 ulp_flow_db_func_id_set(flow_db, fid, 0);
825
826 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
827         BNXT_TF_DBG(ERR, "flow_id = %u:%u freed\n", flow_type, fid);
828 #endif
829         /* all good, return success */
830         return 0;
831 }
832
833 /*
834  *Get the flow database entry details
835  *
836  * ulp_ctxt [in] Ptr to ulp_context
837  * flow_type [in] - specify default or regular
838  * fid [in] The index to the flow entry
839  * nxt_idx [in/out] the index to the next entry
840  * params [out] The contents to be copied into params.
841  *
842  * returns 0 on success and negative on failure.
843  */
844 int32_t
845 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
846                          enum bnxt_ulp_fdb_type flow_type,
847                          uint32_t fid,
848                          uint32_t *nxt_idx,
849                          struct ulp_flow_db_res_params *params)
850 {
851         struct bnxt_ulp_flow_db *flow_db;
852         struct bnxt_ulp_flow_tbl *flow_tbl;
853         struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
854
855         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
856         if (!flow_db) {
857                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
858                 return -EINVAL;
859         }
860
861         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
862                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
863                 return -EINVAL;
864         }
865
866         flow_tbl = &flow_db->flow_tbl;
867
868         /* check for limits of fid */
869         if (fid >= flow_tbl->num_flows || !fid) {
870                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
871                 return -EINVAL;
872         }
873
874         /* check if the flow is active or not */
875         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
876                 BNXT_TF_DBG(ERR, "flow does not exist\n");
877                 return -EINVAL;
878         }
879
880         if (!*nxt_idx) {
881                 fid_resource = &flow_tbl->flow_resources[fid];
882                 ulp_flow_db_res_info_to_params(fid_resource, params);
883                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
884                                         fid_resource->nxt_resource_idx);
885         } else {
886                 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
887                 ulp_flow_db_res_info_to_params(nxt_resource, params);
888                 *nxt_idx = 0;
889                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
890                                         nxt_resource->nxt_resource_idx);
891         }
892
893         /* all good, return success */
894         return 0;
895 }
896
897 /*
898  * Get the flow database entry iteratively
899  *
900  * flow_tbl [in] Ptr to flow table
901  * flow_type [in] - specify default or regular
902  * fid [in/out] The index to the flow entry
903  *
904  * returns 0 on success and negative on failure.
905  */
906 static int32_t
907 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
908                            enum bnxt_ulp_fdb_type flow_type,
909                            uint32_t *fid)
910 {
911         uint32_t lfid = *fid;
912         uint32_t idx, s_idx, mod_fid;
913         uint64_t bs;
914         uint64_t *active_flows;
915         struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
916
917         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) {
918                 active_flows = flowtbl->active_reg_flows;
919         } else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) {
920                 active_flows = flowtbl->active_dflt_flows;
921         } else {
922                 BNXT_TF_DBG(ERR, "Invalid flow type %x\n", flow_type);
923                         return -EINVAL;
924         }
925
926         do {
927                 /* increment the flow id to find the next valid flow id */
928                 lfid++;
929                 if (lfid >= flowtbl->num_flows)
930                         return -ENOENT;
931                 idx = lfid / ULP_INDEX_BITMAP_SIZE;
932                 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
933                 s_idx = idx;
934                 while (!(bs = active_flows[idx])) {
935                         idx++;
936                         if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
937                                 return -ENOENT;
938                 }
939                 /*
940                  * remove the previous bits in the bitset bs to find the
941                  * next non zero bit in the bitset. This needs to be done
942                  * only if the idx is same as he one you started.
943                  */
944                 if (s_idx == idx)
945                         bs &= (-1UL >> mod_fid);
946                 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
947                 if (*fid >= lfid) {
948                         BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
949                         return -ENOENT;
950                 }
951         } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
952                                                       lfid));
953
954         /* all good, return success */
955         *fid = lfid;
956         return 0;
957 }
958
959 /*
960  * Flush all flows in the flow database.
961  *
962  * ulp_ctxt [in] Ptr to ulp context
963  * flow_type [in] - specify default or regular
964  *
965  * returns 0 on success or negative number on failure
966  */
967 int32_t
968 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
969                         enum bnxt_ulp_fdb_type flow_type)
970 {
971         uint32_t fid = 0;
972         struct bnxt_ulp_flow_db *flow_db;
973
974         if (!ulp_ctx) {
975                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
976                 return -EINVAL;
977         }
978
979         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
980         if (!flow_db) {
981                 BNXT_TF_DBG(ERR, "Flow database not found\n");
982                 return -EINVAL;
983         }
984         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
985                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
986                 return -EINVAL;
987         }
988
989         while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
990                 ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
991
992         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
993
994         return 0;
995 }
996
997 /*
998  * Flush all flows in the flow database that belong to a device function.
999  *
1000  * ulp_ctxt [in] Ptr to ulp context
1001  * func_id [in] - The port function id
1002  *
1003  * returns 0 on success or negative number on failure
1004  */
1005 int32_t
1006 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
1007                                 uint16_t func_id)
1008 {
1009         uint32_t flow_id = 0;
1010         struct bnxt_ulp_flow_db *flow_db;
1011
1012         if (!ulp_ctx || !func_id) {
1013                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
1014                 return -EINVAL;
1015         }
1016
1017         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1018         if (!flow_db) {
1019                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1020                 return -EINVAL;
1021         }
1022         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
1023                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
1024                 return -EINVAL;
1025         }
1026
1027         while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
1028                                            &flow_id)) {
1029                 if (flow_db->func_id_tbl[flow_id] == func_id)
1030                         ulp_mapper_resources_free(ulp_ctx,
1031                                                   BNXT_ULP_FDB_TYPE_REGULAR,
1032                                                   flow_id);
1033         }
1034         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
1035         return 0;
1036 }
1037
1038 /*
1039  * Flush all flows in the flow database that are associated with the session.
1040  *
1041  * ulp_ctxt [in] Ptr to ulp context
1042  *
1043  * returns 0 on success or negative number on failure
1044  */
1045 int32_t
1046 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
1047 {
1048         /*
1049          * TBD: Tf core implementation of FW session flush shall change this
1050          * implementation.
1051          */
1052         return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1053 }
1054
1055 /*
1056  * Check that flow id matches the function id or not
1057  *
1058  * ulp_ctxt [in] Ptr to ulp context
1059  * flow_db [in] Ptr to flow table
1060  * func_id [in] The func_id to be set, for reset pass zero.
1061  *
1062  * returns true on success or false on failure
1063  */
1064 bool
1065 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
1066                                uint32_t flow_id,
1067                                uint32_t func_id)
1068 {
1069         struct bnxt_ulp_flow_db *flow_db;
1070
1071         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1072         if (!flow_db) {
1073                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1074                 return false;
1075         }
1076
1077         /* set the function id in the function table */
1078         if (flow_id < flow_db->func_id_tbl_size && func_id &&
1079             flow_db->func_id_tbl[flow_id] == func_id)
1080                 return true;
1081
1082         return false;
1083 }
1084
1085 /*
1086  * Internal api to traverse the resource list within a flow
1087  * and match a resource based on resource func and resource
1088  * sub type. This api should be used only for resources that
1089  * are unique and do not have multiple instances of resource
1090  * func and sub type combination since it will return only
1091  * the first match.
1092  */
1093 static int32_t
1094 ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,
1095                                 enum bnxt_ulp_fdb_type flow_type,
1096                                 uint32_t flow_id,
1097                                 uint32_t resource_func,
1098                                 uint32_t res_subtype,
1099                                 struct ulp_flow_db_res_params *params)
1100 {
1101         struct bnxt_ulp_flow_db *flow_db;
1102         struct bnxt_ulp_flow_tbl *flow_tbl;
1103         struct ulp_fdb_resource_info *fid_res;
1104         uint32_t res_id;
1105
1106         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1107         if (!flow_db) {
1108                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1109                 return -EINVAL;
1110         }
1111
1112         if (!params) {
1113                 BNXT_TF_DBG(ERR, "invalid argument\n");
1114                 return -EINVAL;
1115         }
1116
1117         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1118                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1119                 return -EINVAL;
1120         }
1121
1122         flow_tbl = &flow_db->flow_tbl;
1123
1124         /* check for limits of fid */
1125         if (flow_id >= flow_tbl->num_flows || !flow_id) {
1126                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1127                 return -EINVAL;
1128         }
1129
1130         /* check if the flow is active or not */
1131         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
1132                 BNXT_TF_DBG(ERR, "flow does not exist\n");
1133                 return -EINVAL;
1134         }
1135         /* Iterate the resource to get the resource handle */
1136         res_id =  flow_id;
1137         memset(params, 0, sizeof(struct ulp_flow_db_res_params));
1138         while (res_id) {
1139                 fid_res = &flow_tbl->flow_resources[res_id];
1140                 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
1141                         if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
1142                                 if (res_subtype == fid_res->resource_sub_type) {
1143                                         ulp_flow_db_res_info_to_params(fid_res,
1144                                                                        params);
1145                                         return 0;
1146                                 }
1147
1148                         } else if (resource_func ==
1149                                    BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
1150                                 ulp_flow_db_res_info_to_params(fid_res,
1151                                                                params);
1152                                 return 0;
1153                         }
1154                 }
1155                 res_id = 0;
1156                 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1157         }
1158         return -ENOENT;
1159 }
1160
1161 /*
1162  * Api to get the cfa action pointer from a flow.
1163  *
1164  * ulp_ctxt [in] Ptr to ulp context
1165  * flow_id [in] flow id
1166  * cfa_action [out] The resource handle stored in the flow database
1167  *
1168  * returns 0 on success
1169  */
1170 int32_t
1171 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1172                                    uint32_t flow_id,
1173                                    uint16_t *cfa_action)
1174 {
1175         uint8_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_VFR_CFA_ACTION;
1176         struct ulp_flow_db_res_params params;
1177         int32_t rc;
1178
1179         rc = ulp_flow_db_resource_params_get(ulp_ctx,
1180                                              BNXT_ULP_FDB_TYPE_DEFAULT,
1181                                              flow_id,
1182                                              BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1183                                              sub_typ, &params);
1184         if (rc) {
1185                 BNXT_TF_DBG(INFO, "CFA Action ptr not found for flow id %u\n",
1186                             flow_id);
1187                 return -ENOENT;
1188         }
1189         *cfa_action = params.resource_hndl;
1190         return 0;
1191 }
1192
1193 /* internal validation function for parent flow tbl */
1194 static struct ulp_fdb_parent_info *
1195 ulp_flow_db_pc_db_entry_get(struct bnxt_ulp_context *ulp_ctxt,
1196                             uint32_t pc_idx)
1197 {
1198         struct bnxt_ulp_flow_db *flow_db;
1199
1200         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1201         if (!flow_db) {
1202                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1203                 return NULL;
1204         }
1205
1206         /* check for max flows */
1207         if (pc_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) {
1208                 BNXT_TF_DBG(ERR, "Invalid tunnel index\n");
1209                 return NULL;
1210         }
1211
1212         /* No support for parent child db then just exit */
1213         if (!flow_db->parent_child_db.entries_count) {
1214                 BNXT_TF_DBG(ERR, "parent child db not supported\n");
1215                 return NULL;
1216         }
1217         if (!flow_db->parent_child_db.parent_flow_tbl[pc_idx].valid) {
1218                 BNXT_TF_DBG(ERR, "Not a valid tunnel index\n");
1219                 return NULL;
1220         }
1221
1222         return &flow_db->parent_child_db.parent_flow_tbl[pc_idx];
1223 }
1224
1225 /* internal validation function for parent flow tbl */
1226 static struct bnxt_ulp_flow_db *
1227 ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt,
1228                                   uint32_t tun_idx)
1229 {
1230         struct bnxt_ulp_flow_db *flow_db;
1231
1232         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1233         if (!flow_db) {
1234                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1235                 return NULL;
1236         }
1237
1238         /* check for max flows */
1239         if (tun_idx >= BNXT_ULP_MAX_TUN_CACHE_ENTRIES) {
1240                 BNXT_TF_DBG(ERR, "Invalid tunnel index\n");
1241                 return NULL;
1242         }
1243
1244         /* No support for parent child db then just exit */
1245         if (!flow_db->parent_child_db.entries_count) {
1246                 BNXT_TF_DBG(ERR, "parent child db not supported\n");
1247                 return NULL;
1248         }
1249
1250         return flow_db;
1251 }
1252
1253 /*
1254  * Allocate the entry in the parent-child database
1255  *
1256  * ulp_ctxt [in] Ptr to ulp_context
1257  * tun_idx [in] The tunnel index of the flow entry
1258  *
1259  * returns index on success and negative on failure.
1260  */
1261 static int32_t
1262 ulp_flow_db_pc_db_idx_alloc(struct bnxt_ulp_context *ulp_ctxt,
1263                             uint32_t tun_idx)
1264 {
1265         struct bnxt_ulp_flow_db *flow_db;
1266         struct ulp_fdb_parent_child_db *p_pdb;
1267         uint32_t idx, free_idx = 0;
1268
1269         /* validate the arguments */
1270         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, tun_idx);
1271         if (!flow_db) {
1272                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1273                 return -EINVAL;
1274         }
1275
1276         p_pdb = &flow_db->parent_child_db;
1277         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1278                 if (p_pdb->parent_flow_tbl[idx].valid &&
1279                     p_pdb->parent_flow_tbl[idx].tun_idx == tun_idx) {
1280                         return idx;
1281                 }
1282                 if (!p_pdb->parent_flow_tbl[idx].valid && !free_idx)
1283                         free_idx = idx + 1;
1284         }
1285         /* no free slots */
1286         if (!free_idx) {
1287                 BNXT_TF_DBG(ERR, "parent child db is full\n");
1288                 return -ENOMEM;
1289         }
1290
1291         free_idx -= 1;
1292         /* set the Fid in the parent child */
1293         p_pdb->parent_flow_tbl[free_idx].tun_idx = tun_idx;
1294         p_pdb->parent_flow_tbl[free_idx].valid = 1;
1295         return free_idx;
1296 }
1297
1298 /*
1299  * Free the entry in the parent-child database
1300  *
1301  * pc_entry [in] Ptr to parent child db entry
1302  *
1303  * returns none.
1304  */
1305 static void
1306 ulp_flow_db_pc_db_entry_free(struct bnxt_ulp_context *ulp_ctxt,
1307                              struct ulp_fdb_parent_info *pc_entry)
1308 {
1309         struct bnxt_tun_cache_entry *tun_tbl;
1310         struct bnxt_ulp_flow_db *flow_db;
1311         uint64_t *tmp_bitset;
1312
1313         /* free the tunnel entry */
1314         tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);
1315         if (tun_tbl)
1316                 ulp_tunnel_offload_entry_clear(tun_tbl, pc_entry->tun_idx);
1317
1318         /* free the child bitset*/
1319         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1320         if (flow_db)
1321                 memset(pc_entry->child_fid_bitset, 0,
1322                        flow_db->parent_child_db.child_bitset_size);
1323
1324         /* free the contents */
1325         tmp_bitset = pc_entry->child_fid_bitset;
1326         memset(pc_entry, 0, sizeof(struct ulp_fdb_parent_info));
1327         pc_entry->child_fid_bitset = tmp_bitset;
1328 }
1329
1330 /*
1331  * Set or reset the parent flow in the parent-child database
1332  *
1333  * ulp_ctxt [in] Ptr to ulp_context
1334  * pc_idx [in] The index to parent child db
1335  * parent_fid [in] The flow id of the parent flow entry
1336  * set_flag [in] Use 1 for setting child, 0 to reset
1337  *
1338  * returns zero on success and negative on failure.
1339  */
1340 int32_t
1341 ulp_flow_db_pc_db_parent_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1342                                   uint32_t pc_idx,
1343                                   uint32_t parent_fid,
1344                                   uint32_t set_flag)
1345 {
1346         struct ulp_fdb_parent_info *pc_entry;
1347         struct bnxt_ulp_flow_db *flow_db;
1348
1349         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1350         if (!flow_db) {
1351                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1352                 return -EINVAL;
1353         }
1354
1355         /* check for fid validity */
1356         if (parent_fid >= flow_db->flow_tbl.num_flows || !parent_fid) {
1357                 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_fid);
1358                 return -EINVAL;
1359         }
1360
1361         /* validate the arguments and parent child entry */
1362         pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1363         if (!pc_entry) {
1364                 BNXT_TF_DBG(ERR, "failed to get the parent child entry\n");
1365                 return -EINVAL;
1366         }
1367
1368         if (set_flag) {
1369                 pc_entry->parent_fid = parent_fid;
1370         } else {
1371                 if (pc_entry->parent_fid != parent_fid)
1372                         BNXT_TF_DBG(ERR, "Panic: invalid parent id\n");
1373                 pc_entry->parent_fid = 0;
1374
1375                 /* Free the parent child db entry if no user present */
1376                 if (!pc_entry->f2_cnt)
1377                         ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry);
1378         }
1379         return 0;
1380 }
1381
1382 /*
1383  * Set or reset the child flow in the parent-child database
1384  *
1385  * ulp_ctxt [in] Ptr to ulp_context
1386  * pc_idx [in] The index to parent child db
1387  * child_fid [in] The flow id of the child flow entry
1388  * set_flag [in] Use 1 for setting child, 0 to reset
1389  *
1390  * returns zero on success and negative on failure.
1391  */
1392 int32_t
1393 ulp_flow_db_pc_db_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1394                                  uint32_t pc_idx,
1395                                  uint32_t child_fid,
1396                                  uint32_t set_flag)
1397 {
1398         struct ulp_fdb_parent_info *pc_entry;
1399         struct bnxt_ulp_flow_db *flow_db;
1400         uint32_t a_idx;
1401         uint64_t *t;
1402
1403         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1404         if (!flow_db) {
1405                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1406                 return -EINVAL;
1407         }
1408
1409         /* check for fid validity */
1410         if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) {
1411                 BNXT_TF_DBG(ERR, "Invalid child flow index %x\n", child_fid);
1412                 return -EINVAL;
1413         }
1414
1415         /* validate the arguments and parent child entry */
1416         pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1417         if (!pc_entry) {
1418                 BNXT_TF_DBG(ERR, "failed to get the parent child entry\n");
1419                 return -EINVAL;
1420         }
1421
1422         a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
1423         t = pc_entry->child_fid_bitset;
1424         if (set_flag) {
1425                 ULP_INDEX_BITMAP_SET(t[a_idx], child_fid);
1426                 pc_entry->f2_cnt++;
1427         } else {
1428                 ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid);
1429                 if (pc_entry->f2_cnt)
1430                         pc_entry->f2_cnt--;
1431                 if (!pc_entry->f2_cnt && !pc_entry->parent_fid)
1432                         ulp_flow_db_pc_db_entry_free(ulp_ctxt, pc_entry);
1433         }
1434         return 0;
1435 }
1436
1437 /*
1438  * Get the next child flow in the parent-child database
1439  *
1440  * ulp_ctxt [in] Ptr to ulp_context
1441  * parent_fid [in] The flow id of the parent flow entry
1442  * child_fid [in/out] The flow id of the child flow entry
1443  *
1444  * returns zero on success and negative on failure.
1445  * Pass child_fid as zero for first entry.
1446  */
1447 int32_t
1448 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1449                                              uint32_t parent_idx,
1450                                              uint32_t *child_fid)
1451 {
1452         struct ulp_fdb_parent_child_db *p_pdb;
1453         uint32_t idx, s_idx, mod_fid;
1454         uint32_t next_fid = *child_fid;
1455         uint64_t *child_bitset;
1456         uint64_t bs;
1457
1458         /* check for fid validity */
1459         p_pdb = &flow_db->parent_child_db;
1460         if (parent_idx >= p_pdb->entries_count ||
1461             !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1462                 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1463                 return -EINVAL;
1464         }
1465
1466         child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset;
1467         do {
1468                 /* increment the flow id to find the next valid flow id */
1469                 next_fid++;
1470                 if (next_fid >= flow_db->flow_tbl.num_flows)
1471                         return -ENOENT;
1472                 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1473                 mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE;
1474                 s_idx = idx;
1475                 while (!(bs = child_bitset[idx])) {
1476                         idx++;
1477                         if ((idx * ULP_INDEX_BITMAP_SIZE) >=
1478                             flow_db->flow_tbl.num_flows)
1479                                 return -ENOENT;
1480                 }
1481                 /*
1482                  * remove the previous bits in the bitset bs to find the
1483                  * next non zero bit in the bitset. This needs to be done
1484                  * only if the idx is same as he one you started.
1485                  */
1486                 if (s_idx == idx)
1487                         bs &= (-1UL >> mod_fid);
1488                 next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
1489                 if (*child_fid >= next_fid) {
1490                         BNXT_TF_DBG(ERR, "Parent Child Database is corrupt\n");
1491                         return -ENOENT;
1492                 }
1493                 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1494         } while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid));
1495         *child_fid = next_fid;
1496         return 0;
1497 }
1498
1499 /*
1500  * Set the counter accumulation in the parent flow
1501  *
1502  * ulp_ctxt [in] Ptr to ulp_context
1503  * pc_idx [in] The parent child index of the parent flow entry
1504  *
1505  * returns index on success and negative on failure.
1506  */
1507 static int32_t
1508 ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt,
1509                                         uint32_t pc_idx)
1510 {
1511         struct bnxt_ulp_flow_db *flow_db;
1512         struct ulp_fdb_parent_child_db *p_pdb;
1513
1514         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1515         if (!flow_db) {
1516                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1517                 return -EINVAL;
1518         }
1519
1520         /* check for parent idx validity */
1521         p_pdb = &flow_db->parent_child_db;
1522         if (pc_idx >= p_pdb->entries_count ||
1523             !p_pdb->parent_flow_tbl[pc_idx].parent_fid) {
1524                 BNXT_TF_DBG(ERR, "Invalid parent child index %x\n", pc_idx);
1525                 return -EINVAL;
1526         }
1527
1528         p_pdb->parent_flow_tbl[pc_idx].counter_acc = 1;
1529         return 0;
1530 }
1531
1532 /*
1533  * Orphan the child flow entry
1534  * This is called only for child flows that have
1535  * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
1536  *
1537  * ulp_ctxt [in] Ptr to ulp_context
1538  * flow_type [in] Specify it is regular or default flow
1539  * fid [in] The index to the flow entry
1540  *
1541  * Returns 0 on success and negative on failure.
1542  */
1543 int32_t
1544 ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
1545                              enum bnxt_ulp_fdb_type flow_type,
1546                              uint32_t fid)
1547 {
1548         struct bnxt_ulp_flow_db *flow_db;
1549         struct bnxt_ulp_flow_tbl *flow_tbl;
1550         struct ulp_fdb_resource_info *fid_res;
1551         uint32_t res_id = 0;
1552
1553         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1554         if (!flow_db) {
1555                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1556                 return -EINVAL;
1557         }
1558
1559         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1560                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1561                 return -EINVAL;
1562         }
1563
1564         flow_tbl = &flow_db->flow_tbl;
1565         /* check for max flows */
1566         if (fid >= flow_tbl->num_flows || !fid) {
1567                 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
1568                 return -EINVAL;
1569         }
1570
1571         /* check if the flow is active or not */
1572         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
1573                 BNXT_TF_DBG(ERR, "flow does not exist\n");
1574                 return -EINVAL;
1575         }
1576
1577         /* Iterate the resource to get the resource handle */
1578         res_id =  fid;
1579         while (res_id) {
1580                 fid_res = &flow_tbl->flow_resources[res_id];
1581                 if (ulp_flow_db_resource_func_get(fid_res) ==
1582                     BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) {
1583                         /* invalidate the resource details */
1584                         fid_res->resource_hndl = 0;
1585                         return 0;
1586                 }
1587                 res_id = 0;
1588                 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1589         }
1590         /* failed */
1591         return -1;
1592 }
1593
1594 /*
1595  * Create parent flow in the parent flow tbl
1596  *
1597  * parms [in] Ptr to mapper params
1598  *
1599  * Returns 0 on success and negative on failure.
1600  */
1601 int32_t
1602 ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)
1603 {
1604         struct ulp_flow_db_res_params fid_parms;
1605         uint32_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1606         struct ulp_flow_db_res_params res_params;
1607         int32_t pc_idx;
1608
1609         /* create or get the parent child database */
1610         pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx);
1611         if (pc_idx < 0) {
1612                 BNXT_TF_DBG(ERR, "Error in getting parent child db %x\n",
1613                             parms->tun_idx);
1614                 return -EINVAL;
1615         }
1616
1617         /* Update the parent fid */
1618         if (ulp_flow_db_pc_db_parent_flow_set(parms->ulp_ctx, pc_idx,
1619                                               parms->fid, 1)) {
1620                 BNXT_TF_DBG(ERR, "Error in setting parent fid %x\n",
1621                             parms->tun_idx);
1622                 return -EINVAL;
1623         }
1624
1625         /* Add the parent details in the resource list of the flow */
1626         memset(&fid_parms, 0, sizeof(fid_parms));
1627         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW;
1628         fid_parms.resource_hndl = pc_idx;
1629         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1630         if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
1631                                      parms->fid, &fid_parms)) {
1632                 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1633                             parms->fid);
1634                 return -1;
1635         }
1636
1637         /* check of the flow has internal counter accumulation enabled */
1638         if (!ulp_flow_db_resource_params_get(parms->ulp_ctx,
1639                                              BNXT_ULP_FDB_TYPE_REGULAR,
1640                                              parms->fid,
1641                                              BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1642                                              sub_typ,
1643                                              &res_params)) {
1644                 /* Enable the counter accumulation in parent entry */
1645                 if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx,
1646                                                             pc_idx)) {
1647                         BNXT_TF_DBG(ERR, "Error in setting counter acc %x\n",
1648                                     parms->fid);
1649                         return -1;
1650                 }
1651         }
1652
1653         return 0;
1654 }
1655
1656 /*
1657  * Create child flow in the parent flow tbl
1658  *
1659  * parms [in] Ptr to mapper params
1660  *
1661  * Returns 0 on success and negative on failure.
1662  */
1663 int32_t
1664 ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms)
1665 {
1666         struct ulp_flow_db_res_params fid_parms;
1667         uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1668         enum bnxt_ulp_resource_func res_fun;
1669         struct ulp_flow_db_res_params res_p;
1670         int32_t rc, pc_idx;
1671
1672         /* create or get the parent child database */
1673         pc_idx = ulp_flow_db_pc_db_idx_alloc(parms->ulp_ctx, parms->tun_idx);
1674         if (pc_idx < 0) {
1675                 BNXT_TF_DBG(ERR, "Error in getting parent child db %x\n",
1676                             parms->tun_idx);
1677                 return -1;
1678         }
1679
1680         /* create the parent flow entry in parent flow table */
1681         rc = ulp_flow_db_pc_db_child_flow_set(parms->ulp_ctx, pc_idx,
1682                                               parms->fid, 1);
1683         if (rc) {
1684                 BNXT_TF_DBG(ERR, "Error in setting child fid %x\n", parms->fid);
1685                 return rc;
1686         }
1687
1688         /* Add the parent details in the resource list of the flow */
1689         memset(&fid_parms, 0, sizeof(fid_parms));
1690         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW;
1691         fid_parms.resource_hndl = pc_idx;
1692         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1693         rc  = ulp_flow_db_resource_add(parms->ulp_ctx,
1694                                        BNXT_ULP_FDB_TYPE_REGULAR,
1695                                        parms->fid, &fid_parms);
1696         if (rc) {
1697                 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1698                             parms->fid);
1699                 return rc;
1700         }
1701
1702         /* check if internal count action included for this flow.*/
1703         res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE;
1704         rc = ulp_flow_db_resource_params_get(parms->ulp_ctx,
1705                                              BNXT_ULP_FDB_TYPE_REGULAR,
1706                                              parms->fid,
1707                                              res_fun,
1708                                              sub_type,
1709                                              &res_p);
1710         if (!rc) {
1711                 /* update the counter manager to include parent fid */
1712                 if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx,
1713                                                     res_p.direction,
1714                                                     res_p.resource_hndl,
1715                                                     pc_idx)) {
1716                         BNXT_TF_DBG(ERR, "Error in setting child %x\n",
1717                                     parms->fid);
1718                         return -1;
1719                 }
1720         }
1721
1722         /* return success */
1723         return 0;
1724 }
1725
1726 /*
1727  * Update the parent counters
1728  *
1729  * ulp_ctxt [in] Ptr to ulp_context
1730  * pc_idx [in] The parent flow entry idx
1731  * packet_count [in] - packet count
1732  * byte_count [in] - byte count
1733  *
1734  * returns 0 on success
1735  */
1736 int32_t
1737 ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt,
1738                                      uint32_t pc_idx,
1739                                      uint64_t packet_count,
1740                                      uint64_t byte_count)
1741 {
1742         struct ulp_fdb_parent_info *pc_entry;
1743
1744         /* validate the arguments and get parent child entry */
1745         pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1746         if (!pc_entry) {
1747                 BNXT_TF_DBG(ERR, "failed to get the parent child entry\n");
1748                 return -EINVAL;
1749         }
1750
1751         if (pc_entry->counter_acc) {
1752                 pc_entry->pkt_count += packet_count;
1753                 pc_entry->byte_count += byte_count;
1754         }
1755         return 0;
1756 }
1757
1758 /*
1759  * Get the parent accumulation counters
1760  *
1761  * ulp_ctxt [in] Ptr to ulp_context
1762  * pc_idx [in] The parent flow entry idx
1763  * packet_count [out] - packet count
1764  * byte_count [out] - byte count
1765  *
1766  * returns 0 on success
1767  */
1768 int32_t
1769 ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,
1770                                   uint32_t pc_idx, uint64_t *packet_count,
1771                                   uint64_t *byte_count, uint8_t count_reset)
1772 {
1773         struct ulp_fdb_parent_info *pc_entry;
1774
1775         /* validate the arguments and get parent child entry */
1776         pc_entry = ulp_flow_db_pc_db_entry_get(ulp_ctxt, pc_idx);
1777         if (!pc_entry) {
1778                 BNXT_TF_DBG(ERR, "failed to get the parent child entry\n");
1779                 return -EINVAL;
1780         }
1781
1782         if (pc_entry->counter_acc) {
1783                 *packet_count = pc_entry->pkt_count;
1784                 *byte_count = pc_entry->byte_count;
1785                 if (count_reset) {
1786                         pc_entry->pkt_count = 0;
1787                         pc_entry->byte_count = 0;
1788                 }
1789         }
1790         return 0;
1791 }
1792
1793 /*
1794  * reset the parent accumulation counters
1795  *
1796  * ulp_ctxt [in] Ptr to ulp_context
1797  *
1798  * returns none
1799  */
1800 void
1801 ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt)
1802 {
1803         struct bnxt_ulp_flow_db *flow_db;
1804         struct ulp_fdb_parent_child_db *p_pdb;
1805         uint32_t idx;
1806
1807         /* validate the arguments */
1808         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1809         if (!flow_db) {
1810                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1811                 return;
1812         }
1813
1814         p_pdb = &flow_db->parent_child_db;
1815         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1816                 if (p_pdb->parent_flow_tbl[idx].valid &&
1817                     p_pdb->parent_flow_tbl[idx].counter_acc) {
1818                         p_pdb->parent_flow_tbl[idx].pkt_count = 0;
1819                         p_pdb->parent_flow_tbl[idx].byte_count = 0;
1820                 }
1821         }
1822 }
1823
1824 /*
1825  * Set the shared bit for the flow db entry
1826  *
1827  * res [in] Ptr to fdb entry
1828  * shared [in] shared flag
1829  *
1830  * returns none
1831  */
1832 void ulp_flow_db_shared_session_set(struct ulp_flow_db_res_params *res,
1833                                     enum bnxt_ulp_shared_session shared)
1834 {
1835         if (res && (shared & BNXT_ULP_SHARED_SESSION_YES))
1836                 res->fdb_flags |= ULP_FDB_FLAG_SHARED_SESSION;
1837 }
1838
1839 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1840 /*
1841  * Dump the entry details
1842  *
1843  * ulp_ctxt [in] Ptr to ulp_context
1844  *
1845  * returns none
1846  */
1847 static void ulp_flow_db_res_dump(struct ulp_fdb_resource_info *r,
1848                                  uint32_t *nxt_res)
1849 {
1850         uint8_t res_func = ulp_flow_db_resource_func_get(r);
1851
1852         BNXT_TF_DBG(DEBUG, "Resource func = %x, nxt_resource_idx = %x\n",
1853                     res_func, (ULP_FLOW_DB_RES_NXT_MASK & r->nxt_resource_idx));
1854         if (res_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE)
1855                 BNXT_TF_DBG(DEBUG, "EM Handle = 0x%016" PRIX64 "\n",
1856                             r->resource_em_handle);
1857         else
1858                 BNXT_TF_DBG(DEBUG, "Handle = 0x%08x\n", r->resource_hndl);
1859
1860         *nxt_res = 0;
1861         ULP_FLOW_DB_RES_NXT_SET(*nxt_res,
1862                                 r->nxt_resource_idx);
1863 }
1864
1865 /*
1866  * Dump the flow entry details
1867  *
1868  * flow_db [in] Ptr to flow db
1869  * fid [in] flow id
1870  *
1871  * returns none
1872  */
1873 void
1874 ulp_flow_db_debug_fid_dump(struct bnxt_ulp_flow_db *flow_db, uint32_t fid)
1875 {
1876         struct ulp_fdb_resource_info *r;
1877         struct bnxt_ulp_flow_tbl *flow_tbl;
1878         uint32_t nxt_res = 0;
1879         uint32_t def_flag = 0, reg_flag = 0;
1880
1881         flow_tbl = &flow_db->flow_tbl;
1882         if (ulp_flow_db_active_flows_bit_is_set(flow_db,
1883                                                 BNXT_ULP_FDB_TYPE_REGULAR, fid))
1884                 reg_flag = 1;
1885         if (ulp_flow_db_active_flows_bit_is_set(flow_db,
1886                                                 BNXT_ULP_FDB_TYPE_DEFAULT, fid))
1887                 def_flag = 1;
1888
1889         if (reg_flag && def_flag)
1890                 BNXT_TF_DBG(DEBUG, "RID = %u\n", fid);
1891         else if (reg_flag)
1892                 BNXT_TF_DBG(DEBUG, "Regular fid = %u and func id = %u\n",
1893                             fid, flow_db->func_id_tbl[fid]);
1894         else if (def_flag)
1895                 BNXT_TF_DBG(DEBUG, "Default fid = %u\n", fid);
1896         else
1897                 return;
1898         /* iterate the resource */
1899         nxt_res = fid;
1900         do {
1901                 r = &flow_tbl->flow_resources[nxt_res];
1902                 ulp_flow_db_res_dump(r, &nxt_res);
1903         } while (nxt_res);
1904 }
1905
1906 /*
1907  * Dump the flow database entry details
1908  *
1909  * ulp_ctxt [in] Ptr to ulp_context
1910  * flow_id [in] if zero then all fids are dumped.
1911  *
1912  * returns none
1913  */
1914 int32_t ulp_flow_db_debug_dump(struct bnxt_ulp_context *ulp_ctxt,
1915                                uint32_t flow_id)
1916 {
1917         struct bnxt_ulp_flow_db *flow_db;
1918         struct bnxt_ulp_flow_tbl *flow_tbl;
1919         uint32_t fid;
1920
1921         if (!ulp_ctxt || !ulp_ctxt->cfg_data) {
1922                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1923                 return -EINVAL;
1924         }
1925         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1926         if (!flow_db) {
1927                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1928                 return -EINVAL;
1929         }
1930
1931         flow_tbl = &flow_db->flow_tbl;
1932         if (flow_id) {
1933                 ulp_flow_db_debug_fid_dump(flow_db, flow_id);
1934                 return 0;
1935         }
1936
1937         BNXT_TF_DBG(DEBUG, "Dump flows = %u:%u\n",
1938                     flow_tbl->num_flows,
1939                     flow_tbl->num_resources);
1940         BNXT_TF_DBG(DEBUG, "Head_index = %u, Tail_index = %u\n",
1941                     flow_tbl->head_index, flow_tbl->tail_index);
1942         for (fid = 1; fid < flow_tbl->num_flows; fid++)
1943                 ulp_flow_db_debug_fid_dump(flow_db, fid);
1944         BNXT_TF_DBG(DEBUG, "Done.\n");
1945         return 0;
1946 }
1947 #endif