/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2019-2021 Broadcom * All rights reserved. */ #include #include "tf_identifier.h" #include "tf_shadow_identifier.h" #include "tf_common.h" #include "tf_rm.h" #include "tf_util.h" #include "tfp.h" struct tf; /** * Identifier DBs. */ static void *ident_db[TF_DIR_MAX]; /** * Init flag, set on bind and cleared on unbind */ static uint8_t init; /** * Identifier shadow DBs. */ static void *ident_shadow_db[TF_DIR_MAX]; /** * Shadow DB Init flag, set on bind and cleared on unbind */ static uint8_t shadow_init; int tf_ident_bind(struct tf *tfp, struct tf_ident_cfg_parms *parms) { int rc; int i; struct tf_rm_create_db_parms db_cfg = { 0 }; struct tf_shadow_ident_cfg_parms shadow_cfg = { 0 }; struct tf_shadow_ident_create_db_parms shadow_cdb = { 0 }; TF_CHECK_PARMS2(tfp, parms); if (init) { TFP_DRV_LOG(ERR, "Identifier DB already initialized\n"); return -EINVAL; } db_cfg.type = TF_DEVICE_MODULE_TYPE_IDENTIFIER; db_cfg.num_elements = parms->num_elements; db_cfg.cfg = parms->cfg; for (i = 0; i < TF_DIR_MAX; i++) { db_cfg.dir = i; db_cfg.alloc_cnt = parms->resources->ident_cnt[i].cnt; db_cfg.rm_db = &ident_db[i]; rc = tf_rm_create_db(tfp, &db_cfg); if (rc) { TFP_DRV_LOG(ERR, "%s: Identifier DB creation failed\n", tf_dir_2_str(i)); return rc; } if (parms->shadow_copy) { shadow_cfg.alloc_cnt = parms->resources->ident_cnt[i].cnt; shadow_cdb.num_elements = parms->num_elements; shadow_cdb.tf_shadow_ident_db = &ident_shadow_db[i]; shadow_cdb.cfg = &shadow_cfg; rc = tf_shadow_ident_create_db(&shadow_cdb); if (rc) { TFP_DRV_LOG(ERR, "%s: Ident shadow DB creation failed\n", tf_dir_2_str(i)); return rc; } shadow_init = 1; } } init = 1; TFP_DRV_LOG(INFO, "Identifier - initialized\n"); return 0; } int tf_ident_unbind(struct tf *tfp) { int rc = 0; int i; struct tf_rm_free_db_parms fparms = { 0 }; struct tf_shadow_ident_free_db_parms sparms = { 0 }; TF_CHECK_PARMS1(tfp); /* Bail if nothing has been initialized */ if (!init) { TFP_DRV_LOG(INFO, "No Identifier DBs created\n"); return 0; } for (i = 0; i < TF_DIR_MAX; i++) { fparms.dir = i; fparms.rm_db = ident_db[i]; rc = tf_rm_free_db(tfp, &fparms); if (rc) { TFP_DRV_LOG(ERR, "rm free failed on unbind\n"); } if (shadow_init) { sparms.tf_shadow_ident_db = ident_shadow_db[i]; rc = tf_shadow_ident_free_db(&sparms); if (rc) { /* TODO: If there are failures on unbind we * really just have to try until all DBs are * attempted to be cleared. */ } ident_shadow_db[i] = NULL; } ident_db[i] = NULL; } init = 0; shadow_init = 0; return 0; } int tf_ident_alloc(struct tf *tfp __rte_unused, struct tf_ident_alloc_parms *parms) { int rc; uint32_t id; uint32_t base_id; struct tf_rm_allocate_parms aparms = { 0 }; struct tf_shadow_ident_insert_parms iparms = { 0 }; TF_CHECK_PARMS2(tfp, parms); if (!init) { TFP_DRV_LOG(ERR, "%s: No Identifier DBs created\n", tf_dir_2_str(parms->dir)); return -EINVAL; } /* Allocate requested element */ aparms.rm_db = ident_db[parms->dir]; aparms.db_index = parms->type; aparms.index = &id; aparms.base_index = &base_id; rc = tf_rm_allocate(&aparms); if (rc) { TFP_DRV_LOG(ERR, "%s: Failed allocate, type:%d\n", tf_dir_2_str(parms->dir), parms->type); return rc; } if (shadow_init) { iparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; iparms.type = parms->type; iparms.id = base_id; rc = tf_shadow_ident_insert(&iparms); if (rc) { TFP_DRV_LOG(ERR, "%s: Failed insert shadow DB, type:%d\n", tf_dir_2_str(parms->dir), parms->type); return rc; } } *parms->id = id; return 0; } int tf_ident_free(struct tf *tfp __rte_unused, struct tf_ident_free_parms *parms) { int rc; struct tf_rm_is_allocated_parms aparms = { 0 }; struct tf_rm_free_parms fparms = { 0 }; struct tf_shadow_ident_remove_parms rparms = { 0 }; int allocated = 0; uint32_t base_id; TF_CHECK_PARMS2(tfp, parms); if (!init) { TFP_DRV_LOG(ERR, "%s: No Identifier DBs created\n", tf_dir_2_str(parms->dir)); return -EINVAL; } /* Check if element is in use */ aparms.rm_db = ident_db[parms->dir]; aparms.db_index = parms->type; aparms.index = parms->id; aparms.base_index = &base_id; aparms.allocated = &allocated; rc = tf_rm_is_allocated(&aparms); if (rc) return rc; if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { TFP_DRV_LOG(ERR, "%s: Entry already free, type:%d, index:%d\n", tf_dir_2_str(parms->dir), parms->type, parms->id); return -EINVAL; } if (shadow_init) { rparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; rparms.type = parms->type; rparms.id = base_id; rparms.ref_cnt = parms->ref_cnt; rc = tf_shadow_ident_remove(&rparms); if (rc) { TFP_DRV_LOG(ERR, "%s: ref_cnt was 0 in shadow DB," " type:%d, index:%d\n", tf_dir_2_str(parms->dir), parms->type, parms->id); return rc; } if (*rparms.ref_cnt > 0) return 0; } /* Free requested element */ fparms.rm_db = ident_db[parms->dir]; fparms.db_index = parms->type; fparms.index = parms->id; rc = tf_rm_free(&fparms); if (rc) { TFP_DRV_LOG(ERR, "%s: Free failed, type:%d, index:%d\n", tf_dir_2_str(parms->dir), parms->type, parms->id); return rc; } return 0; } int tf_ident_search(struct tf *tfp __rte_unused, struct tf_ident_search_parms *parms) { int rc; struct tf_rm_is_allocated_parms aparms = { 0 }; struct tf_shadow_ident_search_parms sparms = { 0 }; int allocated = 0; uint32_t base_id; TF_CHECK_PARMS2(tfp, parms); if (!init) { TFP_DRV_LOG(ERR, "%s: No Identifier DBs created\n", tf_dir_2_str(parms->dir)); return -EINVAL; } if (!shadow_init) { TFP_DRV_LOG(ERR, "%s: Identifier Shadow copy is not enabled\n", tf_dir_2_str(parms->dir)); return -EINVAL; } /* Check if element is in use */ aparms.rm_db = ident_db[parms->dir]; aparms.db_index = parms->type; aparms.index = parms->search_id; aparms.base_index = &base_id; aparms.allocated = &allocated; rc = tf_rm_is_allocated(&aparms); if (rc) return rc; if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { TFP_DRV_LOG(ERR, "%s: Entry not allocated, type:%d, index:%d\n", tf_dir_2_str(parms->dir), parms->type, parms->search_id); return -EINVAL; } sparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; sparms.type = parms->type; sparms.search_id = base_id; sparms.hit = parms->hit; sparms.ref_cnt = parms->ref_cnt; rc = tf_shadow_ident_search(&sparms); if (rc) { TFP_DRV_LOG(ERR, "%s: Failed search shadow DB, type:%d\n", tf_dir_2_str(parms->dir), parms->type); return rc; } return 0; }