2c08fb80fe6eb498ab99d6a9eefd3529fd517b05
[dpdk.git] / drivers / net / bnxt / tf_core / tf_rm.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <string.h>
7
8 #include <rte_common.h>
9 #include <rte_debug.h>
10
11 #include <cfa_resource_types.h>
12
13 #include "tf_rm.h"
14 #include "tf_common.h"
15 #include "tf_util.h"
16 #include "tf_session.h"
17 #include "tf_device.h"
18 #include "tfp.h"
19 #include "tf_msg.h"
20
21 /* Logging defines */
22 #define TF_RM_DEBUG  0
23
24 /**
25  * Generic RM Element data type that an RM DB is build upon.
26  */
27 struct tf_rm_element {
28         /**
29          * RM Element configuration type. If Private then the
30          * hcapi_type can be ignored. If Null then the element is not
31          * valid for the device.
32          */
33         enum tf_rm_elem_cfg_type cfg_type;
34
35         /**
36          * HCAPI RM Type for the element.
37          */
38         uint16_t hcapi_type;
39
40         /**
41          * HCAPI RM allocated range information for the element.
42          */
43         struct tf_rm_alloc_info alloc;
44
45         /**
46          * Bit allocator pool for the element. Pool size is controlled
47          * by the struct tf_session_resources at time of session creation.
48          * Null indicates that the element is not used for the device.
49          */
50         struct bitalloc *pool;
51 };
52
53 /**
54  * TF RM DB definition
55  */
56 struct tf_rm_new_db {
57         /**
58          * Number of elements in the DB
59          */
60         uint16_t num_entries;
61
62         /**
63          * Direction this DB controls.
64          */
65         enum tf_dir dir;
66
67         /**
68          * Module type, used for logging purposes.
69          */
70         enum tf_device_module_type type;
71
72         /**
73          * The DB consists of an array of elements
74          */
75         struct tf_rm_element *db;
76 };
77
78 /**
79  * Adjust an index according to the allocation information.
80  *
81  * All resources are controlled in a 0 based pool. Some resources, by
82  * design, are not 0 based, i.e. Full Action Records (SRAM) thus they
83  * need to be adjusted before they are handed out.
84  *
85  * [in] cfg
86  *   Pointer to the DB configuration
87  *
88  * [in] reservations
89  *   Pointer to the allocation values associated with the module
90  *
91  * [in] count
92  *   Number of DB configuration elements
93  *
94  * [out] valid_count
95  *   Number of HCAPI entries with a reservation value greater than 0
96  *
97  * Returns:
98  *     0          - Success
99  *   - EOPNOTSUPP - Operation not supported
100  */
101 static void
102 tf_rm_count_hcapi_reservations(enum tf_dir dir,
103                                enum tf_device_module_type type,
104                                struct tf_rm_element_cfg *cfg,
105                                uint16_t *reservations,
106                                uint16_t count,
107                                uint16_t *valid_count)
108 {
109         int i;
110         uint16_t cnt = 0;
111
112         for (i = 0; i < count; i++) {
113                 if ((cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
114                      cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) &&
115                     reservations[i] > 0)
116                         cnt++;
117
118                 /* Only log msg if a type is attempted reserved and
119                  * not supported. We ignore EM module as its using a
120                  * split configuration array thus it would fail for
121                  * this type of check.
122                  */
123                 if (type != TF_DEVICE_MODULE_TYPE_EM &&
124                     cfg[i].cfg_type == TF_RM_ELEM_CFG_NULL &&
125                     reservations[i] > 0) {
126                         TFP_DRV_LOG(ERR,
127                                 "%s, %s, %s allocation of %d not supported\n",
128                                 tf_device_module_type_2_str(type),
129                                 tf_dir_2_str(dir),
130                                 tf_device_module_type_subtype_2_str(type, i),
131                                 reservations[i]);
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_internal(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                                        dev,
419                                        parms->dir,
420                                        max_types,
421                                        query,
422                                        &resv_strategy);
423         if (rc)
424                 return rc;
425
426         /* Process capabilities against DB requirements. However, as a
427          * DB can hold elements that are not HCAPI we can reduce the
428          * req msg content by removing those out of the request yet
429          * the DB holds them all as to give a fast lookup. We can also
430          * remove entries where there are no request for elements.
431          */
432         tf_rm_count_hcapi_reservations(parms->dir,
433                                        parms->type,
434                                        parms->cfg,
435                                        parms->alloc_cnt,
436                                        parms->num_elements,
437                                        &hcapi_items);
438
439         /* Handle the case where a DB create request really ends up
440          * being empty. Unsupported (if not rare) case but possible
441          * that no resources are necessary for a 'direction'.
442          */
443         if (hcapi_items == 0) {
444                 TFP_DRV_LOG(ERR,
445                         "%s: DB create request for Zero elements, DB Type:%s\n",
446                         tf_dir_2_str(parms->dir),
447                         tf_device_module_type_2_str(parms->type));
448
449                 parms->rm_db = NULL;
450                 return -ENOMEM;
451         }
452
453         /* Alloc request, alignment already set */
454         cparms.nitems = (size_t)hcapi_items;
455         cparms.size = sizeof(struct tf_rm_resc_req_entry);
456         rc = tfp_calloc(&cparms);
457         if (rc)
458                 return rc;
459         req = (struct tf_rm_resc_req_entry *)cparms.mem_va;
460
461         /* Alloc reservation, alignment and nitems already set */
462         cparms.size = sizeof(struct tf_rm_resc_entry);
463         rc = tfp_calloc(&cparms);
464         if (rc)
465                 return rc;
466         resv = (struct tf_rm_resc_entry *)cparms.mem_va;
467
468         /* Build the request */
469         for (i = 0, j = 0; i < parms->num_elements; i++) {
470                 /* Skip any non HCAPI cfg elements */
471                 if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI ||
472                     parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) {
473                         /* Only perform reservation for entries that
474                          * has been requested
475                          */
476                         if (parms->alloc_cnt[i] == 0)
477                                 continue;
478
479                         /* Verify that we can get the full amount
480                          * allocated per the qcaps availability.
481                          */
482                         if (parms->alloc_cnt[i] <=
483                             query[parms->cfg[i].hcapi_type].max) {
484                                 req[j].type = parms->cfg[i].hcapi_type;
485                                 req[j].min = parms->alloc_cnt[i];
486                                 req[j].max = parms->alloc_cnt[i];
487                                 j++;
488                         } else {
489                                 TFP_DRV_LOG(ERR,
490                                             "%s: Resource failure, type:%d\n",
491                                             tf_dir_2_str(parms->dir),
492                                             parms->cfg[i].hcapi_type);
493                                 TFP_DRV_LOG(ERR,
494                                         "req:%d, avail:%d\n",
495                                         parms->alloc_cnt[i],
496                                         query[parms->cfg[i].hcapi_type].max);
497                                 return -EINVAL;
498                         }
499                 }
500         }
501
502         rc = tf_msg_session_resc_alloc(tfp,
503                                        dev,
504                                        parms->dir,
505                                        hcapi_items,
506                                        req,
507                                        resv);
508         if (rc)
509                 return rc;
510
511         /* Build the RM DB per the request */
512         cparms.nitems = 1;
513         cparms.size = sizeof(struct tf_rm_new_db);
514         rc = tfp_calloc(&cparms);
515         if (rc)
516                 return rc;
517         rm_db = (void *)cparms.mem_va;
518
519         /* Build the DB within RM DB */
520         cparms.nitems = parms->num_elements;
521         cparms.size = sizeof(struct tf_rm_element);
522         rc = tfp_calloc(&cparms);
523         if (rc)
524                 return rc;
525         rm_db->db = (struct tf_rm_element *)cparms.mem_va;
526
527         db = rm_db->db;
528         for (i = 0, j = 0; i < parms->num_elements; i++) {
529                 db[i].cfg_type = parms->cfg[i].cfg_type;
530                 db[i].hcapi_type = parms->cfg[i].hcapi_type;
531
532                 /* Skip any non HCAPI types as we didn't include them
533                  * in the reservation request.
534                  */
535                 if (parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI &&
536                     parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
537                         continue;
538
539                 /* If the element didn't request an allocation no need
540                  * to create a pool nor verify if we got a reservation.
541                  */
542                 if (parms->alloc_cnt[i] == 0)
543                         continue;
544
545                 /* If the element had requested an allocation and that
546                  * allocation was a success (full amount) then
547                  * allocate the pool.
548                  */
549                 if (parms->alloc_cnt[i] == resv[j].stride) {
550                         db[i].alloc.entry.start = resv[j].start;
551                         db[i].alloc.entry.stride = resv[j].stride;
552
553                         /* Only allocate BA pool if so requested */
554                         if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) {
555                                 /* Create pool */
556                                 pool_size = (BITALLOC_SIZEOF(resv[j].stride) /
557                                              sizeof(struct bitalloc));
558                                 /* Alloc request, alignment already set */
559                                 cparms.nitems = pool_size;
560                                 cparms.size = sizeof(struct bitalloc);
561                                 rc = tfp_calloc(&cparms);
562                                 if (rc) {
563                                         TFP_DRV_LOG(ERR,
564                                              "%s: Pool alloc failed, type:%d\n",
565                                              tf_dir_2_str(parms->dir),
566                                              db[i].cfg_type);
567                                         goto fail;
568                                 }
569                                 db[i].pool = (struct bitalloc *)cparms.mem_va;
570
571                                 rc = ba_init(db[i].pool, resv[j].stride);
572                                 if (rc) {
573                                         TFP_DRV_LOG(ERR,
574                                              "%s: Pool init failed, type:%d\n",
575                                              tf_dir_2_str(parms->dir),
576                                              db[i].cfg_type);
577                                         goto fail;
578                                 }
579                         }
580                         j++;
581                 } else {
582                         /* Bail out as we want what we requested for
583                          * all elements, not any less.
584                          */
585                         TFP_DRV_LOG(ERR,
586                                     "%s: Alloc failed, type:%d\n",
587                                     tf_dir_2_str(parms->dir),
588                                     db[i].cfg_type);
589                         TFP_DRV_LOG(ERR,
590                                     "req:%d, alloc:%d\n",
591                                     parms->alloc_cnt[i],
592                                     resv[j].stride);
593                         goto fail;
594                 }
595         }
596
597         rm_db->num_entries = parms->num_elements;
598         rm_db->dir = parms->dir;
599         rm_db->type = parms->type;
600         *parms->rm_db = (void *)rm_db;
601
602         tfp_free((void *)req);
603         tfp_free((void *)resv);
604
605         return 0;
606
607  fail:
608         tfp_free((void *)req);
609         tfp_free((void *)resv);
610         tfp_free((void *)db->pool);
611         tfp_free((void *)db);
612         tfp_free((void *)rm_db);
613         parms->rm_db = NULL;
614
615         return -EINVAL;
616 }
617
618 int
619 tf_rm_free_db(struct tf *tfp,
620               struct tf_rm_free_db_parms *parms)
621 {
622         int rc;
623         int i;
624         uint16_t resv_size = 0;
625         struct tf_rm_new_db *rm_db;
626         struct tf_rm_resc_entry *resv;
627         bool residuals_found = false;
628
629         TF_CHECK_PARMS2(parms, parms->rm_db);
630
631         /* Device unbind happens when the TF Session is closed and the
632          * session ref count is 0. Device unbind will cleanup each of
633          * its support modules, i.e. Identifier, thus we're ending up
634          * here to close the DB.
635          *
636          * On TF Session close it is assumed that the session has already
637          * cleaned up all its resources, individually, while
638          * destroying its flows.
639          *
640          * To assist in the 'cleanup checking' the DB is checked for any
641          * remaining elements and logged if found to be the case.
642          *
643          * Any such elements will need to be 'cleared' ahead of
644          * returning the resources to the HCAPI RM.
645          *
646          * RM will signal FW to flush the DB resources. FW will
647          * perform the invalidation. TF Session close will return the
648          * previous allocated elements to the RM and then close the
649          * HCAPI RM registration. That then saves several 'free' msgs
650          * from being required.
651          */
652
653         rm_db = (struct tf_rm_new_db *)parms->rm_db;
654
655         /* Check for residuals that the client didn't clean up */
656         rc = tf_rm_check_residuals(rm_db,
657                                    &resv_size,
658                                    &resv,
659                                    &residuals_found);
660         if (rc)
661                 return rc;
662
663         /* Invalidate any residuals followed by a DB traversal for
664          * pool cleanup.
665          */
666         if (residuals_found) {
667                 rc = tf_msg_session_resc_flush(tfp,
668                                                parms->dir,
669                                                resv_size,
670                                                resv);
671                 tfp_free((void *)resv);
672                 /* On failure we still have to cleanup so we can only
673                  * log that FW failed.
674                  */
675                 if (rc)
676                         TFP_DRV_LOG(ERR,
677                                     "%s: Internal Flush error, module:%s\n",
678                                     tf_dir_2_str(parms->dir),
679                                     tf_device_module_type_2_str(rm_db->type));
680         }
681
682         /* No need to check for configuration type, even if we do not
683          * have a BA pool we just delete on a null ptr, no harm
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         if (!rm_db->db)
706                 return -EINVAL;
707         cfg_type = rm_db->db[parms->db_index].cfg_type;
708
709         /* Bail out if not controlled by RM */
710         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
711                 return -ENOTSUP;
712
713         /* Bail out if the pool is not valid, should never happen */
714         if (rm_db->db[parms->db_index].pool == NULL) {
715                 rc = -ENOTSUP;
716                 TFP_DRV_LOG(ERR,
717                             "%s: Invalid pool for this type:%d, rc:%s\n",
718                             tf_dir_2_str(rm_db->dir),
719                             parms->db_index,
720                             strerror(-rc));
721                 return rc;
722         }
723
724         /*
725          * priority  0: allocate from top of the tcam i.e. high
726          * priority !0: allocate index from bottom i.e lowest
727          */
728         if (parms->priority)
729                 id = ba_alloc_reverse(rm_db->db[parms->db_index].pool);
730         else
731                 id = ba_alloc(rm_db->db[parms->db_index].pool);
732         if (id == BA_FAIL) {
733                 rc = -ENOMEM;
734                 TFP_DRV_LOG(ERR,
735                             "%s: Allocation failed, rc:%s\n",
736                             tf_dir_2_str(rm_db->dir),
737                             strerror(-rc));
738                 return rc;
739         }
740
741         /* Adjust for any non zero start value */
742         rc = tf_rm_adjust_index(rm_db->db,
743                                 TF_RM_ADJUST_ADD_BASE,
744                                 parms->db_index,
745                                 id,
746                                 &index);
747         if (rc) {
748                 TFP_DRV_LOG(ERR,
749                             "%s: Alloc adjust of base index failed, rc:%s\n",
750                             tf_dir_2_str(rm_db->dir),
751                             strerror(-rc));
752                 return -EINVAL;
753         }
754
755         *parms->index = index;
756         if (parms->base_index)
757                 *parms->base_index = id;
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         if (!rm_db->db)
774                 return -EINVAL;
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         if (!rm_db->db)
821                 return -EINVAL;
822         cfg_type = rm_db->db[parms->db_index].cfg_type;
823
824         /* Bail out if not controlled by RM */
825         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
826                 return -ENOTSUP;
827
828         /* Bail out if the pool is not valid, should never happen */
829         if (rm_db->db[parms->db_index].pool == NULL) {
830                 rc = -ENOTSUP;
831                 TFP_DRV_LOG(ERR,
832                             "%s: Invalid pool for this type:%d, rc:%s\n",
833                             tf_dir_2_str(rm_db->dir),
834                             parms->db_index,
835                             strerror(-rc));
836                 return rc;
837         }
838
839         /* Adjust for any non zero start value */
840         rc = tf_rm_adjust_index(rm_db->db,
841                                 TF_RM_ADJUST_RM_BASE,
842                                 parms->db_index,
843                                 parms->index,
844                                 &adj_index);
845         if (rc)
846                 return rc;
847
848         if (parms->base_index)
849                 *parms->base_index = adj_index;
850         *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool,
851                                      adj_index);
852
853         return rc;
854 }
855
856 int
857 tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
858 {
859         struct tf_rm_new_db *rm_db;
860         enum tf_rm_elem_cfg_type cfg_type;
861
862         TF_CHECK_PARMS2(parms, parms->rm_db);
863
864         rm_db = (struct tf_rm_new_db *)parms->rm_db;
865         if (!rm_db->db)
866                 return -EINVAL;
867         cfg_type = rm_db->db[parms->db_index].cfg_type;
868
869         /* Bail out if not controlled by HCAPI */
870         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
871             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
872                 return -ENOTSUP;
873
874         memcpy(parms->info,
875                &rm_db->db[parms->db_index].alloc,
876                sizeof(struct tf_rm_alloc_info));
877
878         return 0;
879 }
880
881 int
882 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
883 {
884         struct tf_rm_new_db *rm_db;
885         enum tf_rm_elem_cfg_type cfg_type;
886
887         TF_CHECK_PARMS2(parms, parms->rm_db);
888
889         rm_db = (struct tf_rm_new_db *)parms->rm_db;
890         if (!rm_db->db)
891                 return -EINVAL;
892         cfg_type = rm_db->db[parms->db_index].cfg_type;
893
894         /* Bail out if not controlled by HCAPI */
895         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
896             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
897                 return -ENOTSUP;
898
899         *parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type;
900
901         return 0;
902 }
903
904 int
905 tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
906 {
907         int rc = 0;
908         struct tf_rm_new_db *rm_db;
909         enum tf_rm_elem_cfg_type cfg_type;
910
911         TF_CHECK_PARMS2(parms, parms->rm_db);
912
913         rm_db = (struct tf_rm_new_db *)parms->rm_db;
914         if (!rm_db->db)
915                 return -EINVAL;
916         cfg_type = rm_db->db[parms->db_index].cfg_type;
917
918         /* Bail out if not controlled by RM */
919         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
920                 return -ENOTSUP;
921
922         /* Bail silently (no logging), if the pool is not valid there
923          * was no elements allocated for it.
924          */
925         if (rm_db->db[parms->db_index].pool == NULL) {
926                 *parms->count = 0;
927                 return 0;
928         }
929
930         *parms->count = ba_inuse_count(rm_db->db[parms->db_index].pool);
931
932         return rc;
933
934 }
935
936 int
937 tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms)
938 {
939         struct tf_rm_new_db *rm_db;
940         enum tf_rm_elem_cfg_type cfg_type;
941         uint32_t base_index;
942         uint32_t stride;
943         int rc = 0;
944
945         TF_CHECK_PARMS2(parms, parms->rm_db);
946
947         rm_db = (struct tf_rm_new_db *)parms->rm_db;
948         if (!rm_db->db)
949                 return -EINVAL;
950         cfg_type = rm_db->db[parms->db_index].cfg_type;
951
952         /* Bail out if not controlled by RM */
953         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
954                 return -ENOTSUP;
955
956         /* Bail out if the pool is not valid, should never happen */
957         if (rm_db->db[parms->db_index].pool == NULL) {
958                 rc = -ENOTSUP;
959                 TFP_DRV_LOG(ERR,
960                             "%s: Invalid pool for this type:%d, rc:%s\n",
961                             tf_dir_2_str(rm_db->dir),
962                             parms->db_index,
963                             strerror(-rc));
964                 return rc;
965         }
966
967         base_index = rm_db->db[parms->db_index].alloc.entry.start;
968         stride = rm_db->db[parms->db_index].alloc.entry.stride;
969
970         if (parms->starting_index < base_index ||
971             parms->starting_index + parms->num_entries > base_index + stride)
972                 return -EINVAL;
973
974         return rc;
975 }