1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2020 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_common.h> 7 8 #include "tf_shadow_identifier.h" 9 #include "tf_common.h" 10 #include "tf_util.h" 11 #include "tfp.h" 12 13 /** 14 * Shadow identifier DB element 15 */ 16 struct tf_shadow_ident_element { 17 /** 18 * Identifier 19 */ 20 uint32_t *id; 21 22 /** 23 * Reference count, array of number of identifier type entries 24 */ 25 uint32_t *ref_count; 26 }; 27 28 /** 29 * Shadow identifier DB definition 30 */ 31 struct tf_shadow_ident_db { 32 /** 33 * Number of elements in the DB 34 */ 35 uint16_t num_entries; 36 37 /** 38 * The DB consists of an array of elements 39 */ 40 struct tf_shadow_ident_element *db; 41 }; 42 43 int tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms * parms)44tf_shadow_ident_create_db(struct tf_shadow_ident_create_db_parms *parms) 45 { 46 int rc; 47 int i; 48 struct tfp_calloc_parms cparms; 49 struct tf_shadow_ident_db *shadow_db; 50 struct tf_shadow_ident_element *db; 51 52 TF_CHECK_PARMS1(parms); 53 54 /* Build the shadow DB per the request */ 55 cparms.nitems = 1; 56 cparms.size = sizeof(struct tf_shadow_ident_db); 57 cparms.alignment = 0; 58 rc = tfp_calloc(&cparms); 59 if (rc) 60 return rc; 61 shadow_db = (void *)cparms.mem_va; 62 63 /* Build the DB within shadow DB */ 64 cparms.nitems = parms->num_elements; 65 cparms.size = sizeof(struct tf_shadow_ident_element); 66 rc = tfp_calloc(&cparms); 67 if (rc) 68 return rc; 69 shadow_db->db = (struct tf_shadow_ident_element *)cparms.mem_va; 70 shadow_db->num_entries = parms->num_elements; 71 72 db = shadow_db->db; 73 for (i = 0; i < parms->num_elements; i++) { 74 /* If the element didn't request an allocation no need 75 * to create a pool nor verify if we got a reservation. 76 */ 77 if (parms->cfg->alloc_cnt[i] == 0) 78 continue; 79 80 /* Create array */ 81 cparms.nitems = parms->cfg->alloc_cnt[i]; 82 cparms.size = sizeof(uint32_t); 83 rc = tfp_calloc(&cparms); 84 if (rc) { 85 TFP_DRV_LOG(ERR, 86 "%s: Array alloc failed, type:%d\n", 87 tf_dir_2_str(parms->dir), 88 i); 89 goto fail; 90 } 91 db[i].ref_count = (uint32_t *)cparms.mem_va; 92 } 93 94 *parms->tf_shadow_ident_db = (void *)shadow_db; 95 96 return 0; 97 fail: 98 tfp_free((void *)db->ref_count); 99 tfp_free((void *)db); 100 tfp_free((void *)shadow_db); 101 parms->tf_shadow_ident_db = NULL; 102 103 return -EINVAL; 104 } 105 106 int tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms * parms)107tf_shadow_ident_free_db(struct tf_shadow_ident_free_db_parms *parms) 108 { 109 int i; 110 struct tf_shadow_ident_db *shadow_db; 111 112 TF_CHECK_PARMS1(parms); 113 114 shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; 115 for (i = 0; i < shadow_db->num_entries; i++) 116 tfp_free((void *)shadow_db->db[i].ref_count); 117 118 tfp_free((void *)shadow_db->db); 119 tfp_free((void *)parms->tf_shadow_ident_db); 120 121 return 0; 122 } 123 124 int tf_shadow_ident_search(struct tf_shadow_ident_search_parms * parms)125tf_shadow_ident_search(struct tf_shadow_ident_search_parms *parms) 126 { 127 struct tf_shadow_ident_db *shadow_db; 128 uint32_t ref_cnt = 0; 129 130 TF_CHECK_PARMS1(parms); 131 132 shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; 133 ref_cnt = shadow_db->db[parms->type].ref_count[parms->search_id]; 134 if (ref_cnt > 0) { 135 *parms->hit = 1; 136 *parms->ref_cnt = ++ref_cnt; 137 shadow_db->db[parms->type].ref_count[parms->search_id] = 138 ref_cnt; 139 } else { 140 *parms->hit = 0; 141 *parms->ref_cnt = 0; 142 } 143 144 145 return 0; 146 } 147 148 #define ID_REF_CNT_MAX 0xffffffff 149 int tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms * parms)150tf_shadow_ident_insert(struct tf_shadow_ident_insert_parms *parms) 151 { 152 struct tf_shadow_ident_db *shadow_db; 153 154 TF_CHECK_PARMS1(parms); 155 156 shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; 157 158 /* In case of overflow, ref count keeps the max value */ 159 if (shadow_db->db[parms->type].ref_count[parms->id] < ID_REF_CNT_MAX) 160 shadow_db->db[parms->type].ref_count[parms->id]++; 161 else 162 TFP_DRV_LOG(ERR, 163 "Identifier %d in type %d reaches the max ref_cnt\n", 164 parms->type, 165 parms->id); 166 167 parms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id]; 168 169 return 0; 170 } 171 172 int tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms * parms)173tf_shadow_ident_remove(struct tf_shadow_ident_remove_parms *parms) 174 { 175 struct tf_shadow_ident_db *shadow_db; 176 uint32_t ref_cnt = 0; 177 178 TF_CHECK_PARMS1(parms); 179 180 shadow_db = (struct tf_shadow_ident_db *)parms->tf_shadow_ident_db; 181 ref_cnt = shadow_db->db[parms->type].ref_count[parms->id]; 182 if (ref_cnt > 0) 183 shadow_db->db[parms->type].ref_count[parms->id]--; 184 else 185 return -EINVAL; 186 187 *parms->ref_cnt = shadow_db->db[parms->type].ref_count[parms->id]; 188 189 return 0; 190 } 191