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