1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include "tf_device.h" 7 #include "tf_device_p4.h" 8 #include "tf_device_p58.h" 9 #include "tfp.h" 10 #include "tf_em.h" 11 #include "tf_rm.h" 12 #include "tf_tcam_shared.h" 13 #include "tf_tbl_sram.h" 14 15 struct tf; 16 17 /* Forward declarations */ 18 static int tf_dev_unbind_p4(struct tf *tfp); 19 static int tf_dev_unbind_p58(struct tf *tfp); 20 21 /** 22 * Resource Reservation Check function 23 * 24 * [in] count 25 * Number of module subtypes 26 * 27 * [in] cfg 28 * Pointer to rm element config 29 * 30 * [in] reservations 31 * Pointer to resource reservation array 32 * 33 * Returns 34 * - (n) number of tables in module that have non-zero reservation count. 35 */ 36 static int 37 tf_dev_reservation_check(uint16_t count, 38 struct tf_rm_element_cfg *cfg, 39 uint16_t *reservations) 40 { 41 uint16_t cnt = 0; 42 uint16_t *rm_num; 43 int i, j; 44 45 for (i = 0; i < TF_DIR_MAX; i++) { 46 rm_num = (uint16_t *)reservations + i * count; 47 for (j = 0; j < count; j++) { 48 if ((cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI || 49 cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || 50 cfg[j].cfg_type == 51 TF_RM_ELEM_CFG_HCAPI_BA_PARENT || 52 cfg[j].cfg_type == 53 TF_RM_ELEM_CFG_HCAPI_BA_CHILD) && 54 rm_num[j] > 0) 55 cnt++; 56 } 57 } 58 59 return cnt; 60 } 61 62 /** 63 * Device specific bind function, WH+ 64 * 65 * [in] tfp 66 * Pointer to TF handle 67 * 68 * [in] resources 69 * Pointer to resource allocation information 70 * 71 * [out] dev_handle 72 * Device handle 73 * 74 * Returns 75 * - (0) if successful. 76 * - (-EINVAL) on parameter or internal failure. 77 */ 78 static int 79 tf_dev_bind_p4(struct tf *tfp, 80 struct tf_session_resources *resources, 81 struct tf_dev_info *dev_handle, 82 enum tf_wc_num_slice wc_num_slices) 83 { 84 int rc; 85 int frc; 86 int rsv_cnt; 87 bool no_rsv_flag = true; 88 struct tf_ident_cfg_parms ident_cfg; 89 struct tf_tbl_cfg_parms tbl_cfg; 90 struct tf_tcam_cfg_parms tcam_cfg; 91 struct tf_em_cfg_parms em_cfg; 92 struct tf_if_tbl_cfg_parms if_tbl_cfg; 93 struct tf_global_cfg_cfg_parms global_cfg; 94 struct tf_session *tfs; 95 96 /* Retrieve the session information */ 97 rc = tf_session_get_session_internal(tfp, &tfs); 98 if (rc) 99 return rc; 100 101 /* Initial function initialization */ 102 dev_handle->ops = &tf_dev_ops_p4_init; 103 104 /* Initialize the modules */ 105 106 rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX, 107 tf_ident_p4, 108 (uint16_t *)resources->ident_cnt); 109 if (rsv_cnt) { 110 ident_cfg.num_elements = TF_IDENT_TYPE_MAX; 111 ident_cfg.cfg = tf_ident_p4; 112 ident_cfg.resources = resources; 113 rc = tf_ident_bind(tfp, &ident_cfg); 114 if (rc) { 115 TFP_DRV_LOG(ERR, 116 "Identifier initialization failure\n"); 117 goto fail; 118 } 119 120 no_rsv_flag = false; 121 } 122 123 rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX, 124 tf_tbl_p4[TF_DIR_RX], 125 (uint16_t *)resources->tbl_cnt); 126 if (rsv_cnt) { 127 tbl_cfg.num_elements = TF_TBL_TYPE_MAX; 128 tbl_cfg.cfg = tf_tbl_p4[TF_DIR_RX]; 129 tbl_cfg.resources = resources; 130 rc = tf_tbl_bind(tfp, &tbl_cfg); 131 if (rc) { 132 TFP_DRV_LOG(ERR, 133 "Table initialization failure\n"); 134 goto fail; 135 } 136 137 no_rsv_flag = false; 138 } 139 140 rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX, 141 tf_tcam_p4, 142 (uint16_t *)resources->tcam_cnt); 143 if (rsv_cnt) { 144 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX; 145 tcam_cfg.cfg = tf_tcam_p4; 146 tcam_cfg.resources = resources; 147 tcam_cfg.wc_num_slices = wc_num_slices; 148 rc = tf_tcam_shared_bind(tfp, &tcam_cfg); 149 if (rc) { 150 TFP_DRV_LOG(ERR, 151 "TCAM initialization failure\n"); 152 goto fail; 153 } 154 no_rsv_flag = false; 155 } 156 157 /* 158 * EEM 159 */ 160 161 em_cfg.cfg = tf_em_ext_p4; 162 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 163 em_cfg.cfg, 164 (uint16_t *)resources->em_cnt); 165 if (rsv_cnt) { 166 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 167 em_cfg.resources = resources; 168 em_cfg.mem_type = TF_EEM_MEM_TYPE_HOST; 169 rc = tf_em_ext_common_bind(tfp, &em_cfg); 170 if (rc) { 171 TFP_DRV_LOG(ERR, 172 "EEM initialization failure\n"); 173 goto fail; 174 } 175 no_rsv_flag = false; 176 } 177 178 /* 179 * EM 180 */ 181 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 182 tf_em_int_p4, 183 (uint16_t *)resources->em_cnt); 184 if (rsv_cnt) { 185 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 186 em_cfg.cfg = tf_em_int_p4; 187 em_cfg.resources = resources; 188 em_cfg.mem_type = 0; /* Not used by EM */ 189 190 rc = tf_em_int_bind(tfp, &em_cfg); 191 if (rc) { 192 TFP_DRV_LOG(ERR, 193 "EM initialization failure\n"); 194 goto fail; 195 } 196 no_rsv_flag = false; 197 } 198 199 /* 200 * There is no rm reserved for any tables 201 * 202 */ 203 if (no_rsv_flag) { 204 TFP_DRV_LOG(ERR, 205 "No rm reserved for any tables\n"); 206 return -ENOMEM; 207 } 208 209 /* 210 * IF_TBL 211 */ 212 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX; 213 if_tbl_cfg.cfg = tf_if_tbl_p4; 214 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg); 215 if (rc) { 216 TFP_DRV_LOG(ERR, 217 "IF Table initialization failure\n"); 218 goto fail; 219 } 220 221 if (!tf_session_is_shared_session(tfs)) { 222 /* 223 * GLOBAL_CFG 224 */ 225 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX; 226 global_cfg.cfg = tf_global_cfg_p4; 227 rc = tf_global_cfg_bind(tfp, &global_cfg); 228 if (rc) { 229 TFP_DRV_LOG(ERR, 230 "Global Cfg initialization failure\n"); 231 goto fail; 232 } 233 } 234 /* Final function initialization */ 235 dev_handle->ops = &tf_dev_ops_p4; 236 237 return 0; 238 239 fail: 240 /* Cleanup of already created modules */ 241 frc = tf_dev_unbind_p4(tfp); 242 if (frc) 243 return frc; 244 245 return rc; 246 } 247 248 /** 249 * Device specific unbind function, WH+ 250 * 251 * [in] tfp 252 * Pointer to TF handle 253 * 254 * Returns 255 * - (0) if successful. 256 * - (-EINVAL) on failure. 257 */ 258 static int 259 tf_dev_unbind_p4(struct tf *tfp) 260 { 261 int rc = 0; 262 bool fail = false; 263 struct tf_session *tfs; 264 265 /* Retrieve the session information */ 266 rc = tf_session_get_session_internal(tfp, &tfs); 267 if (rc) 268 return rc; 269 270 /* Unbind all the support modules. As this is only done on 271 * close we only report errors as everything has to be cleaned 272 * up regardless. 273 * 274 * In case of residuals TCAMs are cleaned up first as to 275 * invalidate the pipeline in a clean manner. 276 */ 277 rc = tf_tcam_shared_unbind(tfp); 278 if (rc) { 279 TFP_DRV_LOG(INFO, 280 "Device unbind failed, TCAM\n"); 281 fail = true; 282 } 283 284 rc = tf_ident_unbind(tfp); 285 if (rc) { 286 TFP_DRV_LOG(INFO, 287 "Device unbind failed, Identifier\n"); 288 fail = true; 289 } 290 291 rc = tf_tbl_unbind(tfp); 292 if (rc) { 293 TFP_DRV_LOG(INFO, 294 "Device unbind failed, Table Type\n"); 295 fail = true; 296 } 297 298 rc = tf_em_ext_common_unbind(tfp); 299 if (rc) { 300 TFP_DRV_LOG(INFO, 301 "Device unbind failed, EEM\n"); 302 fail = true; 303 } 304 305 rc = tf_em_int_unbind(tfp); 306 if (rc) { 307 TFP_DRV_LOG(INFO, 308 "Device unbind failed, EM\n"); 309 fail = true; 310 } 311 312 if (!tf_session_is_shared_session(tfs)) { 313 rc = tf_if_tbl_unbind(tfp); 314 if (rc) { 315 TFP_DRV_LOG(INFO, 316 "Device unbind failed, IF Table Type\n"); 317 fail = true; 318 } 319 320 rc = tf_global_cfg_unbind(tfp); 321 if (rc) { 322 TFP_DRV_LOG(INFO, 323 "Device unbind failed, Global Cfg Type\n"); 324 fail = true; 325 } 326 } 327 328 if (fail) 329 return -1; 330 331 return rc; 332 } 333 334 /** 335 * Device specific bind function, P5 336 * 337 * [in] tfp 338 * Pointer to TF handle 339 * 340 * [in] resources 341 * Pointer to resource allocation information 342 * 343 * [out] dev_handle 344 * Device handle 345 * 346 * Returns 347 * - (0) if successful. 348 * - (-EINVAL) on parameter or internal failure. 349 */ 350 static int 351 tf_dev_bind_p58(struct tf *tfp, 352 struct tf_session_resources *resources, 353 struct tf_dev_info *dev_handle, 354 enum tf_wc_num_slice wc_num_slices) 355 { 356 int rc; 357 int frc; 358 int rsv_cnt; 359 bool no_rsv_flag = true; 360 struct tf_ident_cfg_parms ident_cfg; 361 struct tf_tbl_cfg_parms tbl_cfg; 362 struct tf_tcam_cfg_parms tcam_cfg; 363 struct tf_em_cfg_parms em_cfg; 364 struct tf_if_tbl_cfg_parms if_tbl_cfg; 365 struct tf_global_cfg_cfg_parms global_cfg; 366 struct tf_session *tfs; 367 368 /* Initial function initialization */ 369 dev_handle->ops = &tf_dev_ops_p58_init; 370 371 /* Retrieve the session information */ 372 rc = tf_session_get_session_internal(tfp, &tfs); 373 if (rc) 374 return rc; 375 376 rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX, 377 tf_ident_p58, 378 (uint16_t *)resources->ident_cnt); 379 if (rsv_cnt) { 380 ident_cfg.num_elements = TF_IDENT_TYPE_MAX; 381 ident_cfg.cfg = tf_ident_p58; 382 ident_cfg.resources = resources; 383 rc = tf_ident_bind(tfp, &ident_cfg); 384 if (rc) { 385 TFP_DRV_LOG(ERR, 386 "Identifier initialization failure\n"); 387 goto fail; 388 } 389 no_rsv_flag = false; 390 } 391 392 rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX, 393 tf_tbl_p58[TF_DIR_RX], 394 (uint16_t *)resources->tbl_cnt); 395 rsv_cnt += tf_dev_reservation_check(TF_TBL_TYPE_MAX, 396 tf_tbl_p58[TF_DIR_TX], 397 (uint16_t *)resources->tbl_cnt); 398 if (rsv_cnt) { 399 tbl_cfg.num_elements = TF_TBL_TYPE_MAX; 400 tbl_cfg.cfg = tf_tbl_p58[TF_DIR_RX]; 401 tbl_cfg.resources = resources; 402 rc = tf_tbl_bind(tfp, &tbl_cfg); 403 if (rc) { 404 TFP_DRV_LOG(ERR, 405 "Table initialization failure\n"); 406 goto fail; 407 } 408 no_rsv_flag = false; 409 410 rc = tf_tbl_sram_bind(tfp); 411 if (rc) { 412 TFP_DRV_LOG(ERR, 413 "SRAM table initialization failure\n"); 414 goto fail; 415 } 416 } 417 418 rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX, 419 tf_tcam_p58, 420 (uint16_t *)resources->tcam_cnt); 421 if (rsv_cnt) { 422 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX; 423 tcam_cfg.cfg = tf_tcam_p58; 424 tcam_cfg.resources = resources; 425 tcam_cfg.wc_num_slices = wc_num_slices; 426 rc = tf_tcam_shared_bind(tfp, &tcam_cfg); 427 if (rc) { 428 TFP_DRV_LOG(ERR, 429 "TCAM initialization failure\n"); 430 goto fail; 431 } 432 no_rsv_flag = false; 433 } 434 435 /* 436 * EM 437 */ 438 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 439 tf_em_int_p58, 440 (uint16_t *)resources->em_cnt); 441 if (rsv_cnt) { 442 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 443 em_cfg.cfg = tf_em_int_p58; 444 em_cfg.resources = resources; 445 em_cfg.mem_type = 0; /* Not used by EM */ 446 447 rc = tf_em_int_bind(tfp, &em_cfg); 448 if (rc) { 449 TFP_DRV_LOG(ERR, 450 "EM initialization failure\n"); 451 goto fail; 452 } 453 no_rsv_flag = false; 454 } 455 456 /* 457 * There is no rm reserved for any tables 458 * 459 */ 460 if (no_rsv_flag) { 461 TFP_DRV_LOG(ERR, 462 "No rm reserved for any tables\n"); 463 return -ENOMEM; 464 } 465 466 /* 467 * IF_TBL 468 */ 469 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX; 470 if_tbl_cfg.cfg = tf_if_tbl_p58; 471 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg); 472 if (rc) { 473 TFP_DRV_LOG(ERR, 474 "IF Table initialization failure\n"); 475 goto fail; 476 } 477 478 if (!tf_session_is_shared_session(tfs)) { 479 /* 480 * GLOBAL_CFG 481 */ 482 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX; 483 global_cfg.cfg = tf_global_cfg_p58; 484 rc = tf_global_cfg_bind(tfp, &global_cfg); 485 if (rc) { 486 TFP_DRV_LOG(ERR, 487 "Global Cfg initialization failure\n"); 488 goto fail; 489 } 490 } 491 492 /* Final function initialization */ 493 dev_handle->ops = &tf_dev_ops_p58; 494 495 return 0; 496 497 fail: 498 /* Cleanup of already created modules */ 499 frc = tf_dev_unbind_p58(tfp); 500 if (frc) 501 return frc; 502 503 return rc; 504 } 505 506 /** 507 * Device specific unbind function, P5 508 * 509 * [in] tfp 510 * Pointer to TF handle 511 * 512 * Returns 513 * - (0) if successful. 514 * - (-EINVAL) on failure. 515 */ 516 static int 517 tf_dev_unbind_p58(struct tf *tfp) 518 { 519 int rc = 0; 520 bool fail = false; 521 struct tf_session *tfs; 522 523 /* Retrieve the session information */ 524 rc = tf_session_get_session_internal(tfp, &tfs); 525 if (rc) 526 return rc; 527 528 /* Unbind all the support modules. As this is only done on 529 * close we only report errors as everything has to be cleaned 530 * up regardless. 531 * 532 * In case of residuals TCAMs are cleaned up first as to 533 * invalidate the pipeline in a clean manner. 534 */ 535 rc = tf_tcam_shared_unbind(tfp); 536 if (rc) { 537 TFP_DRV_LOG(INFO, 538 "Device unbind failed, TCAM\n"); 539 fail = true; 540 } 541 542 rc = tf_ident_unbind(tfp); 543 if (rc) { 544 TFP_DRV_LOG(INFO, 545 "Device unbind failed, Identifier\n"); 546 fail = true; 547 } 548 549 /* Unbind the SRAM table prior to table as the table manager 550 * owns and frees the table DB while the SRAM table manager owns 551 * and manages it's internal data structures. SRAM table manager 552 * relies on the table rm_db to exist. 553 */ 554 rc = tf_tbl_sram_unbind(tfp); 555 if (rc) { 556 TFP_DRV_LOG(ERR, 557 "Device unbind failed, SRAM table\n"); 558 fail = true; 559 } 560 561 rc = tf_tbl_unbind(tfp); 562 if (rc) { 563 TFP_DRV_LOG(INFO, 564 "Device unbind failed, Table Type\n"); 565 fail = true; 566 } 567 568 rc = tf_em_int_unbind(tfp); 569 if (rc) { 570 TFP_DRV_LOG(INFO, 571 "Device unbind failed, EM\n"); 572 fail = true; 573 } 574 575 rc = tf_if_tbl_unbind(tfp); 576 if (rc) { 577 TFP_DRV_LOG(ERR, 578 "Device unbind failed, IF Table Type\n"); 579 fail = true; 580 } 581 582 if (!tf_session_is_shared_session(tfs)) { 583 rc = tf_global_cfg_unbind(tfp); 584 if (rc) { 585 TFP_DRV_LOG(ERR, 586 "Device unbind failed, Global Cfg Type\n"); 587 fail = true; 588 } 589 } 590 591 if (fail) 592 return -1; 593 594 return rc; 595 } 596 597 int 598 tf_dev_bind(struct tf *tfp __rte_unused, 599 enum tf_device_type type, 600 struct tf_session_resources *resources, 601 uint16_t wc_num_slices, 602 struct tf_dev_info *dev_handle) 603 { 604 switch (type) { 605 case TF_DEVICE_TYPE_P4: 606 case TF_DEVICE_TYPE_SR: 607 dev_handle->type = type; 608 return tf_dev_bind_p4(tfp, 609 resources, 610 dev_handle, 611 wc_num_slices); 612 case TF_DEVICE_TYPE_P5: 613 dev_handle->type = type; 614 return tf_dev_bind_p58(tfp, 615 resources, 616 dev_handle, 617 wc_num_slices); 618 default: 619 TFP_DRV_LOG(ERR, 620 "No such device\n"); 621 return -ENODEV; 622 } 623 } 624 625 int 626 tf_dev_bind_ops(enum tf_device_type type, 627 struct tf_dev_info *dev_handle) 628 { 629 switch (type) { 630 case TF_DEVICE_TYPE_P4: 631 case TF_DEVICE_TYPE_SR: 632 dev_handle->ops = &tf_dev_ops_p4_init; 633 break; 634 case TF_DEVICE_TYPE_P5: 635 dev_handle->ops = &tf_dev_ops_p58_init; 636 break; 637 default: 638 TFP_DRV_LOG(ERR, 639 "No such device\n"); 640 return -ENODEV; 641 } 642 643 return 0; 644 } 645 646 int 647 tf_dev_unbind(struct tf *tfp, 648 struct tf_dev_info *dev_handle) 649 { 650 switch (dev_handle->type) { 651 case TF_DEVICE_TYPE_P4: 652 case TF_DEVICE_TYPE_SR: 653 return tf_dev_unbind_p4(tfp); 654 case TF_DEVICE_TYPE_P5: 655 return tf_dev_unbind_p58(tfp); 656 default: 657 TFP_DRV_LOG(ERR, 658 "No such device\n"); 659 return -ENODEV; 660 } 661 } 662