X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fbnxt%2Ftf_core%2Ftf_rm.c;h=dd537aaececc1950ab9bad3f2d9ca8e3fd620a9d;hb=f1f6ebc0eaf68a825c6175f5e6a436f7d91660c3;hp=30313e2eac658ccaf99ea05f8decac01fe0cfbc6;hpb=d0d22f1f062d6d08839601397e74d2aeb6b5a72c;p=dpdk.git diff --git a/drivers/net/bnxt/tf_core/tf_rm.c b/drivers/net/bnxt/tf_core/tf_rm.c index 30313e2eac..dd537aaece 100644 --- a/drivers/net/bnxt/tf_core/tf_rm.c +++ b/drivers/net/bnxt/tf_core/tf_rm.c @@ -1,11 +1,12 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2019-2020 Broadcom + * Copyright(c) 2019-2021 Broadcom * All rights reserved. */ #include #include +#include #include @@ -36,15 +37,29 @@ struct tf_rm_element { */ uint16_t hcapi_type; + /** + * Resource slices. How many slices will fit in the + * resource pool chunk size. + */ + uint8_t slices; + /** * HCAPI RM allocated range information for the element. */ struct tf_rm_alloc_info alloc; + /** + * If cfg_type == HCAPI_BA_CHILD, this field indicates + * the parent module subtype for look up into the parent pool. + * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a + * module subtype of TF_MODULE_TYPE_TABLE. + */ + uint16_t parent_subtype; + /** * Bit allocator pool for the element. Pool size is controlled * by the struct tf_session_resources at time of session creation. - * Null indicates that the element is not used for the device. + * Null indicates that the pool is not used for the element. */ struct bitalloc *pool; }; @@ -66,7 +81,7 @@ struct tf_rm_new_db { /** * Module type, used for logging purposes. */ - enum tf_device_module_type type; + enum tf_module_type module; /** * The DB consists of an array of elements @@ -99,7 +114,7 @@ struct tf_rm_new_db { */ static void tf_rm_count_hcapi_reservations(enum tf_dir dir, - enum tf_device_module_type type, + enum tf_module_type module, struct tf_rm_element_cfg *cfg, uint16_t *reservations, uint16_t count, @@ -109,8 +124,7 @@ tf_rm_count_hcapi_reservations(enum tf_dir dir, uint16_t cnt = 0; for (i = 0; i < count; i++) { - if ((cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI || - cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) && + if (cfg[i].cfg_type != TF_RM_ELEM_CFG_NULL && reservations[i] > 0) cnt++; @@ -119,14 +133,14 @@ tf_rm_count_hcapi_reservations(enum tf_dir dir, * split configuration array thus it would fail for * this type of check. */ - if (type != TF_DEVICE_MODULE_TYPE_EM && + if (module != TF_MODULE_TYPE_EM && cfg[i].cfg_type == TF_RM_ELEM_CFG_NULL && reservations[i] > 0) { TFP_DRV_LOG(ERR, "%s, %s, %s allocation of %d not supported\n", - tf_device_module_type_2_str(type), + tf_module_2_str(module), tf_dir_2_str(dir), - tf_device_module_type_subtype_2_str(type, i), + tf_module_subtype_2_str(module, i), reservations[i]); } } @@ -155,8 +169,10 @@ enum tf_rm_adjust_type { * [in] action * Adjust action * - * [in] db_index - * DB index for the element type + * [in] subtype + * TF module subtype used as an index into the database. + * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a + * module subtype of TF_MODULE_TYPE_TABLE. * * [in] index * Index to convert @@ -171,14 +187,14 @@ enum tf_rm_adjust_type { static int tf_rm_adjust_index(struct tf_rm_element *db, enum tf_rm_adjust_type action, - uint32_t db_index, + uint32_t subtype, uint32_t index, uint32_t *adj_index) { int rc = 0; uint32_t base_index; - base_index = db[db_index].alloc.entry.start; + base_index = db[subtype].alloc.entry.start; switch (action) { case TF_RM_ADJUST_RM_BASE: @@ -200,7 +216,7 @@ tf_rm_adjust_index(struct tf_rm_element *db, * [in] dir * Receive or transmit direction * - * [in] type + * [in] module * Type of Device Module * * [in] count @@ -211,9 +227,10 @@ tf_rm_adjust_index(struct tf_rm_element *db, * the DB in which this function is used. Each entry holds residual * value for that entry. */ +#if (TF_RM_DEBUG == 1) static void tf_rm_log_residuals(enum tf_dir dir, - enum tf_device_module_type type, + enum tf_module_type module, uint16_t count, uint16_t *residuals) { @@ -224,14 +241,14 @@ tf_rm_log_residuals(enum tf_dir dir, */ for (i = 0; i < count; i++) { if (residuals[i] != 0) - TFP_DRV_LOG(ERR, + TFP_DRV_LOG(INFO, "%s, %s was not cleaned up, %d outstanding\n", tf_dir_2_str(dir), - tf_device_module_type_subtype_2_str(type, i), + tf_module_subtype_2_str(module, i), residuals[i]); } } - +#endif /* TF_RM_DEBUG == 1 */ /** * Performs a check of the passed in DB for any lingering elements. If * a resource type was found to not have been cleaned up by the caller @@ -294,7 +311,7 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db, iparms.rm_db = rm_db; iparms.count = &count; for (i = 0, found = 0; i < rm_db->num_entries; i++) { - iparms.db_index = i; + iparms.subtype = i; rc = tf_rm_get_inuse_count(&iparms); /* Not a device supported entry, just skip */ if (rc == -ENOTSUP) @@ -328,13 +345,13 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db, for (i = 0, f = 0; i < rm_db->num_entries; i++) { if (residuals[i] == 0) continue; - aparms.db_index = i; + aparms.subtype = i; aparms.info = &info; rc = tf_rm_get_info(&aparms); if (rc) goto cleanup_all; - hparms.db_index = i; + hparms.subtype = i; rc = tf_rm_get_hcapi_type(&hparms); if (rc) goto cleanup_all; @@ -347,11 +364,12 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db, *resv_size = found; } +#if (TF_RM_DEBUG == 1) tf_rm_log_residuals(rm_db->dir, - rm_db->type, + rm_db->module, rm_db->num_entries, residuals); - +#endif tfp_free((void *)residuals); *resv = local_resv; @@ -366,16 +384,132 @@ tf_rm_check_residuals(struct tf_rm_new_db *rm_db, return rc; } +/** + * Some resources do not have a 1:1 mapping between the Truflow type and the cfa + * resource type (HCAPI RM). These resources have multiple Truflow types which + * map to a single HCAPI RM type. In order to support this, one Truflow type + * sharing the HCAPI resources is designated the parent. All other Truflow + * types associated with that HCAPI RM type are designated the children. + * + * This function updates the resource counts of any HCAPI_BA_PARENT with the + * counts of the HCAPI_BA_CHILDREN. These are read from the alloc_cnt and + * written back to the req_cnt. + * + * [in] cfg + * Pointer to an array of module specific Truflow type indexed RM cfg items + * + * [in] alloc_cnt + * Pointer to the tf_open_session() configured array of module specific + * Truflow type indexed requested counts. + * + * [in/out] req_cnt + * Pointer to the location to put the updated resource counts. + * + * Returns: + * 0 - Success + * - - Failure if negative + */ +static int +tf_rm_update_parent_reservations(struct tf *tfp, + struct tf_dev_info *dev, + struct tf_rm_element_cfg *cfg, + uint16_t *alloc_cnt, + uint16_t num_elements, + uint16_t *req_cnt, + bool shared_session) +{ + int parent, child; + const char *type_str; + + /* Search through all the elements */ + for (parent = 0; parent < num_elements; parent++) { + uint16_t combined_cnt = 0; + + /* If I am a parent */ + if (cfg[parent].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { + uint8_t p_slices = 1; + + /* Shared session doesn't support slices */ + if (!shared_session) + p_slices = cfg[parent].slices; + + RTE_ASSERT(p_slices); + + combined_cnt = alloc_cnt[parent] / p_slices; + + if (alloc_cnt[parent] % p_slices) + combined_cnt++; + + if (alloc_cnt[parent]) { + dev->ops->tf_dev_get_resource_str(tfp, + cfg[parent].hcapi_type, + &type_str); +#if (TF_RM_DEBUG == 1) + printf("%s:%s cnt(%d) slices(%d)\n", + type_str, tf_tbl_type_2_str(parent), + alloc_cnt[parent], p_slices); +#endif /* (TF_RM_DEBUG == 1) */ + } + + /* Search again through all the elements */ + for (child = 0; child < num_elements; child++) { + /* If this is one of my children */ + if (cfg[child].cfg_type == + TF_RM_ELEM_CFG_HCAPI_BA_CHILD && + cfg[child].parent_subtype == parent && + alloc_cnt[child]) { + uint8_t c_slices = 1; + uint16_t cnt = 0; + + if (!shared_session) + c_slices = cfg[child].slices; + + RTE_ASSERT(c_slices); + + dev->ops->tf_dev_get_resource_str(tfp, + cfg[child].hcapi_type, + &type_str); +#if (TF_RM_DEBUG == 1) + printf("%s:%s cnt(%d) slices(%d)\n", + type_str, + tf_tbl_type_2_str(child), + alloc_cnt[child], + c_slices); +#endif /* (TF_RM_DEBUG == 1) */ + /* Increment the parents combined count + * with each child's count adjusted for + * number of slices per RM alloc item. + */ + cnt = alloc_cnt[child] / c_slices; + + if (alloc_cnt[child] % c_slices) + cnt++; + + combined_cnt += cnt; + /* Clear the requested child count */ + req_cnt[child] = 0; + } + } + /* Save the parent count to be requested */ + req_cnt[parent] = combined_cnt; +#if (TF_RM_DEBUG == 1) + printf("%s calculated total:%d\n\n", + type_str, req_cnt[parent]); +#endif /* (TF_RM_DEBUG == 1) */ + } + } + return 0; +} + int tf_rm_create_db(struct tf *tfp, struct tf_rm_create_db_parms *parms) { int rc; - int i; - int j; struct tf_session *tfs; struct tf_dev_info *dev; - uint16_t max_types; + int i, j; + uint16_t max_types, hcapi_items, *req_cnt; struct tfp_calloc_parms cparms; struct tf_rm_resc_req_entry *query; enum tf_rm_resc_resv_strategy resv_strategy; @@ -384,12 +518,12 @@ tf_rm_create_db(struct tf *tfp, struct tf_rm_new_db *rm_db; struct tf_rm_element *db; uint32_t pool_size; - uint16_t hcapi_items; + bool shared_session = 0; TF_CHECK_PARMS2(tfp, parms); /* Retrieve the session information */ - rc = tf_session_get_session(tfp, &tfs); + rc = tf_session_get_session_internal(tfp, &tfs); if (rc) return rc; @@ -400,9 +534,8 @@ tf_rm_create_db(struct tf *tfp, /* Need device max number of elements for the RM QCAPS */ rc = dev->ops->tf_dev_get_max_types(tfp, &max_types); - if (rc) - return rc; + /* Allocate memory for RM QCAPS request */ cparms.nitems = max_types; cparms.size = sizeof(struct tf_rm_resc_req_entry); cparms.alignment = 0; @@ -414,6 +547,7 @@ tf_rm_create_db(struct tf *tfp, /* Get Firmware Capabilities */ rc = tf_msg_session_resc_qcaps(tfp, + dev, parms->dir, max_types, query, @@ -421,6 +555,31 @@ tf_rm_create_db(struct tf *tfp, if (rc) return rc; + /* Copy requested counts (alloc_cnt) from tf_open_session() to local + * copy (req_cnt) so that it can be updated if required. + */ + + cparms.nitems = parms->num_elements; + cparms.size = sizeof(uint16_t); + rc = tfp_calloc(&cparms); + if (rc) + return rc; + + req_cnt = (uint16_t *)cparms.mem_va; + + tfp_memcpy(req_cnt, parms->alloc_cnt, + parms->num_elements * sizeof(uint16_t)); + + shared_session = tf_session_is_shared_session(tfs); + + /* Update the req_cnt based upon the element configuration + */ + tf_rm_update_parent_reservations(tfp, dev, parms->cfg, + parms->alloc_cnt, + parms->num_elements, + req_cnt, + shared_session); + /* Process capabilities against DB requirements. However, as a * DB can hold elements that are not HCAPI we can reduce the * req msg content by removing those out of the request yet @@ -428,22 +587,19 @@ tf_rm_create_db(struct tf *tfp, * remove entries where there are no request for elements. */ tf_rm_count_hcapi_reservations(parms->dir, - parms->type, + parms->module, parms->cfg, - parms->alloc_cnt, + req_cnt, parms->num_elements, &hcapi_items); - /* Handle the case where a DB create request really ends up - * being empty. Unsupported (if not rare) case but possible - * that no resources are necessary for a 'direction'. - */ if (hcapi_items == 0) { - TFP_DRV_LOG(ERR, - "%s: DB create request for Zero elements, DB Type:%s\n", +#if (TF_RM_DEBUG == 1) + TFP_DRV_LOG(INFO, + "%s: module: %s Empty RM DB create request\n", tf_dir_2_str(parms->dir), - tf_device_module_type_2_str(parms->type)); - + tf_module_2_str(parms->module)); +#endif parms->rm_db = NULL; return -ENOMEM; } @@ -465,39 +621,47 @@ tf_rm_create_db(struct tf *tfp, /* Build the request */ for (i = 0, j = 0; i < parms->num_elements; i++) { - /* Skip any non HCAPI cfg elements */ - if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI || - parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) { - /* Only perform reservation for entries that - * has been requested - */ - if (parms->alloc_cnt[i] == 0) - continue; + struct tf_rm_element_cfg *cfg = &parms->cfg[i]; + uint16_t hcapi_type = cfg->hcapi_type; - /* Verify that we can get the full amount - * allocated per the qcaps availability. + /* Only perform reservation for requested entries + */ + if (req_cnt[i] == 0) + continue; + + /* Skip any children in the request */ + if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI || + cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || + cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { + + /* Verify that we can get the full amount per qcaps. */ - if (parms->alloc_cnt[i] <= - query[parms->cfg[i].hcapi_type].max) { - req[j].type = parms->cfg[i].hcapi_type; - req[j].min = parms->alloc_cnt[i]; - req[j].max = parms->alloc_cnt[i]; + if (req_cnt[i] <= query[hcapi_type].max) { + req[j].type = hcapi_type; + req[j].min = req_cnt[i]; + req[j].max = req_cnt[i]; j++; } else { + const char *type_str; + + dev->ops->tf_dev_get_resource_str(tfp, + hcapi_type, + &type_str); TFP_DRV_LOG(ERR, - "%s: Resource failure, type:%d\n", - tf_dir_2_str(parms->dir), - parms->cfg[i].hcapi_type); - TFP_DRV_LOG(ERR, - "req:%d, avail:%d\n", - parms->alloc_cnt[i], - query[parms->cfg[i].hcapi_type].max); + "Failure, %s:%d:%s req:%d avail:%d\n", + tf_dir_2_str(parms->dir), + hcapi_type, type_str, + req_cnt[i], + query[hcapi_type].max); return -EINVAL; } } } + /* Allocate all resources for the module type + */ rc = tf_msg_session_resc_alloc(tfp, + dev, parms->dir, hcapi_items, req, @@ -523,32 +687,46 @@ tf_rm_create_db(struct tf *tfp, db = rm_db->db; for (i = 0, j = 0; i < parms->num_elements; i++) { - db[i].cfg_type = parms->cfg[i].cfg_type; - db[i].hcapi_type = parms->cfg[i].hcapi_type; + struct tf_rm_element_cfg *cfg = &parms->cfg[i]; + const char *type_str; + + dev->ops->tf_dev_get_resource_str(tfp, + cfg->hcapi_type, + &type_str); - /* Skip any non HCAPI types as we didn't include them - * in the reservation request. + db[i].cfg_type = cfg->cfg_type; + db[i].hcapi_type = cfg->hcapi_type; + db[i].slices = cfg->slices; + + /* Save the parent subtype for later use to find the pool */ - if (parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI && - parms->cfg[i].cfg_type != TF_RM_ELEM_CFG_HCAPI_BA) - continue; + if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD) + db[i].parent_subtype = cfg->parent_subtype; /* If the element didn't request an allocation no need * to create a pool nor verify if we got a reservation. */ - if (parms->alloc_cnt[i] == 0) + if (req_cnt[i] == 0) + continue; + + /* Skip any children or invalid + */ + if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI && + cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && + cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT) continue; /* If the element had requested an allocation and that * allocation was a success (full amount) then * allocate the pool. */ - if (parms->alloc_cnt[i] == resv[j].stride) { + if (req_cnt[i] == resv[j].stride) { db[i].alloc.entry.start = resv[j].start; db[i].alloc.entry.stride = resv[j].stride; - /* Only allocate BA pool if so requested */ - if (parms->cfg[i].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA) { + /* Only allocate BA pool if a BA type not a child */ + if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || + cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { /* Create pool */ pool_size = (BITALLOC_SIZEOF(resv[j].stride) / sizeof(struct bitalloc)); @@ -558,19 +736,21 @@ tf_rm_create_db(struct tf *tfp, rc = tfp_calloc(&cparms); if (rc) { TFP_DRV_LOG(ERR, - "%s: Pool alloc failed, type:%d\n", - tf_dir_2_str(parms->dir), - db[i].cfg_type); + "%s: Pool alloc failed, type:%d:%s\n", + tf_dir_2_str(parms->dir), + cfg->hcapi_type, type_str); goto fail; } db[i].pool = (struct bitalloc *)cparms.mem_va; - rc = ba_init(db[i].pool, resv[j].stride); + rc = ba_init(db[i].pool, + resv[j].stride, + !tf_session_is_shared_session(tfs)); if (rc) { TFP_DRV_LOG(ERR, - "%s: Pool init failed, type:%d\n", - tf_dir_2_str(parms->dir), - db[i].cfg_type); + "%s: Pool init failed, type:%d:%s\n", + tf_dir_2_str(parms->dir), + cfg->hcapi_type, type_str); goto fail; } } @@ -580,32 +760,28 @@ tf_rm_create_db(struct tf *tfp, * all elements, not any less. */ TFP_DRV_LOG(ERR, - "%s: Alloc failed, type:%d\n", - tf_dir_2_str(parms->dir), - db[i].cfg_type); - TFP_DRV_LOG(ERR, - "req:%d, alloc:%d\n", - parms->alloc_cnt[i], - resv[j].stride); + "%s: Alloc failed %d:%s req:%d, alloc:%d\n", + tf_dir_2_str(parms->dir), cfg->hcapi_type, + type_str, req_cnt[i], resv[j].stride); goto fail; } } rm_db->num_entries = parms->num_elements; rm_db->dir = parms->dir; - rm_db->type = parms->type; + rm_db->module = parms->module; *parms->rm_db = (void *)rm_db; #if (TF_RM_DEBUG == 1) - printf("%s: type:%d num_entries:%d\n", + + printf("%s: module:%s\n", tf_dir_2_str(parms->dir), - parms->type, - i); + tf_module_2_str(parms->module)); #endif /* (TF_RM_DEBUG == 1) */ tfp_free((void *)req); tfp_free((void *)resv); - + tfp_free((void *)req_cnt); return 0; fail: @@ -614,11 +790,251 @@ tf_rm_create_db(struct tf *tfp, tfp_free((void *)db->pool); tfp_free((void *)db); tfp_free((void *)rm_db); + tfp_free((void *)req_cnt); parms->rm_db = NULL; return -EINVAL; } +int +tf_rm_create_db_no_reservation(struct tf *tfp, + struct tf_rm_create_db_parms *parms) +{ + int rc; + struct tf_session *tfs; + struct tf_dev_info *dev; + int i, j; + uint16_t hcapi_items, *req_cnt; + struct tfp_calloc_parms cparms; + struct tf_rm_resc_req_entry *req; + struct tf_rm_resc_entry *resv; + struct tf_rm_new_db *rm_db; + struct tf_rm_element *db; + uint32_t pool_size; + + TF_CHECK_PARMS2(tfp, parms); + + /* Retrieve the session information */ + rc = tf_session_get_session_internal(tfp, &tfs); + if (rc) + return rc; + + /* Retrieve device information */ + rc = tf_session_get_device(tfs, &dev); + if (rc) + return rc; + + /* Copy requested counts (alloc_cnt) from tf_open_session() to local + * copy (req_cnt) so that it can be updated if required. + */ + + cparms.nitems = parms->num_elements; + cparms.size = sizeof(uint16_t); + cparms.alignment = 0; + rc = tfp_calloc(&cparms); + if (rc) + return rc; + + req_cnt = (uint16_t *)cparms.mem_va; + + tfp_memcpy(req_cnt, parms->alloc_cnt, + parms->num_elements * sizeof(uint16_t)); + + /* Process capabilities against DB requirements. However, as a + * DB can hold elements that are not HCAPI we can reduce the + * req msg content by removing those out of the request yet + * the DB holds them all as to give a fast lookup. We can also + * remove entries where there are no request for elements. + */ + tf_rm_count_hcapi_reservations(parms->dir, + parms->module, + parms->cfg, + req_cnt, + parms->num_elements, + &hcapi_items); + + if (hcapi_items == 0) { + TFP_DRV_LOG(ERR, + "%s: module:%s Empty RM DB create request\n", + tf_dir_2_str(parms->dir), + tf_module_2_str(parms->module)); + + parms->rm_db = NULL; + return -ENOMEM; + } + + /* Alloc request, alignment already set */ + cparms.nitems = (size_t)hcapi_items; + cparms.size = sizeof(struct tf_rm_resc_req_entry); + rc = tfp_calloc(&cparms); + if (rc) + return rc; + req = (struct tf_rm_resc_req_entry *)cparms.mem_va; + + /* Alloc reservation, alignment and nitems already set */ + cparms.size = sizeof(struct tf_rm_resc_entry); + rc = tfp_calloc(&cparms); + if (rc) + return rc; + resv = (struct tf_rm_resc_entry *)cparms.mem_va; + + /* Build the request */ + for (i = 0, j = 0; i < parms->num_elements; i++) { + struct tf_rm_element_cfg *cfg = &parms->cfg[i]; + uint16_t hcapi_type = cfg->hcapi_type; + + /* Only perform reservation for requested entries + */ + if (req_cnt[i] == 0) + continue; + + /* Skip any children in the request */ + if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI || + cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || + cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { + req[j].type = hcapi_type; + req[j].min = req_cnt[i]; + req[j].max = req_cnt[i]; + j++; + } + } + + /* Get all resources info for the module type + */ + rc = tf_msg_session_resc_info(tfp, + dev, + parms->dir, + hcapi_items, + req, + resv); + if (rc) + return rc; + + /* Build the RM DB per the request */ + cparms.nitems = 1; + cparms.size = sizeof(struct tf_rm_new_db); + rc = tfp_calloc(&cparms); + if (rc) + return rc; + rm_db = (void *)cparms.mem_va; + + /* Build the DB within RM DB */ + cparms.nitems = parms->num_elements; + cparms.size = sizeof(struct tf_rm_element); + rc = tfp_calloc(&cparms); + if (rc) + return rc; + rm_db->db = (struct tf_rm_element *)cparms.mem_va; + + db = rm_db->db; + for (i = 0, j = 0; i < parms->num_elements; i++) { + struct tf_rm_element_cfg *cfg = &parms->cfg[i]; + const char *type_str; + + dev->ops->tf_dev_get_resource_str(tfp, + cfg->hcapi_type, + &type_str); + + db[i].cfg_type = cfg->cfg_type; + db[i].hcapi_type = cfg->hcapi_type; + + /* Save the parent subtype for later use to find the pool + */ + if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD) + db[i].parent_subtype = cfg->parent_subtype; + + /* If the element didn't request an allocation no need + * to create a pool nor verify if we got a reservation. + */ + if (req_cnt[i] == 0) + continue; + + /* Skip any children or invalid + */ + if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI && + cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && + cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT) + continue; + + /* If the element had requested an allocation and that + * allocation was a success (full amount) then + * allocate the pool. + */ + if (req_cnt[i] == resv[j].stride) { + db[i].alloc.entry.start = resv[j].start; + db[i].alloc.entry.stride = resv[j].stride; + + /* Only allocate BA pool if a BA type not a child */ + if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || + cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { + /* Create pool */ + pool_size = (BITALLOC_SIZEOF(resv[j].stride) / + sizeof(struct bitalloc)); + /* Alloc request, alignment already set */ + cparms.nitems = pool_size; + cparms.size = sizeof(struct bitalloc); + rc = tfp_calloc(&cparms); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Pool alloc failed, type:%d:%s\n", + tf_dir_2_str(parms->dir), + cfg->hcapi_type, type_str); + goto fail; + } + db[i].pool = (struct bitalloc *)cparms.mem_va; + + rc = ba_init(db[i].pool, + resv[j].stride, + !tf_session_is_shared_session(tfs)); + if (rc) { + TFP_DRV_LOG(ERR, + "%s: Pool init failed, type:%d:%s\n", + tf_dir_2_str(parms->dir), + cfg->hcapi_type, type_str); + goto fail; + } + } + j++; + } else { + /* Bail out as we want what we requested for + * all elements, not any less. + */ + TFP_DRV_LOG(ERR, + "%s: Alloc failed %d:%s req:%d, alloc:%d\n", + tf_dir_2_str(parms->dir), cfg->hcapi_type, + type_str, req_cnt[i], resv[j].stride); + goto fail; + } + } + + rm_db->num_entries = parms->num_elements; + rm_db->dir = parms->dir; + rm_db->module = parms->module; + *parms->rm_db = (void *)rm_db; + +#if (TF_RM_DEBUG == 1) + + printf("%s: module:%s\n", + tf_dir_2_str(parms->dir), + tf_module_2_str(parms->module)); +#endif /* (TF_RM_DEBUG == 1) */ + + tfp_free((void *)req); + tfp_free((void *)resv); + tfp_free((void *)req_cnt); + return 0; + + fail: + tfp_free((void *)req); + tfp_free((void *)resv); + tfp_free((void *)db->pool); + tfp_free((void *)db); + tfp_free((void *)rm_db); + tfp_free((void *)req_cnt); + parms->rm_db = NULL; + + return -EINVAL; +} int tf_rm_free_db(struct tf *tfp, struct tf_rm_free_db_parms *parms) @@ -680,7 +1096,7 @@ tf_rm_free_db(struct tf *tfp, TFP_DRV_LOG(ERR, "%s: Internal Flush error, module:%s\n", tf_dir_2_str(parms->dir), - tf_device_module_type_2_str(rm_db->type)); + tf_module_2_str(rm_db->module)); } /* No need to check for configuration type, even if we do not @@ -693,6 +1109,54 @@ tf_rm_free_db(struct tf *tfp, return rc; } +/** + * Get the bit allocator pool associated with the subtype and the db + * + * [in] rm_db + * Pointer to the DB + * + * [in] subtype + * Module subtype used to index into the module specific database. + * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a + * module subtype of TF_MODULE_TYPE_TABLE. + * + * [in/out] pool + * Pointer to the bit allocator pool used + * + * [in/out] new_subtype + * Pointer to the subtype of the actual pool used + * Returns: + * 0 - Success + * - ENOTSUP - Operation not supported + */ +static int +tf_rm_get_pool(struct tf_rm_new_db *rm_db, + uint16_t subtype, + struct bitalloc **pool, + uint16_t *new_subtype) +{ + int rc = 0; + uint16_t tmp_subtype = subtype; + + /* If we are a child, get the parent table index */ + if (rm_db->db[subtype].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD) + tmp_subtype = rm_db->db[subtype].parent_subtype; + + *pool = rm_db->db[tmp_subtype].pool; + + /* Bail out if the pool is not valid, should never happen */ + if (rm_db->db[tmp_subtype].pool == NULL) { + rc = -ENOTSUP; + TFP_DRV_LOG(ERR, + "%s: Invalid pool for this type:%d, rc:%s\n", + tf_dir_2_str(rm_db->dir), + tmp_subtype, + strerror(-rc)); + return rc; + } + *new_subtype = tmp_subtype; + return rc; +} int tf_rm_allocate(struct tf_rm_allocate_parms *parms) @@ -702,35 +1166,33 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms) uint32_t index; struct tf_rm_new_db *rm_db; enum tf_rm_elem_cfg_type cfg_type; + struct bitalloc *pool; + uint16_t subtype; TF_CHECK_PARMS2(parms, parms->rm_db); rm_db = (struct tf_rm_new_db *)parms->rm_db; - cfg_type = rm_db->db[parms->db_index].cfg_type; + TF_CHECK_PARMS1(rm_db->db); + + cfg_type = rm_db->db[parms->subtype].cfg_type; /* Bail out if not controlled by RM */ - if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA) + if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) return -ENOTSUP; - /* Bail out if the pool is not valid, should never happen */ - if (rm_db->db[parms->db_index].pool == NULL) { - rc = -ENOTSUP; - TFP_DRV_LOG(ERR, - "%s: Invalid pool for this type:%d, rc:%s\n", - tf_dir_2_str(rm_db->dir), - parms->db_index, - strerror(-rc)); + rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); + if (rc) return rc; - } - /* * priority 0: allocate from top of the tcam i.e. high * priority !0: allocate index from bottom i.e lowest */ if (parms->priority) - id = ba_alloc_reverse(rm_db->db[parms->db_index].pool); + id = ba_alloc_reverse(pool); else - id = ba_alloc(rm_db->db[parms->db_index].pool); + id = ba_alloc(pool); if (id == BA_FAIL) { rc = -ENOMEM; TFP_DRV_LOG(ERR, @@ -743,7 +1205,7 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms) /* Adjust for any non zero start value */ rc = tf_rm_adjust_index(rm_db->db, TF_RM_ADJUST_ADD_BASE, - parms->db_index, + subtype, id, &index); if (rc) { @@ -755,6 +1217,8 @@ tf_rm_allocate(struct tf_rm_allocate_parms *parms) } *parms->index = index; + if (parms->base_index) + *parms->base_index = id; return rc; } @@ -766,37 +1230,35 @@ tf_rm_free(struct tf_rm_free_parms *parms) uint32_t adj_index; struct tf_rm_new_db *rm_db; enum tf_rm_elem_cfg_type cfg_type; + struct bitalloc *pool; + uint16_t subtype; TF_CHECK_PARMS2(parms, parms->rm_db); - rm_db = (struct tf_rm_new_db *)parms->rm_db; - cfg_type = rm_db->db[parms->db_index].cfg_type; + TF_CHECK_PARMS1(rm_db->db); + + cfg_type = rm_db->db[parms->subtype].cfg_type; /* Bail out if not controlled by RM */ - if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA) + if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) return -ENOTSUP; - /* Bail out if the pool is not valid, should never happen */ - if (rm_db->db[parms->db_index].pool == NULL) { - rc = -ENOTSUP; - TFP_DRV_LOG(ERR, - "%s: Invalid pool for this type:%d, rc:%s\n", - tf_dir_2_str(rm_db->dir), - parms->db_index, - strerror(-rc)); + rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); + if (rc) return rc; - } /* Adjust for any non zero start value */ rc = tf_rm_adjust_index(rm_db->db, TF_RM_ADJUST_RM_BASE, - parms->db_index, + subtype, parms->index, &adj_index); if (rc) return rc; - rc = ba_free(rm_db->db[parms->db_index].pool, adj_index); + rc = ba_free(pool, adj_index); /* No logging direction matters and that is not available here */ if (rc) return rc; @@ -811,38 +1273,37 @@ tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms) uint32_t adj_index; struct tf_rm_new_db *rm_db; enum tf_rm_elem_cfg_type cfg_type; + struct bitalloc *pool; + uint16_t subtype; TF_CHECK_PARMS2(parms, parms->rm_db); - rm_db = (struct tf_rm_new_db *)parms->rm_db; - cfg_type = rm_db->db[parms->db_index].cfg_type; + TF_CHECK_PARMS1(rm_db->db); + + cfg_type = rm_db->db[parms->subtype].cfg_type; /* Bail out if not controlled by RM */ - if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA) + if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) return -ENOTSUP; - /* Bail out if the pool is not valid, should never happen */ - if (rm_db->db[parms->db_index].pool == NULL) { - rc = -ENOTSUP; - TFP_DRV_LOG(ERR, - "%s: Invalid pool for this type:%d, rc:%s\n", - tf_dir_2_str(rm_db->dir), - parms->db_index, - strerror(-rc)); + rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); + if (rc) return rc; - } /* Adjust for any non zero start value */ rc = tf_rm_adjust_index(rm_db->db, TF_RM_ADJUST_RM_BASE, - parms->db_index, + subtype, parms->index, &adj_index); if (rc) return rc; - *parms->allocated = ba_inuse(rm_db->db[parms->db_index].pool, - adj_index); + if (parms->base_index) + *parms->base_index = adj_index; + *parms->allocated = ba_inuse(pool, adj_index); return rc; } @@ -854,22 +1315,58 @@ tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms) enum tf_rm_elem_cfg_type cfg_type; TF_CHECK_PARMS2(parms, parms->rm_db); - rm_db = (struct tf_rm_new_db *)parms->rm_db; - cfg_type = rm_db->db[parms->db_index].cfg_type; + TF_CHECK_PARMS1(rm_db->db); + + cfg_type = rm_db->db[parms->subtype].cfg_type; /* Bail out if not controlled by HCAPI */ - if (cfg_type != TF_RM_ELEM_CFG_HCAPI && - cfg_type != TF_RM_ELEM_CFG_HCAPI_BA) + if (cfg_type == TF_RM_ELEM_CFG_NULL) return -ENOTSUP; memcpy(parms->info, - &rm_db->db[parms->db_index].alloc, + &rm_db->db[parms->subtype].alloc, sizeof(struct tf_rm_alloc_info)); return 0; } +int +tf_rm_get_all_info(struct tf_rm_get_alloc_info_parms *parms, int size) +{ + struct tf_rm_new_db *rm_db; + enum tf_rm_elem_cfg_type cfg_type; + struct tf_rm_alloc_info *info = parms->info; + int i; + + TF_CHECK_PARMS1(parms); + + /* No rm info available for this module type + */ + if (!parms->rm_db) + return -ENOMEM; + + rm_db = (struct tf_rm_new_db *)parms->rm_db; + TF_CHECK_PARMS1(rm_db->db); + + for (i = 0; i < size; i++) { + cfg_type = rm_db->db[i].cfg_type; + + /* Bail out if not controlled by HCAPI */ + if (cfg_type == TF_RM_ELEM_CFG_NULL) { + info++; + continue; + } + + memcpy(info, + &rm_db->db[i].alloc, + sizeof(struct tf_rm_alloc_info)); + info++; + } + + return 0; +} + int tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms) { @@ -877,16 +1374,36 @@ tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms) enum tf_rm_elem_cfg_type cfg_type; TF_CHECK_PARMS2(parms, parms->rm_db); + rm_db = (struct tf_rm_new_db *)parms->rm_db; + TF_CHECK_PARMS1(rm_db->db); + + cfg_type = rm_db->db[parms->subtype].cfg_type; + + /* Bail out if not controlled by HCAPI */ + if (cfg_type == TF_RM_ELEM_CFG_NULL) + return -ENOTSUP; + *parms->hcapi_type = rm_db->db[parms->subtype].hcapi_type; + + return 0; +} +int +tf_rm_get_slices(struct tf_rm_get_slices_parms *parms) +{ + struct tf_rm_new_db *rm_db; + enum tf_rm_elem_cfg_type cfg_type; + + TF_CHECK_PARMS2(parms, parms->rm_db); rm_db = (struct tf_rm_new_db *)parms->rm_db; - cfg_type = rm_db->db[parms->db_index].cfg_type; + TF_CHECK_PARMS1(rm_db->db); + + cfg_type = rm_db->db[parms->subtype].cfg_type; /* Bail out if not controlled by HCAPI */ - if (cfg_type != TF_RM_ELEM_CFG_HCAPI && - cfg_type != TF_RM_ELEM_CFG_HCAPI_BA) + if (cfg_type == TF_RM_ELEM_CFG_NULL) return -ENOTSUP; - *parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type; + *parms->slices = rm_db->db[parms->subtype].slices; return 0; } @@ -899,24 +1416,64 @@ tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms) enum tf_rm_elem_cfg_type cfg_type; TF_CHECK_PARMS2(parms, parms->rm_db); - rm_db = (struct tf_rm_new_db *)parms->rm_db; - cfg_type = rm_db->db[parms->db_index].cfg_type; + TF_CHECK_PARMS1(rm_db->db); - /* Bail out if not controlled by RM */ - if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA) + cfg_type = rm_db->db[parms->subtype].cfg_type; + + /* Bail out if not a BA pool */ + if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) return -ENOTSUP; /* Bail silently (no logging), if the pool is not valid there * was no elements allocated for it. */ - if (rm_db->db[parms->db_index].pool == NULL) { + if (rm_db->db[parms->subtype].pool == NULL) { *parms->count = 0; return 0; } - *parms->count = ba_inuse_count(rm_db->db[parms->db_index].pool); + *parms->count = ba_inuse_count(rm_db->db[parms->subtype].pool); return rc; +} +/* Only used for table bulk get at this time + */ +int +tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms) +{ + struct tf_rm_new_db *rm_db; + enum tf_rm_elem_cfg_type cfg_type; + uint32_t base_index; + uint32_t stride; + int rc = 0; + struct bitalloc *pool; + uint16_t subtype; + TF_CHECK_PARMS2(parms, parms->rm_db); + rm_db = (struct tf_rm_new_db *)parms->rm_db; + TF_CHECK_PARMS1(rm_db->db); + + cfg_type = rm_db->db[parms->subtype].cfg_type; + + /* Bail out if not a BA pool */ + if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && + cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) + return -ENOTSUP; + + rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); + if (rc) + return rc; + + base_index = rm_db->db[subtype].alloc.entry.start; + stride = rm_db->db[subtype].alloc.entry.stride; + + if (parms->starting_index < base_index || + parms->starting_index + parms->num_entries > base_index + stride) + return -EINVAL; + + return rc; }