net/ice/base: add inner VLAN protocol type for QinQ filter
[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
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         if (!rm_db->db)
710                 return -EINVAL;
711         cfg_type = rm_db->db[parms->db_index].cfg_type;
712
713         /* Bail out if not controlled by RM */
714         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
715                 return -ENOTSUP;
716
717         /* Bail out if the pool is not valid, should never happen */
718         if (rm_db->db[parms->db_index].pool == NULL) {
719                 rc = -ENOTSUP;
720                 TFP_DRV_LOG(ERR,
721                             "%s: Invalid pool for this type:%d, rc:%s\n",
722                             tf_dir_2_str(rm_db->dir),
723                             parms->db_index,
724                             strerror(-rc));
725                 return rc;
726         }
727
728         /*
729          * priority  0: allocate from top of the tcam i.e. high
730          * priority !0: allocate index from bottom i.e lowest
731          */
732         if (parms->priority)
733                 id = ba_alloc_reverse(rm_db->db[parms->db_index].pool);
734         else
735                 id = ba_alloc(rm_db->db[parms->db_index].pool);
736         if (id == BA_FAIL) {
737                 rc = -ENOMEM;
738                 TFP_DRV_LOG(ERR,
739                             "%s: Allocation failed, rc:%s\n",
740                             tf_dir_2_str(rm_db->dir),
741                             strerror(-rc));
742                 return rc;
743         }
744
745         /* Adjust for any non zero start value */
746         rc = tf_rm_adjust_index(rm_db->db,
747                                 TF_RM_ADJUST_ADD_BASE,
748                                 parms->db_index,
749                                 id,
750                                 &index);
751         if (rc) {
752                 TFP_DRV_LOG(ERR,
753                             "%s: Alloc adjust of base index failed, rc:%s\n",
754                             tf_dir_2_str(rm_db->dir),
755                             strerror(-rc));
756                 return -EINVAL;
757         }
758
759         *parms->index = index;
760         if (parms->base_index)
761                 *parms->base_index = id;
762
763         return rc;
764 }
765
766 int
767 tf_rm_free(struct tf_rm_free_parms *parms)
768 {
769         int rc;
770         uint32_t adj_index;
771         struct tf_rm_new_db *rm_db;
772         enum tf_rm_elem_cfg_type cfg_type;
773
774         TF_CHECK_PARMS2(parms, parms->rm_db);
775
776         rm_db = (struct tf_rm_new_db *)parms->rm_db;
777         if (!rm_db->db)
778                 return -EINVAL;
779         cfg_type = rm_db->db[parms->db_index].cfg_type;
780
781         /* Bail out if not controlled by RM */
782         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
783                 return -ENOTSUP;
784
785         /* Bail out if the pool is not valid, should never happen */
786         if (rm_db->db[parms->db_index].pool == NULL) {
787                 rc = -ENOTSUP;
788                 TFP_DRV_LOG(ERR,
789                             "%s: Invalid pool for this type:%d, rc:%s\n",
790                             tf_dir_2_str(rm_db->dir),
791                             parms->db_index,
792                             strerror(-rc));
793                 return rc;
794         }
795
796         /* Adjust for any non zero start value */
797         rc = tf_rm_adjust_index(rm_db->db,
798                                 TF_RM_ADJUST_RM_BASE,
799                                 parms->db_index,
800                                 parms->index,
801                                 &adj_index);
802         if (rc)
803                 return rc;
804
805         rc = ba_free(rm_db->db[parms->db_index].pool, adj_index);
806         /* No logging direction matters and that is not available here */
807         if (rc)
808                 return rc;
809
810         return rc;
811 }
812
813 int
814 tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)
815 {
816         int rc;
817         uint32_t adj_index;
818         struct tf_rm_new_db *rm_db;
819         enum tf_rm_elem_cfg_type cfg_type;
820
821         TF_CHECK_PARMS2(parms, parms->rm_db);
822
823         rm_db = (struct tf_rm_new_db *)parms->rm_db;
824         if (!rm_db->db)
825                 return -EINVAL;
826         cfg_type = rm_db->db[parms->db_index].cfg_type;
827
828         /* Bail out if not controlled by RM */
829         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
830                 return -ENOTSUP;
831
832         /* Bail out if the pool is not valid, should never happen */
833         if (rm_db->db[parms->db_index].pool == NULL) {
834                 rc = -ENOTSUP;
835                 TFP_DRV_LOG(ERR,
836                             "%s: Invalid pool for this type:%d, rc:%s\n",
837                             tf_dir_2_str(rm_db->dir),
838                             parms->db_index,
839                             strerror(-rc));
840                 return rc;
841         }
842
843         /* Adjust for any non zero start value */
844         rc = tf_rm_adjust_index(rm_db->db,
845                                 TF_RM_ADJUST_RM_BASE,
846                                 parms->db_index,
847                                 parms->index,
848                                 &adj_index);
849         if (rc)
850                 return rc;
851
852         if (parms->base_index)
853                 *parms->base_index = adj_index;
854         *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool,
855                                      adj_index);
856
857         return rc;
858 }
859
860 int
861 tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
862 {
863         struct tf_rm_new_db *rm_db;
864         enum tf_rm_elem_cfg_type cfg_type;
865
866         TF_CHECK_PARMS2(parms, parms->rm_db);
867
868         rm_db = (struct tf_rm_new_db *)parms->rm_db;
869         if (!rm_db->db)
870                 return -EINVAL;
871         cfg_type = rm_db->db[parms->db_index].cfg_type;
872
873         /* Bail out if not controlled by HCAPI */
874         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
875             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
876                 return -ENOTSUP;
877
878         memcpy(parms->info,
879                &rm_db->db[parms->db_index].alloc,
880                sizeof(struct tf_rm_alloc_info));
881
882         return 0;
883 }
884
885 int
886 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
887 {
888         struct tf_rm_new_db *rm_db;
889         enum tf_rm_elem_cfg_type cfg_type;
890
891         TF_CHECK_PARMS2(parms, parms->rm_db);
892
893         rm_db = (struct tf_rm_new_db *)parms->rm_db;
894         if (!rm_db->db)
895                 return -EINVAL;
896         cfg_type = rm_db->db[parms->db_index].cfg_type;
897
898         /* Bail out if not controlled by HCAPI */
899         if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
900             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
901                 return -ENOTSUP;
902
903         *parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type;
904
905         return 0;
906 }
907
908 int
909 tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
910 {
911         int rc = 0;
912         struct tf_rm_new_db *rm_db;
913         enum tf_rm_elem_cfg_type cfg_type;
914
915         TF_CHECK_PARMS2(parms, parms->rm_db);
916
917         rm_db = (struct tf_rm_new_db *)parms->rm_db;
918         if (!rm_db->db)
919                 return -EINVAL;
920         cfg_type = rm_db->db[parms->db_index].cfg_type;
921
922         /* Bail out if not controlled by RM */
923         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
924                 return -ENOTSUP;
925
926         /* Bail silently (no logging), if the pool is not valid there
927          * was no elements allocated for it.
928          */
929         if (rm_db->db[parms->db_index].pool == NULL) {
930                 *parms->count = 0;
931                 return 0;
932         }
933
934         *parms->count = ba_inuse_count(rm_db->db[parms->db_index].pool);
935
936         return rc;
937
938 }
939
940 int
941 tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms)
942 {
943         struct tf_rm_new_db *rm_db;
944         enum tf_rm_elem_cfg_type cfg_type;
945         uint32_t base_index;
946         uint32_t stride;
947         int rc = 0;
948
949         TF_CHECK_PARMS2(parms, parms->rm_db);
950
951         rm_db = (struct tf_rm_new_db *)parms->rm_db;
952         if (!rm_db->db)
953                 return -EINVAL;
954         cfg_type = rm_db->db[parms->db_index].cfg_type;
955
956         /* Bail out if not controlled by RM */
957         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA)
958                 return -ENOTSUP;
959
960         /* Bail out if the pool is not valid, should never happen */
961         if (rm_db->db[parms->db_index].pool == NULL) {
962                 rc = -ENOTSUP;
963                 TFP_DRV_LOG(ERR,
964                             "%s: Invalid pool for this type:%d, rc:%s\n",
965                             tf_dir_2_str(rm_db->dir),
966                             parms->db_index,
967                             strerror(-rc));
968                 return rc;
969         }
970
971         base_index = rm_db->db[parms->db_index].alloc.entry.start;
972         stride = rm_db->db[parms->db_index].alloc.entry.stride;
973
974         if (parms->starting_index < base_index ||
975             parms->starting_index + parms->num_entries > base_index + stride)
976                 return -EINVAL;
977
978         return rc;
979 }