6842291adf4137fa36529fc18b6805e26b1cdf5d
[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         int db_rc[TF_DIR_MAX] = { 0 };
45         struct tf_rm_create_db_parms db_cfg = { 0 };
46         struct tbl_rm_db *tbl_db;
47         struct tfp_calloc_parms cparms;
48         struct tf_session *tfs;
49
50         TF_CHECK_PARMS2(tfp, parms);
51
52         /* Retrieve the session information */
53         rc = tf_session_get_session_internal(tfp, &tfs);
54         if (rc)
55                 return rc;
56
57         memset(&db_cfg, 0, sizeof(db_cfg));
58         cparms.nitems = 1;
59         cparms.size = sizeof(struct tbl_rm_db);
60         cparms.alignment = 0;
61         if (tfp_calloc(&cparms) != 0) {
62                 TFP_DRV_LOG(ERR, "tbl_rm_db alloc error %s\n",
63                             strerror(ENOMEM));
64                 return -ENOMEM;
65         }
66
67         tbl_db = cparms.mem_va;
68         for (i = 0; i < TF_DIR_MAX; i++)
69                 tbl_db->tbl_db[i] = NULL;
70         tf_session_set_db(tfp, TF_MODULE_TYPE_TABLE, tbl_db);
71
72         db_cfg.num_elements = parms->num_elements;
73         db_cfg.module = TF_MODULE_TYPE_TABLE;
74         db_cfg.num_elements = parms->num_elements;
75         db_cfg.cfg = parms->cfg;
76
77         for (d = 0; d < TF_DIR_MAX; d++) {
78                 db_cfg.dir = d;
79                 db_cfg.alloc_cnt = parms->resources->tbl_cnt[d].cnt;
80                 db_cfg.rm_db = (void *)&tbl_db->tbl_db[d];
81                 if (tf_session_is_shared_session(tfs) &&
82                         (!tf_session_is_shared_session_creator(tfs)))
83                         db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
84                 else
85                         db_rc[d] = tf_rm_create_db(tfp, &db_cfg);
86         }
87
88         /* No db created */
89         if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
90                 TFP_DRV_LOG(ERR,
91                             "%s: No Table DB created\n",
92                             tf_dir_2_str(d));
93                 return db_rc[TF_DIR_RX];
94         }
95
96         TFP_DRV_LOG(INFO,
97                     "Table Type - initialized\n");
98
99         return 0;
100 }
101
102 int
103 tf_tbl_unbind(struct tf *tfp)
104 {
105         int rc;
106         int i;
107         struct tf_rm_free_db_parms fparms = { 0 };
108         struct tbl_rm_db *tbl_db;
109         void *tbl_db_ptr = NULL;
110         TF_CHECK_PARMS1(tfp);
111
112         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
113         if (rc)
114                 return 0;
115         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
116
117         for (i = 0; i < TF_DIR_MAX; i++) {
118                 if (tbl_db->tbl_db[i] == NULL)
119                         continue;
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, i;
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         uint16_t base = 0, shift = 0;
630         struct tf_dev_info *dev;
631         struct tf_session *tfs;
632
633         TF_CHECK_PARMS2(tfp, tbl);
634
635         /* Retrieve the session information */
636         rc = tf_session_get_session_internal(tfp, &tfs);
637         if (rc)
638                 return rc;
639
640         /* Retrieve the device information */
641         rc = tf_session_get_device(tfs, &dev);
642         if (rc)
643                 return rc;
644
645         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
646         if (rc) {
647                 TFP_DRV_LOG(INFO,
648                             "No resource allocated for table from session\n");
649                 return 0;
650         }
651         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
652
653         /* check if reserved resource for WC is multiple of num_slices */
654         for (d = 0; d < TF_DIR_MAX; d++) {
655                 ainfo.rm_db = tbl_db->tbl_db[d];
656                 dinfo = tbl[d].info;
657
658                 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
659                 ainfo.subtype = 0;
660                 rc = tf_rm_get_all_info(&ainfo, TF_TBL_TYPE_MAX);
661                 if (rc)
662                         return rc;
663
664                 if (dev->ops->tf_dev_get_tbl_info) {
665                         /* Adjust all */
666                         for (i = 0; i < TF_TBL_TYPE_MAX; i++) {
667                                 /* Only get table info if required for the device */
668                                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
669                                                                    tbl_db->tbl_db[d],
670                                                                    i,
671                                                                    &base,
672                                                                    &shift);
673                                 if (rc) {
674                                         TFP_DRV_LOG(ERR,
675                                                     "%s: Failed to get table info:%d\n",
676                                                     tf_dir_2_str(d),
677                                                     i);
678                                         return rc;
679                                 }
680                                 if (dinfo[i].stride)
681                                         TF_TBL_RM_TO_PTR(&dinfo[i].start,
682                                                          dinfo[i].start,
683                                                          base,
684                                                          shift);
685                         }
686                 }
687         }
688
689         return 0;
690 }