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