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