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