net/bnxt: support shared session
[dpdk.git] / drivers / net / bnxt / tf_core / tf_tbl.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5
6 /* Truflow Table APIs and supporting code */
7
8 #include <rte_common.h>
9
10 #include "tf_tbl.h"
11 #include "tf_common.h"
12 #include "tf_rm.h"
13 #include "tf_util.h"
14 #include "tf_msg.h"
15 #include "tfp.h"
16 #include "tf_session.h"
17 #include "tf_device.h"
18
19 #define TF_TBL_RM_TO_PTR(new_idx, idx, base, shift) {           \
20                 *(new_idx) = (((idx) + (base)) << (shift));     \
21 }
22
23 #define TF_TBL_PTR_TO_RM(new_idx, idx, base, shift) {           \
24                 *(new_idx) = (((idx) >> (shift)) - (base));     \
25 }
26
27 struct tf;
28
29 /**
30  * Table Shadow DBs
31  */
32 static void *shadow_tbl_db[TF_DIR_MAX];
33
34 /**
35  * Shadow init flag, set on bind and cleared on unbind
36  */
37 static uint8_t shadow_init;
38
39 int
40 tf_tbl_bind(struct tf *tfp,
41             struct tf_tbl_cfg_parms *parms)
42 {
43         int rc, d, i;
44         struct tf_rm_create_db_parms db_cfg = { 0 };
45         struct tbl_rm_db *tbl_db;
46         struct tfp_calloc_parms cparms;
47         struct tf_session *tfs;
48
49         TF_CHECK_PARMS2(tfp, parms);
50
51         /* Retrieve the session information */
52         rc = tf_session_get_session_internal(tfp, &tfs);
53         if (rc)
54                 return rc;
55
56         memset(&db_cfg, 0, sizeof(db_cfg));
57         cparms.nitems = 1;
58         cparms.size = sizeof(struct tbl_rm_db);
59         cparms.alignment = 0;
60         if (tfp_calloc(&cparms) != 0) {
61                 TFP_DRV_LOG(ERR, "tbl_rm_db alloc error %s\n",
62                             strerror(ENOMEM));
63                 return -ENOMEM;
64         }
65
66         tbl_db = cparms.mem_va;
67         for (i = 0; i < TF_DIR_MAX; i++)
68                 tbl_db->tbl_db[i] = NULL;
69         tf_session_set_db(tfp, TF_MODULE_TYPE_TABLE, tbl_db);
70
71         db_cfg.num_elements = parms->num_elements;
72         db_cfg.module = TF_MODULE_TYPE_TABLE;
73         db_cfg.num_elements = parms->num_elements;
74         db_cfg.cfg = parms->cfg;
75
76         for (d = 0; d < TF_DIR_MAX; d++) {
77                 db_cfg.dir = d;
78                 db_cfg.alloc_cnt = parms->resources->tbl_cnt[d].cnt;
79                 db_cfg.rm_db = (void *)&tbl_db->tbl_db[d];
80                 if (tf_session_is_shared_session(tfs) &&
81                         (!tf_session_is_shared_session_creator(tfs)))
82                         rc = tf_rm_create_db_no_reservation(tfp, &db_cfg);
83                 else
84                         rc = tf_rm_create_db(tfp, &db_cfg);
85                 if (rc) {
86                         TFP_DRV_LOG(ERR,
87                                     "%s: Table DB creation failed\n",
88                                     tf_dir_2_str(d));
89
90                         return rc;
91                 }
92         }
93
94         TFP_DRV_LOG(INFO,
95                     "Table Type - initialized\n");
96
97         return 0;
98 }
99
100 int
101 tf_tbl_unbind(struct tf *tfp)
102 {
103         int rc;
104         int i;
105         struct tf_rm_free_db_parms fparms = { 0 };
106         struct tbl_rm_db *tbl_db;
107         void *tbl_db_ptr = NULL;
108         TF_CHECK_PARMS1(tfp);
109
110         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
111         if (rc) {
112                 TFP_DRV_LOG(ERR,
113                             "Failed to get em_ext_db from session, rc:%s\n",
114                             strerror(-rc));
115                 return rc;
116         }
117         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
118
119         for (i = 0; i < TF_DIR_MAX; i++) {
120                 fparms.dir = i;
121                 fparms.rm_db = tbl_db->tbl_db[i];
122                 rc = tf_rm_free_db(tfp, &fparms);
123                 if (rc)
124                         return rc;
125
126                 tbl_db->tbl_db[i] = NULL;
127         }
128
129         shadow_init = 0;
130
131         return 0;
132 }
133
134 int
135 tf_tbl_alloc(struct tf *tfp __rte_unused,
136              struct tf_tbl_alloc_parms *parms)
137 {
138         int rc;
139         uint32_t idx;
140         struct tf_rm_allocate_parms aparms = { 0 };
141         struct tf_session *tfs;
142         struct tf_dev_info *dev;
143         uint16_t base = 0, shift = 0;
144         struct tbl_rm_db *tbl_db;
145         void *tbl_db_ptr = NULL;
146
147         TF_CHECK_PARMS2(tfp, parms);
148
149         /* Retrieve the session information */
150         rc = tf_session_get_session_internal(tfp, &tfs);
151         if (rc)
152                 return rc;
153
154         /* Retrieve the device information */
155         rc = tf_session_get_device(tfs, &dev);
156         if (rc)
157                 return rc;
158
159         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
160         if (rc) {
161                 TFP_DRV_LOG(ERR,
162                             "Failed to get em_ext_db from session, rc:%s\n",
163                             strerror(-rc));
164                 return rc;
165         }
166         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
167
168         /* Only get table info if required for the device */
169         if (dev->ops->tf_dev_get_tbl_info) {
170                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
171                                                    tbl_db->tbl_db[parms->dir],
172                                                    parms->type,
173                                                    &base,
174                                                    &shift);
175                 if (rc) {
176                         TFP_DRV_LOG(ERR,
177                                     "%s: Failed to get table info:%d\n",
178                                     tf_dir_2_str(parms->dir),
179                                     parms->type);
180                         return rc;
181                 }
182         }
183
184         /* Allocate requested element */
185         aparms.rm_db = tbl_db->tbl_db[parms->dir];
186         aparms.subtype = parms->type;
187         aparms.index = &idx;
188         rc = tf_rm_allocate(&aparms);
189         if (rc) {
190                 TFP_DRV_LOG(ERR,
191                             "%s: Failed allocate, type:%d\n",
192                             tf_dir_2_str(parms->dir),
193                             parms->type);
194                 return rc;
195         }
196
197         TF_TBL_RM_TO_PTR(&idx, idx, base, shift);
198         *parms->idx = idx;
199
200         return 0;
201 }
202
203 int
204 tf_tbl_free(struct tf *tfp __rte_unused,
205             struct tf_tbl_free_parms *parms)
206 {
207         int rc;
208         struct tf_rm_is_allocated_parms aparms = { 0 };
209         struct tf_rm_free_parms fparms = { 0 };
210         int allocated = 0;
211         struct tf_session *tfs;
212         struct tf_dev_info *dev;
213         uint16_t base = 0, shift = 0;
214         struct tbl_rm_db *tbl_db;
215         void *tbl_db_ptr = NULL;
216
217         TF_CHECK_PARMS2(tfp, parms);
218
219         /* Retrieve the session information */
220         rc = tf_session_get_session_internal(tfp, &tfs);
221         if (rc)
222                 return rc;
223
224         /* Retrieve the device information */
225         rc = tf_session_get_device(tfs, &dev);
226         if (rc)
227                 return rc;
228
229         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
230         if (rc) {
231                 TFP_DRV_LOG(ERR,
232                             "Failed to get em_ext_db from session, rc:%s\n",
233                             strerror(-rc));
234                 return rc;
235         }
236         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
237
238         /* Only get table info if required for the device */
239         if (dev->ops->tf_dev_get_tbl_info) {
240                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
241                                                    tbl_db->tbl_db[parms->dir],
242                                                    parms->type,
243                                                    &base,
244                                                    &shift);
245                 if (rc) {
246                         TFP_DRV_LOG(ERR,
247                                     "%s: Failed to get table info:%d\n",
248                                     tf_dir_2_str(parms->dir),
249                                     parms->type);
250                         return rc;
251                 }
252         }
253
254         /* Check if element is in use */
255         aparms.rm_db = tbl_db->tbl_db[parms->dir];
256         aparms.subtype = parms->type;
257
258         TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
259
260         aparms.allocated = &allocated;
261         rc = tf_rm_is_allocated(&aparms);
262         if (rc)
263                 return rc;
264
265         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
266                 TFP_DRV_LOG(ERR,
267                             "%s: Entry already free, type:%d, index:%d\n",
268                             tf_dir_2_str(parms->dir),
269                             parms->type,
270                             parms->idx);
271                 return -EINVAL;
272         }
273         /* Free requested element */
274         fparms.rm_db = tbl_db->tbl_db[parms->dir];
275         fparms.subtype = parms->type;
276
277         TF_TBL_PTR_TO_RM(&fparms.index, parms->idx, base, shift);
278
279         rc = tf_rm_free(&fparms);
280         if (rc) {
281                 TFP_DRV_LOG(ERR,
282                             "%s: Free failed, type:%d, index:%d\n",
283                             tf_dir_2_str(parms->dir),
284                             parms->type,
285                             parms->idx);
286                 return rc;
287         }
288
289         return 0;
290 }
291
292 int
293 tf_tbl_alloc_search(struct tf *tfp,
294                     struct tf_tbl_alloc_search_parms *parms)
295 {
296         int rc = 0;
297         TF_CHECK_PARMS2(tfp, parms);
298
299         if (!shadow_init || !shadow_tbl_db[parms->dir]) {
300                 TFP_DRV_LOG(ERR, "%s: Shadow TBL not initialized.\n",
301                             tf_dir_2_str(parms->dir));
302                 return -EINVAL;
303         }
304
305         return rc;
306 }
307
308 int
309 tf_tbl_set(struct tf *tfp,
310            struct tf_tbl_set_parms *parms)
311 {
312         int rc;
313         int allocated = 0;
314         uint16_t hcapi_type;
315         struct tf_rm_is_allocated_parms aparms = { 0 };
316         struct tf_rm_get_hcapi_parms hparms = { 0 };
317         struct tf_session *tfs;
318         struct tf_dev_info *dev;
319         uint16_t base = 0, shift = 0;
320         struct tbl_rm_db *tbl_db;
321         void *tbl_db_ptr = NULL;
322
323         TF_CHECK_PARMS3(tfp, parms, parms->data);
324
325         /* Retrieve the session information */
326         rc = tf_session_get_session_internal(tfp, &tfs);
327         if (rc)
328                 return rc;
329
330         /* Retrieve the device information */
331         rc = tf_session_get_device(tfs, &dev);
332         if (rc)
333                 return rc;
334
335         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
336         if (rc) {
337                 TFP_DRV_LOG(ERR,
338                             "Failed to get em_ext_db from session, rc:%s\n",
339                             strerror(-rc));
340                 return rc;
341         }
342         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
343
344         /* Only get table info if required for the device */
345         if (dev->ops->tf_dev_get_tbl_info) {
346                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
347                                                    tbl_db->tbl_db[parms->dir],
348                                                    parms->type,
349                                                    &base,
350                                                    &shift);
351                 if (rc) {
352                         TFP_DRV_LOG(ERR,
353                                     "%s: Failed to get table info:%d\n",
354                                     tf_dir_2_str(parms->dir),
355                                     parms->type);
356                         return rc;
357                 }
358         }
359
360         /* Verify that the entry has been previously allocated */
361         aparms.rm_db = tbl_db->tbl_db[parms->dir];
362         aparms.subtype = parms->type;
363         TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
364
365         aparms.allocated = &allocated;
366         rc = tf_rm_is_allocated(&aparms);
367         if (rc)
368                 return rc;
369
370         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
371                 TFP_DRV_LOG(ERR,
372                    "%s, Invalid or not allocated index, type:%d, idx:%d\n",
373                    tf_dir_2_str(parms->dir),
374                    parms->type,
375                    parms->idx);
376                 return -EINVAL;
377         }
378
379         /* Set the entry */
380         hparms.rm_db = tbl_db->tbl_db[parms->dir];
381         hparms.subtype = parms->type;
382         hparms.hcapi_type = &hcapi_type;
383         rc = tf_rm_get_hcapi_type(&hparms);
384         if (rc) {
385                 TFP_DRV_LOG(ERR,
386                             "%s, Failed type lookup, type:%d, rc:%s\n",
387                             tf_dir_2_str(parms->dir),
388                             parms->type,
389                             strerror(-rc));
390                 return rc;
391         }
392
393         rc = tf_msg_set_tbl_entry(tfp,
394                                   parms->dir,
395                                   hcapi_type,
396                                   parms->data_sz_in_bytes,
397                                   parms->data,
398                                   parms->idx);
399         if (rc) {
400                 TFP_DRV_LOG(ERR,
401                             "%s, Set failed, type:%d, rc:%s\n",
402                             tf_dir_2_str(parms->dir),
403                             parms->type,
404                             strerror(-rc));
405                 return rc;
406         }
407
408         return 0;
409 }
410
411 int
412 tf_tbl_get(struct tf *tfp,
413            struct tf_tbl_get_parms *parms)
414 {
415         int rc;
416         uint16_t hcapi_type;
417         int allocated = 0;
418         struct tf_rm_is_allocated_parms aparms = { 0 };
419         struct tf_rm_get_hcapi_parms hparms = { 0 };
420         struct tf_session *tfs;
421         struct tf_dev_info *dev;
422         uint16_t base = 0, shift = 0;
423         struct tbl_rm_db *tbl_db;
424         void *tbl_db_ptr = NULL;
425
426         TF_CHECK_PARMS3(tfp, parms, parms->data);
427
428         /* Retrieve the session information */
429         rc = tf_session_get_session_internal(tfp, &tfs);
430         if (rc)
431                 return rc;
432
433         /* Retrieve the device information */
434         rc = tf_session_get_device(tfs, &dev);
435         if (rc)
436                 return rc;
437
438         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
439         if (rc) {
440                 TFP_DRV_LOG(ERR,
441                             "Failed to get em_ext_db from session, rc:%s\n",
442                             strerror(-rc));
443                 return rc;
444         }
445         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
446
447         /* Only get table info if required for the device */
448         if (dev->ops->tf_dev_get_tbl_info) {
449                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
450                                                    tbl_db->tbl_db[parms->dir],
451                                                    parms->type,
452                                                    &base,
453                                                    &shift);
454                 if (rc) {
455                         TFP_DRV_LOG(ERR,
456                                     "%s: Failed to get table info:%d\n",
457                                     tf_dir_2_str(parms->dir),
458                                     parms->type);
459                         return rc;
460                 }
461         }
462
463         /* Verify that the entry has been previously allocated */
464         aparms.rm_db = tbl_db->tbl_db[parms->dir];
465         aparms.subtype = parms->type;
466         TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
467
468         aparms.allocated = &allocated;
469         rc = tf_rm_is_allocated(&aparms);
470         if (rc)
471                 return rc;
472
473         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
474                 TFP_DRV_LOG(ERR,
475                    "%s, Invalid or not allocated index, type:%d, idx:%d\n",
476                    tf_dir_2_str(parms->dir),
477                    parms->type,
478                    parms->idx);
479                 return -EINVAL;
480         }
481
482         /* Set the entry */
483         hparms.rm_db = tbl_db->tbl_db[parms->dir];
484         hparms.subtype = parms->type;
485         hparms.hcapi_type = &hcapi_type;
486         rc = tf_rm_get_hcapi_type(&hparms);
487         if (rc) {
488                 TFP_DRV_LOG(ERR,
489                             "%s, Failed type lookup, type:%d, rc:%s\n",
490                             tf_dir_2_str(parms->dir),
491                             parms->type,
492                             strerror(-rc));
493                 return rc;
494         }
495
496         /* Get the entry */
497         rc = tf_msg_get_tbl_entry(tfp,
498                                   parms->dir,
499                                   hcapi_type,
500                                   parms->data_sz_in_bytes,
501                                   parms->data,
502                                   parms->idx);
503         if (rc) {
504                 TFP_DRV_LOG(ERR,
505                             "%s, Get failed, type:%d, rc:%s\n",
506                             tf_dir_2_str(parms->dir),
507                             parms->type,
508                             strerror(-rc));
509                 return rc;
510         }
511
512         return 0;
513 }
514
515 int
516 tf_tbl_bulk_get(struct tf *tfp,
517                 struct tf_tbl_get_bulk_parms *parms)
518 {
519         int rc;
520         uint16_t hcapi_type;
521         struct tf_rm_get_hcapi_parms hparms = { 0 };
522         struct tf_rm_check_indexes_in_range_parms cparms = { 0 };
523         struct tf_session *tfs;
524         struct tf_dev_info *dev;
525         uint16_t base = 0, shift = 0;
526         struct tbl_rm_db *tbl_db;
527         void *tbl_db_ptr = NULL;
528
529         TF_CHECK_PARMS2(tfp, parms);
530
531         /* Retrieve the session information */
532         rc = tf_session_get_session_internal(tfp, &tfs);
533         if (rc)
534                 return rc;
535
536         /* Retrieve the device information */
537         rc = tf_session_get_device(tfs, &dev);
538         if (rc)
539                 return rc;
540
541         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
542         if (rc) {
543                 TFP_DRV_LOG(ERR,
544                             "Failed to get em_ext_db from session, rc:%s\n",
545                             strerror(-rc));
546                 return rc;
547         }
548         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
549
550         /* Only get table info if required for the device */
551         if (dev->ops->tf_dev_get_tbl_info) {
552                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
553                                                    tbl_db->tbl_db[parms->dir],
554                                                    parms->type,
555                                                    &base,
556                                                    &shift);
557                 if (rc) {
558                         TFP_DRV_LOG(ERR,
559                                     "%s: Failed to get table info:%d\n",
560                                     tf_dir_2_str(parms->dir),
561                                     parms->type);
562                         return rc;
563                 }
564         }
565
566         /* Verify that the entries are in the range of reserved resources. */
567         cparms.rm_db = tbl_db->tbl_db[parms->dir];
568         cparms.subtype = parms->type;
569
570         TF_TBL_PTR_TO_RM(&cparms.starting_index, parms->starting_idx,
571                          base, shift);
572
573         cparms.num_entries = parms->num_entries;
574
575         rc = tf_rm_check_indexes_in_range(&cparms);
576         if (rc) {
577                 TFP_DRV_LOG(ERR,
578                             "%s, Invalid or %d index starting from %d"
579                             " not in range, type:%d",
580                             tf_dir_2_str(parms->dir),
581                             parms->starting_idx,
582                             parms->num_entries,
583                             parms->type);
584                 return rc;
585         }
586
587         hparms.rm_db = tbl_db->tbl_db[parms->dir];
588         hparms.subtype = parms->type;
589         hparms.hcapi_type = &hcapi_type;
590         rc = tf_rm_get_hcapi_type(&hparms);
591         if (rc) {
592                 TFP_DRV_LOG(ERR,
593                             "%s, Failed type lookup, type:%d, rc:%s\n",
594                             tf_dir_2_str(parms->dir),
595                             parms->type,
596                             strerror(-rc));
597                 return rc;
598         }
599
600         /* Get the entries */
601         rc = tf_msg_bulk_get_tbl_entry(tfp,
602                                        parms->dir,
603                                        hcapi_type,
604                                        parms->starting_idx,
605                                        parms->num_entries,
606                                        parms->entry_sz_in_bytes,
607                                        parms->physical_mem_addr);
608         if (rc) {
609                 TFP_DRV_LOG(ERR,
610                             "%s, Bulk get failed, type:%d, rc:%s\n",
611                             tf_dir_2_str(parms->dir),
612                             parms->type,
613                             strerror(-rc));
614         }
615
616         return rc;
617 }
618
619 int
620 tf_tbl_get_resc_info(struct tf *tfp,
621                      struct tf_tbl_resource_info *tbl)
622 {
623         int rc;
624         int d;
625         struct tf_resource_info *dinfo;
626         struct tf_rm_get_alloc_info_parms ainfo;
627         void *tbl_db_ptr = NULL;
628         struct tbl_rm_db *tbl_db;
629
630         TF_CHECK_PARMS2(tfp, tbl);
631
632         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
633         if (rc) {
634                 TFP_DRV_LOG(ERR,
635                             "Failed to get em_ext_db from session, rc:%s\n",
636                             strerror(-rc));
637                 return rc;
638         }
639         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
640
641         /* check if reserved resource for WC is multiple of num_slices */
642         for (d = 0; d < TF_DIR_MAX; d++) {
643                 ainfo.rm_db = tbl_db->tbl_db[d];
644                 dinfo = tbl[d].info;
645
646                 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
647                 ainfo.subtype = 0;
648                 rc = tf_rm_get_all_info(&ainfo, TF_TBL_TYPE_MAX);
649                 if (rc)
650                         return rc;
651         }
652
653         return 0;
654 }