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[TF_DIR_RX], 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[TF_DIR_RX]; 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[TF_DIR_RX], 419 (uint16_t *)resources->tbl_cnt); 420 rsv_cnt += tf_dev_reservation_check(TF_TBL_TYPE_MAX, 421 tf_tbl_p58[TF_DIR_TX], 422 (uint16_t *)resources->tbl_cnt); 423 if (rsv_cnt) { 424 tbl_cfg.num_elements = TF_TBL_TYPE_MAX; 425 tbl_cfg.cfg = tf_tbl_p58[TF_DIR_RX]; 426 tbl_cfg.resources = resources; 427 rc = tf_tbl_bind(tfp, &tbl_cfg); 428 if (rc) { 429 TFP_DRV_LOG(ERR, 430 "Table initialization failure\n"); 431 goto fail; 432 } 433 no_rsv_flag = false; 434 435 rc = tf_tbl_sram_bind(tfp); 436 if (rc) { 437 TFP_DRV_LOG(ERR, 438 "SRAM table initialization failure\n"); 439 goto fail; 440 } 441 } 442 443 rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX, 444 tf_tcam_p58, 445 (uint16_t *)resources->tcam_cnt); 446 if (rsv_cnt) { 447 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX; 448 tcam_cfg.cfg = tf_tcam_p58; 449 tcam_cfg.shadow_copy = shadow_copy; 450 tcam_cfg.resources = resources; 451 tcam_cfg.wc_num_slices = wc_num_slices; 452 #ifdef TF_TCAM_SHARED 453 rc = tf_tcam_shared_bind(tfp, &tcam_cfg); 454 #else /* !TF_TCAM_SHARED */ 455 rc = tf_tcam_bind(tfp, &tcam_cfg); 456 #endif 457 if (rc) { 458 TFP_DRV_LOG(ERR, 459 "TCAM initialization failure\n"); 460 goto fail; 461 } 462 no_rsv_flag = false; 463 } 464 465 /* 466 * EM 467 */ 468 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 469 tf_em_int_p58, 470 (uint16_t *)resources->em_cnt); 471 if (rsv_cnt) { 472 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 473 em_cfg.cfg = tf_em_int_p58; 474 em_cfg.resources = resources; 475 em_cfg.mem_type = 0; /* Not used by EM */ 476 477 rc = tf_em_int_bind(tfp, &em_cfg); 478 if (rc) { 479 TFP_DRV_LOG(ERR, 480 "EM initialization failure\n"); 481 goto fail; 482 } 483 no_rsv_flag = false; 484 } 485 486 /* 487 * There is no rm reserved for any tables 488 * 489 */ 490 if (no_rsv_flag) { 491 TFP_DRV_LOG(ERR, 492 "No rm reserved for any tables\n"); 493 return -ENOMEM; 494 } 495 496 /* 497 * IF_TBL 498 */ 499 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX; 500 if_tbl_cfg.cfg = tf_if_tbl_p58; 501 if_tbl_cfg.shadow_copy = shadow_copy; 502 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg); 503 if (rc) { 504 TFP_DRV_LOG(ERR, 505 "IF Table initialization failure\n"); 506 goto fail; 507 } 508 509 if (!tf_session_is_shared_session(tfs)) { 510 /* 511 * GLOBAL_CFG 512 */ 513 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX; 514 global_cfg.cfg = tf_global_cfg_p58; 515 rc = tf_global_cfg_bind(tfp, &global_cfg); 516 if (rc) { 517 TFP_DRV_LOG(ERR, 518 "Global Cfg initialization failure\n"); 519 goto fail; 520 } 521 } 522 523 /* Final function initialization */ 524 dev_handle->ops = &tf_dev_ops_p58; 525 526 return 0; 527 528 fail: 529 /* Cleanup of already created modules */ 530 frc = tf_dev_unbind_p58(tfp); 531 if (frc) 532 return frc; 533 534 return rc; 535 } 536 537 /** 538 * Device specific unbind function, THOR 539 * 540 * [in] tfp 541 * Pointer to TF handle 542 * 543 * Returns 544 * - (0) if successful. 545 * - (-EINVAL) on failure. 546 */ 547 static int 548 tf_dev_unbind_p58(struct tf *tfp) 549 { 550 int rc = 0; 551 bool fail = false; 552 struct tf_session *tfs; 553 554 /* Retrieve the session information */ 555 rc = tf_session_get_session_internal(tfp, &tfs); 556 if (rc) 557 return rc; 558 559 /* Unbind all the support modules. As this is only done on 560 * close we only report errors as everything has to be cleaned 561 * up regardless. 562 * 563 * In case of residuals TCAMs are cleaned up first as to 564 * invalidate the pipeline in a clean manner. 565 */ 566 #ifdef TF_TCAM_SHARED 567 rc = tf_tcam_shared_unbind(tfp); 568 #else /* !TF_TCAM_SHARED */ 569 rc = tf_tcam_unbind(tfp); 570 #endif /* TF_TCAM_SHARED */ 571 if (rc) { 572 TFP_DRV_LOG(INFO, 573 "Device unbind failed, TCAM\n"); 574 fail = true; 575 } 576 577 rc = tf_ident_unbind(tfp); 578 if (rc) { 579 TFP_DRV_LOG(INFO, 580 "Device unbind failed, Identifier\n"); 581 fail = true; 582 } 583 584 /* Unbind the SRAM table prior to table as the table manager 585 * owns and frees the table DB while the SRAM table manager owns 586 * and manages it's internal data structures. SRAM table manager 587 * relies on the table rm_db to exist. 588 */ 589 rc = tf_tbl_sram_unbind(tfp); 590 if (rc) { 591 TFP_DRV_LOG(ERR, 592 "Device unbind failed, SRAM table\n"); 593 fail = true; 594 } 595 596 rc = tf_tbl_unbind(tfp); 597 if (rc) { 598 TFP_DRV_LOG(INFO, 599 "Device unbind failed, Table Type\n"); 600 fail = true; 601 } 602 603 rc = tf_em_int_unbind(tfp); 604 if (rc) { 605 TFP_DRV_LOG(INFO, 606 "Device unbind failed, EM\n"); 607 fail = true; 608 } 609 610 rc = tf_if_tbl_unbind(tfp); 611 if (rc) { 612 TFP_DRV_LOG(ERR, 613 "Device unbind failed, IF Table Type\n"); 614 fail = true; 615 } 616 617 if (!tf_session_is_shared_session(tfs)) { 618 rc = tf_global_cfg_unbind(tfp); 619 if (rc) { 620 TFP_DRV_LOG(ERR, 621 "Device unbind failed, Global Cfg Type\n"); 622 fail = true; 623 } 624 } 625 626 if (fail) 627 return -1; 628 629 return rc; 630 } 631 632 int 633 tf_dev_bind(struct tf *tfp __rte_unused, 634 enum tf_device_type type, 635 bool shadow_copy, 636 struct tf_session_resources *resources, 637 uint16_t wc_num_slices, 638 struct tf_dev_info *dev_handle) 639 { 640 switch (type) { 641 case TF_DEVICE_TYPE_WH: 642 case TF_DEVICE_TYPE_SR: 643 dev_handle->type = type; 644 return tf_dev_bind_p4(tfp, 645 shadow_copy, 646 resources, 647 dev_handle, 648 wc_num_slices); 649 case TF_DEVICE_TYPE_THOR: 650 dev_handle->type = type; 651 return tf_dev_bind_p58(tfp, 652 shadow_copy, 653 resources, 654 dev_handle, 655 wc_num_slices); 656 default: 657 TFP_DRV_LOG(ERR, 658 "No such device\n"); 659 return -ENODEV; 660 } 661 } 662 663 int 664 tf_dev_bind_ops(enum tf_device_type type, 665 struct tf_dev_info *dev_handle) 666 { 667 switch (type) { 668 case TF_DEVICE_TYPE_WH: 669 case TF_DEVICE_TYPE_SR: 670 dev_handle->ops = &tf_dev_ops_p4_init; 671 break; 672 case TF_DEVICE_TYPE_THOR: 673 dev_handle->ops = &tf_dev_ops_p58_init; 674 break; 675 default: 676 TFP_DRV_LOG(ERR, 677 "No such device\n"); 678 return -ENODEV; 679 } 680 681 return 0; 682 } 683 684 int 685 tf_dev_unbind(struct tf *tfp, 686 struct tf_dev_info *dev_handle) 687 { 688 switch (dev_handle->type) { 689 case TF_DEVICE_TYPE_WH: 690 case TF_DEVICE_TYPE_SR: 691 return tf_dev_unbind_p4(tfp); 692 case TF_DEVICE_TYPE_THOR: 693 return tf_dev_unbind_p58(tfp); 694 default: 695 TFP_DRV_LOG(ERR, 696 "No such device\n"); 697 return -ENODEV; 698 } 699 } 700