1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 Broadcom
8 #include <rte_common.h>
10 #include <cfa_resource_types.h>
12 #include "tf_rm_new.h"
13 #include "tf_common.h"
15 #include "tf_session.h"
16 #include "tf_device.h"
21 * Generic RM Element data type that an RM DB is build upon.
23 struct tf_rm_element {
25 * RM Element configuration type. If Private then the
26 * hcapi_type can be ignored. If Null then the element is not
27 * valid for the device.
29 enum tf_rm_elem_cfg_type cfg_type;
32 * HCAPI RM Type for the element.
37 * HCAPI RM allocated range information for the element.
39 struct tf_rm_alloc_info alloc;
42 * Bit allocator pool for the element. Pool size is controlled
43 * by the struct tf_session_resources at time of session creation.
44 * Null indicates that the element is not used for the device.
46 struct bitalloc *pool;
54 * Number of elements in the DB
59 * Direction this DB controls.
64 * The DB consists of an array of elements
66 struct tf_rm_element *db;
70 * Adjust an index according to the allocation information.
72 * All resources are controlled in a 0 based pool. Some resources, by
73 * design, are not 0 based, i.e. Full Action Records (SRAM) thus they
74 * need to be adjusted before they are handed out.
77 * Pointer to the DB configuration
80 * Pointer to the allocation values associated with the module
83 * Number of DB configuration elements
86 * Number of HCAPI entries with a reservation value greater than 0
90 * - EOPNOTSUPP - Operation not supported
93 tf_rm_count_hcapi_reservations(struct tf_rm_element_cfg *cfg,
94 uint16_t *reservations,
96 uint16_t *valid_count)
101 for (i = 0; i < count; i++) {
102 if (cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI &&
111 * Resource Manager Adjust of base index definitions.
113 enum tf_rm_adjust_type {
114 TF_RM_ADJUST_ADD_BASE, /**< Adds base to the index */
115 TF_RM_ADJUST_RM_BASE /**< Removes base from the index */
119 * Adjust an index according to the allocation information.
121 * All resources are controlled in a 0 based pool. Some resources, by
122 * design, are not 0 based, i.e. Full Action Records (SRAM) thus they
123 * need to be adjusted before they are handed out.
126 * Pointer to the db, used for the lookup
132 * DB index for the element type
142 * - EOPNOTSUPP - Operation not supported
145 tf_rm_adjust_index(struct tf_rm_element *db,
146 enum tf_rm_adjust_type action,
154 base_index = db[db_index].alloc.entry.start;
157 case TF_RM_ADJUST_RM_BASE:
158 *adj_index = index - base_index;
160 case TF_RM_ADJUST_ADD_BASE:
161 *adj_index = index + base_index;
171 tf_rm_create_db(struct tf *tfp,
172 struct tf_rm_create_db_parms *parms)
177 struct tf_session *tfs;
178 struct tf_dev_info *dev;
180 struct tfp_calloc_parms cparms;
181 struct tf_rm_resc_req_entry *query;
182 enum tf_rm_resc_resv_strategy resv_strategy;
183 struct tf_rm_resc_req_entry *req;
184 struct tf_rm_resc_entry *resv;
185 struct tf_rm_new_db *rm_db;
186 struct tf_rm_element *db;
188 uint16_t hcapi_items;
190 TF_CHECK_PARMS2(tfp, parms);
192 /* Retrieve the session information */
193 rc = tf_session_get_session(tfp, &tfs);
197 /* Retrieve device information */
198 rc = tf_session_get_device(tfs, &dev);
202 /* Need device max number of elements for the RM QCAPS */
203 rc = dev->ops->tf_dev_get_max_types(tfp, &max_types);
207 cparms.nitems = max_types;
208 cparms.size = sizeof(struct tf_rm_resc_req_entry);
209 cparms.alignment = 0;
210 rc = tfp_calloc(&cparms);
214 query = (struct tf_rm_resc_req_entry *)cparms.mem_va;
216 /* Get Firmware Capabilities */
217 rc = tf_msg_session_resc_qcaps(tfp,
225 /* Process capabilities against DB requirements. However, as a
226 * DB can hold elements that are not HCAPI we can reduce the
227 * req msg content by removing those out of the request yet
228 * the DB holds them all as to give a fast lookup. We can also
229 * remove entries where there are no request for elements.
231 tf_rm_count_hcapi_reservations(parms->cfg,
236 /* Alloc request, alignment already set */
237 cparms.nitems = (size_t)hcapi_items;
238 cparms.size = sizeof(struct tf_rm_resc_req_entry);
239 rc = tfp_calloc(&cparms);
242 req = (struct tf_rm_resc_req_entry *)cparms.mem_va;
244 /* Alloc reservation, alignment and nitems already set */
245 cparms.size = sizeof(struct tf_rm_resc_entry);
246 rc = tfp_calloc(&cparms);
249 resv = (struct tf_rm_resc_entry *)cparms.mem_va;
251 /* Build the request */
252 for (i = 0, j = 0; i < parms->num_elements; i++) {
253 /* Skip any non HCAPI cfg elements */
254 if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI) {
255 /* Only perform reservation for entries that
258 if (parms->alloc_cnt[i] == 0)
261 /* Verify that we can get the full amount
262 * allocated per the qcaps availability.
264 if (parms->alloc_cnt[i] <=
265 query[parms->cfg[i].hcapi_type].max) {
266 req[j].type = parms->cfg[i].hcapi_type;
267 req[j].min = parms->alloc_cnt[i];
268 req[j].max = parms->alloc_cnt[i];
272 "%s: Resource failure, type:%d\n",
273 tf_dir_2_str(parms->dir),
274 parms->cfg[i].hcapi_type);
276 "req:%d, avail:%d\n",
278 query[parms->cfg[i].hcapi_type].max);
284 rc = tf_msg_session_resc_alloc(tfp,
292 /* Build the RM DB per the request */
294 cparms.size = sizeof(struct tf_rm_new_db);
295 rc = tfp_calloc(&cparms);
298 rm_db = (void *)cparms.mem_va;
300 /* Build the DB within RM DB */
301 cparms.nitems = parms->num_elements;
302 cparms.size = sizeof(struct tf_rm_element);
303 rc = tfp_calloc(&cparms);
306 rm_db->db = (struct tf_rm_element *)cparms.mem_va;
309 for (i = 0, j = 0; i < parms->num_elements; i++) {
310 db[i].cfg_type = parms->cfg[i].cfg_type;
311 db[i].hcapi_type = parms->cfg[i].hcapi_type;
313 /* Skip any non HCAPI types as we didn't include them
314 * in the reservation request.
316 if (parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI)
319 /* If the element didn't request an allocation no need
320 * to create a pool nor verify if we got a reservation.
322 if (parms->alloc_cnt[i] == 0)
325 /* If the element had requested an allocation and that
326 * allocation was a success (full amount) then
329 if (parms->alloc_cnt[i] == resv[j].stride) {
330 db[i].alloc.entry.start = resv[j].start;
331 db[i].alloc.entry.stride = resv[j].stride;
334 pool_size = (BITALLOC_SIZEOF(resv[j].stride) /
335 sizeof(struct bitalloc));
336 /* Alloc request, alignment already set */
337 cparms.nitems = pool_size;
338 cparms.size = sizeof(struct bitalloc);
339 rc = tfp_calloc(&cparms);
342 "%s: Pool alloc failed, type:%d\n",
343 tf_dir_2_str(parms->dir),
347 db[i].pool = (struct bitalloc *)cparms.mem_va;
349 rc = ba_init(db[i].pool, resv[j].stride);
352 "%s: Pool init failed, type:%d\n",
353 tf_dir_2_str(parms->dir),
359 /* Bail out as we want what we requested for
360 * all elements, not any less.
363 "%s: Alloc failed, type:%d\n",
364 tf_dir_2_str(parms->dir),
367 "req:%d, alloc:%d\n",
374 rm_db->num_entries = i;
375 rm_db->dir = parms->dir;
376 *parms->rm_db = (void *)rm_db;
378 tfp_free((void *)req);
379 tfp_free((void *)resv);
384 tfp_free((void *)req);
385 tfp_free((void *)resv);
386 tfp_free((void *)db->pool);
387 tfp_free((void *)db);
388 tfp_free((void *)rm_db);
395 tf_rm_free_db(struct tf *tfp __rte_unused,
396 struct tf_rm_free_db_parms *parms)
400 struct tf_rm_new_db *rm_db;
402 TF_CHECK_PARMS1(parms);
404 /* Traverse the DB and clear each pool.
406 * Firmware is not cleared. It will be cleared on close only.
408 rm_db = (struct tf_rm_new_db *)parms->rm_db;
409 for (i = 0; i < rm_db->num_entries; i++)
410 tfp_free((void *)rm_db->db[i].pool);
412 tfp_free((void *)parms->rm_db);
418 tf_rm_allocate(struct tf_rm_allocate_parms *parms)
423 struct tf_rm_new_db *rm_db;
424 enum tf_rm_elem_cfg_type cfg_type;
426 TF_CHECK_PARMS2(parms, parms->rm_db);
428 rm_db = (struct tf_rm_new_db *)parms->rm_db;
429 cfg_type = rm_db->db[parms->db_index].cfg_type;
431 /* Bail out if not controlled by RM */
432 if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
433 cfg_type != TF_RM_ELEM_CFG_PRIVATE)
436 /* Bail out if the pool is not valid, should never happen */
437 if (rm_db->db[parms->db_index].pool == NULL) {
440 "%s: Invalid pool for this type:%d, rc:%s\n",
441 tf_dir_2_str(rm_db->dir),
447 id = ba_alloc(rm_db->db[parms->db_index].pool);
450 "%s: Allocation failed, rc:%s\n",
451 tf_dir_2_str(rm_db->dir),
456 /* Adjust for any non zero start value */
457 rc = tf_rm_adjust_index(rm_db->db,
458 TF_RM_ADJUST_ADD_BASE,
464 "%s: Alloc adjust of base index failed, rc:%s\n",
465 tf_dir_2_str(rm_db->dir),
470 *parms->index = index;
476 tf_rm_free(struct tf_rm_free_parms *parms)
480 struct tf_rm_new_db *rm_db;
481 enum tf_rm_elem_cfg_type cfg_type;
483 TF_CHECK_PARMS2(parms, parms->rm_db);
485 rm_db = (struct tf_rm_new_db *)parms->rm_db;
486 cfg_type = rm_db->db[parms->db_index].cfg_type;
488 /* Bail out if not controlled by RM */
489 if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
490 cfg_type != TF_RM_ELEM_CFG_PRIVATE)
493 /* Bail out if the pool is not valid, should never happen */
494 if (rm_db->db[parms->db_index].pool == NULL) {
497 "%s: Invalid pool for this type:%d, rc:%s\n",
498 tf_dir_2_str(rm_db->dir),
504 /* Adjust for any non zero start value */
505 rc = tf_rm_adjust_index(rm_db->db,
506 TF_RM_ADJUST_RM_BASE,
513 rc = ba_free(rm_db->db[parms->db_index].pool, adj_index);
514 /* No logging direction matters and that is not available here */
522 tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)
526 struct tf_rm_new_db *rm_db;
527 enum tf_rm_elem_cfg_type cfg_type;
529 TF_CHECK_PARMS2(parms, parms->rm_db);
531 rm_db = (struct tf_rm_new_db *)parms->rm_db;
532 cfg_type = rm_db->db[parms->db_index].cfg_type;
534 /* Bail out if not controlled by RM */
535 if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
536 cfg_type != TF_RM_ELEM_CFG_PRIVATE)
539 /* Bail out if the pool is not valid, should never happen */
540 if (rm_db->db[parms->db_index].pool == NULL) {
543 "%s: Invalid pool for this type:%d, rc:%s\n",
544 tf_dir_2_str(rm_db->dir),
550 /* Adjust for any non zero start value */
551 rc = tf_rm_adjust_index(rm_db->db,
552 TF_RM_ADJUST_RM_BASE,
559 *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool,
566 tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
569 struct tf_rm_new_db *rm_db;
570 enum tf_rm_elem_cfg_type cfg_type;
572 TF_CHECK_PARMS2(parms, parms->rm_db);
574 rm_db = (struct tf_rm_new_db *)parms->rm_db;
575 cfg_type = rm_db->db[parms->db_index].cfg_type;
577 /* Bail out if not controlled by RM */
578 if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
579 cfg_type != TF_RM_ELEM_CFG_PRIVATE)
582 parms->info = &rm_db->db[parms->db_index].alloc;
588 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
591 struct tf_rm_new_db *rm_db;
592 enum tf_rm_elem_cfg_type cfg_type;
594 TF_CHECK_PARMS2(parms, parms->rm_db);
596 rm_db = (struct tf_rm_new_db *)parms->rm_db;
597 cfg_type = rm_db->db[parms->db_index].cfg_type;
599 /* Bail out if not controlled by RM */
600 if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
601 cfg_type != TF_RM_ELEM_CFG_PRIVATE)
604 *parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type;