1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <string.h> 7 #include <rte_common.h> 8 #include "tf_session.h" 9 #include "tf_common.h" 10 #include "tf_msg.h" 11 #include "tfp.h" 12 #include "bnxt.h" 13 14 struct tf_session_client_create_parms { 15 /** 16 * [in] Pointer to the control channel name string 17 */ 18 char *ctrl_chan_name; 19 20 /** 21 * [out] Firmware Session Client ID 22 */ 23 union tf_session_client_id *session_client_id; 24 }; 25 26 struct tf_session_client_destroy_parms { 27 /** 28 * FW Session Client Identifier 29 */ 30 union tf_session_client_id session_client_id; 31 }; 32 33 /** 34 * Creates a Session and the associated client. 35 * 36 * [in] tfp 37 * Pointer to TF handle 38 * 39 * [in] parms 40 * Pointer to session client create parameters 41 * 42 * Returns 43 * - (0) if successful. 44 * - (-EINVAL) on failure. 45 * - (-ENOMEM) if max session clients has been reached. 46 */ 47 static int 48 tf_session_create(struct tf *tfp, 49 struct tf_session_open_session_parms *parms) 50 { 51 int rc; 52 struct tf_session *session = NULL; 53 struct tf_session_client *client; 54 struct tfp_calloc_parms cparms; 55 uint8_t fw_session_id; 56 uint8_t fw_session_client_id; 57 union tf_session_id *session_id; 58 struct tf_dev_info dev; 59 bool shared_session_creator; 60 char *shared_name; 61 char *tcam_session_name; 62 char *pool_session_name; 63 64 TF_CHECK_PARMS2(tfp, parms); 65 66 tf_dev_bind_ops(parms->open_cfg->device_type, 67 &dev); 68 69 /* Open FW session and get a new session_id */ 70 rc = tf_msg_session_open(parms->open_cfg->bp, 71 parms->open_cfg->ctrl_chan_name, 72 &fw_session_id, 73 &fw_session_client_id, 74 &dev, 75 &shared_session_creator); 76 if (rc) { 77 /* Log error */ 78 if (rc == -EEXIST) 79 TFP_DRV_LOG(ERR, 80 "Session is already open, rc:%s\n", 81 strerror(-rc)); 82 else 83 TFP_DRV_LOG(ERR, 84 "Open message send failed, rc:%s\n", 85 strerror(-rc)); 86 87 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID; 88 return rc; 89 } 90 91 /* Allocate session */ 92 cparms.nitems = 1; 93 cparms.size = sizeof(struct tf_session_info); 94 cparms.alignment = 0; 95 rc = tfp_calloc(&cparms); 96 if (rc) { 97 /* Log error */ 98 TFP_DRV_LOG(ERR, 99 "Failed to allocate session info, rc:%s\n", 100 strerror(-rc)); 101 goto cleanup; 102 } 103 tfp->session = (struct tf_session_info *)cparms.mem_va; 104 105 /* Allocate core data for the session */ 106 cparms.nitems = 1; 107 cparms.size = sizeof(struct tf_session); 108 cparms.alignment = 0; 109 rc = tfp_calloc(&cparms); 110 if (rc) { 111 /* Log error */ 112 TFP_DRV_LOG(ERR, 113 "Failed to allocate session data, rc:%s\n", 114 strerror(-rc)); 115 goto cleanup; 116 } 117 tfp->session->core_data = cparms.mem_va; 118 session_id = &parms->open_cfg->session_id; 119 120 /* Update Session Info, which is what is visible to the caller */ 121 tfp->session->ver.major = 0; 122 tfp->session->ver.minor = 0; 123 tfp->session->ver.update = 0; 124 125 tfp->session->session_id.internal.domain = session_id->internal.domain; 126 tfp->session->session_id.internal.bus = session_id->internal.bus; 127 tfp->session->session_id.internal.device = session_id->internal.device; 128 tfp->session->session_id.internal.fw_session_id = fw_session_id; 129 130 /* Initialize Session and Device, which is private */ 131 session = (struct tf_session *)tfp->session->core_data; 132 session->ver.major = 0; 133 session->ver.minor = 0; 134 session->ver.update = 0; 135 136 session->session_id.internal.domain = session_id->internal.domain; 137 session->session_id.internal.bus = session_id->internal.bus; 138 session->session_id.internal.device = session_id->internal.device; 139 session->session_id.internal.fw_session_id = fw_session_id; 140 /* Return the allocated session id */ 141 session_id->id = session->session_id.id; 142 143 /* Init session client list */ 144 ll_init(&session->client_ll); 145 146 /* Create the local session client, initialize and attach to 147 * the session 148 */ 149 cparms.nitems = 1; 150 cparms.size = sizeof(struct tf_session_client); 151 cparms.alignment = 0; 152 rc = tfp_calloc(&cparms); 153 if (rc) { 154 /* Log error */ 155 TFP_DRV_LOG(ERR, 156 "Failed to allocate session client, rc:%s\n", 157 strerror(-rc)); 158 goto cleanup; 159 } 160 client = cparms.mem_va; 161 162 /* Register FID with the client */ 163 rc = tfp_get_fid(tfp, &client->fw_fid); 164 if (rc) 165 return rc; 166 167 client->session_client_id.internal.fw_session_id = fw_session_id; 168 client->session_client_id.internal.fw_session_client_id = 169 fw_session_client_id; 170 171 tfp_memcpy(client->ctrl_chan_name, 172 parms->open_cfg->ctrl_chan_name, 173 TF_SESSION_NAME_MAX); 174 175 ll_insert(&session->client_ll, &client->ll_entry); 176 session->ref_count++; 177 178 /* Init session em_ext_db */ 179 session->em_ext_db_handle = NULL; 180 181 /* Populate the request */ 182 shared_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared"); 183 if (shared_name) { 184 session->shared_session = true; 185 /* 186 * "tf_shared-wc_tcam" is defined for tf_fw version 1.0.0. 187 * "tf_shared-pool" is defined for version 1.0.1. 188 */ 189 tcam_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-wc_tcam"); 190 pool_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-pool"); 191 if (tcam_session_name || pool_session_name) 192 session->shared_session_hotup = true; 193 } 194 195 if (session->shared_session && shared_session_creator) { 196 session->shared_session_creator = true; 197 parms->open_cfg->shared_session_creator = true; 198 } 199 200 rc = tf_dev_bind(tfp, 201 parms->open_cfg->device_type, 202 &parms->open_cfg->resources, 203 parms->open_cfg->wc_num_slices, 204 &session->dev); 205 206 /* Logging handled by dev_bind */ 207 if (rc) 208 goto cleanup; 209 210 if (session->dev.ops->tf_dev_get_mailbox == NULL) { 211 /* Log error */ 212 TFP_DRV_LOG(ERR, 213 "No tf_dev_get_mailbox() defined for device\n"); 214 goto cleanup; 215 } 216 217 session->dev_init = true; 218 219 return 0; 220 221 cleanup: 222 rc = tf_msg_session_close(tfp, 223 fw_session_id, 224 dev.ops->tf_dev_get_mailbox()); 225 if (rc) { 226 /* Log error */ 227 TFP_DRV_LOG(ERR, 228 "FW Session close failed, rc:%s\n", 229 strerror(-rc)); 230 } 231 if (tfp->session) { 232 tfp_free(tfp->session->core_data); 233 tfp_free(tfp->session); 234 tfp->session = NULL; 235 } 236 237 return rc; 238 } 239 240 /** 241 * Creates a Session Client on an existing Session. 242 * 243 * [in] tfp 244 * Pointer to TF handle 245 * 246 * [in] parms 247 * Pointer to session client create parameters 248 * 249 * Returns 250 * - (0) if successful. 251 * - (-EINVAL) on failure. 252 * - (-ENOMEM) if max session clients has been reached. 253 */ 254 static int 255 tf_session_client_create(struct tf *tfp, 256 struct tf_session_client_create_parms *parms) 257 { 258 int rc; 259 struct tf_session *session = NULL; 260 struct tf_session_client *client; 261 struct tfp_calloc_parms cparms; 262 union tf_session_client_id session_client_id; 263 264 TF_CHECK_PARMS2(tfp, parms); 265 266 /* Using internal version as session client may not exist yet */ 267 rc = tf_session_get_session_internal(tfp, &session); 268 if (rc) { 269 TFP_DRV_LOG(ERR, 270 "Failed to lookup session, rc:%s\n", 271 strerror(-rc)); 272 return rc; 273 } 274 275 client = tf_session_find_session_client_by_name(session, 276 parms->ctrl_chan_name); 277 if (client) { 278 TFP_DRV_LOG(ERR, 279 "Client %s, already registered with this session\n", 280 parms->ctrl_chan_name); 281 return -EOPNOTSUPP; 282 } 283 284 rc = tf_msg_session_client_register 285 (tfp, 286 session, 287 parms->ctrl_chan_name, 288 &session_client_id.internal.fw_session_client_id); 289 if (rc) { 290 TFP_DRV_LOG(ERR, 291 "Failed to create client on session, rc:%s\n", 292 strerror(-rc)); 293 return rc; 294 } 295 296 /* Create the local session client, initialize and attach to 297 * the session 298 */ 299 cparms.nitems = 1; 300 cparms.size = sizeof(struct tf_session_client); 301 cparms.alignment = 0; 302 rc = tfp_calloc(&cparms); 303 if (rc) { 304 TFP_DRV_LOG(ERR, 305 "Failed to allocate session client, rc:%s\n", 306 strerror(-rc)); 307 goto cleanup; 308 } 309 client = cparms.mem_va; 310 311 /* Register FID with the client */ 312 rc = tfp_get_fid(tfp, &client->fw_fid); 313 if (rc) 314 return rc; 315 316 /* Build the Session Client ID by adding the fw_session_id */ 317 rc = tf_session_get_fw_session_id 318 (tfp, 319 &session_client_id.internal.fw_session_id); 320 if (rc) { 321 TFP_DRV_LOG(ERR, 322 "Session Firmware id lookup failed, rc:%s\n", 323 strerror(-rc)); 324 return rc; 325 } 326 327 tfp_memcpy(client->ctrl_chan_name, 328 parms->ctrl_chan_name, 329 TF_SESSION_NAME_MAX); 330 331 client->session_client_id.id = session_client_id.id; 332 333 ll_insert(&session->client_ll, &client->ll_entry); 334 335 session->ref_count++; 336 337 /* Build the return value */ 338 parms->session_client_id->id = session_client_id.id; 339 340 cleanup: 341 /* TBD - Add code to unregister newly create client from fw */ 342 343 return rc; 344 } 345 346 /** 347 * Destroys a Session Client on an existing Session. 348 * 349 * [in] tfp 350 * Pointer to TF handle 351 * 352 * [in] parms 353 * Pointer to the session client destroy parameters 354 * 355 * Returns 356 * - (0) if successful. 357 * - (-EINVAL) on failure. 358 * - (-ENOTFOUND) error, client not owned by the session. 359 * - (-ENOTSUPP) error, unable to destroy client as its the last 360 * client. Please use the tf_session_close(). 361 */ 362 static int 363 tf_session_client_destroy(struct tf *tfp, 364 struct tf_session_client_destroy_parms *parms) 365 { 366 int rc; 367 struct tf_session *tfs; 368 struct tf_session_client *client; 369 370 TF_CHECK_PARMS2(tfp, parms); 371 372 rc = tf_session_get_session(tfp, &tfs); 373 if (rc) { 374 TFP_DRV_LOG(ERR, 375 "Failed to lookup session, rc:%s\n", 376 strerror(-rc)); 377 return rc; 378 } 379 380 /* Check session owns this client and that we're not the last client */ 381 client = tf_session_get_session_client(tfs, 382 parms->session_client_id); 383 if (client == NULL) { 384 TFP_DRV_LOG(ERR, 385 "Client %d, not found within this session\n", 386 parms->session_client_id.id); 387 return -EINVAL; 388 } 389 390 /* If last client the request is rejected and cleanup should 391 * be done by session close. 392 */ 393 if (tfs->ref_count == 1) 394 return -EOPNOTSUPP; 395 396 rc = tf_msg_session_client_unregister 397 (tfp, 398 tfs, 399 parms->session_client_id.internal.fw_session_client_id); 400 401 /* Log error, but continue. If FW fails we do not really have 402 * a way to fix this but the client would no longer be valid 403 * thus we remove from the session. 404 */ 405 if (rc) { 406 TFP_DRV_LOG(ERR, 407 "Client destroy on FW Failed, rc:%s\n", 408 strerror(-rc)); 409 } 410 411 ll_delete(&tfs->client_ll, &client->ll_entry); 412 413 /* Decrement the session ref_count */ 414 tfs->ref_count--; 415 416 tfp_free(client); 417 418 return rc; 419 } 420 421 int 422 tf_session_open_session(struct tf *tfp, 423 struct tf_session_open_session_parms *parms) 424 { 425 int rc; 426 struct tf_session_client_create_parms scparms; 427 428 TF_CHECK_PARMS3(tfp, parms, parms->open_cfg->bp); 429 430 tfp->bp = parms->open_cfg->bp; 431 /* Decide if we're creating a new session or session client */ 432 if (tfp->session == NULL) { 433 rc = tf_session_create(tfp, parms); 434 if (rc) { 435 TFP_DRV_LOG(ERR, 436 "Failed to create session, ctrl_chan_name:%s, rc:%s\n", 437 parms->open_cfg->ctrl_chan_name, 438 strerror(-rc)); 439 return rc; 440 } 441 442 TFP_DRV_LOG(INFO, 443 "Session created, session_client_id:%d," 444 " session_id:0x%08x, fw_session_id:%d\n", 445 parms->open_cfg->session_client_id.id, 446 parms->open_cfg->session_id.id, 447 parms->open_cfg->session_id.internal.fw_session_id); 448 } else { 449 scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name; 450 scparms.session_client_id = &parms->open_cfg->session_client_id; 451 452 /* Create the new client and get it associated with 453 * the session. 454 */ 455 rc = tf_session_client_create(tfp, &scparms); 456 if (rc) { 457 TFP_DRV_LOG(ERR, 458 "Failed to create client on session 0x%x, rc:%s\n", 459 parms->open_cfg->session_id.id, 460 strerror(-rc)); 461 return rc; 462 } 463 464 TFP_DRV_LOG(INFO, 465 "Session Client:%d registered on session:0x%08x\n", 466 scparms.session_client_id->internal.fw_session_client_id, 467 tfp->session->session_id.id); 468 } 469 470 return 0; 471 } 472 473 int 474 tf_session_attach_session(struct tf *tfp __rte_unused, 475 struct tf_session_attach_session_parms *parms __rte_unused) 476 { 477 int rc = -EOPNOTSUPP; 478 479 TF_CHECK_PARMS2(tfp, parms); 480 481 TFP_DRV_LOG(ERR, 482 "Attach not yet supported, rc:%s\n", 483 strerror(-rc)); 484 return rc; 485 } 486 487 int 488 tf_session_close_session(struct tf *tfp, 489 struct tf_session_close_session_parms *parms) 490 { 491 int rc; 492 struct tf_session *tfs = NULL; 493 struct tf_session_client *client; 494 struct tf_dev_info *tfd = NULL; 495 struct tf_session_client_destroy_parms scdparms; 496 uint16_t fid; 497 uint8_t fw_session_id = 1; 498 int mailbox = 0; 499 500 TF_CHECK_PARMS2(tfp, parms); 501 502 rc = tf_session_get_session(tfp, &tfs); 503 if (rc) { 504 TFP_DRV_LOG(ERR, 505 "Session lookup failed, rc:%s\n", 506 strerror(-rc)); 507 return rc; 508 } 509 510 if (tfs->session_id.id == TF_SESSION_ID_INVALID) { 511 rc = -EINVAL; 512 TFP_DRV_LOG(ERR, 513 "Invalid session id, unable to close, rc:%s\n", 514 strerror(-rc)); 515 return rc; 516 } 517 518 /* Get the client, we need it independently of the closure 519 * type (client or session closure). 520 * 521 * We find the client by way of the fid. Thus one cannot close 522 * a client on behalf of someone else. 523 */ 524 rc = tfp_get_fid(tfp, &fid); 525 if (rc) 526 return rc; 527 528 client = tf_session_find_session_client_by_fid(tfs, 529 fid); 530 if (!client) { 531 rc = -EINVAL; 532 TFP_DRV_LOG(ERR, 533 "Client not part of the session, unable to close, rc:%s\n", 534 strerror(-rc)); 535 return rc; 536 } 537 538 /* Record the session we're closing so the caller knows the 539 * details. 540 */ 541 *parms->session_id = tfs->session_id; 542 543 /* In case multiple clients we chose to close those first */ 544 if (tfs->ref_count > 1) { 545 /* Linaro gcc can't static init this structure */ 546 memset(&scdparms, 547 0, 548 sizeof(struct tf_session_client_destroy_parms)); 549 550 scdparms.session_client_id = client->session_client_id; 551 /* Destroy requested client so its no longer 552 * registered with this session. 553 */ 554 rc = tf_session_client_destroy(tfp, &scdparms); 555 if (rc) { 556 TFP_DRV_LOG(ERR, 557 "Failed to unregister Client %d, rc:%s\n", 558 client->session_client_id.id, 559 strerror(-rc)); 560 return rc; 561 } 562 563 TFP_DRV_LOG(INFO, 564 "Closed session client, session_client_id:%d\n", 565 client->session_client_id.id); 566 567 TFP_DRV_LOG(INFO, 568 "session_id:0x%08x, ref_count:%d\n", 569 tfs->session_id.id, 570 tfs->ref_count); 571 572 return 0; 573 } 574 575 rc = tf_session_get_device(tfs, &tfd); 576 if (rc) { 577 TFP_DRV_LOG(ERR, 578 "Device lookup failed, rc:%s\n", 579 strerror(-rc)); 580 return rc; 581 } 582 583 mailbox = tfd->ops->tf_dev_get_mailbox(); 584 585 rc = tf_session_get_fw_session_id(tfp, &fw_session_id); 586 if (rc) { 587 TFP_DRV_LOG(ERR, 588 "Unable to lookup FW id, rc:%s\n", 589 strerror(-rc)); 590 return rc; 591 } 592 593 /* Unbind the device */ 594 rc = tf_dev_unbind(tfp, tfd); 595 if (rc) { 596 /* Log error */ 597 TFP_DRV_LOG(ERR, 598 "Device unbind failed, rc:%s\n", 599 strerror(-rc)); 600 } 601 602 rc = tf_msg_session_close(tfp, fw_session_id, mailbox); 603 if (rc) { 604 /* Log error */ 605 TFP_DRV_LOG(ERR, 606 "FW Session close failed, rc:%s\n", 607 strerror(-rc)); 608 } 609 610 /* Final cleanup as we're last user of the session thus we 611 * also delete the last client. 612 */ 613 ll_delete(&tfs->client_ll, &client->ll_entry); 614 tfp_free(client); 615 616 tfs->ref_count--; 617 618 TFP_DRV_LOG(INFO, 619 "Closed session, session_id:0x%08x, ref_count:%d\n", 620 tfs->session_id.id, 621 tfs->ref_count); 622 623 tfs->dev_init = false; 624 625 tfp_free(tfp->session->core_data); 626 tfp_free(tfp->session); 627 tfp->session = NULL; 628 629 return 0; 630 } 631 632 bool 633 tf_session_is_fid_supported(struct tf_session *tfs, 634 uint16_t fid) 635 { 636 struct ll_entry *c_entry; 637 struct tf_session_client *client; 638 639 for (c_entry = tfs->client_ll.head; 640 c_entry != NULL; 641 c_entry = c_entry->next) { 642 client = (struct tf_session_client *)c_entry; 643 if (client->fw_fid == fid) 644 return true; 645 } 646 647 return false; 648 } 649 650 int 651 tf_session_get_session_internal(struct tf *tfp, 652 struct tf_session **tfs) 653 { 654 int rc = 0; 655 656 /* Skip using the check macro as we want to control the error msg */ 657 if (tfp->session == NULL || tfp->session->core_data == NULL) { 658 rc = -EINVAL; 659 TFP_DRV_LOG(ERR, 660 "Session not created, rc:%s\n", 661 strerror(-rc)); 662 return rc; 663 } 664 665 *tfs = (struct tf_session *)(tfp->session->core_data); 666 667 return rc; 668 } 669 670 int 671 tf_session_get_session(struct tf *tfp, 672 struct tf_session **tfs) 673 { 674 int rc; 675 uint16_t fw_fid; 676 bool supported = false; 677 678 rc = tf_session_get_session_internal(tfp, 679 tfs); 680 /* Logging done by tf_session_get_session_internal */ 681 if (rc) 682 return rc; 683 684 /* As session sharing among functions aka 'individual clients' 685 * is supported we have to assure that the client is indeed 686 * registered before we get deep in the TruFlow api stack. 687 */ 688 rc = tfp_get_fid(tfp, &fw_fid); 689 if (rc) { 690 TFP_DRV_LOG(ERR, 691 "Internal FID lookup\n, rc:%s\n", 692 strerror(-rc)); 693 return rc; 694 } 695 696 supported = tf_session_is_fid_supported(*tfs, fw_fid); 697 if (!supported) { 698 TFP_DRV_LOG 699 (ERR, 700 "Ctrl channel not registered with session\n, rc:%s\n", 701 strerror(-rc)); 702 return -EINVAL; 703 } 704 705 return rc; 706 } 707 708 int tf_session_get(struct tf *tfp, 709 struct tf_session **tfs, 710 struct tf_dev_info **tfd) 711 { 712 int rc; 713 rc = tf_session_get_session_internal(tfp, tfs); 714 715 /* Logging done by tf_session_get_session_internal */ 716 if (rc) 717 return rc; 718 719 rc = tf_session_get_device(*tfs, tfd); 720 721 return rc; 722 } 723 724 struct tf_session_client * 725 tf_session_get_session_client(struct tf_session *tfs, 726 union tf_session_client_id session_client_id) 727 { 728 struct ll_entry *c_entry; 729 struct tf_session_client *client; 730 731 /* Skip using the check macro as we just want to return */ 732 if (tfs == NULL) 733 return NULL; 734 735 for (c_entry = tfs->client_ll.head; 736 c_entry != NULL; 737 c_entry = c_entry->next) { 738 client = (struct tf_session_client *)c_entry; 739 if (client->session_client_id.id == session_client_id.id) 740 return client; 741 } 742 743 return NULL; 744 } 745 746 struct tf_session_client * 747 tf_session_find_session_client_by_name(struct tf_session *tfs, 748 const char *ctrl_chan_name) 749 { 750 struct ll_entry *c_entry; 751 struct tf_session_client *client; 752 753 /* Skip using the check macro as we just want to return */ 754 if (tfs == NULL || ctrl_chan_name == NULL) 755 return NULL; 756 757 for (c_entry = tfs->client_ll.head; 758 c_entry != NULL; 759 c_entry = c_entry->next) { 760 client = (struct tf_session_client *)c_entry; 761 if (strncmp(client->ctrl_chan_name, 762 ctrl_chan_name, 763 TF_SESSION_NAME_MAX) == 0) 764 return client; 765 } 766 767 return NULL; 768 } 769 770 struct tf_session_client * 771 tf_session_find_session_client_by_fid(struct tf_session *tfs, 772 uint16_t fid) 773 { 774 struct ll_entry *c_entry; 775 struct tf_session_client *client; 776 777 /* Skip using the check macro as we just want to return */ 778 if (tfs == NULL) 779 return NULL; 780 781 for (c_entry = tfs->client_ll.head; 782 c_entry != NULL; 783 c_entry = c_entry->next) { 784 client = (struct tf_session_client *)c_entry; 785 if (client->fw_fid == fid) 786 return client; 787 } 788 789 return NULL; 790 } 791 792 int 793 tf_session_get_device(struct tf_session *tfs, 794 struct tf_dev_info **tfd) 795 { 796 *tfd = &tfs->dev; 797 798 return 0; 799 } 800 801 int 802 tf_session_get_fw_session_id(struct tf *tfp, 803 uint8_t *fw_session_id) 804 { 805 int rc; 806 struct tf_session *tfs = NULL; 807 808 /* Skip using the check macro as we want to control the error msg */ 809 if (tfp->session == NULL) { 810 rc = -EINVAL; 811 TFP_DRV_LOG(ERR, 812 "Session not created, rc:%s\n", 813 strerror(-rc)); 814 return rc; 815 } 816 817 if (fw_session_id == NULL) { 818 rc = -EINVAL; 819 TFP_DRV_LOG(ERR, 820 "Invalid Argument(s), rc:%s\n", 821 strerror(-rc)); 822 return rc; 823 } 824 825 rc = tf_session_get_session_internal(tfp, &tfs); 826 if (rc) 827 return rc; 828 829 *fw_session_id = tfs->session_id.internal.fw_session_id; 830 831 return 0; 832 } 833 834 int 835 tf_session_get_session_id(struct tf *tfp, 836 union tf_session_id *session_id) 837 { 838 int rc; 839 struct tf_session *tfs = NULL; 840 841 if (tfp->session == NULL) { 842 rc = -EINVAL; 843 TFP_DRV_LOG(ERR, 844 "Session not created, rc:%s\n", 845 strerror(-rc)); 846 return rc; 847 } 848 849 if (session_id == NULL) { 850 rc = -EINVAL; 851 TFP_DRV_LOG(ERR, 852 "Invalid Argument(s), rc:%s\n", 853 strerror(-rc)); 854 return rc; 855 } 856 857 /* Using internal version as session client may not exist yet */ 858 rc = tf_session_get_session_internal(tfp, &tfs); 859 if (rc) 860 return rc; 861 862 *session_id = tfs->session_id; 863 864 return 0; 865 } 866 867 int 868 tf_session_get_em_ext_db(struct tf *tfp, 869 void **em_ext_db_handle) 870 { 871 struct tf_session *tfs = NULL; 872 int rc = 0; 873 874 *em_ext_db_handle = NULL; 875 876 if (tfp == NULL) 877 return (-EINVAL); 878 879 rc = tf_session_get_session_internal(tfp, &tfs); 880 if (rc) 881 return rc; 882 883 *em_ext_db_handle = tfs->em_ext_db_handle; 884 return rc; 885 } 886 887 int 888 tf_session_set_em_ext_db(struct tf *tfp, 889 void *em_ext_db_handle) 890 { 891 struct tf_session *tfs = NULL; 892 int rc = 0; 893 894 if (tfp == NULL) 895 return (-EINVAL); 896 897 rc = tf_session_get_session_internal(tfp, &tfs); 898 if (rc) 899 return rc; 900 901 tfs->em_ext_db_handle = em_ext_db_handle; 902 return rc; 903 } 904 905 int 906 tf_session_get_db(struct tf *tfp, 907 enum tf_module_type type, 908 void **db_handle) 909 { 910 struct tf_session *tfs = NULL; 911 int rc = 0; 912 913 *db_handle = NULL; 914 915 if (tfp == NULL) 916 return (-EINVAL); 917 918 rc = tf_session_get_session_internal(tfp, &tfs); 919 if (rc) 920 return rc; 921 922 switch (type) { 923 case TF_MODULE_TYPE_IDENTIFIER: 924 if (tfs->id_db_handle) 925 *db_handle = tfs->id_db_handle; 926 else 927 rc = -ENOMEM; 928 break; 929 case TF_MODULE_TYPE_TABLE: 930 if (tfs->tbl_db_handle) 931 *db_handle = tfs->tbl_db_handle; 932 else 933 rc = -ENOMEM; 934 935 break; 936 case TF_MODULE_TYPE_TCAM: 937 if (tfs->tcam_db_handle) 938 *db_handle = tfs->tcam_db_handle; 939 else 940 rc = -ENOMEM; 941 break; 942 case TF_MODULE_TYPE_EM: 943 if (tfs->em_db_handle) 944 *db_handle = tfs->em_db_handle; 945 else 946 rc = -ENOMEM; 947 break; 948 default: 949 rc = -EINVAL; 950 break; 951 } 952 953 return rc; 954 } 955 956 int 957 tf_session_set_db(struct tf *tfp, 958 enum tf_module_type type, 959 void *db_handle) 960 { 961 struct tf_session *tfs = NULL; 962 int rc = 0; 963 964 if (tfp == NULL) 965 return (-EINVAL); 966 967 rc = tf_session_get_session_internal(tfp, &tfs); 968 if (rc) 969 return rc; 970 971 switch (type) { 972 case TF_MODULE_TYPE_IDENTIFIER: 973 tfs->id_db_handle = db_handle; 974 break; 975 case TF_MODULE_TYPE_TABLE: 976 tfs->tbl_db_handle = db_handle; 977 break; 978 case TF_MODULE_TYPE_TCAM: 979 tfs->tcam_db_handle = db_handle; 980 break; 981 case TF_MODULE_TYPE_EM: 982 tfs->em_db_handle = db_handle; 983 break; 984 default: 985 rc = -EINVAL; 986 break; 987 } 988 989 return rc; 990 } 991 992 int 993 tf_session_get_tcam_shared_db(struct tf *tfp, 994 void **tcam_shared_db_handle) 995 { 996 struct tf_session *tfs = NULL; 997 int rc = 0; 998 999 *tcam_shared_db_handle = NULL; 1000 1001 if (tfp == NULL) 1002 return (-EINVAL); 1003 1004 rc = tf_session_get_session_internal(tfp, &tfs); 1005 if (rc) 1006 return rc; 1007 1008 *tcam_shared_db_handle = tfs->tcam_shared_db_handle; 1009 return rc; 1010 } 1011 1012 int 1013 tf_session_set_tcam_shared_db(struct tf *tfp, 1014 void *tcam_shared_db_handle) 1015 { 1016 struct tf_session *tfs = NULL; 1017 int rc = 0; 1018 1019 if (tfp == NULL) 1020 return (-EINVAL); 1021 1022 rc = tf_session_get_session_internal(tfp, &tfs); 1023 if (rc) 1024 return rc; 1025 1026 tfs->tcam_shared_db_handle = tcam_shared_db_handle; 1027 return rc; 1028 } 1029 1030 int 1031 tf_session_get_sram_db(struct tf *tfp, 1032 void **sram_handle) 1033 { 1034 struct tf_session *tfs = NULL; 1035 int rc = 0; 1036 1037 *sram_handle = NULL; 1038 1039 if (tfp == NULL) 1040 return (-EINVAL); 1041 1042 rc = tf_session_get_session_internal(tfp, &tfs); 1043 if (rc) 1044 return rc; 1045 1046 *sram_handle = tfs->sram_handle; 1047 return rc; 1048 } 1049 1050 int 1051 tf_session_set_sram_db(struct tf *tfp, 1052 void *sram_handle) 1053 { 1054 struct tf_session *tfs = NULL; 1055 int rc = 0; 1056 1057 if (tfp == NULL) 1058 return (-EINVAL); 1059 1060 rc = tf_session_get_session_internal(tfp, &tfs); 1061 if (rc) 1062 return rc; 1063 1064 tfs->sram_handle = sram_handle; 1065 return rc; 1066 } 1067 1068 int 1069 tf_session_get_global_db(struct tf *tfp, 1070 void **global_handle) 1071 { 1072 struct tf_session *tfs = NULL; 1073 int rc = 0; 1074 1075 *global_handle = NULL; 1076 1077 if (tfp == NULL) 1078 return (-EINVAL); 1079 1080 rc = tf_session_get_session_internal(tfp, &tfs); 1081 if (rc) 1082 return rc; 1083 1084 *global_handle = tfs->global_db_handle; 1085 return rc; 1086 } 1087 1088 int 1089 tf_session_set_global_db(struct tf *tfp, 1090 void *global_handle) 1091 { 1092 struct tf_session *tfs = NULL; 1093 int rc = 0; 1094 1095 if (tfp == NULL) 1096 return (-EINVAL); 1097 1098 rc = tf_session_get_session_internal(tfp, &tfs); 1099 if (rc) 1100 return rc; 1101 1102 tfs->global_db_handle = global_handle; 1103 return rc; 1104 } 1105 1106 int 1107 tf_session_get_if_tbl_db(struct tf *tfp, 1108 void **if_tbl_handle) 1109 { 1110 struct tf_session *tfs = NULL; 1111 int rc = 0; 1112 1113 *if_tbl_handle = NULL; 1114 1115 if (tfp == NULL) 1116 return (-EINVAL); 1117 1118 rc = tf_session_get_session_internal(tfp, &tfs); 1119 if (rc) 1120 return rc; 1121 1122 *if_tbl_handle = tfs->if_tbl_db_handle; 1123 return rc; 1124 } 1125 1126 int 1127 tf_session_set_if_tbl_db(struct tf *tfp, 1128 void *if_tbl_handle) 1129 { 1130 struct tf_session *tfs = NULL; 1131 int rc = 0; 1132 1133 if (tfp == NULL) 1134 return (-EINVAL); 1135 1136 rc = tf_session_get_session_internal(tfp, &tfs); 1137 if (rc) 1138 return rc; 1139 1140 tfs->if_tbl_db_handle = if_tbl_handle; 1141 return rc; 1142 } 1143 1144 int 1145 tf_session_set_hotup_state(struct tf *tfp, 1146 struct tf_set_session_hotup_state_parms *parms) 1147 { 1148 int rc = 0; 1149 struct tf_session *tfs = NULL; 1150 1151 rc = tf_session_get_session(tfp, &tfs); 1152 if (rc) { 1153 TFP_DRV_LOG(ERR, 1154 "Session lookup failed, rc:%s\n", 1155 strerror(-rc)); 1156 return rc; 1157 } 1158 1159 if (!tf_session_is_shared_session(tfs)) { 1160 rc = -EINVAL; 1161 TFP_DRV_LOG(ERR, 1162 "Only shared session able to set state, rc:%s\n", 1163 strerror(-rc)); 1164 return rc; 1165 } 1166 1167 rc = tf_msg_session_set_hotup_state(tfp, parms->state); 1168 if (rc) { 1169 /* Log error */ 1170 TFP_DRV_LOG(ERR, 1171 "Set session hot upgrade state failed, rc:%s\n", 1172 strerror(-rc)); 1173 } 1174 1175 return rc; 1176 } 1177 1178 int 1179 tf_session_get_hotup_state(struct tf *tfp, 1180 struct tf_get_session_hotup_state_parms *parms) 1181 { 1182 int rc = 0; 1183 struct tf_session *tfs = NULL; 1184 1185 rc = tf_session_get_session(tfp, &tfs); 1186 if (rc) { 1187 TFP_DRV_LOG(ERR, 1188 "Session lookup failed, rc:%s\n", 1189 strerror(-rc)); 1190 return rc; 1191 } 1192 1193 if (!tf_session_is_shared_session(tfs)) { 1194 rc = -EINVAL; 1195 TFP_DRV_LOG(ERR, 1196 "Only shared session able to get state, rc:%s\n", 1197 strerror(-rc)); 1198 return rc; 1199 } 1200 1201 rc = tf_msg_session_get_hotup_state(tfp, &parms->state, &parms->ref_cnt); 1202 if (rc) { 1203 /* Log error */ 1204 TFP_DRV_LOG(ERR, 1205 "Get session hot upgrade state failed, rc:%s\n", 1206 strerror(-rc)); 1207 } 1208 1209 return rc; 1210 } 1211