net/bnxt: check index range in bulk get
[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_internal(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         if (parms->base_index)
759                 *parms->base_index = id;
760
761         return rc;
762 }
763
764 int
765 tf_rm_free(struct tf_rm_free_parms *parms)
766 {
767         int rc;
768         uint32_t adj_index;
769         struct tf_rm_new_db *rm_db;
770         enum tf_rm_elem_cfg_type cfg_type;
771
772         TF_CHECK_PARMS2(parms, parms->rm_db);
773
774         rm_db = (struct tf_rm_new_db *)parms->rm_db;
775         cfg_type = rm_db->db[parms->db_index].cfg_type;
776
777         /* Bail out if not controlled by RM */
778         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
779                 return -ENOTSUP;
780
781         /* Bail out if the pool is not valid, should never happen */
782         if (rm_db->db[parms->db_index].pool == NULL) {
783                 rc = -ENOTSUP;
784                 TFP_DRV_LOG(ERR,
785                             "%s: Invalid pool for this type:%d, rc:%s\n",
786                             tf_dir_2_str(rm_db->dir),
787                             parms->db_index,
788                             strerror(-rc));
789                 return rc;
790         }
791
792         /* Adjust for any non zero start value */
793         rc = tf_rm_adjust_index(rm_db->db,
794                                 TF_RM_ADJUST_RM_BASE,
795                                 parms->db_index,
796                                 parms->index,
797                                 &adj_index);
798         if (rc)
799                 return rc;
800
801         rc = ba_free(rm_db->db[parms->db_index].pool, adj_index);
802         /* No logging direction matters and that is not available here */
803         if (rc)
804                 return rc;
805
806         return rc;
807 }
808
809 int
810 tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)
811 {
812         int rc;
813         uint32_t adj_index;
814         struct tf_rm_new_db *rm_db;
815         enum tf_rm_elem_cfg_type cfg_type;
816
817         TF_CHECK_PARMS2(parms, parms->rm_db);
818
819         rm_db = (struct tf_rm_new_db *)parms->rm_db;
820         cfg_type = rm_db->db[parms->db_index].cfg_type;
821
822         /* Bail out if not controlled by RM */
823         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
824                 return -ENOTSUP;
825
826         /* Bail out if the pool is not valid, should never happen */
827         if (rm_db->db[parms->db_index].pool == NULL) {
828                 rc = -ENOTSUP;
829                 TFP_DRV_LOG(ERR,
830                             "%s: Invalid pool for this type:%d, rc:%s\n",
831                             tf_dir_2_str(rm_db->dir),
832                             parms->db_index,
833                             strerror(-rc));
834                 return rc;
835         }
836
837         /* Adjust for any non zero start value */
838         rc = tf_rm_adjust_index(rm_db->db,
839                                 TF_RM_ADJUST_RM_BASE,
840                                 parms->db_index,
841                                 parms->index,
842                                 &adj_index);
843         if (rc)
844                 return rc;
845
846         if (parms->base_index)
847                 *parms->base_index = adj_index;
848         *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool,
849                                      adj_index);
850
851         return rc;
852 }
853
854 int
855 tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
856 {
857         struct tf_rm_new_db *rm_db;
858         enum tf_rm_elem_cfg_type cfg_type;
859
860         TF_CHECK_PARMS2(parms, parms->rm_db);
861
862         rm_db = (struct tf_rm_new_db *)parms->rm_db;
863         cfg_type = rm_db->db[parms->db_index].cfg_type;
864
865         /* Bail out if not controlled by HCAPI */
866         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
867             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
868                 return -ENOTSUP;
869
870         memcpy(parms->info,
871                &rm_db->db[parms->db_index].alloc,
872                sizeof(struct tf_rm_alloc_info));
873
874         return 0;
875 }
876
877 int
878 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
879 {
880         struct tf_rm_new_db *rm_db;
881         enum tf_rm_elem_cfg_type cfg_type;
882
883         TF_CHECK_PARMS2(parms, parms->rm_db);
884
885         rm_db = (struct tf_rm_new_db *)parms->rm_db;
886         cfg_type = rm_db->db[parms->db_index].cfg_type;
887
888         /* Bail out if not controlled by HCAPI */
889         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
890             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
891                 return -ENOTSUP;
892
893         *parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type;
894
895         return 0;
896 }
897
898 int
899 tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
900 {
901         int rc = 0;
902         struct tf_rm_new_db *rm_db;
903         enum tf_rm_elem_cfg_type cfg_type;
904
905         TF_CHECK_PARMS2(parms, parms->rm_db);
906
907         rm_db = (struct tf_rm_new_db *)parms->rm_db;
908         cfg_type = rm_db->db[parms->db_index].cfg_type;
909
910         /* Bail out if not controlled by RM */
911         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
912                 return -ENOTSUP;
913
914         /* Bail silently (no logging), if the pool is not valid there
915          * was no elements allocated for it.
916          */
917         if (rm_db->db[parms->db_index].pool == NULL) {
918                 *parms->count = 0;
919                 return 0;
920         }
921
922         *parms->count = ba_inuse_count(rm_db->db[parms->db_index].pool);
923
924         return rc;
925
926 }
927
928 int
929 tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms)
930 {
931         struct tf_rm_new_db *rm_db;
932         enum tf_rm_elem_cfg_type cfg_type;
933         uint32_t base_index;
934         uint32_t stride;
935         int rc = 0;
936
937         TF_CHECK_PARMS2(parms, parms->rm_db);
938
939         rm_db = (struct tf_rm_new_db *)parms->rm_db;
940         cfg_type = rm_db->db[parms->db_index].cfg_type;
941
942         /* Bail out if not controlled by RM */
943         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
944                 return -ENOTSUP;
945
946         /* Bail out if the pool is not valid, should never happen */
947         if (rm_db->db[parms->db_index].pool == NULL) {
948                 rc = -ENOTSUP;
949                 TFP_DRV_LOG(ERR,
950                             "%s: Invalid pool for this type:%d, rc:%s\n",
951                             tf_dir_2_str(rm_db->dir),
952                             parms->db_index,
953                             strerror(-rc));
954                 return rc;
955         }
956
957         base_index = rm_db->db[parms->db_index].alloc.entry.start;
958         stride = rm_db->db[parms->db_index].alloc.entry.stride;
959
960         if (parms->starting_index < base_index ||
961             parms->starting_index + parms->num_entries > base_index + stride)
962                 return -EINVAL;
963
964         return rc;
965 }