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