net/bnxt: support exact match
[dpdk.git] / drivers / net / bnxt / tf_core / tf_core.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <stdio.h>
7
8 #include "tf_core.h"
9 #include "tf_session.h"
10 #include "tf_tbl.h"
11 #include "tf_em.h"
12 #include "tf_rm.h"
13 #include "tf_msg.h"
14 #include "tfp.h"
15 #include "bitalloc.h"
16 #include "bnxt.h"
17 #include "rand.h"
18
19 static inline uint32_t SWAP_WORDS32(uint32_t val32)
20 {
21         return (((val32 & 0x0000ffff) << 16) |
22                 ((val32 & 0xffff0000) >> 16));
23 }
24
25 static void tf_seeds_init(struct tf_session *session)
26 {
27         int i;
28         uint32_t r;
29
30         /* Initialize the lfsr */
31         rand_init();
32
33         /* RX and TX use the same seed values */
34         session->lkup_lkup3_init_cfg[TF_DIR_RX] =
35                 session->lkup_lkup3_init_cfg[TF_DIR_TX] =
36                                                 SWAP_WORDS32(rand32());
37
38         for (i = 0; i < TF_LKUP_SEED_MEM_SIZE / 2; i++) {
39                 r = SWAP_WORDS32(rand32());
40                 session->lkup_em_seed_mem[TF_DIR_RX][i * 2] = r;
41                 session->lkup_em_seed_mem[TF_DIR_TX][i * 2] = r;
42                 r = SWAP_WORDS32(rand32());
43                 session->lkup_em_seed_mem[TF_DIR_RX][i * 2 + 1] = (r & 0x1);
44                 session->lkup_em_seed_mem[TF_DIR_TX][i * 2 + 1] = (r & 0x1);
45         }
46 }
47
48 /**
49  * Create EM Tbl pool of memory indexes.
50  *
51  * [in] session
52  *   Pointer to session
53  * [in] dir
54  *   direction
55  * [in] num_entries
56  *   number of entries to write
57  *
58  * Return:
59  *  0       - Success, entry allocated - no search support
60  *  -ENOMEM -EINVAL -EOPNOTSUPP
61  *          - Failure, entry not allocated, out of resources
62  */
63 static int
64 tf_create_em_pool(struct tf_session *session,
65                   enum tf_dir dir,
66                   uint32_t num_entries)
67 {
68         struct tfp_calloc_parms parms;
69         uint32_t i, j;
70         int rc = 0;
71         struct stack *pool = &session->em_pool[dir];
72
73         parms.nitems = num_entries;
74         parms.size = sizeof(uint32_t);
75         parms.alignment = 0;
76
77         if (tfp_calloc(&parms) != 0) {
78                 TFP_DRV_LOG(ERR, "EM pool allocation failure %s\n",
79                             strerror(-ENOMEM));
80                 return -ENOMEM;
81         }
82
83         /* Create empty stack
84          */
85         rc = stack_init(num_entries, parms.mem_va, pool);
86
87         if (rc != 0) {
88                 TFP_DRV_LOG(ERR, "EM pool stack init failure %s\n",
89                             strerror(-rc));
90                 goto cleanup;
91         }
92
93         /* Fill pool with indexes
94          */
95         j = num_entries - 1;
96
97         for (i = 0; i < num_entries; i++) {
98                 rc = stack_push(pool, j);
99                 if (rc != 0) {
100                         TFP_DRV_LOG(ERR, "EM pool stack push failure %s\n",
101                                     strerror(-rc));
102                         goto cleanup;
103                 }
104                 j--;
105         }
106
107         if (!stack_is_full(pool)) {
108                 rc = -EINVAL;
109                 TFP_DRV_LOG(ERR, "EM pool stack failure %s\n",
110                             strerror(-rc));
111                 goto cleanup;
112         }
113
114         return 0;
115 cleanup:
116         tfp_free((void *)parms.mem_va);
117         return rc;
118 }
119
120 /**
121  * Create EM Tbl pool of memory indexes.
122  *
123  * [in] session
124  *   Pointer to session
125  * [in] dir
126  *   direction
127  *
128  * Return:
129  */
130 static void
131 tf_free_em_pool(struct tf_session *session,
132                 enum tf_dir dir)
133 {
134         struct stack *pool = &session->em_pool[dir];
135         uint32_t *ptr;
136
137         ptr = stack_items(pool);
138
139         tfp_free(ptr);
140 }
141
142 int
143 tf_open_session(struct tf                    *tfp,
144                 struct tf_open_session_parms *parms)
145 {
146         int rc;
147         struct tf_session *session;
148         struct tfp_calloc_parms alloc_parms;
149         unsigned int domain, bus, slot, device;
150         uint8_t fw_session_id;
151         int dir;
152
153         if (tfp == NULL || parms == NULL)
154                 return -EINVAL;
155
156         /* Filter out any non-supported device types on the Core
157          * side. It is assumed that the Firmware will be supported if
158          * firmware open session succeeds.
159          */
160         if (parms->device_type != TF_DEVICE_TYPE_WH)
161                 return -ENOTSUP;
162
163         /* Build the beginning of session_id */
164         rc = sscanf(parms->ctrl_chan_name,
165                     "%x:%x:%x.%d",
166                     &domain,
167                     &bus,
168                     &slot,
169                     &device);
170         if (rc != 4) {
171                 PMD_DRV_LOG(ERR,
172                             "Failed to scan device ctrl_chan_name\n");
173                 return -EINVAL;
174         }
175
176         /* open FW session and get a new session_id */
177         rc = tf_msg_session_open(tfp,
178                                  parms->ctrl_chan_name,
179                                  &fw_session_id);
180         if (rc) {
181                 /* Log error */
182                 if (rc == -EEXIST)
183                         PMD_DRV_LOG(ERR,
184                                     "Session is already open, rc:%d\n",
185                                     rc);
186                 else
187                         PMD_DRV_LOG(ERR,
188                                     "Open message send failed, rc:%d\n",
189                                     rc);
190
191                 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
192                 return rc;
193         }
194
195         /* Allocate session */
196         alloc_parms.nitems = 1;
197         alloc_parms.size = sizeof(struct tf_session_info);
198         alloc_parms.alignment = 0;
199         rc = tfp_calloc(&alloc_parms);
200         if (rc) {
201                 /* Log error */
202                 PMD_DRV_LOG(ERR,
203                             "Failed to allocate session info, rc:%d\n",
204                             rc);
205                 goto cleanup;
206         }
207
208         tfp->session = alloc_parms.mem_va;
209
210         /* Allocate core data for the session */
211         alloc_parms.nitems = 1;
212         alloc_parms.size = sizeof(struct tf_session);
213         alloc_parms.alignment = 0;
214         rc = tfp_calloc(&alloc_parms);
215         if (rc) {
216                 /* Log error */
217                 PMD_DRV_LOG(ERR,
218                             "Failed to allocate session data, rc:%d\n",
219                             rc);
220                 goto cleanup;
221         }
222
223         tfp->session->core_data = alloc_parms.mem_va;
224
225         session = (struct tf_session *)tfp->session->core_data;
226         tfp_memcpy(session->ctrl_chan_name,
227                    parms->ctrl_chan_name,
228                    TF_SESSION_NAME_MAX);
229
230         /* Initialize Session */
231         session->device_type = parms->device_type;
232         tf_rm_init(tfp);
233
234         /* Construct the Session ID */
235         session->session_id.internal.domain = domain;
236         session->session_id.internal.bus = bus;
237         session->session_id.internal.device = device;
238         session->session_id.internal.fw_session_id = fw_session_id;
239
240         rc = tf_msg_session_qcfg(tfp);
241         if (rc) {
242                 /* Log error */
243                 PMD_DRV_LOG(ERR,
244                             "Query config message send failed, rc:%d\n",
245                             rc);
246                 goto cleanup_close;
247         }
248
249         /* Shadow DB configuration */
250         if (parms->shadow_copy) {
251                 /* Ignore shadow_copy setting */
252                 session->shadow_copy = 0;/* parms->shadow_copy; */
253 #if (TF_SHADOW == 1)
254                 rc = tf_rm_shadow_db_init(tfs);
255                 if (rc)
256                         PMD_DRV_LOG(ERR,
257                                     "Shadow DB Initialization failed\n, rc:%d",
258                                     rc);
259                 /* Add additional processing */
260 #endif /* TF_SHADOW */
261         }
262
263         /* Adjust the Session with what firmware allowed us to get */
264         rc = tf_rm_allocate_validate(tfp);
265         if (rc) {
266                 /* Log error */
267                 goto cleanup_close;
268         }
269
270         /* Setup hash seeds */
271         tf_seeds_init(session);
272
273         /* Initialize EM pool */
274         for (dir = 0; dir < TF_DIR_MAX; dir++) {
275                 rc = tf_create_em_pool(session, dir, TF_SESSION_EM_POOL_SIZE);
276                 if (rc) {
277                         TFP_DRV_LOG(ERR,
278                                     "EM Pool initialization failed\n");
279                         goto cleanup_close;
280                 }
281         }
282
283         session->ref_count++;
284
285         /* Return session ID */
286         parms->session_id = session->session_id;
287
288         PMD_DRV_LOG(INFO,
289                     "Session created, session_id:%d\n",
290                     parms->session_id.id);
291
292         PMD_DRV_LOG(INFO,
293                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
294                     parms->session_id.internal.domain,
295                     parms->session_id.internal.bus,
296                     parms->session_id.internal.device,
297                     parms->session_id.internal.fw_session_id);
298
299         return 0;
300
301  cleanup:
302         tfp_free(tfp->session->core_data);
303         tfp_free(tfp->session);
304         tfp->session = NULL;
305         return rc;
306
307  cleanup_close:
308         tf_close_session(tfp);
309         return -EINVAL;
310 }
311
312 int
313 tf_attach_session(struct tf *tfp __rte_unused,
314                   struct tf_attach_session_parms *parms __rte_unused)
315 {
316 #if (TF_SHARED == 1)
317         int rc;
318
319         if (tfp == NULL)
320                 return -EINVAL;
321
322         /* - Open the shared memory for the attach_chan_name
323          * - Point to the shared session for this Device instance
324          * - Check that session is valid
325          * - Attach to the firmware so it can record there is more
326          *   than one client of the session.
327          */
328
329         if (tfp->session) {
330                 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
331                         rc = tf_msg_session_attach(tfp,
332                                                    parms->ctrl_chan_name,
333                                                    parms->session_id);
334                 }
335         }
336 #endif /* TF_SHARED */
337         return -1;
338 }
339
340 int
341 tf_close_session(struct tf *tfp)
342 {
343         int rc;
344         int rc_close = 0;
345         struct tf_session *tfs;
346         union tf_session_id session_id;
347         int dir;
348
349         if (tfp == NULL || tfp->session == NULL)
350                 return -EINVAL;
351
352         tfs = (struct tf_session *)(tfp->session->core_data);
353
354         /* Cleanup if we're last user of the session */
355         if (tfs->ref_count == 1) {
356                 /* Cleanup any outstanding resources */
357                 rc_close = tf_rm_close(tfp);
358         }
359
360         if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
361                 rc = tf_msg_session_close(tfp);
362                 if (rc) {
363                         /* Log error */
364                         PMD_DRV_LOG(ERR,
365                                     "Message send failed, rc:%d\n",
366                                     rc);
367                 }
368
369                 /* Update the ref_count */
370                 tfs->ref_count--;
371         }
372
373         session_id = tfs->session_id;
374
375         /* Final cleanup as we're last user of the session */
376         if (tfs->ref_count == 0) {
377                 /* Free EM pool */
378                 for (dir = 0; dir < TF_DIR_MAX; dir++)
379                         tf_free_em_pool(tfs, dir);
380
381                 tfp_free(tfp->session->core_data);
382                 tfp_free(tfp->session);
383                 tfp->session = NULL;
384         }
385
386         PMD_DRV_LOG(INFO,
387                     "Session closed, session_id:%d\n",
388                     session_id.id);
389
390         PMD_DRV_LOG(INFO,
391                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
392                     session_id.internal.domain,
393                     session_id.internal.bus,
394                     session_id.internal.device,
395                     session_id.internal.fw_session_id);
396
397         return rc_close;
398 }
399
400 /** insert EM hash entry API
401  *
402  *    returns:
403  *    0       - Success
404  *    -EINVAL - Error
405  */
406 int tf_insert_em_entry(struct tf *tfp,
407                        struct tf_insert_em_entry_parms *parms)
408 {
409         struct tf_tbl_scope_cb     *tbl_scope_cb;
410
411         if (tfp == NULL || parms == NULL)
412                 return -EINVAL;
413
414         tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
415                                          (tfp->session->core_data),
416                                          parms->tbl_scope_id);
417         if (tbl_scope_cb == NULL)
418                 return -EINVAL;
419
420         /* Process the EM entry per Table Scope type */
421         if (parms->mem == TF_MEM_EXTERNAL) {
422                 /* External EEM */
423                 return tf_insert_eem_entry((struct tf_session *)
424                                            (tfp->session->core_data),
425                                            tbl_scope_cb,
426                                            parms);
427         } else if (parms->mem == TF_MEM_INTERNAL) {
428                 /* Internal EM */
429                 return tf_insert_em_internal_entry(tfp, parms);
430         }
431
432         return -EINVAL;
433 }
434
435 /** Delete EM hash entry API
436  *
437  *    returns:
438  *    0       - Success
439  *    -EINVAL - Error
440  */
441 int tf_delete_em_entry(struct tf *tfp,
442                        struct tf_delete_em_entry_parms *parms)
443 {
444         struct tf_tbl_scope_cb     *tbl_scope_cb;
445
446         if (tfp == NULL || parms == NULL)
447                 return -EINVAL;
448
449         tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
450                                          (tfp->session->core_data),
451                                          parms->tbl_scope_id);
452         if (tbl_scope_cb == NULL)
453                 return -EINVAL;
454
455         if (parms->mem == TF_MEM_EXTERNAL)
456                 return tf_delete_eem_entry(tfp, parms);
457         else
458                 return tf_delete_em_internal_entry(tfp, parms);
459 }
460
461 /** allocate identifier resource
462  *
463  * Returns success or failure code.
464  */
465 int tf_alloc_identifier(struct tf *tfp,
466                         struct tf_alloc_identifier_parms *parms)
467 {
468         struct bitalloc *session_pool;
469         struct tf_session *tfs;
470         int id;
471         int rc;
472
473         if (parms == NULL || tfp == NULL)
474                 return -EINVAL;
475
476         if (tfp->session == NULL || tfp->session->core_data == NULL) {
477                 PMD_DRV_LOG(ERR, "%s: session error\n",
478                             tf_dir_2_str(parms->dir));
479                 return -EINVAL;
480         }
481
482         tfs = (struct tf_session *)(tfp->session->core_data);
483
484         switch (parms->ident_type) {
485         case TF_IDENT_TYPE_L2_CTXT:
486                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
487                                 TF_L2_CTXT_REMAP_POOL_NAME,
488                                 rc);
489                 break;
490         case TF_IDENT_TYPE_PROF_FUNC:
491                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
492                                 TF_PROF_FUNC_POOL_NAME,
493                                 rc);
494                 break;
495         case TF_IDENT_TYPE_EM_PROF:
496                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
497                                 TF_EM_PROF_ID_POOL_NAME,
498                                 rc);
499                 break;
500         case TF_IDENT_TYPE_WC_PROF:
501                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
502                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
503                                 rc);
504                 break;
505         case TF_IDENT_TYPE_L2_FUNC:
506                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
507                             tf_dir_2_str(parms->dir),
508                             tf_ident_2_str(parms->ident_type));
509                 rc = -EOPNOTSUPP;
510                 break;
511         default:
512                 PMD_DRV_LOG(ERR, "%s: %s\n",
513                             tf_dir_2_str(parms->dir),
514                             tf_ident_2_str(parms->ident_type));
515                 rc = -EINVAL;
516                 break;
517         }
518
519         if (rc) {
520                 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
521                             tf_dir_2_str(parms->dir),
522                             tf_ident_2_str(parms->ident_type));
523                 return rc;
524         }
525
526         id = ba_alloc(session_pool);
527
528         if (id == BA_FAIL) {
529                 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
530                             tf_dir_2_str(parms->dir),
531                             tf_ident_2_str(parms->ident_type));
532                 return -ENOMEM;
533         }
534         parms->id = id;
535         return 0;
536 }
537
538 /** free identifier resource
539  *
540  * Returns success or failure code.
541  */
542 int tf_free_identifier(struct tf *tfp,
543                        struct tf_free_identifier_parms *parms)
544 {
545         struct bitalloc *session_pool;
546         int rc;
547         int ba_rc;
548         struct tf_session *tfs;
549
550         if (parms == NULL || tfp == NULL)
551                 return -EINVAL;
552
553         if (tfp->session == NULL || tfp->session->core_data == NULL) {
554                 PMD_DRV_LOG(ERR, "%s: Session error\n",
555                             tf_dir_2_str(parms->dir));
556                 return -EINVAL;
557         }
558
559         tfs = (struct tf_session *)(tfp->session->core_data);
560
561         switch (parms->ident_type) {
562         case TF_IDENT_TYPE_L2_CTXT:
563                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
564                                 TF_L2_CTXT_REMAP_POOL_NAME,
565                                 rc);
566                 break;
567         case TF_IDENT_TYPE_PROF_FUNC:
568                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
569                                 TF_PROF_FUNC_POOL_NAME,
570                                 rc);
571                 break;
572         case TF_IDENT_TYPE_EM_PROF:
573                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
574                                 TF_EM_PROF_ID_POOL_NAME,
575                                 rc);
576                 break;
577         case TF_IDENT_TYPE_WC_PROF:
578                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
579                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
580                                 rc);
581                 break;
582         case TF_IDENT_TYPE_L2_FUNC:
583                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
584                             tf_dir_2_str(parms->dir),
585                             tf_ident_2_str(parms->ident_type));
586                 rc = -EOPNOTSUPP;
587                 break;
588         default:
589                 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
590                             tf_dir_2_str(parms->dir),
591                             tf_ident_2_str(parms->ident_type));
592                 rc = -EINVAL;
593                 break;
594         }
595         if (rc) {
596                 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
597                             tf_dir_2_str(parms->dir),
598                             tf_ident_2_str(parms->ident_type));
599                 return rc;
600         }
601
602         ba_rc = ba_inuse(session_pool, (int)parms->id);
603
604         if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
605                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
606                             tf_dir_2_str(parms->dir),
607                             tf_ident_2_str(parms->ident_type),
608                             parms->id);
609                 return -EINVAL;
610         }
611
612         ba_free(session_pool, (int)parms->id);
613
614         return 0;
615 }
616
617 int
618 tf_alloc_tcam_entry(struct tf *tfp,
619                     struct tf_alloc_tcam_entry_parms *parms)
620 {
621         int rc;
622         int index;
623         struct tf_session *tfs;
624         struct bitalloc *session_pool;
625
626         if (parms == NULL || tfp == NULL)
627                 return -EINVAL;
628
629         if (tfp->session == NULL || tfp->session->core_data == NULL) {
630                 PMD_DRV_LOG(ERR, "%s: session error\n",
631                             tf_dir_2_str(parms->dir));
632                 return -EINVAL;
633         }
634
635         tfs = (struct tf_session *)(tfp->session->core_data);
636
637         rc = tf_rm_lookup_tcam_type_pool(tfs,
638                                          parms->dir,
639                                          parms->tcam_tbl_type,
640                                          &session_pool);
641         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
642         if (rc)
643                 return rc;
644
645         index = ba_alloc(session_pool);
646         if (index == BA_FAIL) {
647                 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
648                             tf_dir_2_str(parms->dir),
649                             tf_tcam_tbl_2_str(parms->tcam_tbl_type));
650                 return -ENOMEM;
651         }
652
653         parms->idx = index;
654         return 0;
655 }
656
657 int
658 tf_set_tcam_entry(struct tf *tfp,
659                   struct tf_set_tcam_entry_parms *parms)
660 {
661         int rc;
662         int id;
663         struct tf_session *tfs;
664         struct bitalloc *session_pool;
665
666         if (tfp == NULL || parms == NULL) {
667                 PMD_DRV_LOG(ERR, "Invalid parameters\n");
668                 return -EINVAL;
669         }
670
671         if (tfp->session == NULL || tfp->session->core_data == NULL) {
672                 PMD_DRV_LOG(ERR,
673                             "%s, Session info invalid\n",
674                             tf_dir_2_str(parms->dir));
675                 return -EINVAL;
676         }
677
678         tfs = (struct tf_session *)(tfp->session->core_data);
679
680         /*
681          * Each tcam send msg function should check for key sizes range
682          */
683
684         rc = tf_rm_lookup_tcam_type_pool(tfs,
685                                          parms->dir,
686                                          parms->tcam_tbl_type,
687                                          &session_pool);
688         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
689         if (rc)
690                 return rc;
691
692
693         /* Verify that the entry has been previously allocated */
694         id = ba_inuse(session_pool, parms->idx);
695         if (id != 1) {
696                 PMD_DRV_LOG(ERR,
697                    "%s: %s: Invalid or not allocated index, idx:%d\n",
698                    tf_dir_2_str(parms->dir),
699                    tf_tcam_tbl_2_str(parms->tcam_tbl_type),
700                    parms->idx);
701                 return -EINVAL;
702         }
703
704         rc = tf_msg_tcam_entry_set(tfp, parms);
705
706         return rc;
707 }
708
709 int
710 tf_get_tcam_entry(struct tf *tfp __rte_unused,
711                   struct tf_get_tcam_entry_parms *parms __rte_unused)
712 {
713         int rc = -EOPNOTSUPP;
714
715         if (tfp == NULL || parms == NULL) {
716                 PMD_DRV_LOG(ERR, "Invalid parameters\n");
717                 return -EINVAL;
718         }
719
720         if (tfp->session == NULL || tfp->session->core_data == NULL) {
721                 PMD_DRV_LOG(ERR,
722                             "%s, Session info invalid\n",
723                             tf_dir_2_str(parms->dir));
724                 return -EINVAL;
725         }
726
727         return rc;
728 }
729
730 int
731 tf_free_tcam_entry(struct tf *tfp,
732                    struct tf_free_tcam_entry_parms *parms)
733 {
734         int rc;
735         struct tf_session *tfs;
736         struct bitalloc *session_pool;
737
738         if (parms == NULL || tfp == NULL)
739                 return -EINVAL;
740
741         if (tfp->session == NULL || tfp->session->core_data == NULL) {
742                 PMD_DRV_LOG(ERR, "%s: Session error\n",
743                             tf_dir_2_str(parms->dir));
744                 return -EINVAL;
745         }
746
747         tfs = (struct tf_session *)(tfp->session->core_data);
748
749         rc = tf_rm_lookup_tcam_type_pool(tfs,
750                                          parms->dir,
751                                          parms->tcam_tbl_type,
752                                          &session_pool);
753         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
754         if (rc)
755                 return rc;
756
757         rc = ba_inuse(session_pool, (int)parms->idx);
758         if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
759                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
760                             tf_dir_2_str(parms->dir),
761                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
762                             parms->idx);
763                 return -EINVAL;
764         }
765
766         ba_free(session_pool, (int)parms->idx);
767
768         rc = tf_msg_tcam_entry_free(tfp, parms);
769         if (rc) {
770                 /* Log error */
771                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
772                             tf_dir_2_str(parms->dir),
773                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
774                             parms->idx);
775         }
776
777         return rc;
778 }