5a100ef1de65b6f1cdaed4f31184d943774c9d95
[dpdk.git] / drivers / net / bnxt / tf_core / tf_em_internal.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <string.h>
7 #include <rte_common.h>
8 #include <rte_errno.h>
9 #include <rte_log.h>
10
11 #include "tf_core.h"
12 #include "tf_util.h"
13 #include "tf_common.h"
14 #include "tf_em.h"
15 #include "tf_msg.h"
16 #include "tfp.h"
17 #include "tf_ext_flow_handle.h"
18
19 #include "bnxt.h"
20
21 #define TF_EM_DB_EM_REC 0
22
23 /**
24  * Init flag, set on bind and cleared on unbind
25  */
26 static uint8_t init;
27
28 /**
29  * EM Pool
30  */
31 struct stack em_pool[TF_DIR_MAX];
32
33 /**
34  * Create EM Tbl pool of memory indexes.
35  *
36  * [in] dir
37  *   direction
38  * [in] num_entries
39  *   number of entries to write
40  * [in] start
41  *   starting offset
42  *
43  * Return:
44  *  0       - Success, entry allocated - no search support
45  *  -ENOMEM -EINVAL -EOPNOTSUPP
46  *          - Failure, entry not allocated, out of resources
47  */
48 static int
49 tf_create_em_pool(enum tf_dir dir,
50                   uint32_t num_entries,
51                   uint32_t start)
52 {
53         struct tfp_calloc_parms parms;
54         uint32_t i, j;
55         int rc = 0;
56         struct stack *pool = &em_pool[dir];
57
58         /* Assumes that num_entries has been checked before we get here */
59         parms.nitems = num_entries / TF_SESSION_EM_ENTRY_SIZE;
60         parms.size = sizeof(uint32_t);
61         parms.alignment = 0;
62
63         rc = tfp_calloc(&parms);
64
65         if (rc) {
66                 TFP_DRV_LOG(ERR,
67                             "%s, EM pool allocation failure %s\n",
68                             tf_dir_2_str(dir),
69                             strerror(-rc));
70                 return rc;
71         }
72
73         /* Create empty stack
74          */
75         rc = stack_init(num_entries / TF_SESSION_EM_ENTRY_SIZE,
76                         (uint32_t *)parms.mem_va,
77                         pool);
78
79         if (rc) {
80                 TFP_DRV_LOG(ERR,
81                             "%s, EM pool stack init failure %s\n",
82                             tf_dir_2_str(dir),
83                             strerror(-rc));
84                 goto cleanup;
85         }
86
87         /* Fill pool with indexes
88          */
89         j = start + num_entries - TF_SESSION_EM_ENTRY_SIZE;
90
91         for (i = 0; i < (num_entries / TF_SESSION_EM_ENTRY_SIZE); i++) {
92                 rc = stack_push(pool, j);
93                 if (rc) {
94                         TFP_DRV_LOG(ERR,
95                                     "%s, EM pool stack push failure %s\n",
96                                     tf_dir_2_str(dir),
97                                     strerror(-rc));
98                         goto cleanup;
99                 }
100
101                 j -= TF_SESSION_EM_ENTRY_SIZE;
102         }
103
104         if (!stack_is_full(pool)) {
105                 rc = -EINVAL;
106                 TFP_DRV_LOG(ERR,
107                             "%s, EM pool stack failure %s\n",
108                             tf_dir_2_str(dir),
109                             strerror(-rc));
110                 goto cleanup;
111         }
112
113         return 0;
114 cleanup:
115         tfp_free((void *)parms.mem_va);
116         return rc;
117 }
118
119 /**
120  * Create EM Tbl pool of memory indexes.
121  *
122  * [in] dir
123  *   direction
124  *
125  * Return:
126  */
127 static void
128 tf_free_em_pool(enum tf_dir dir)
129 {
130         struct stack *pool = &em_pool[dir];
131         uint32_t *ptr;
132
133         ptr = stack_items(pool);
134
135         if (ptr != NULL)
136                 tfp_free(ptr);
137 }
138
139 /**
140  * Insert EM internal entry API
141  *
142  *  returns:
143  *     0 - Success
144  */
145 int
146 tf_em_insert_int_entry(struct tf *tfp,
147                        struct tf_insert_em_entry_parms *parms)
148 {
149         int rc;
150         uint32_t gfid;
151         uint16_t rptr_index = 0;
152         uint8_t rptr_entry = 0;
153         uint8_t num_of_entries = 0;
154         struct stack *pool = &em_pool[parms->dir];
155         uint32_t index;
156
157         rc = stack_pop(pool, &index);
158
159         if (rc) {
160                 PMD_DRV_LOG(ERR,
161                             "%s, EM entry index allocation failed\n",
162                             tf_dir_2_str(parms->dir));
163                 return rc;
164         }
165
166         rptr_index = index;
167         rc = tf_msg_insert_em_internal_entry(tfp,
168                                              parms,
169                                              &rptr_index,
170                                              &rptr_entry,
171                                              &num_of_entries);
172         if (rc) {
173                 /* Free the allocated index before returning */
174                 stack_push(pool, index);
175                 return -1;
176         }
177
178         PMD_DRV_LOG
179                   (DEBUG,
180                    "%s, Internal entry @ Index:%d rptr_index:0x%x rptr_entry:0x%x num_of_entries:%d\n",
181                    tf_dir_2_str(parms->dir),
182                    index,
183                    rptr_index,
184                    rptr_entry,
185                    num_of_entries);
186
187         TF_SET_GFID(gfid,
188                     ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
189                      rptr_entry),
190                     0); /* N/A for internal table */
191
192         TF_SET_FLOW_ID(parms->flow_id,
193                        gfid,
194                        TF_GFID_TABLE_INTERNAL,
195                        parms->dir);
196
197         TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
198                                      (uint32_t)num_of_entries,
199                                      0,
200                                      TF_FLAGS_FLOW_HANDLE_INTERNAL,
201                                      rptr_index,
202                                      rptr_entry,
203                                      0);
204         return 0;
205 }
206
207
208 /** Delete EM internal entry API
209  *
210  * returns:
211  * 0
212  * -EINVAL
213  */
214 int
215 tf_em_delete_int_entry(struct tf *tfp,
216                        struct tf_delete_em_entry_parms *parms)
217 {
218         int rc = 0;
219         struct stack *pool = &em_pool[parms->dir];
220
221         rc = tf_msg_delete_em_entry(tfp, parms);
222
223         /* Return resource to pool */
224         if (rc == 0)
225                 stack_push(pool, parms->index);
226
227         return rc;
228 }
229
230 int
231 tf_em_int_bind(struct tf *tfp,
232                struct tf_em_cfg_parms *parms)
233 {
234         int rc;
235         int i;
236         struct tf_rm_create_db_parms db_cfg = { 0 };
237         uint8_t db_exists = 0;
238         struct tf_rm_get_alloc_info_parms iparms;
239         struct tf_rm_alloc_info info;
240         struct em_rm_db *em_db;
241         struct tfp_calloc_parms cparms;
242
243         TF_CHECK_PARMS2(tfp, parms);
244
245         if (init) {
246                 TFP_DRV_LOG(ERR,
247                             "EM Int DB already initialized\n");
248                 return -EINVAL;
249         }
250
251         memset(&db_cfg, 0, sizeof(db_cfg));
252         cparms.nitems = 1;
253         cparms.size = sizeof(struct em_rm_db);
254         cparms.alignment = 0;
255         if (tfp_calloc(&cparms) != 0) {
256                 TFP_DRV_LOG(ERR, "em_rm_db alloc error %s\n",
257                             strerror(ENOMEM));
258                 return -ENOMEM;
259         }
260
261         em_db = cparms.mem_va;
262         for (i = 0; i < TF_DIR_MAX; i++)
263                 em_db->em_db[i] = NULL;
264         tf_session_set_db(tfp, TF_MODULE_TYPE_EM, em_db);
265
266         db_cfg.module = TF_MODULE_TYPE_EM;
267         db_cfg.num_elements = parms->num_elements;
268         db_cfg.cfg = parms->cfg;
269
270         for (i = 0; i < TF_DIR_MAX; i++) {
271                 db_cfg.dir = i;
272                 db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
273
274                 /* Check if we got any request to support EEM, if so
275                  * we build an EM Int DB holding Table Scopes.
276                  */
277                 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] == 0)
278                         continue;
279
280                 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] %
281                     TF_SESSION_EM_ENTRY_SIZE != 0) {
282                         rc = -ENOMEM;
283                         TFP_DRV_LOG(ERR,
284                                     "%s, EM Allocation must be in blocks of %d, failure %s\n",
285                                     tf_dir_2_str(i),
286                                     TF_SESSION_EM_ENTRY_SIZE,
287                                     strerror(-rc));
288
289                         return rc;
290                 }
291
292                 db_cfg.rm_db = (void *)&em_db->em_db[i];
293
294                 rc = tf_rm_create_db(tfp, &db_cfg);
295                 if (rc) {
296                         TFP_DRV_LOG(ERR,
297                                     "%s: EM Int DB creation failed\n",
298                                     tf_dir_2_str(i));
299
300                         return rc;
301                 }
302                 db_exists = 1;
303         }
304
305         if (db_exists)
306                 init = 1;
307
308         for (i = 0; i < TF_DIR_MAX; i++) {
309                 iparms.rm_db = em_db->em_db[i];
310                 iparms.subtype = TF_EM_DB_EM_REC;
311                 iparms.info = &info;
312
313                 rc = tf_rm_get_info(&iparms);
314                 if (rc) {
315                         TFP_DRV_LOG(ERR,
316                                     "%s: EM DB get info failed\n",
317                                     tf_dir_2_str(i));
318                         return rc;
319                 }
320
321                 rc = tf_create_em_pool(i,
322                                        iparms.info->entry.stride,
323                                        iparms.info->entry.start);
324                 /* Logging handled in tf_create_em_pool */
325                 if (rc)
326                         return rc;
327         }
328
329
330         return 0;
331 }
332
333 int
334 tf_em_int_unbind(struct tf *tfp)
335 {
336         int rc;
337         int i;
338         struct tf_rm_free_db_parms fparms = { 0 };
339         struct em_rm_db *em_db;
340         void *em_db_ptr = NULL;
341
342         TF_CHECK_PARMS1(tfp);
343
344         /* Bail if nothing has been initialized */
345         if (!init) {
346                 TFP_DRV_LOG(INFO,
347                             "No EM Int DBs created\n");
348                 return 0;
349         }
350
351         for (i = 0; i < TF_DIR_MAX; i++)
352                 tf_free_em_pool(i);
353
354         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
355         if (rc) {
356                 TFP_DRV_LOG(ERR,
357                             "Failed to get em_ext_db from session, rc:%s\n",
358                             strerror(-rc));
359                 return rc;
360         }
361         em_db = (struct em_rm_db *)em_db_ptr;
362
363         for (i = 0; i < TF_DIR_MAX; i++) {
364                 fparms.dir = i;
365                 fparms.rm_db = em_db->em_db[i];
366                 if (em_db->em_db[i] != NULL) {
367                         rc = tf_rm_free_db(tfp, &fparms);
368                         if (rc)
369                                 return rc;
370                 }
371
372                 em_db->em_db[i] = NULL;
373         }
374
375         init = 0;
376
377         return 0;
378 }