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