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