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