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