6e73f25042f32480259143c36a47d0ed6d7bc340
[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
20 /* Macro to copy the nxt_resource_idx */
21 #define ULP_FLOW_DB_RES_NXT_SET(dst, src)       {(dst) |= ((src) &\
22                                          ULP_FLOW_DB_RES_NXT_MASK); }
23 #define ULP_FLOW_DB_RES_NXT_RESET(dst)  ((dst) &= ~(ULP_FLOW_DB_RES_NXT_MASK))
24
25 /*
26  * Helper function to allocate the flow table and initialize
27  *  is set.No validation being done in this function.
28  *
29  * flow_tbl [in] Ptr to flow table
30  * idx [in] The index to bit to be set or reset.
31  *
32  * returns 1 on set or 0 if not set.
33  */
34 static int32_t
35 ulp_flow_db_active_flow_is_set(struct bnxt_ulp_flow_tbl *flow_tbl,
36                                uint32_t                 idx)
37 {
38         uint32_t                active_index;
39
40         active_index = idx / ULP_INDEX_BITMAP_SIZE;
41         return ULP_INDEX_BITMAP_GET(flow_tbl->active_flow_tbl[active_index],
42                                     idx);
43 }
44
45 /*
46  * Helper function to copy the resource params to resource info
47  *  No validation being done in this function.
48  *
49  * resource_info [out] Ptr to resource information
50  * params [in] The input params from the caller
51  * returns none
52  */
53 static void
54 ulp_flow_db_res_params_to_info(struct ulp_fdb_resource_info   *resource_info,
55                                struct ulp_flow_db_res_params  *params)
56 {
57         resource_info->nxt_resource_idx |= ((params->direction <<
58                                       ULP_FLOW_DB_RES_DIR_BIT) &
59                                      ULP_FLOW_DB_RES_DIR_MASK);
60         resource_info->nxt_resource_idx |= ((params->resource_func <<
61                                              ULP_FLOW_DB_RES_FUNC_BITS) &
62                                             ULP_FLOW_DB_RES_FUNC_MASK);
63
64         if (params->resource_func != BNXT_ULP_RESOURCE_FUNC_EM_TABLE) {
65                 resource_info->resource_hndl = (uint32_t)params->resource_hndl;
66                 resource_info->resource_type = params->resource_type;
67
68         } else {
69                 resource_info->resource_em_handle = params->resource_hndl;
70         }
71 }
72
73 /*
74  * Helper function to allocate the flow table and initialize
75  * the stack for allocation operations.
76  *
77  * flow_db [in] Ptr to flow database structure
78  * tbl_idx [in] The index to table creation.
79  *
80  * Returns 0 on success or negative number on failure.
81  */
82 static int32_t
83 ulp_flow_db_alloc_resource(struct bnxt_ulp_flow_db *flow_db,
84                            enum bnxt_ulp_flow_db_tables tbl_idx)
85 {
86         uint32_t                        idx = 0;
87         struct bnxt_ulp_flow_tbl        *flow_tbl;
88         uint32_t                        size;
89
90         flow_tbl = &flow_db->flow_tbl[tbl_idx];
91
92         size = sizeof(struct ulp_fdb_resource_info) * flow_tbl->num_resources;
93         flow_tbl->flow_resources =
94                         rte_zmalloc("ulp_fdb_resource_info", size, 0);
95
96         if (!flow_tbl->flow_resources) {
97                 BNXT_TF_DBG(ERR, "Failed to alloc memory for flow table\n");
98                 return -ENOMEM;
99         }
100         size = sizeof(uint32_t) * flow_tbl->num_resources;
101         flow_tbl->flow_tbl_stack = rte_zmalloc("flow_tbl_stack", size, 0);
102         if (!flow_tbl->flow_tbl_stack) {
103                 BNXT_TF_DBG(ERR, "Failed to alloc memory flow tbl stack\n");
104                 return -ENOMEM;
105         }
106         size = (flow_tbl->num_flows / sizeof(uint64_t)) + 1;
107         flow_tbl->active_flow_tbl = rte_zmalloc("active flow tbl", size, 0);
108         if (!flow_tbl->active_flow_tbl) {
109                 BNXT_TF_DBG(ERR, "Failed to alloc memory active tbl\n");
110                 return -ENOMEM;
111         }
112
113         /* Initialize the stack table. */
114         for (idx = 0; idx < flow_tbl->num_resources; idx++)
115                 flow_tbl->flow_tbl_stack[idx] = idx;
116
117         /* Ignore the first element in the list. */
118         flow_tbl->head_index = 1;
119         /* Tail points to the last entry in the list. */
120         flow_tbl->tail_index = flow_tbl->num_resources - 1;
121         return 0;
122 }
123
124 /*
125  * Helper function to de allocate the flow table.
126  *
127  * flow_db [in] Ptr to flow database structure
128  * tbl_idx [in] The index to table creation.
129  *
130  * Returns none.
131  */
132 static void
133 ulp_flow_db_dealloc_resource(struct bnxt_ulp_flow_db *flow_db,
134                              enum bnxt_ulp_flow_db_tables tbl_idx)
135 {
136         struct bnxt_ulp_flow_tbl        *flow_tbl;
137
138         flow_tbl = &flow_db->flow_tbl[tbl_idx];
139
140         /* Free all the allocated tables in the flow table. */
141         if (flow_tbl->active_flow_tbl) {
142                 rte_free(flow_tbl->active_flow_tbl);
143                 flow_tbl->active_flow_tbl = NULL;
144         }
145
146         if (flow_tbl->flow_tbl_stack) {
147                 rte_free(flow_tbl->flow_tbl_stack);
148                 flow_tbl->flow_tbl_stack = NULL;
149         }
150
151         if (flow_tbl->flow_resources) {
152                 rte_free(flow_tbl->flow_resources);
153                 flow_tbl->flow_resources = NULL;
154         }
155 }
156
157 /*
158  * Initialize the flow database. Memory is allocated in this
159  * call and assigned to the flow database.
160  *
161  * ulp_ctxt [in] Ptr to ulp context
162  *
163  * Returns 0 on success or negative number on failure.
164  */
165 int32_t ulp_flow_db_init(struct bnxt_ulp_context *ulp_ctxt)
166 {
167         struct bnxt_ulp_device_params           *dparms;
168         struct bnxt_ulp_flow_tbl                *flow_tbl;
169         struct bnxt_ulp_flow_db                 *flow_db;
170         uint32_t                                dev_id;
171
172         /* Get the dev specific number of flows that needed to be supported. */
173         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctxt, &dev_id)) {
174                 BNXT_TF_DBG(ERR, "Invalid device id\n");
175                 return -EINVAL;
176         }
177
178         dparms = bnxt_ulp_device_params_get(dev_id);
179         if (!dparms) {
180                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
181                 return -ENODEV;
182         }
183
184         flow_db = rte_zmalloc("bnxt_ulp_flow_db",
185                               sizeof(struct bnxt_ulp_flow_db), 0);
186         if (!flow_db) {
187                 BNXT_TF_DBG(ERR,
188                             "Failed to allocate memory for flow table ptr\n");
189                 goto error_free;
190         }
191
192         /* Attach the flow database to the ulp context. */
193         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, flow_db);
194
195         /* Populate the regular flow table limits. */
196         flow_tbl = &flow_db->flow_tbl[BNXT_ULP_REGULAR_FLOW_TABLE];
197         flow_tbl->num_flows = dparms->num_flows + 1;
198         flow_tbl->num_resources = (flow_tbl->num_flows *
199                                    dparms->num_resources_per_flow);
200
201         /* Populate the default flow table limits. */
202         flow_tbl = &flow_db->flow_tbl[BNXT_ULP_DEFAULT_FLOW_TABLE];
203         flow_tbl->num_flows = BNXT_FLOW_DB_DEFAULT_NUM_FLOWS + 1;
204         flow_tbl->num_resources = (flow_tbl->num_flows *
205                                    BNXT_FLOW_DB_DEFAULT_NUM_RESOURCES);
206
207         /* Allocate the resource for the regular flow table. */
208         if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE))
209                 goto error_free;
210         if (ulp_flow_db_alloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE))
211                 goto error_free;
212
213         /* All good so return. */
214         return 0;
215 error_free:
216         ulp_flow_db_deinit(ulp_ctxt);
217         return -ENOMEM;
218 }
219
220 /*
221  * Deinitialize the flow database. Memory is deallocated in
222  * this call and all flows should have been purged before this
223  * call.
224  *
225  * ulp_ctxt [in] Ptr to ulp context
226  *
227  * Returns 0 on success.
228  */
229 int32_t ulp_flow_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
230 {
231         struct bnxt_ulp_flow_db                 *flow_db;
232
233         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
234         if (!flow_db) {
235                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
236                 return -EINVAL;
237         }
238
239         /* Detach the flow database from the ulp context. */
240         bnxt_ulp_cntxt_ptr2_flow_db_set(ulp_ctxt, NULL);
241
242         /* Free up all the memory. */
243         ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_REGULAR_FLOW_TABLE);
244         ulp_flow_db_dealloc_resource(flow_db, BNXT_ULP_DEFAULT_FLOW_TABLE);
245         rte_free(flow_db);
246
247         return 0;
248 }
249
250 /*
251  * Allocate the flow database entry.
252  * The params->critical_resource has to be set to 0 to allocate a new resource.
253  *
254  * ulp_ctxt [in] Ptr to ulp_context
255  * tbl_idx [in] Specify it is regular or default flow
256  * fid [in] The index to the flow entry
257  * params [in] The contents to be copied into resource
258  *
259  * returns 0 on success and negative on failure.
260  */
261 int32_t ulp_flow_db_resource_add(struct bnxt_ulp_context        *ulp_ctxt,
262                                  enum bnxt_ulp_flow_db_tables   tbl_idx,
263                                  uint32_t                       fid,
264                                  struct ulp_flow_db_res_params  *params)
265 {
266         struct bnxt_ulp_flow_db         *flow_db;
267         struct bnxt_ulp_flow_tbl        *flow_tbl;
268         struct ulp_fdb_resource_info    *resource, *fid_resource;
269         uint32_t                        idx;
270
271         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp_ctxt);
272         if (!flow_db) {
273                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
274                 return -EINVAL;
275         }
276
277         if (tbl_idx >= BNXT_ULP_FLOW_TABLE_MAX) {
278                 BNXT_TF_DBG(ERR, "Invalid table index\n");
279                 return -EINVAL;
280         }
281         flow_tbl = &flow_db->flow_tbl[tbl_idx];
282
283         /* check for max flows */
284         if (fid >= flow_tbl->num_flows || !fid) {
285                 BNXT_TF_DBG(ERR, "Invalid flow index\n");
286                 return -EINVAL;
287         }
288
289         /* check if the flow is active or not */
290         if (!ulp_flow_db_active_flow_is_set(flow_tbl, fid)) {
291                 BNXT_TF_DBG(ERR, "flow does not exist\n");
292                 return -EINVAL;
293         }
294
295         /* check for max resource */
296         if ((flow_tbl->num_flows + 1) >= flow_tbl->tail_index) {
297                 BNXT_TF_DBG(ERR, "Flow db has reached max resources\n");
298                 return -ENOMEM;
299         }
300         fid_resource = &flow_tbl->flow_resources[fid];
301
302         if (!params->critical_resource) {
303                 /* Not the critical_resource so allocate a resource */
304                 idx = flow_tbl->flow_tbl_stack[flow_tbl->tail_index];
305                 resource = &flow_tbl->flow_resources[idx];
306                 flow_tbl->tail_index--;
307
308                 /* Update the chain list of resource*/
309                 ULP_FLOW_DB_RES_NXT_SET(resource->nxt_resource_idx,
310                                         fid_resource->nxt_resource_idx);
311                 /* update the contents */
312                 ulp_flow_db_res_params_to_info(resource, params);
313                 ULP_FLOW_DB_RES_NXT_RESET(fid_resource->nxt_resource_idx);
314                 ULP_FLOW_DB_RES_NXT_SET(fid_resource->nxt_resource_idx,
315                                         idx);
316         } else {
317                 /* critical resource. Just update the fid resource */
318                 ulp_flow_db_res_params_to_info(fid_resource, params);
319         }
320
321         /* all good, return success */
322         return 0;
323 }