net/bnxt: modify resource reservation strategy
[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                 if (db_rc[d]) {
87                         TFP_DRV_LOG(ERR,
88                                     "%s: Table DB creation failed\n",
89                                     tf_dir_2_str(d));
90
91                 }
92         }
93
94         /* No db created */
95         if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX])
96                 return db_rc[TF_DIR_RX];
97
98         TFP_DRV_LOG(INFO,
99                     "Table Type - initialized\n");
100
101         return 0;
102 }
103
104 int
105 tf_tbl_unbind(struct tf *tfp)
106 {
107         int rc;
108         int i;
109         struct tf_rm_free_db_parms fparms = { 0 };
110         struct tbl_rm_db *tbl_db;
111         void *tbl_db_ptr = NULL;
112         TF_CHECK_PARMS1(tfp);
113
114         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
115         if (rc) {
116                 TFP_DRV_LOG(INFO,
117                             "Tbl_db is not initialized, rc:%s\n",
118                             strerror(-rc));
119                 return 0;
120         }
121         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
122
123         for (i = 0; i < TF_DIR_MAX; i++) {
124                 if (tbl_db->tbl_db[i] == NULL)
125                         continue;
126                 fparms.dir = i;
127                 fparms.rm_db = tbl_db->tbl_db[i];
128                 rc = tf_rm_free_db(tfp, &fparms);
129                 if (rc)
130                         return rc;
131
132                 tbl_db->tbl_db[i] = NULL;
133         }
134
135         shadow_init = 0;
136
137         return 0;
138 }
139
140 int
141 tf_tbl_alloc(struct tf *tfp __rte_unused,
142              struct tf_tbl_alloc_parms *parms)
143 {
144         int rc;
145         uint32_t idx;
146         struct tf_rm_allocate_parms aparms = { 0 };
147         struct tf_session *tfs;
148         struct tf_dev_info *dev;
149         uint16_t base = 0, shift = 0;
150         struct tbl_rm_db *tbl_db;
151         void *tbl_db_ptr = NULL;
152
153         TF_CHECK_PARMS2(tfp, parms);
154
155         /* Retrieve the session information */
156         rc = tf_session_get_session_internal(tfp, &tfs);
157         if (rc)
158                 return rc;
159
160         /* Retrieve the device information */
161         rc = tf_session_get_device(tfs, &dev);
162         if (rc)
163                 return rc;
164
165         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
166         if (rc) {
167                 TFP_DRV_LOG(ERR,
168                             "Failed to get em_ext_db from session, rc:%s\n",
169                             strerror(-rc));
170                 return rc;
171         }
172         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
173
174         /* Only get table info if required for the device */
175         if (dev->ops->tf_dev_get_tbl_info) {
176                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
177                                                    tbl_db->tbl_db[parms->dir],
178                                                    parms->type,
179                                                    &base,
180                                                    &shift);
181                 if (rc) {
182                         TFP_DRV_LOG(ERR,
183                                     "%s: Failed to get table info:%d\n",
184                                     tf_dir_2_str(parms->dir),
185                                     parms->type);
186                         return rc;
187                 }
188         }
189
190         /* Allocate requested element */
191         aparms.rm_db = tbl_db->tbl_db[parms->dir];
192         aparms.subtype = parms->type;
193         aparms.index = &idx;
194         rc = tf_rm_allocate(&aparms);
195         if (rc) {
196                 TFP_DRV_LOG(ERR,
197                             "%s: Failed allocate, type:%d\n",
198                             tf_dir_2_str(parms->dir),
199                             parms->type);
200                 return rc;
201         }
202
203         TF_TBL_RM_TO_PTR(&idx, idx, base, shift);
204         *parms->idx = idx;
205
206         return 0;
207 }
208
209 int
210 tf_tbl_free(struct tf *tfp __rte_unused,
211             struct tf_tbl_free_parms *parms)
212 {
213         int rc;
214         struct tf_rm_is_allocated_parms aparms = { 0 };
215         struct tf_rm_free_parms fparms = { 0 };
216         int allocated = 0;
217         struct tf_session *tfs;
218         struct tf_dev_info *dev;
219         uint16_t base = 0, shift = 0;
220         struct tbl_rm_db *tbl_db;
221         void *tbl_db_ptr = NULL;
222
223         TF_CHECK_PARMS2(tfp, parms);
224
225         /* Retrieve the session information */
226         rc = tf_session_get_session_internal(tfp, &tfs);
227         if (rc)
228                 return rc;
229
230         /* Retrieve the device information */
231         rc = tf_session_get_device(tfs, &dev);
232         if (rc)
233                 return rc;
234
235         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
236         if (rc) {
237                 TFP_DRV_LOG(ERR,
238                             "Failed to get em_ext_db from session, rc:%s\n",
239                             strerror(-rc));
240                 return rc;
241         }
242         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
243
244         /* Only get table info if required for the device */
245         if (dev->ops->tf_dev_get_tbl_info) {
246                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
247                                                    tbl_db->tbl_db[parms->dir],
248                                                    parms->type,
249                                                    &base,
250                                                    &shift);
251                 if (rc) {
252                         TFP_DRV_LOG(ERR,
253                                     "%s: Failed to get table info:%d\n",
254                                     tf_dir_2_str(parms->dir),
255                                     parms->type);
256                         return rc;
257                 }
258         }
259
260         /* Check if element is in use */
261         aparms.rm_db = tbl_db->tbl_db[parms->dir];
262         aparms.subtype = parms->type;
263
264         TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
265
266         aparms.allocated = &allocated;
267         rc = tf_rm_is_allocated(&aparms);
268         if (rc)
269                 return rc;
270
271         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
272                 TFP_DRV_LOG(ERR,
273                             "%s: Entry already free, type:%d, index:%d\n",
274                             tf_dir_2_str(parms->dir),
275                             parms->type,
276                             parms->idx);
277                 return -EINVAL;
278         }
279         /* Free requested element */
280         fparms.rm_db = tbl_db->tbl_db[parms->dir];
281         fparms.subtype = parms->type;
282
283         TF_TBL_PTR_TO_RM(&fparms.index, parms->idx, base, shift);
284
285         rc = tf_rm_free(&fparms);
286         if (rc) {
287                 TFP_DRV_LOG(ERR,
288                             "%s: Free failed, type:%d, index:%d\n",
289                             tf_dir_2_str(parms->dir),
290                             parms->type,
291                             parms->idx);
292                 return rc;
293         }
294
295         return 0;
296 }
297
298 int
299 tf_tbl_alloc_search(struct tf *tfp,
300                     struct tf_tbl_alloc_search_parms *parms)
301 {
302         int rc = 0;
303         TF_CHECK_PARMS2(tfp, parms);
304
305         if (!shadow_init || !shadow_tbl_db[parms->dir]) {
306                 TFP_DRV_LOG(ERR, "%s: Shadow TBL not initialized.\n",
307                             tf_dir_2_str(parms->dir));
308                 return -EINVAL;
309         }
310
311         return rc;
312 }
313
314 int
315 tf_tbl_set(struct tf *tfp,
316            struct tf_tbl_set_parms *parms)
317 {
318         int rc;
319         int allocated = 0;
320         uint16_t hcapi_type;
321         struct tf_rm_is_allocated_parms aparms = { 0 };
322         struct tf_rm_get_hcapi_parms hparms = { 0 };
323         struct tf_session *tfs;
324         struct tf_dev_info *dev;
325         uint16_t base = 0, shift = 0;
326         struct tbl_rm_db *tbl_db;
327         void *tbl_db_ptr = NULL;
328
329         TF_CHECK_PARMS3(tfp, parms, parms->data);
330
331         /* Retrieve the session information */
332         rc = tf_session_get_session_internal(tfp, &tfs);
333         if (rc)
334                 return rc;
335
336         /* Retrieve the device information */
337         rc = tf_session_get_device(tfs, &dev);
338         if (rc)
339                 return rc;
340
341         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
342         if (rc) {
343                 TFP_DRV_LOG(ERR,
344                             "Failed to get em_ext_db from session, rc:%s\n",
345                             strerror(-rc));
346                 return rc;
347         }
348         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
349
350         /* Only get table info if required for the device */
351         if (dev->ops->tf_dev_get_tbl_info) {
352                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
353                                                    tbl_db->tbl_db[parms->dir],
354                                                    parms->type,
355                                                    &base,
356                                                    &shift);
357                 if (rc) {
358                         TFP_DRV_LOG(ERR,
359                                     "%s: Failed to get table info:%d\n",
360                                     tf_dir_2_str(parms->dir),
361                                     parms->type);
362                         return rc;
363                 }
364         }
365
366         /* Verify that the entry has been previously allocated */
367         aparms.rm_db = tbl_db->tbl_db[parms->dir];
368         aparms.subtype = parms->type;
369         TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
370
371         aparms.allocated = &allocated;
372         rc = tf_rm_is_allocated(&aparms);
373         if (rc)
374                 return rc;
375
376         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
377                 TFP_DRV_LOG(ERR,
378                    "%s, Invalid or not allocated index, type:%d, idx:%d\n",
379                    tf_dir_2_str(parms->dir),
380                    parms->type,
381                    parms->idx);
382                 return -EINVAL;
383         }
384
385         /* Set the entry */
386         hparms.rm_db = tbl_db->tbl_db[parms->dir];
387         hparms.subtype = parms->type;
388         hparms.hcapi_type = &hcapi_type;
389         rc = tf_rm_get_hcapi_type(&hparms);
390         if (rc) {
391                 TFP_DRV_LOG(ERR,
392                             "%s, Failed type lookup, type:%d, rc:%s\n",
393                             tf_dir_2_str(parms->dir),
394                             parms->type,
395                             strerror(-rc));
396                 return rc;
397         }
398
399         rc = tf_msg_set_tbl_entry(tfp,
400                                   parms->dir,
401                                   hcapi_type,
402                                   parms->data_sz_in_bytes,
403                                   parms->data,
404                                   parms->idx);
405         if (rc) {
406                 TFP_DRV_LOG(ERR,
407                             "%s, Set failed, type:%d, rc:%s\n",
408                             tf_dir_2_str(parms->dir),
409                             parms->type,
410                             strerror(-rc));
411                 return rc;
412         }
413
414         return 0;
415 }
416
417 int
418 tf_tbl_get(struct tf *tfp,
419            struct tf_tbl_get_parms *parms)
420 {
421         int rc;
422         uint16_t hcapi_type;
423         int allocated = 0;
424         struct tf_rm_is_allocated_parms aparms = { 0 };
425         struct tf_rm_get_hcapi_parms hparms = { 0 };
426         struct tf_session *tfs;
427         struct tf_dev_info *dev;
428         uint16_t base = 0, shift = 0;
429         struct tbl_rm_db *tbl_db;
430         void *tbl_db_ptr = NULL;
431
432         TF_CHECK_PARMS3(tfp, parms, parms->data);
433
434         /* Retrieve the session information */
435         rc = tf_session_get_session_internal(tfp, &tfs);
436         if (rc)
437                 return rc;
438
439         /* Retrieve the device information */
440         rc = tf_session_get_device(tfs, &dev);
441         if (rc)
442                 return rc;
443
444         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
445         if (rc) {
446                 TFP_DRV_LOG(ERR,
447                             "Failed to get em_ext_db from session, rc:%s\n",
448                             strerror(-rc));
449                 return rc;
450         }
451         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
452
453         /* Only get table info if required for the device */
454         if (dev->ops->tf_dev_get_tbl_info) {
455                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
456                                                    tbl_db->tbl_db[parms->dir],
457                                                    parms->type,
458                                                    &base,
459                                                    &shift);
460                 if (rc) {
461                         TFP_DRV_LOG(ERR,
462                                     "%s: Failed to get table info:%d\n",
463                                     tf_dir_2_str(parms->dir),
464                                     parms->type);
465                         return rc;
466                 }
467         }
468
469         /* Verify that the entry has been previously allocated */
470         aparms.rm_db = tbl_db->tbl_db[parms->dir];
471         aparms.subtype = parms->type;
472         TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
473
474         aparms.allocated = &allocated;
475         rc = tf_rm_is_allocated(&aparms);
476         if (rc)
477                 return rc;
478
479         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
480                 TFP_DRV_LOG(ERR,
481                    "%s, Invalid or not allocated index, type:%d, idx:%d\n",
482                    tf_dir_2_str(parms->dir),
483                    parms->type,
484                    parms->idx);
485                 return -EINVAL;
486         }
487
488         /* Set the entry */
489         hparms.rm_db = tbl_db->tbl_db[parms->dir];
490         hparms.subtype = parms->type;
491         hparms.hcapi_type = &hcapi_type;
492         rc = tf_rm_get_hcapi_type(&hparms);
493         if (rc) {
494                 TFP_DRV_LOG(ERR,
495                             "%s, Failed type lookup, type:%d, rc:%s\n",
496                             tf_dir_2_str(parms->dir),
497                             parms->type,
498                             strerror(-rc));
499                 return rc;
500         }
501
502         /* Get the entry */
503         rc = tf_msg_get_tbl_entry(tfp,
504                                   parms->dir,
505                                   hcapi_type,
506                                   parms->data_sz_in_bytes,
507                                   parms->data,
508                                   parms->idx);
509         if (rc) {
510                 TFP_DRV_LOG(ERR,
511                             "%s, Get failed, type:%d, rc:%s\n",
512                             tf_dir_2_str(parms->dir),
513                             parms->type,
514                             strerror(-rc));
515                 return rc;
516         }
517
518         return 0;
519 }
520
521 int
522 tf_tbl_bulk_get(struct tf *tfp,
523                 struct tf_tbl_get_bulk_parms *parms)
524 {
525         int rc;
526         uint16_t hcapi_type;
527         struct tf_rm_get_hcapi_parms hparms = { 0 };
528         struct tf_rm_check_indexes_in_range_parms cparms = { 0 };
529         struct tf_session *tfs;
530         struct tf_dev_info *dev;
531         uint16_t base = 0, shift = 0;
532         struct tbl_rm_db *tbl_db;
533         void *tbl_db_ptr = NULL;
534
535         TF_CHECK_PARMS2(tfp, parms);
536
537         /* Retrieve the session information */
538         rc = tf_session_get_session_internal(tfp, &tfs);
539         if (rc)
540                 return rc;
541
542         /* Retrieve the device information */
543         rc = tf_session_get_device(tfs, &dev);
544         if (rc)
545                 return rc;
546
547         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
548         if (rc) {
549                 TFP_DRV_LOG(ERR,
550                             "Failed to get em_ext_db from session, rc:%s\n",
551                             strerror(-rc));
552                 return rc;
553         }
554         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
555
556         /* Only get table info if required for the device */
557         if (dev->ops->tf_dev_get_tbl_info) {
558                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
559                                                    tbl_db->tbl_db[parms->dir],
560                                                    parms->type,
561                                                    &base,
562                                                    &shift);
563                 if (rc) {
564                         TFP_DRV_LOG(ERR,
565                                     "%s: Failed to get table info:%d\n",
566                                     tf_dir_2_str(parms->dir),
567                                     parms->type);
568                         return rc;
569                 }
570         }
571
572         /* Verify that the entries are in the range of reserved resources. */
573         cparms.rm_db = tbl_db->tbl_db[parms->dir];
574         cparms.subtype = parms->type;
575
576         TF_TBL_PTR_TO_RM(&cparms.starting_index, parms->starting_idx,
577                          base, shift);
578
579         cparms.num_entries = parms->num_entries;
580
581         rc = tf_rm_check_indexes_in_range(&cparms);
582         if (rc) {
583                 TFP_DRV_LOG(ERR,
584                             "%s, Invalid or %d index starting from %d"
585                             " not in range, type:%d",
586                             tf_dir_2_str(parms->dir),
587                             parms->starting_idx,
588                             parms->num_entries,
589                             parms->type);
590                 return rc;
591         }
592
593         hparms.rm_db = tbl_db->tbl_db[parms->dir];
594         hparms.subtype = parms->type;
595         hparms.hcapi_type = &hcapi_type;
596         rc = tf_rm_get_hcapi_type(&hparms);
597         if (rc) {
598                 TFP_DRV_LOG(ERR,
599                             "%s, Failed type lookup, type:%d, rc:%s\n",
600                             tf_dir_2_str(parms->dir),
601                             parms->type,
602                             strerror(-rc));
603                 return rc;
604         }
605
606         /* Get the entries */
607         rc = tf_msg_bulk_get_tbl_entry(tfp,
608                                        parms->dir,
609                                        hcapi_type,
610                                        parms->starting_idx,
611                                        parms->num_entries,
612                                        parms->entry_sz_in_bytes,
613                                        parms->physical_mem_addr);
614         if (rc) {
615                 TFP_DRV_LOG(ERR,
616                             "%s, Bulk get failed, type:%d, rc:%s\n",
617                             tf_dir_2_str(parms->dir),
618                             parms->type,
619                             strerror(-rc));
620         }
621
622         return rc;
623 }
624
625 int
626 tf_tbl_get_resc_info(struct tf *tfp,
627                      struct tf_tbl_resource_info *tbl)
628 {
629         int rc;
630         int d, i;
631         struct tf_resource_info *dinfo;
632         struct tf_rm_get_alloc_info_parms ainfo;
633         void *tbl_db_ptr = NULL;
634         struct tbl_rm_db *tbl_db;
635         uint16_t base = 0, shift = 0;
636         struct tf_dev_info *dev;
637         struct tf_session *tfs;
638
639         TF_CHECK_PARMS2(tfp, tbl);
640
641         /* Retrieve the session information */
642         rc = tf_session_get_session_internal(tfp, &tfs);
643         if (rc)
644                 return rc;
645
646         /* Retrieve the device information */
647         rc = tf_session_get_device(tfs, &dev);
648         if (rc)
649                 return rc;
650
651         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
652         if (rc) {
653                 TFP_DRV_LOG(INFO,
654                             "No resource allocated for table from session\n");
655                 return 0;
656         }
657         tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
658
659
660         /* check if reserved resource for WC is multiple of num_slices */
661         for (d = 0; d < TF_DIR_MAX; d++) {
662                 ainfo.rm_db = tbl_db->tbl_db[d];
663                 dinfo = tbl[d].info;
664
665                 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
666                 ainfo.subtype = 0;
667                 rc = tf_rm_get_all_info(&ainfo, TF_TBL_TYPE_MAX);
668                 if (rc)
669                         return rc;
670
671                 if (dev->ops->tf_dev_get_tbl_info) {
672                         /* Adjust all */
673                         for (i = 0; i < TF_TBL_TYPE_MAX; i++) {
674                                 /* Only get table info if required for the device */
675                                 rc = dev->ops->tf_dev_get_tbl_info(tfp,
676                                                                    tbl_db->tbl_db[d],
677                                                                    i,
678                                                                    &base,
679                                                                    &shift);
680                                 if (rc) {
681                                         TFP_DRV_LOG(ERR,
682                                                     "%s: Failed to get table info:%d\n",
683                                                     tf_dir_2_str(d),
684                                                     i);
685                                         return rc;
686                                 }
687                                 if (dinfo[i].stride)
688                                         TF_TBL_RM_TO_PTR(&dinfo[i].start,
689                                                          dinfo[i].start,
690                                                          base,
691                                                          shift);
692                         }
693                 }
694         }
695
696
697
698         return 0;
699 }