eal: remove sys/queue.h from public headers
[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 #include "bnxt.h"
19
20 #define TF_EM_DB_EM_REC 0
21
22 /**
23  * EM Pool
24  */
25 #include "dpool.h"
26
27 /**
28  * Insert EM internal entry API
29  *
30  *  returns:
31  *     0 - Success
32  */
33 int
34 tf_em_insert_int_entry(struct tf *tfp,
35                        struct tf_insert_em_entry_parms *parms)
36 {
37         int rc;
38         uint32_t gfid;
39         uint16_t rptr_index = 0;
40         uint8_t rptr_entry = 0;
41         uint8_t num_of_entries = 0;
42         struct tf_session *tfs;
43         struct dpool *pool;
44         uint32_t index;
45
46         /* Retrieve the session information */
47         rc = tf_session_get_session(tfp, &tfs);
48         if (rc) {
49                 TFP_DRV_LOG(ERR,
50                             "%s: Failed to lookup session, rc:%s\n",
51                             tf_dir_2_str(parms->dir),
52                             strerror(-rc));
53                 return rc;
54         }
55
56         pool = (struct dpool *)tfs->em_pool[parms->dir];
57         index = dpool_alloc(pool, TF_SESSION_EM_ENTRY_SIZE, 0);
58         if (index == DP_INVALID_INDEX) {
59                 PMD_DRV_LOG(ERR,
60                             "%s, EM entry index allocation failed\n",
61                             tf_dir_2_str(parms->dir));
62                 return -1;
63         }
64
65
66         rptr_index = index;
67         rc = tf_msg_insert_em_internal_entry(tfp,
68                                              parms,
69                                              &rptr_index,
70                                              &rptr_entry,
71                                              &num_of_entries);
72         if (rc) {
73                 /* Free the allocated index before returning */
74                 dpool_free(pool, index);
75                 return -1;
76         }
77         TF_SET_GFID(gfid,
78                     ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
79                      rptr_entry),
80                     0); /* N/A for internal table */
81
82         TF_SET_FLOW_ID(parms->flow_id,
83                        gfid,
84                        TF_GFID_TABLE_INTERNAL,
85                        parms->dir);
86
87         TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
88                                      (uint32_t)num_of_entries,
89                                      0,
90                                      TF_FLAGS_FLOW_HANDLE_INTERNAL,
91                                      rptr_index,
92                                      rptr_entry,
93                                      0);
94         return 0;
95 }
96
97
98 /** Delete EM internal entry API
99  *
100  * returns:
101  * 0
102  * -EINVAL
103  */
104 int
105 tf_em_delete_int_entry(struct tf *tfp,
106                        struct tf_delete_em_entry_parms *parms)
107 {
108         int rc = 0;
109         struct tf_session *tfs;
110         struct dpool *pool;
111         /* Retrieve the session information */
112         rc = tf_session_get_session(tfp, &tfs);
113         if (rc) {
114                 TFP_DRV_LOG(ERR,
115                             "%s: Failed to lookup session, rc:%s\n",
116                             tf_dir_2_str(parms->dir),
117                             strerror(-rc));
118                 return rc;
119         }
120
121         rc = tf_msg_delete_em_entry(tfp, parms);
122
123         /* Return resource to pool */
124         if (rc == 0) {
125                 pool = (struct dpool *)tfs->em_pool[parms->dir];
126                 dpool_free(pool, parms->index);
127         }
128
129         return rc;
130 }
131
132 static int
133 tf_em_move_callback(void *user_data,
134                     uint64_t entry_data,
135                     uint32_t new_index)
136 {
137         int rc;
138         struct tf *tfp = (struct tf *)user_data;
139         struct tf_move_em_entry_parms parms;
140         struct tf_dev_info     *dev;
141         struct tf_session      *tfs;
142
143         memset(&parms, 0, sizeof(parms));
144
145         parms.tbl_scope_id = 0;
146         parms.flow_handle  = entry_data;
147         parms.new_index    = new_index;
148         TF_GET_DIR_FROM_FLOW_ID(entry_data, parms.dir);
149         parms.mem          = TF_MEM_INTERNAL;
150
151         /* Retrieve the session information */
152         rc = tf_session_get_session(tfp, &tfs);
153         if (rc) {
154                 TFP_DRV_LOG(ERR,
155                             "%s: Failed to lookup session, rc:%s\n",
156                             tf_dir_2_str(parms.dir),
157                             strerror(-rc));
158                 return rc;
159         }
160
161         /* Retrieve the device information */
162         rc = tf_session_get_device(tfs, &dev);
163         if (rc) {
164                 TFP_DRV_LOG(ERR,
165                             "%s: Failed to lookup device, rc:%s\n",
166                             tf_dir_2_str(parms.dir),
167                             strerror(-rc));
168                 return rc;
169         }
170
171         if (dev->ops->tf_dev_move_int_em_entry != NULL)
172                 rc = dev->ops->tf_dev_move_int_em_entry(tfp, &parms);
173         else
174                 rc = -EOPNOTSUPP;
175
176         return rc;
177 }
178
179 int
180 tf_em_int_bind(struct tf *tfp,
181                struct tf_em_cfg_parms *parms)
182 {
183         int rc;
184         int db_rc[TF_DIR_MAX] = { 0 };
185         int i;
186         struct tf_rm_create_db_parms db_cfg = { 0 };
187         struct tf_rm_get_alloc_info_parms iparms;
188         struct tf_rm_alloc_info info;
189         struct em_rm_db *em_db;
190         struct tfp_calloc_parms cparms;
191         struct tf_session *tfs;
192
193         TF_CHECK_PARMS2(tfp, parms);
194
195         /* Retrieve the session information */
196         rc = tf_session_get_session_internal(tfp, &tfs);
197         if (rc)
198                 return rc;
199
200         memset(&db_cfg, 0, sizeof(db_cfg));
201         cparms.nitems = 1;
202         cparms.size = sizeof(struct em_rm_db);
203         cparms.alignment = 0;
204         if (tfp_calloc(&cparms) != 0) {
205                 TFP_DRV_LOG(ERR, "em_rm_db alloc error %s\n",
206                             strerror(ENOMEM));
207                 return -ENOMEM;
208         }
209
210         em_db = cparms.mem_va;
211         for (i = 0; i < TF_DIR_MAX; i++)
212                 em_db->em_db[i] = NULL;
213         tf_session_set_db(tfp, TF_MODULE_TYPE_EM, em_db);
214
215         db_cfg.module = TF_MODULE_TYPE_EM;
216         db_cfg.num_elements = parms->num_elements;
217         db_cfg.cfg = parms->cfg;
218
219         for (i = 0; i < TF_DIR_MAX; i++) {
220                 db_cfg.dir = i;
221                 db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
222
223                 /* Check if we got any request to support EEM, if so
224                  * we build an EM Int DB holding Table Scopes.
225                  */
226                 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] == 0)
227                         continue;
228
229                 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] %
230                     TF_SESSION_EM_ENTRY_SIZE != 0) {
231                         rc = -ENOMEM;
232                         TFP_DRV_LOG(ERR,
233                                     "%s, EM Allocation must be in blocks of %d, failure %s\n",
234                                     tf_dir_2_str(i),
235                                     TF_SESSION_EM_ENTRY_SIZE,
236                                     strerror(-rc));
237
238                         return rc;
239                 }
240
241                 db_cfg.rm_db = (void *)&em_db->em_db[i];
242                 if (tf_session_is_shared_session(tfs) &&
243                         (!tf_session_is_shared_session_creator(tfs)))
244                         db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
245                 else
246                         db_rc[i] = tf_rm_create_db(tfp, &db_cfg);
247         }
248
249         /* No db created */
250         if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
251                 TFP_DRV_LOG(ERR, "EM Int DB creation failed\n");
252                 return db_rc[TF_DIR_RX];
253         }
254
255
256         if (!tf_session_is_shared_session(tfs)) {
257                 for (i = 0; i < TF_DIR_MAX; i++) {
258                         iparms.rm_db = em_db->em_db[i];
259                         iparms.subtype = TF_EM_DB_EM_REC;
260                         iparms.info = &info;
261
262                         rc = tf_rm_get_info(&iparms);
263                         if (rc) {
264                                 TFP_DRV_LOG(ERR,
265                                             "%s: EM DB get info failed\n",
266                                             tf_dir_2_str(i));
267                                 return rc;
268                         }
269
270                         /*
271                          * Allocate stack pool
272                          */
273                         cparms.nitems = 1;
274                         cparms.size = sizeof(struct dpool);
275                         cparms.alignment = 0;
276
277                         rc = tfp_calloc(&cparms);
278
279                         if (rc) {
280                                 TFP_DRV_LOG(ERR,
281                                          "%s, EM stack allocation failure %s\n",
282                                          tf_dir_2_str(i),
283                                          strerror(-rc));
284                                 return rc;
285                         }
286
287                         tfs->em_pool[i] = (struct dpool *)cparms.mem_va;
288
289                         rc = dpool_init(tfs->em_pool[i],
290                                         iparms.info->entry.start,
291                                         iparms.info->entry.stride,
292                                         7,
293                                         (void *)tfp,
294                                         tf_em_move_callback);
295                         /* Logging handled in tf_create_em_pool */
296                         if (rc)
297                                 return rc;
298                 }
299
300                 if (rc) {
301                         TFP_DRV_LOG(ERR,
302                                     "%s: EM pool init failed\n",
303                                     tf_dir_2_str(i));
304                         return rc;
305                 }
306         }
307
308         return 0;
309 }
310
311 int
312 tf_em_int_unbind(struct tf *tfp)
313 {
314         int rc;
315         int i;
316         struct tf_rm_free_db_parms fparms = { 0 };
317         struct em_rm_db *em_db;
318         void *em_db_ptr = NULL;
319         struct tf_session *tfs;
320
321         TF_CHECK_PARMS1(tfp);
322
323         /* Retrieve the session information */
324         rc = tf_session_get_session_internal(tfp, &tfs);
325         if (rc)
326                 return rc;
327
328         if (!tf_session_is_shared_session(tfs)) {
329                 for (i = 0; i < TF_DIR_MAX; i++) {
330                         if (tfs->em_pool[i] == NULL)
331                                 continue;
332                         dpool_free_all(tfs->em_pool[i]);
333                 }
334         }
335
336         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
337         if (rc) {
338                 return 0;
339         }
340         em_db = (struct em_rm_db *)em_db_ptr;
341
342         for (i = 0; i < TF_DIR_MAX; i++) {
343                 if (em_db->em_db[i] == NULL)
344                         continue;
345                 fparms.dir = i;
346                 fparms.rm_db = em_db->em_db[i];
347                 rc = tf_rm_free_db(tfp, &fparms);
348                 if (rc)
349                         return rc;
350
351                 em_db->em_db[i] = NULL;
352         }
353
354         return 0;
355 }
356
357 int
358 tf_em_get_resc_info(struct tf *tfp,
359                     struct tf_em_resource_info *em)
360 {
361         int rc;
362         int d;
363         struct tf_resource_info *dinfo;
364         struct tf_rm_get_alloc_info_parms ainfo;
365         void *em_db_ptr = NULL;
366         struct em_rm_db *em_db;
367
368         TF_CHECK_PARMS2(tfp, em);
369
370         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
371         if (rc == -ENOMEM)
372                 return 0;  /* db does not exist */
373         else if (rc)
374                 return rc; /* db error */
375
376         em_db = (struct em_rm_db *)em_db_ptr;
377
378         /* check if reserved resource for EM is multiple of num_slices */
379         for (d = 0; d < TF_DIR_MAX; d++) {
380                 ainfo.rm_db = em_db->em_db[d];
381                 dinfo = em[d].info;
382
383                 if (!ainfo.rm_db)
384                         continue;
385
386                 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
387                 ainfo.subtype = 0;
388                 rc = tf_rm_get_all_info(&ainfo, TF_EM_TBL_TYPE_MAX);
389                 if (rc && rc != -ENOTSUP)
390                         return rc;
391         }
392
393         return 0;
394 }