eal: remove sys/queue.h from public headers
[dpdk.git] / drivers / net / bnxt / tf_core / tf_tcam.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <string.h>
7 #include <rte_common.h>
8
9 #include "tf_tcam.h"
10 #include "tf_common.h"
11 #include "tf_util.h"
12 #include "tf_rm.h"
13 #include "tf_device.h"
14 #include "tfp.h"
15 #include "tf_session.h"
16 #include "tf_msg.h"
17 #include "tf_shadow_tcam.h"
18
19 struct tf;
20
21 /**
22  * TCAM Shadow DBs
23  */
24 static void *shadow_tcam_db[TF_DIR_MAX];
25
26 /**
27  * Shadow init flag, set on bind and cleared on unbind
28  */
29 static uint8_t shadow_init;
30
31 int
32 tf_tcam_bind(struct tf *tfp,
33              struct tf_tcam_cfg_parms *parms)
34 {
35         int rc;
36         int db_rc[TF_DIR_MAX] = { 0 };
37         int i, d;
38         struct tf_rm_alloc_info info;
39         struct tf_rm_free_db_parms fparms;
40         struct tf_rm_create_db_parms db_cfg;
41         struct tf_tcam_resources *tcam_cnt;
42         struct tf_rm_get_alloc_info_parms ainfo;
43         struct tf_shadow_tcam_free_db_parms fshadow;
44         struct tf_shadow_tcam_cfg_parms shadow_cfg;
45         struct tf_shadow_tcam_create_db_parms shadow_cdb;
46         uint16_t num_slices = parms->wc_num_slices;
47         struct tf_session *tfs;
48         struct tf_dev_info *dev;
49         struct tcam_rm_db *tcam_db;
50         struct tfp_calloc_parms cparms;
51
52         TF_CHECK_PARMS2(tfp, parms);
53
54         /* Retrieve the session information */
55         rc = tf_session_get_session_internal(tfp, &tfs);
56         if (rc)
57                 return rc;
58
59         /* Retrieve the device information */
60         rc = tf_session_get_device(tfs, &dev);
61         if (rc)
62                 return rc;
63
64         if (dev->ops->tf_dev_set_tcam_slice_info == NULL) {
65                 rc = -EOPNOTSUPP;
66                 TFP_DRV_LOG(ERR,
67                             "Operation not supported, rc:%s\n",
68                             strerror(-rc));
69                 return rc;
70         }
71
72         rc = dev->ops->tf_dev_set_tcam_slice_info(tfp,
73                                                   num_slices);
74         if (rc)
75                 return rc;
76
77         tcam_cnt = parms->resources->tcam_cnt;
78         if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices) ||
79             (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices)) {
80                 TFP_DRV_LOG(ERR,
81                             "Requested num of WC TCAM entries has to be multiple %d\n",
82                             num_slices);
83                 return -EINVAL;
84         }
85
86         memset(&db_cfg, 0, sizeof(db_cfg));
87         cparms.nitems = 1;
88         cparms.size = sizeof(struct tcam_rm_db);
89         cparms.alignment = 0;
90         if (tfp_calloc(&cparms) != 0) {
91                 TFP_DRV_LOG(ERR, "tcam_rm_db alloc error %s\n",
92                             strerror(ENOMEM));
93                 return -ENOMEM;
94         }
95
96         tcam_db = cparms.mem_va;
97         for (i = 0; i < TF_DIR_MAX; i++)
98                 tcam_db->tcam_db[i] = NULL;
99         tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, tcam_db);
100
101         db_cfg.module = TF_MODULE_TYPE_TCAM;
102         db_cfg.num_elements = parms->num_elements;
103         db_cfg.cfg = parms->cfg;
104
105         for (d = 0; d < TF_DIR_MAX; d++) {
106                 db_cfg.dir = d;
107                 db_cfg.alloc_cnt = parms->resources->tcam_cnt[d].cnt;
108                 db_cfg.rm_db = (void *)&tcam_db->tcam_db[d];
109                 if (tf_session_is_shared_session(tfs) &&
110                         (!tf_session_is_shared_session_creator(tfs)))
111                         db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
112                 else
113                         db_rc[d] = tf_rm_create_db(tfp, &db_cfg);
114         }
115
116         /* No db created */
117         if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
118                 TFP_DRV_LOG(ERR, "No TCAM DB created\n");
119                 return db_rc[TF_DIR_RX];
120         }
121
122         /* check if reserved resource for WC is multiple of num_slices */
123         for (d = 0; d < TF_DIR_MAX; d++) {
124                 if (!tcam_db->tcam_db[d])
125                         continue;
126
127                 memset(&info, 0, sizeof(info));
128                 ainfo.rm_db = tcam_db->tcam_db[d];
129                 ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
130                 ainfo.info = &info;
131                 rc = tf_rm_get_info(&ainfo);
132                 if (rc)
133                         goto error;
134
135                 if (info.entry.start % num_slices != 0 ||
136                     info.entry.stride % num_slices != 0) {
137                         TFP_DRV_LOG(ERR,
138                                     "%s: TCAM reserved resource is not multiple of %d\n",
139                                     tf_dir_2_str(d),
140                                     num_slices);
141                         rc = -EINVAL;
142                         goto error;
143                 }
144         }
145
146         /* Initialize the TCAM manager. */
147         if (parms->shadow_copy) {
148                 for (d = 0; d < TF_DIR_MAX; d++) {
149                         memset(&shadow_cfg, 0, sizeof(shadow_cfg));
150                         memset(&shadow_cdb, 0, sizeof(shadow_cdb));
151                         /* Get the base addresses of the tcams for tcam mgr */
152                         for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
153                                 memset(&info, 0, sizeof(info));
154
155                                 if (!parms->resources->tcam_cnt[d].cnt[i])
156                                         continue;
157                                 ainfo.rm_db = tcam_db->tcam_db[d];
158                                 ainfo.subtype = i;
159                                 ainfo.info = &info;
160                                 rc = tf_rm_get_info(&ainfo);
161                                 if (rc)
162                                         goto error;
163
164                                 shadow_cfg.base_addr[i] = info.entry.start;
165                         }
166
167                         /* Create the shadow db */
168                         shadow_cfg.alloc_cnt =
169                                 parms->resources->tcam_cnt[d].cnt;
170                         shadow_cfg.num_entries = parms->num_elements;
171
172                         shadow_cdb.shadow_db = &shadow_tcam_db[d];
173                         shadow_cdb.cfg = &shadow_cfg;
174                         rc = tf_shadow_tcam_create_db(&shadow_cdb);
175                         if (rc) {
176                                 TFP_DRV_LOG(ERR,
177                                             "TCAM MGR DB creation failed "
178                                             "rc=%d\n", rc);
179                                 goto error;
180                         }
181                 }
182                 shadow_init = 1;
183         }
184
185         TFP_DRV_LOG(INFO,
186                     "TCAM - initialized\n");
187
188         return 0;
189 error:
190         for (i = 0; i < TF_DIR_MAX; i++) {
191                 memset(&fparms, 0, sizeof(fparms));
192                 fparms.dir = i;
193                 fparms.rm_db = tcam_db->tcam_db[i];
194                 /* Ignoring return here since we are in the error case */
195                 (void)tf_rm_free_db(tfp, &fparms);
196
197                 if (parms->shadow_copy) {
198                         fshadow.shadow_db = shadow_tcam_db[i];
199                         tf_shadow_tcam_free_db(&fshadow);
200                         shadow_tcam_db[i] = NULL;
201                 }
202
203                 tcam_db->tcam_db[i] = NULL;
204                 tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL);
205         }
206
207         shadow_init = 0;
208
209         return rc;
210 }
211
212 int
213 tf_tcam_unbind(struct tf *tfp)
214 {
215         int rc;
216         int i;
217         struct tf_rm_free_db_parms fparms;
218         struct tcam_rm_db *tcam_db;
219         void *tcam_db_ptr = NULL;
220         struct tf_shadow_tcam_free_db_parms fshadow;
221         TF_CHECK_PARMS1(tfp);
222
223         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
224         if (rc) {
225                 return 0;
226         }
227         tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
228
229         for (i = 0; i < TF_DIR_MAX; i++) {
230                 if (tcam_db->tcam_db[i] == NULL)
231                         continue;
232                 memset(&fparms, 0, sizeof(fparms));
233                 fparms.dir = i;
234                 fparms.rm_db = tcam_db->tcam_db[i];
235                 rc = tf_rm_free_db(tfp, &fparms);
236                 if (rc)
237                         return rc;
238
239                 tcam_db->tcam_db[i] = NULL;
240
241                 if (shadow_init) {
242                         memset(&fshadow, 0, sizeof(fshadow));
243
244                         fshadow.shadow_db = shadow_tcam_db[i];
245                         tf_shadow_tcam_free_db(&fshadow);
246                         shadow_tcam_db[i] = NULL;
247                 }
248         }
249
250         shadow_init = 0;
251
252         return 0;
253 }
254
255 int
256 tf_tcam_alloc(struct tf *tfp,
257               struct tf_tcam_alloc_parms *parms)
258 {
259         int rc, i;
260         struct tf_session *tfs;
261         struct tf_dev_info *dev;
262         struct tf_rm_allocate_parms aparms;
263         uint16_t num_slices = 1;
264         uint32_t index;
265         struct tcam_rm_db *tcam_db;
266         void *tcam_db_ptr = NULL;
267
268         TF_CHECK_PARMS2(tfp, parms);
269
270         /* Retrieve the session information */
271         rc = tf_session_get_session_internal(tfp, &tfs);
272         if (rc)
273                 return rc;
274
275         /* Retrieve the device information */
276         rc = tf_session_get_device(tfs, &dev);
277         if (rc)
278                 return rc;
279
280         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
281                 rc = -EOPNOTSUPP;
282                 TFP_DRV_LOG(ERR,
283                             "%s: Operation not supported, rc:%s\n",
284                             tf_dir_2_str(parms->dir),
285                             strerror(-rc));
286                 return rc;
287         }
288
289         /* Need to retrieve number of slices based on the key_size */
290         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
291                                                   parms->type,
292                                                   parms->key_size,
293                                                   &num_slices);
294         if (rc)
295                 return rc;
296
297         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
298         if (rc) {
299                 TFP_DRV_LOG(ERR,
300                             "Failed to get tcam_db from session, rc:%s\n",
301                             strerror(-rc));
302                 return rc;
303         }
304         tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
305
306         /*
307          * For WC TCAM, number of slices could be 4, 2, 1 based on
308          * the key_size. For other TCAM, it is always 1
309          */
310         for (i = 0; i < num_slices; i++) {
311                 memset(&aparms, 0, sizeof(aparms));
312                 aparms.rm_db = tcam_db->tcam_db[parms->dir];
313                 aparms.subtype = parms->type;
314                 aparms.priority = parms->priority;
315                 aparms.index = &index;
316                 rc = tf_rm_allocate(&aparms);
317                 if (rc) {
318                         TFP_DRV_LOG(ERR,
319                                     "%s: Failed tcam, type:%d\n",
320                                     tf_dir_2_str(parms->dir),
321                                     parms->type);
322                         return rc;
323                 }
324
325                 /* return the start index of each row */
326                 if (parms->priority == 0) {
327                         if (i == 0)
328                                 parms->idx = index;
329                 } else {
330                         parms->idx = index;
331                 }
332         }
333
334         return 0;
335 }
336
337 int
338 tf_tcam_free(struct tf *tfp,
339              struct tf_tcam_free_parms *parms)
340 {
341         int rc;
342         struct tf_session *tfs;
343         struct tf_dev_info *dev;
344         struct tf_rm_is_allocated_parms aparms;
345         struct tf_rm_free_parms fparms;
346         struct tf_rm_get_hcapi_parms hparms;
347         uint16_t num_slices = 1;
348         int allocated = 0;
349         struct tf_shadow_tcam_remove_parms shparms;
350         int i;
351         struct tcam_rm_db *tcam_db;
352         void *tcam_db_ptr = NULL;
353
354         TF_CHECK_PARMS2(tfp, parms);
355
356         /* Retrieve the session information */
357         rc = tf_session_get_session_internal(tfp, &tfs);
358         if (rc)
359                 return rc;
360
361         /* Retrieve the device information */
362         rc = tf_session_get_device(tfs, &dev);
363         if (rc)
364                 return rc;
365
366         if (dev->ops->tf_dev_get_tcam_slice_info == 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 rc;
373         }
374
375         /* Need to retrieve row size etc */
376         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
377                                                   parms->type,
378                                                   0,
379                                                   &num_slices);
380         if (rc)
381                 return rc;
382
383         if (parms->idx % num_slices) {
384                 TFP_DRV_LOG(ERR,
385                             "%s: TCAM reserved resource is not multiple of %d\n",
386                             tf_dir_2_str(parms->dir),
387                             num_slices);
388                 return -EINVAL;
389         }
390
391         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
392         if (rc) {
393                 TFP_DRV_LOG(ERR,
394                             "Failed to get em_ext_db from session, rc:%s\n",
395                             strerror(-rc));
396                 return rc;
397         }
398         tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
399
400         /* Check if element is in use */
401         memset(&aparms, 0, sizeof(aparms));
402         aparms.rm_db = tcam_db->tcam_db[parms->dir];
403         aparms.subtype = parms->type;
404         aparms.index = parms->idx;
405         aparms.allocated = &allocated;
406         rc = tf_rm_is_allocated(&aparms);
407         if (rc)
408                 return rc;
409
410         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
411                 TFP_DRV_LOG(ERR,
412                             "%s: Entry already free, type:%d, index:%d\n",
413                             tf_dir_2_str(parms->dir),
414                             parms->type,
415                             parms->idx);
416                 return -EINVAL;
417         }
418
419         /*
420          * The Shadow mgmt, if enabled, determines if the entry needs
421          * to be deleted.
422          */
423         if (shadow_init) {
424                 shparms.shadow_db = shadow_tcam_db[parms->dir];
425                 shparms.fparms = parms;
426                 rc = tf_shadow_tcam_remove(&shparms);
427                 if (rc) {
428                         /*
429                          * Should not get here, log it and let the entry be
430                          * deleted.
431                          */
432                         TFP_DRV_LOG(ERR, "%s: Shadow free fail, "
433                                     "type:%d index:%d deleting the entry.\n",
434                                     tf_dir_2_str(parms->dir),
435                                     parms->type,
436                                     parms->idx);
437                 } else {
438                         /*
439                          * If the entry still has references, just return the
440                          * ref count to the caller.  No need to remove entry
441                          * from rm or hw
442                          */
443                         if (parms->ref_cnt >= 1)
444                                 return rc;
445                 }
446         }
447
448         for (i = 0; i < num_slices; i++) {
449                 /* Free requested element */
450                 memset(&fparms, 0, sizeof(fparms));
451                 fparms.rm_db = tcam_db->tcam_db[parms->dir];
452                 fparms.subtype = parms->type;
453                 fparms.index = parms->idx + i;
454                 rc = tf_rm_free(&fparms);
455                 if (rc) {
456                         TFP_DRV_LOG(ERR,
457                                     "%s: Free failed, type:%d, index:%d\n",
458                                     tf_dir_2_str(parms->dir),
459                                     parms->type,
460                                     parms->idx);
461                         return rc;
462                 }
463         }
464
465         /* Convert TF type to HCAPI RM type */
466         memset(&hparms, 0, sizeof(hparms));
467
468         hparms.rm_db = tcam_db->tcam_db[parms->dir];
469         hparms.subtype = parms->type;
470         hparms.hcapi_type = &parms->hcapi_type;
471
472         rc = tf_rm_get_hcapi_type(&hparms);
473         if (rc)
474                 return rc;
475
476         rc = tf_msg_tcam_entry_free(tfp, dev, parms);
477         if (rc) {
478                 /* Log error */
479                 TFP_DRV_LOG(ERR,
480                             "%s: %s: Entry %d free failed, rc:%s\n",
481                             tf_dir_2_str(parms->dir),
482                             tf_tcam_tbl_2_str(parms->type),
483                             parms->idx,
484                             strerror(-rc));
485                 return rc;
486         }
487
488         return 0;
489 }
490
491 int
492 tf_tcam_alloc_search(struct tf *tfp,
493                      struct tf_tcam_alloc_search_parms *parms)
494 {
495         struct tf_shadow_tcam_search_parms sparms;
496         struct tf_shadow_tcam_bind_index_parms bparms;
497         struct tf_tcam_free_parms fparms;
498         struct tf_tcam_alloc_parms aparms;
499         uint16_t num_slice_per_row = 1;
500         struct tf_session *tfs;
501         struct tf_dev_info *dev;
502         int rc;
503
504         TF_CHECK_PARMS2(tfp, parms);
505
506         if (!shadow_init || !shadow_tcam_db[parms->dir]) {
507                 TFP_DRV_LOG(ERR, "%s: TCAM Shadow not initialized for %s\n",
508                             tf_dir_2_str(parms->dir),
509                             tf_tcam_tbl_2_str(parms->type));
510                 return -EINVAL;
511         }
512
513         /* Retrieve the session information */
514         rc = tf_session_get_session_internal(tfp, &tfs);
515         if (rc)
516                 return rc;
517
518         /* Retrieve the device information */
519         rc = tf_session_get_device(tfs, &dev);
520         if (rc)
521                 return rc;
522
523         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
524                 rc = -EOPNOTSUPP;
525                 TFP_DRV_LOG(ERR,
526                             "%s: Operation not supported, rc:%s\n",
527                             tf_dir_2_str(parms->dir),
528                             strerror(-rc));
529                 return rc;
530         }
531
532         /* Need to retrieve row size etc */
533         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
534                                                   parms->type,
535                                                   parms->key_size,
536                                                   &num_slice_per_row);
537         if (rc)
538                 return rc;
539
540         /*
541          * Prep the shadow search, reusing the parms from original search
542          * instead of copying them.  Shadow will update output in there.
543          */
544         memset(&sparms, 0, sizeof(sparms));
545         sparms.sparms = parms;
546         sparms.shadow_db = shadow_tcam_db[parms->dir];
547
548         rc = tf_shadow_tcam_search(&sparms);
549         if (rc)
550                 return rc;
551
552         /*
553          * The app didn't request us to alloc the entry, so return now.
554          * The hit should have been updated in the original search parm.
555          */
556         if (!parms->alloc || parms->search_status != MISS)
557                 return rc;
558
559         /* Caller desires an allocate on miss */
560         if (dev->ops->tf_dev_alloc_tcam == NULL) {
561                 rc = -EOPNOTSUPP;
562                 TFP_DRV_LOG(ERR,
563                             "%s: Operation not supported, rc:%s\n",
564                             tf_dir_2_str(parms->dir),
565                             strerror(-rc));
566                 return rc;
567         }
568         memset(&aparms, 0, sizeof(aparms));
569         aparms.dir = parms->dir;
570         aparms.type = parms->type;
571         aparms.key_size = parms->key_size;
572         aparms.priority = parms->priority;
573         rc = dev->ops->tf_dev_alloc_tcam(tfp, &aparms);
574         if (rc)
575                 return rc;
576
577         /* Successful allocation, attempt to add it to the shadow */
578         memset(&bparms, 0, sizeof(bparms));
579         bparms.dir = parms->dir;
580         bparms.shadow_db = shadow_tcam_db[parms->dir];
581         bparms.type = parms->type;
582         bparms.key = parms->key;
583         bparms.mask = parms->mask;
584         bparms.key_size = parms->key_size;
585         bparms.idx = aparms.idx;
586         bparms.hb_handle = sparms.hb_handle;
587         rc = tf_shadow_tcam_bind_index(&bparms);
588         if (rc) {
589                 /* Error binding entry, need to free the allocated idx */
590                 if (dev->ops->tf_dev_free_tcam == NULL) {
591                         rc = -EOPNOTSUPP;
592                         TFP_DRV_LOG(ERR,
593                                     "%s: Operation not supported, rc:%s\n",
594                                     tf_dir_2_str(parms->dir),
595                                     strerror(-rc));
596                         return rc;
597                 }
598
599                 fparms.dir = parms->dir;
600                 fparms.type = parms->type;
601                 fparms.idx = aparms.idx;
602                 rc = dev->ops->tf_dev_free_tcam(tfp, &fparms);
603                 if (rc)
604                         return rc;
605         }
606
607         /* Add the allocated index to output and done */
608         parms->idx = aparms.idx;
609
610         return 0;
611 }
612
613 int
614 tf_tcam_set(struct tf *tfp __rte_unused,
615             struct tf_tcam_set_parms *parms __rte_unused)
616 {
617         int rc;
618         struct tf_session *tfs;
619         struct tf_dev_info *dev;
620         struct tf_rm_is_allocated_parms aparms;
621         struct tf_rm_get_hcapi_parms hparms;
622         struct tf_shadow_tcam_insert_parms iparms;
623         uint16_t num_slice_per_row = 1;
624         int allocated = 0;
625         struct tcam_rm_db *tcam_db;
626         void *tcam_db_ptr = NULL;
627
628         TF_CHECK_PARMS2(tfp, parms);
629
630         /* Retrieve the session information */
631         rc = tf_session_get_session_internal(tfp, &tfs);
632         if (rc)
633                 return rc;
634
635         /* Retrieve the device information */
636         rc = tf_session_get_device(tfs, &dev);
637         if (rc)
638                 return rc;
639
640         if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
641                 rc = -EOPNOTSUPP;
642                 TFP_DRV_LOG(ERR,
643                             "%s: Operation not supported, rc:%s\n",
644                             tf_dir_2_str(parms->dir),
645                             strerror(-rc));
646                 return rc;
647         }
648
649         /* Need to retrieve row size etc */
650         rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
651                                                   parms->type,
652                                                   parms->key_size,
653                                                   &num_slice_per_row);
654         if (rc)
655                 return rc;
656
657         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
658         if (rc) {
659                 TFP_DRV_LOG(ERR,
660                             "Failed to get em_ext_db from session, rc:%s\n",
661                             strerror(-rc));
662                 return rc;
663         }
664         tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
665
666         /* Check if element is in use */
667         memset(&aparms, 0, sizeof(aparms));
668
669         aparms.rm_db = tcam_db->tcam_db[parms->dir];
670         aparms.subtype = parms->type;
671         aparms.index = parms->idx;
672         aparms.allocated = &allocated;
673         rc = tf_rm_is_allocated(&aparms);
674         if (rc)
675                 return rc;
676
677         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
678                 TFP_DRV_LOG(ERR,
679                             "%s: Entry is not allocated, type:%d, index:%d\n",
680                             tf_dir_2_str(parms->dir),
681                             parms->type,
682                             parms->idx);
683                 return -EINVAL;
684         }
685
686         /* Convert TF type to HCAPI RM type */
687         memset(&hparms, 0, sizeof(hparms));
688
689         hparms.rm_db = tcam_db->tcam_db[parms->dir];
690         hparms.subtype = parms->type;
691         hparms.hcapi_type = &parms->hcapi_type;
692
693         rc = tf_rm_get_hcapi_type(&hparms);
694         if (rc)
695                 return rc;
696
697         rc = tf_msg_tcam_entry_set(tfp, dev, parms);
698         if (rc) {
699                 /* Log error */
700                 TFP_DRV_LOG(ERR,
701                             "%s: %s: Entry %d set failed, rc:%s",
702                             tf_dir_2_str(parms->dir),
703                             tf_tcam_tbl_2_str(parms->type),
704                             parms->idx,
705                             strerror(-rc));
706                 return rc;
707         }
708
709         /* Successfully added to hw, now for shadow if enabled. */
710         if (!shadow_init || !shadow_tcam_db[parms->dir])
711                 return 0;
712
713         iparms.shadow_db = shadow_tcam_db[parms->dir];
714         iparms.sparms = parms;
715         rc = tf_shadow_tcam_insert(&iparms);
716         if (rc) {
717                 TFP_DRV_LOG(ERR,
718                             "%s: %s: Entry %d set failed, rc:%s",
719                             tf_dir_2_str(parms->dir),
720                             tf_tcam_tbl_2_str(parms->type),
721                             parms->idx,
722                             strerror(-rc));
723                 return rc;
724         }
725
726         return 0;
727 }
728
729 int
730 tf_tcam_get(struct tf *tfp __rte_unused,
731             struct tf_tcam_get_parms *parms)
732 {
733         int rc;
734         struct tf_session *tfs;
735         struct tf_dev_info *dev;
736         struct tf_rm_is_allocated_parms aparms;
737         struct tf_rm_get_hcapi_parms hparms;
738         int allocated = 0;
739         struct tcam_rm_db *tcam_db;
740         void *tcam_db_ptr = NULL;
741
742         TF_CHECK_PARMS2(tfp, parms);
743
744         /* Retrieve the session information */
745         rc = tf_session_get_session_internal(tfp, &tfs);
746         if (rc)
747                 return rc;
748
749         /* Retrieve the device information */
750         rc = tf_session_get_device(tfs, &dev);
751         if (rc)
752                 return rc;
753
754         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
755         if (rc) {
756                 TFP_DRV_LOG(ERR,
757                             "Failed to get em_ext_db from session, rc:%s\n",
758                             strerror(-rc));
759                 return rc;
760         }
761         tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
762
763         /* Check if element is in use */
764         memset(&aparms, 0, sizeof(aparms));
765
766         aparms.rm_db = tcam_db->tcam_db[parms->dir];
767         aparms.subtype = parms->type;
768         aparms.index = parms->idx;
769         aparms.allocated = &allocated;
770         rc = tf_rm_is_allocated(&aparms);
771         if (rc)
772                 return rc;
773
774         if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
775                 TFP_DRV_LOG(ERR,
776                             "%s: Entry is not allocated, type:%d, index:%d\n",
777                             tf_dir_2_str(parms->dir),
778                             parms->type,
779                             parms->idx);
780                 return -EINVAL;
781         }
782
783         /* Convert TF type to HCAPI RM type */
784         memset(&hparms, 0, sizeof(hparms));
785
786         hparms.rm_db = tcam_db->tcam_db[parms->dir];
787         hparms.subtype = parms->type;
788         hparms.hcapi_type = &parms->hcapi_type;
789
790         rc = tf_rm_get_hcapi_type(&hparms);
791         if (rc)
792                 return rc;
793
794         rc = tf_msg_tcam_entry_get(tfp, dev, parms);
795         if (rc) {
796                 /* Log error */
797                 TFP_DRV_LOG(ERR,
798                             "%s: %s: Entry %d set failed, rc:%s",
799                             tf_dir_2_str(parms->dir),
800                             tf_tcam_tbl_2_str(parms->type),
801                             parms->idx,
802                             strerror(-rc));
803                 return rc;
804         }
805
806         return 0;
807 }
808
809 int
810 tf_tcam_get_resc_info(struct tf *tfp,
811                       struct tf_tcam_resource_info *tcam)
812 {
813         int rc;
814         int d;
815         struct tf_resource_info *dinfo;
816         struct tf_rm_get_alloc_info_parms ainfo;
817         void *tcam_db_ptr = NULL;
818         struct tcam_rm_db *tcam_db;
819
820         TF_CHECK_PARMS2(tfp, tcam);
821
822         rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
823         if (rc == -ENOMEM)
824                 return 0;  /* db doesn't exist */
825         else if (rc)
826                 return rc; /* error getting db */
827
828         tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
829
830         /* check if reserved resource for WC is multiple of num_slices */
831         for (d = 0; d < TF_DIR_MAX; d++) {
832                 ainfo.rm_db = tcam_db->tcam_db[d];
833
834                 if (!ainfo.rm_db)
835                         continue;
836
837                 dinfo = tcam[d].info;
838
839                 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
840                 ainfo.subtype = 0;
841                 rc = tf_rm_get_all_info(&ainfo, TF_TCAM_TBL_TYPE_MAX);
842                 if (rc && rc != -ENOTSUP)
843                         return rc;
844         }
845
846         return 0;
847 }