1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2022 Broadcom 3 * All rights reserved. 4 */ 5 #include <stdio.h> 6 #include <errno.h> 7 #include <string.h> 8 #include "tfo.h" 9 #include "cfa_types.h" 10 #include "cfa_tim.h" 11 #include "bnxt.h" 12 13 /** Table scope stored configuration 14 */ 15 struct tfc_tsid_db { 16 bool ts_valid; /**< Table scope is valid */ 17 bool ts_is_shared; /**< Table scope is shared */ 18 bool ts_is_bs_owner; /**< Backing store allocated by this instance (PF) */ 19 uint16_t ts_max_pools; /**< maximum pools per CPM instance */ 20 enum cfa_app_type ts_app; /**< application type TF/AFM */ 21 /** backing store memory config */ 22 struct tfc_ts_mem_cfg ts_mem[CFA_REGION_TYPE_MAX][CFA_DIR_MAX]; 23 /** pool info config */ 24 struct tfc_ts_pool_info ts_pool[CFA_DIR_MAX]; 25 }; 26 27 /** TFC Object Signature 28 * This signature identifies the tfc object database and 29 * is used for pointer validation 30 */ 31 #define TFC_OBJ_SIGNATURE 0xABACABAF 32 33 /** TFC Object 34 * This data structure contains all data stored per bnxt port 35 * Access is restricted through set/get APIs. 36 * 37 * If a module (e.g. tbl_scope needs to store data, it should 38 * be added here and accessor functions created. 39 */ 40 struct tfc_object { 41 uint32_t signature; /**< TF object signature */ 42 uint16_t sid; /**< Session ID */ 43 bool is_pf; /**< port is a PF */ 44 struct cfa_bld_mpcinfo mpc_info; /**< MPC ops handle */ 45 struct tfc_tsid_db tsid_db[TFC_TBL_SCOPE_MAX]; /**< tsid database */ 46 /** TIM instance pointer (PF) - this is where the 4 instances 47 * of the TPM (rx/tx_lkup, rx/tx_act) will be stored per shared 48 * table scope. Only valid on a PF. 49 */ 50 void *ts_tim; 51 }; 52 53 void tfo_open(void **tfo, bool is_pf) 54 { 55 int rc; 56 struct tfc_object *tfco = NULL; 57 uint32_t tim_db_size; 58 59 if (tfo == NULL) { 60 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 61 return; 62 } 63 64 tfco = (struct tfc_object *)rte_zmalloc("tf", sizeof(*tfco), 0); 65 if (tfco == NULL) 66 return; 67 68 tfco->signature = TFC_OBJ_SIGNATURE; 69 tfco->is_pf = is_pf; 70 tfco->sid = INVALID_SID; 71 tfco->ts_tim = NULL; 72 73 /* Bind to the MPC builder */ 74 rc = cfa_bld_mpc_bind(CFA_P70, &tfco->mpc_info); 75 if (rc) { 76 PMD_DRV_LOG_LINE(ERR, "MPC bind failed"); 77 rte_free(tfco); 78 *tfo = NULL; 79 return; 80 } 81 if (is_pf) { 82 /* Allocate TIM */ 83 rc = cfa_tim_query(TFC_TBL_SCOPE_MAX, CFA_REGION_TYPE_MAX, 84 &tim_db_size); 85 if (rc) 86 goto cleanup; 87 88 tfco->ts_tim = rte_zmalloc("TIM", tim_db_size, 0); 89 if (tfco->ts_tim == NULL) 90 goto cleanup; 91 92 rc = cfa_tim_open(tfco->ts_tim, 93 tim_db_size, 94 TFC_TBL_SCOPE_MAX, 95 CFA_REGION_TYPE_MAX); 96 if (rc) { 97 rte_free(tfco->ts_tim); 98 tfco->ts_tim = NULL; 99 goto cleanup; 100 } 101 } 102 103 *tfo = tfco; 104 return; 105 106 cleanup: 107 if (tfco != NULL) 108 rte_free(tfo); 109 } 110 111 void tfo_close(void **tfo) 112 { 113 struct tfc_object *tfco = (struct tfc_object *)(*tfo); 114 enum cfa_region_type region; 115 int dir; 116 int tsid; 117 void *tim; 118 void *tpm; 119 120 if (*tfo && tfco->signature == TFC_OBJ_SIGNATURE) { 121 /* If TIM is setup free it and any TPMs */ 122 if (tfo_tim_get(*tfo, &tim)) 123 goto done; 124 125 if (!tim) 126 goto done; 127 128 for (tsid = 0; tsid < TFC_TBL_SCOPE_MAX; tsid++) { 129 for (region = 0; region < CFA_REGION_TYPE_MAX; region++) { 130 for (dir = 0; dir < CFA_DIR_MAX; dir++) { 131 tpm = NULL; 132 cfa_tim_tpm_inst_get(tim, 133 tsid, 134 region, 135 dir, 136 &tpm); 137 if (tpm) { 138 cfa_tim_tpm_inst_set(tim, 139 tsid, 140 region, 141 dir, 142 NULL); 143 rte_free(tpm); 144 } 145 } 146 } 147 } 148 rte_free(tim); 149 tfco->ts_tim = NULL; 150 done: 151 rte_free(*tfo); 152 *tfo = NULL; 153 } 154 } 155 156 int tfo_mpcinfo_get(void *tfo, struct cfa_bld_mpcinfo **mpc_info) 157 { 158 struct tfc_object *tfco = (struct tfc_object *)tfo; 159 160 if (tfo == NULL) { 161 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 162 return -EINVAL; 163 } 164 165 if (tfco->signature != TFC_OBJ_SIGNATURE) { 166 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 167 return -EINVAL; 168 } 169 170 *mpc_info = &tfco->mpc_info; 171 172 return 0; 173 } 174 175 int tfo_ts_validate(void *tfo, uint8_t ts_tsid, bool *ts_valid) 176 { 177 struct tfc_object *tfco = (struct tfc_object *)tfo; 178 struct tfc_tsid_db *tsid_db; 179 180 if (tfo == NULL) { 181 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 182 return -EINVAL; 183 } 184 185 if (tfco->signature != TFC_OBJ_SIGNATURE) { 186 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 187 return -EINVAL; 188 } 189 190 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 191 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 192 return -EINVAL; 193 } 194 tsid_db = &tfco->tsid_db[ts_tsid]; 195 196 if (ts_valid) 197 *ts_valid = tsid_db->ts_valid; 198 199 return 0; 200 } 201 202 int tfo_ts_set(void *tfo, uint8_t ts_tsid, bool ts_is_shared, 203 enum cfa_app_type ts_app, bool ts_valid, uint16_t ts_max_pools) 204 { 205 struct tfc_object *tfco = (struct tfc_object *)tfo; 206 struct tfc_tsid_db *tsid_db; 207 208 if (tfo == NULL) { 209 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 210 return -EINVAL; 211 } 212 if (tfco->signature != TFC_OBJ_SIGNATURE) { 213 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 214 return -EINVAL; 215 } 216 217 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 218 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 219 return -EINVAL; 220 } 221 222 tsid_db = &tfco->tsid_db[ts_tsid]; 223 224 tsid_db->ts_valid = ts_valid; 225 tsid_db->ts_is_shared = ts_is_shared; 226 tsid_db->ts_app = ts_app; 227 tsid_db->ts_max_pools = ts_max_pools; 228 229 return 0; 230 } 231 232 int tfo_ts_get(void *tfo, uint8_t ts_tsid, bool *ts_is_shared, 233 enum cfa_app_type *ts_app, bool *ts_valid, 234 uint16_t *ts_max_pools) 235 { 236 struct tfc_object *tfco = (struct tfc_object *)tfo; 237 struct tfc_tsid_db *tsid_db; 238 239 if (tfo == NULL) { 240 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 241 return -EINVAL; 242 } 243 if (tfco->signature != TFC_OBJ_SIGNATURE) { 244 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 245 return -EINVAL; 246 } 247 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 248 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 249 return -EINVAL; 250 } 251 252 tsid_db = &tfco->tsid_db[ts_tsid]; 253 254 if (ts_valid) 255 *ts_valid = tsid_db->ts_valid; 256 257 if (ts_is_shared) 258 *ts_is_shared = tsid_db->ts_is_shared; 259 260 if (ts_app) 261 *ts_app = tsid_db->ts_app; 262 263 if (ts_max_pools) 264 *ts_max_pools = tsid_db->ts_max_pools; 265 266 return 0; 267 } 268 269 /** Set the table scope memory configuration for this direction 270 */ 271 int tfo_ts_set_mem_cfg(void *tfo, uint8_t ts_tsid, enum cfa_dir dir, 272 enum cfa_region_type region, bool is_bs_owner, 273 struct tfc_ts_mem_cfg *mem_cfg) 274 { 275 struct tfc_object *tfco = (struct tfc_object *)tfo; 276 int rc = 0; 277 struct tfc_tsid_db *tsid_db; 278 279 if (tfo == NULL) { 280 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 281 return -EINVAL; 282 } 283 if (tfco->signature != TFC_OBJ_SIGNATURE) { 284 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 285 return -EINVAL; 286 } 287 if (mem_cfg == NULL) { 288 PMD_DRV_LOG_LINE(ERR, "Invalid mem_cfg pointer"); 289 return -EINVAL; 290 } 291 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 292 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 293 return -EINVAL; 294 } 295 296 tsid_db = &tfco->tsid_db[ts_tsid]; 297 298 tsid_db->ts_mem[region][dir] = *mem_cfg; 299 tsid_db->ts_is_bs_owner = is_bs_owner; 300 301 return rc; 302 } 303 304 /** Get the table scope memory configuration for this direction 305 */ 306 int tfo_ts_get_mem_cfg(void *tfo, uint8_t ts_tsid, enum cfa_dir dir, 307 enum cfa_region_type region, bool *is_bs_owner, 308 struct tfc_ts_mem_cfg *mem_cfg) 309 { 310 struct tfc_object *tfco = (struct tfc_object *)tfo; 311 int rc = 0; 312 struct tfc_tsid_db *tsid_db; 313 314 if (tfo == NULL) { 315 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 316 return -EINVAL; 317 } 318 if (tfco->signature != TFC_OBJ_SIGNATURE) { 319 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 320 return -EINVAL; 321 } 322 if (mem_cfg == NULL) { 323 PMD_DRV_LOG_LINE(ERR, "Invalid mem_cfg pointer"); 324 return -EINVAL; 325 } 326 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 327 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 328 return -EINVAL; 329 } 330 331 tsid_db = &tfco->tsid_db[ts_tsid]; 332 333 *mem_cfg = tsid_db->ts_mem[region][dir]; 334 if (is_bs_owner) 335 *is_bs_owner = tsid_db->ts_is_bs_owner; 336 337 return rc; 338 } 339 340 /** Get the Pool Manager instance 341 */ 342 int tfo_ts_get_cpm_inst(void *tfo, uint8_t ts_tsid, enum cfa_dir dir, 343 struct tfc_cpm **cpm_lkup, struct tfc_cpm **cpm_act) 344 { 345 int rc = 0; 346 struct tfc_object *tfco = (struct tfc_object *)tfo; 347 struct tfc_tsid_db *tsid_db; 348 349 if (tfo == NULL) { 350 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 351 return -EINVAL; 352 } 353 if (tfco->signature != TFC_OBJ_SIGNATURE) { 354 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 355 return -EINVAL; 356 } 357 if (cpm_lkup == NULL) { 358 PMD_DRV_LOG_LINE(ERR, "Invalid cpm_lkup pointer"); 359 return -EINVAL; 360 } 361 if (cpm_act == NULL) { 362 PMD_DRV_LOG_LINE(ERR, "Invalid cpm_act pointer"); 363 return -EINVAL; 364 } 365 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 366 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 367 return -EINVAL; 368 } 369 370 tsid_db = &tfco->tsid_db[ts_tsid]; 371 372 *cpm_lkup = tsid_db->ts_pool[dir].lkup_cpm; 373 *cpm_act = tsid_db->ts_pool[dir].act_cpm; 374 375 return rc; 376 } 377 /** Set the Pool Manager instance 378 */ 379 int tfo_ts_set_cpm_inst(void *tfo, uint8_t ts_tsid, enum cfa_dir dir, 380 struct tfc_cpm *cpm_lkup, struct tfc_cpm *cpm_act) 381 { 382 int rc = 0; 383 struct tfc_object *tfco = (struct tfc_object *)tfo; 384 struct tfc_tsid_db *tsid_db; 385 386 if (tfo == NULL) { 387 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 388 return -EINVAL; 389 } 390 if (tfco->signature != TFC_OBJ_SIGNATURE) { 391 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 392 return -EINVAL; 393 } 394 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 395 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 396 return -EINVAL; 397 } 398 tsid_db = &tfco->tsid_db[ts_tsid]; 399 400 tsid_db->ts_pool[dir].lkup_cpm = cpm_lkup; 401 tsid_db->ts_pool[dir].act_cpm = cpm_act; 402 403 return rc; 404 } 405 /** Set the table scope pool memory configuration for this direction 406 */ 407 int tfo_ts_set_pool_info(void *tfo, uint8_t ts_tsid, enum cfa_dir dir, 408 struct tfc_ts_pool_info *ts_pool) 409 { 410 struct tfc_object *tfco = (struct tfc_object *)tfo; 411 int rc = 0; 412 struct tfc_tsid_db *tsid_db; 413 414 if (tfo == NULL) { 415 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 416 return -EINVAL; 417 } 418 if (tfco->signature != TFC_OBJ_SIGNATURE) { 419 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 420 return -EINVAL; 421 } 422 if (ts_pool == NULL) { 423 PMD_DRV_LOG_LINE(ERR, "Invalid ts_pool pointer"); 424 return -EINVAL; 425 } 426 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 427 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 428 return -EINVAL; 429 } 430 tsid_db = &tfco->tsid_db[ts_tsid]; 431 432 tsid_db->ts_pool[dir] = *ts_pool; 433 434 return rc; 435 } 436 437 /** Get the table scope pool memory configuration for this direction 438 */ 439 int tfo_ts_get_pool_info(void *tfo, uint8_t ts_tsid, enum cfa_dir dir, 440 struct tfc_ts_pool_info *ts_pool) 441 { 442 struct tfc_object *tfco = (struct tfc_object *)tfo; 443 int rc = 0; 444 struct tfc_tsid_db *tsid_db; 445 446 if (tfo == NULL) { 447 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 448 return -EINVAL; 449 } 450 if (tfco->signature != TFC_OBJ_SIGNATURE) { 451 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 452 return -EINVAL; 453 } 454 if (ts_pool == NULL) { 455 PMD_DRV_LOG_LINE(ERR, "Invalid ts_pool pointer"); 456 return -EINVAL; 457 } 458 if (ts_tsid >= TFC_TBL_SCOPE_MAX) { 459 PMD_DRV_LOG_LINE(ERR, "Invalid tsid %d", ts_tsid); 460 return -EINVAL; 461 } 462 tsid_db = &tfco->tsid_db[ts_tsid]; 463 464 *ts_pool = tsid_db->ts_pool[dir]; 465 466 return rc; 467 } 468 469 int tfo_sid_set(void *tfo, uint16_t sid) 470 { 471 struct tfc_object *tfco = (struct tfc_object *)tfo; 472 473 if (tfo == NULL) { 474 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 475 return -EINVAL; 476 } 477 if (tfco->signature != TFC_OBJ_SIGNATURE) { 478 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 479 return -EINVAL; 480 } 481 if (tfco->sid != INVALID_SID && sid != INVALID_SID && 482 tfco->sid != sid) { 483 PMD_DRV_LOG_LINE(ERR, 484 "Cannot set SID %u, current session is %u", 485 sid, tfco->sid); 486 return -EINVAL; 487 } 488 489 tfco->sid = sid; 490 491 return 0; 492 } 493 494 int tfo_sid_get(void *tfo, uint16_t *sid) 495 { 496 struct tfc_object *tfco = (struct tfc_object *)tfo; 497 498 if (tfo == NULL) { 499 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 500 return -EINVAL; 501 } 502 if (tfco->signature != TFC_OBJ_SIGNATURE) { 503 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 504 return -EINVAL; 505 } 506 if (sid == NULL) { 507 PMD_DRV_LOG_LINE(ERR, "Invalid sid pointer"); 508 return -EINVAL; 509 } 510 511 if (tfco->sid == INVALID_SID) { 512 /* Session has not been created */ 513 return -ENODEV; 514 } 515 516 *sid = tfco->sid; 517 518 return 0; 519 } 520 521 int tfo_tim_set(void *tfo, void *tim) 522 { 523 struct tfc_object *tfco = (struct tfc_object *)tfo; 524 525 if (tfo == NULL) { 526 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 527 return -EINVAL; 528 } 529 if (tfco->signature != TFC_OBJ_SIGNATURE) { 530 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 531 return -EINVAL; 532 } 533 if (tim == NULL) { 534 PMD_DRV_LOG_LINE(ERR, "Invalid tim pointer"); 535 return -EINVAL; 536 } 537 538 if (tfco->ts_tim != NULL && 539 tfco->ts_tim != tim) { 540 PMD_DRV_LOG_LINE(ERR, 541 "Cannot set TS TIM, TIM is already set"); 542 return -EINVAL; 543 } 544 545 tfco->ts_tim = tim; 546 547 return 0; 548 } 549 550 int tfo_tim_get(void *tfo, void **tim) 551 { 552 struct tfc_object *tfco = (struct tfc_object *)tfo; 553 554 if (tfo == NULL) { 555 PMD_DRV_LOG_LINE(ERR, "Invalid tfo pointer"); 556 return -EINVAL; 557 } 558 if (tfco->signature != TFC_OBJ_SIGNATURE) { 559 PMD_DRV_LOG_LINE(ERR, "Invalid tfo object"); 560 return -EINVAL; 561 } 562 if (tim == NULL) { 563 PMD_DRV_LOG_LINE(ERR, "Invalid tim pointer to pointer"); 564 return -EINVAL; 565 } 566 if (tfco->ts_tim == NULL) { 567 /* ts tim could be null, no need to log error message */ 568 return -ENODEV; 569 } 570 571 *tim = tfco->ts_tim; 572 573 return 0; 574 } 575