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 * EM 158 */ 159 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 160 tf_em_int_p4, 161 (uint16_t *)resources->em_cnt); 162 if (rsv_cnt) { 163 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 164 em_cfg.cfg = tf_em_int_p4; 165 em_cfg.resources = resources; 166 em_cfg.mem_type = 0; /* Not used by EM */ 167 168 rc = tf_em_int_bind(tfp, &em_cfg); 169 if (rc) { 170 TFP_DRV_LOG(ERR, 171 "EM initialization failure\n"); 172 goto fail; 173 } 174 no_rsv_flag = false; 175 } 176 177 /* 178 * There is no rm reserved for any tables 179 * 180 */ 181 if (no_rsv_flag) { 182 TFP_DRV_LOG(ERR, 183 "No rm reserved for any tables\n"); 184 return -ENOMEM; 185 } 186 187 /* 188 * IF_TBL 189 */ 190 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX; 191 if_tbl_cfg.cfg = tf_if_tbl_p4; 192 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg); 193 if (rc) { 194 TFP_DRV_LOG(ERR, 195 "IF Table initialization failure\n"); 196 goto fail; 197 } 198 199 if (!tf_session_is_shared_session(tfs)) { 200 /* 201 * GLOBAL_CFG 202 */ 203 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX; 204 global_cfg.cfg = tf_global_cfg_p4; 205 rc = tf_global_cfg_bind(tfp, &global_cfg); 206 if (rc) { 207 TFP_DRV_LOG(ERR, 208 "Global Cfg initialization failure\n"); 209 goto fail; 210 } 211 } 212 /* Final function initialization */ 213 dev_handle->ops = &tf_dev_ops_p4; 214 215 return 0; 216 217 fail: 218 /* Cleanup of already created modules */ 219 frc = tf_dev_unbind_p4(tfp); 220 if (frc) 221 return frc; 222 223 return rc; 224 } 225 226 /** 227 * Device specific unbind function, WH+ 228 * 229 * [in] tfp 230 * Pointer to TF handle 231 * 232 * Returns 233 * - (0) if successful. 234 * - (-EINVAL) on failure. 235 */ 236 static int 237 tf_dev_unbind_p4(struct tf *tfp) 238 { 239 int rc = 0; 240 bool fail = false; 241 struct tf_session *tfs; 242 243 /* Retrieve the session information */ 244 rc = tf_session_get_session_internal(tfp, &tfs); 245 if (rc) 246 return rc; 247 248 /* Unbind all the support modules. As this is only done on 249 * close we only report errors as everything has to be cleaned 250 * up regardless. 251 * 252 * In case of residuals TCAMs are cleaned up first as to 253 * invalidate the pipeline in a clean manner. 254 */ 255 rc = tf_tcam_shared_unbind(tfp); 256 if (rc) { 257 TFP_DRV_LOG(INFO, 258 "Device unbind failed, TCAM\n"); 259 fail = true; 260 } 261 262 rc = tf_ident_unbind(tfp); 263 if (rc) { 264 TFP_DRV_LOG(INFO, 265 "Device unbind failed, Identifier\n"); 266 fail = true; 267 } 268 269 rc = tf_tbl_unbind(tfp); 270 if (rc) { 271 TFP_DRV_LOG(INFO, 272 "Device unbind failed, Table Type\n"); 273 fail = true; 274 } 275 rc = tf_em_int_unbind(tfp); 276 if (rc) { 277 TFP_DRV_LOG(INFO, 278 "Device unbind failed, EM\n"); 279 fail = true; 280 } 281 282 if (!tf_session_is_shared_session(tfs)) { 283 rc = tf_if_tbl_unbind(tfp); 284 if (rc) { 285 TFP_DRV_LOG(INFO, 286 "Device unbind failed, IF Table Type\n"); 287 fail = true; 288 } 289 290 rc = tf_global_cfg_unbind(tfp); 291 if (rc) { 292 TFP_DRV_LOG(INFO, 293 "Device unbind failed, Global Cfg Type\n"); 294 fail = true; 295 } 296 } 297 298 if (fail) 299 return -1; 300 301 return rc; 302 } 303 304 /** 305 * Device specific bind function, P5 306 * 307 * [in] tfp 308 * Pointer to TF handle 309 * 310 * [in] resources 311 * Pointer to resource allocation information 312 * 313 * [out] dev_handle 314 * Device handle 315 * 316 * Returns 317 * - (0) if successful. 318 * - (-EINVAL) on parameter or internal failure. 319 */ 320 static int 321 tf_dev_bind_p58(struct tf *tfp, 322 struct tf_session_resources *resources, 323 struct tf_dev_info *dev_handle, 324 enum tf_wc_num_slice wc_num_slices) 325 { 326 int rc; 327 int frc; 328 int rsv_cnt; 329 bool no_rsv_flag = true; 330 struct tf_ident_cfg_parms ident_cfg; 331 struct tf_tbl_cfg_parms tbl_cfg; 332 struct tf_tcam_cfg_parms tcam_cfg; 333 struct tf_em_cfg_parms em_cfg; 334 struct tf_if_tbl_cfg_parms if_tbl_cfg; 335 struct tf_global_cfg_cfg_parms global_cfg; 336 struct tf_session *tfs; 337 338 /* Initial function initialization */ 339 dev_handle->ops = &tf_dev_ops_p58_init; 340 341 /* Retrieve the session information */ 342 rc = tf_session_get_session_internal(tfp, &tfs); 343 if (rc) 344 return rc; 345 346 rsv_cnt = tf_dev_reservation_check(TF_IDENT_TYPE_MAX, 347 tf_ident_p58, 348 (uint16_t *)resources->ident_cnt); 349 if (rsv_cnt) { 350 ident_cfg.num_elements = TF_IDENT_TYPE_MAX; 351 ident_cfg.cfg = tf_ident_p58; 352 ident_cfg.resources = resources; 353 rc = tf_ident_bind(tfp, &ident_cfg); 354 if (rc) { 355 TFP_DRV_LOG(ERR, 356 "Identifier initialization failure\n"); 357 goto fail; 358 } 359 no_rsv_flag = false; 360 } 361 362 rsv_cnt = tf_dev_reservation_check(TF_TBL_TYPE_MAX, 363 tf_tbl_p58[TF_DIR_RX], 364 (uint16_t *)resources->tbl_cnt); 365 rsv_cnt += tf_dev_reservation_check(TF_TBL_TYPE_MAX, 366 tf_tbl_p58[TF_DIR_TX], 367 (uint16_t *)resources->tbl_cnt); 368 if (rsv_cnt) { 369 tbl_cfg.num_elements = TF_TBL_TYPE_MAX; 370 tbl_cfg.cfg = tf_tbl_p58[TF_DIR_RX]; 371 tbl_cfg.resources = resources; 372 rc = tf_tbl_bind(tfp, &tbl_cfg); 373 if (rc) { 374 TFP_DRV_LOG(ERR, 375 "Table initialization failure\n"); 376 goto fail; 377 } 378 no_rsv_flag = false; 379 380 rc = tf_tbl_sram_bind(tfp); 381 if (rc) { 382 TFP_DRV_LOG(ERR, 383 "SRAM table initialization failure\n"); 384 goto fail; 385 } 386 } 387 388 rsv_cnt = tf_dev_reservation_check(TF_TCAM_TBL_TYPE_MAX, 389 tf_tcam_p58, 390 (uint16_t *)resources->tcam_cnt); 391 if (rsv_cnt) { 392 tcam_cfg.num_elements = TF_TCAM_TBL_TYPE_MAX; 393 tcam_cfg.cfg = tf_tcam_p58; 394 tcam_cfg.resources = resources; 395 tcam_cfg.wc_num_slices = wc_num_slices; 396 rc = tf_tcam_shared_bind(tfp, &tcam_cfg); 397 if (rc) { 398 TFP_DRV_LOG(ERR, 399 "TCAM initialization failure\n"); 400 goto fail; 401 } 402 no_rsv_flag = false; 403 } 404 405 /* 406 * EM 407 */ 408 rsv_cnt = tf_dev_reservation_check(TF_EM_TBL_TYPE_MAX, 409 tf_em_int_p58, 410 (uint16_t *)resources->em_cnt); 411 if (rsv_cnt) { 412 em_cfg.num_elements = TF_EM_TBL_TYPE_MAX; 413 em_cfg.cfg = tf_em_int_p58; 414 em_cfg.resources = resources; 415 em_cfg.mem_type = 0; /* Not used by EM */ 416 417 rc = tf_em_int_bind(tfp, &em_cfg); 418 if (rc) { 419 TFP_DRV_LOG(ERR, 420 "EM initialization failure\n"); 421 goto fail; 422 } 423 no_rsv_flag = false; 424 } 425 426 /* 427 * There is no rm reserved for any tables 428 * 429 */ 430 if (no_rsv_flag) { 431 TFP_DRV_LOG(ERR, 432 "No rm reserved for any tables\n"); 433 return -ENOMEM; 434 } 435 436 /* 437 * IF_TBL 438 */ 439 if_tbl_cfg.num_elements = TF_IF_TBL_TYPE_MAX; 440 if_tbl_cfg.cfg = tf_if_tbl_p58; 441 rc = tf_if_tbl_bind(tfp, &if_tbl_cfg); 442 if (rc) { 443 TFP_DRV_LOG(ERR, 444 "IF Table initialization failure\n"); 445 goto fail; 446 } 447 448 if (!tf_session_is_shared_session(tfs)) { 449 /* 450 * GLOBAL_CFG 451 */ 452 global_cfg.num_elements = TF_GLOBAL_CFG_TYPE_MAX; 453 global_cfg.cfg = tf_global_cfg_p58; 454 rc = tf_global_cfg_bind(tfp, &global_cfg); 455 if (rc) { 456 TFP_DRV_LOG(ERR, 457 "Global Cfg initialization failure\n"); 458 goto fail; 459 } 460 } 461 462 /* Final function initialization */ 463 dev_handle->ops = &tf_dev_ops_p58; 464 465 return 0; 466 467 fail: 468 /* Cleanup of already created modules */ 469 frc = tf_dev_unbind_p58(tfp); 470 if (frc) 471 return frc; 472 473 return rc; 474 } 475 476 /** 477 * Device specific unbind function, P5 478 * 479 * [in] tfp 480 * Pointer to TF handle 481 * 482 * Returns 483 * - (0) if successful. 484 * - (-EINVAL) on failure. 485 */ 486 static int 487 tf_dev_unbind_p58(struct tf *tfp) 488 { 489 int rc = 0; 490 bool fail = false; 491 struct tf_session *tfs; 492 493 /* Retrieve the session information */ 494 rc = tf_session_get_session_internal(tfp, &tfs); 495 if (rc) 496 return rc; 497 498 /* Unbind all the support modules. As this is only done on 499 * close we only report errors as everything has to be cleaned 500 * up regardless. 501 * 502 * In case of residuals TCAMs are cleaned up first as to 503 * invalidate the pipeline in a clean manner. 504 */ 505 rc = tf_tcam_shared_unbind(tfp); 506 if (rc) { 507 TFP_DRV_LOG(INFO, 508 "Device unbind failed, TCAM\n"); 509 fail = true; 510 } 511 512 rc = tf_ident_unbind(tfp); 513 if (rc) { 514 TFP_DRV_LOG(INFO, 515 "Device unbind failed, Identifier\n"); 516 fail = true; 517 } 518 519 /* Unbind the SRAM table prior to table as the table manager 520 * owns and frees the table DB while the SRAM table manager owns 521 * and manages it's internal data structures. SRAM table manager 522 * relies on the table rm_db to exist. 523 */ 524 rc = tf_tbl_sram_unbind(tfp); 525 if (rc) { 526 TFP_DRV_LOG(ERR, 527 "Device unbind failed, SRAM table\n"); 528 fail = true; 529 } 530 531 rc = tf_tbl_unbind(tfp); 532 if (rc) { 533 TFP_DRV_LOG(INFO, 534 "Device unbind failed, Table Type\n"); 535 fail = true; 536 } 537 538 rc = tf_em_int_unbind(tfp); 539 if (rc) { 540 TFP_DRV_LOG(INFO, 541 "Device unbind failed, EM\n"); 542 fail = true; 543 } 544 545 rc = tf_if_tbl_unbind(tfp); 546 if (rc) { 547 TFP_DRV_LOG(ERR, 548 "Device unbind failed, IF Table Type\n"); 549 fail = true; 550 } 551 552 if (!tf_session_is_shared_session(tfs)) { 553 rc = tf_global_cfg_unbind(tfp); 554 if (rc) { 555 TFP_DRV_LOG(ERR, 556 "Device unbind failed, Global Cfg Type\n"); 557 fail = true; 558 } 559 } 560 561 if (fail) 562 return -1; 563 564 return rc; 565 } 566 567 int 568 tf_dev_bind(struct tf *tfp __rte_unused, 569 enum tf_device_type type, 570 struct tf_session_resources *resources, 571 uint16_t wc_num_slices, 572 struct tf_dev_info *dev_handle) 573 { 574 switch (type) { 575 case TF_DEVICE_TYPE_P4: 576 case TF_DEVICE_TYPE_SR: 577 dev_handle->type = type; 578 return tf_dev_bind_p4(tfp, 579 resources, 580 dev_handle, 581 wc_num_slices); 582 case TF_DEVICE_TYPE_P5: 583 dev_handle->type = type; 584 return tf_dev_bind_p58(tfp, 585 resources, 586 dev_handle, 587 wc_num_slices); 588 default: 589 TFP_DRV_LOG(ERR, 590 "No such device\n"); 591 return -ENODEV; 592 } 593 } 594 595 int 596 tf_dev_bind_ops(enum tf_device_type type, 597 struct tf_dev_info *dev_handle) 598 { 599 switch (type) { 600 case TF_DEVICE_TYPE_P4: 601 case TF_DEVICE_TYPE_SR: 602 dev_handle->ops = &tf_dev_ops_p4_init; 603 break; 604 case TF_DEVICE_TYPE_P5: 605 dev_handle->ops = &tf_dev_ops_p58_init; 606 break; 607 default: 608 TFP_DRV_LOG(ERR, 609 "No such device\n"); 610 return -ENODEV; 611 } 612 613 return 0; 614 } 615 616 int 617 tf_dev_unbind(struct tf *tfp, 618 struct tf_dev_info *dev_handle) 619 { 620 switch (dev_handle->type) { 621 case TF_DEVICE_TYPE_P4: 622 case TF_DEVICE_TYPE_SR: 623 return tf_dev_unbind_p4(tfp); 624 case TF_DEVICE_TYPE_P5: 625 return tf_dev_unbind_p58(tfp); 626 default: 627 TFP_DRV_LOG(ERR, 628 "No such device\n"); 629 return -ENODEV; 630 } 631 } 632