net/bnxt: rename fields in device params structure
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_flow_db.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2020 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_flow_db.h"
10 #include "ulp_utils.h"
11 #include "ulp_template_struct.h"
12 #include "ulp_mapper.h"
13
14 #define ULP_FLOW_DB_RES_DIR_BIT         31
15 #define ULP_FLOW_DB_RES_DIR_MASK        0x80000000
16 #define ULP_FLOW_DB_RES_FUNC_BITS       28
17 #define ULP_FLOW_DB_RES_FUNC_MASK       0x70000000
18 #define ULP_FLOW_DB_RES_NXT_MASK        0x0FFFFFFF
19 #define ULP_FLOW_DB_RES_FUNC_UPPER      5
20 #define ULP_FLOW_DB_RES_FUNC_NEED_LOWER 0x80
21 #define ULP_FLOW_DB_RES_FUNC_LOWER_MASK 0x1F
22
23 /* Macro to copy the nxt_resource_idx */
24 #define ULP_FLOW_DB_RES_NXT_SET(dst, src)       {(dst) |= ((src) &\
25                                          ULP_FLOW_DB_RES_NXT_MASK); }
26 #define ULP_FLOW_DB_RES_NXT_RESET(dst)  ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
27
28 /*
29  * Helper function to set the bit in the active flow table
30  * No validation is done in this function.
31  *
32  * flow_tbl [in] Ptr to flow table
33  * idx [in] The index to bit to be set or reset.
34  * flag [in] 1 to set and 0 to reset.
35  *
36  * returns none
37  */
38 static void
39 ulp_flow_db_active_flow_set(struct bnxt_ulp_flow_tbl    *flow_tbl,
40                             uint32_t                    idx,
41                             uint32_t                    flag)
42 {
43         uint32_t                active_index;
44
45         active_index = idx / ULP_INDEX_BITMAP_SIZE;
46         if (flag)
47                 ULP_INDEX_BITMAP_SET(flow_tbl->active_flow_tbl[active_index],
48                                      idx);
49         else
50                 ULP_INDEX_BITMAP_RESET(flow_tbl->active_flow_tbl[active_index],
51                                        idx);
52 }
53
54 /*
55  * Helper function to allocate the flow table and initialize
56  * is set.No validation being done in this function.
57  *
58  * flow_tbl [in] Ptr to flow table
59  * idx [in] The index to bit to be set or reset.
60  *
61  * returns 1 on set or 0 if not set.
62  */
63 static int32_t
64 ulp_flow_db_active_flow_is_set(struct bnxt_ulp_flow_tbl *flow_tbl,
65                                uint32_t                 idx)
66 {
67         uint32_t                active_index;
68
69         active_index = idx / ULP_INDEX_BITMAP_SIZE;
70         return ULP_INDEX_BITMAP_GET(flow_tbl->active_flow_tbl[active_index],
71                                     idx);
72 }
73
74 static uint8_t
75 ulp_flow_db_resource_func_get(struct ulp_fdb_resource_info *res_info)
76 {
77         uint8_t func;
78
79         func = (((res_info->nxt_resource_idx & ULP_FLOW_DB_RES_FUNC_MASK) >>
80                  ULP_FLOW_DB_RES_FUNC_BITS) << ULP_FLOW_DB_RES_FUNC_UPPER);
81         /* The reource func is split into upper and lower */
82         if (func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER)
83                 return (func | res_info->resource_func_lower);
84         return func;
85 }
86
87 /*
88  * Helper function to copy the resource params to resource info
89  *  No validation being done in this function.
90  *
91  * resource_info [out] Ptr to resource information
92  * params [in] The input params from the caller
93  * returns none
94  */
95 static void
96 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info *resource_info,
97                                struct ulp_flow_db_res_params *params)
98 {
99         uint32_t resource_func;
100
101         resource_info->nxt_resource_idx |= ((params->direction <<
102                                       ULP_FLOW_DB_RES_DIR_BIT) &
103                                      ULP_FLOW_DB_RES_DIR_MASK);
104         resource_func = (params->resource_func >> ULP_FLOW_DB_RES_FUNC_UPPER);
105         resource_info->nxt_resource_idx |= ((resource_func <<
106                                              ULP_FLOW_DB_RES_FUNC_BITS) &
107                                             ULP_FLOW_DB_RES_FUNC_MASK);
108
109         if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
110                 /* Break the resource func into two parts */
111                 resource_func = (params->resource_func &
112                                  ULP_FLOW_DB_RES_FUNC_LOWER_MASK);
113                 resource_info->resource_func_lower = resource_func;
114         }
115
116         /* Store the handle as 64bit only for EM table entries */
117         if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
118                 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
119                 resource_info->resource_type = params->resource_type;
120                 resource_info->resource_sub_type = params->resource_sub_type;
121                 resource_info->reserved = params->reserved;
122         } else {
123                 resource_info->resource_em_handle = params->resource_hndl;
124         }
125 }
126
127 /*
128  * Helper function to copy the resource params to resource info
129  *  No validation being done in this function.
130  *
131  * resource_info [in] Ptr to resource information
132  * params [out] The output params to the caller
133  *
134  * returns none
135  */
136 static void
137 ulp_flow_db_res_info_to_params(struct ulp_fdb_resource_info *resource_info,
138                                struct ulp_flow_db_res_params *params)
139 {
140         memset(params, 0, sizeof(struct ulp_flow_db_res_params));
141         params->direction = ((resource_info->nxt_resource_idx &
142                                  ULP_FLOW_DB_RES_DIR_MASK) >>
143                                  ULP_FLOW_DB_RES_DIR_BIT);
144
145         /* use the helper function to get the resource func */
146         params->resource_func = ulp_flow_db_resource_func_get(resource_info);
147
148         if (params->resource_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
149                 params->resource_hndl = resource_info->resource_em_handle;
150         } else if (params->resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
151                 params->resource_hndl = resource_info->resource_hndl;
152                 params->resource_type = resource_info->resource_type;
153                 params->resource_sub_type = resource_info->resource_sub_type;
154                 params->reserved = resource_info->reserved;
155         }
156 }
157
158 /*
159  * Helper function to allocate the flow table and initialize
160  * the stack for allocation operations.
161  *
162  * flow_db [in] Ptr to flow database structure
163  * tbl_idx [in] The index to table creation.
164  *
165  * Returns 0 on success or negative number on failure.
166  */
167 static int32_t
168 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db,
169                            enum bnxt_ulp_flow_db_tables tbl_idx)
170 {
171         uint32_t                        idx = 0;
172         struct bnxt_ulp_flow_tbl        *flow_tbl;
173         uint32_t                        size;
174
175         flow_tbl = &flow_db->flow_tbl[tbl_idx];
176
177         size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
178         flow_tbl->flow_resources =
179                         rte_zmalloc("ulp_fdb_resource_info", size, 0);
180
181         if (!flow_tbl->flow_resources) {
182                 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
183                 return -ENOMEM;
184         }
185         size = sizeof(uint32_t) * flow_tbl->num_resources;
186         flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
187         if (!flow_tbl->flow_tbl_stack) {
188                 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
189                 return -ENOMEM;
190         }
191         size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
192         flow_tbl->active_flow_tbl = rte_zmalloc("active flow tbl", size, 0);
193         if (!flow_tbl->active_flow_tbl) {
194                 BNXT_TF_DBG(ERR, "Failed to alloc memory active tbl\n");
195                 return -ENOMEM;
196         }
197
198         /* Initialize the stack table. */
199         for (idx = 0; idx < flow_tbl->num_resources; idx++)
200                 flow_tbl->flow_tbl_stack[idx] = idx;
201
202         /* Ignore the first element in the list. */
203         flow_tbl->head_index = 1;
204         /* Tail points to the last entry in the list. */
205         flow_tbl->tail_index = flow_tbl->num_resources - 1;
206         return 0;
207 }
208
209 /*
210  * Helper function to deallocate the flow table.
211  *
212  * flow_db [in] Ptr to flow database structure
213  * tbl_idx [in] The index to table creation.
214  *
215  * Returns none.
216  */
217 static void
218 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db,
219                              enum bnxt_ulp_flow_db_tables tbl_idx)
220 {
221         struct bnxt_ulp_flow_tbl        *flow_tbl;
222
223         flow_tbl = &flow_db->flow_tbl[tbl_idx];
224
225         /* Free all the allocated tables in the flow table. */
226         if (flow_tbl->active_flow_tbl) {
227                 rte_free(flow_tbl->active_flow_tbl);
228                 flow_tbl->active_flow_tbl = NULL;
229         }
230
231         if (flow_tbl->flow_tbl_stack) {
232                 rte_free(flow_tbl->flow_tbl_stack);
233                 flow_tbl->flow_tbl_stack = NULL;
234         }
235
236         if (flow_tbl->flow_resources) {
237                 rte_free(flow_tbl->flow_resources);
238                 flow_tbl->flow_resources = NULL;
239         }
240 }
241
242 /*
243  * Helper function to add function id to the flow table
244  *
245  * flow_db [in] Ptr to flow table
246  * flow_id [in] The flow id of the flow
247  * func_id [in] The func_id to be set, for reset pass zero
248  *
249  * returns none
250  */
251 static void
252 ulp_flow_db_func_id_set(struct bnxt_ulp_flow_db *flow_db,
253                         uint32_t flow_id,
254                         uint32_t func_id)
255 {
256         /* set the function id in the function table */
257         if (flow_id < flow_db->func_id_tbl_size)
258                 flow_db->func_id_tbl[flow_id] = func_id;
259         else /* This should never happen */
260                 BNXT_TF_DBG(ERR, "Invalid flow id, flowdb corrupt\n");
261 }
262
263 /*
264  * Initialize the flow database. Memory is allocated in this
265  * call and assigned to the flow database.
266  *
267  * ulp_ctxt [in] Ptr to ulp context
268  *
269  * Returns 0 on success or negative number on failure.
270  */
271 int32_t ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
272 {
273         struct bnxt_ulp_device_params           *dparms;
274         struct bnxt_ulp_flow_tbl                *flow_tbl;
275         struct bnxt_ulp_flow_db                 *flow_db;
276         uint32_t                                dev_id;
277
278         /* Get the dev specific number of flows that needed to be supported. */
279         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
280                 BNXT_TF_DBG(ERR, "Invalid device id\n");
281                 return -EINVAL;
282         }
283
284         dparms = bnxt_ulp_device_params_get(dev_id);
285         if (!dparms) {
286                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
287                 return -ENODEV;
288         }
289
290         flow_db = rte_zmalloc("bnxt_ulp_flow_db",
291                               sizeof(struct bnxt_ulp_flow_db), 0);
292         if (!flow_db) {
293                 BNXT_TF_DBG(ERR,
294                             "Failed to allocate memory for flow table ptr\n");
295                 return -ENOMEM;
296         }
297
298         /* Attach the flow database to the ulp context. */
299         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
300
301         /* Populate the regular flow table limits. */
302         flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
303         flow_tbl->num_flows = dparms->flow_db_num_entries + 1;
304         flow_tbl->num_resources = (flow_tbl->num_flows *
305                                    dparms->num_resources_per_flow);
306
307         /* Populate the default flow table limits. */
308         flow_tbl = &flow_db->flow_tbl[BNXT_ULP_DEFAULT_FLOW_TABLE];
309         flow_tbl->num_flows = BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1;
310         flow_tbl->num_resources = (flow_tbl->num_flows *
311                                    BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
312
313         /* Allocate the resource for the regular flow table. */
314         if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE))
315                 goto error_free;
316         if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE))
317                 goto error_free;
318
319         /* add 1 since we are not using index 0 for flow id */
320         flow_db->func_id_tbl_size = dparms->flow_db_num_entries + 1;
321         /* Allocate the function Id table */
322         flow_db->func_id_tbl = rte_zmalloc("bnxt_ulp_flow_db_func_id_table",
323                                            flow_db->func_id_tbl_size *
324                                            sizeof(uint16_t), 0);
325         if (!flow_db->func_id_tbl) {
326                 BNXT_TF_DBG(ERR,
327                             "Failed to allocate mem for flow table func id\n");
328                 goto error_free;
329         }
330         /* All good so return. */
331         return 0;
332 error_free:
333         ulp_flow_db_deinit(ulp_ctxt);
334         return -ENOMEM;
335 }
336
337 /*
338  * Deinitialize the flow database. Memory is deallocated in
339  * this call and all flows should have been purged before this
340  * call.
341  *
342  * ulp_ctxt [in] Ptr to ulp context
343  *
344  * Returns 0 on success.
345  */
346 int32_t ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
347 {
348         struct bnxt_ulp_flow_db                 *flow_db;
349
350         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
351         if (!flow_db) {
352                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
353                 return -EINVAL;
354         }
355
356         /* Detach the flow database from the ulp context. */
357         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
358
359         /* Free up all the memory. */
360         ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
361         ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
362         rte_free(flow_db->func_id_tbl);
363         rte_free(flow_db);
364
365         return 0;
366 }
367
368 /*
369  * Allocate the flow database entry
370  *
371  * ulp_ctxt [in] Ptr to ulp_context
372  * tbl_idx [in] Specify it is regular or default flow
373  * fid [out] The index to the flow entry
374  *
375  * returns 0 on success and negative on failure.
376  */
377 int32_t ulp_flow_db_fid_alloc(struct bnxt_ulp_context *ulp_ctxt,
378                               enum bnxt_ulp_flow_db_tables tbl_idx,
379                               uint16_t func_id,
380                               uint32_t *fid)
381 {
382         struct bnxt_ulp_flow_db *flow_db;
383         struct bnxt_ulp_flow_tbl *flow_tbl;
384
385         *fid = 0; /* Initialize fid to invalid value */
386         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
387         if (!flow_db) {
388                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
389                 return -EINVAL;
390         }
391
392         flow_tbl = &flow_db->flow_tbl[tbl_idx];
393         /* check for max flows */
394         if (flow_tbl->num_flows <= flow_tbl->head_index) {
395                 BNXT_TF_DBG(ERR, "Flow database has reached max flows\n");
396                 return -ENOMEM;
397         }
398         if (flow_tbl->tail_index <= (flow_tbl->head_index + 1)) {
399                 BNXT_TF_DBG(ERR, "Flow database has reached max resources\n");
400                 return -ENOMEM;
401         }
402         *fid = flow_tbl->flow_tbl_stack[flow_tbl->head_index];
403         flow_tbl->head_index++;
404         ulp_flow_db_active_flow_set(flow_tbl, *fid, 1);
405
406         /* The function id update is only valid for regular flow table */
407         if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
408                 ulp_flow_db_func_id_set(flow_db, *fid, func_id);
409
410         /* all good, return success */
411         return 0;
412 }
413
414 /*
415  * Allocate the flow database entry.
416  * The params->critical_resource has to be set to 0 to allocate a new resource.
417  *
418  * ulp_ctxt [in] Ptr to ulp_context
419  * tbl_idx [in] Specify it is regular or default flow
420  * fid [in] The index to the flow entry
421  * params [in] The contents to be copied into resource
422  *
423  * returns 0 on success and negative on failure.
424  */
425 int32_t ulp_flow_db_resource_add(struct bnxt_ulp_context        *ulp_ctxt,
426                                  enum bnxt_ulp_flow_db_tables   tbl_idx,
427                                  uint32_t                       fid,
428                                  struct ulp_flow_db_res_params  *params)
429 {
430         struct bnxt_ulp_flow_db         *flow_db;
431         struct bnxt_ulp_flow_tbl        *flow_tbl;
432         struct ulp_fdb_resource_info    *resource, *fid_resource;
433         uint32_t                        idx;
434
435         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
436         if (!flow_db) {
437                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
438                 return -EINVAL;
439         }
440
441         if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
442                 BNXT_TF_DBG(ERR, "Invalid table index\n");
443                 return -EINVAL;
444         }
445         flow_tbl = &flow_db->flow_tbl[tbl_idx];
446
447         /* check for max flows */
448         if (fid >= flow_tbl->num_flows || !fid) {
449                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
450                 return -EINVAL;
451         }
452
453         /* check if the flow is active or not */
454         if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
455                 BNXT_TF_DBG(ERR, "flow does not exist\n");
456                 return -EINVAL;
457         }
458
459         /* check for max resource */
460         if ((flow_tbl->head_index + 1) >= flow_tbl->tail_index) {
461                 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
462                 return -ENOMEM;
463         }
464         fid_resource = &flow_tbl->flow_resources[fid];
465
466         if (!params->critical_resource) {
467                 /* Not the critical_resource so allocate a resource */
468                 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
469                 resource = &flow_tbl->flow_resources[idx];
470                 flow_tbl->tail_index--;
471
472                 /* Update the chain list of resource*/
473                 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
474                                         fid_resource->nxt_resource_idx);
475                 /* update the contents */
476                 ulp_flow_db_res_params_to_info(resource, params);
477                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
478                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
479                                         idx);
480         } else {
481                 /* critical resource. Just update the fid resource */
482                 ulp_flow_db_res_params_to_info(fid_resource, params);
483         }
484
485         /* all good, return success */
486         return 0;
487 }
488
489 /*
490  * Free the flow database entry.
491  * The params->critical_resource has to be set to 1 to free the first resource.
492  *
493  * ulp_ctxt [in] Ptr to ulp_context
494  * tbl_idx [in] Specify it is regular or default flow
495  * fid [in] The index to the flow entry
496  * params [in/out] The contents to be copied into params.
497  * Onlythe critical_resource needs to be set by the caller.
498  *
499  * Returns 0 on success and negative on failure.
500  */
501 int32_t ulp_flow_db_resource_del(struct bnxt_ulp_context        *ulp_ctxt,
502                                  enum bnxt_ulp_flow_db_tables   tbl_idx,
503                                  uint32_t                       fid,
504                                  struct ulp_flow_db_res_params  *params)
505 {
506         struct bnxt_ulp_flow_db         *flow_db;
507         struct bnxt_ulp_flow_tbl        *flow_tbl;
508         struct ulp_fdb_resource_info    *nxt_resource, *fid_resource;
509         uint32_t                        nxt_idx = 0;
510
511         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
512         if (!flow_db) {
513                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
514                 return -EINVAL;
515         }
516
517         if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
518                 BNXT_TF_DBG(ERR, "Invalid table index\n");
519                 return -EINVAL;
520         }
521         flow_tbl = &flow_db->flow_tbl[tbl_idx];
522
523         /* check for max flows */
524         if (fid >= flow_tbl->num_flows || !fid) {
525                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
526                 return -EINVAL;
527         }
528
529         /* check if the flow is active or not */
530         if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
531                 BNXT_TF_DBG(ERR, "flow does not exist\n");
532                 return -EINVAL;
533         }
534
535         fid_resource = &flow_tbl->flow_resources[fid];
536         if (!params->critical_resource) {
537                 /* Not the critical resource so free the resource */
538                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
539                                         fid_resource->nxt_resource_idx);
540                 if (!nxt_idx) {
541                         /* reached end of resources */
542                         return -ENOENT;
543                 }
544                 nxt_resource = &flow_tbl->flow_resources[nxt_idx];
545
546                 /* connect the fid resource to the next resource */
547                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
548                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
549                                         nxt_resource->nxt_resource_idx);
550
551                 /* update the contents to be given to caller */
552                 ulp_flow_db_res_info_to_params(nxt_resource, params);
553
554                 /* Delete the nxt_resource */
555                 memset(nxt_resource, 0, sizeof(struct ulp_fdb_resource_info));
556
557                 /* add it to the free list */
558                 flow_tbl->tail_index++;
559                 if (flow_tbl->tail_index >= flow_tbl->num_resources) {
560                         BNXT_TF_DBG(ERR, "FlowDB:Tail reached max\n");
561                         return -ENOENT;
562                 }
563                 flow_tbl->flow_tbl_stack[flow_tbl->tail_index] = nxt_idx;
564
565         } else {
566                 /* Critical resource. copy the contents and exit */
567                 ulp_flow_db_res_info_to_params(fid_resource, params);
568                 ULP_FLOW_DB_RES_NXT_SET(nxt_idx,
569                                         fid_resource->nxt_resource_idx);
570                 memset(fid_resource, 0, sizeof(struct ulp_fdb_resource_info));
571                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
572                                         nxt_idx);
573         }
574
575         /* all good, return success */
576         return 0;
577 }
578
579 /*
580  * Free the flow database entry
581  *
582  * ulp_ctxt [in] Ptr to ulp_context
583  * tbl_idx [in] Specify it is regular or default flow
584  * fid [in] The index to the flow entry
585  *
586  * returns 0 on success and negative on failure.
587  */
588 int32_t ulp_flow_db_fid_free(struct bnxt_ulp_context            *ulp_ctxt,
589                              enum bnxt_ulp_flow_db_tables       tbl_idx,
590                              uint32_t                           fid)
591 {
592         struct bnxt_ulp_flow_db         *flow_db;
593         struct bnxt_ulp_flow_tbl        *flow_tbl;
594
595         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
596         if (!flow_db) {
597                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
598                 return -EINVAL;
599         }
600
601         if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
602                 BNXT_TF_DBG(ERR, "Invalid table index\n");
603                 return -EINVAL;
604         }
605
606         flow_tbl = &flow_db->flow_tbl[tbl_idx];
607
608         /* check for limits of fid */
609         if (fid >= flow_tbl->num_flows || !fid) {
610                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
611                 return -EINVAL;
612         }
613
614         /* check if the flow is active or not */
615         if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
616                 BNXT_TF_DBG(ERR, "flow does not exist\n");
617                 return -EINVAL;
618         }
619         flow_tbl->head_index--;
620         if (!flow_tbl->head_index) {
621                 BNXT_TF_DBG(ERR, "FlowDB: Head Ptr is zero\n");
622                 return -ENOENT;
623         }
624         flow_tbl->flow_tbl_stack[flow_tbl->head_index] = fid;
625         ulp_flow_db_active_flow_set(flow_tbl, fid, 0);
626         if (tbl_idx == BNXT_ULP_REGULAR_FLOW_TABLE)
627                 ulp_flow_db_func_id_set(flow_db, fid, 0);
628
629         /* all good, return success */
630         return 0;
631 }
632
633 /*
634  * Get the flow database entry details
635  *
636  * ulp_ctxt [in] Ptr to ulp_context
637  * tbl_idx [in] Specify it is regular or default flow
638  * fid [in] The index to the flow entry
639  * nxt_idx [in/out] the index to the next entry
640  * params [out] The contents to be copied into params.
641  *
642  * returns 0 on success and negative on failure.
643  */
644 int32_t ulp_flow_db_resource_get(struct bnxt_ulp_context        *ulp_ctxt,
645                                  enum bnxt_ulp_flow_db_tables   tbl_idx,
646                                  uint32_t                       fid,
647                                  uint32_t                       *nxt_idx,
648                                  struct ulp_flow_db_res_params  *params)
649 {
650         struct bnxt_ulp_flow_db         *flow_db;
651         struct bnxt_ulp_flow_tbl        *flow_tbl;
652         struct ulp_fdb_resource_info    *nxt_resource, *fid_resource;
653
654         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
655         if (!flow_db) {
656                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
657                 return -EINVAL;
658         }
659
660         if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
661                 BNXT_TF_DBG(ERR, "Invalid table index\n");
662                 return -EINVAL;
663         }
664
665         flow_tbl = &flow_db->flow_tbl[tbl_idx];
666
667         /* check for limits of fid */
668         if (fid >= flow_tbl->num_flows || !fid) {
669                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
670                 return -EINVAL;
671         }
672
673         /* check if the flow is active or not */
674         if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
675                 BNXT_TF_DBG(ERR, "flow does not exist\n");
676                 return -EINVAL;
677         }
678
679         if (!*nxt_idx) {
680                 fid_resource = &flow_tbl->flow_resources[fid];
681                 ulp_flow_db_res_info_to_params(fid_resource, params);
682                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
683                                         fid_resource->nxt_resource_idx);
684         } else {
685                 nxt_resource = &flow_tbl->flow_resources[*nxt_idx];
686                 ulp_flow_db_res_info_to_params(nxt_resource, params);
687                 *nxt_idx = 0;
688                 ULP_FLOW_DB_RES_NXT_SET(*nxt_idx,
689                                         nxt_resource->nxt_resource_idx);
690         }
691
692         /* all good, return success */
693         return 0;
694 }
695
696 /*
697  * Get the flow database entry iteratively
698  *
699  * flow_tbl [in] Ptr to flow table
700  * fid [in/out] The index to the flow entry
701  *
702  * returns 0 on success and negative on failure.
703  */
704 static int32_t
705 ulp_flow_db_next_entry_get(struct bnxt_ulp_flow_tbl     *flowtbl,
706                            uint32_t                     *fid)
707 {
708         uint32_t        lfid = *fid;
709         uint32_t        idx, s_idx, mod_fid;
710         uint64_t        bs;
711
712         do {
713                 /* increment the flow id to find the next valid flow id */
714                 lfid++;
715                 if (lfid >= flowtbl->num_flows)
716                         return -ENOENT;
717                 idx = lfid / ULP_INDEX_BITMAP_SIZE;
718                 mod_fid = lfid % ULP_INDEX_BITMAP_SIZE;
719                 s_idx = idx;
720                 while (!(bs = flowtbl->active_flow_tbl[idx])) {
721                         idx++;
722                         if ((idx * ULP_INDEX_BITMAP_SIZE) >= flowtbl->num_flows)
723                                 return -ENOENT;
724                 }
725                 /*
726                  * remove the previous bits in the bitset bs to find the
727                  * next non zero bit in the bitset. This needs to be done
728                  * only if the idx is same as he one you started.
729                  */
730                 if (s_idx == idx)
731                         bs &= (-1UL >> mod_fid);
732                 lfid = (idx * ULP_INDEX_BITMAP_SIZE) + __builtin_clzl(bs);
733                 if (*fid >= lfid) {
734                         BNXT_TF_DBG(ERR, "Flow Database is corrupt\n");
735                         return -ENOENT;
736                 }
737         } while (!ulp_flow_db_active_flow_is_set(flowtbl, lfid));
738
739         /* all good, return success */
740         *fid = lfid;
741         return 0;
742 }
743
744 /*
745  * Flush all flows in the flow database.
746  *
747  * ulp_ctxt [in] Ptr to ulp context
748  * tbl_idx [in] The index to table
749  *
750  * returns 0 on success or negative number on failure
751  */
752 int32_t ulp_flow_db_flush_flows(struct bnxt_ulp_context *ulp_ctx,
753                                 uint32_t                idx)
754 {
755         uint32_t                        fid = 0;
756         struct bnxt_ulp_flow_db         *flow_db;
757         struct bnxt_ulp_flow_tbl        *flow_tbl;
758
759         if (!ulp_ctx) {
760                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
761                 return -EINVAL;
762         }
763
764         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
765         if (!flow_db) {
766                 BNXT_TF_DBG(ERR, "Flow database not found\n");
767                 return -EINVAL;
768         }
769         flow_tbl = &flow_db->flow_tbl[idx];
770         while (!ulp_flow_db_next_entry_get(flow_tbl, &fid))
771                 ulp_mapper_resources_free(ulp_ctx, fid, idx);
772
773         return 0;
774 }
775
776 /*
777  * Flush all flows in the flow database that belong to a device function.
778  *
779  * ulp_ctxt [in] Ptr to ulp context
780  * tbl_idx [in] The index to table
781  *
782  * returns 0 on success or negative number on failure
783  */
784 int32_t
785 ulp_flow_db_function_flow_flush(struct bnxt_ulp_context *ulp_ctx,
786                                 uint16_t func_id)
787 {
788         uint32_t flow_id = 0;
789         struct bnxt_ulp_flow_db *flow_db;
790         struct bnxt_ulp_flow_tbl *flow_tbl;
791
792         if (!ulp_ctx || !func_id) {
793                 BNXT_TF_DBG(ERR, "Invalid Argument\n");
794                 return -EINVAL;
795         }
796
797         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
798         if (!flow_db) {
799                 BNXT_TF_DBG(ERR, "Flow database not found\n");
800                 return -EINVAL;
801         }
802         flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
803         while (!ulp_flow_db_next_entry_get(flow_tbl, &flow_id)) {
804                 if (flow_db->func_id_tbl[flow_id] == func_id)
805                         ulp_mapper_resources_free(ulp_ctx, flow_id,
806                                                   BNXT_ULP_REGULAR_FLOW_TABLE);
807         }
808
809         return 0;
810 }
811
812 /*
813  * Flush all flows in the flow database that are associated with the session.
814  *
815  * ulp_ctxt [in] Ptr to ulp context
816  *
817  * returns 0 on success or negative number on failure
818  */
819 int32_t
820 ulp_flow_db_session_flow_flush(struct bnxt_ulp_context *ulp_ctx)
821 {
822         /*
823          * TBD: Tf core implementation of FW session flush shall change this
824          * implementation.
825          */
826         return ulp_flow_db_flush_flows(ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
827 }
828
829 /*
830  * Check that flow id matches the function id or not
831  *
832  * ulp_ctxt [in] Ptr to ulp context
833  * flow_db [in] Ptr to flow table
834  * func_id [in] The func_id to be set, for reset pass zero.
835  *
836  * returns true on success or false on failure
837  */
838 bool
839 ulp_flow_db_validate_flow_func(struct bnxt_ulp_context *ulp_ctx,
840                                uint32_t flow_id,
841                                uint32_t func_id)
842 {
843         struct bnxt_ulp_flow_db *flow_db;
844
845         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
846         if (!flow_db) {
847                 BNXT_TF_DBG(ERR, "Flow database not found\n");
848                 return false;
849         }
850
851         /* set the function id in the function table */
852         if (flow_id < flow_db->func_id_tbl_size && func_id &&
853             flow_db->func_id_tbl[flow_id] == func_id)
854                 return true;
855
856         return false;
857 }
858
859 /*
860  * Internal api to traverse the resource list within a flow
861  * and match a resource based on resource func and resource
862  * sub type. This api should be used only for resources that
863  * are unique and do not have multiple instances of resource
864  * func and sub type combination since it will return only
865  * the first match.
866  */
867 static int32_t
868 ulp_flow_db_resource_hndl_get(struct bnxt_ulp_context *ulp_ctx,
869                               enum bnxt_ulp_flow_db_tables tbl_idx,
870                               uint32_t flow_id,
871                               uint32_t resource_func,
872                               uint32_t res_subtype,
873                               uint64_t *res_hndl)
874 {
875         struct bnxt_ulp_flow_db *flow_db;
876         struct bnxt_ulp_flow_tbl *flow_tbl;
877         struct ulp_fdb_resource_info *fid_res;
878         uint32_t res_id;
879
880         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctx);
881         if (!flow_db) {
882                 BNXT_TF_DBG(ERR, "Flow database not found\n");
883                 return -EINVAL;
884         }
885
886         flow_tbl = &flow_db->flow_tbl[tbl_idx];
887
888         /* check for limits of fid */
889         if (flow_id >= flow_tbl->num_flows || !flow_id) {
890                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
891                 return -EINVAL;
892         }
893
894         /* check if the flow is active or not */
895         if (!ulp_flow_db_active_flow_is_set(flow_tbl, flow_id)) {
896                 BNXT_TF_DBG(ERR, "flow does not exist\n");
897                 return -EINVAL;
898         }
899         /* Iterate the resource to get the resource handle */
900         res_id =  flow_id;
901         while (res_id) {
902                 fid_res = &flow_tbl->flow_resources[res_id];
903                 if (ulp_flow_db_resource_func_get(fid_res) == resource_func) {
904                         if (resource_func & ULP_FLOW_DB_RES_FUNC_NEED_LOWER) {
905                                 if (res_subtype == fid_res->resource_sub_type) {
906                                         *res_hndl = fid_res->resource_hndl;
907                                         return 0;
908                                 }
909
910                         } else if (resource_func ==
911                                    BNXT_ULP_RESOURCE_FUNC_EM_TABLE){
912                                 *res_hndl = fid_res->resource_em_handle;
913                                 return 0;
914                         }
915                 }
916                 res_id = 0;
917                 ULP_FLOW_DB_RES_NXT_SET(res_id, fid_res->nxt_resource_idx);
918         }
919         return -ENOENT;
920 }
921
922 /*
923  * Api to get the cfa action pointer from a flow.
924  *
925  * ulp_ctxt [in] Ptr to ulp context
926  * flow_id [in] flow id
927  * cfa_action [out] The resource handle stored in the flow database
928  *
929  * returns 0 on success
930  */
931 int32_t
932 ulp_default_flow_db_cfa_action_get(struct bnxt_ulp_context *ulp_ctx,
933                                    uint32_t flow_id,
934                                    uint32_t *cfa_action)
935 {
936         uint8_t sub_type = BNXT_ULP_RESOURCE_SUB_TYPE_INDEX_TYPE_VFR_ACT_IDX;
937         uint64_t hndl;
938         int32_t rc;
939
940         rc = ulp_flow_db_resource_hndl_get(ulp_ctx,
941                                            BNXT_ULP_DEFAULT_FLOW_TABLE,
942                                            flow_id,
943                                            BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE,
944                                            sub_type, &hndl);
945         if (rc) {
946                 BNXT_TF_DBG(ERR, "CFA Action ptr not found for flow id %u\n",
947                             flow_id);
948                 return -ENOENT;
949         }
950         *cfa_action = hndl;
951         return 0;
952 }
953
954 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
955 /*
956  * Dump the entry details
957  *
958  * ulp_ctxt [in] Ptr to ulp_context
959  *
960  * returns none
961  */
962 static void ulp_flow_db_res_dump(struct ulp_fdb_resource_info   *r,
963                                  uint32_t       *nxt_res)
964 {
965         uint8_t res_func = ulp_flow_db_resource_func_get(r);
966
967         BNXT_TF_DBG(DEBUG, "Resource func = %x, nxt_resource_idx = %x\n",
968                     res_func, (ULP_FLOW_DB_RES_NXT_MASK & r->nxt_resource_idx));
969         if (res_func == BNXT_ULP_RESOURCE_FUNC_EM_TABLE)
970                 BNXT_TF_DBG(DEBUG, "EM Handle = 0x%016" PRIX64 "\n",
971                             r->resource_em_handle);
972         else
973                 BNXT_TF_DBG(DEBUG, "Handle = 0x%08x\n", r->resource_hndl);
974
975         *nxt_res = 0;
976         ULP_FLOW_DB_RES_NXT_SET(*nxt_res,
977                                 r->nxt_resource_idx);
978 }
979
980 /*
981  * Dump the flow database entry details
982  *
983  * ulp_ctxt [in] Ptr to ulp_context
984  *
985  * returns none
986  */
987 int32_t ulp_flow_db_debug_dump(struct bnxt_ulp_context  *ulp_ctxt)
988 {
989         struct bnxt_ulp_flow_db         *flow_db;
990         struct bnxt_ulp_flow_tbl        *flow_tbl;
991         struct ulp_fdb_resource_info    *r;
992         uint32_t                        nxt_res = 0;
993         enum bnxt_ulp_flow_db_tables    tbl_idx;
994         uint32_t                        fid;
995
996         if (!ulp_ctxt || !ulp_ctxt->cfg_data) {
997                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
998                 return -EINVAL;
999         }
1000         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
1001         if (!flow_db) {
1002                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
1003                 return -EINVAL;
1004         }
1005
1006         for (tbl_idx = 0; tbl_idx < BNXT_ULP_FLOW_TABLE_MAX; tbl_idx++) {
1007                 flow_tbl = &flow_db->flow_tbl[tbl_idx];
1008                 BNXT_TF_DBG(DEBUG, "Dump Tbl index = %u, flows = %u:%u\n",
1009                             tbl_idx, flow_tbl->num_flows,
1010                             flow_tbl->num_resources);
1011                 BNXT_TF_DBG(DEBUG, "Head_index = %u, Tail_index = %u\n",
1012                             flow_tbl->head_index, flow_tbl->tail_index);
1013                 for (fid = 0; fid < flow_tbl->num_flows; fid++) {
1014                         if (ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
1015                                 BNXT_TF_DBG(DEBUG, "fid = %u\n", fid);
1016                                 /* iterate the resource */
1017                                 nxt_res = fid;
1018                                 do {
1019                                         r = &flow_tbl->flow_resources[nxt_res];
1020                                         ulp_flow_db_res_dump(r, &nxt_res);
1021                                 } while (nxt_res);
1022                         }
1023                 }
1024                 BNXT_TF_DBG(DEBUG, "Done.\n");
1025         }
1026         return 0;
1027 }
1028 #endif