eal: remove sys/queue.h from public headers
[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          * Resource slices.  How many slices will fit in the
42          * resource pool chunk size.
43          */
44         uint8_t slices;
45
46         /**
47          * HCAPI RM allocated range information for the element.
48          */
49         struct tf_rm_alloc_info alloc;
50
51         /**
52          * If cfg_type == HCAPI_BA_CHILD, this field indicates
53          * the parent module subtype for look up into the parent pool.
54          * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a
55          * module subtype of TF_MODULE_TYPE_TABLE.
56          */
57         uint16_t parent_subtype;
58
59         /**
60          * Bit allocator pool for the element. Pool size is controlled
61          * by the struct tf_session_resources at time of session creation.
62          * Null indicates that the pool is not used for the element.
63          */
64         struct bitalloc *pool;
65 };
66
67 /**
68  * TF RM DB definition
69  */
70 struct tf_rm_new_db {
71         /**
72          * Number of elements in the DB
73          */
74         uint16_t num_entries;
75
76         /**
77          * Direction this DB controls.
78          */
79         enum tf_dir dir;
80
81         /**
82          * Module type, used for logging purposes.
83          */
84         enum tf_module_type module;
85
86         /**
87          * The DB consists of an array of elements
88          */
89         struct tf_rm_element *db;
90 };
91
92 /**
93  * Adjust an index according to the allocation information.
94  *
95  * All resources are controlled in a 0 based pool. Some resources, by
96  * design, are not 0 based, i.e. Full Action Records (SRAM) thus they
97  * need to be adjusted before they are handed out.
98  *
99  * [in] cfg
100  *   Pointer to the DB configuration
101  *
102  * [in] reservations
103  *   Pointer to the allocation values associated with the module
104  *
105  * [in] count
106  *   Number of DB configuration elements
107  *
108  * [out] valid_count
109  *   Number of HCAPI entries with a reservation value greater than 0
110  *
111  * Returns:
112  *     0          - Success
113  *   - EOPNOTSUPP - Operation not supported
114  */
115 static void
116 tf_rm_count_hcapi_reservations(enum tf_dir dir,
117                                enum tf_module_type module,
118                                struct tf_rm_element_cfg *cfg,
119                                uint16_t *reservations,
120                                uint16_t count,
121                                uint16_t *valid_count)
122 {
123         int i;
124         uint16_t cnt = 0;
125
126         for (i = 0; i < count; i++) {
127                 if (cfg[i].cfg_type != TF_RM_ELEM_CFG_NULL &&
128                     reservations[i] > 0)
129                         cnt++;
130
131                 /* Only log msg if a type is attempted reserved and
132                  * not supported. We ignore EM module as its using a
133                  * split configuration array thus it would fail for
134                  * this type of check.
135                  */
136                 if (module != TF_MODULE_TYPE_EM &&
137                     cfg[i].cfg_type == TF_RM_ELEM_CFG_NULL &&
138                     reservations[i] > 0) {
139                         TFP_DRV_LOG(ERR,
140                                 "%s, %s, %s allocation of %d not supported\n",
141                                 tf_module_2_str(module),
142                                 tf_dir_2_str(dir),
143                                 tf_module_subtype_2_str(module, i),
144                                 reservations[i]);
145                 }
146         }
147
148         *valid_count = cnt;
149 }
150
151 /**
152  * Resource Manager Adjust of base index definitions.
153  */
154 enum tf_rm_adjust_type {
155         TF_RM_ADJUST_ADD_BASE, /**< Adds base to the index */
156         TF_RM_ADJUST_RM_BASE   /**< Removes base from the index */
157 };
158
159 /**
160  * Adjust an index according to the allocation information.
161  *
162  * All resources are controlled in a 0 based pool. Some resources, by
163  * design, are not 0 based, i.e. Full Action Records (SRAM) thus they
164  * need to be adjusted before they are handed out.
165  *
166  * [in] db
167  *   Pointer to the db, used for the lookup
168  *
169  * [in] action
170  *   Adjust action
171  *
172  * [in] subtype
173  *   TF module subtype used as an index into the database.
174  *   An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a
175  *   module subtype of TF_MODULE_TYPE_TABLE.
176  *
177  * [in] index
178  *   Index to convert
179  *
180  * [out] adj_index
181  *   Adjusted index
182  *
183  * Returns:
184  *     0          - Success
185  *   - EOPNOTSUPP - Operation not supported
186  */
187 static int
188 tf_rm_adjust_index(struct tf_rm_element *db,
189                    enum tf_rm_adjust_type action,
190                    uint32_t subtype,
191                    uint32_t index,
192                    uint32_t *adj_index)
193 {
194         int rc = 0;
195         uint32_t base_index;
196
197         base_index = db[subtype].alloc.entry.start;
198
199         switch (action) {
200         case TF_RM_ADJUST_RM_BASE:
201                 *adj_index = index - base_index;
202                 break;
203         case TF_RM_ADJUST_ADD_BASE:
204                 *adj_index = index + base_index;
205                 break;
206         default:
207                 return -EOPNOTSUPP;
208         }
209
210         return rc;
211 }
212
213 /**
214  * Logs an array of found residual entries to the console.
215  *
216  * [in] dir
217  *   Receive or transmit direction
218  *
219  * [in] module
220  *   Type of Device Module
221  *
222  * [in] count
223  *   Number of entries in the residual array
224  *
225  * [in] residuals
226  *   Pointer to an array of residual entries. Array is index same as
227  *   the DB in which this function is used. Each entry holds residual
228  *   value for that entry.
229  */
230 #if (TF_RM_DEBUG == 1)
231 static void
232 tf_rm_log_residuals(enum tf_dir dir,
233                     enum tf_module_type module,
234                     uint16_t count,
235                     uint16_t *residuals)
236 {
237         int i;
238
239         /* Walk the residual array and log the types that wasn't
240          * cleaned up to the console.
241          */
242         for (i = 0; i < count; i++) {
243                 if (residuals[i] != 0)
244                         TFP_DRV_LOG(INFO,
245                                 "%s, %s was not cleaned up, %d outstanding\n",
246                                 tf_dir_2_str(dir),
247                                 tf_module_subtype_2_str(module, i),
248                                 residuals[i]);
249         }
250 }
251 #endif /* TF_RM_DEBUG == 1 */
252 /**
253  * Performs a check of the passed in DB for any lingering elements. If
254  * a resource type was found to not have been cleaned up by the caller
255  * then its residual values are recorded, logged and passed back in an
256  * allocate reservation array that the caller can pass to the FW for
257  * cleanup.
258  *
259  * [in] db
260  *   Pointer to the db, used for the lookup
261  *
262  * [out] resv_size
263  *   Pointer to the reservation size of the generated reservation
264  *   array.
265  *
266  * [in/out] resv
267  *   Pointer Pointer to a reservation array. The reservation array is
268  *   allocated after the residual scan and holds any found residual
269  *   entries. Thus it can be smaller than the DB that the check was
270  *   performed on. Array must be freed by the caller.
271  *
272  * [out] residuals_present
273  *   Pointer to a bool flag indicating if residual was present in the
274  *   DB
275  *
276  * Returns:
277  *     0          - Success
278  *   - EOPNOTSUPP - Operation not supported
279  */
280 static int
281 tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
282                       uint16_t *resv_size,
283                       struct tf_rm_resc_entry **resv,
284                       bool *residuals_present)
285 {
286         int rc;
287         int i;
288         int f;
289         uint16_t count;
290         uint16_t found;
291         uint16_t *residuals = NULL;
292         uint16_t hcapi_type;
293         struct tf_rm_get_inuse_count_parms iparms;
294         struct tf_rm_get_alloc_info_parms aparms;
295         struct tf_rm_get_hcapi_parms hparms;
296         struct tf_rm_alloc_info info;
297         struct tfp_calloc_parms cparms;
298         struct tf_rm_resc_entry *local_resv = NULL;
299
300         /* Create array to hold the entries that have residuals */
301         cparms.nitems = rm_db->num_entries;
302         cparms.size = sizeof(uint16_t);
303         cparms.alignment = 0;
304         rc = tfp_calloc(&cparms);
305         if (rc)
306                 return rc;
307
308         residuals = (uint16_t *)cparms.mem_va;
309
310         /* Traverse the DB and collect any residual elements */
311         iparms.rm_db = rm_db;
312         iparms.count = &count;
313         for (i = 0, found = 0; i < rm_db->num_entries; i++) {
314                 iparms.subtype = i;
315                 rc = tf_rm_get_inuse_count(&iparms);
316                 /* Not a device supported entry, just skip */
317                 if (rc == -ENOTSUP)
318                         continue;
319                 if (rc)
320                         goto cleanup_residuals;
321
322                 if (count) {
323                         found++;
324                         residuals[i] = count;
325                         *residuals_present = true;
326                 }
327         }
328
329         if (*residuals_present) {
330                 /* Populate a reduced resv array with only the entries
331                  * that have residuals.
332                  */
333                 cparms.nitems = found;
334                 cparms.size = sizeof(struct tf_rm_resc_entry);
335                 cparms.alignment = 0;
336                 rc = tfp_calloc(&cparms);
337                 if (rc)
338                         return rc;
339
340                 local_resv = (struct tf_rm_resc_entry *)cparms.mem_va;
341
342                 aparms.rm_db = rm_db;
343                 hparms.rm_db = rm_db;
344                 hparms.hcapi_type = &hcapi_type;
345                 for (i = 0, f = 0; i < rm_db->num_entries; i++) {
346                         if (residuals[i] == 0)
347                                 continue;
348                         aparms.subtype = i;
349                         aparms.info = &info;
350                         rc = tf_rm_get_info(&aparms);
351                         if (rc)
352                                 goto cleanup_all;
353
354                         hparms.subtype = i;
355                         rc = tf_rm_get_hcapi_type(&hparms);
356                         if (rc)
357                                 goto cleanup_all;
358
359                         local_resv[f].type = hcapi_type;
360                         local_resv[f].start = info.entry.start;
361                         local_resv[f].stride = info.entry.stride;
362                         f++;
363                 }
364                 *resv_size = found;
365         }
366
367 #if (TF_RM_DEBUG == 1)
368         tf_rm_log_residuals(rm_db->dir,
369                             rm_db->module,
370                             rm_db->num_entries,
371                             residuals);
372 #endif
373         tfp_free((void *)residuals);
374         *resv = local_resv;
375
376         return 0;
377
378  cleanup_all:
379         tfp_free((void *)local_resv);
380         *resv = NULL;
381  cleanup_residuals:
382         tfp_free((void *)residuals);
383
384         return rc;
385 }
386
387 /**
388  * Some resources do not have a 1:1 mapping between the Truflow type and the cfa
389  * resource type (HCAPI RM).  These resources have multiple Truflow types which
390  * map to a single HCAPI RM type.  In order to support this, one Truflow type
391  * sharing the HCAPI resources is designated the parent.  All other Truflow
392  * types associated with that HCAPI RM type are designated the children.
393  *
394  * This function updates the resource counts of any HCAPI_BA_PARENT with the
395  * counts of the HCAPI_BA_CHILDREN.  These are read from the alloc_cnt and
396  * written back to the req_cnt.
397  *
398  * [in] cfg
399  *   Pointer to an array of module specific Truflow type indexed RM cfg items
400  *
401  * [in] alloc_cnt
402  *   Pointer to the tf_open_session() configured array of module specific
403  *   Truflow type indexed requested counts.
404  *
405  * [in/out] req_cnt
406  *   Pointer to the location to put the updated resource counts.
407  *
408  * Returns:
409  *     0          - Success
410  *     -          - Failure if negative
411  */
412 static int
413 tf_rm_update_parent_reservations(struct tf *tfp,
414                                  struct tf_dev_info *dev,
415                                  struct tf_rm_element_cfg *cfg,
416                                  uint16_t *alloc_cnt,
417                                  uint16_t num_elements,
418                                  uint16_t *req_cnt,
419                                  bool shared_session)
420 {
421         int parent, child;
422         const char *type_str;
423
424         /* Search through all the elements */
425         for (parent = 0; parent < num_elements; parent++) {
426                 uint16_t combined_cnt = 0;
427
428                 /* If I am a parent */
429                 if (cfg[parent].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
430                         uint8_t p_slices = 1;
431
432                         /* Shared session doesn't support slices */
433                         if (!shared_session)
434                                 p_slices = cfg[parent].slices;
435
436                         RTE_ASSERT(p_slices);
437
438                         combined_cnt = alloc_cnt[parent] / p_slices;
439
440                         if (alloc_cnt[parent] % p_slices)
441                                 combined_cnt++;
442
443                         if (alloc_cnt[parent]) {
444                                 dev->ops->tf_dev_get_resource_str(tfp,
445                                                          cfg[parent].hcapi_type,
446                                                          &type_str);
447 #if (TF_RM_DEBUG == 1)
448                                 printf("%s:%s cnt(%d) slices(%d)\n",
449                                        type_str, tf_tbl_type_2_str(parent),
450                                        alloc_cnt[parent], p_slices);
451 #endif /* (TF_RM_DEBUG == 1) */
452                         }
453
454                         /* Search again through all the elements */
455                         for (child = 0; child < num_elements; child++) {
456                                 /* If this is one of my children */
457                                 if (cfg[child].cfg_type ==
458                                     TF_RM_ELEM_CFG_HCAPI_BA_CHILD &&
459                                     cfg[child].parent_subtype == parent &&
460                                     alloc_cnt[child]) {
461                                         uint8_t c_slices = 1;
462                                         uint16_t cnt = 0;
463
464                                         if (!shared_session)
465                                                 c_slices = cfg[child].slices;
466
467                                         RTE_ASSERT(c_slices);
468
469                                         dev->ops->tf_dev_get_resource_str(tfp,
470                                                           cfg[child].hcapi_type,
471                                                            &type_str);
472 #if (TF_RM_DEBUG == 1)
473                                         printf("%s:%s cnt(%d) slices(%d)\n",
474                                                type_str,
475                                                tf_tbl_type_2_str(child),
476                                                alloc_cnt[child],
477                                                c_slices);
478 #endif /* (TF_RM_DEBUG == 1) */
479                                         /* Increment the parents combined count
480                                          * with each child's count adjusted for
481                                          * number of slices per RM alloc item.
482                                          */
483                                         cnt = alloc_cnt[child] / c_slices;
484
485                                         if (alloc_cnt[child] % c_slices)
486                                                 cnt++;
487
488                                         combined_cnt += cnt;
489                                         /* Clear the requested child count */
490                                         req_cnt[child] = 0;
491                                 }
492                         }
493                         /* Save the parent count to be requested */
494                         req_cnt[parent] = combined_cnt;
495 #if (TF_RM_DEBUG == 1)
496                         printf("%s calculated total:%d\n\n",
497                                type_str, req_cnt[parent]);
498 #endif /* (TF_RM_DEBUG == 1) */
499                 }
500         }
501         return 0;
502 }
503
504 int
505 tf_rm_create_db(struct tf *tfp,
506                 struct tf_rm_create_db_parms *parms)
507 {
508         int rc;
509         struct tf_session *tfs;
510         struct tf_dev_info *dev;
511         int i, j;
512         uint16_t max_types, hcapi_items, *req_cnt;
513         struct tfp_calloc_parms cparms;
514         struct tf_rm_resc_req_entry *query;
515         enum tf_rm_resc_resv_strategy resv_strategy;
516         struct tf_rm_resc_req_entry *req;
517         struct tf_rm_resc_entry *resv;
518         struct tf_rm_new_db *rm_db;
519         struct tf_rm_element *db;
520         uint32_t pool_size;
521         bool shared_session = 0;
522
523         TF_CHECK_PARMS2(tfp, parms);
524
525         /* Retrieve the session information */
526         rc = tf_session_get_session_internal(tfp, &tfs);
527         if (rc)
528                 return rc;
529
530         /* Retrieve device information */
531         rc = tf_session_get_device(tfs, &dev);
532         if (rc)
533                 return rc;
534
535         /* Need device max number of elements for the RM QCAPS */
536         rc = dev->ops->tf_dev_get_max_types(tfp, &max_types);
537
538         /* Allocate memory for RM QCAPS request */
539         cparms.nitems = max_types;
540         cparms.size = sizeof(struct tf_rm_resc_req_entry);
541         cparms.alignment = 0;
542         rc = tfp_calloc(&cparms);
543         if (rc)
544                 return rc;
545
546         query = (struct tf_rm_resc_req_entry *)cparms.mem_va;
547
548         /* Get Firmware Capabilities */
549         rc = tf_msg_session_resc_qcaps(tfp,
550                                        dev,
551                                        parms->dir,
552                                        max_types,
553                                        query,
554                                        &resv_strategy);
555         if (rc)
556                 return rc;
557
558         /* Copy requested counts (alloc_cnt) from tf_open_session() to local
559          * copy (req_cnt) so that it can be updated if required.
560          */
561
562         cparms.nitems = parms->num_elements;
563         cparms.size = sizeof(uint16_t);
564         rc = tfp_calloc(&cparms);
565         if (rc)
566                 return rc;
567
568         req_cnt = (uint16_t *)cparms.mem_va;
569
570         tfp_memcpy(req_cnt, parms->alloc_cnt,
571                    parms->num_elements * sizeof(uint16_t));
572
573         shared_session = tf_session_is_shared_session(tfs);
574
575         /* Update the req_cnt based upon the element configuration
576          */
577         tf_rm_update_parent_reservations(tfp, dev, parms->cfg,
578                                          parms->alloc_cnt,
579                                          parms->num_elements,
580                                          req_cnt,
581                                          shared_session);
582
583         /* Process capabilities against DB requirements. However, as a
584          * DB can hold elements that are not HCAPI we can reduce the
585          * req msg content by removing those out of the request yet
586          * the DB holds them all as to give a fast lookup. We can also
587          * remove entries where there are no request for elements.
588          */
589         tf_rm_count_hcapi_reservations(parms->dir,
590                                        parms->module,
591                                        parms->cfg,
592                                        req_cnt,
593                                        parms->num_elements,
594                                        &hcapi_items);
595
596         if (hcapi_items == 0) {
597 #if (TF_RM_DEBUG == 1)
598                 TFP_DRV_LOG(INFO,
599                         "%s: module: %s Empty RM DB create request\n",
600                         tf_dir_2_str(parms->dir),
601                         tf_module_2_str(parms->module));
602 #endif
603                 parms->rm_db = NULL;
604                 return -ENOMEM;
605         }
606
607         /* Alloc request, alignment already set */
608         cparms.nitems = (size_t)hcapi_items;
609         cparms.size = sizeof(struct tf_rm_resc_req_entry);
610         rc = tfp_calloc(&cparms);
611         if (rc)
612                 return rc;
613         req = (struct tf_rm_resc_req_entry *)cparms.mem_va;
614
615         /* Alloc reservation, alignment and nitems already set */
616         cparms.size = sizeof(struct tf_rm_resc_entry);
617         rc = tfp_calloc(&cparms);
618         if (rc)
619                 return rc;
620         resv = (struct tf_rm_resc_entry *)cparms.mem_va;
621
622         /* Build the request */
623         for (i = 0, j = 0; i < parms->num_elements; i++) {
624                 struct tf_rm_element_cfg *cfg = &parms->cfg[i];
625                 uint16_t hcapi_type = cfg->hcapi_type;
626
627                 /* Only perform reservation for requested entries
628                  */
629                 if (req_cnt[i] == 0)
630                         continue;
631
632                 /* Skip any children in the request */
633                 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI ||
634                     cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
635                     cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
636
637                         /* Verify that we can get the full amount per qcaps.
638                          */
639                         if (req_cnt[i] <= query[hcapi_type].max) {
640                                 req[j].type = hcapi_type;
641                                 req[j].min = req_cnt[i];
642                                 req[j].max = req_cnt[i];
643                                 j++;
644                         } else {
645                                 const char *type_str;
646
647                                 dev->ops->tf_dev_get_resource_str(tfp,
648                                                               hcapi_type,
649                                                               &type_str);
650                                 TFP_DRV_LOG(ERR,
651                                         "Failure, %s:%d:%s req:%d avail:%d\n",
652                                         tf_dir_2_str(parms->dir),
653                                         hcapi_type, type_str,
654                                         req_cnt[i],
655                                         query[hcapi_type].max);
656                                 return -EINVAL;
657                         }
658                 }
659         }
660
661         /* Allocate all resources for the module type
662          */
663         rc = tf_msg_session_resc_alloc(tfp,
664                                        dev,
665                                        parms->dir,
666                                        hcapi_items,
667                                        req,
668                                        resv);
669         if (rc)
670                 return rc;
671
672         /* Build the RM DB per the request */
673         cparms.nitems = 1;
674         cparms.size = sizeof(struct tf_rm_new_db);
675         rc = tfp_calloc(&cparms);
676         if (rc)
677                 return rc;
678         rm_db = (void *)cparms.mem_va;
679
680         /* Build the DB within RM DB */
681         cparms.nitems = parms->num_elements;
682         cparms.size = sizeof(struct tf_rm_element);
683         rc = tfp_calloc(&cparms);
684         if (rc)
685                 return rc;
686         rm_db->db = (struct tf_rm_element *)cparms.mem_va;
687
688         db = rm_db->db;
689         for (i = 0, j = 0; i < parms->num_elements; i++) {
690                 struct tf_rm_element_cfg *cfg = &parms->cfg[i];
691                 const char *type_str;
692
693                 dev->ops->tf_dev_get_resource_str(tfp,
694                                                   cfg->hcapi_type,
695                                                   &type_str);
696
697                 db[i].cfg_type = cfg->cfg_type;
698                 db[i].hcapi_type = cfg->hcapi_type;
699                 db[i].slices = cfg->slices;
700
701                 /* Save the parent subtype for later use to find the pool
702                  */
703                 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
704                         db[i].parent_subtype = cfg->parent_subtype;
705
706                 /* If the element didn't request an allocation no need
707                  * to create a pool nor verify if we got a reservation.
708                  */
709                 if (req_cnt[i] == 0)
710                         continue;
711
712                 /* Skip any children or invalid
713                  */
714                 if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI &&
715                     cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
716                     cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT)
717                         continue;
718
719                 /* If the element had requested an allocation and that
720                  * allocation was a success (full amount) then
721                  * allocate the pool.
722                  */
723                 if (req_cnt[i] == resv[j].stride) {
724                         db[i].alloc.entry.start = resv[j].start;
725                         db[i].alloc.entry.stride = resv[j].stride;
726
727                         /* Only allocate BA pool if a BA type not a child */
728                         if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
729                             cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
730                                 /* Create pool */
731                                 pool_size = (BITALLOC_SIZEOF(resv[j].stride) /
732                                              sizeof(struct bitalloc));
733                                 /* Alloc request, alignment already set */
734                                 cparms.nitems = pool_size;
735                                 cparms.size = sizeof(struct bitalloc);
736                                 rc = tfp_calloc(&cparms);
737                                 if (rc) {
738                                         TFP_DRV_LOG(ERR,
739                                          "%s: Pool alloc failed, type:%d:%s\n",
740                                          tf_dir_2_str(parms->dir),
741                                          cfg->hcapi_type, type_str);
742                                         goto fail;
743                                 }
744                                 db[i].pool = (struct bitalloc *)cparms.mem_va;
745
746                                 rc = ba_init(db[i].pool,
747                                              resv[j].stride,
748                                              !tf_session_is_shared_session(tfs));
749                                 if (rc) {
750                                         TFP_DRV_LOG(ERR,
751                                           "%s: Pool init failed, type:%d:%s\n",
752                                           tf_dir_2_str(parms->dir),
753                                           cfg->hcapi_type, type_str);
754                                         goto fail;
755                                 }
756                         }
757                         j++;
758                 } else {
759                         /* Bail out as we want what we requested for
760                          * all elements, not any less.
761                          */
762                         TFP_DRV_LOG(ERR,
763                                     "%s: Alloc failed %d:%s req:%d, alloc:%d\n",
764                                     tf_dir_2_str(parms->dir), cfg->hcapi_type,
765                                     type_str, req_cnt[i], resv[j].stride);
766                         goto fail;
767                 }
768         }
769
770         rm_db->num_entries = parms->num_elements;
771         rm_db->dir = parms->dir;
772         rm_db->module = parms->module;
773         *parms->rm_db = (void *)rm_db;
774
775 #if (TF_RM_DEBUG == 1)
776
777         printf("%s: module:%s\n",
778                tf_dir_2_str(parms->dir),
779                tf_module_2_str(parms->module));
780 #endif /* (TF_RM_DEBUG == 1) */
781
782         tfp_free((void *)req);
783         tfp_free((void *)resv);
784         tfp_free((void *)req_cnt);
785         return 0;
786
787  fail:
788         tfp_free((void *)req);
789         tfp_free((void *)resv);
790         tfp_free((void *)db->pool);
791         tfp_free((void *)db);
792         tfp_free((void *)rm_db);
793         tfp_free((void *)req_cnt);
794         parms->rm_db = NULL;
795
796         return -EINVAL;
797 }
798
799 int
800 tf_rm_create_db_no_reservation(struct tf *tfp,
801                                struct tf_rm_create_db_parms *parms)
802 {
803         int rc;
804         struct tf_session *tfs;
805         struct tf_dev_info *dev;
806         int i, j;
807         uint16_t hcapi_items, *req_cnt;
808         struct tfp_calloc_parms cparms;
809         struct tf_rm_resc_req_entry *req;
810         struct tf_rm_resc_entry *resv;
811         struct tf_rm_new_db *rm_db;
812         struct tf_rm_element *db;
813         uint32_t pool_size;
814
815         TF_CHECK_PARMS2(tfp, parms);
816
817         /* Retrieve the session information */
818         rc = tf_session_get_session_internal(tfp, &tfs);
819         if (rc)
820                 return rc;
821
822         /* Retrieve device information */
823         rc = tf_session_get_device(tfs, &dev);
824         if (rc)
825                 return rc;
826
827         /* Copy requested counts (alloc_cnt) from tf_open_session() to local
828          * copy (req_cnt) so that it can be updated if required.
829          */
830
831         cparms.nitems = parms->num_elements;
832         cparms.size = sizeof(uint16_t);
833         cparms.alignment = 0;
834         rc = tfp_calloc(&cparms);
835         if (rc)
836                 return rc;
837
838         req_cnt = (uint16_t *)cparms.mem_va;
839
840         tfp_memcpy(req_cnt, parms->alloc_cnt,
841                    parms->num_elements * sizeof(uint16_t));
842
843         /* Process capabilities against DB requirements. However, as a
844          * DB can hold elements that are not HCAPI we can reduce the
845          * req msg content by removing those out of the request yet
846          * the DB holds them all as to give a fast lookup. We can also
847          * remove entries where there are no request for elements.
848          */
849         tf_rm_count_hcapi_reservations(parms->dir,
850                                        parms->module,
851                                        parms->cfg,
852                                        req_cnt,
853                                        parms->num_elements,
854                                        &hcapi_items);
855
856         if (hcapi_items == 0) {
857                 TFP_DRV_LOG(ERR,
858                         "%s: module:%s Empty RM DB create request\n",
859                         tf_dir_2_str(parms->dir),
860                         tf_module_2_str(parms->module));
861
862                 parms->rm_db = NULL;
863                 return -ENOMEM;
864         }
865
866         /* Alloc request, alignment already set */
867         cparms.nitems = (size_t)hcapi_items;
868         cparms.size = sizeof(struct tf_rm_resc_req_entry);
869         rc = tfp_calloc(&cparms);
870         if (rc)
871                 return rc;
872         req = (struct tf_rm_resc_req_entry *)cparms.mem_va;
873
874         /* Alloc reservation, alignment and nitems already set */
875         cparms.size = sizeof(struct tf_rm_resc_entry);
876         rc = tfp_calloc(&cparms);
877         if (rc)
878                 return rc;
879         resv = (struct tf_rm_resc_entry *)cparms.mem_va;
880
881         /* Build the request */
882         for (i = 0, j = 0; i < parms->num_elements; i++) {
883                 struct tf_rm_element_cfg *cfg = &parms->cfg[i];
884                 uint16_t hcapi_type = cfg->hcapi_type;
885
886                 /* Only perform reservation for requested entries
887                  */
888                 if (req_cnt[i] == 0)
889                         continue;
890
891                 /* Skip any children in the request */
892                 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI ||
893                     cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
894                     cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
895                         req[j].type = hcapi_type;
896                         req[j].min = req_cnt[i];
897                         req[j].max = req_cnt[i];
898                         j++;
899                 }
900         }
901
902         /* Get all resources info for the module type
903          */
904         rc = tf_msg_session_resc_info(tfp,
905                                       dev,
906                                       parms->dir,
907                                       hcapi_items,
908                                       req,
909                                       resv);
910         if (rc)
911                 return rc;
912
913         /* Build the RM DB per the request */
914         cparms.nitems = 1;
915         cparms.size = sizeof(struct tf_rm_new_db);
916         rc = tfp_calloc(&cparms);
917         if (rc)
918                 return rc;
919         rm_db = (void *)cparms.mem_va;
920
921         /* Build the DB within RM DB */
922         cparms.nitems = parms->num_elements;
923         cparms.size = sizeof(struct tf_rm_element);
924         rc = tfp_calloc(&cparms);
925         if (rc)
926                 return rc;
927         rm_db->db = (struct tf_rm_element *)cparms.mem_va;
928
929         db = rm_db->db;
930         for (i = 0, j = 0; i < parms->num_elements; i++) {
931                 struct tf_rm_element_cfg *cfg = &parms->cfg[i];
932                 const char *type_str;
933
934                 dev->ops->tf_dev_get_resource_str(tfp,
935                                                   cfg->hcapi_type,
936                                                   &type_str);
937
938                 db[i].cfg_type = cfg->cfg_type;
939                 db[i].hcapi_type = cfg->hcapi_type;
940
941                 /* Save the parent subtype for later use to find the pool
942                  */
943                 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
944                         db[i].parent_subtype = cfg->parent_subtype;
945
946                 /* If the element didn't request an allocation no need
947                  * to create a pool nor verify if we got a reservation.
948                  */
949                 if (req_cnt[i] == 0)
950                         continue;
951
952                 /* Skip any children or invalid
953                  */
954                 if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI &&
955                     cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
956                     cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT)
957                         continue;
958
959                 /* If the element had requested an allocation and that
960                  * allocation was a success (full amount) then
961                  * allocate the pool.
962                  */
963                 if (req_cnt[i] == resv[j].stride) {
964                         db[i].alloc.entry.start = resv[j].start;
965                         db[i].alloc.entry.stride = resv[j].stride;
966
967                         /* Only allocate BA pool if a BA type not a child */
968                         if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA ||
969                             cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) {
970                                 /* Create pool */
971                                 pool_size = (BITALLOC_SIZEOF(resv[j].stride) /
972                                              sizeof(struct bitalloc));
973                                 /* Alloc request, alignment already set */
974                                 cparms.nitems = pool_size;
975                                 cparms.size = sizeof(struct bitalloc);
976                                 rc = tfp_calloc(&cparms);
977                                 if (rc) {
978                                         TFP_DRV_LOG(ERR,
979                                          "%s: Pool alloc failed, type:%d:%s\n",
980                                          tf_dir_2_str(parms->dir),
981                                          cfg->hcapi_type, type_str);
982                                         goto fail;
983                                 }
984                                 db[i].pool = (struct bitalloc *)cparms.mem_va;
985
986                                 rc = ba_init(db[i].pool,
987                                              resv[j].stride,
988                                              !tf_session_is_shared_session(tfs));
989                                 if (rc) {
990                                         TFP_DRV_LOG(ERR,
991                                           "%s: Pool init failed, type:%d:%s\n",
992                                           tf_dir_2_str(parms->dir),
993                                           cfg->hcapi_type, type_str);
994                                         goto fail;
995                                 }
996                         }
997                         j++;
998                 } else {
999                         /* Bail out as we want what we requested for
1000                          * all elements, not any less.
1001                          */
1002                         TFP_DRV_LOG(ERR,
1003                                     "%s: Alloc failed %d:%s req:%d, alloc:%d\n",
1004                                     tf_dir_2_str(parms->dir), cfg->hcapi_type,
1005                                     type_str, req_cnt[i], resv[j].stride);
1006                         goto fail;
1007                 }
1008         }
1009
1010         rm_db->num_entries = parms->num_elements;
1011         rm_db->dir = parms->dir;
1012         rm_db->module = parms->module;
1013         *parms->rm_db = (void *)rm_db;
1014
1015 #if (TF_RM_DEBUG == 1)
1016
1017         printf("%s: module:%s\n",
1018                tf_dir_2_str(parms->dir),
1019                tf_module_2_str(parms->module));
1020 #endif /* (TF_RM_DEBUG == 1) */
1021
1022         tfp_free((void *)req);
1023         tfp_free((void *)resv);
1024         tfp_free((void *)req_cnt);
1025         return 0;
1026
1027  fail:
1028         tfp_free((void *)req);
1029         tfp_free((void *)resv);
1030         tfp_free((void *)db->pool);
1031         tfp_free((void *)db);
1032         tfp_free((void *)rm_db);
1033         tfp_free((void *)req_cnt);
1034         parms->rm_db = NULL;
1035
1036         return -EINVAL;
1037 }
1038 int
1039 tf_rm_free_db(struct tf *tfp,
1040               struct tf_rm_free_db_parms *parms)
1041 {
1042         int rc;
1043         int i;
1044         uint16_t resv_size = 0;
1045         struct tf_rm_new_db *rm_db;
1046         struct tf_rm_resc_entry *resv;
1047         bool residuals_found = false;
1048
1049         TF_CHECK_PARMS2(parms, parms->rm_db);
1050
1051         /* Device unbind happens when the TF Session is closed and the
1052          * session ref count is 0. Device unbind will cleanup each of
1053          * its support modules, i.e. Identifier, thus we're ending up
1054          * here to close the DB.
1055          *
1056          * On TF Session close it is assumed that the session has already
1057          * cleaned up all its resources, individually, while
1058          * destroying its flows.
1059          *
1060          * To assist in the 'cleanup checking' the DB is checked for any
1061          * remaining elements and logged if found to be the case.
1062          *
1063          * Any such elements will need to be 'cleared' ahead of
1064          * returning the resources to the HCAPI RM.
1065          *
1066          * RM will signal FW to flush the DB resources. FW will
1067          * perform the invalidation. TF Session close will return the
1068          * previous allocated elements to the RM and then close the
1069          * HCAPI RM registration. That then saves several 'free' msgs
1070          * from being required.
1071          */
1072
1073         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1074
1075         /* Check for residuals that the client didn't clean up */
1076         rc = tf_rm_check_residuals(rm_db,
1077                                    &resv_size,
1078                                    &resv,
1079                                    &residuals_found);
1080         if (rc)
1081                 return rc;
1082
1083         /* Invalidate any residuals followed by a DB traversal for
1084          * pool cleanup.
1085          */
1086         if (residuals_found) {
1087                 rc = tf_msg_session_resc_flush(tfp,
1088                                                parms->dir,
1089                                                resv_size,
1090                                                resv);
1091                 tfp_free((void *)resv);
1092                 /* On failure we still have to cleanup so we can only
1093                  * log that FW failed.
1094                  */
1095                 if (rc)
1096                         TFP_DRV_LOG(ERR,
1097                                     "%s: Internal Flush error, module:%s\n",
1098                                     tf_dir_2_str(parms->dir),
1099                                     tf_module_2_str(rm_db->module));
1100         }
1101
1102         /* No need to check for configuration type, even if we do not
1103          * have a BA pool we just delete on a null ptr, no harm
1104          */
1105         for (i = 0; i < rm_db->num_entries; i++)
1106                 tfp_free((void *)rm_db->db[i].pool);
1107
1108         tfp_free((void *)parms->rm_db);
1109
1110         return rc;
1111 }
1112 /**
1113  * Get the bit allocator pool associated with the subtype and the db
1114  *
1115  * [in] rm_db
1116  *   Pointer to the DB
1117  *
1118  * [in] subtype
1119  *   Module subtype used to index into the module specific database.
1120  *   An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a
1121  *   module subtype of TF_MODULE_TYPE_TABLE.
1122  *
1123  * [in/out] pool
1124  *   Pointer to the bit allocator pool used
1125  *
1126  * [in/out] new_subtype
1127  *   Pointer to the subtype of the actual pool used
1128  * Returns:
1129  *     0          - Success
1130  *   - ENOTSUP    - Operation not supported
1131  */
1132 static int
1133 tf_rm_get_pool(struct tf_rm_new_db *rm_db,
1134                uint16_t subtype,
1135                struct bitalloc **pool,
1136                uint16_t *new_subtype)
1137 {
1138         int rc = 0;
1139         uint16_t tmp_subtype = subtype;
1140
1141         /* If we are a child, get the parent table index */
1142         if (rm_db->db[subtype].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
1143                 tmp_subtype = rm_db->db[subtype].parent_subtype;
1144
1145         *pool = rm_db->db[tmp_subtype].pool;
1146
1147         /* Bail out if the pool is not valid, should never happen */
1148         if (rm_db->db[tmp_subtype].pool == NULL) {
1149                 rc = -ENOTSUP;
1150                 TFP_DRV_LOG(ERR,
1151                             "%s: Invalid pool for this type:%d, rc:%s\n",
1152                             tf_dir_2_str(rm_db->dir),
1153                             tmp_subtype,
1154                             strerror(-rc));
1155                 return rc;
1156         }
1157         *new_subtype = tmp_subtype;
1158         return rc;
1159 }
1160
1161 int
1162 tf_rm_allocate(struct tf_rm_allocate_parms *parms)
1163 {
1164         int rc;
1165         int id;
1166         uint32_t index;
1167         struct tf_rm_new_db *rm_db;
1168         enum tf_rm_elem_cfg_type cfg_type;
1169         struct bitalloc *pool;
1170         uint16_t subtype;
1171
1172         TF_CHECK_PARMS2(parms, parms->rm_db);
1173
1174         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1175         TF_CHECK_PARMS1(rm_db->db);
1176
1177         cfg_type = rm_db->db[parms->subtype].cfg_type;
1178
1179         /* Bail out if not controlled by RM */
1180         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
1181             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
1182             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
1183                 return -ENOTSUP;
1184
1185         rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
1186         if (rc)
1187                 return rc;
1188         /*
1189          * priority  0: allocate from top of the tcam i.e. high
1190          * priority !0: allocate index from bottom i.e lowest
1191          */
1192         if (parms->priority)
1193                 id = ba_alloc_reverse(pool);
1194         else
1195                 id = ba_alloc(pool);
1196         if (id == BA_FAIL) {
1197                 rc = -ENOMEM;
1198                 TFP_DRV_LOG(ERR,
1199                             "%s: Allocation failed, rc:%s\n",
1200                             tf_dir_2_str(rm_db->dir),
1201                             strerror(-rc));
1202                 return rc;
1203         }
1204
1205         /* Adjust for any non zero start value */
1206         rc = tf_rm_adjust_index(rm_db->db,
1207                                 TF_RM_ADJUST_ADD_BASE,
1208                                 subtype,
1209                                 id,
1210                                 &index);
1211         if (rc) {
1212                 TFP_DRV_LOG(ERR,
1213                             "%s: Alloc adjust of base index failed, rc:%s\n",
1214                             tf_dir_2_str(rm_db->dir),
1215                             strerror(-rc));
1216                 return -EINVAL;
1217         }
1218
1219         *parms->index = index;
1220         if (parms->base_index)
1221                 *parms->base_index = id;
1222
1223         return rc;
1224 }
1225
1226 int
1227 tf_rm_free(struct tf_rm_free_parms *parms)
1228 {
1229         int rc;
1230         uint32_t adj_index;
1231         struct tf_rm_new_db *rm_db;
1232         enum tf_rm_elem_cfg_type cfg_type;
1233         struct bitalloc *pool;
1234         uint16_t subtype;
1235
1236         TF_CHECK_PARMS2(parms, parms->rm_db);
1237         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1238         TF_CHECK_PARMS1(rm_db->db);
1239
1240         cfg_type = rm_db->db[parms->subtype].cfg_type;
1241
1242         /* Bail out if not controlled by RM */
1243         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
1244             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
1245             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
1246                 return -ENOTSUP;
1247
1248         rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
1249         if (rc)
1250                 return rc;
1251
1252         /* Adjust for any non zero start value */
1253         rc = tf_rm_adjust_index(rm_db->db,
1254                                 TF_RM_ADJUST_RM_BASE,
1255                                 subtype,
1256                                 parms->index,
1257                                 &adj_index);
1258         if (rc)
1259                 return rc;
1260
1261         rc = ba_free(pool, adj_index);
1262         /* No logging direction matters and that is not available here */
1263         if (rc)
1264                 return rc;
1265
1266         return rc;
1267 }
1268
1269 int
1270 tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)
1271 {
1272         int rc;
1273         uint32_t adj_index;
1274         struct tf_rm_new_db *rm_db;
1275         enum tf_rm_elem_cfg_type cfg_type;
1276         struct bitalloc *pool;
1277         uint16_t subtype;
1278
1279         TF_CHECK_PARMS2(parms, parms->rm_db);
1280         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1281         TF_CHECK_PARMS1(rm_db->db);
1282
1283         cfg_type = rm_db->db[parms->subtype].cfg_type;
1284
1285         /* Bail out if not controlled by RM */
1286         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
1287             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
1288             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
1289                 return -ENOTSUP;
1290
1291         rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
1292         if (rc)
1293                 return rc;
1294
1295         /* Adjust for any non zero start value */
1296         rc = tf_rm_adjust_index(rm_db->db,
1297                                 TF_RM_ADJUST_RM_BASE,
1298                                 subtype,
1299                                 parms->index,
1300                                 &adj_index);
1301         if (rc)
1302                 return rc;
1303
1304         if (parms->base_index)
1305                 *parms->base_index = adj_index;
1306         *parms->allocated = ba_inuse(pool, adj_index);
1307
1308         return rc;
1309 }
1310
1311 int
1312 tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
1313 {
1314         struct tf_rm_new_db *rm_db;
1315         enum tf_rm_elem_cfg_type cfg_type;
1316
1317         TF_CHECK_PARMS2(parms, parms->rm_db);
1318         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1319         TF_CHECK_PARMS1(rm_db->db);
1320
1321         cfg_type = rm_db->db[parms->subtype].cfg_type;
1322
1323         /* Bail out if not controlled by HCAPI */
1324         if (cfg_type == TF_RM_ELEM_CFG_NULL)
1325                 return -ENOTSUP;
1326
1327         memcpy(parms->info,
1328                &rm_db->db[parms->subtype].alloc,
1329                sizeof(struct tf_rm_alloc_info));
1330
1331         return 0;
1332 }
1333
1334 int
1335 tf_rm_get_all_info(struct tf_rm_get_alloc_info_parms *parms, int size)
1336 {
1337         struct tf_rm_new_db *rm_db;
1338         enum tf_rm_elem_cfg_type cfg_type;
1339         struct tf_rm_alloc_info *info = parms->info;
1340         int i;
1341
1342         TF_CHECK_PARMS1(parms);
1343
1344         /* No rm info available for this module type
1345          */
1346         if (!parms->rm_db)
1347                 return -ENOMEM;
1348
1349         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1350         TF_CHECK_PARMS1(rm_db->db);
1351
1352         for (i = 0; i < size; i++) {
1353                 cfg_type = rm_db->db[i].cfg_type;
1354
1355                 /* Bail out if not controlled by HCAPI */
1356                 if (cfg_type == TF_RM_ELEM_CFG_NULL) {
1357                         info++;
1358                         continue;
1359                 }
1360
1361                 memcpy(info,
1362                        &rm_db->db[i].alloc,
1363                        sizeof(struct tf_rm_alloc_info));
1364                 info++;
1365         }
1366
1367         return 0;
1368 }
1369
1370 int
1371 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
1372 {
1373         struct tf_rm_new_db *rm_db;
1374         enum tf_rm_elem_cfg_type cfg_type;
1375
1376         TF_CHECK_PARMS2(parms, parms->rm_db);
1377         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1378         TF_CHECK_PARMS1(rm_db->db);
1379
1380         cfg_type = rm_db->db[parms->subtype].cfg_type;
1381
1382         /* Bail out if not controlled by HCAPI */
1383         if (cfg_type == TF_RM_ELEM_CFG_NULL)
1384                 return -ENOTSUP;
1385
1386         *parms->hcapi_type = rm_db->db[parms->subtype].hcapi_type;
1387
1388         return 0;
1389 }
1390 int
1391 tf_rm_get_slices(struct tf_rm_get_slices_parms *parms)
1392 {
1393         struct tf_rm_new_db *rm_db;
1394         enum tf_rm_elem_cfg_type cfg_type;
1395
1396         TF_CHECK_PARMS2(parms, parms->rm_db);
1397         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1398         TF_CHECK_PARMS1(rm_db->db);
1399
1400         cfg_type = rm_db->db[parms->subtype].cfg_type;
1401
1402         /* Bail out if not controlled by HCAPI */
1403         if (cfg_type == TF_RM_ELEM_CFG_NULL)
1404                 return -ENOTSUP;
1405
1406         *parms->slices = rm_db->db[parms->subtype].slices;
1407
1408         return 0;
1409 }
1410
1411 int
1412 tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
1413 {
1414         int rc = 0;
1415         struct tf_rm_new_db *rm_db;
1416         enum tf_rm_elem_cfg_type cfg_type;
1417
1418         TF_CHECK_PARMS2(parms, parms->rm_db);
1419         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1420         TF_CHECK_PARMS1(rm_db->db);
1421
1422         cfg_type = rm_db->db[parms->subtype].cfg_type;
1423
1424         /* Bail out if not a BA pool */
1425         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
1426             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
1427             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
1428                 return -ENOTSUP;
1429
1430         /* Bail silently (no logging), if the pool is not valid there
1431          * was no elements allocated for it.
1432          */
1433         if (rm_db->db[parms->subtype].pool == NULL) {
1434                 *parms->count = 0;
1435                 return 0;
1436         }
1437
1438         *parms->count = ba_inuse_count(rm_db->db[parms->subtype].pool);
1439
1440         return rc;
1441 }
1442 /* Only used for table bulk get at this time
1443  */
1444 int
1445 tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms)
1446 {
1447         struct tf_rm_new_db *rm_db;
1448         enum tf_rm_elem_cfg_type cfg_type;
1449         uint32_t base_index;
1450         uint32_t stride;
1451         int rc = 0;
1452         struct bitalloc *pool;
1453         uint16_t subtype;
1454
1455         TF_CHECK_PARMS2(parms, parms->rm_db);
1456         rm_db = (struct tf_rm_new_db *)parms->rm_db;
1457         TF_CHECK_PARMS1(rm_db->db);
1458
1459         cfg_type = rm_db->db[parms->subtype].cfg_type;
1460
1461         /* Bail out if not a BA pool */
1462         if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA &&
1463             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT &&
1464             cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD)
1465                 return -ENOTSUP;
1466
1467         rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype);
1468         if (rc)
1469                 return rc;
1470
1471         base_index = rm_db->db[subtype].alloc.entry.start;
1472         stride = rm_db->db[subtype].alloc.entry.stride;
1473
1474         if (parms->starting_index < base_index ||
1475             parms->starting_index + parms->num_entries > base_index + stride)
1476                 return -EINVAL;
1477
1478         return rc;
1479 }