016c86fb6ee6e64589cafa3db224d4f3b064a999
[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 reource 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 /* internal validation function for parent flow tbl */
390 static struct bnxt_ulp_flow_db *
391 ulp_flow_db_parent_arg_validation(struct bnxt_ulp_context *ulp_ctxt,
392                                   uint32_t fid)
393 {
394         struct bnxt_ulp_flow_db *flow_db;
395
396         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
397         if (!flow_db) {
398                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
399                 return NULL;
400         }
401
402         /* check for max flows */
403         if (fid >= flow_db->flow_tbl.num_flows || !fid) {
404                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
405                 return NULL;
406         }
407
408         /* No support for parent child db then just exit */
409         if (!flow_db->parent_child_db.entries_count) {
410                 BNXT_TF_DBG(ERR, "parent child db not supported\n");
411                 return NULL;
412         }
413
414         return flow_db;
415 }
416
417 /*
418  * Set the tunnel index in the parent flow
419  *
420  * ulp_ctxt [in] Ptr to ulp_context
421  * parent_idx [in] The parent index of the parent flow entry
422  *
423  * returns index on success and negative on failure.
424  */
425 static int32_t
426 ulp_flow_db_parent_tun_idx_set(struct bnxt_ulp_context *ulp_ctxt,
427                                uint32_t parent_idx, uint8_t tun_idx)
428 {
429         struct bnxt_ulp_flow_db *flow_db;
430         struct ulp_fdb_parent_child_db *p_pdb;
431
432         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
433         if (!flow_db) {
434                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
435                 return -EINVAL;
436         }
437
438         /* check for parent idx validity */
439         p_pdb = &flow_db->parent_child_db;
440         if (parent_idx >= p_pdb->entries_count ||
441             !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
442                 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
443                 return -EINVAL;
444         }
445
446         p_pdb->parent_flow_tbl[parent_idx].tun_idx = tun_idx;
447         return 0;
448 }
449
450 /*
451  * Get the tunnel index from the parent flow
452  *
453  * ulp_ctxt [in] Ptr to ulp_context
454  * parent_fid [in] The flow id of the parent flow entry
455  *
456  * returns 0 if counter accum is set else -1.
457  */
458 static int32_t
459 ulp_flow_db_parent_tun_idx_get(struct bnxt_ulp_context *ulp_ctxt,
460                                uint32_t parent_fid, uint8_t *tun_idx)
461 {
462         struct bnxt_ulp_flow_db *flow_db;
463         struct ulp_fdb_parent_child_db *p_pdb;
464         uint32_t idx;
465
466         /* validate the arguments */
467         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
468         if (!flow_db) {
469                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
470                 return -EINVAL;
471         }
472
473         p_pdb = &flow_db->parent_child_db;
474         for (idx = 0; idx < p_pdb->entries_count; idx++) {
475                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
476                         *tun_idx = p_pdb->parent_flow_tbl[idx].tun_idx;
477                         return 0;
478                 }
479         }
480
481         return -EINVAL;
482 }
483
484 /*
485  * Initialize the flow database. Memory is allocated in this
486  * call and assigned to the flow database.
487  *
488  * ulp_ctxt [in] Ptr to ulp context
489  *
490  * Returns 0 on success or negative number on failure.
491  */
492 int32_t
493 ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
494 {
495         struct bnxt_ulp_device_params *dparms;
496         struct bnxt_ulp_flow_tbl *flow_tbl;
497         struct bnxt_ulp_flow_db *flow_db;
498         uint32_t dev_id, num_flows;
499         enum bnxt_ulp_flow_mem_type mtype;
500
501         /* Get the dev specific number of flows that needed to be supported. */
502         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
503                 BNXT_TF_DBG(ERR, "Invalid device id\n");
504                 return -EINVAL;
505         }
506
507         dparms = bnxt_ulp_device_params_get(dev_id);
508         if (!dparms) {
509                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
510                 return -ENODEV;
511         }
512
513         flow_db = rte_zmalloc("bnxt_ulp_flow_db",
514                               sizeof(struct bnxt_ulp_flow_db), 0);
515         if (!flow_db) {
516                 BNXT_TF_DBG(ERR,
517                             "Failed to allocate memory for flow table ptr\n");
518                 return -ENOMEM;
519         }
520
521         /* Attach the flow database to the ulp context. */
522         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
523
524         /* Determine the number of flows based on EM type */
525         if (bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype))
526                 goto error_free;
527
528         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
529                 num_flows = dparms->int_flow_db_num_entries;
530         else
531                 num_flows = dparms->ext_flow_db_num_entries;
532
533         /* Populate the regular flow table limits. */
534         flow_tbl = &flow_db->flow_tbl;
535         flow_tbl->num_flows = num_flows + 1;
536         flow_tbl->num_resources = ((num_flows + 1) *
537                                    dparms->num_resources_per_flow);
538
539         /* Include the default flow table limits. */
540         flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
541         flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
542                                     BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
543
544         /* Allocate the resource for the flow table. */
545         if (ulp_flow_db_alloc_resource(flow_db))
546                 goto error_free;
547
548         /* add 1 since we are not using index 0 for flow id */
549         flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
550         /* Allocate the function Id table */
551         flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
552                                            flow_db->func_id_tbl_size *
553                                            sizeof(uint16_t), 0);
554         if (!flow_db->func_id_tbl) {
555                 BNXT_TF_DBG(ERR,
556                             "Failed to allocate mem for flow table func id\n");
557                 goto error_free;
558         }
559         /* initialize the parent child database */
560         if (ulp_flow_db_parent_tbl_init(flow_db,
561                                         dparms->fdb_parent_flow_entries)) {
562                 BNXT_TF_DBG(ERR,
563                             "Failed to allocate mem for parent child db\n");
564                 goto error_free;
565         }
566
567         /* All good so return. */
568         BNXT_TF_DBG(INFO, "FlowDB initialized with %d flows.\n",
569                     flow_tbl->num_flows);
570         return 0;
571 error_free:
572         ulp_flow_db_deinit(ulp_ctxt);
573         return -ENOMEM;
574 }
575
576 /*
577  * Deinitialize the flow database. Memory is deallocated in
578  * this call and all flows should have been purged before this
579  * call.
580  *
581  * ulp_ctxt [in] Ptr to ulp context
582  *
583  * Returns 0 on success.
584  */
585 int32_t
586 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
587 {
588         struct bnxt_ulp_flow_db *flow_db;
589
590         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
591         if (!flow_db)
592                 return -EINVAL;
593
594         /* Detach the flow database from the ulp context. */
595         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
596
597         /* Free up all the memory. */
598         ulp_flow_db_parent_tbl_deinit(flow_db);
599         ulp_flow_db_dealloc_resource(flow_db);
600         rte_free(flow_db->func_id_tbl);
601         rte_free(flow_db);
602
603         return 0;
604 }
605
606 /*
607  * Allocate the flow database entry
608  *
609  * ulp_ctxt [in] Ptr to ulp_context
610  * flow_type [in] - specify default or regular
611  * func_id [in].function id of the ingress port
612  * fid [out] The index to the flow entry
613  *
614  * returns 0 on success and negative on failure.
615  */
616 int32_t
617 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
618                       enum bnxt_ulp_fdb_type flow_type,
619                       uint16_t func_id,
620                       uint32_t *fid)
621 {
622         struct bnxt_ulp_flow_db *flow_db;
623         struct bnxt_ulp_flow_tbl *flow_tbl;
624
625         *fid = 0; /* Initialize fid to invalid value */
626         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
627         if (!flow_db) {
628                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
629                 return -EINVAL;
630         }
631
632         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
633                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
634                 return -EINVAL;
635         }
636
637         flow_tbl = &flow_db->flow_tbl;
638         /* check for max flows */
639         if (flow_tbl->num_flows <= flow_tbl->head_index) {
640                 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
641                 return -ENOMEM;
642         }
643         if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
644                 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
645                 return -ENOMEM;
646         }
647         *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
648         flow_tbl->head_index++;
649
650         /* Set the flow type */
651         ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
652
653         /* function id update is only valid for regular flow table */
654         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
655                 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
656
657 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
658         BNXT_TF_DBG(ERR, "flow_id = %u:%u allocated\n", flow_type, *fid);
659 #endif
660         /* return success */
661         return 0;
662 }
663
664 /*
665  * Allocate the flow database entry.
666  * The params->critical_resource has to be set to 0 to allocate a new resource.
667  *
668  * ulp_ctxt [in] Ptr to ulp_context
669  * flow_type [in] Specify it is regular or default flow
670  * fid [in] The index to the flow entry
671  * params [in] The contents to be copied into resource
672  *
673  * returns 0 on success and negative on failure.
674  */
675 int32_t
676 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
677                          enum bnxt_ulp_fdb_type flow_type,
678                          uint32_t fid,
679                          struct ulp_flow_db_res_params *params)
680 {
681         struct bnxt_ulp_flow_db *flow_db;
682         struct bnxt_ulp_flow_tbl *flow_tbl;
683         struct ulp_fdb_resource_info *resource, *fid_resource;
684         struct bnxt_ulp_fc_info *ulp_fc_info;
685         uint32_t idx;
686
687         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
688         if (!flow_db) {
689                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
690                 return -EINVAL;
691         }
692
693         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
694                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
695                 return -EINVAL;
696         }
697
698         flow_tbl = &flow_db->flow_tbl;
699         /* check for max flows */
700         if (fid >= flow_tbl->num_flows || !fid) {
701                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
702                 return -EINVAL;
703         }
704
705         /* check if the flow is active or not */
706         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
707                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
708                 return -EINVAL;
709         }
710
711         /* check for max resource */
712         if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
713                 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
714                 return -ENOMEM;
715         }
716         fid_resource = &flow_tbl->flow_resources[fid];
717
718         if (params->critical_resource && fid_resource->resource_em_handle) {
719                 BNXT_TF_DBG(DEBUG, "Ignore multiple critical resources\n");
720                 /* Ignore the multiple critical resources */
721                 params->critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
722         }
723
724         if (!params->critical_resource) {
725                 /* Not the critical_resource so allocate a resource */
726                 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
727                 resource = &flow_tbl->flow_resources[idx];
728                 flow_tbl->tail_index--;
729
730                 /* Update the chain list of resource*/
731                 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
732                                         fid_resource->nxt_resource_idx);
733                 /* update the contents */
734                 ulp_flow_db_res_params_to_info(resource, params);
735                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
736                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
737                                         idx);
738         } else {
739                 /* critical resource. Just update the fid resource */
740                 ulp_flow_db_res_params_to_info(fid_resource, params);
741         }
742
743         ulp_fc_info = bnxt_ulp_cntxt_ptr2_fc_info_get(ulp_ctxt);
744         if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
745             params->resource_sub_type ==
746             BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT &&
747             ulp_fc_info && ulp_fc_info->num_counters) {
748                 /* Store the first HW counter ID for this table */
749                 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
750                         ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
751                                                  params->resource_hndl);
752
753                 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
754                                     params->resource_hndl);
755
756                 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
757                         ulp_fc_mgr_thread_start(ulp_ctxt);
758         }
759
760         /* all good, return success */
761         return 0;
762 }
763
764 /*
765  * Free the flow database entry.
766  * The params->critical_resource has to be set to 1 to free the first resource.
767  *
768  * ulp_ctxt [in] Ptr to ulp_context
769  * flow_type [in] Specify it is regular or default flow
770  * fid [in] The index to the flow entry
771  * params [in/out] The contents to be copied into params.
772  * Onlythe critical_resource needs to be set by the caller.
773  *
774  * Returns 0 on success and negative on failure.
775  */
776 int32_t
777 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
778                          enum bnxt_ulp_fdb_type flow_type,
779                          uint32_t fid,
780                          struct ulp_flow_db_res_params *params)
781 {
782         struct bnxt_ulp_flow_db *flow_db;
783         struct bnxt_ulp_flow_tbl *flow_tbl;
784         struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
785         uint32_t nxt_idx = 0;
786         struct bnxt_tun_cache_entry *tun_tbl;
787         uint8_t tun_idx = 0;
788         int rc;
789
790         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
791         if (!flow_db) {
792                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
793                 return -EINVAL;
794         }
795
796         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
797                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
798                 return -EINVAL;
799         }
800
801         flow_tbl = &flow_db->flow_tbl;
802         /* check for max flows */
803         if (fid >= flow_tbl->num_flows || !fid) {
804                 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
805                 return -EINVAL;
806         }
807
808         /* check if the flow is active or not */
809         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
810                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
811                 return -EINVAL;
812         }
813
814         fid_resource = &flow_tbl->flow_resources[fid];
815         if (!params->critical_resource) {
816                 /* Not the critical resource so free the resource */
817                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
818                                         fid_resource->nxt_resource_idx);
819                 if (!nxt_idx) {
820                         /* reached end of resources */
821                         return -ENOENT;
822                 }
823                 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
824
825                 /* connect the fid resource to the next resource */
826                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
827                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
828                                         nxt_resource->nxt_resource_idx);
829
830                 /* update the contents to be given to caller */
831                 ulp_flow_db_res_info_to_params(nxt_resource, params);
832
833                 /* Delete the nxt_resource */
834                 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
835
836                 /* add it to the free list */
837                 flow_tbl->tail_index++;
838                 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
839                         BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
840                         return -ENOENT;
841                 }
842                 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
843
844         } else {
845                 /* Critical resource. copy the contents and exit */
846                 ulp_flow_db_res_info_to_params(fid_resource, params);
847                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
848                                         fid_resource->nxt_resource_idx);
849                 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
850                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
851                                         nxt_idx);
852         }
853
854         /* Now that the HW Flow counter resource is deleted, reset it's
855          * corresponding slot in the SW accumulation table in the Flow Counter
856          * manager
857          */
858         if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
859             params->resource_sub_type ==
860             BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) {
861                 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
862                                       params->resource_hndl);
863         }
864
865         if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW) {
866                 tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);
867                 if (!tun_tbl)
868                         return -EINVAL;
869
870                 rc = ulp_flow_db_parent_tun_idx_get(ulp_ctxt, fid, &tun_idx);
871                 if (rc)
872                         return rc;
873
874                 ulp_clear_tun_entry(tun_tbl, tun_idx);
875         }
876
877         /* all good, return success */
878         return 0;
879 }
880
881 /*
882  * Free the flow database entry
883  *
884  * ulp_ctxt [in] Ptr to ulp_context
885  * flow_type [in] - specify default or regular
886  * fid [in] The index to the flow entry
887  *
888  * returns 0 on success and negative on failure.
889  */
890 int32_t
891 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
892                      enum bnxt_ulp_fdb_type flow_type,
893                      uint32_t fid)
894 {
895         struct bnxt_tun_cache_entry *tun_tbl;
896         struct bnxt_ulp_flow_tbl *flow_tbl;
897         struct bnxt_ulp_flow_db *flow_db;
898
899         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
900         if (!flow_db) {
901                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
902                 return -EINVAL;
903         }
904
905         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
906                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
907                 return -EINVAL;
908         }
909
910         flow_tbl = &flow_db->flow_tbl;
911
912         /* check for limits of fid */
913         if (fid >= flow_tbl->num_flows || !fid) {
914                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
915                 return -EINVAL;
916         }
917
918         /* check if the flow is active or not */
919         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
920                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
921                 return -EINVAL;
922         }
923         flow_tbl->head_index--;
924         if (!flow_tbl->head_index) {
925                 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
926                 return -ENOENT;
927         }
928
929         flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
930
931         /* Clear the flows bitmap */
932         ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
933
934         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
935                 ulp_flow_db_func_id_set(flow_db, fid, 0);
936
937         tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);
938         if (!tun_tbl)
939                 return -EINVAL;
940
941         ulp_clear_tun_inner_entry(tun_tbl, fid);
942
943 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
944         BNXT_TF_DBG(ERR, "flow_id = %u:%u freed\n", flow_type, fid);
945 #endif
946         /* all good, return success */
947         return 0;
948 }
949
950 /*
951  *Get the flow database entry details
952  *
953  * ulp_ctxt [in] Ptr to ulp_context
954  * flow_type [in] - specify default or regular
955  * fid [in] The index to the flow entry
956  * nxt_idx [in/out] the index to the next entry
957  * params [out] The contents to be copied into params.
958  *
959  * returns 0 on success and negative on failure.
960  */
961 int32_t
962 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
963                          enum bnxt_ulp_fdb_type flow_type,
964                          uint32_t fid,
965                          uint32_t *nxt_idx,
966                          struct ulp_flow_db_res_params *params)
967 {
968         struct bnxt_ulp_flow_db *flow_db;
969         struct bnxt_ulp_flow_tbl *flow_tbl;
970         struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
971
972         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
973         if (!flow_db) {
974                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
975                 return -EINVAL;
976         }
977
978         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
979                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
980                 return -EINVAL;
981         }
982
983         flow_tbl = &flow_db->flow_tbl;
984
985         /* check for limits of fid */
986         if (fid >= flow_tbl->num_flows || !fid) {
987                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
988                 return -EINVAL;
989         }
990
991         /* check if the flow is active or not */
992         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
993                 BNXT_TF_DBG(ERR, "flow does not exist\n");
994                 return -EINVAL;
995         }
996
997         if (!*nxt_idx) {
998                 fid_resource = &flow_tbl->flow_resources[fid];
999                 ulp_flow_db_res_info_to_params(fid_resource, params);
1000                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
1001                                         fid_resource->nxt_resource_idx);
1002         } else {
1003                 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
1004                 ulp_flow_db_res_info_to_params(nxt_resource, params);
1005                 *nxt_idx = 0;
1006                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
1007                                         nxt_resource->nxt_resource_idx);
1008         }
1009
1010         /* all good, return success */
1011         return 0;
1012 }
1013
1014 /*
1015  * Get the flow database entry iteratively
1016  *
1017  * flow_tbl [in] Ptr to flow table
1018  * flow_type [in] - specify default or regular
1019  * fid [in/out] The index to the flow entry
1020  *
1021  * returns 0 on success and negative on failure.
1022  */
1023 static int32_t
1024 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1025                            enum bnxt_ulp_fdb_type flow_type,
1026                            uint32_t *fid)
1027 {
1028         uint32_t lfid = *fid;
1029         uint32_t idx, s_idx, mod_fid;
1030         uint64_t bs;
1031         uint64_t *active_flows;
1032         struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
1033
1034         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) {
1035                 active_flows = flowtbl->active_reg_flows;
1036         } else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) {
1037                 active_flows = flowtbl->active_dflt_flows;
1038         } else {
1039                 BNXT_TF_DBG(ERR, "Invalid flow type %x\n", flow_type);
1040                         return -EINVAL;
1041         }
1042
1043         do {
1044                 /* increment the flow id to find the next valid flow id */
1045                 lfid++;
1046                 if (lfid >= flowtbl->num_flows)
1047                         return -ENOENT;
1048                 idx = lfid / ULP_INDEX_BITMAP_SIZE;
1049                 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
1050                 s_idx = idx;
1051                 while (!(bs = active_flows[idx])) {
1052                         idx++;
1053                         if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
1054                                 return -ENOENT;
1055                 }
1056                 /*
1057                  * remove the previous bits in the bitset bs to find the
1058                  * next non zero bit in the bitset. This needs to be done
1059                  * only if the idx is same as he one you started.
1060                  */
1061                 if (s_idx == idx)
1062                         bs &= (-1UL >> mod_fid);
1063                 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
1064                 if (*fid >= lfid) {
1065                         BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
1066                         return -ENOENT;
1067                 }
1068         } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
1069                                                       lfid));
1070
1071         /* all good, return success */
1072         *fid = lfid;
1073         return 0;
1074 }
1075
1076 /*
1077  * Flush all flows in the flow database.
1078  *
1079  * ulp_ctxt [in] Ptr to ulp context
1080  * flow_type [in] - specify default or regular
1081  *
1082  * returns 0 on success or negative number on failure
1083  */
1084 int32_t
1085 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
1086                         enum bnxt_ulp_fdb_type flow_type)
1087 {
1088         uint32_t fid = 0;
1089         struct bnxt_ulp_flow_db *flow_db;
1090
1091         if (!ulp_ctx) {
1092                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
1093                 return -EINVAL;
1094         }
1095
1096         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1097         if (!flow_db) {
1098                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1099                 return -EINVAL;
1100         }
1101         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
1102                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
1103                 return -EINVAL;
1104         }
1105
1106         while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
1107                 ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
1108
1109         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
1110
1111         return 0;
1112 }
1113
1114 /*
1115  * Flush all flows in the flow database that belong to a device function.
1116  *
1117  * ulp_ctxt [in] Ptr to ulp context
1118  * func_id [in] - The port function id
1119  *
1120  * returns 0 on success or negative number on failure
1121  */
1122 int32_t
1123 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
1124                                 uint16_t func_id)
1125 {
1126         uint32_t flow_id = 0;
1127         struct bnxt_ulp_flow_db *flow_db;
1128
1129         if (!ulp_ctx || !func_id) {
1130                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
1131                 return -EINVAL;
1132         }
1133
1134         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1135         if (!flow_db) {
1136                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1137                 return -EINVAL;
1138         }
1139         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
1140                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
1141                 return -EINVAL;
1142         }
1143
1144         while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
1145                                            &flow_id)) {
1146                 if (flow_db->func_id_tbl[flow_id] == func_id)
1147                         ulp_mapper_resources_free(ulp_ctx,
1148                                                   BNXT_ULP_FDB_TYPE_REGULAR,
1149                                                   flow_id);
1150         }
1151         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
1152         return 0;
1153 }
1154
1155 /*
1156  * Flush all flows in the flow database that are associated with the session.
1157  *
1158  * ulp_ctxt [in] Ptr to ulp context
1159  *
1160  * returns 0 on success or negative number on failure
1161  */
1162 int32_t
1163 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
1164 {
1165         /*
1166          * TBD: Tf core implementation of FW session flush shall change this
1167          * implementation.
1168          */
1169         return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1170 }
1171
1172 /*
1173  * Check that flow id matches the function id or not
1174  *
1175  * ulp_ctxt [in] Ptr to ulp context
1176  * flow_db [in] Ptr to flow table
1177  * func_id [in] The func_id to be set, for reset pass zero.
1178  *
1179  * returns true on success or false on failure
1180  */
1181 bool
1182 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
1183                                uint32_t flow_id,
1184                                uint32_t func_id)
1185 {
1186         struct bnxt_ulp_flow_db *flow_db;
1187
1188         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1189         if (!flow_db) {
1190                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1191                 return false;
1192         }
1193
1194         /* set the function id in the function table */
1195         if (flow_id < flow_db->func_id_tbl_size && func_id &&
1196             flow_db->func_id_tbl[flow_id] == func_id)
1197                 return true;
1198
1199         return false;
1200 }
1201
1202 /*
1203  * Internal api to traverse the resource list within a flow
1204  * and match a resource based on resource func and resource
1205  * sub type. This api should be used only for resources that
1206  * are unique and do not have multiple instances of resource
1207  * func and sub type combination since it will return only
1208  * the first match.
1209  */
1210 static int32_t
1211 ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,
1212                                 enum bnxt_ulp_fdb_type flow_type,
1213                                 uint32_t flow_id,
1214                                 uint32_t resource_func,
1215                                 uint32_t res_subtype,
1216                                 struct ulp_flow_db_res_params *params)
1217 {
1218         struct bnxt_ulp_flow_db *flow_db;
1219         struct bnxt_ulp_flow_tbl *flow_tbl;
1220         struct ulp_fdb_resource_info *fid_res;
1221         uint32_t res_id;
1222
1223         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1224         if (!flow_db) {
1225                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1226                 return -EINVAL;
1227         }
1228
1229         if (!params) {
1230                 BNXT_TF_DBG(ERR, "invalid argument\n");
1231                 return -EINVAL;
1232         }
1233
1234         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1235                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1236                 return -EINVAL;
1237         }
1238
1239         flow_tbl = &flow_db->flow_tbl;
1240
1241         /* check for limits of fid */
1242         if (flow_id >= flow_tbl->num_flows || !flow_id) {
1243                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1244                 return -EINVAL;
1245         }
1246
1247         /* check if the flow is active or not */
1248         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
1249                 BNXT_TF_DBG(ERR, "flow does not exist\n");
1250                 return -EINVAL;
1251         }
1252         /* Iterate the resource to get the resource handle */
1253         res_id =  flow_id;
1254         memset(params, 0, sizeof(struct ulp_flow_db_res_params));
1255         while (res_id) {
1256                 fid_res = &flow_tbl->flow_resources[res_id];
1257                 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
1258                         if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
1259                                 if (res_subtype == fid_res->resource_sub_type) {
1260                                         ulp_flow_db_res_info_to_params(fid_res,
1261                                                                        params);
1262                                         return 0;
1263                                 }
1264
1265                         } else if (resource_func ==
1266                                    BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
1267                                 ulp_flow_db_res_info_to_params(fid_res,
1268                                                                params);
1269                                 return 0;
1270                         }
1271                 }
1272                 res_id = 0;
1273                 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1274         }
1275         return -ENOENT;
1276 }
1277
1278 /*
1279  * Api to get the cfa action pointer from a flow.
1280  *
1281  * ulp_ctxt [in] Ptr to ulp context
1282  * flow_id [in] flow id
1283  * cfa_action [out] The resource handle stored in the flow database
1284  *
1285  * returns 0 on success
1286  */
1287 int32_t
1288 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1289                                    uint32_t flow_id,
1290                                    uint16_t *cfa_action)
1291 {
1292         uint8_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_VFR_CFA_ACTION;
1293         struct ulp_flow_db_res_params params;
1294         int32_t rc;
1295
1296         rc = ulp_flow_db_resource_params_get(ulp_ctx,
1297                                              BNXT_ULP_FDB_TYPE_DEFAULT,
1298                                              flow_id,
1299                                              BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1300                                              sub_typ, &params);
1301         if (rc) {
1302                 BNXT_TF_DBG(INFO, "CFA Action ptr not found for flow id %u\n",
1303                             flow_id);
1304                 return -ENOENT;
1305         }
1306         *cfa_action = params.resource_hndl;
1307         return 0;
1308 }
1309
1310 /*
1311  * Allocate the entry in the parent-child database
1312  *
1313  * ulp_ctxt [in] Ptr to ulp_context
1314  * fid [in] The flow id to the flow entry
1315  *
1316  * returns index on success and negative on failure.
1317  */
1318 int32_t
1319 ulp_flow_db_parent_flow_alloc(struct bnxt_ulp_context *ulp_ctxt,
1320                               uint32_t fid)
1321 {
1322         struct bnxt_ulp_flow_db *flow_db;
1323         struct ulp_fdb_parent_child_db *p_pdb;
1324         uint32_t idx, free_idx = 0;
1325
1326         /* validate the arguments */
1327         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid);
1328         if (!flow_db) {
1329                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1330                 return -EINVAL;
1331         }
1332
1333         p_pdb = &flow_db->parent_child_db;
1334         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1335                 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1336                         BNXT_TF_DBG(ERR, "fid is already allocated\n");
1337                         return -EINVAL;
1338                 }
1339                 if (!p_pdb->parent_flow_tbl[idx].parent_fid && !free_idx)
1340                         free_idx = idx + 1;
1341         }
1342         /* no free slots */
1343         if (!free_idx) {
1344                 BNXT_TF_DBG(ERR, "parent child db is full\n");
1345                 return -ENOMEM;
1346         }
1347
1348         free_idx -= 1;
1349         /* set the Fid in the parent child */
1350         p_pdb->parent_flow_tbl[free_idx].parent_fid = fid;
1351         return free_idx;
1352 }
1353
1354 /*
1355  * Free the entry in the parent-child database
1356  *
1357  * ulp_ctxt [in] Ptr to ulp_context
1358  * fid [in] The flow id to the flow entry
1359  *
1360  * returns 0 on success and negative on failure.
1361  */
1362 int32_t
1363 ulp_flow_db_parent_flow_free(struct bnxt_ulp_context *ulp_ctxt,
1364                              uint32_t fid)
1365 {
1366         struct bnxt_ulp_flow_db *flow_db;
1367         struct ulp_fdb_parent_child_db *p_pdb;
1368         uint32_t idx;
1369
1370         /* validate the arguments */
1371         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid);
1372         if (!flow_db) {
1373                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1374                 return -EINVAL;
1375         }
1376
1377         p_pdb = &flow_db->parent_child_db;
1378         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1379                 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1380                         /* free the contents */
1381                         p_pdb->parent_flow_tbl[idx].parent_fid = 0;
1382                         memset(p_pdb->parent_flow_tbl[idx].child_fid_bitset,
1383                                0, p_pdb->child_bitset_size);
1384                         return 0;
1385                 }
1386         }
1387         BNXT_TF_DBG(ERR, "parent entry not found = %x\n", fid);
1388         return -EINVAL;
1389 }
1390
1391 /*
1392  * Set or reset the child flow in the parent-child database
1393  *
1394  * ulp_ctxt [in] Ptr to ulp_context
1395  * parent_fid [in] The flow id of the parent flow entry
1396  * child_fid [in] The flow id of the child flow entry
1397  * set_flag [in] Use 1 for setting child, 0 to reset
1398  *
1399  * returns zero on success and negative on failure.
1400  */
1401 int32_t
1402 ulp_flow_db_parent_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1403                                   uint32_t parent_fid,
1404                                   uint32_t child_fid,
1405                                   uint32_t set_flag)
1406 {
1407         struct bnxt_ulp_flow_db *flow_db;
1408         struct ulp_fdb_parent_child_db *p_pdb;
1409         uint32_t idx, a_idx;
1410         uint64_t *t;
1411
1412         /* validate the arguments */
1413         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1414         if (!flow_db) {
1415                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1416                 return -EINVAL;
1417         }
1418
1419         /* check for fid validity */
1420         if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) {
1421                 BNXT_TF_DBG(ERR, "Invalid child flow index %x\n", child_fid);
1422                 return -EINVAL;
1423         }
1424
1425         p_pdb = &flow_db->parent_child_db;
1426         a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
1427         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1428                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1429                         t = p_pdb->parent_flow_tbl[idx].child_fid_bitset;
1430                         if (set_flag)
1431                                 ULP_INDEX_BITMAP_SET(t[a_idx], child_fid);
1432                         else
1433                                 ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid);
1434                         return 0;
1435                 }
1436         }
1437         BNXT_TF_DBG(ERR, "Unable to set the parent-child flow %x:%x\n",
1438                     parent_fid, child_fid);
1439         return -1;
1440 }
1441
1442 /*
1443  * Get the parent index from the parent-child database
1444  *
1445  * ulp_ctxt [in] Ptr to ulp_context
1446  * parent_fid [in] The flow id of the parent flow entry
1447  * parent_idx [out] The parent index of parent flow entry
1448  *
1449  * returns zero on success and negative on failure.
1450  */
1451 int32_t
1452 ulp_flow_db_parent_flow_idx_get(struct bnxt_ulp_context *ulp_ctxt,
1453                                 uint32_t parent_fid,
1454                                 uint32_t *parent_idx)
1455 {
1456         struct bnxt_ulp_flow_db *flow_db;
1457         struct ulp_fdb_parent_child_db *p_pdb;
1458         uint32_t idx;
1459
1460         /* validate the arguments */
1461         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1462         if (!flow_db) {
1463                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1464                 return -EINVAL;
1465         }
1466
1467         p_pdb = &flow_db->parent_child_db;
1468         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1469                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1470                         *parent_idx = idx;
1471                         return 0;
1472                 }
1473         }
1474         BNXT_TF_DBG(ERR, "Unable to get the parent flow %x\n", parent_fid);
1475         return -1;
1476 }
1477
1478 /*
1479  * Get the next child flow in the parent-child database
1480  *
1481  * ulp_ctxt [in] Ptr to ulp_context
1482  * parent_fid [in] The flow id of the parent flow entry
1483  * child_fid [in/out] The flow id of the child flow entry
1484  *
1485  * returns zero on success and negative on failure.
1486  * Pass child_fid as zero for first entry.
1487  */
1488 int32_t
1489 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1490                                              uint32_t parent_idx,
1491                                              uint32_t *child_fid)
1492 {
1493         struct ulp_fdb_parent_child_db *p_pdb;
1494         uint32_t idx, s_idx, mod_fid;
1495         uint32_t next_fid = *child_fid;
1496         uint64_t *child_bitset;
1497         uint64_t bs;
1498
1499         /* check for fid validity */
1500         p_pdb = &flow_db->parent_child_db;
1501         if (parent_idx >= p_pdb->entries_count ||
1502             !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1503                 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1504                 return -EINVAL;
1505         }
1506
1507         child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset;
1508         do {
1509                 /* increment the flow id to find the next valid flow id */
1510                 next_fid++;
1511                 if (next_fid >= flow_db->flow_tbl.num_flows)
1512                         return -ENOENT;
1513                 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1514                 mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE;
1515                 s_idx = idx;
1516                 while (!(bs = child_bitset[idx])) {
1517                         idx++;
1518                         if ((idx * ULP_INDEX_BITMAP_SIZE) >=
1519                             flow_db->flow_tbl.num_flows)
1520                                 return -ENOENT;
1521                 }
1522                 /*
1523                  * remove the previous bits in the bitset bs to find the
1524                  * next non zero bit in the bitset. This needs to be done
1525                  * only if the idx is same as he one you started.
1526                  */
1527                 if (s_idx == idx)
1528                         bs &= (-1UL >> mod_fid);
1529                 next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
1530                 if (*child_fid >= next_fid) {
1531                         BNXT_TF_DBG(ERR, "Parent Child Database is corrupt\n");
1532                         return -ENOENT;
1533                 }
1534                 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1535         } while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid));
1536         *child_fid = next_fid;
1537         return 0;
1538 }
1539
1540 /*
1541  * Set the counter accumulation in the parent flow
1542  *
1543  * ulp_ctxt [in] Ptr to ulp_context
1544  * parent_idx [in] The parent index of the parent flow entry
1545  *
1546  * returns index on success and negative on failure.
1547  */
1548 static int32_t
1549 ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt,
1550                                         uint32_t parent_idx)
1551 {
1552         struct bnxt_ulp_flow_db *flow_db;
1553         struct ulp_fdb_parent_child_db *p_pdb;
1554
1555         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1556         if (!flow_db) {
1557                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1558                 return -EINVAL;
1559         }
1560
1561         /* check for parent idx validity */
1562         p_pdb = &flow_db->parent_child_db;
1563         if (parent_idx >= p_pdb->entries_count ||
1564             !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1565                 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1566                 return -EINVAL;
1567         }
1568
1569         p_pdb->parent_flow_tbl[parent_idx].counter_acc = 1;
1570         return 0;
1571 }
1572
1573 /*
1574  * Get the counter accumulation in the parent flow
1575  *
1576  * ulp_ctxt [in] Ptr to ulp_context
1577  * parent_fid [in] The flow id of the parent flow entry
1578  *
1579  * returns 0 if counter accum is set else -1.
1580  */
1581 static int32_t
1582 ulp_flow_db_parent_flow_count_accum_get(struct bnxt_ulp_context *ulp_ctxt,
1583                                         uint32_t parent_fid)
1584 {
1585         struct bnxt_ulp_flow_db *flow_db;
1586         struct ulp_fdb_parent_child_db *p_pdb;
1587         uint32_t idx;
1588
1589         /* validate the arguments */
1590         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1591         if (!flow_db) {
1592                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1593                 return -EINVAL;
1594         }
1595
1596         p_pdb = &flow_db->parent_child_db;
1597         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1598                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1599                         if (p_pdb->parent_flow_tbl[idx].counter_acc)
1600                                 return 0;
1601                         break;
1602                 }
1603         }
1604         return -1;
1605 }
1606
1607 /*
1608  * Orphan the child flow entry
1609  * This is called only for child flows that have
1610  * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
1611  *
1612  * ulp_ctxt [in] Ptr to ulp_context
1613  * flow_type [in] Specify it is regular or default flow
1614  * fid [in] The index to the flow entry
1615  *
1616  * Returns 0 on success and negative on failure.
1617  */
1618 int32_t
1619 ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
1620                              enum bnxt_ulp_fdb_type flow_type,
1621                              uint32_t fid)
1622 {
1623         struct bnxt_ulp_flow_db *flow_db;
1624         struct bnxt_ulp_flow_tbl *flow_tbl;
1625         struct ulp_fdb_resource_info *fid_res;
1626         uint32_t res_id = 0;
1627
1628         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1629         if (!flow_db) {
1630                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1631                 return -EINVAL;
1632         }
1633
1634         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1635                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1636                 return -EINVAL;
1637         }
1638
1639         flow_tbl = &flow_db->flow_tbl;
1640         /* check for max flows */
1641         if (fid >= flow_tbl->num_flows || !fid) {
1642                 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
1643                 return -EINVAL;
1644         }
1645
1646         /* check if the flow is active or not */
1647         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
1648                 BNXT_TF_DBG(ERR, "flow does not exist\n");
1649                 return -EINVAL;
1650         }
1651
1652         /* Iterate the resource to get the resource handle */
1653         res_id =  fid;
1654         while (res_id) {
1655                 fid_res = &flow_tbl->flow_resources[res_id];
1656                 if (ulp_flow_db_resource_func_get(fid_res) ==
1657                     BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) {
1658                         /* invalidate the resource details */
1659                         fid_res->resource_hndl = 0;
1660                         return 0;
1661                 }
1662                 res_id = 0;
1663                 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1664         }
1665         /* failed */
1666         return -1;
1667 }
1668
1669 /*
1670  * Create parent flow in the parent flow tbl
1671  *
1672  * parms [in] Ptr to mapper params
1673  *
1674  * Returns 0 on success and negative on failure.
1675  */
1676 int32_t
1677 ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)
1678 {
1679         struct ulp_flow_db_res_params fid_parms;
1680         uint32_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT_ACC;
1681         struct ulp_flow_db_res_params res_params;
1682         int32_t fid_idx, rc;
1683
1684         /* create the child flow entry in parent flow table */
1685         fid_idx = ulp_flow_db_parent_flow_alloc(parms->ulp_ctx, parms->fid);
1686         if (fid_idx < 0) {
1687                 BNXT_TF_DBG(ERR, "Error in creating parent flow fid %x\n",
1688                             parms->fid);
1689                 return -1;
1690         }
1691
1692         /* Add the parent details in the resource list of the flow */
1693         memset(&fid_parms, 0, sizeof(fid_parms));
1694         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW;
1695         fid_parms.resource_hndl = fid_idx;
1696         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1697         if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
1698                                      parms->fid, &fid_parms)) {
1699                 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1700                             parms->fid);
1701                 return -1;
1702         }
1703
1704         /* check of the flow has internal counter accumulation enabled */
1705         if (!ulp_flow_db_resource_params_get(parms->ulp_ctx,
1706                                              BNXT_ULP_FDB_TYPE_REGULAR,
1707                                              parms->fid,
1708                                              BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1709                                              sub_typ,
1710                                              &res_params)) {
1711                 /* Enable the counter accumulation in parent entry */
1712                 if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx,
1713                                                             fid_idx)) {
1714                         BNXT_TF_DBG(ERR, "Error in setting counter acc %x\n",
1715                                     parms->fid);
1716                         return -1;
1717                 }
1718         }
1719
1720         rc  = ulp_flow_db_parent_tun_idx_set(parms->ulp_ctx, fid_idx,
1721                                              parms->tun_idx);
1722         if (rc) {
1723                 BNXT_TF_DBG(ERR, "Error setting tun_idx in the parent flow\n");
1724                 return rc;
1725         }
1726
1727         return 0;
1728 }
1729
1730 /*
1731  * Create child flow in the parent flow tbl
1732  *
1733  * parms [in] Ptr to mapper params
1734  *
1735  * Returns 0 on success and negative on failure.
1736  */
1737 int32_t
1738 ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms)
1739 {
1740         struct ulp_flow_db_res_params fid_parms;
1741         uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1742         enum bnxt_ulp_resource_func res_fun;
1743         struct ulp_flow_db_res_params res_p;
1744         uint32_t parent_fid = parms->parent_fid;
1745         int32_t rc;
1746
1747         /* create the parent flow entry in parent flow table */
1748         rc = ulp_flow_db_parent_child_flow_set(parms->ulp_ctx,
1749                                                parms->parent_fid,
1750                                                parms->fid, 1);
1751         if (rc) {
1752                 BNXT_TF_DBG(ERR, "Error in setting child fid %x\n", parms->fid);
1753                 return rc;
1754         }
1755
1756         /* Add the parent details in the resource list of the flow */
1757         memset(&fid_parms, 0, sizeof(fid_parms));
1758         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW;
1759         fid_parms.resource_hndl = parms->parent_fid;
1760         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1761         rc  = ulp_flow_db_resource_add(parms->ulp_ctx,
1762                                        BNXT_ULP_FDB_TYPE_REGULAR,
1763                                        parms->fid, &fid_parms);
1764         if (rc) {
1765                 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1766                             parms->fid);
1767                 return rc;
1768         }
1769
1770         /* check if accumulation count is set for parent flow */
1771         rc = ulp_flow_db_parent_flow_count_accum_get(parms->ulp_ctx,
1772                                                      parms->parent_fid);
1773         if (!rc) {
1774                 /* check if internal count action included for this flow.*/
1775                 res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE;
1776                 rc = ulp_flow_db_resource_params_get(parms->ulp_ctx,
1777                                                      BNXT_ULP_FDB_TYPE_REGULAR,
1778                                                      parms->fid,
1779                                                      res_fun,
1780                                                      sub_type,
1781                                                      &res_p);
1782                 if (!rc) {
1783                         /* update the counter manager to include parent fid */
1784                         if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx,
1785                                                             res_p.direction,
1786                                                             res_p.resource_hndl,
1787                                                             parent_fid)) {
1788                                 BNXT_TF_DBG(ERR, "Error in setting child %x\n",
1789                                             parms->fid);
1790                                 return -1;
1791                         }
1792                 }
1793         }
1794         /* return success */
1795         return 0;
1796 }
1797
1798 /*
1799  * Update the parent counters
1800  *
1801  * ulp_ctxt [in] Ptr to ulp_context
1802  * parent_fid [in] The flow id of the parent flow entry
1803  * packet_count [in] - packet count
1804  * byte_count [in] - byte count
1805  *
1806  * returns 0 on success
1807  */
1808 int32_t
1809 ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt,
1810                                      uint32_t parent_fid,
1811                                      uint64_t packet_count,
1812                                      uint64_t byte_count)
1813 {
1814         struct bnxt_ulp_flow_db *flow_db;
1815         struct ulp_fdb_parent_child_db *p_pdb;
1816         uint32_t idx;
1817
1818         /* validate the arguments */
1819         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1820         if (!flow_db) {
1821                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1822                 return -EINVAL;
1823         }
1824
1825         p_pdb = &flow_db->parent_child_db;
1826         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1827                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1828                         if (p_pdb->parent_flow_tbl[idx].counter_acc) {
1829                                 p_pdb->parent_flow_tbl[idx].pkt_count +=
1830                                         packet_count;
1831                                 p_pdb->parent_flow_tbl[idx].byte_count +=
1832                                         byte_count;
1833                         }
1834                         return 0;
1835                 }
1836         }
1837         return -ENOENT;
1838 }
1839
1840 /*
1841  * Get the parent accumulation counters
1842  *
1843  * ulp_ctxt [in] Ptr to ulp_context
1844  * parent_fid [in] The flow id of the parent flow entry
1845  * packet_count [out] - packet count
1846  * byte_count [out] - byte count
1847  *
1848  * returns 0 on success
1849  */
1850 int32_t
1851 ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,
1852                                   uint32_t parent_fid, uint64_t *packet_count,
1853                                   uint64_t *byte_count, uint8_t count_reset)
1854 {
1855         struct bnxt_ulp_flow_db *flow_db;
1856         struct ulp_fdb_parent_child_db *p_pdb;
1857         uint32_t idx;
1858
1859         /* validate the arguments */
1860         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1861         if (!flow_db) {
1862                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1863                 return -EINVAL;
1864         }
1865
1866         p_pdb = &flow_db->parent_child_db;
1867         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1868                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1869                         if (p_pdb->parent_flow_tbl[idx].counter_acc) {
1870                                 *packet_count =
1871                                         p_pdb->parent_flow_tbl[idx].pkt_count;
1872                                 *byte_count =
1873                                         p_pdb->parent_flow_tbl[idx].byte_count;
1874                                 if (count_reset) {
1875                                         p_pdb->parent_flow_tbl[idx].pkt_count = 0;
1876                                         p_pdb->parent_flow_tbl[idx].byte_count = 0;
1877                                 }
1878                         }
1879                         return 0;
1880                 }
1881         }
1882         return -ENOENT;
1883 }
1884
1885 /*
1886  * reset the parent accumulation counters
1887  *
1888  * ulp_ctxt [in] Ptr to ulp_context
1889  *
1890  * returns none
1891  */
1892 void
1893 ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt)
1894 {
1895         struct bnxt_ulp_flow_db *flow_db;
1896         struct ulp_fdb_parent_child_db *p_pdb;
1897         uint32_t idx;
1898
1899         /* validate the arguments */
1900         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, 1);
1901         if (!flow_db) {
1902                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1903                 return;
1904         }
1905
1906         p_pdb = &flow_db->parent_child_db;
1907         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1908                 if (p_pdb->parent_flow_tbl[idx].parent_fid &&
1909                     p_pdb->parent_flow_tbl[idx].counter_acc) {
1910                         p_pdb->parent_flow_tbl[idx].pkt_count = 0;
1911                         p_pdb->parent_flow_tbl[idx].byte_count = 0;
1912                 }
1913         }
1914 }
1915
1916 /*
1917  * Set the shared bit for the flow db entry
1918  *
1919  * res [in] Ptr to fdb entry
1920  * shared [in] shared flag
1921  *
1922  * returns none
1923  */
1924 void ulp_flow_db_shared_session_set(struct ulp_flow_db_res_params *res,
1925                                     enum bnxt_ulp_shared_session shared)
1926 {
1927         if (res && (shared & BNXT_ULP_SHARED_SESSION_YES))
1928                 res->fdb_flags |= ULP_FDB_FLAG_SHARED_SESSION;
1929 }
1930
1931 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
1932 /*
1933  * Dump the entry details
1934  *
1935  * ulp_ctxt [in] Ptr to ulp_context
1936  *
1937  * returns none
1938  */
1939 static void ulp_flow_db_res_dump(struct ulp_fdb_resource_info *r,
1940                                  uint32_t *nxt_res)
1941 {
1942         uint8_t res_func = ulp_flow_db_resource_func_get(r);
1943
1944         BNXT_TF_DBG(DEBUG, "Resource func = %x, nxt_resource_idx = %x\n",
1945                     res_func, (ULP_FLOW_DB_RES_NXT_MASK & r->nxt_resource_idx));
1946         if (res_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE)
1947                 BNXT_TF_DBG(DEBUG, "EM Handle = 0x%016" PRIX64 "\n",
1948                             r->resource_em_handle);
1949         else
1950                 BNXT_TF_DBG(DEBUG, "Handle = 0x%08x\n", r->resource_hndl);
1951
1952         *nxt_res = 0;
1953         ULP_FLOW_DB_RES_NXT_SET(*nxt_res,
1954                                 r->nxt_resource_idx);
1955 }
1956
1957 /*
1958  * Dump the flow entry details
1959  *
1960  * flow_db [in] Ptr to flow db
1961  * fid [in] flow id
1962  *
1963  * returns none
1964  */
1965 void
1966 ulp_flow_db_debug_fid_dump(struct bnxt_ulp_flow_db *flow_db, uint32_t fid)
1967 {
1968         struct ulp_fdb_resource_info *r;
1969         struct bnxt_ulp_flow_tbl *flow_tbl;
1970         uint32_t nxt_res = 0;
1971         uint32_t def_flag = 0, reg_flag = 0;
1972
1973         flow_tbl = &flow_db->flow_tbl;
1974         if (ulp_flow_db_active_flows_bit_is_set(flow_db,
1975                                                 BNXT_ULP_FDB_TYPE_REGULAR, fid))
1976                 reg_flag = 1;
1977         if (ulp_flow_db_active_flows_bit_is_set(flow_db,
1978                                                 BNXT_ULP_FDB_TYPE_DEFAULT, fid))
1979                 def_flag = 1;
1980
1981         if (reg_flag && def_flag)
1982                 BNXT_TF_DBG(DEBUG, "RID = %u\n", fid);
1983         else if (reg_flag)
1984                 BNXT_TF_DBG(DEBUG, "Regular fid = %u and func id = %u\n",
1985                             fid, flow_db->func_id_tbl[fid]);
1986         else if (def_flag)
1987                 BNXT_TF_DBG(DEBUG, "Default fid = %u\n", fid);
1988         else
1989                 return;
1990         /* iterate the resource */
1991         nxt_res = fid;
1992         do {
1993                 r = &flow_tbl->flow_resources[nxt_res];
1994                 ulp_flow_db_res_dump(r, &nxt_res);
1995         } while (nxt_res);
1996 }
1997
1998 /*
1999  * Dump the flow database entry details
2000  *
2001  * ulp_ctxt [in] Ptr to ulp_context
2002  * flow_id [in] if zero then all fids are dumped.
2003  *
2004  * returns none
2005  */
2006 int32_t ulp_flow_db_debug_dump(struct bnxt_ulp_context *ulp_ctxt,
2007                                uint32_t flow_id)
2008 {
2009         struct bnxt_ulp_flow_db *flow_db;
2010         struct bnxt_ulp_flow_tbl *flow_tbl;
2011         uint32_t fid;
2012
2013         if (!ulp_ctxt || !ulp_ctxt->cfg_data) {
2014                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2015                 return -EINVAL;
2016         }
2017         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
2018         if (!flow_db) {
2019                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2020                 return -EINVAL;
2021         }
2022
2023         flow_tbl = &flow_db->flow_tbl;
2024         if (flow_id) {
2025                 ulp_flow_db_debug_fid_dump(flow_db, flow_id);
2026                 return 0;
2027         }
2028
2029         BNXT_TF_DBG(DEBUG, "Dump flows = %u:%u\n",
2030                     flow_tbl->num_flows,
2031                     flow_tbl->num_resources);
2032         BNXT_TF_DBG(DEBUG, "Head_index = %u, Tail_index = %u\n",
2033                     flow_tbl->head_index, flow_tbl->tail_index);
2034         for (fid = 1; fid < flow_tbl->num_flows; fid++)
2035                 ulp_flow_db_debug_fid_dump(flow_db, fid);
2036         BNXT_TF_DBG(DEBUG, "Done.\n");
2037         return 0;
2038 }
2039 #endif