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