net/bnxt: identify duplicate flows
[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
89         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
90                 return ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx],
91                                             idx);
92         else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT)
93                 return ULP_INDEX_BITMAP_GET(f_tbl->active_dflt_flows[a_idx],
94                                             idx);
95         else if (flow_type == BNXT_ULP_FDB_TYPE_RID)
96                 return (ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx],
97                                              idx) &&
98                         ULP_INDEX_BITMAP_GET(f_tbl->active_reg_flows[a_idx],
99                                              idx));
100         return 0;
101 }
102
103 static inline enum tf_dir
104 ulp_flow_db_resource_dir_get(struct ulp_fdb_resource_info *res_info)
105 {
106         return ((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_DIR_MASK) >>
107                 ULP_FLOW_DB_RES_DIR_BIT);
108 }
109
110 static uint8_t
111 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
112 {
113         uint8_t func;
114
115         func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
116                  ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
117         /* The reource func is split into upper and lower */
118         if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
119                 return (func | res_info->resource_func_lower);
120         return func;
121 }
122
123 /*
124  * Helper function to copy the resource params to resource info
125  *  No validation being done in this function.
126  *
127  * resource_info [out] Ptr to resource information
128  * params [in] The input params from the caller
129  * returns none
130  */
131 static void
132 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
133                                struct ulp_flow_db_res_params *params)
134 {
135         uint32_t resource_func;
136
137         resource_info->nxt_resource_idx |= ((params->direction <<
138                                       ULP_FLOW_DB_RES_DIR_BIT) &
139                                      ULP_FLOW_DB_RES_DIR_MASK);
140         resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
141         resource_info->nxt_resource_idx |= ((resource_func <<
142                                              ULP_FLOW_DB_RES_FUNC_BITS) &
143                                             ULP_FLOW_DB_RES_FUNC_MASK);
144
145         if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
146                 /* Break the resource func into two parts */
147                 resource_func = (params->resource_func &
148                                  ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
149                 resource_info->resource_func_lower = resource_func;
150         }
151
152         /* Store the handle as 64bit only for EM table entries */
153         if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE &&
154             params->resource_func != BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
155                 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
156                 resource_info->resource_type = params->resource_type;
157                 resource_info->resource_sub_type = params->resource_sub_type;
158                 resource_info->reserved = params->reserved;
159         } else {
160                 resource_info->resource_em_handle = params->resource_hndl;
161         }
162 }
163
164 /*
165  * Helper function to copy the resource params to resource info
166  *  No validation being done in this function.
167  *
168  * resource_info [in] Ptr to resource information
169  * params [out] The output params to the caller
170  *
171  * returns none
172  */
173 static void
174 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
175                                struct ulp_flow_db_res_params *params)
176 {
177         memset(params, 0, sizeof(struct ulp_flow_db_res_params));
178
179         /* use the helper function to get the resource func */
180         params->direction = ulp_flow_db_resource_dir_get(resource_info);
181         params->resource_func = ulp_flow_db_resource_func_get(resource_info);
182
183         if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
184             params->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_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->reserved = resource_info->reserved;
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         bnxt_ulp_cntxt_mem_type_get(ulp_ctxt, &mtype);
526         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
527                 num_flows = dparms->int_flow_db_num_entries;
528         else
529                 num_flows = dparms->ext_flow_db_num_entries;
530
531         /* Populate the regular flow table limits. */
532         flow_tbl = &flow_db->flow_tbl;
533         flow_tbl->num_flows = num_flows + 1;
534         flow_tbl->num_resources = ((num_flows + 1) *
535                                    dparms->num_resources_per_flow);
536
537         /* Include the default flow table limits. */
538         flow_tbl->num_flows += (BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1);
539         flow_tbl->num_resources += ((BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1) *
540                                     BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
541
542         /* Allocate the resource for the flow table. */
543         if (ulp_flow_db_alloc_resource(flow_db))
544                 goto error_free;
545
546         /* add 1 since we are not using index 0 for flow id */
547         flow_db->func_id_tbl_size = flow_tbl->num_flows + 1;
548         /* Allocate the function Id table */
549         flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
550                                            flow_db->func_id_tbl_size *
551                                            sizeof(uint16_t), 0);
552         if (!flow_db->func_id_tbl) {
553                 BNXT_TF_DBG(ERR,
554                             "Failed to allocate mem for flow table func id\n");
555                 goto error_free;
556         }
557         /* initialize the parent child database */
558         if (ulp_flow_db_parent_tbl_init(flow_db,
559                                         dparms->fdb_parent_flow_entries)) {
560                 BNXT_TF_DBG(ERR,
561                             "Failed to allocate mem for parent child db\n");
562                 goto error_free;
563         }
564
565         /* All good so return. */
566         BNXT_TF_DBG(INFO, "FlowDB initialized with %d flows.\n",
567                     flow_tbl->num_flows);
568         return 0;
569 error_free:
570         ulp_flow_db_deinit(ulp_ctxt);
571         return -ENOMEM;
572 }
573
574 /*
575  * Deinitialize the flow database. Memory is deallocated in
576  * this call and all flows should have been purged before this
577  * call.
578  *
579  * ulp_ctxt [in] Ptr to ulp context
580  *
581  * Returns 0 on success.
582  */
583 int32_t
584 ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
585 {
586         struct bnxt_ulp_flow_db *flow_db;
587
588         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
589         if (!flow_db)
590                 return -EINVAL;
591
592         /* Detach the flow database from the ulp context. */
593         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
594
595         /* Free up all the memory. */
596         ulp_flow_db_parent_tbl_deinit(flow_db);
597         ulp_flow_db_dealloc_resource(flow_db);
598         rte_free(flow_db->func_id_tbl);
599         rte_free(flow_db);
600
601         return 0;
602 }
603
604 /*
605  * Allocate the flow database entry
606  *
607  * ulp_ctxt [in] Ptr to ulp_context
608  * flow_type [in] - specify default or regular
609  * func_id [in].function id of the ingress port
610  * fid [out] The index to the flow entry
611  *
612  * returns 0 on success and negative on failure.
613  */
614 int32_t
615 ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
616                       enum bnxt_ulp_fdb_type flow_type,
617                       uint16_t func_id,
618                       uint32_t *fid)
619 {
620         struct bnxt_ulp_flow_db *flow_db;
621         struct bnxt_ulp_flow_tbl *flow_tbl;
622
623         *fid = 0; /* Initialize fid to invalid value */
624         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
625         if (!flow_db) {
626                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
627                 return -EINVAL;
628         }
629
630         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
631                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
632                 return -EINVAL;
633         }
634
635         flow_tbl = &flow_db->flow_tbl;
636         /* check for max flows */
637         if (flow_tbl->num_flows <= flow_tbl->head_index) {
638                 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
639                 return -ENOMEM;
640         }
641         if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
642                 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
643                 return -ENOMEM;
644         }
645         *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
646         flow_tbl->head_index++;
647
648         /* Set the flow type */
649         ulp_flow_db_active_flows_bit_set(flow_db, flow_type, *fid, 1);
650
651         /* function id update is only valid for regular flow table */
652         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
653                 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
654
655         /* return success */
656         return 0;
657 }
658
659 /*
660  * Allocate the flow database entry.
661  * The params->critical_resource has to be set to 0 to allocate a new resource.
662  *
663  * ulp_ctxt [in] Ptr to ulp_context
664  * flow_type [in] Specify it is regular or default flow
665  * fid [in] The index to the flow entry
666  * params [in] The contents to be copied into resource
667  *
668  * returns 0 on success and negative on failure.
669  */
670 int32_t
671 ulp_flow_db_resource_add(struct bnxt_ulp_context *ulp_ctxt,
672                          enum bnxt_ulp_fdb_type flow_type,
673                          uint32_t fid,
674                          struct ulp_flow_db_res_params *params)
675 {
676         struct bnxt_ulp_flow_db *flow_db;
677         struct bnxt_ulp_flow_tbl *flow_tbl;
678         struct ulp_fdb_resource_info *resource, *fid_resource;
679         uint32_t idx;
680
681         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
682         if (!flow_db) {
683                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
684                 return -EINVAL;
685         }
686
687         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
688                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
689                 return -EINVAL;
690         }
691
692         flow_tbl = &flow_db->flow_tbl;
693         /* check for max flows */
694         if (fid >= flow_tbl->num_flows || !fid) {
695                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
696                 return -EINVAL;
697         }
698
699         /* check if the flow is active or not */
700         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
701                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
702                 return -EINVAL;
703         }
704
705         /* check for max resource */
706         if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
707                 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
708                 return -ENOMEM;
709         }
710         fid_resource = &flow_tbl->flow_resources[fid];
711
712         if (!params->critical_resource) {
713                 /* Not the critical_resource so allocate a resource */
714                 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
715                 resource = &flow_tbl->flow_resources[idx];
716                 flow_tbl->tail_index--;
717
718                 /* Update the chain list of resource*/
719                 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
720                                         fid_resource->nxt_resource_idx);
721                 /* update the contents */
722                 ulp_flow_db_res_params_to_info(resource, params);
723                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
724                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
725                                         idx);
726         } else {
727                 /* critical resource. Just update the fid resource */
728                 ulp_flow_db_res_params_to_info(fid_resource, params);
729         }
730
731         if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
732             params->resource_sub_type ==
733             BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) {
734                 /* Store the first HW counter ID for this table */
735                 if (!ulp_fc_mgr_start_idx_isset(ulp_ctxt, params->direction))
736                         ulp_fc_mgr_start_idx_set(ulp_ctxt, params->direction,
737                                                  params->resource_hndl);
738
739                 ulp_fc_mgr_cntr_set(ulp_ctxt, params->direction,
740                                     params->resource_hndl);
741
742                 if (!ulp_fc_mgr_thread_isstarted(ulp_ctxt))
743                         ulp_fc_mgr_thread_start(ulp_ctxt);
744         }
745
746         /* all good, return success */
747         return 0;
748 }
749
750 /*
751  * Free the flow database entry.
752  * The params->critical_resource has to be set to 1 to free the first resource.
753  *
754  * ulp_ctxt [in] Ptr to ulp_context
755  * flow_type [in] Specify it is regular or default flow
756  * fid [in] The index to the flow entry
757  * params [in/out] The contents to be copied into params.
758  * Onlythe critical_resource needs to be set by the caller.
759  *
760  * Returns 0 on success and negative on failure.
761  */
762 int32_t
763 ulp_flow_db_resource_del(struct bnxt_ulp_context *ulp_ctxt,
764                          enum bnxt_ulp_fdb_type flow_type,
765                          uint32_t fid,
766                          struct ulp_flow_db_res_params *params)
767 {
768         struct bnxt_ulp_flow_db *flow_db;
769         struct bnxt_ulp_flow_tbl *flow_tbl;
770         struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
771         uint32_t nxt_idx = 0;
772         struct bnxt_tun_cache_entry *tun_tbl;
773         uint8_t tun_idx = 0;
774         int rc;
775
776         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
777         if (!flow_db) {
778                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
779                 return -EINVAL;
780         }
781
782         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
783                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
784                 return -EINVAL;
785         }
786
787         flow_tbl = &flow_db->flow_tbl;
788         /* check for max flows */
789         if (fid >= flow_tbl->num_flows || !fid) {
790                 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
791                 return -EINVAL;
792         }
793
794         /* check if the flow is active or not */
795         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
796                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
797                 return -EINVAL;
798         }
799
800         fid_resource = &flow_tbl->flow_resources[fid];
801         if (!params->critical_resource) {
802                 /* Not the critical resource so free the resource */
803                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
804                                         fid_resource->nxt_resource_idx);
805                 if (!nxt_idx) {
806                         /* reached end of resources */
807                         return -ENOENT;
808                 }
809                 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
810
811                 /* connect the fid resource to the next resource */
812                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
813                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
814                                         nxt_resource->nxt_resource_idx);
815
816                 /* update the contents to be given to caller */
817                 ulp_flow_db_res_info_to_params(nxt_resource, params);
818
819                 /* Delete the nxt_resource */
820                 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
821
822                 /* add it to the free list */
823                 flow_tbl->tail_index++;
824                 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
825                         BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
826                         return -ENOENT;
827                 }
828                 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
829
830         } else {
831                 /* Critical resource. copy the contents and exit */
832                 ulp_flow_db_res_info_to_params(fid_resource, params);
833                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
834                                         fid_resource->nxt_resource_idx);
835                 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
836                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
837                                         nxt_idx);
838         }
839
840         /* Now that the HW Flow counter resource is deleted, reset it's
841          * corresponding slot in the SW accumulation table in the Flow Counter
842          * manager
843          */
844         if (params->resource_type == TF_TBL_TYPE_ACT_STATS_64 &&
845             params->resource_sub_type ==
846             BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT) {
847                 ulp_fc_mgr_cntr_reset(ulp_ctxt, params->direction,
848                                       params->resource_hndl);
849         }
850
851         if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW) {
852                 tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(ulp_ctxt);
853                 if (!tun_tbl)
854                         return -EINVAL;
855
856                 rc = ulp_flow_db_parent_tun_idx_get(ulp_ctxt, fid, &tun_idx);
857                 if (rc)
858                         return rc;
859
860                 ulp_clear_tun_entry(tun_tbl, tun_idx);
861         }
862
863         /* all good, return success */
864         return 0;
865 }
866
867 /*
868  * Free the flow database entry
869  *
870  * ulp_ctxt [in] Ptr to ulp_context
871  * flow_type [in] - specify default or regular
872  * fid [in] The index to the flow entry
873  *
874  * returns 0 on success and negative on failure.
875  */
876 int32_t
877 ulp_flow_db_fid_free(struct bnxt_ulp_context *ulp_ctxt,
878                      enum bnxt_ulp_fdb_type flow_type,
879                      uint32_t fid)
880 {
881         struct bnxt_ulp_flow_db *flow_db;
882         struct bnxt_ulp_flow_tbl *flow_tbl;
883
884         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
885         if (!flow_db) {
886                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
887                 return -EINVAL;
888         }
889
890         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
891                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
892                 return -EINVAL;
893         }
894
895         flow_tbl = &flow_db->flow_tbl;
896
897         /* check for limits of fid */
898         if (fid >= flow_tbl->num_flows || !fid) {
899                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
900                 return -EINVAL;
901         }
902
903         /* check if the flow is active or not */
904         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
905                 BNXT_TF_DBG(ERR, "flow does not exist %x:%x\n", flow_type, fid);
906                 return -EINVAL;
907         }
908         flow_tbl->head_index--;
909         if (!flow_tbl->head_index) {
910                 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
911                 return -ENOENT;
912         }
913
914         flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
915
916         /* Clear the flows bitmap */
917         ulp_flow_db_active_flows_bit_set(flow_db, flow_type, fid, 0);
918
919         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR)
920                 ulp_flow_db_func_id_set(flow_db, fid, 0);
921
922         /* all good, return success */
923         return 0;
924 }
925
926 /*
927  *Get the flow database entry details
928  *
929  * ulp_ctxt [in] Ptr to ulp_context
930  * flow_type [in] - specify default or regular
931  * fid [in] The index to the flow entry
932  * nxt_idx [in/out] the index to the next entry
933  * params [out] The contents to be copied into params.
934  *
935  * returns 0 on success and negative on failure.
936  */
937 int32_t
938 ulp_flow_db_resource_get(struct bnxt_ulp_context *ulp_ctxt,
939                          enum bnxt_ulp_fdb_type flow_type,
940                          uint32_t fid,
941                          uint32_t *nxt_idx,
942                          struct ulp_flow_db_res_params *params)
943 {
944         struct bnxt_ulp_flow_db *flow_db;
945         struct bnxt_ulp_flow_tbl *flow_tbl;
946         struct ulp_fdb_resource_info *nxt_resource, *fid_resource;
947
948         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
949         if (!flow_db) {
950                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
951                 return -EINVAL;
952         }
953
954         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
955                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
956                 return -EINVAL;
957         }
958
959         flow_tbl = &flow_db->flow_tbl;
960
961         /* check for limits of fid */
962         if (fid >= flow_tbl->num_flows || !fid) {
963                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
964                 return -EINVAL;
965         }
966
967         /* check if the flow is active or not */
968         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
969                 BNXT_TF_DBG(ERR, "flow does not exist\n");
970                 return -EINVAL;
971         }
972
973         if (!*nxt_idx) {
974                 fid_resource = &flow_tbl->flow_resources[fid];
975                 ulp_flow_db_res_info_to_params(fid_resource, params);
976                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
977                                         fid_resource->nxt_resource_idx);
978         } else {
979                 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
980                 ulp_flow_db_res_info_to_params(nxt_resource, params);
981                 *nxt_idx = 0;
982                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
983                                         nxt_resource->nxt_resource_idx);
984         }
985
986         /* all good, return success */
987         return 0;
988 }
989
990 /*
991  * Get the flow database entry iteratively
992  *
993  * flow_tbl [in] Ptr to flow table
994  * flow_type [in] - specify default or regular
995  * fid [in/out] The index to the flow entry
996  *
997  * returns 0 on success and negative on failure.
998  */
999 static int32_t
1000 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1001                            enum bnxt_ulp_fdb_type flow_type,
1002                            uint32_t *fid)
1003 {
1004         uint32_t lfid = *fid;
1005         uint32_t idx, s_idx, mod_fid;
1006         uint64_t bs;
1007         uint64_t *active_flows;
1008         struct bnxt_ulp_flow_tbl *flowtbl = &flow_db->flow_tbl;
1009
1010         if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) {
1011                 active_flows = flowtbl->active_reg_flows;
1012         } else if (flow_type == BNXT_ULP_FDB_TYPE_DEFAULT) {
1013                 active_flows = flowtbl->active_dflt_flows;
1014         } else {
1015                 BNXT_TF_DBG(ERR, "Invalid flow type %x\n", flow_type);
1016                         return -EINVAL;
1017         }
1018
1019         do {
1020                 /* increment the flow id to find the next valid flow id */
1021                 lfid++;
1022                 if (lfid >= flowtbl->num_flows)
1023                         return -ENOENT;
1024                 idx = lfid / ULP_INDEX_BITMAP_SIZE;
1025                 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
1026                 s_idx = idx;
1027                 while (!(bs = active_flows[idx])) {
1028                         idx++;
1029                         if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
1030                                 return -ENOENT;
1031                 }
1032                 /*
1033                  * remove the previous bits in the bitset bs to find the
1034                  * next non zero bit in the bitset. This needs to be done
1035                  * only if the idx is same as he one you started.
1036                  */
1037                 if (s_idx == idx)
1038                         bs &= (-1UL >> mod_fid);
1039                 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
1040                 if (*fid >= lfid) {
1041                         BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
1042                         return -ENOENT;
1043                 }
1044         } while (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type,
1045                                                       lfid));
1046
1047         /* all good, return success */
1048         *fid = lfid;
1049         return 0;
1050 }
1051
1052 /*
1053  * Flush all flows in the flow database.
1054  *
1055  * ulp_ctxt [in] Ptr to ulp context
1056  * flow_type [in] - specify default or regular
1057  *
1058  * returns 0 on success or negative number on failure
1059  */
1060 int32_t
1061 ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
1062                         enum bnxt_ulp_fdb_type flow_type)
1063 {
1064         uint32_t fid = 0;
1065         struct bnxt_ulp_flow_db *flow_db;
1066
1067         if (!ulp_ctx) {
1068                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
1069                 return -EINVAL;
1070         }
1071
1072         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1073         if (!flow_db) {
1074                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1075                 return -EINVAL;
1076         }
1077         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
1078                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
1079                 return -EINVAL;
1080         }
1081
1082         while (!ulp_flow_db_next_entry_get(flow_db, flow_type, &fid))
1083                 ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
1084
1085         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
1086
1087         return 0;
1088 }
1089
1090 /*
1091  * Flush all flows in the flow database that belong to a device function.
1092  *
1093  * ulp_ctxt [in] Ptr to ulp context
1094  * func_id [in] - The port function id
1095  *
1096  * returns 0 on success or negative number on failure
1097  */
1098 int32_t
1099 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
1100                                 uint16_t func_id)
1101 {
1102         uint32_t flow_id = 0;
1103         struct bnxt_ulp_flow_db *flow_db;
1104
1105         if (!ulp_ctx || !func_id) {
1106                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
1107                 return -EINVAL;
1108         }
1109
1110         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1111         if (!flow_db) {
1112                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1113                 return -EINVAL;
1114         }
1115         if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
1116                 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n");
1117                 return -EINVAL;
1118         }
1119
1120         while (!ulp_flow_db_next_entry_get(flow_db, BNXT_ULP_FDB_TYPE_REGULAR,
1121                                            &flow_id)) {
1122                 if (flow_db->func_id_tbl[flow_id] == func_id)
1123                         ulp_mapper_resources_free(ulp_ctx,
1124                                                   BNXT_ULP_FDB_TYPE_REGULAR,
1125                                                   flow_id);
1126         }
1127         bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
1128         return 0;
1129 }
1130
1131 /*
1132  * Flush all flows in the flow database that are associated with the session.
1133  *
1134  * ulp_ctxt [in] Ptr to ulp context
1135  *
1136  * returns 0 on success or negative number on failure
1137  */
1138 int32_t
1139 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
1140 {
1141         /*
1142          * TBD: Tf core implementation of FW session flush shall change this
1143          * implementation.
1144          */
1145         return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1146 }
1147
1148 /*
1149  * Check that flow id matches the function id or not
1150  *
1151  * ulp_ctxt [in] Ptr to ulp context
1152  * flow_db [in] Ptr to flow table
1153  * func_id [in] The func_id to be set, for reset pass zero.
1154  *
1155  * returns true on success or false on failure
1156  */
1157 bool
1158 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
1159                                uint32_t flow_id,
1160                                uint32_t func_id)
1161 {
1162         struct bnxt_ulp_flow_db *flow_db;
1163
1164         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1165         if (!flow_db) {
1166                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1167                 return false;
1168         }
1169
1170         /* set the function id in the function table */
1171         if (flow_id < flow_db->func_id_tbl_size && func_id &&
1172             flow_db->func_id_tbl[flow_id] == func_id)
1173                 return true;
1174
1175         return false;
1176 }
1177
1178 /*
1179  * Internal api to traverse the resource list within a flow
1180  * and match a resource based on resource func and resource
1181  * sub type. This api should be used only for resources that
1182  * are unique and do not have multiple instances of resource
1183  * func and sub type combination since it will return only
1184  * the first match.
1185  */
1186 static int32_t
1187 ulp_flow_db_resource_params_get(struct bnxt_ulp_context *ulp_ctx,
1188                                 enum bnxt_ulp_fdb_type flow_type,
1189                                 uint32_t flow_id,
1190                                 uint32_t resource_func,
1191                                 uint32_t res_subtype,
1192                                 struct ulp_flow_db_res_params *params)
1193 {
1194         struct bnxt_ulp_flow_db *flow_db;
1195         struct bnxt_ulp_flow_tbl *flow_tbl;
1196         struct ulp_fdb_resource_info *fid_res;
1197         uint32_t res_id;
1198
1199         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
1200         if (!flow_db) {
1201                 BNXT_TF_DBG(ERR, "Flow database not found\n");
1202                 return -EINVAL;
1203         }
1204
1205         if (!params) {
1206                 BNXT_TF_DBG(ERR, "invalid argument\n");
1207                 return -EINVAL;
1208         }
1209
1210         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1211                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1212                 return -EINVAL;
1213         }
1214
1215         flow_tbl = &flow_db->flow_tbl;
1216
1217         /* check for limits of fid */
1218         if (flow_id >= flow_tbl->num_flows || !flow_id) {
1219                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
1220                 return -EINVAL;
1221         }
1222
1223         /* check if the flow is active or not */
1224         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, flow_id)) {
1225                 BNXT_TF_DBG(ERR, "flow does not exist\n");
1226                 return -EINVAL;
1227         }
1228         /* Iterate the resource to get the resource handle */
1229         res_id =  flow_id;
1230         memset(params, 0, sizeof(struct ulp_flow_db_res_params));
1231         while (res_id) {
1232                 fid_res = &flow_tbl->flow_resources[res_id];
1233                 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
1234                         if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
1235                                 if (res_subtype == fid_res->resource_sub_type) {
1236                                         ulp_flow_db_res_info_to_params(fid_res,
1237                                                                        params);
1238                                         return 0;
1239                                 }
1240
1241                         } else if (resource_func ==
1242                                    BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE ||
1243                                    resource_func ==
1244                                    BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) {
1245                                 ulp_flow_db_res_info_to_params(fid_res,
1246                                                                params);
1247                                 return 0;
1248                         }
1249                 }
1250                 res_id = 0;
1251                 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1252         }
1253         return -ENOENT;
1254 }
1255
1256 /*
1257  * Api to get the cfa action pointer from a flow.
1258  *
1259  * ulp_ctxt [in] Ptr to ulp context
1260  * flow_id [in] flow id
1261  * cfa_action [out] The resource handle stored in the flow database
1262  *
1263  * returns 0 on success
1264  */
1265 int32_t
1266 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
1267                                    uint32_t flow_id,
1268                                    uint16_t *cfa_action)
1269 {
1270         uint8_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_VFR_CFA_ACTION;
1271         struct ulp_flow_db_res_params params;
1272         int32_t rc;
1273
1274         rc = ulp_flow_db_resource_params_get(ulp_ctx,
1275                                              BNXT_ULP_FDB_TYPE_DEFAULT,
1276                                              flow_id,
1277                                              BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1278                                              sub_typ, &params);
1279         if (rc) {
1280                 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
1281                             flow_id);
1282                 return -ENOENT;
1283         }
1284         *cfa_action = params.resource_hndl;
1285         return 0;
1286 }
1287
1288 /*
1289  * Allocate the entry in the parent-child database
1290  *
1291  * ulp_ctxt [in] Ptr to ulp_context
1292  * fid [in] The flow id to the flow entry
1293  *
1294  * returns index on success and negative on failure.
1295  */
1296 int32_t
1297 ulp_flow_db_parent_flow_alloc(struct bnxt_ulp_context *ulp_ctxt,
1298                               uint32_t fid)
1299 {
1300         struct bnxt_ulp_flow_db *flow_db;
1301         struct ulp_fdb_parent_child_db *p_pdb;
1302         uint32_t idx, free_idx = 0;
1303
1304         /* validate the arguments */
1305         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid);
1306         if (!flow_db) {
1307                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1308                 return -EINVAL;
1309         }
1310
1311         p_pdb = &flow_db->parent_child_db;
1312         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1313                 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1314                         BNXT_TF_DBG(ERR, "fid is already allocated\n");
1315                         return -EINVAL;
1316                 }
1317                 if (!p_pdb->parent_flow_tbl[idx].parent_fid && !free_idx)
1318                         free_idx = idx + 1;
1319         }
1320         /* no free slots */
1321         if (!free_idx) {
1322                 BNXT_TF_DBG(ERR, "parent child db is full\n");
1323                 return -ENOMEM;
1324         }
1325
1326         free_idx -= 1;
1327         /* set the Fid in the parent child */
1328         p_pdb->parent_flow_tbl[free_idx].parent_fid = fid;
1329         return free_idx;
1330 }
1331
1332 /*
1333  * Free the entry in the parent-child database
1334  *
1335  * ulp_ctxt [in] Ptr to ulp_context
1336  * fid [in] The flow id to the flow entry
1337  *
1338  * returns 0 on success and negative on failure.
1339  */
1340 int32_t
1341 ulp_flow_db_parent_flow_free(struct bnxt_ulp_context *ulp_ctxt,
1342                              uint32_t fid)
1343 {
1344         struct bnxt_ulp_flow_db *flow_db;
1345         struct ulp_fdb_parent_child_db *p_pdb;
1346         uint32_t idx;
1347
1348         /* validate the arguments */
1349         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, fid);
1350         if (!flow_db) {
1351                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1352                 return -EINVAL;
1353         }
1354
1355         p_pdb = &flow_db->parent_child_db;
1356         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1357                 if (p_pdb->parent_flow_tbl[idx].parent_fid == fid) {
1358                         /* free the contents */
1359                         p_pdb->parent_flow_tbl[idx].parent_fid = 0;
1360                         memset(p_pdb->parent_flow_tbl[idx].child_fid_bitset,
1361                                0, p_pdb->child_bitset_size);
1362                         return 0;
1363                 }
1364         }
1365         BNXT_TF_DBG(ERR, "parent entry not found = %x\n", fid);
1366         return -EINVAL;
1367 }
1368
1369 /*
1370  * Set or reset the child flow in the parent-child database
1371  *
1372  * ulp_ctxt [in] Ptr to ulp_context
1373  * parent_fid [in] The flow id of the parent flow entry
1374  * child_fid [in] The flow id of the child flow entry
1375  * set_flag [in] Use 1 for setting child, 0 to reset
1376  *
1377  * returns zero on success and negative on failure.
1378  */
1379 int32_t
1380 ulp_flow_db_parent_child_flow_set(struct bnxt_ulp_context *ulp_ctxt,
1381                                   uint32_t parent_fid,
1382                                   uint32_t child_fid,
1383                                   uint32_t set_flag)
1384 {
1385         struct bnxt_ulp_flow_db *flow_db;
1386         struct ulp_fdb_parent_child_db *p_pdb;
1387         uint32_t idx, a_idx;
1388         uint64_t *t;
1389
1390         /* validate the arguments */
1391         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1392         if (!flow_db) {
1393                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1394                 return -EINVAL;
1395         }
1396
1397         /* check for fid validity */
1398         if (child_fid >= flow_db->flow_tbl.num_flows || !child_fid) {
1399                 BNXT_TF_DBG(ERR, "Invalid child flow index %x\n", child_fid);
1400                 return -EINVAL;
1401         }
1402
1403         p_pdb = &flow_db->parent_child_db;
1404         a_idx = child_fid / ULP_INDEX_BITMAP_SIZE;
1405         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1406                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1407                         t = p_pdb->parent_flow_tbl[idx].child_fid_bitset;
1408                         if (set_flag)
1409                                 ULP_INDEX_BITMAP_SET(t[a_idx], child_fid);
1410                         else
1411                                 ULP_INDEX_BITMAP_RESET(t[a_idx], child_fid);
1412                         return 0;
1413                 }
1414         }
1415         BNXT_TF_DBG(ERR, "Unable to set the parent-child flow %x:%x\n",
1416                     parent_fid, child_fid);
1417         return -1;
1418 }
1419
1420 /*
1421  * Get the parent index from the parent-child database
1422  *
1423  * ulp_ctxt [in] Ptr to ulp_context
1424  * parent_fid [in] The flow id of the parent flow entry
1425  * parent_idx [out] The parent index of parent flow entry
1426  *
1427  * returns zero on success and negative on failure.
1428  */
1429 int32_t
1430 ulp_flow_db_parent_flow_idx_get(struct bnxt_ulp_context *ulp_ctxt,
1431                                 uint32_t parent_fid,
1432                                 uint32_t *parent_idx)
1433 {
1434         struct bnxt_ulp_flow_db *flow_db;
1435         struct ulp_fdb_parent_child_db *p_pdb;
1436         uint32_t idx;
1437
1438         /* validate the arguments */
1439         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1440         if (!flow_db) {
1441                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1442                 return -EINVAL;
1443         }
1444
1445         p_pdb = &flow_db->parent_child_db;
1446         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1447                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1448                         *parent_idx = idx;
1449                         return 0;
1450                 }
1451         }
1452         BNXT_TF_DBG(ERR, "Unable to get the parent flow %x\n", parent_fid);
1453         return -1;
1454 }
1455
1456 /*
1457  * Get the next child flow in the parent-child database
1458  *
1459  * ulp_ctxt [in] Ptr to ulp_context
1460  * parent_fid [in] The flow id of the parent flow entry
1461  * child_fid [in/out] The flow id of the child flow entry
1462  *
1463  * returns zero on success and negative on failure.
1464  * Pass child_fid as zero for first entry.
1465  */
1466 int32_t
1467 ulp_flow_db_parent_child_flow_next_entry_get(struct bnxt_ulp_flow_db *flow_db,
1468                                              uint32_t parent_idx,
1469                                              uint32_t *child_fid)
1470 {
1471         struct ulp_fdb_parent_child_db *p_pdb;
1472         uint32_t idx, s_idx, mod_fid;
1473         uint32_t next_fid = *child_fid;
1474         uint64_t *child_bitset;
1475         uint64_t bs;
1476
1477         /* check for fid validity */
1478         p_pdb = &flow_db->parent_child_db;
1479         if (parent_idx >= p_pdb->entries_count ||
1480             !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1481                 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1482                 return -EINVAL;
1483         }
1484
1485         child_bitset = p_pdb->parent_flow_tbl[parent_idx].child_fid_bitset;
1486         do {
1487                 /* increment the flow id to find the next valid flow id */
1488                 next_fid++;
1489                 if (next_fid >= flow_db->flow_tbl.num_flows)
1490                         return -ENOENT;
1491                 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1492                 mod_fid = next_fid % ULP_INDEX_BITMAP_SIZE;
1493                 s_idx = idx;
1494                 while (!(bs = child_bitset[idx])) {
1495                         idx++;
1496                         if ((idx * ULP_INDEX_BITMAP_SIZE) >=
1497                             flow_db->flow_tbl.num_flows)
1498                                 return -ENOENT;
1499                 }
1500                 /*
1501                  * remove the previous bits in the bitset bs to find the
1502                  * next non zero bit in the bitset. This needs to be done
1503                  * only if the idx is same as he one you started.
1504                  */
1505                 if (s_idx == idx)
1506                         bs &= (-1UL >> mod_fid);
1507                 next_fid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
1508                 if (*child_fid >= next_fid) {
1509                         BNXT_TF_DBG(ERR, "Parent Child Database is corrupt\n");
1510                         return -ENOENT;
1511                 }
1512                 idx = next_fid / ULP_INDEX_BITMAP_SIZE;
1513         } while (!ULP_INDEX_BITMAP_GET(child_bitset[idx], next_fid));
1514         *child_fid = next_fid;
1515         return 0;
1516 }
1517
1518 /*
1519  * Set the counter accumulation in the parent flow
1520  *
1521  * ulp_ctxt [in] Ptr to ulp_context
1522  * parent_idx [in] The parent index of the parent flow entry
1523  *
1524  * returns index on success and negative on failure.
1525  */
1526 static int32_t
1527 ulp_flow_db_parent_flow_count_accum_set(struct bnxt_ulp_context *ulp_ctxt,
1528                                         uint32_t parent_idx)
1529 {
1530         struct bnxt_ulp_flow_db *flow_db;
1531         struct ulp_fdb_parent_child_db *p_pdb;
1532
1533         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1534         if (!flow_db) {
1535                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1536                 return -EINVAL;
1537         }
1538
1539         /* check for parent idx validity */
1540         p_pdb = &flow_db->parent_child_db;
1541         if (parent_idx >= p_pdb->entries_count ||
1542             !p_pdb->parent_flow_tbl[parent_idx].parent_fid) {
1543                 BNXT_TF_DBG(ERR, "Invalid parent flow index %x\n", parent_idx);
1544                 return -EINVAL;
1545         }
1546
1547         p_pdb->parent_flow_tbl[parent_idx].counter_acc = 1;
1548         return 0;
1549 }
1550
1551 /*
1552  * Get the counter accumulation in the parent flow
1553  *
1554  * ulp_ctxt [in] Ptr to ulp_context
1555  * parent_fid [in] The flow id of the parent flow entry
1556  *
1557  * returns 0 if counter accum is set else -1.
1558  */
1559 static int32_t
1560 ulp_flow_db_parent_flow_count_accum_get(struct bnxt_ulp_context *ulp_ctxt,
1561                                         uint32_t parent_fid)
1562 {
1563         struct bnxt_ulp_flow_db *flow_db;
1564         struct ulp_fdb_parent_child_db *p_pdb;
1565         uint32_t idx;
1566
1567         /* validate the arguments */
1568         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1569         if (!flow_db) {
1570                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1571                 return -EINVAL;
1572         }
1573
1574         p_pdb = &flow_db->parent_child_db;
1575         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1576                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1577                         if (p_pdb->parent_flow_tbl[idx].counter_acc)
1578                                 return 0;
1579                         break;
1580                 }
1581         }
1582         return -1;
1583 }
1584
1585 /*
1586  * Orphan the child flow entry
1587  * This is called only for child flows that have
1588  * BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW resource
1589  *
1590  * ulp_ctxt [in] Ptr to ulp_context
1591  * flow_type [in] Specify it is regular or default flow
1592  * fid [in] The index to the flow entry
1593  *
1594  * Returns 0 on success and negative on failure.
1595  */
1596 int32_t
1597 ulp_flow_db_child_flow_reset(struct bnxt_ulp_context *ulp_ctxt,
1598                              enum bnxt_ulp_fdb_type flow_type,
1599                              uint32_t fid)
1600 {
1601         struct bnxt_ulp_flow_db *flow_db;
1602         struct bnxt_ulp_flow_tbl *flow_tbl;
1603         struct ulp_fdb_resource_info *fid_res;
1604         uint32_t res_id = 0;
1605
1606         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1607         if (!flow_db) {
1608                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1609                 return -EINVAL;
1610         }
1611
1612         if (flow_type >= BNXT_ULP_FDB_TYPE_LAST) {
1613                 BNXT_TF_DBG(ERR, "Invalid flow type\n");
1614                 return -EINVAL;
1615         }
1616
1617         flow_tbl = &flow_db->flow_tbl;
1618         /* check for max flows */
1619         if (fid >= flow_tbl->num_flows || !fid) {
1620                 BNXT_TF_DBG(ERR, "Invalid flow index %x\n", fid);
1621                 return -EINVAL;
1622         }
1623
1624         /* check if the flow is active or not */
1625         if (!ulp_flow_db_active_flows_bit_is_set(flow_db, flow_type, fid)) {
1626                 BNXT_TF_DBG(ERR, "flow does not exist\n");
1627                 return -EINVAL;
1628         }
1629
1630         /* Iterate the resource to get the resource handle */
1631         res_id =  fid;
1632         while (res_id) {
1633                 fid_res = &flow_tbl->flow_resources[res_id];
1634                 if (ulp_flow_db_resource_func_get(fid_res) ==
1635                     BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW) {
1636                         /* invalidate the resource details */
1637                         fid_res->resource_hndl = 0;
1638                         return 0;
1639                 }
1640                 res_id = 0;
1641                 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
1642         }
1643         /* failed */
1644         return -1;
1645 }
1646
1647 /*
1648  * Create parent flow in the parent flow tbl
1649  *
1650  * parms [in] Ptr to mapper params
1651  *
1652  * Returns 0 on success and negative on failure.
1653  */
1654 int32_t
1655 ulp_flow_db_parent_flow_create(struct bnxt_ulp_mapper_parms *parms)
1656 {
1657         struct ulp_flow_db_res_params fid_parms;
1658         uint32_t sub_typ = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT_ACC;
1659         struct ulp_flow_db_res_params res_params;
1660         int32_t fid_idx, rc;
1661
1662         /* create the child flow entry in parent flow table */
1663         fid_idx = ulp_flow_db_parent_flow_alloc(parms->ulp_ctx, parms->fid);
1664         if (fid_idx < 0) {
1665                 BNXT_TF_DBG(ERR, "Error in creating parent flow fid %x\n",
1666                             parms->fid);
1667                 return -1;
1668         }
1669
1670         /* Add the parent details in the resource list of the flow */
1671         memset(&fid_parms, 0, sizeof(fid_parms));
1672         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW;
1673         fid_parms.resource_hndl = fid_idx;
1674         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1675         if (ulp_flow_db_resource_add(parms->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR,
1676                                      parms->fid, &fid_parms)) {
1677                 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1678                             parms->fid);
1679                 return -1;
1680         }
1681
1682         /* check of the flow has internal counter accumulation enabled */
1683         if (!ulp_flow_db_resource_params_get(parms->ulp_ctx,
1684                                              BNXT_ULP_FDB_TYPE_REGULAR,
1685                                              parms->fid,
1686                                              BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
1687                                              sub_typ,
1688                                              &res_params)) {
1689                 /* Enable the counter accumulation in parent entry */
1690                 if (ulp_flow_db_parent_flow_count_accum_set(parms->ulp_ctx,
1691                                                             fid_idx)) {
1692                         BNXT_TF_DBG(ERR, "Error in setting counter acc %x\n",
1693                                     parms->fid);
1694                         return -1;
1695                 }
1696         }
1697
1698         rc  = ulp_flow_db_parent_tun_idx_set(parms->ulp_ctx, fid_idx,
1699                                              parms->tun_idx);
1700         if (rc) {
1701                 BNXT_TF_DBG(ERR, "Error setting tun_idx in the parent flow\n");
1702                 return rc;
1703         }
1704
1705         return 0;
1706 }
1707
1708 /*
1709  * Create child flow in the parent flow tbl
1710  *
1711  * parms [in] Ptr to mapper params
1712  *
1713  * Returns 0 on success and negative on failure.
1714  */
1715 int32_t
1716 ulp_flow_db_child_flow_create(struct bnxt_ulp_mapper_parms *parms)
1717 {
1718         struct ulp_flow_db_res_params fid_parms;
1719         uint32_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TABLE_INT_COUNT;
1720         enum bnxt_ulp_resource_func res_fun;
1721         struct ulp_flow_db_res_params res_p;
1722         uint32_t parent_fid = parms->parent_fid;
1723         int32_t rc;
1724
1725         /* create the parent flow entry in parent flow table */
1726         rc = ulp_flow_db_parent_child_flow_set(parms->ulp_ctx,
1727                                                parms->parent_fid,
1728                                                parms->fid, 1);
1729         if (rc) {
1730                 BNXT_TF_DBG(ERR, "Error in setting child fid %x\n", parms->fid);
1731                 return rc;
1732         }
1733
1734         /* Add the parent details in the resource list of the flow */
1735         memset(&fid_parms, 0, sizeof(fid_parms));
1736         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW;
1737         fid_parms.resource_hndl = parms->parent_fid;
1738         fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
1739         rc  = ulp_flow_db_resource_add(parms->ulp_ctx,
1740                                        BNXT_ULP_FDB_TYPE_REGULAR,
1741                                        parms->fid, &fid_parms);
1742         if (rc) {
1743                 BNXT_TF_DBG(ERR, "Error in adding flow res for fid %x\n",
1744                             parms->fid);
1745                 return rc;
1746         }
1747
1748         /* check if accumulation count is set for parent flow */
1749         rc = ulp_flow_db_parent_flow_count_accum_get(parms->ulp_ctx,
1750                                                      parms->parent_fid);
1751         if (!rc) {
1752                 /* check if internal count action included for this flow.*/
1753                 res_fun = BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE;
1754                 rc = ulp_flow_db_resource_params_get(parms->ulp_ctx,
1755                                                      BNXT_ULP_FDB_TYPE_REGULAR,
1756                                                      parms->fid,
1757                                                      res_fun,
1758                                                      sub_type,
1759                                                      &res_p);
1760                 if (!rc) {
1761                         /* update the counter manager to include parent fid */
1762                         if (ulp_fc_mgr_cntr_parent_flow_set(parms->ulp_ctx,
1763                                                             res_p.direction,
1764                                                             res_p.resource_hndl,
1765                                                             parent_fid)) {
1766                                 BNXT_TF_DBG(ERR, "Error in setting child %x\n",
1767                                             parms->fid);
1768                                 return -1;
1769                         }
1770                 }
1771         }
1772         /* return success */
1773         return 0;
1774 }
1775
1776 /*
1777  * Update the parent counters
1778  *
1779  * ulp_ctxt [in] Ptr to ulp_context
1780  * parent_fid [in] The flow id of the parent flow entry
1781  * packet_count [in] - packet count
1782  * byte_count [in] - byte count
1783  *
1784  * returns 0 on success
1785  */
1786 int32_t
1787 ulp_flow_db_parent_flow_count_update(struct bnxt_ulp_context *ulp_ctxt,
1788                                      uint32_t parent_fid,
1789                                      uint64_t packet_count,
1790                                      uint64_t byte_count)
1791 {
1792         struct bnxt_ulp_flow_db *flow_db;
1793         struct ulp_fdb_parent_child_db *p_pdb;
1794         uint32_t idx;
1795
1796         /* validate the arguments */
1797         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1798         if (!flow_db) {
1799                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1800                 return -EINVAL;
1801         }
1802
1803         p_pdb = &flow_db->parent_child_db;
1804         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1805                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1806                         if (p_pdb->parent_flow_tbl[idx].counter_acc) {
1807                                 p_pdb->parent_flow_tbl[idx].pkt_count +=
1808                                         packet_count;
1809                                 p_pdb->parent_flow_tbl[idx].byte_count +=
1810                                         byte_count;
1811                         }
1812                         return 0;
1813                 }
1814         }
1815         return -ENOENT;
1816 }
1817
1818 /*
1819  * Get the parent accumulation counters
1820  *
1821  * ulp_ctxt [in] Ptr to ulp_context
1822  * parent_fid [in] The flow id of the parent flow entry
1823  * packet_count [out] - packet count
1824  * byte_count [out] - byte count
1825  *
1826  * returns 0 on success
1827  */
1828 int32_t
1829 ulp_flow_db_parent_flow_count_get(struct bnxt_ulp_context *ulp_ctxt,
1830                                   uint32_t parent_fid,
1831                                   uint64_t *packet_count,
1832                                   uint64_t *byte_count)
1833 {
1834         struct bnxt_ulp_flow_db *flow_db;
1835         struct ulp_fdb_parent_child_db *p_pdb;
1836         uint32_t idx;
1837
1838         /* validate the arguments */
1839         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, parent_fid);
1840         if (!flow_db) {
1841                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1842                 return -EINVAL;
1843         }
1844
1845         p_pdb = &flow_db->parent_child_db;
1846         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1847                 if (p_pdb->parent_flow_tbl[idx].parent_fid == parent_fid) {
1848                         if (p_pdb->parent_flow_tbl[idx].counter_acc) {
1849                                 *packet_count =
1850                                         p_pdb->parent_flow_tbl[idx].pkt_count;
1851                                 *byte_count =
1852                                         p_pdb->parent_flow_tbl[idx].byte_count;
1853                         }
1854                         return 0;
1855                 }
1856         }
1857         return -ENOENT;
1858 }
1859
1860 /*
1861  * reset the parent accumulation counters
1862  *
1863  * ulp_ctxt [in] Ptr to ulp_context
1864  *
1865  * returns none
1866  */
1867 void
1868 ulp_flow_db_parent_flow_count_reset(struct bnxt_ulp_context *ulp_ctxt)
1869 {
1870         struct bnxt_ulp_flow_db *flow_db;
1871         struct ulp_fdb_parent_child_db *p_pdb;
1872         uint32_t idx;
1873
1874         /* validate the arguments */
1875         flow_db = ulp_flow_db_parent_arg_validation(ulp_ctxt, 1);
1876         if (!flow_db) {
1877                 BNXT_TF_DBG(ERR, "parent child db validation failed\n");
1878                 return;
1879         }
1880
1881         p_pdb = &flow_db->parent_child_db;
1882         for (idx = 0; idx < p_pdb->entries_count; idx++) {
1883                 if (p_pdb->parent_flow_tbl[idx].parent_fid &&
1884                     p_pdb->parent_flow_tbl[idx].counter_acc) {
1885                         p_pdb->parent_flow_tbl[idx].pkt_count = 0;
1886                         p_pdb->parent_flow_tbl[idx].byte_count = 0;
1887                 }
1888         }
1889 }