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