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