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 /* Forward declarations */ 20 static int tf_dev_unbind_p4(struct tf *tfp); 21 static int tf_dev_unbind_p58(struct tf *tfp); 22 23 /** 24 * Resource Reservation Check function 25 * 26 * [in] count 27 * Number of module subtypes 28 * 29 * [in] cfg 30 * Pointer to rm element config 31 * 32 * [in] reservations 33 * Pointer to resource reservation array 34 * 35 * Returns 36 * - (n) number of tables in module that have non-zero reservation count. 37 */ 38 static int 39 tf_dev_reservation_check(uint16_t count, 40 struct tf_rm_element_cfg *cfg, 41 uint16_t *reservations) 42 { 43 uint16_t cnt = 0; 44 uint16_t *rm_num; 45 int i, j; 46 47 for (i = 0; i < TF_DIR_MAX; i++) { 48 rm_num = (uint16_t *)reservations + i * count; 49 for (j = 0; j < count; j++) { 50 if ((cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI || 51 cfg[j].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || 52 cfg[j].cfg_type == 53 TF_RM_ELEM_CFG_HCAPI_BA_PARENT || 54 cfg[j].cfg_type == 55 TF_RM_ELEM_CFG_HCAPI_BA_CHILD) && 56 rm_num[j] > 0) 57 cnt++; 58 } 59 } 60 61 return cnt; 62 } 63 64 /** 65 * Device specific bind function, WH+ 66 * 67 * [in] tfp 68 * Pointer to TF handle 69 * 70 * [in] shadow_copy 71 * Flag controlling shadow copy DB creation 72 * 73 * [in] resources 74 * Pointer to resource allocation information 75 * 76 * [out] dev_handle 77 * Device handle 78 * 79 * Returns 80 * - (0) if successful. 81 * - (-EINVAL) on parameter or internal failure. 82 */ 83 static int 84 tf_dev_bind_p4(struct tf *tfp, 85 bool shadow_copy, 86 struct tf_session_resources *resources, 87 struct tf_dev_info *dev_handle, 88 enum tf_wc_num_slice wc_num_slices) 89 { 90 int rc; 91 int frc; 92 int rsv_cnt; 93 bool no_rsv_flag = true; 94 struct tf_ident_cfg_parms ident_cfg; 95 struct tf_tbl_cfg_parms tbl_cfg; 96 struct tf_tcam_cfg_parms tcam_cfg; 97 struct tf_em_cfg_parms em_cfg; 98 struct tf_if_tbl_cfg_parms if_tbl_cfg; 99 struct tf_global_cfg_cfg_parms global_cfg; 100 struct tf_session *tfs; 101 102 /* Retrieve the session information */ 103 rc = tf_session_get_session_internal(tfp, &tfs); 104 if (rc) 105 return rc; 106 107 /* Initial function initialization */ 108 dev_handle->ops = &tf_dev_ops_p4_init; 109 110 /* Initialize the modules */ 111 112 rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX, 113 tf_ident_p4, 114 (uint16_t *)resources->ident_cnt); 115 if (rsv_cnt) { 116 ident_cfg.num_elements = TF_IDENT_TYPE_MAX; 117 ident_cfg.cfg = tf_ident_p4; 118 ident_cfg.shadow_copy = shadow_copy; 119 ident_cfg.resources = resources; 120 rc = tf_ident_bind(tfp, &ident_cfg); 121 if (rc) { 122 TFP_DRV_LOG(ERR, 123 "Identifier initialization failure\n"); 124 goto fail; 125 } 126 127 no_rsv_flag = false; 128 } 129 130 rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX, 131 tf_tbl_p4[TF_DIR_RX], 132 (uint16_t *)resources->tbl_cnt); 133 if (rsv_cnt) { 134 tbl_cfg.num_elements = TF_TBL_TYPE_MAX; 135 tbl_cfg.cfg = tf_tbl_p4[TF_DIR_RX]; 136 tbl_cfg.resources = resources; 137 rc = tf_tbl_bind(tfp, &tbl_cfg); 138 if (rc) { 139 TFP_DRV_LOG(ERR, 140 "Table initialization failure\n"); 141 goto fail; 142 } 143 144 no_rsv_flag = false; 145 } 146 147 rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX, 148 tf_tcam_p4, 149 (uint16_t *)resources->tcam_cnt); 150 if (rsv_cnt) { 151 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX; 152 tcam_cfg.cfg = tf_tcam_p4; 153 tcam_cfg.shadow_copy = shadow_copy; 154 tcam_cfg.resources = resources; 155 tcam_cfg.wc_num_slices = wc_num_slices; 156 #ifdef TF_TCAM_SHARED 157 rc = tf_tcam_shared_bind(tfp, &tcam_cfg); 158 #else /* !TF_TCAM_SHARED */ 159 rc = tf_tcam_bind(tfp, &tcam_cfg); 160 #endif 161 if (rc) { 162 TFP_DRV_LOG(ERR, 163 "TCAM initialization failure\n"); 164 goto fail; 165 } 166 no_rsv_flag = false; 167 } 168 169 /* 170 * EEM 171 */ 172 173 em_cfg.cfg = tf_em_ext_p4; 174 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 175 em_cfg.cfg, 176 (uint16_t *)resources->em_cnt); 177 if (rsv_cnt) { 178 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 179 em_cfg.resources = resources; 180 em_cfg.mem_type = TF_EEM_MEM_TYPE_HOST; 181 rc = tf_em_ext_common_bind(tfp, &em_cfg); 182 if (rc) { 183 TFP_DRV_LOG(ERR, 184 "EEM initialization failure\n"); 185 goto fail; 186 } 187 no_rsv_flag = false; 188 } 189 190 /* 191 * EM 192 */ 193 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 194 tf_em_int_p4, 195 (uint16_t *)resources->em_cnt); 196 if (rsv_cnt) { 197 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 198 em_cfg.cfg = tf_em_int_p4; 199 em_cfg.resources = resources; 200 em_cfg.mem_type = 0; /* Not used by EM */ 201 202 rc = tf_em_int_bind(tfp, &em_cfg); 203 if (rc) { 204 TFP_DRV_LOG(ERR, 205 "EM initialization failure\n"); 206 goto fail; 207 } 208 no_rsv_flag = false; 209 } 210 211 /* 212 * There is no rm reserved for any tables 213 * 214 */ 215 if (no_rsv_flag) { 216 TFP_DRV_LOG(ERR, 217 "No rm reserved for any tables\n"); 218 return -ENOMEM; 219 } 220 221 /* 222 * IF_TBL 223 */ 224 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX; 225 if_tbl_cfg.cfg = tf_if_tbl_p4; 226 if_tbl_cfg.shadow_copy = shadow_copy; 227 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg); 228 if (rc) { 229 TFP_DRV_LOG(ERR, 230 "IF Table initialization failure\n"); 231 goto fail; 232 } 233 234 if (!tf_session_is_shared_session(tfs)) { 235 /* 236 * GLOBAL_CFG 237 */ 238 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX; 239 global_cfg.cfg = tf_global_cfg_p4; 240 rc = tf_global_cfg_bind(tfp, &global_cfg); 241 if (rc) { 242 TFP_DRV_LOG(ERR, 243 "Global Cfg initialization failure\n"); 244 goto fail; 245 } 246 } 247 /* Final function initialization */ 248 dev_handle->ops = &tf_dev_ops_p4; 249 250 return 0; 251 252 fail: 253 /* Cleanup of already created modules */ 254 frc = tf_dev_unbind_p4(tfp); 255 if (frc) 256 return frc; 257 258 return rc; 259 } 260 261 /** 262 * Device specific unbind function, WH+ 263 * 264 * [in] tfp 265 * Pointer to TF handle 266 * 267 * Returns 268 * - (0) if successful. 269 * - (-EINVAL) on failure. 270 */ 271 static int 272 tf_dev_unbind_p4(struct tf *tfp) 273 { 274 int rc = 0; 275 bool fail = false; 276 struct tf_session *tfs; 277 278 /* Retrieve the session information */ 279 rc = tf_session_get_session_internal(tfp, &tfs); 280 if (rc) 281 return rc; 282 283 /* Unbind all the support modules. As this is only done on 284 * close we only report errors as everything has to be cleaned 285 * up regardless. 286 * 287 * In case of residuals TCAMs are cleaned up first as to 288 * invalidate the pipeline in a clean manner. 289 */ 290 #ifdef TF_TCAM_SHARED 291 rc = tf_tcam_shared_unbind(tfp); 292 #else /* !TF_TCAM_SHARED */ 293 rc = tf_tcam_unbind(tfp); 294 #endif /* TF_TCAM_SHARED */ 295 if (rc) { 296 TFP_DRV_LOG(INFO, 297 "Device unbind failed, TCAM\n"); 298 fail = true; 299 } 300 301 rc = tf_ident_unbind(tfp); 302 if (rc) { 303 TFP_DRV_LOG(INFO, 304 "Device unbind failed, Identifier\n"); 305 fail = true; 306 } 307 308 rc = tf_tbl_unbind(tfp); 309 if (rc) { 310 TFP_DRV_LOG(INFO, 311 "Device unbind failed, Table Type\n"); 312 fail = true; 313 } 314 315 rc = tf_em_ext_common_unbind(tfp); 316 if (rc) { 317 TFP_DRV_LOG(INFO, 318 "Device unbind failed, EEM\n"); 319 fail = true; 320 } 321 322 rc = tf_em_int_unbind(tfp); 323 if (rc) { 324 TFP_DRV_LOG(INFO, 325 "Device unbind failed, EM\n"); 326 fail = true; 327 } 328 329 if (!tf_session_is_shared_session(tfs)) { 330 rc = tf_if_tbl_unbind(tfp); 331 if (rc) { 332 TFP_DRV_LOG(INFO, 333 "Device unbind failed, IF Table Type\n"); 334 fail = true; 335 } 336 337 rc = tf_global_cfg_unbind(tfp); 338 if (rc) { 339 TFP_DRV_LOG(INFO, 340 "Device unbind failed, Global Cfg Type\n"); 341 fail = true; 342 } 343 } 344 345 if (fail) 346 return -1; 347 348 return rc; 349 } 350 351 /** 352 * Device specific bind function, THOR 353 * 354 * [in] tfp 355 * Pointer to TF handle 356 * 357 * [in] shadow_copy 358 * Flag controlling shadow copy DB creation 359 * 360 * [in] resources 361 * Pointer to resource allocation information 362 * 363 * [out] dev_handle 364 * Device handle 365 * 366 * Returns 367 * - (0) if successful. 368 * - (-EINVAL) on parameter or internal failure. 369 */ 370 static int 371 tf_dev_bind_p58(struct tf *tfp, 372 bool shadow_copy, 373 struct tf_session_resources *resources, 374 struct tf_dev_info *dev_handle, 375 enum tf_wc_num_slice wc_num_slices) 376 { 377 int rc; 378 int frc; 379 int rsv_cnt; 380 bool no_rsv_flag = true; 381 struct tf_ident_cfg_parms ident_cfg; 382 struct tf_tbl_cfg_parms tbl_cfg; 383 struct tf_tcam_cfg_parms tcam_cfg; 384 struct tf_em_cfg_parms em_cfg; 385 struct tf_if_tbl_cfg_parms if_tbl_cfg; 386 struct tf_global_cfg_cfg_parms global_cfg; 387 struct tf_session *tfs; 388 389 /* Initial function initialization */ 390 dev_handle->ops = &tf_dev_ops_p58_init; 391 392 /* Retrieve the session information */ 393 rc = tf_session_get_session_internal(tfp, &tfs); 394 if (rc) 395 return rc; 396 397 rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX, 398 tf_ident_p58, 399 (uint16_t *)resources->ident_cnt); 400 if (rsv_cnt) { 401 ident_cfg.num_elements = TF_IDENT_TYPE_MAX; 402 ident_cfg.cfg = tf_ident_p58; 403 ident_cfg.shadow_copy = shadow_copy; 404 ident_cfg.resources = resources; 405 rc = tf_ident_bind(tfp, &ident_cfg); 406 if (rc) { 407 TFP_DRV_LOG(ERR, 408 "Identifier initialization failure\n"); 409 goto fail; 410 } 411 no_rsv_flag = false; 412 } 413 414 rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX, 415 tf_tbl_p58[TF_DIR_RX], 416 (uint16_t *)resources->tbl_cnt); 417 rsv_cnt += tf_dev_reservation_check(TF_TBL_TYPE_MAX, 418 tf_tbl_p58[TF_DIR_TX], 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[TF_DIR_RX]; 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