eac57e7bdaaf172b3d1cc5a77a834d55b6209917
[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, (uint32_t *)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->dev = NULL;
235         tf_rm_init(tfp);
236
237         /* Construct the Session ID */
238         session->session_id.internal.domain = domain;
239         session->session_id.internal.bus = bus;
240         session->session_id.internal.device = device;
241         session->session_id.internal.fw_session_id = fw_session_id;
242
243         rc = tf_msg_session_qcfg(tfp);
244         if (rc) {
245                 /* Log error */
246                 PMD_DRV_LOG(ERR,
247                             "Query config message send failed, rc:%d\n",
248                             rc);
249                 goto cleanup_close;
250         }
251
252         /* Shadow DB configuration */
253         if (parms->shadow_copy) {
254                 /* Ignore shadow_copy setting */
255                 session->shadow_copy = 0;/* parms->shadow_copy; */
256 #if (TF_SHADOW == 1)
257                 rc = tf_rm_shadow_db_init(tfs);
258                 if (rc)
259                         PMD_DRV_LOG(ERR,
260                                     "Shadow DB Initialization failed\n, rc:%d",
261                                     rc);
262                 /* Add additional processing */
263 #endif /* TF_SHADOW */
264         }
265
266         /* Adjust the Session with what firmware allowed us to get */
267         rc = tf_rm_allocate_validate(tfp);
268         if (rc) {
269                 /* Log error */
270                 goto cleanup_close;
271         }
272
273         /* Setup hash seeds */
274         tf_seeds_init(session);
275
276         /* Initialize EM pool */
277         for (dir = 0; dir < TF_DIR_MAX; dir++) {
278                 rc = tf_create_em_pool(session,
279                                        (enum tf_dir)dir,
280                                        TF_SESSION_EM_POOL_SIZE);
281                 if (rc) {
282                         TFP_DRV_LOG(ERR,
283                                     "EM Pool initialization failed\n");
284                         goto cleanup_close;
285                 }
286         }
287
288         session->ref_count++;
289
290         /* Return session ID */
291         parms->session_id = session->session_id;
292
293         PMD_DRV_LOG(INFO,
294                     "Session created, session_id:%d\n",
295                     parms->session_id.id);
296
297         PMD_DRV_LOG(INFO,
298                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
299                     parms->session_id.internal.domain,
300                     parms->session_id.internal.bus,
301                     parms->session_id.internal.device,
302                     parms->session_id.internal.fw_session_id);
303
304         return 0;
305
306  cleanup:
307         tfp_free(tfp->session->core_data);
308         tfp_free(tfp->session);
309         tfp->session = NULL;
310         return rc;
311
312  cleanup_close:
313         tf_close_session(tfp);
314         return -EINVAL;
315 }
316
317 int
318 tf_open_session_new(struct tf *tfp,
319                     struct tf_open_session_parms *parms)
320 {
321         int rc;
322         unsigned int domain, bus, slot, device;
323         struct tf_session_open_session_parms oparms;
324
325         TF_CHECK_PARMS(tfp, parms);
326
327         /* Filter out any non-supported device types on the Core
328          * side. It is assumed that the Firmware will be supported if
329          * firmware open session succeeds.
330          */
331         if (parms->device_type != TF_DEVICE_TYPE_WH) {
332                 TFP_DRV_LOG(ERR,
333                             "Unsupported device type %d\n",
334                             parms->device_type);
335                 return -ENOTSUP;
336         }
337
338         /* Verify control channel and build the beginning of session_id */
339         rc = sscanf(parms->ctrl_chan_name,
340                     "%x:%x:%x.%d",
341                     &domain,
342                     &bus,
343                     &slot,
344                     &device);
345         if (rc != 4) {
346                 TFP_DRV_LOG(ERR,
347                             "Failed to scan device ctrl_chan_name\n");
348                 return -EINVAL;
349         }
350
351         parms->session_id.internal.domain = domain;
352         parms->session_id.internal.bus = bus;
353         parms->session_id.internal.device = device;
354         oparms.open_cfg = parms;
355
356         rc = tf_session_open_session(tfp, &oparms);
357         /* Logging handled by tf_session_open_session */
358         if (rc)
359                 return rc;
360
361         TFP_DRV_LOG(INFO,
362                     "Session created, session_id:%d\n",
363                     parms->session_id.id);
364
365         TFP_DRV_LOG(INFO,
366                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
367                     parms->session_id.internal.domain,
368                     parms->session_id.internal.bus,
369                     parms->session_id.internal.device,
370                     parms->session_id.internal.fw_session_id);
371
372         return 0;
373 }
374
375 int
376 tf_attach_session(struct tf *tfp __rte_unused,
377                   struct tf_attach_session_parms *parms __rte_unused)
378 {
379 #if (TF_SHARED == 1)
380         int rc;
381
382         if (tfp == NULL)
383                 return -EINVAL;
384
385         /* - Open the shared memory for the attach_chan_name
386          * - Point to the shared session for this Device instance
387          * - Check that session is valid
388          * - Attach to the firmware so it can record there is more
389          *   than one client of the session.
390          */
391
392         if (tfp->session) {
393                 if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
394                         rc = tf_msg_session_attach(tfp,
395                                                    parms->ctrl_chan_name,
396                                                    parms->session_id);
397                 }
398         }
399 #endif /* TF_SHARED */
400         return -1;
401 }
402
403 int
404 tf_attach_session_new(struct tf *tfp,
405                       struct tf_attach_session_parms *parms)
406 {
407         int rc;
408         unsigned int domain, bus, slot, device;
409         struct tf_session_attach_session_parms aparms;
410
411         TF_CHECK_PARMS2(tfp, parms);
412
413         /* Verify control channel */
414         rc = sscanf(parms->ctrl_chan_name,
415                     "%x:%x:%x.%d",
416                     &domain,
417                     &bus,
418                     &slot,
419                     &device);
420         if (rc != 4) {
421                 TFP_DRV_LOG(ERR,
422                             "Failed to scan device ctrl_chan_name\n");
423                 return -EINVAL;
424         }
425
426         /* Verify 'attach' channel */
427         rc = sscanf(parms->attach_chan_name,
428                     "%x:%x:%x.%d",
429                     &domain,
430                     &bus,
431                     &slot,
432                     &device);
433         if (rc != 4) {
434                 TFP_DRV_LOG(ERR,
435                             "Failed to scan device attach_chan_name\n");
436                 return -EINVAL;
437         }
438
439         /* Prepare return value of session_id, using ctrl_chan_name
440          * device values as it becomes the session id.
441          */
442         parms->session_id.internal.domain = domain;
443         parms->session_id.internal.bus = bus;
444         parms->session_id.internal.device = device;
445         aparms.attach_cfg = parms;
446         rc = tf_session_attach_session(tfp,
447                                        &aparms);
448         /* Logging handled by dev_bind */
449         if (rc)
450                 return rc;
451
452         TFP_DRV_LOG(INFO,
453                     "Attached to session, session_id:%d\n",
454                     parms->session_id.id);
455
456         TFP_DRV_LOG(INFO,
457                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
458                     parms->session_id.internal.domain,
459                     parms->session_id.internal.bus,
460                     parms->session_id.internal.device,
461                     parms->session_id.internal.fw_session_id);
462
463         return rc;
464 }
465
466 int
467 tf_close_session(struct tf *tfp)
468 {
469         int rc;
470         int rc_close = 0;
471         struct tf_session *tfs;
472         union tf_session_id session_id;
473         int dir;
474
475         if (tfp == NULL || tfp->session == NULL)
476                 return -EINVAL;
477
478         tfs = (struct tf_session *)(tfp->session->core_data);
479
480         /* Cleanup if we're last user of the session */
481         if (tfs->ref_count == 1) {
482                 /* Cleanup any outstanding resources */
483                 rc_close = tf_rm_close(tfp);
484         }
485
486         if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
487                 rc = tf_msg_session_close(tfp);
488                 if (rc) {
489                         /* Log error */
490                         PMD_DRV_LOG(ERR,
491                                     "Message send failed, rc:%d\n",
492                                     rc);
493                 }
494
495                 /* Update the ref_count */
496                 tfs->ref_count--;
497         }
498
499         session_id = tfs->session_id;
500
501         /* Final cleanup as we're last user of the session */
502         if (tfs->ref_count == 0) {
503                 /* Free EM pool */
504                 for (dir = 0; dir < TF_DIR_MAX; dir++)
505                         tf_free_em_pool(tfs, (enum tf_dir)dir);
506
507                 tfp_free(tfp->session->core_data);
508                 tfp_free(tfp->session);
509                 tfp->session = NULL;
510         }
511
512         PMD_DRV_LOG(INFO,
513                     "Session closed, session_id:%d\n",
514                     session_id.id);
515
516         PMD_DRV_LOG(INFO,
517                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
518                     session_id.internal.domain,
519                     session_id.internal.bus,
520                     session_id.internal.device,
521                     session_id.internal.fw_session_id);
522
523         return rc_close;
524 }
525
526 int
527 tf_close_session_new(struct tf *tfp)
528 {
529         int rc;
530         struct tf_session_close_session_parms cparms = { 0 };
531         union tf_session_id session_id = { 0 };
532         uint8_t ref_count;
533
534         TF_CHECK_PARMS1(tfp);
535
536         cparms.ref_count = &ref_count;
537         cparms.session_id = &session_id;
538         rc = tf_session_close_session(tfp,
539                                       &cparms);
540         /* Logging handled by tf_session_close_session */
541         if (rc)
542                 return rc;
543
544         TFP_DRV_LOG(INFO,
545                     "Closed session, session_id:%d, ref_count:%d\n",
546                     cparms.session_id->id,
547                     *cparms.ref_count);
548
549         TFP_DRV_LOG(INFO,
550                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
551                     cparms.session_id->internal.domain,
552                     cparms.session_id->internal.bus,
553                     cparms.session_id->internal.device,
554                     cparms.session_id->internal.fw_session_id);
555
556         return rc;
557 }
558
559 /** insert EM hash entry API
560  *
561  *    returns:
562  *    0       - Success
563  *    -EINVAL - Error
564  */
565 int tf_insert_em_entry(struct tf *tfp,
566                        struct tf_insert_em_entry_parms *parms)
567 {
568         struct tf_tbl_scope_cb     *tbl_scope_cb;
569
570         if (tfp == NULL || parms == NULL)
571                 return -EINVAL;
572
573         tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
574                                          (tfp->session->core_data),
575                                          parms->tbl_scope_id);
576         if (tbl_scope_cb == NULL)
577                 return -EINVAL;
578
579         /* Process the EM entry per Table Scope type */
580         if (parms->mem == TF_MEM_EXTERNAL) {
581                 /* External EEM */
582                 return tf_insert_eem_entry((struct tf_session *)
583                                            (tfp->session->core_data),
584                                            tbl_scope_cb,
585                                            parms);
586         } else if (parms->mem == TF_MEM_INTERNAL) {
587                 /* Internal EM */
588                 return tf_insert_em_internal_entry(tfp, parms);
589         }
590
591         return -EINVAL;
592 }
593
594 /** Delete EM hash entry API
595  *
596  *    returns:
597  *    0       - Success
598  *    -EINVAL - Error
599  */
600 int tf_delete_em_entry(struct tf *tfp,
601                        struct tf_delete_em_entry_parms *parms)
602 {
603         struct tf_tbl_scope_cb     *tbl_scope_cb;
604
605         if (tfp == NULL || parms == NULL)
606                 return -EINVAL;
607
608         tbl_scope_cb = tbl_scope_cb_find((struct tf_session *)
609                                          (tfp->session->core_data),
610                                          parms->tbl_scope_id);
611         if (tbl_scope_cb == NULL)
612                 return -EINVAL;
613
614         if (parms->mem == TF_MEM_EXTERNAL)
615                 return tf_delete_eem_entry(tfp, parms);
616         else
617                 return tf_delete_em_internal_entry(tfp, parms);
618 }
619
620 /** allocate identifier resource
621  *
622  * Returns success or failure code.
623  */
624 int tf_alloc_identifier(struct tf *tfp,
625                         struct tf_alloc_identifier_parms *parms)
626 {
627         struct bitalloc *session_pool;
628         struct tf_session *tfs;
629         int id;
630         int rc;
631
632         if (parms == NULL || tfp == NULL)
633                 return -EINVAL;
634
635         if (tfp->session == NULL || tfp->session->core_data == NULL) {
636                 PMD_DRV_LOG(ERR, "%s: session error\n",
637                             tf_dir_2_str(parms->dir));
638                 return -EINVAL;
639         }
640
641         tfs = (struct tf_session *)(tfp->session->core_data);
642
643         switch (parms->ident_type) {
644         case TF_IDENT_TYPE_L2_CTXT:
645                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
646                                 TF_L2_CTXT_REMAP_POOL_NAME,
647                                 rc);
648                 break;
649         case TF_IDENT_TYPE_PROF_FUNC:
650                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
651                                 TF_PROF_FUNC_POOL_NAME,
652                                 rc);
653                 break;
654         case TF_IDENT_TYPE_EM_PROF:
655                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
656                                 TF_EM_PROF_ID_POOL_NAME,
657                                 rc);
658                 break;
659         case TF_IDENT_TYPE_WC_PROF:
660                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
661                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
662                                 rc);
663                 break;
664         case TF_IDENT_TYPE_L2_FUNC:
665                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
666                             tf_dir_2_str(parms->dir),
667                             tf_ident_2_str(parms->ident_type));
668                 rc = -EOPNOTSUPP;
669                 break;
670         default:
671                 PMD_DRV_LOG(ERR, "%s: %s\n",
672                             tf_dir_2_str(parms->dir),
673                             tf_ident_2_str(parms->ident_type));
674                 rc = -EINVAL;
675                 break;
676         }
677
678         if (rc) {
679                 PMD_DRV_LOG(ERR, "%s: identifier pool %s failure\n",
680                             tf_dir_2_str(parms->dir),
681                             tf_ident_2_str(parms->ident_type));
682                 return rc;
683         }
684
685         id = ba_alloc(session_pool);
686
687         if (id == BA_FAIL) {
688                 PMD_DRV_LOG(ERR, "%s: %s: No resource available\n",
689                             tf_dir_2_str(parms->dir),
690                             tf_ident_2_str(parms->ident_type));
691                 return -ENOMEM;
692         }
693         parms->id = id;
694         return 0;
695 }
696
697 int
698 tf_alloc_identifier_new(struct tf *tfp,
699                         struct tf_alloc_identifier_parms *parms)
700 {
701         int rc;
702         struct tf_session *tfs;
703         struct tf_dev_info *dev;
704         struct tf_ident_alloc_parms aparms;
705         uint16_t id;
706
707         TF_CHECK_PARMS2(tfp, parms);
708
709         /* Can't do static initialization due to UT enum check */
710         memset(&aparms, 0, sizeof(struct tf_ident_alloc_parms));
711
712         /* Retrieve the session information */
713         rc = tf_session_get_session(tfp, &tfs);
714         if (rc) {
715                 TFP_DRV_LOG(ERR,
716                             "%s: Failed to lookup session, rc:%s\n",
717                             tf_dir_2_str(parms->dir),
718                             strerror(-rc));
719                 return rc;
720         }
721
722         /* Retrieve the device information */
723         rc = tf_session_get_device(tfs, &dev);
724         if (rc) {
725                 TFP_DRV_LOG(ERR,
726                             "%s: Failed to lookup device, rc:%s\n",
727                             tf_dir_2_str(parms->dir),
728                             strerror(-rc));
729                 return rc;
730         }
731
732         if (dev->ops->tf_dev_alloc_ident == NULL) {
733                 rc = -EOPNOTSUPP;
734                 TFP_DRV_LOG(ERR,
735                             "%s: Operation not supported, rc:%s\n",
736                             tf_dir_2_str(parms->dir),
737                             strerror(-rc));
738                 return -EOPNOTSUPP;
739         }
740
741         aparms.dir = parms->dir;
742         aparms.ident_type = parms->ident_type;
743         aparms.id = &id;
744         rc = dev->ops->tf_dev_alloc_ident(tfp, &aparms);
745         if (rc) {
746                 TFP_DRV_LOG(ERR,
747                             "%s: Identifier allocation failed, rc:%s\n",
748                             tf_dir_2_str(parms->dir),
749                             strerror(-rc));
750                 return rc;
751         }
752
753         parms->id = id;
754
755         return 0;
756 }
757
758 int tf_free_identifier(struct tf *tfp,
759                        struct tf_free_identifier_parms *parms)
760 {
761         struct bitalloc *session_pool;
762         int rc;
763         int ba_rc;
764         struct tf_session *tfs;
765
766         if (parms == NULL || tfp == NULL)
767                 return -EINVAL;
768
769         if (tfp->session == NULL || tfp->session->core_data == NULL) {
770                 PMD_DRV_LOG(ERR, "%s: Session error\n",
771                             tf_dir_2_str(parms->dir));
772                 return -EINVAL;
773         }
774
775         tfs = (struct tf_session *)(tfp->session->core_data);
776
777         switch (parms->ident_type) {
778         case TF_IDENT_TYPE_L2_CTXT:
779                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
780                                 TF_L2_CTXT_REMAP_POOL_NAME,
781                                 rc);
782                 break;
783         case TF_IDENT_TYPE_PROF_FUNC:
784                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
785                                 TF_PROF_FUNC_POOL_NAME,
786                                 rc);
787                 break;
788         case TF_IDENT_TYPE_EM_PROF:
789                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
790                                 TF_EM_PROF_ID_POOL_NAME,
791                                 rc);
792                 break;
793         case TF_IDENT_TYPE_WC_PROF:
794                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
795                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
796                                 rc);
797                 break;
798         case TF_IDENT_TYPE_L2_FUNC:
799                 PMD_DRV_LOG(ERR, "%s: unsupported %s\n",
800                             tf_dir_2_str(parms->dir),
801                             tf_ident_2_str(parms->ident_type));
802                 rc = -EOPNOTSUPP;
803                 break;
804         default:
805                 PMD_DRV_LOG(ERR, "%s: invalid %s\n",
806                             tf_dir_2_str(parms->dir),
807                             tf_ident_2_str(parms->ident_type));
808                 rc = -EINVAL;
809                 break;
810         }
811         if (rc) {
812                 PMD_DRV_LOG(ERR, "%s: %s Identifier pool access failed\n",
813                             tf_dir_2_str(parms->dir),
814                             tf_ident_2_str(parms->ident_type));
815                 return rc;
816         }
817
818         ba_rc = ba_inuse(session_pool, (int)parms->id);
819
820         if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
821                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
822                             tf_dir_2_str(parms->dir),
823                             tf_ident_2_str(parms->ident_type),
824                             parms->id);
825                 return -EINVAL;
826         }
827
828         ba_free(session_pool, (int)parms->id);
829
830         return 0;
831 }
832
833 int
834 tf_free_identifier_new(struct tf *tfp,
835                        struct tf_free_identifier_parms *parms)
836 {
837         int rc;
838         struct tf_session *tfs;
839         struct tf_dev_info *dev;
840         struct tf_ident_free_parms fparms;
841
842         TF_CHECK_PARMS2(tfp, parms);
843
844         /* Can't do static initialization due to UT enum check */
845         memset(&fparms, 0, sizeof(struct tf_ident_free_parms));
846
847         /* Retrieve the session information */
848         rc = tf_session_get_session(tfp, &tfs);
849         if (rc) {
850                 TFP_DRV_LOG(ERR,
851                             "%s: Failed to lookup session, rc:%s\n",
852                             tf_dir_2_str(parms->dir),
853                             strerror(-rc));
854                 return rc;
855         }
856
857         /* Retrieve the device information */
858         rc = tf_session_get_device(tfs, &dev);
859         if (rc) {
860                 TFP_DRV_LOG(ERR,
861                             "%s: Failed to lookup device, rc:%s\n",
862                             tf_dir_2_str(parms->dir),
863                             strerror(-rc));
864                 return rc;
865         }
866
867         if (dev->ops->tf_dev_free_ident == NULL) {
868                 rc = -EOPNOTSUPP;
869                 TFP_DRV_LOG(ERR,
870                             "%s: Operation not supported, rc:%s\n",
871                             tf_dir_2_str(parms->dir),
872                             strerror(-rc));
873                 return -EOPNOTSUPP;
874         }
875
876         fparms.dir = parms->dir;
877         fparms.ident_type = parms->ident_type;
878         fparms.id = parms->id;
879         rc = dev->ops->tf_dev_free_ident(tfp, &fparms);
880         if (rc) {
881                 TFP_DRV_LOG(ERR,
882                             "%s: Identifier allocation failed, rc:%s\n",
883                             tf_dir_2_str(parms->dir),
884                             strerror(-rc));
885                 return rc;
886         }
887
888         return 0;
889 }
890
891 int
892 tf_alloc_tcam_entry(struct tf *tfp,
893                     struct tf_alloc_tcam_entry_parms *parms)
894 {
895         int rc;
896         int index = 0;
897         struct tf_session *tfs;
898         struct bitalloc *session_pool;
899
900         if (parms == NULL || tfp == NULL)
901                 return -EINVAL;
902
903         if (tfp->session == NULL || tfp->session->core_data == NULL) {
904                 PMD_DRV_LOG(ERR, "%s: session error\n",
905                             tf_dir_2_str(parms->dir));
906                 return -EINVAL;
907         }
908
909         tfs = (struct tf_session *)(tfp->session->core_data);
910
911         rc = tf_rm_lookup_tcam_type_pool(tfs,
912                                          parms->dir,
913                                          parms->tcam_tbl_type,
914                                          &session_pool);
915         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
916         if (rc)
917                 return rc;
918
919         /*
920          * priority  0: allocate from top of the tcam i.e. high
921          * priority !0: allocate index from bottom i.e lowest
922          */
923         if (parms->priority) {
924                 for (index = session_pool->size - 1; index >= 0; index--) {
925                         if (ba_inuse(session_pool,
926                                           index) == BA_ENTRY_FREE) {
927                                 break;
928                         }
929                 }
930                 if (ba_alloc_index(session_pool,
931                                    index) == BA_FAIL) {
932                         TFP_DRV_LOG(ERR,
933                                     "%s: %s: ba_alloc index %d failed\n",
934                                     tf_dir_2_str(parms->dir),
935                                     tf_tcam_tbl_2_str(parms->tcam_tbl_type),
936                                     index);
937                         return -ENOMEM;
938                 }
939         } else {
940                 index = ba_alloc(session_pool);
941                 if (index == BA_FAIL) {
942                         TFP_DRV_LOG(ERR, "%s: %s: Out of resource\n",
943                                     tf_dir_2_str(parms->dir),
944                                     tf_tcam_tbl_2_str(parms->tcam_tbl_type));
945                         return -ENOMEM;
946                 }
947         }
948
949         parms->idx = index;
950         return 0;
951 }
952
953 int
954 tf_set_tcam_entry(struct tf *tfp,
955                   struct tf_set_tcam_entry_parms *parms)
956 {
957         int rc;
958         int id;
959         struct tf_session *tfs;
960         struct bitalloc *session_pool;
961
962         if (tfp == NULL || parms == NULL) {
963                 PMD_DRV_LOG(ERR, "Invalid parameters\n");
964                 return -EINVAL;
965         }
966
967         if (tfp->session == NULL || tfp->session->core_data == NULL) {
968                 PMD_DRV_LOG(ERR,
969                             "%s, Session info invalid\n",
970                             tf_dir_2_str(parms->dir));
971                 return -EINVAL;
972         }
973
974         tfs = (struct tf_session *)(tfp->session->core_data);
975
976         /*
977          * Each tcam send msg function should check for key sizes range
978          */
979
980         rc = tf_rm_lookup_tcam_type_pool(tfs,
981                                          parms->dir,
982                                          parms->tcam_tbl_type,
983                                          &session_pool);
984         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
985         if (rc)
986                 return rc;
987
988
989         /* Verify that the entry has been previously allocated */
990         id = ba_inuse(session_pool, parms->idx);
991         if (id != 1) {
992                 PMD_DRV_LOG(ERR,
993                    "%s: %s: Invalid or not allocated index, idx:%d\n",
994                    tf_dir_2_str(parms->dir),
995                    tf_tcam_tbl_2_str(parms->tcam_tbl_type),
996                    parms->idx);
997                 return -EINVAL;
998         }
999
1000         rc = tf_msg_tcam_entry_set(tfp, parms);
1001
1002         return rc;
1003 }
1004
1005 int
1006 tf_get_tcam_entry(struct tf *tfp __rte_unused,
1007                   struct tf_get_tcam_entry_parms *parms __rte_unused)
1008 {
1009         int rc = -EOPNOTSUPP;
1010
1011         if (tfp == NULL || parms == NULL) {
1012                 PMD_DRV_LOG(ERR, "Invalid parameters\n");
1013                 return -EINVAL;
1014         }
1015
1016         if (tfp->session == NULL || tfp->session->core_data == NULL) {
1017                 PMD_DRV_LOG(ERR,
1018                             "%s, Session info invalid\n",
1019                             tf_dir_2_str(parms->dir));
1020                 return -EINVAL;
1021         }
1022
1023         return rc;
1024 }
1025
1026 int
1027 tf_free_tcam_entry(struct tf *tfp,
1028                    struct tf_free_tcam_entry_parms *parms)
1029 {
1030         int rc;
1031         struct tf_session *tfs;
1032         struct bitalloc *session_pool;
1033
1034         if (parms == NULL || tfp == NULL)
1035                 return -EINVAL;
1036
1037         if (tfp->session == NULL || tfp->session->core_data == NULL) {
1038                 PMD_DRV_LOG(ERR, "%s: Session error\n",
1039                             tf_dir_2_str(parms->dir));
1040                 return -EINVAL;
1041         }
1042
1043         tfs = (struct tf_session *)(tfp->session->core_data);
1044
1045         rc = tf_rm_lookup_tcam_type_pool(tfs,
1046                                          parms->dir,
1047                                          parms->tcam_tbl_type,
1048                                          &session_pool);
1049         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
1050         if (rc)
1051                 return rc;
1052
1053         rc = ba_inuse(session_pool, (int)parms->idx);
1054         if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
1055                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d already free",
1056                             tf_dir_2_str(parms->dir),
1057                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1058                             parms->idx);
1059                 return -EINVAL;
1060         }
1061
1062         ba_free(session_pool, (int)parms->idx);
1063
1064         rc = tf_msg_tcam_entry_free(tfp, parms);
1065         if (rc) {
1066                 /* Log error */
1067                 PMD_DRV_LOG(ERR, "%s: %s: Entry %d free failed",
1068                             tf_dir_2_str(parms->dir),
1069                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1070                             parms->idx);
1071         }
1072
1073         return rc;
1074 }