net/bnxt: update table get to use new design
[dpdk.git] / drivers / net / bnxt / tf_core / tf_rm.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <string.h>
7
8 #include <rte_common.h>
9
10 #include <cfa_resource_types.h>
11
12 #include "tf_rm.h"
13 #include "tf_common.h"
14 #include "tf_util.h"
15 #include "tf_session.h"
16 #include "tf_device.h"
17 #include "tfp.h"
18 #include "tf_msg.h"
19
20 /**
21  * Generic RM Element data type that an RM DB is build upon.
22  */
23 struct tf_rm_element {
24         /**
25          * RM Element configuration type. If Private then the
26          * hcapi_type can be ignored. If Null then the element is not
27          * valid for the device.
28          */
29         enum tf_rm_elem_cfg_type cfg_type;
30
31         /**
32          * HCAPI RM Type for the element.
33          */
34         uint16_t hcapi_type;
35
36         /**
37          * HCAPI RM allocated range information for the element.
38          */
39         struct tf_rm_alloc_info alloc;
40
41         /**
42          * Bit allocator pool for the element. Pool size is controlled
43          * by the struct tf_session_resources at time of session creation.
44          * Null indicates that the element is not used for the device.
45          */
46         struct bitalloc *pool;
47 };
48
49 /**
50  * TF RM DB definition
51  */
52 struct tf_rm_new_db {
53         /**
54          * Number of elements in the DB
55          */
56         uint16_t num_entries;
57
58         /**
59          * Direction this DB controls.
60          */
61         enum tf_dir dir;
62
63         /**
64          * Module type, used for logging purposes.
65          */
66         enum tf_device_module_type type;
67
68         /**
69          * The DB consists of an array of elements
70          */
71         struct tf_rm_element *db;
72 };
73
74 /**
75  * Adjust an index according to the allocation information.
76  *
77  * All resources are controlled in a 0 based pool. Some resources, by
78  * design, are not 0 based, i.e. Full Action Records (SRAM) thus they
79  * need to be adjusted before they are handed out.
80  *
81  * [in] cfg
82  *   Pointer to the DB configuration
83  *
84  * [in] reservations
85  *   Pointer to the allocation values associated with the module
86  *
87  * [in] count
88  *   Number of DB configuration elements
89  *
90  * [out] valid_count
91  *   Number of HCAPI entries with a reservation value greater than 0
92  *
93  * Returns:
94  *     0          - Success
95  *   - EOPNOTSUPP - Operation not supported
96  */
97 static void
98 tf_rm_count_hcapi_reservations(enum tf_dir dir,
99                                enum tf_device_module_type type,
100                                struct tf_rm_element_cfg *cfg,
101                                uint16_t *reservations,
102                                uint16_t count,
103                                uint16_t *valid_count)
104 {
105         int i;
106         uint16_t cnt = 0;
107
108         for (i = 0; i < count; i++) {
109                 if (cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI &&
110                     reservations[i] > 0)
111                         cnt++;
112
113                 /* Only log msg if a type is attempted reserved and
114                  * not supported. We ignore EM module as its using a
115                  * split configuration array thus it would fail for
116                  * this type of check.
117                  */
118                 if (type != TF_DEVICE_MODULE_TYPE_EM &&
119                     cfg[i].cfg_type == TF_RM_ELEM_CFG_NULL &&
120                     reservations[i] > 0) {
121                         TFP_DRV_LOG(ERR,
122                                 "%s, %s, %s allocation not supported\n",
123                                 tf_device_module_type_2_str(type),
124                                 tf_dir_2_str(dir),
125                                 tf_device_module_type_subtype_2_str(type, i));
126                         printf("%s, %s, %s allocation of %d not supported\n",
127                                 tf_device_module_type_2_str(type),
128                                 tf_dir_2_str(dir),
129                                tf_device_module_type_subtype_2_str(type, i),
130                                reservations[i]);
131
132                 }
133         }
134
135         *valid_count = cnt;
136 }
137
138 /**
139  * Resource Manager Adjust of base index definitions.
140  */
141 enum tf_rm_adjust_type {
142         TF_RM_ADJUST_ADD_BASE, /**< Adds base to the index */
143         TF_RM_ADJUST_RM_BASE   /**< Removes base from the index */
144 };
145
146 /**
147  * Adjust an index according to the allocation information.
148  *
149  * All resources are controlled in a 0 based pool. Some resources, by
150  * design, are not 0 based, i.e. Full Action Records (SRAM) thus they
151  * need to be adjusted before they are handed out.
152  *
153  * [in] db
154  *   Pointer to the db, used for the lookup
155  *
156  * [in] action
157  *   Adjust action
158  *
159  * [in] db_index
160  *   DB index for the element type
161  *
162  * [in] index
163  *   Index to convert
164  *
165  * [out] adj_index
166  *   Adjusted index
167  *
168  * Returns:
169  *     0          - Success
170  *   - EOPNOTSUPP - Operation not supported
171  */
172 static int
173 tf_rm_adjust_index(struct tf_rm_element *db,
174                    enum tf_rm_adjust_type action,
175                    uint32_t db_index,
176                    uint32_t index,
177                    uint32_t *adj_index)
178 {
179         int rc = 0;
180         uint32_t base_index;
181
182         base_index = db[db_index].alloc.entry.start;
183
184         switch (action) {
185         case TF_RM_ADJUST_RM_BASE:
186                 *adj_index = index - base_index;
187                 break;
188         case TF_RM_ADJUST_ADD_BASE:
189                 *adj_index = index + base_index;
190                 break;
191         default:
192                 return -EOPNOTSUPP;
193         }
194
195         return rc;
196 }
197
198 /**
199  * Logs an array of found residual entries to the console.
200  *
201  * [in] dir
202  *   Receive or transmit direction
203  *
204  * [in] type
205  *   Type of Device Module
206  *
207  * [in] count
208  *   Number of entries in the residual array
209  *
210  * [in] residuals
211  *   Pointer to an array of residual entries. Array is index same as
212  *   the DB in which this function is used. Each entry holds residual
213  *   value for that entry.
214  */
215 static void
216 tf_rm_log_residuals(enum tf_dir dir,
217                     enum tf_device_module_type type,
218                     uint16_t count,
219                     uint16_t *residuals)
220 {
221         int i;
222
223         /* Walk the residual array and log the types that wasn't
224          * cleaned up to the console.
225          */
226         for (i = 0; i < count; i++) {
227                 if (residuals[i] != 0)
228                         TFP_DRV_LOG(ERR,
229                                 "%s, %s was not cleaned up, %d outstanding\n",
230                                 tf_dir_2_str(dir),
231                                 tf_device_module_type_subtype_2_str(type, i),
232                                 residuals[i]);
233         }
234 }
235
236 /**
237  * Performs a check of the passed in DB for any lingering elements. If
238  * a resource type was found to not have been cleaned up by the caller
239  * then its residual values are recorded, logged and passed back in an
240  * allocate reservation array that the caller can pass to the FW for
241  * cleanup.
242  *
243  * [in] db
244  *   Pointer to the db, used for the lookup
245  *
246  * [out] resv_size
247  *   Pointer to the reservation size of the generated reservation
248  *   array.
249  *
250  * [in/out] resv
251  *   Pointer Pointer to a reservation array. The reservation array is
252  *   allocated after the residual scan and holds any found residual
253  *   entries. Thus it can be smaller than the DB that the check was
254  *   performed on. Array must be freed by the caller.
255  *
256  * [out] residuals_present
257  *   Pointer to a bool flag indicating if residual was present in the
258  *   DB
259  *
260  * Returns:
261  *     0          - Success
262  *   - EOPNOTSUPP - Operation not supported
263  */
264 static int
265 tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
266                       uint16_t *resv_size,
267                       struct tf_rm_resc_entry **resv,
268                       bool *residuals_present)
269 {
270         int rc;
271         int i;
272         int f;
273         uint16_t count;
274         uint16_t found;
275         uint16_t *residuals = NULL;
276         uint16_t hcapi_type;
277         struct tf_rm_get_inuse_count_parms iparms;
278         struct tf_rm_get_alloc_info_parms aparms;
279         struct tf_rm_get_hcapi_parms hparms;
280         struct tf_rm_alloc_info info;
281         struct tfp_calloc_parms cparms;
282         struct tf_rm_resc_entry *local_resv = NULL;
283
284         /* Create array to hold the entries that have residuals */
285         cparms.nitems = rm_db->num_entries;
286         cparms.size = sizeof(uint16_t);
287         cparms.alignment = 0;
288         rc = tfp_calloc(&cparms);
289         if (rc)
290                 return rc;
291
292         residuals = (uint16_t *)cparms.mem_va;
293
294         /* Traverse the DB and collect any residual elements */
295         iparms.rm_db = rm_db;
296         iparms.count = &count;
297         for (i = 0, found = 0; i < rm_db->num_entries; i++) {
298                 iparms.db_index = i;
299                 rc = tf_rm_get_inuse_count(&iparms);
300                 /* Not a device supported entry, just skip */
301                 if (rc == -ENOTSUP)
302                         continue;
303                 if (rc)
304                         goto cleanup_residuals;
305
306                 if (count) {
307                         found++;
308                         residuals[i] = count;
309                         *residuals_present = true;
310                 }
311         }
312
313         if (*residuals_present) {
314                 /* Populate a reduced resv array with only the entries
315                  * that have residuals.
316                  */
317                 cparms.nitems = found;
318                 cparms.size = sizeof(struct tf_rm_resc_entry);
319                 cparms.alignment = 0;
320                 rc = tfp_calloc(&cparms);
321                 if (rc)
322                         return rc;
323
324                 local_resv = (struct tf_rm_resc_entry *)cparms.mem_va;
325
326                 aparms.rm_db = rm_db;
327                 hparms.rm_db = rm_db;
328                 hparms.hcapi_type = &hcapi_type;
329                 for (i = 0, f = 0; i < rm_db->num_entries; i++) {
330                         if (residuals[i] == 0)
331                                 continue;
332                         aparms.db_index = i;
333                         aparms.info = &info;
334                         rc = tf_rm_get_info(&aparms);
335                         if (rc)
336                                 goto cleanup_all;
337
338                         hparms.db_index = i;
339                         rc = tf_rm_get_hcapi_type(&hparms);
340                         if (rc)
341                                 goto cleanup_all;
342
343                         local_resv[f].type = hcapi_type;
344                         local_resv[f].start = info.entry.start;
345                         local_resv[f].stride = info.entry.stride;
346                         f++;
347                 }
348                 *resv_size = found;
349         }
350
351         tf_rm_log_residuals(rm_db->dir,
352                             rm_db->type,
353                             rm_db->num_entries,
354                             residuals);
355
356         tfp_free((void *)residuals);
357         *resv = local_resv;
358
359         return 0;
360
361  cleanup_all:
362         tfp_free((void *)local_resv);
363         *resv = NULL;
364  cleanup_residuals:
365         tfp_free((void *)residuals);
366
367         return rc;
368 }
369
370 int
371 tf_rm_create_db(struct tf *tfp,
372                 struct tf_rm_create_db_parms *parms)
373 {
374         int rc;
375         int i;
376         int j;
377         struct tf_session *tfs;
378         struct tf_dev_info *dev;
379         uint16_t max_types;
380         struct tfp_calloc_parms cparms;
381         struct tf_rm_resc_req_entry *query;
382         enum tf_rm_resc_resv_strategy resv_strategy;
383         struct tf_rm_resc_req_entry *req;
384         struct tf_rm_resc_entry *resv;
385         struct tf_rm_new_db *rm_db;
386         struct tf_rm_element *db;
387         uint32_t pool_size;
388         uint16_t hcapi_items;
389
390         TF_CHECK_PARMS2(tfp, parms);
391
392         /* Retrieve the session information */
393         rc = tf_session_get_session(tfp, &tfs);
394         if (rc)
395                 return rc;
396
397         /* Retrieve device information */
398         rc = tf_session_get_device(tfs, &dev);
399         if (rc)
400                 return rc;
401
402         /* Need device max number of elements for the RM QCAPS */
403         rc = dev->ops->tf_dev_get_max_types(tfp, &max_types);
404         if (rc)
405                 return rc;
406
407         cparms.nitems = max_types;
408         cparms.size = sizeof(struct tf_rm_resc_req_entry);
409         cparms.alignment = 0;
410         rc = tfp_calloc(&cparms);
411         if (rc)
412                 return rc;
413
414         query = (struct tf_rm_resc_req_entry *)cparms.mem_va;
415
416         /* Get Firmware Capabilities */
417         rc = tf_msg_session_resc_qcaps(tfp,
418                                        parms->dir,
419                                        max_types,
420                                        query,
421                                        &resv_strategy);
422         if (rc)
423                 return rc;
424
425         /* Process capabilities against DB requirements. However, as a
426          * DB can hold elements that are not HCAPI we can reduce the
427          * req msg content by removing those out of the request yet
428          * the DB holds them all as to give a fast lookup. We can also
429          * remove entries where there are no request for elements.
430          */
431         tf_rm_count_hcapi_reservations(parms->dir,
432                                        parms->type,
433                                        parms->cfg,
434                                        parms->alloc_cnt,
435                                        parms->num_elements,
436                                        &hcapi_items);
437
438         /* Handle the case where a DB create request really ends up
439          * being empty. Unsupported (if not rare) case but possible
440          * that no resources are necessary for a 'direction'.
441          */
442         if (hcapi_items == 0) {
443                 TFP_DRV_LOG(ERR,
444                         "%s: DB create request for Zero elements, DB Type:%s\n",
445                         tf_dir_2_str(parms->dir),
446                         tf_device_module_type_2_str(parms->type));
447
448                 parms->rm_db = NULL;
449                 return -ENOMEM;
450         }
451
452         /* Alloc request, alignment already set */
453         cparms.nitems = (size_t)hcapi_items;
454         cparms.size = sizeof(struct tf_rm_resc_req_entry);
455         rc = tfp_calloc(&cparms);
456         if (rc)
457                 return rc;
458         req = (struct tf_rm_resc_req_entry *)cparms.mem_va;
459
460         /* Alloc reservation, alignment and nitems already set */
461         cparms.size = sizeof(struct tf_rm_resc_entry);
462         rc = tfp_calloc(&cparms);
463         if (rc)
464                 return rc;
465         resv = (struct tf_rm_resc_entry *)cparms.mem_va;
466
467         /* Build the request */
468         for (i = 0, j = 0; i < parms->num_elements; i++) {
469                 /* Skip any non HCAPI cfg elements */
470                 if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI) {
471                         /* Only perform reservation for entries that
472                          * has been requested
473                          */
474                         if (parms->alloc_cnt[i] == 0)
475                                 continue;
476
477                         /* Verify that we can get the full amount
478                          * allocated per the qcaps availability.
479                          */
480                         if (parms->alloc_cnt[i] <=
481                             query[parms->cfg[i].hcapi_type].max) {
482                                 req[j].type = parms->cfg[i].hcapi_type;
483                                 req[j].min = parms->alloc_cnt[i];
484                                 req[j].max = parms->alloc_cnt[i];
485                                 j++;
486                         } else {
487                                 TFP_DRV_LOG(ERR,
488                                             "%s: Resource failure, type:%d\n",
489                                             tf_dir_2_str(parms->dir),
490                                             parms->cfg[i].hcapi_type);
491                                 TFP_DRV_LOG(ERR,
492                                         "req:%d, avail:%d\n",
493                                         parms->alloc_cnt[i],
494                                         query[parms->cfg[i].hcapi_type].max);
495                                 return -EINVAL;
496                         }
497                 }
498         }
499
500         rc = tf_msg_session_resc_alloc(tfp,
501                                        parms->dir,
502                                        hcapi_items,
503                                        req,
504                                        resv);
505         if (rc)
506                 return rc;
507
508         /* Build the RM DB per the request */
509         cparms.nitems = 1;
510         cparms.size = sizeof(struct tf_rm_new_db);
511         rc = tfp_calloc(&cparms);
512         if (rc)
513                 return rc;
514         rm_db = (void *)cparms.mem_va;
515
516         /* Build the DB within RM DB */
517         cparms.nitems = parms->num_elements;
518         cparms.size = sizeof(struct tf_rm_element);
519         rc = tfp_calloc(&cparms);
520         if (rc)
521                 return rc;
522         rm_db->db = (struct tf_rm_element *)cparms.mem_va;
523
524         db = rm_db->db;
525         for (i = 0, j = 0; i < parms->num_elements; i++) {
526                 db[i].cfg_type = parms->cfg[i].cfg_type;
527                 db[i].hcapi_type = parms->cfg[i].hcapi_type;
528
529                 /* Skip any non HCAPI types as we didn't include them
530                  * in the reservation request.
531                  */
532                 if (parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI)
533                         continue;
534
535                 /* If the element didn't request an allocation no need
536                  * to create a pool nor verify if we got a reservation.
537                  */
538                 if (parms->alloc_cnt[i] == 0)
539                         continue;
540
541                 /* If the element had requested an allocation and that
542                  * allocation was a success (full amount) then
543                  * allocate the pool.
544                  */
545                 if (parms->alloc_cnt[i] == resv[j].stride) {
546                         db[i].alloc.entry.start = resv[j].start;
547                         db[i].alloc.entry.stride = resv[j].stride;
548
549                         printf("Entry:%d Start:%d Stride:%d\n",
550                                i,
551                                resv[j].start,
552                                resv[j].stride);
553
554                         /* Create pool */
555                         pool_size = (BITALLOC_SIZEOF(resv[j].stride) /
556                                      sizeof(struct bitalloc));
557                         /* Alloc request, alignment already set */
558                         cparms.nitems = pool_size;
559                         cparms.size = sizeof(struct bitalloc);
560                         rc = tfp_calloc(&cparms);
561                         if (rc) {
562                                 TFP_DRV_LOG(ERR,
563                                             "%s: Pool alloc failed, type:%d\n",
564                                             tf_dir_2_str(parms->dir),
565                                             db[i].cfg_type);
566                                 goto fail;
567                         }
568                         db[i].pool = (struct bitalloc *)cparms.mem_va;
569
570                         rc = ba_init(db[i].pool, resv[j].stride);
571                         if (rc) {
572                                 TFP_DRV_LOG(ERR,
573                                             "%s: Pool init failed, type:%d\n",
574                                             tf_dir_2_str(parms->dir),
575                                             db[i].cfg_type);
576                                 goto fail;
577                         }
578                         j++;
579                 } else {
580                         /* Bail out as we want what we requested for
581                          * all elements, not any less.
582                          */
583                         TFP_DRV_LOG(ERR,
584                                     "%s: Alloc failed, type:%d\n",
585                                     tf_dir_2_str(parms->dir),
586                                     db[i].cfg_type);
587                         TFP_DRV_LOG(ERR,
588                                     "req:%d, alloc:%d\n",
589                                     parms->alloc_cnt[i],
590                                     resv[j].stride);
591                         goto fail;
592                 }
593         }
594
595         rm_db->num_entries = parms->num_elements;
596         rm_db->dir = parms->dir;
597         rm_db->type = parms->type;
598         *parms->rm_db = (void *)rm_db;
599
600         printf("%s: type:%d num_entries:%d\n",
601                tf_dir_2_str(parms->dir),
602                parms->type,
603                i);
604
605         tfp_free((void *)req);
606         tfp_free((void *)resv);
607
608         return 0;
609
610  fail:
611         tfp_free((void *)req);
612         tfp_free((void *)resv);
613         tfp_free((void *)db->pool);
614         tfp_free((void *)db);
615         tfp_free((void *)rm_db);
616         parms->rm_db = NULL;
617
618         return -EINVAL;
619 }
620
621 int
622 tf_rm_free_db(struct tf *tfp,
623               struct tf_rm_free_db_parms *parms)
624 {
625         int rc;
626         int i;
627         uint16_t resv_size = 0;
628         struct tf_rm_new_db *rm_db;
629         struct tf_rm_resc_entry *resv;
630         bool residuals_found = false;
631
632         TF_CHECK_PARMS2(parms, parms->rm_db);
633
634         /* Device unbind happens when the TF Session is closed and the
635          * session ref count is 0. Device unbind will cleanup each of
636          * its support modules, i.e. Identifier, thus we're ending up
637          * here to close the DB.
638          *
639          * On TF Session close it is assumed that the session has already
640          * cleaned up all its resources, individually, while
641          * destroying its flows.
642          *
643          * To assist in the 'cleanup checking' the DB is checked for any
644          * remaining elements and logged if found to be the case.
645          *
646          * Any such elements will need to be 'cleared' ahead of
647          * returning the resources to the HCAPI RM.
648          *
649          * RM will signal FW to flush the DB resources. FW will
650          * perform the invalidation. TF Session close will return the
651          * previous allocated elements to the RM and then close the
652          * HCAPI RM registration. That then saves several 'free' msgs
653          * from being required.
654          */
655
656         rm_db = (struct tf_rm_new_db *)parms->rm_db;
657
658         /* Check for residuals that the client didn't clean up */
659         rc = tf_rm_check_residuals(rm_db,
660                                    &resv_size,
661                                    &resv,
662                                    &residuals_found);
663         if (rc)
664                 return rc;
665
666         /* Invalidate any residuals followed by a DB traversal for
667          * pool cleanup.
668          */
669         if (residuals_found) {
670                 rc = tf_msg_session_resc_flush(tfp,
671                                                parms->dir,
672                                                resv_size,
673                                                resv);
674                 tfp_free((void *)resv);
675                 /* On failure we still have to cleanup so we can only
676                  * log that FW failed.
677                  */
678                 if (rc)
679                         TFP_DRV_LOG(ERR,
680                                     "%s: Internal Flush error, module:%s\n",
681                                     tf_dir_2_str(parms->dir),
682                                     tf_device_module_type_2_str(rm_db->type));
683         }
684
685         for (i = 0; i < rm_db->num_entries; i++)
686                 tfp_free((void *)rm_db->db[i].pool);
687
688         tfp_free((void *)parms->rm_db);
689
690         return rc;
691 }
692
693 int
694 tf_rm_allocate(struct tf_rm_allocate_parms *parms)
695 {
696         int rc;
697         int id;
698         uint32_t index;
699         struct tf_rm_new_db *rm_db;
700         enum tf_rm_elem_cfg_type cfg_type;
701
702         TF_CHECK_PARMS2(parms, parms->rm_db);
703
704         rm_db = (struct tf_rm_new_db *)parms->rm_db;
705         cfg_type = rm_db->db[parms->db_index].cfg_type;
706
707         /* Bail out if not controlled by RM */
708         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
709             cfg_type != TF_RM_ELEM_CFG_PRIVATE)
710                 return -ENOTSUP;
711
712         /* Bail out if the pool is not valid, should never happen */
713         if (rm_db->db[parms->db_index].pool == NULL) {
714                 rc = -ENOTSUP;
715                 TFP_DRV_LOG(ERR,
716                             "%s: Invalid pool for this type:%d, rc:%s\n",
717                             tf_dir_2_str(rm_db->dir),
718                             parms->db_index,
719                             strerror(-rc));
720                 return rc;
721         }
722
723         /*
724          * priority  0: allocate from top of the tcam i.e. high
725          * priority !0: allocate index from bottom i.e lowest
726          */
727         if (parms->priority)
728                 id = ba_alloc_reverse(rm_db->db[parms->db_index].pool);
729         else
730                 id = ba_alloc(rm_db->db[parms->db_index].pool);
731         if (id == BA_FAIL) {
732                 rc = -ENOMEM;
733                 TFP_DRV_LOG(ERR,
734                             "%s: Allocation failed, rc:%s\n",
735                             tf_dir_2_str(rm_db->dir),
736                             strerror(-rc));
737                 return rc;
738         }
739
740         /* Adjust for any non zero start value */
741         rc = tf_rm_adjust_index(rm_db->db,
742                                 TF_RM_ADJUST_ADD_BASE,
743                                 parms->db_index,
744                                 id,
745                                 &index);
746         if (rc) {
747                 TFP_DRV_LOG(ERR,
748                             "%s: Alloc adjust of base index failed, rc:%s\n",
749                             tf_dir_2_str(rm_db->dir),
750                             strerror(-rc));
751                 return -EINVAL;
752         }
753
754         *parms->index = index;
755
756         return rc;
757 }
758
759 int
760 tf_rm_free(struct tf_rm_free_parms *parms)
761 {
762         int rc;
763         uint32_t adj_index;
764         struct tf_rm_new_db *rm_db;
765         enum tf_rm_elem_cfg_type cfg_type;
766
767         TF_CHECK_PARMS2(parms, parms->rm_db);
768
769         rm_db = (struct tf_rm_new_db *)parms->rm_db;
770         cfg_type = rm_db->db[parms->db_index].cfg_type;
771
772         /* Bail out if not controlled by RM */
773         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
774             cfg_type != TF_RM_ELEM_CFG_PRIVATE)
775                 return -ENOTSUP;
776
777         /* Bail out if the pool is not valid, should never happen */
778         if (rm_db->db[parms->db_index].pool == NULL) {
779                 rc = -ENOTSUP;
780                 TFP_DRV_LOG(ERR,
781                             "%s: Invalid pool for this type:%d, rc:%s\n",
782                             tf_dir_2_str(rm_db->dir),
783                             parms->db_index,
784                             strerror(-rc));
785                 return rc;
786         }
787
788         /* Adjust for any non zero start value */
789         rc = tf_rm_adjust_index(rm_db->db,
790                                 TF_RM_ADJUST_RM_BASE,
791                                 parms->db_index,
792                                 parms->index,
793                                 &adj_index);
794         if (rc)
795                 return rc;
796
797         rc = ba_free(rm_db->db[parms->db_index].pool, adj_index);
798         /* No logging direction matters and that is not available here */
799         if (rc)
800                 return rc;
801
802         return rc;
803 }
804
805 int
806 tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)
807 {
808         int rc;
809         uint32_t adj_index;
810         struct tf_rm_new_db *rm_db;
811         enum tf_rm_elem_cfg_type cfg_type;
812
813         TF_CHECK_PARMS2(parms, parms->rm_db);
814
815         rm_db = (struct tf_rm_new_db *)parms->rm_db;
816         cfg_type = rm_db->db[parms->db_index].cfg_type;
817
818         /* Bail out if not controlled by RM */
819         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
820             cfg_type != TF_RM_ELEM_CFG_PRIVATE)
821                 return -ENOTSUP;
822
823         /* Bail out if the pool is not valid, should never happen */
824         if (rm_db->db[parms->db_index].pool == NULL) {
825                 rc = -ENOTSUP;
826                 TFP_DRV_LOG(ERR,
827                             "%s: Invalid pool for this type:%d, rc:%s\n",
828                             tf_dir_2_str(rm_db->dir),
829                             parms->db_index,
830                             strerror(-rc));
831                 return rc;
832         }
833
834         /* Adjust for any non zero start value */
835         rc = tf_rm_adjust_index(rm_db->db,
836                                 TF_RM_ADJUST_RM_BASE,
837                                 parms->db_index,
838                                 parms->index,
839                                 &adj_index);
840         if (rc)
841                 return rc;
842
843         *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool,
844                                      adj_index);
845
846         return rc;
847 }
848
849 int
850 tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
851 {
852         struct tf_rm_new_db *rm_db;
853         enum tf_rm_elem_cfg_type cfg_type;
854
855         TF_CHECK_PARMS2(parms, parms->rm_db);
856
857         rm_db = (struct tf_rm_new_db *)parms->rm_db;
858         cfg_type = rm_db->db[parms->db_index].cfg_type;
859
860         /* Bail out if not controlled by RM */
861         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
862             cfg_type != TF_RM_ELEM_CFG_PRIVATE)
863                 return -ENOTSUP;
864
865         memcpy(parms->info,
866                &rm_db->db[parms->db_index].alloc,
867                sizeof(struct tf_rm_alloc_info));
868
869         return 0;
870 }
871
872 int
873 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
874 {
875         struct tf_rm_new_db *rm_db;
876         enum tf_rm_elem_cfg_type cfg_type;
877
878         TF_CHECK_PARMS2(parms, parms->rm_db);
879
880         rm_db = (struct tf_rm_new_db *)parms->rm_db;
881         cfg_type = rm_db->db[parms->db_index].cfg_type;
882
883         /* Bail out if not controlled by RM */
884         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
885             cfg_type != TF_RM_ELEM_CFG_PRIVATE)
886                 return -ENOTSUP;
887
888         *parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type;
889
890         return 0;
891 }
892
893 int
894 tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
895 {
896         int rc = 0;
897         struct tf_rm_new_db *rm_db;
898         enum tf_rm_elem_cfg_type cfg_type;
899
900         TF_CHECK_PARMS2(parms, parms->rm_db);
901
902         rm_db = (struct tf_rm_new_db *)parms->rm_db;
903         cfg_type = rm_db->db[parms->db_index].cfg_type;
904
905         /* Bail out if not controlled by RM */
906         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
907             cfg_type != TF_RM_ELEM_CFG_PRIVATE)
908                 return -ENOTSUP;
909
910         /* Bail silently (no logging), if the pool is not valid there
911          * was no elements allocated for it.
912          */
913         if (rm_db->db[parms->db_index].pool == NULL) {
914                 *parms->count = 0;
915                 return 0;
916         }
917
918         *parms->count = ba_inuse_count(rm_db->db[parms->db_index].pool);
919
920         return rc;
921
922 }