net/bnxt: add core changes for EM and EEM lookups
[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 int tf_check_tcam_entry(enum tf_tcam_tbl_type tcam_tbl_type,
23                                enum tf_device_type device,
24                                uint16_t key_sz_in_bits,
25                                uint16_t *num_slice_per_row)
26 {
27         uint16_t key_bytes;
28         uint16_t slice_sz = 0;
29
30 #define CFA_P4_WC_TCAM_SLICES_PER_ROW 2
31 #define CFA_P4_WC_TCAM_SLICE_SIZE     12
32
33         if (tcam_tbl_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
34                 key_bytes = TF_BITS2BYTES_WORD_ALIGN(key_sz_in_bits);
35                 if (device == TF_DEVICE_TYPE_WH) {
36                         slice_sz = CFA_P4_WC_TCAM_SLICE_SIZE;
37                         *num_slice_per_row = CFA_P4_WC_TCAM_SLICES_PER_ROW;
38                 } else {
39                         TFP_DRV_LOG(ERR,
40                                     "Unsupported device type %d\n",
41                                     device);
42                         return -ENOTSUP;
43                 }
44
45                 if (key_bytes > *num_slice_per_row * slice_sz) {
46                         TFP_DRV_LOG(ERR,
47                                     "%s: Key size %d is not supported\n",
48                                     tf_tcam_tbl_2_str(tcam_tbl_type),
49                                     key_bytes);
50                         return -ENOTSUP;
51                 }
52         } else { /* for other type of tcam */
53                 *num_slice_per_row = 1;
54         }
55
56         return 0;
57 }
58
59 /**
60  * Create EM Tbl pool of memory indexes.
61  *
62  * [in] session
63  *   Pointer to session
64  * [in] dir
65  *   direction
66  * [in] num_entries
67  *   number of entries to write
68  *
69  * Return:
70  *  0       - Success, entry allocated - no search support
71  *  -ENOMEM -EINVAL -EOPNOTSUPP
72  *          - Failure, entry not allocated, out of resources
73  */
74 static int
75 tf_create_em_pool(struct tf_session *session,
76                   enum tf_dir dir,
77                   uint32_t num_entries)
78 {
79         struct tfp_calloc_parms parms;
80         uint32_t i, j;
81         int rc = 0;
82         struct stack *pool = &session->em_pool[dir];
83
84         parms.nitems = num_entries;
85         parms.size = sizeof(uint32_t);
86         parms.alignment = 0;
87
88         if (tfp_calloc(&parms) != 0) {
89                 TFP_DRV_LOG(ERR, "EM pool allocation failure %s\n",
90                             strerror(-ENOMEM));
91                 return -ENOMEM;
92         }
93
94         /* Create empty stack
95          */
96         rc = stack_init(num_entries, (uint32_t *)parms.mem_va, pool);
97
98         if (rc != 0) {
99                 TFP_DRV_LOG(ERR, "EM pool stack init failure %s\n",
100                             strerror(-rc));
101                 goto cleanup;
102         }
103
104         /* Fill pool with indexes
105          */
106         j = num_entries - 1;
107
108         for (i = 0; i < num_entries; i++) {
109                 rc = stack_push(pool, j);
110                 if (rc != 0) {
111                         TFP_DRV_LOG(ERR, "EM pool stack push failure %s\n",
112                                     strerror(-rc));
113                         goto cleanup;
114                 }
115                 j--;
116         }
117
118         if (!stack_is_full(pool)) {
119                 rc = -EINVAL;
120                 TFP_DRV_LOG(ERR, "EM pool stack failure %s\n",
121                             strerror(-rc));
122                 goto cleanup;
123         }
124
125         return 0;
126 cleanup:
127         tfp_free((void *)parms.mem_va);
128         return rc;
129 }
130
131 /**
132  * Create EM Tbl pool of memory indexes.
133  *
134  * [in] session
135  *   Pointer to session
136  * [in] dir
137  *   direction
138  *
139  * Return:
140  */
141 static void
142 tf_free_em_pool(struct tf_session *session,
143                 enum tf_dir dir)
144 {
145         struct stack *pool = &session->em_pool[dir];
146         uint32_t *ptr;
147
148         ptr = stack_items(pool);
149
150         tfp_free(ptr);
151 }
152
153 int
154 tf_open_session(struct tf                    *tfp,
155                 struct tf_open_session_parms *parms)
156 {
157         int rc;
158         struct tf_session *session;
159         struct tfp_calloc_parms alloc_parms;
160         unsigned int domain, bus, slot, device;
161         uint8_t fw_session_id;
162         int dir;
163
164         TF_CHECK_PARMS(tfp, parms);
165
166         /* Filter out any non-supported device types on the Core
167          * side. It is assumed that the Firmware will be supported if
168          * firmware open session succeeds.
169          */
170         if (parms->device_type != TF_DEVICE_TYPE_WH) {
171                 TFP_DRV_LOG(ERR,
172                             "Unsupported device type %d\n",
173                             parms->device_type);
174                 return -ENOTSUP;
175         }
176
177         /* Build the beginning of session_id */
178         rc = sscanf(parms->ctrl_chan_name,
179                     "%x:%x:%x.%d",
180                     &domain,
181                     &bus,
182                     &slot,
183                     &device);
184         if (rc != 4) {
185                 TFP_DRV_LOG(ERR,
186                             "Failed to scan device ctrl_chan_name\n");
187                 return -EINVAL;
188         }
189
190         /* open FW session and get a new session_id */
191         rc = tf_msg_session_open(tfp,
192                                  parms->ctrl_chan_name,
193                                  &fw_session_id);
194         if (rc) {
195                 /* Log error */
196                 if (rc == -EEXIST)
197                         TFP_DRV_LOG(ERR,
198                                     "Session is already open, rc:%s\n",
199                                     strerror(-rc));
200                 else
201                         TFP_DRV_LOG(ERR,
202                                     "Open message send failed, rc:%s\n",
203                                     strerror(-rc));
204
205                 parms->session_id.id = TF_FW_SESSION_ID_INVALID;
206                 return rc;
207         }
208
209         /* Allocate session */
210         alloc_parms.nitems = 1;
211         alloc_parms.size = sizeof(struct tf_session_info);
212         alloc_parms.alignment = 0;
213         rc = tfp_calloc(&alloc_parms);
214         if (rc) {
215                 /* Log error */
216                 TFP_DRV_LOG(ERR,
217                             "Failed to allocate session info, rc:%s\n",
218                             strerror(-rc));
219                 goto cleanup;
220         }
221
222         tfp->session = (struct tf_session_info *)alloc_parms.mem_va;
223
224         /* Allocate core data for the session */
225         alloc_parms.nitems = 1;
226         alloc_parms.size = sizeof(struct tf_session);
227         alloc_parms.alignment = 0;
228         rc = tfp_calloc(&alloc_parms);
229         if (rc) {
230                 /* Log error */
231                 TFP_DRV_LOG(ERR,
232                             "Failed to allocate session data, rc:%s\n",
233                             strerror(-rc));
234                 goto cleanup;
235         }
236
237         tfp->session->core_data = alloc_parms.mem_va;
238
239         session = (struct tf_session *)tfp->session->core_data;
240         tfp_memcpy(session->ctrl_chan_name,
241                    parms->ctrl_chan_name,
242                    TF_SESSION_NAME_MAX);
243
244         /* Initialize Session */
245         session->dev = NULL;
246         tf_rm_init(tfp);
247
248         /* Construct the Session ID */
249         session->session_id.internal.domain = domain;
250         session->session_id.internal.bus = bus;
251         session->session_id.internal.device = device;
252         session->session_id.internal.fw_session_id = fw_session_id;
253
254         /* Query for Session Config
255          */
256         rc = tf_msg_session_qcfg(tfp);
257         if (rc) {
258                 TFP_DRV_LOG(ERR,
259                             "Query config message send failed, rc:%s\n",
260                             strerror(-rc));
261                 goto cleanup_close;
262         }
263
264         /* Shadow DB configuration */
265         if (parms->shadow_copy) {
266                 /* Ignore shadow_copy setting */
267                 session->shadow_copy = 0;/* parms->shadow_copy; */
268 #if (TF_SHADOW == 1)
269                 rc = tf_rm_shadow_db_init(tfs);
270                 if (rc)
271                         TFP_DRV_LOG(ERR,
272                                     "Shadow DB Initialization failed\n, rc:%s",
273                                     strerror(-rc));
274                 /* Add additional processing */
275 #endif /* TF_SHADOW */
276         }
277
278         /* Adjust the Session with what firmware allowed us to get */
279         rc = tf_rm_allocate_validate(tfp);
280         if (rc) {
281                 TFP_DRV_LOG(ERR,
282                             "Rm allocate validate failed, rc:%s\n",
283                             strerror(-rc));
284                 goto cleanup_close;
285         }
286
287         /* Initialize EM pool */
288         for (dir = 0; dir < TF_DIR_MAX; dir++) {
289                 rc = tf_create_em_pool(session,
290                                        (enum tf_dir)dir,
291                                        TF_SESSION_EM_POOL_SIZE);
292                 if (rc) {
293                         TFP_DRV_LOG(ERR,
294                                     "EM Pool initialization failed\n");
295                         goto cleanup_close;
296                 }
297         }
298
299         session->ref_count++;
300
301         /* Return session ID */
302         parms->session_id = session->session_id;
303
304         TFP_DRV_LOG(INFO,
305                     "Session created, session_id:%d\n",
306                     parms->session_id.id);
307
308         TFP_DRV_LOG(INFO,
309                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
310                     parms->session_id.internal.domain,
311                     parms->session_id.internal.bus,
312                     parms->session_id.internal.device,
313                     parms->session_id.internal.fw_session_id);
314
315         return 0;
316
317  cleanup:
318         tfp_free(tfp->session->core_data);
319         tfp_free(tfp->session);
320         tfp->session = NULL;
321         return rc;
322
323  cleanup_close:
324         tf_close_session(tfp);
325         return -EINVAL;
326 }
327
328 int
329 tf_open_session_new(struct tf *tfp,
330                     struct tf_open_session_parms *parms)
331 {
332         int rc;
333         unsigned int domain, bus, slot, device;
334         struct tf_session_open_session_parms oparms;
335
336         TF_CHECK_PARMS(tfp, parms);
337
338         /* Filter out any non-supported device types on the Core
339          * side. It is assumed that the Firmware will be supported if
340          * firmware open session succeeds.
341          */
342         if (parms->device_type != TF_DEVICE_TYPE_WH) {
343                 TFP_DRV_LOG(ERR,
344                             "Unsupported device type %d\n",
345                             parms->device_type);
346                 return -ENOTSUP;
347         }
348
349         /* Verify control channel and build the beginning of session_id */
350         rc = sscanf(parms->ctrl_chan_name,
351                     "%x:%x:%x.%d",
352                     &domain,
353                     &bus,
354                     &slot,
355                     &device);
356         if (rc != 4) {
357                 TFP_DRV_LOG(ERR,
358                             "Failed to scan device ctrl_chan_name\n");
359                 return -EINVAL;
360         }
361
362         parms->session_id.internal.domain = domain;
363         parms->session_id.internal.bus = bus;
364         parms->session_id.internal.device = device;
365         oparms.open_cfg = parms;
366
367         rc = tf_session_open_session(tfp, &oparms);
368         /* Logging handled by tf_session_open_session */
369         if (rc)
370                 return rc;
371
372         TFP_DRV_LOG(INFO,
373                     "Session created, session_id:%d\n",
374                     parms->session_id.id);
375
376         TFP_DRV_LOG(INFO,
377                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
378                     parms->session_id.internal.domain,
379                     parms->session_id.internal.bus,
380                     parms->session_id.internal.device,
381                     parms->session_id.internal.fw_session_id);
382
383         return 0;
384 }
385
386 int
387 tf_attach_session(struct tf *tfp __rte_unused,
388                   struct tf_attach_session_parms *parms __rte_unused)
389 {
390 #if (TF_SHARED == 1)
391         int rc;
392
393         TF_CHECK_PARMS_SESSION(tfp, parms);
394
395         /* - Open the shared memory for the attach_chan_name
396          * - Point to the shared session for this Device instance
397          * - Check that session is valid
398          * - Attach to the firmware so it can record there is more
399          *   than one client of the session.
400          */
401
402         if (tfp->session->session_id.id != TF_SESSION_ID_INVALID) {
403                 rc = tf_msg_session_attach(tfp,
404                                            parms->ctrl_chan_name,
405                                            parms->session_id);
406         }
407 #endif /* TF_SHARED */
408         return -1;
409 }
410
411 int
412 tf_attach_session_new(struct tf *tfp,
413                       struct tf_attach_session_parms *parms)
414 {
415         int rc;
416         unsigned int domain, bus, slot, device;
417         struct tf_session_attach_session_parms aparms;
418
419         TF_CHECK_PARMS2(tfp, parms);
420
421         /* Verify control channel */
422         rc = sscanf(parms->ctrl_chan_name,
423                     "%x:%x:%x.%d",
424                     &domain,
425                     &bus,
426                     &slot,
427                     &device);
428         if (rc != 4) {
429                 TFP_DRV_LOG(ERR,
430                             "Failed to scan device ctrl_chan_name\n");
431                 return -EINVAL;
432         }
433
434         /* Verify 'attach' channel */
435         rc = sscanf(parms->attach_chan_name,
436                     "%x:%x:%x.%d",
437                     &domain,
438                     &bus,
439                     &slot,
440                     &device);
441         if (rc != 4) {
442                 TFP_DRV_LOG(ERR,
443                             "Failed to scan device attach_chan_name\n");
444                 return -EINVAL;
445         }
446
447         /* Prepare return value of session_id, using ctrl_chan_name
448          * device values as it becomes the session id.
449          */
450         parms->session_id.internal.domain = domain;
451         parms->session_id.internal.bus = bus;
452         parms->session_id.internal.device = device;
453         aparms.attach_cfg = parms;
454         rc = tf_session_attach_session(tfp,
455                                        &aparms);
456         /* Logging handled by dev_bind */
457         if (rc)
458                 return rc;
459
460         TFP_DRV_LOG(INFO,
461                     "Attached to session, session_id:%d\n",
462                     parms->session_id.id);
463
464         TFP_DRV_LOG(INFO,
465                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
466                     parms->session_id.internal.domain,
467                     parms->session_id.internal.bus,
468                     parms->session_id.internal.device,
469                     parms->session_id.internal.fw_session_id);
470
471         return rc;
472 }
473
474 int
475 tf_close_session(struct tf *tfp)
476 {
477         int rc;
478         int rc_close = 0;
479         struct tf_session *tfs;
480         union tf_session_id session_id;
481         int dir;
482
483         TF_CHECK_TFP_SESSION(tfp);
484
485         tfs = (struct tf_session *)(tfp->session->core_data);
486
487         /* Cleanup if we're last user of the session */
488         if (tfs->ref_count == 1) {
489                 /* Cleanup any outstanding resources */
490                 rc_close = tf_rm_close(tfp);
491         }
492
493         if (tfs->session_id.id != TF_SESSION_ID_INVALID) {
494                 rc = tf_msg_session_close(tfp);
495                 if (rc) {
496                         /* Log error */
497                         TFP_DRV_LOG(ERR,
498                                     "Message send failed, rc:%s\n",
499                                     strerror(-rc));
500                 }
501
502                 /* Update the ref_count */
503                 tfs->ref_count--;
504         }
505
506         session_id = tfs->session_id;
507
508         /* Final cleanup as we're last user of the session */
509         if (tfs->ref_count == 0) {
510                 /* Free EM pool */
511                 for (dir = 0; dir < TF_DIR_MAX; dir++)
512                         tf_free_em_pool(tfs, (enum tf_dir)dir);
513
514                 tfp_free(tfp->session->core_data);
515                 tfp_free(tfp->session);
516                 tfp->session = NULL;
517         }
518
519         TFP_DRV_LOG(INFO,
520                     "Session closed, session_id:%d\n",
521                     session_id.id);
522
523         TFP_DRV_LOG(INFO,
524                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
525                     session_id.internal.domain,
526                     session_id.internal.bus,
527                     session_id.internal.device,
528                     session_id.internal.fw_session_id);
529
530         return rc_close;
531 }
532
533 int
534 tf_close_session_new(struct tf *tfp)
535 {
536         int rc;
537         struct tf_session_close_session_parms cparms = { 0 };
538         union tf_session_id session_id = { 0 };
539         uint8_t ref_count;
540
541         TF_CHECK_PARMS1(tfp);
542
543         cparms.ref_count = &ref_count;
544         cparms.session_id = &session_id;
545         rc = tf_session_close_session(tfp,
546                                       &cparms);
547         /* Logging handled by tf_session_close_session */
548         if (rc)
549                 return rc;
550
551         TFP_DRV_LOG(INFO,
552                     "Closed session, session_id:%d, ref_count:%d\n",
553                     cparms.session_id->id,
554                     *cparms.ref_count);
555
556         TFP_DRV_LOG(INFO,
557                     "domain:%d, bus:%d, device:%d, fw_session_id:%d\n",
558                     cparms.session_id->internal.domain,
559                     cparms.session_id->internal.bus,
560                     cparms.session_id->internal.device,
561                     cparms.session_id->internal.fw_session_id);
562
563         return rc;
564 }
565
566 /** insert EM hash entry API
567  *
568  *    returns:
569  *    0       - Success
570  *    -EINVAL - Error
571  */
572 int tf_insert_em_entry(struct tf *tfp,
573                        struct tf_insert_em_entry_parms *parms)
574 {
575         struct tf_session      *tfs;
576         struct tf_dev_info     *dev;
577         int rc;
578
579         TF_CHECK_PARMS_SESSION(tfp, parms);
580
581         /* Retrieve the session information */
582         rc = tf_session_get_session(tfp, &tfs);
583         if (rc) {
584                 TFP_DRV_LOG(ERR,
585                             "%s: Failed to lookup session, rc:%s\n",
586                             tf_dir_2_str(parms->dir),
587                             strerror(-rc));
588                 return rc;
589         }
590
591         /* Retrieve the device information */
592         rc = tf_session_get_device(tfs, &dev);
593         if (rc) {
594                 TFP_DRV_LOG(ERR,
595                             "%s: Failed to lookup device, rc:%s\n",
596                             tf_dir_2_str(parms->dir),
597                             strerror(-rc));
598                 return rc;
599         }
600
601         rc = dev->ops->tf_dev_insert_em_entry(tfp, parms);
602         if (rc) {
603                 TFP_DRV_LOG(ERR,
604                             "%s: EM insert failed, rc:%s\n",
605                             tf_dir_2_str(parms->dir),
606                             strerror(-rc));
607                 return rc;
608         }
609
610         return -EINVAL;
611 }
612
613 /** Delete EM hash entry API
614  *
615  *    returns:
616  *    0       - Success
617  *    -EINVAL - Error
618  */
619 int tf_delete_em_entry(struct tf *tfp,
620                        struct tf_delete_em_entry_parms *parms)
621 {
622         struct tf_session      *tfs;
623         struct tf_dev_info     *dev;
624         int rc;
625
626         TF_CHECK_PARMS_SESSION(tfp, parms);
627
628         /* Retrieve the session information */
629         rc = tf_session_get_session(tfp, &tfs);
630         if (rc) {
631                 TFP_DRV_LOG(ERR,
632                             "%s: Failed to lookup session, rc:%s\n",
633                             tf_dir_2_str(parms->dir),
634                             strerror(-rc));
635                 return rc;
636         }
637
638         /* Retrieve the device information */
639         rc = tf_session_get_device(tfs, &dev);
640         if (rc) {
641                 TFP_DRV_LOG(ERR,
642                             "%s: Failed to lookup device, rc:%s\n",
643                             tf_dir_2_str(parms->dir),
644                             strerror(-rc));
645                 return rc;
646         }
647
648         rc = dev->ops->tf_dev_delete_em_entry(tfp, parms);
649         if (rc) {
650                 TFP_DRV_LOG(ERR,
651                             "%s: EM delete failed, rc:%s\n",
652                             tf_dir_2_str(parms->dir),
653                             strerror(-rc));
654                 return rc;
655         }
656
657         return rc;
658 }
659
660 int tf_alloc_identifier(struct tf *tfp,
661                         struct tf_alloc_identifier_parms *parms)
662 {
663         struct bitalloc *session_pool;
664         struct tf_session *tfs;
665         int id;
666         int rc;
667
668         TF_CHECK_PARMS_SESSION(tfp, parms);
669
670         tfs = (struct tf_session *)(tfp->session->core_data);
671
672         switch (parms->ident_type) {
673         case TF_IDENT_TYPE_L2_CTXT:
674                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
675                                 TF_L2_CTXT_REMAP_POOL_NAME,
676                                 rc);
677                 break;
678         case TF_IDENT_TYPE_PROF_FUNC:
679                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
680                                 TF_PROF_FUNC_POOL_NAME,
681                                 rc);
682                 break;
683         case TF_IDENT_TYPE_EM_PROF:
684                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
685                                 TF_EM_PROF_ID_POOL_NAME,
686                                 rc);
687                 break;
688         case TF_IDENT_TYPE_WC_PROF:
689                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
690                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
691                                 rc);
692                 break;
693         case TF_IDENT_TYPE_L2_FUNC:
694                 TFP_DRV_LOG(ERR, "%s: unsupported %s\n",
695                             tf_dir_2_str(parms->dir),
696                             tf_ident_2_str(parms->ident_type));
697                 rc = -EOPNOTSUPP;
698                 break;
699         default:
700                 TFP_DRV_LOG(ERR, "%s: %s\n",
701                             tf_dir_2_str(parms->dir),
702                             tf_ident_2_str(parms->ident_type));
703                 rc = -EOPNOTSUPP;
704                 break;
705         }
706
707         if (rc) {
708                 TFP_DRV_LOG(ERR, "%s: identifier pool %s failure, rc:%s\n",
709                             tf_dir_2_str(parms->dir),
710                             tf_ident_2_str(parms->ident_type),
711                             strerror(-rc));
712                 return rc;
713         }
714
715         id = ba_alloc(session_pool);
716
717         if (id == BA_FAIL) {
718                 TFP_DRV_LOG(ERR, "%s: %s: No resource available\n",
719                             tf_dir_2_str(parms->dir),
720                             tf_ident_2_str(parms->ident_type));
721                 return -ENOMEM;
722         }
723         parms->id = id;
724         return 0;
725 }
726
727 int
728 tf_alloc_identifier_new(struct tf *tfp,
729                         struct tf_alloc_identifier_parms *parms)
730 {
731         int rc;
732         struct tf_session *tfs;
733         struct tf_dev_info *dev;
734         struct tf_ident_alloc_parms aparms;
735         uint16_t id;
736
737         TF_CHECK_PARMS2(tfp, parms);
738
739         /* Can't do static initialization due to UT enum check */
740         memset(&aparms, 0, sizeof(struct tf_ident_alloc_parms));
741
742         /* Retrieve the session information */
743         rc = tf_session_get_session(tfp, &tfs);
744         if (rc) {
745                 TFP_DRV_LOG(ERR,
746                             "%s: Failed to lookup session, rc:%s\n",
747                             tf_dir_2_str(parms->dir),
748                             strerror(-rc));
749                 return rc;
750         }
751
752         /* Retrieve the device information */
753         rc = tf_session_get_device(tfs, &dev);
754         if (rc) {
755                 TFP_DRV_LOG(ERR,
756                             "%s: Failed to lookup device, rc:%s\n",
757                             tf_dir_2_str(parms->dir),
758                             strerror(-rc));
759                 return rc;
760         }
761
762         if (dev->ops->tf_dev_alloc_ident == NULL) {
763                 rc = -EOPNOTSUPP;
764                 TFP_DRV_LOG(ERR,
765                             "%s: Operation not supported, rc:%s\n",
766                             tf_dir_2_str(parms->dir),
767                             strerror(-rc));
768                 return -EOPNOTSUPP;
769         }
770
771         aparms.dir = parms->dir;
772         aparms.ident_type = parms->ident_type;
773         aparms.id = &id;
774         rc = dev->ops->tf_dev_alloc_ident(tfp, &aparms);
775         if (rc) {
776                 TFP_DRV_LOG(ERR,
777                             "%s: Identifier allocation failed, rc:%s\n",
778                             tf_dir_2_str(parms->dir),
779                             strerror(-rc));
780                 return rc;
781         }
782
783         parms->id = id;
784
785         return 0;
786 }
787
788 int tf_free_identifier(struct tf *tfp,
789                        struct tf_free_identifier_parms *parms)
790 {
791         struct bitalloc *session_pool;
792         int rc;
793         int ba_rc;
794         struct tf_session *tfs;
795
796         TF_CHECK_PARMS_SESSION(tfp, parms);
797
798         tfs = (struct tf_session *)(tfp->session->core_data);
799
800         switch (parms->ident_type) {
801         case TF_IDENT_TYPE_L2_CTXT:
802                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
803                                 TF_L2_CTXT_REMAP_POOL_NAME,
804                                 rc);
805                 break;
806         case TF_IDENT_TYPE_PROF_FUNC:
807                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
808                                 TF_PROF_FUNC_POOL_NAME,
809                                 rc);
810                 break;
811         case TF_IDENT_TYPE_EM_PROF:
812                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
813                                 TF_EM_PROF_ID_POOL_NAME,
814                                 rc);
815                 break;
816         case TF_IDENT_TYPE_WC_PROF:
817                 TF_RM_GET_POOLS(tfs, parms->dir, &session_pool,
818                                 TF_WC_TCAM_PROF_ID_POOL_NAME,
819                                 rc);
820                 break;
821         case TF_IDENT_TYPE_L2_FUNC:
822                 TFP_DRV_LOG(ERR, "%s: unsupported %s\n",
823                             tf_dir_2_str(parms->dir),
824                             tf_ident_2_str(parms->ident_type));
825                 rc = -EOPNOTSUPP;
826                 break;
827         default:
828                 TFP_DRV_LOG(ERR, "%s: invalid %s\n",
829                             tf_dir_2_str(parms->dir),
830                             tf_ident_2_str(parms->ident_type));
831                 rc = -EOPNOTSUPP;
832                 break;
833         }
834         if (rc) {
835                 TFP_DRV_LOG(ERR,
836                             "%s: %s Identifier pool access failed, rc:%s\n",
837                             tf_dir_2_str(parms->dir),
838                             tf_ident_2_str(parms->ident_type),
839                             strerror(-rc));
840                 return rc;
841         }
842
843         ba_rc = ba_inuse(session_pool, (int)parms->id);
844
845         if (ba_rc == BA_FAIL || ba_rc == BA_ENTRY_FREE) {
846                 TFP_DRV_LOG(ERR, "%s: %s: Entry %d already free",
847                             tf_dir_2_str(parms->dir),
848                             tf_ident_2_str(parms->ident_type),
849                             parms->id);
850                 return -EINVAL;
851         }
852
853         ba_free(session_pool, (int)parms->id);
854
855         return 0;
856 }
857
858 int
859 tf_free_identifier_new(struct tf *tfp,
860                        struct tf_free_identifier_parms *parms)
861 {
862         int rc;
863         struct tf_session *tfs;
864         struct tf_dev_info *dev;
865         struct tf_ident_free_parms fparms;
866
867         TF_CHECK_PARMS2(tfp, parms);
868
869         /* Can't do static initialization due to UT enum check */
870         memset(&fparms, 0, sizeof(struct tf_ident_free_parms));
871
872         /* Retrieve the session information */
873         rc = tf_session_get_session(tfp, &tfs);
874         if (rc) {
875                 TFP_DRV_LOG(ERR,
876                             "%s: Failed to lookup session, rc:%s\n",
877                             tf_dir_2_str(parms->dir),
878                             strerror(-rc));
879                 return rc;
880         }
881
882         /* Retrieve the device information */
883         rc = tf_session_get_device(tfs, &dev);
884         if (rc) {
885                 TFP_DRV_LOG(ERR,
886                             "%s: Failed to lookup device, rc:%s\n",
887                             tf_dir_2_str(parms->dir),
888                             strerror(-rc));
889                 return rc;
890         }
891
892         if (dev->ops->tf_dev_free_ident == NULL) {
893                 rc = -EOPNOTSUPP;
894                 TFP_DRV_LOG(ERR,
895                             "%s: Operation not supported, rc:%s\n",
896                             tf_dir_2_str(parms->dir),
897                             strerror(-rc));
898                 return -EOPNOTSUPP;
899         }
900
901         fparms.dir = parms->dir;
902         fparms.ident_type = parms->ident_type;
903         fparms.id = parms->id;
904         rc = dev->ops->tf_dev_free_ident(tfp, &fparms);
905         if (rc) {
906                 TFP_DRV_LOG(ERR,
907                             "%s: Identifier allocation failed, rc:%s\n",
908                             tf_dir_2_str(parms->dir),
909                             strerror(-rc));
910                 return rc;
911         }
912
913         return 0;
914 }
915
916 int
917 tf_alloc_tcam_entry(struct tf *tfp,
918                     struct tf_alloc_tcam_entry_parms *parms)
919 {
920         int rc;
921         int index;
922         struct tf_session *tfs;
923         struct bitalloc *session_pool;
924         uint16_t num_slice_per_row;
925
926         /* TEMP, due to device design. When tcam is modularized device
927          * should be retrieved from the session
928          */
929         enum tf_device_type device_type;
930         /* TEMP */
931         device_type = TF_DEVICE_TYPE_WH;
932
933         TF_CHECK_PARMS_SESSION(tfp, parms);
934
935         tfs = (struct tf_session *)(tfp->session->core_data);
936
937         rc = tf_check_tcam_entry(parms->tcam_tbl_type,
938                                  device_type,
939                                  parms->key_sz_in_bits,
940                                  &num_slice_per_row);
941         /* Error logging handled by tf_check_tcam_entry */
942         if (rc)
943                 return rc;
944
945         rc = tf_rm_lookup_tcam_type_pool(tfs,
946                                          parms->dir,
947                                          parms->tcam_tbl_type,
948                                          &session_pool);
949         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
950         if (rc)
951                 return rc;
952
953         index = ba_alloc(session_pool);
954         if (index == BA_FAIL) {
955                 TFP_DRV_LOG(ERR, "%s: %s: No resource available\n",
956                             tf_dir_2_str(parms->dir),
957                             tf_tcam_tbl_2_str(parms->tcam_tbl_type));
958                 return -ENOMEM;
959         }
960
961         index *= num_slice_per_row;
962
963         parms->idx = index;
964         return 0;
965 }
966
967 int
968 tf_set_tcam_entry(struct tf *tfp,
969                   struct tf_set_tcam_entry_parms *parms)
970 {
971         int rc;
972         int id;
973         int index;
974         struct tf_session *tfs;
975         struct bitalloc *session_pool;
976         uint16_t num_slice_per_row;
977
978         /* TEMP, due to device design. When tcam is modularized device
979          * should be retrieved from the session
980          */
981         enum tf_device_type device_type;
982         /* TEMP */
983         device_type = TF_DEVICE_TYPE_WH;
984
985         TF_CHECK_PARMS_SESSION(tfp, parms);
986
987         tfs = (struct tf_session *)(tfp->session->core_data);
988
989         rc = tf_check_tcam_entry(parms->tcam_tbl_type,
990                                  device_type,
991                                  parms->key_sz_in_bits,
992                                  &num_slice_per_row);
993         /* Error logging handled by tf_check_tcam_entry */
994         if (rc)
995                 return rc;
996
997         rc = tf_rm_lookup_tcam_type_pool(tfs,
998                                          parms->dir,
999                                          parms->tcam_tbl_type,
1000                                          &session_pool);
1001         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
1002         if (rc)
1003                 return rc;
1004
1005         /* Verify that the entry has been previously allocated */
1006         index = parms->idx / num_slice_per_row;
1007
1008         id = ba_inuse(session_pool, index);
1009         if (id != 1) {
1010                 TFP_DRV_LOG(ERR,
1011                    "%s: %s: Invalid or not allocated index, idx:%d\n",
1012                    tf_dir_2_str(parms->dir),
1013                    tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1014                    parms->idx);
1015                 return -EINVAL;
1016         }
1017
1018         rc = tf_msg_tcam_entry_set(tfp, parms);
1019
1020         return rc;
1021 }
1022
1023 int
1024 tf_get_tcam_entry(struct tf *tfp __rte_unused,
1025                   struct tf_get_tcam_entry_parms *parms __rte_unused)
1026 {
1027         TF_CHECK_PARMS_SESSION(tfp, parms);
1028         return -EOPNOTSUPP;
1029 }
1030
1031 int
1032 tf_free_tcam_entry(struct tf *tfp,
1033                    struct tf_free_tcam_entry_parms *parms)
1034 {
1035         int rc;
1036         int index;
1037         struct tf_session *tfs;
1038         struct bitalloc *session_pool;
1039         uint16_t num_slice_per_row = 1;
1040
1041         /* TEMP, due to device design. When tcam is modularized device
1042          * should be retrieved from the session
1043          */
1044         enum tf_device_type device_type;
1045         /* TEMP */
1046         device_type = TF_DEVICE_TYPE_WH;
1047
1048         TF_CHECK_PARMS_SESSION(tfp, parms);
1049         tfs = (struct tf_session *)(tfp->session->core_data);
1050
1051         rc = tf_check_tcam_entry(parms->tcam_tbl_type,
1052                                  device_type,
1053                                  0,
1054                                  &num_slice_per_row);
1055         /* Error logging handled by tf_check_tcam_entry */
1056         if (rc)
1057                 return rc;
1058
1059         rc = tf_rm_lookup_tcam_type_pool(tfs,
1060                                          parms->dir,
1061                                          parms->tcam_tbl_type,
1062                                          &session_pool);
1063         /* Error logging handled by tf_rm_lookup_tcam_type_pool */
1064         if (rc)
1065                 return rc;
1066
1067         index = parms->idx / num_slice_per_row;
1068
1069         rc = ba_inuse(session_pool, index);
1070         if (rc == BA_FAIL || rc == BA_ENTRY_FREE) {
1071                 TFP_DRV_LOG(ERR, "%s: %s: Entry %d already free",
1072                             tf_dir_2_str(parms->dir),
1073                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1074                             index);
1075                 return -EINVAL;
1076         }
1077
1078         ba_free(session_pool, index);
1079
1080         rc = tf_msg_tcam_entry_free(tfp, parms);
1081         if (rc) {
1082                 /* Log error */
1083                 TFP_DRV_LOG(ERR, "%s: %s: Entry %d free failed with err %s",
1084                             tf_dir_2_str(parms->dir),
1085                             tf_tcam_tbl_2_str(parms->tcam_tbl_type),
1086                             parms->idx,
1087                             strerror(-rc));
1088         }
1089
1090         return rc;
1091 }