1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_common.h> 7 8 #include "tf_identifier.h" 9 #include "tf_shadow_identifier.h" 10 #include "tf_common.h" 11 #include "tf_rm.h" 12 #include "tf_util.h" 13 #include "tfp.h" 14 #include "tf_session.h" 15 16 struct tf; 17 18 /** 19 * Identifier shadow DBs. 20 */ 21 static void *ident_shadow_db[TF_DIR_MAX]; 22 23 /** 24 * Shadow DB Init flag, set on bind and cleared on unbind 25 */ 26 static uint8_t shadow_init; 27 28 int 29 tf_ident_bind(struct tf *tfp, 30 struct tf_ident_cfg_parms *parms) 31 { 32 int rc; 33 int db_rc[TF_DIR_MAX] = { 0 }; 34 int i; 35 struct tf_rm_create_db_parms db_cfg = { 0 }; 36 struct tf_shadow_ident_cfg_parms shadow_cfg = { 0 }; 37 struct tf_shadow_ident_create_db_parms shadow_cdb = { 0 }; 38 struct ident_rm_db *ident_db; 39 struct tfp_calloc_parms cparms; 40 struct tf_session *tfs; 41 42 TF_CHECK_PARMS2(tfp, parms); 43 44 /* Retrieve the session information */ 45 rc = tf_session_get_session_internal(tfp, &tfs); 46 if (rc) 47 return rc; 48 49 memset(&db_cfg, 0, sizeof(db_cfg)); 50 cparms.nitems = 1; 51 cparms.size = sizeof(struct ident_rm_db); 52 cparms.alignment = 0; 53 if (tfp_calloc(&cparms) != 0) { 54 TFP_DRV_LOG(ERR, "ident_rm_db alloc error %s\n", 55 strerror(ENOMEM)); 56 return -ENOMEM; 57 } 58 59 ident_db = cparms.mem_va; 60 for (i = 0; i < TF_DIR_MAX; i++) 61 ident_db->ident_db[i] = NULL; 62 tf_session_set_db(tfp, TF_MODULE_TYPE_IDENTIFIER, ident_db); 63 64 db_cfg.module = TF_MODULE_TYPE_IDENTIFIER; 65 db_cfg.num_elements = parms->num_elements; 66 db_cfg.cfg = parms->cfg; 67 68 for (i = 0; i < TF_DIR_MAX; i++) { 69 db_cfg.rm_db = (void *)&ident_db->ident_db[i]; 70 db_cfg.dir = i; 71 db_cfg.alloc_cnt = parms->resources->ident_cnt[i].cnt; 72 if (tf_session_is_shared_session(tfs) && 73 (!tf_session_is_shared_session_creator(tfs))) 74 db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg); 75 else 76 db_rc[i] = tf_rm_create_db(tfp, &db_cfg); 77 78 if (parms->shadow_copy) { 79 shadow_cfg.alloc_cnt = 80 parms->resources->ident_cnt[i].cnt; 81 shadow_cdb.num_elements = parms->num_elements; 82 shadow_cdb.tf_shadow_ident_db = &ident_shadow_db[i]; 83 shadow_cdb.cfg = &shadow_cfg; 84 rc = tf_shadow_ident_create_db(&shadow_cdb); 85 if (rc) { 86 TFP_DRV_LOG(ERR, 87 "%s: Ident shadow DB creation failed\n", 88 tf_dir_2_str(i)); 89 90 return rc; 91 } 92 shadow_init = 1; 93 } 94 } 95 96 /* No db created */ 97 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) { 98 TFP_DRV_LOG(ERR, "No Identifier DB created\n"); 99 return db_rc[TF_DIR_RX]; 100 } 101 102 TFP_DRV_LOG(INFO, 103 "Identifier - initialized\n"); 104 105 return 0; 106 } 107 108 int 109 tf_ident_unbind(struct tf *tfp) 110 { 111 int rc = 0; 112 int i; 113 struct tf_rm_free_db_parms fparms = { 0 }; 114 struct tf_shadow_ident_free_db_parms sparms = { 0 }; 115 struct ident_rm_db *ident_db; 116 void *ident_db_ptr = NULL; 117 118 TF_CHECK_PARMS1(tfp); 119 120 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr); 121 if (rc) 122 return 0; 123 ident_db = (struct ident_rm_db *)ident_db_ptr; 124 125 for (i = 0; i < TF_DIR_MAX; i++) { 126 if (ident_db->ident_db[i] == NULL) 127 continue; 128 fparms.rm_db = ident_db->ident_db[i]; 129 fparms.dir = i; 130 rc = tf_rm_free_db(tfp, &fparms); 131 if (rc) { 132 TFP_DRV_LOG(ERR, 133 "rm free failed on unbind\n"); 134 } 135 if (shadow_init) { 136 sparms.tf_shadow_ident_db = ident_shadow_db[i]; 137 rc = tf_shadow_ident_free_db(&sparms); 138 if (rc) { 139 /* TODO: If there are failures on unbind we 140 * really just have to try until all DBs are 141 * attempted to be cleared. 142 */ 143 } 144 ident_shadow_db[i] = NULL; 145 } 146 ident_db->ident_db[i] = NULL; 147 } 148 149 shadow_init = 0; 150 151 return 0; 152 } 153 154 int 155 tf_ident_alloc(struct tf *tfp __rte_unused, 156 struct tf_ident_alloc_parms *parms) 157 { 158 int rc; 159 uint32_t id; 160 uint32_t base_id; 161 struct tf_rm_allocate_parms aparms = { 0 }; 162 struct tf_shadow_ident_insert_parms iparms = { 0 }; 163 struct ident_rm_db *ident_db; 164 void *ident_db_ptr = NULL; 165 166 TF_CHECK_PARMS2(tfp, parms); 167 168 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr); 169 if (rc) { 170 TFP_DRV_LOG(ERR, 171 "Failed to get ident_db from session, rc:%s\n", 172 strerror(-rc)); 173 return rc; 174 } 175 ident_db = (struct ident_rm_db *)ident_db_ptr; 176 177 aparms.rm_db = ident_db->ident_db[parms->dir]; 178 aparms.subtype = parms->type; 179 aparms.index = &id; 180 aparms.base_index = &base_id; 181 rc = tf_rm_allocate(&aparms); 182 if (rc) { 183 TFP_DRV_LOG(ERR, 184 "%s: Failed allocate, type:%d\n", 185 tf_dir_2_str(parms->dir), 186 parms->type); 187 return rc; 188 } 189 190 if (shadow_init) { 191 iparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; 192 iparms.type = parms->type; 193 iparms.id = base_id; 194 195 rc = tf_shadow_ident_insert(&iparms); 196 if (rc) { 197 TFP_DRV_LOG(ERR, 198 "%s: Failed insert shadow DB, type:%d\n", 199 tf_dir_2_str(parms->dir), 200 parms->type); 201 return rc; 202 } 203 } 204 205 *parms->id = id; 206 207 return 0; 208 } 209 210 int 211 tf_ident_free(struct tf *tfp __rte_unused, 212 struct tf_ident_free_parms *parms) 213 { 214 int rc; 215 struct tf_rm_is_allocated_parms aparms = { 0 }; 216 struct tf_rm_free_parms fparms = { 0 }; 217 struct tf_shadow_ident_remove_parms rparms = { 0 }; 218 int allocated = 0; 219 uint32_t base_id; 220 struct ident_rm_db *ident_db; 221 void *ident_db_ptr = NULL; 222 223 TF_CHECK_PARMS2(tfp, parms); 224 225 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr); 226 if (rc) { 227 TFP_DRV_LOG(ERR, 228 "Failed to get ident_db from session, rc:%s\n", 229 strerror(-rc)); 230 return rc; 231 } 232 ident_db = (struct ident_rm_db *)ident_db_ptr; 233 234 /* Check if element is in use */ 235 aparms.rm_db = ident_db->ident_db[parms->dir]; 236 aparms.subtype = parms->type; 237 aparms.index = parms->id; 238 aparms.base_index = &base_id; 239 aparms.allocated = &allocated; 240 rc = tf_rm_is_allocated(&aparms); 241 if (rc) 242 return rc; 243 244 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 245 TFP_DRV_LOG(ERR, 246 "%s: Entry already free, type:%d, index:%d\n", 247 tf_dir_2_str(parms->dir), 248 parms->type, 249 parms->id); 250 return -EINVAL; 251 } 252 253 if (shadow_init) { 254 rparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; 255 rparms.type = parms->type; 256 rparms.id = base_id; 257 rparms.ref_cnt = parms->ref_cnt; 258 259 rc = tf_shadow_ident_remove(&rparms); 260 if (rc) { 261 TFP_DRV_LOG(ERR, 262 "%s: ref_cnt was 0 in shadow DB," 263 " type:%d, index:%d\n", 264 tf_dir_2_str(parms->dir), 265 parms->type, 266 parms->id); 267 return rc; 268 } 269 270 if (*rparms.ref_cnt > 0) 271 return 0; 272 } 273 274 /* Free requested element */ 275 fparms.rm_db = ident_db->ident_db[parms->dir]; 276 fparms.subtype = parms->type; 277 fparms.index = parms->id; 278 rc = tf_rm_free(&fparms); 279 if (rc) { 280 TFP_DRV_LOG(ERR, 281 "%s: Free failed, type:%d, index:%d\n", 282 tf_dir_2_str(parms->dir), 283 parms->type, 284 parms->id); 285 return rc; 286 } 287 288 return 0; 289 } 290 291 int 292 tf_ident_search(struct tf *tfp __rte_unused, 293 struct tf_ident_search_parms *parms) 294 { 295 int rc; 296 struct tf_rm_is_allocated_parms aparms = { 0 }; 297 struct tf_shadow_ident_search_parms sparms = { 0 }; 298 int allocated = 0; 299 uint32_t base_id; 300 struct ident_rm_db *ident_db; 301 void *ident_db_ptr = NULL; 302 303 TF_CHECK_PARMS2(tfp, parms); 304 305 if (!shadow_init) { 306 TFP_DRV_LOG(ERR, 307 "%s: Identifier Shadow copy is not enabled\n", 308 tf_dir_2_str(parms->dir)); 309 return -EINVAL; 310 } 311 312 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr); 313 if (rc) { 314 TFP_DRV_LOG(ERR, 315 "Failed to get ident_db from session, rc:%s\n", 316 strerror(-rc)); 317 return rc; 318 } 319 ident_db = (struct ident_rm_db *)ident_db_ptr; 320 321 /* Check if element is in use */ 322 aparms.rm_db = ident_db->ident_db[parms->dir]; 323 aparms.subtype = parms->type; 324 aparms.index = parms->search_id; 325 aparms.base_index = &base_id; 326 aparms.allocated = &allocated; 327 rc = tf_rm_is_allocated(&aparms); 328 if (rc) 329 return rc; 330 331 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 332 TFP_DRV_LOG(ERR, 333 "%s: Entry not allocated, type:%d, index:%d\n", 334 tf_dir_2_str(parms->dir), 335 parms->type, 336 parms->search_id); 337 return -EINVAL; 338 } 339 340 sparms.tf_shadow_ident_db = ident_shadow_db[parms->dir]; 341 sparms.type = parms->type; 342 sparms.search_id = base_id; 343 sparms.hit = parms->hit; 344 sparms.ref_cnt = parms->ref_cnt; 345 346 rc = tf_shadow_ident_search(&sparms); 347 if (rc) { 348 TFP_DRV_LOG(ERR, 349 "%s: Failed search shadow DB, type:%d\n", 350 tf_dir_2_str(parms->dir), 351 parms->type); 352 return rc; 353 } 354 355 return 0; 356 } 357 358 int 359 tf_ident_get_resc_info(struct tf *tfp, 360 struct tf_identifier_resource_info *ident) 361 { 362 int rc; 363 int d; 364 struct tf_resource_info *dinfo; 365 struct tf_rm_get_alloc_info_parms ainfo; 366 void *ident_db_ptr = NULL; 367 struct ident_rm_db *ident_db; 368 369 TF_CHECK_PARMS2(tfp, ident); 370 371 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_IDENTIFIER, &ident_db_ptr); 372 if (rc == -ENOMEM) 373 return 0; /* db doesn't exist */ 374 else if (rc) 375 return rc; /* error getting db */ 376 377 ident_db = (struct ident_rm_db *)ident_db_ptr; 378 379 /* check if reserved resource for WC is multiple of num_slices */ 380 for (d = 0; d < TF_DIR_MAX; d++) { 381 ainfo.rm_db = ident_db->ident_db[d]; 382 383 if (!ainfo.rm_db) 384 continue; 385 386 dinfo = ident[d].info; 387 388 ainfo.info = (struct tf_rm_alloc_info *)dinfo; 389 ainfo.subtype = 0; 390 rc = tf_rm_get_all_info(&ainfo, TF_IDENT_TYPE_MAX); 391 if (rc) 392 return rc; 393 } 394 395 return 0; 396 } 397