1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <string.h> 7 8 #include <rte_common.h> 9 10 #include "tf_session.h" 11 #include "tf_common.h" 12 #include "tf_msg.h" 13 #include "tfp.h" 14 #include "bnxt.h" 15 16 struct tf_session_client_create_parms { 17 /** 18 * [in] Pointer to the control channel name string 19 */ 20 char *ctrl_chan_name; 21 22 /** 23 * [out] Firmware Session Client ID 24 */ 25 union tf_session_client_id *session_client_id; 26 }; 27 28 struct tf_session_client_destroy_parms { 29 /** 30 * FW Session Client Identifier 31 */ 32 union tf_session_client_id session_client_id; 33 }; 34 35 /** 36 * Creates a Session and the associated client. 37 * 38 * [in] tfp 39 * Pointer to TF handle 40 * 41 * [in] parms 42 * Pointer to session client create parameters 43 * 44 * Returns 45 * - (0) if successful. 46 * - (-EINVAL) on failure. 47 * - (-ENOMEM) if max session clients has been reached. 48 */ 49 static int 50 tf_session_create(struct tf *tfp, 51 struct tf_session_open_session_parms *parms) 52 { 53 int rc; 54 struct tf_session *session = NULL; 55 struct tf_session_client *client; 56 struct tfp_calloc_parms cparms; 57 uint8_t fw_session_id; 58 uint8_t fw_session_client_id; 59 union tf_session_id *session_id; 60 struct tf_dev_info dev; 61 bool shared_session_creator; 62 int name_len; 63 char *name; 64 65 TF_CHECK_PARMS2(tfp, parms); 66 67 tf_dev_bind_ops(parms->open_cfg->device_type, 68 &dev); 69 70 /* Open FW session and get a new session_id */ 71 rc = tf_msg_session_open(parms->open_cfg->bp, 72 parms->open_cfg->ctrl_chan_name, 73 &fw_session_id, 74 &fw_session_client_id, 75 &dev, 76 &shared_session_creator); 77 if (rc) { 78 /* Log error */ 79 if (rc == -EEXIST) 80 TFP_DRV_LOG(ERR, 81 "Session is already open, rc:%s\n", 82 strerror(-rc)); 83 else 84 TFP_DRV_LOG(ERR, 85 "Open message send failed, rc:%s\n", 86 strerror(-rc)); 87 88 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID; 89 return rc; 90 } 91 92 /* Allocate session */ 93 cparms.nitems = 1; 94 cparms.size = sizeof(struct tf_session_info); 95 cparms.alignment = 0; 96 rc = tfp_calloc(&cparms); 97 if (rc) { 98 /* Log error */ 99 TFP_DRV_LOG(ERR, 100 "Failed to allocate session info, rc:%s\n", 101 strerror(-rc)); 102 goto cleanup; 103 } 104 tfp->session = (struct tf_session_info *)cparms.mem_va; 105 106 /* Allocate core data for the session */ 107 cparms.nitems = 1; 108 cparms.size = sizeof(struct tf_session); 109 cparms.alignment = 0; 110 rc = tfp_calloc(&cparms); 111 if (rc) { 112 /* Log error */ 113 TFP_DRV_LOG(ERR, 114 "Failed to allocate session data, rc:%s\n", 115 strerror(-rc)); 116 goto cleanup; 117 } 118 tfp->session->core_data = cparms.mem_va; 119 session_id = &parms->open_cfg->session_id; 120 121 /* Update Session Info, which is what is visible to the caller */ 122 tfp->session->ver.major = 0; 123 tfp->session->ver.minor = 0; 124 tfp->session->ver.update = 0; 125 126 tfp->session->session_id.internal.domain = session_id->internal.domain; 127 tfp->session->session_id.internal.bus = session_id->internal.bus; 128 tfp->session->session_id.internal.device = session_id->internal.device; 129 tfp->session->session_id.internal.fw_session_id = fw_session_id; 130 131 /* Initialize Session and Device, which is private */ 132 session = (struct tf_session *)tfp->session->core_data; 133 session->ver.major = 0; 134 session->ver.minor = 0; 135 session->ver.update = 0; 136 137 session->session_id.internal.domain = session_id->internal.domain; 138 session->session_id.internal.bus = session_id->internal.bus; 139 session->session_id.internal.device = session_id->internal.device; 140 session->session_id.internal.fw_session_id = fw_session_id; 141 /* Return the allocated session id */ 142 session_id->id = session->session_id.id; 143 144 session->shadow_copy = parms->open_cfg->shadow_copy; 145 146 /* Init session client list */ 147 ll_init(&session->client_ll); 148 149 /* Create the local session client, initialize and attach to 150 * the session 151 */ 152 cparms.nitems = 1; 153 cparms.size = sizeof(struct tf_session_client); 154 cparms.alignment = 0; 155 rc = tfp_calloc(&cparms); 156 if (rc) { 157 /* Log error */ 158 TFP_DRV_LOG(ERR, 159 "Failed to allocate session client, rc:%s\n", 160 strerror(-rc)); 161 goto cleanup; 162 } 163 client = cparms.mem_va; 164 165 /* Register FID with the client */ 166 rc = tfp_get_fid(tfp, &client->fw_fid); 167 if (rc) 168 return rc; 169 170 client->session_client_id.internal.fw_session_id = fw_session_id; 171 client->session_client_id.internal.fw_session_client_id = 172 fw_session_client_id; 173 174 tfp_memcpy(client->ctrl_chan_name, 175 parms->open_cfg->ctrl_chan_name, 176 TF_SESSION_NAME_MAX); 177 178 ll_insert(&session->client_ll, &client->ll_entry); 179 session->ref_count++; 180 181 /* Init session em_ext_db */ 182 session->em_ext_db_handle = NULL; 183 184 /* Populate the request */ 185 name_len = strnlen(parms->open_cfg->ctrl_chan_name, 186 TF_SESSION_NAME_MAX); 187 name = &parms->open_cfg->ctrl_chan_name[name_len - strlen("tf_shared")]; 188 if (!strncmp(name, "tf_shared", strlen("tf_shared"))) 189 session->shared_session = true; 190 191 name = &parms->open_cfg->ctrl_chan_name[name_len - 192 strlen("tf_shared-wc_tcam")]; 193 if (!strncmp(name, "tf_shared-wc_tcam", strlen("tf_shared-wc_tcam"))) 194 session->shared_session = true; 195 196 if (session->shared_session && shared_session_creator) { 197 session->shared_session_creator = true; 198 parms->open_cfg->shared_session_creator = true; 199 } 200 201 rc = tf_dev_bind(tfp, 202 parms->open_cfg->device_type, 203 session->shadow_copy, 204 &parms->open_cfg->resources, 205 &session->dev); 206 207 /* Logging handled by dev_bind */ 208 if (rc) 209 goto cleanup; 210 211 if (session->dev.ops->tf_dev_get_mailbox == NULL) { 212 /* Log error */ 213 TFP_DRV_LOG(ERR, 214 "No tf_dev_get_mailbox() defined for device\n"); 215 goto cleanup; 216 } 217 218 session->dev_init = true; 219 220 return 0; 221 222 cleanup: 223 rc = tf_msg_session_close(tfp, 224 fw_session_id, 225 dev.ops->tf_dev_get_mailbox()); 226 if (rc) { 227 /* Log error */ 228 TFP_DRV_LOG(ERR, 229 "FW Session close failed, rc:%s\n", 230 strerror(-rc)); 231 } 232 233 tfp_free(tfp->session->core_data); 234 tfp_free(tfp->session); 235 tfp->session = NULL; 236 return rc; 237 } 238 239 /** 240 * Creates a Session Client on an existing Session. 241 * 242 * [in] tfp 243 * Pointer to TF handle 244 * 245 * [in] parms 246 * Pointer to session client create parameters 247 * 248 * Returns 249 * - (0) if successful. 250 * - (-EINVAL) on failure. 251 * - (-ENOMEM) if max session clients has been reached. 252 */ 253 static int 254 tf_session_client_create(struct tf *tfp, 255 struct tf_session_client_create_parms *parms) 256 { 257 int rc; 258 struct tf_session *session = NULL; 259 struct tf_session_client *client; 260 struct tfp_calloc_parms cparms; 261 union tf_session_client_id session_client_id; 262 263 TF_CHECK_PARMS2(tfp, parms); 264 265 /* Using internal version as session client may not exist yet */ 266 rc = tf_session_get_session_internal(tfp, &session); 267 if (rc) { 268 TFP_DRV_LOG(ERR, 269 "Failed to lookup session, rc:%s\n", 270 strerror(-rc)); 271 return rc; 272 } 273 274 client = tf_session_find_session_client_by_name(session, 275 parms->ctrl_chan_name); 276 if (client) { 277 TFP_DRV_LOG(ERR, 278 "Client %s, already registered with this session\n", 279 parms->ctrl_chan_name); 280 return -EOPNOTSUPP; 281 } 282 283 rc = tf_msg_session_client_register 284 (tfp, 285 session, 286 parms->ctrl_chan_name, 287 &session_client_id.internal.fw_session_client_id); 288 if (rc) { 289 TFP_DRV_LOG(ERR, 290 "Failed to create client on session, rc:%s\n", 291 strerror(-rc)); 292 return rc; 293 } 294 295 /* Create the local session client, initialize and attach to 296 * the session 297 */ 298 cparms.nitems = 1; 299 cparms.size = sizeof(struct tf_session_client); 300 cparms.alignment = 0; 301 rc = tfp_calloc(&cparms); 302 if (rc) { 303 TFP_DRV_LOG(ERR, 304 "Failed to allocate session client, rc:%s\n", 305 strerror(-rc)); 306 goto cleanup; 307 } 308 client = cparms.mem_va; 309 310 /* Register FID with the client */ 311 rc = tfp_get_fid(tfp, &client->fw_fid); 312 if (rc) 313 return rc; 314 315 /* Build the Session Client ID by adding the fw_session_id */ 316 rc = tf_session_get_fw_session_id 317 (tfp, 318 &session_client_id.internal.fw_session_id); 319 if (rc) { 320 TFP_DRV_LOG(ERR, 321 "Session Firmware id lookup failed, rc:%s\n", 322 strerror(-rc)); 323 return rc; 324 } 325 326 tfp_memcpy(client->ctrl_chan_name, 327 parms->ctrl_chan_name, 328 TF_SESSION_NAME_MAX); 329 330 client->session_client_id.id = session_client_id.id; 331 332 ll_insert(&session->client_ll, &client->ll_entry); 333 334 session->ref_count++; 335 336 /* Build the return value */ 337 parms->session_client_id->id = session_client_id.id; 338 339 cleanup: 340 /* TBD - Add code to unregister newly create client from fw */ 341 342 return rc; 343 } 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%8x\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 /* In case multiple clients we chose to close those first */ 539 if (tfs->ref_count > 1) { 540 /* Linaro gcc can't static init this structure */ 541 memset(&scdparms, 542 0, 543 sizeof(struct tf_session_client_destroy_parms)); 544 545 scdparms.session_client_id = client->session_client_id; 546 /* Destroy requested client so its no longer 547 * registered with this session. 548 */ 549 rc = tf_session_client_destroy(tfp, &scdparms); 550 if (rc) { 551 TFP_DRV_LOG(ERR, 552 "Failed to unregister Client %d, rc:%s\n", 553 client->session_client_id.id, 554 strerror(-rc)); 555 return rc; 556 } 557 558 TFP_DRV_LOG(INFO, 559 "Closed session client, session_client_id:%d\n", 560 client->session_client_id.id); 561 562 TFP_DRV_LOG(INFO, 563 "session_id:0x%08x, ref_count:%d\n", 564 tfs->session_id.id, 565 tfs->ref_count); 566 567 return 0; 568 } 569 570 /* Record the session we're closing so the caller knows the 571 * details. 572 */ 573 *parms->session_id = tfs->session_id; 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 struct tf_session_client * 709 tf_session_get_session_client(struct tf_session *tfs, 710 union tf_session_client_id session_client_id) 711 { 712 struct ll_entry *c_entry; 713 struct tf_session_client *client; 714 715 /* Skip using the check macro as we just want to return */ 716 if (tfs == NULL) 717 return NULL; 718 719 for (c_entry = tfs->client_ll.head; 720 c_entry != NULL; 721 c_entry = c_entry->next) { 722 client = (struct tf_session_client *)c_entry; 723 if (client->session_client_id.id == session_client_id.id) 724 return client; 725 } 726 727 return NULL; 728 } 729 730 struct tf_session_client * 731 tf_session_find_session_client_by_name(struct tf_session *tfs, 732 const char *ctrl_chan_name) 733 { 734 struct ll_entry *c_entry; 735 struct tf_session_client *client; 736 737 /* Skip using the check macro as we just want to return */ 738 if (tfs == NULL || ctrl_chan_name == NULL) 739 return NULL; 740 741 for (c_entry = tfs->client_ll.head; 742 c_entry != NULL; 743 c_entry = c_entry->next) { 744 client = (struct tf_session_client *)c_entry; 745 if (strncmp(client->ctrl_chan_name, 746 ctrl_chan_name, 747 TF_SESSION_NAME_MAX) == 0) 748 return client; 749 } 750 751 return NULL; 752 } 753 754 struct tf_session_client * 755 tf_session_find_session_client_by_fid(struct tf_session *tfs, 756 uint16_t fid) 757 { 758 struct ll_entry *c_entry; 759 struct tf_session_client *client; 760 761 /* Skip using the check macro as we just want to return */ 762 if (tfs == NULL) 763 return NULL; 764 765 for (c_entry = tfs->client_ll.head; 766 c_entry != NULL; 767 c_entry = c_entry->next) { 768 client = (struct tf_session_client *)c_entry; 769 if (client->fw_fid == fid) 770 return client; 771 } 772 773 return NULL; 774 } 775 776 int 777 tf_session_get_device(struct tf_session *tfs, 778 struct tf_dev_info **tfd) 779 { 780 *tfd = &tfs->dev; 781 782 return 0; 783 } 784 785 int 786 tf_session_get_fw_session_id(struct tf *tfp, 787 uint8_t *fw_session_id) 788 { 789 int rc; 790 struct tf_session *tfs = NULL; 791 792 /* Skip using the check macro as we want to control the error msg */ 793 if (tfp->session == NULL) { 794 rc = -EINVAL; 795 TFP_DRV_LOG(ERR, 796 "Session not created, rc:%s\n", 797 strerror(-rc)); 798 return rc; 799 } 800 801 if (fw_session_id == NULL) { 802 rc = -EINVAL; 803 TFP_DRV_LOG(ERR, 804 "Invalid Argument(s), rc:%s\n", 805 strerror(-rc)); 806 return rc; 807 } 808 809 rc = tf_session_get_session_internal(tfp, &tfs); 810 if (rc) 811 return rc; 812 813 *fw_session_id = tfs->session_id.internal.fw_session_id; 814 815 return 0; 816 } 817 818 int 819 tf_session_get_session_id(struct tf *tfp, 820 union tf_session_id *session_id) 821 { 822 int rc; 823 struct tf_session *tfs = NULL; 824 825 if (tfp->session == NULL) { 826 rc = -EINVAL; 827 TFP_DRV_LOG(ERR, 828 "Session not created, rc:%s\n", 829 strerror(-rc)); 830 return rc; 831 } 832 833 if (session_id == NULL) { 834 rc = -EINVAL; 835 TFP_DRV_LOG(ERR, 836 "Invalid Argument(s), rc:%s\n", 837 strerror(-rc)); 838 return rc; 839 } 840 841 /* Using internal version as session client may not exist yet */ 842 rc = tf_session_get_session_internal(tfp, &tfs); 843 if (rc) 844 return rc; 845 846 *session_id = tfs->session_id; 847 848 return 0; 849 } 850 851 int 852 tf_session_get_em_ext_db(struct tf *tfp, 853 void **em_ext_db_handle) 854 { 855 struct tf_session *tfs = NULL; 856 int rc = 0; 857 858 *em_ext_db_handle = NULL; 859 860 if (tfp == NULL) 861 return (-EINVAL); 862 863 rc = tf_session_get_session_internal(tfp, &tfs); 864 if (rc) 865 return rc; 866 867 *em_ext_db_handle = tfs->em_ext_db_handle; 868 return rc; 869 } 870 871 int 872 tf_session_set_em_ext_db(struct tf *tfp, 873 void *em_ext_db_handle) 874 { 875 struct tf_session *tfs = NULL; 876 int rc = 0; 877 878 if (tfp == NULL) 879 return (-EINVAL); 880 881 rc = tf_session_get_session_internal(tfp, &tfs); 882 if (rc) 883 return rc; 884 885 tfs->em_ext_db_handle = em_ext_db_handle; 886 return rc; 887 } 888 889 int 890 tf_session_get_db(struct tf *tfp, 891 enum tf_module_type type, 892 void **db_handle) 893 { 894 struct tf_session *tfs = NULL; 895 int rc = 0; 896 897 *db_handle = NULL; 898 899 if (tfp == NULL) 900 return (-EINVAL); 901 902 rc = tf_session_get_session_internal(tfp, &tfs); 903 if (rc) 904 return rc; 905 906 switch (type) { 907 case TF_MODULE_TYPE_IDENTIFIER: 908 if (tfs->id_db_handle) 909 *db_handle = tfs->id_db_handle; 910 else 911 rc = -ENOMEM; 912 break; 913 case TF_MODULE_TYPE_TABLE: 914 if (tfs->tbl_db_handle) 915 *db_handle = tfs->tbl_db_handle; 916 else 917 rc = -ENOMEM; 918 919 break; 920 case TF_MODULE_TYPE_TCAM: 921 if (tfs->tcam_db_handle) 922 *db_handle = tfs->tcam_db_handle; 923 else 924 rc = -ENOMEM; 925 break; 926 case TF_MODULE_TYPE_EM: 927 if (tfs->em_db_handle) 928 *db_handle = tfs->em_db_handle; 929 else 930 rc = -ENOMEM; 931 break; 932 default: 933 rc = -EINVAL; 934 break; 935 } 936 937 return rc; 938 } 939 940 int 941 tf_session_set_db(struct tf *tfp, 942 enum tf_module_type type, 943 void *db_handle) 944 { 945 struct tf_session *tfs = NULL; 946 int rc = 0; 947 948 if (tfp == NULL) 949 return (-EINVAL); 950 951 rc = tf_session_get_session_internal(tfp, &tfs); 952 if (rc) 953 return rc; 954 955 switch (type) { 956 case TF_MODULE_TYPE_IDENTIFIER: 957 tfs->id_db_handle = db_handle; 958 break; 959 case TF_MODULE_TYPE_TABLE: 960 tfs->tbl_db_handle = db_handle; 961 break; 962 case TF_MODULE_TYPE_TCAM: 963 tfs->tcam_db_handle = db_handle; 964 break; 965 case TF_MODULE_TYPE_EM: 966 tfs->em_db_handle = db_handle; 967 break; 968 default: 969 rc = -EINVAL; 970 break; 971 } 972 973 return rc; 974 } 975 976 #ifdef TF_TCAM_SHARED 977 978 int 979 tf_session_get_tcam_shared_db(struct tf *tfp, 980 void **tcam_shared_db_handle) 981 { 982 struct tf_session *tfs = NULL; 983 int rc = 0; 984 985 *tcam_shared_db_handle = NULL; 986 987 if (tfp == NULL) 988 return (-EINVAL); 989 990 rc = tf_session_get_session_internal(tfp, &tfs); 991 if (rc) 992 return rc; 993 994 *tcam_shared_db_handle = tfs->tcam_shared_db_handle; 995 return rc; 996 } 997 998 int 999 tf_session_set_tcam_shared_db(struct tf *tfp, 1000 void *tcam_shared_db_handle) 1001 { 1002 struct tf_session *tfs = NULL; 1003 int rc = 0; 1004 1005 if (tfp == NULL) 1006 return (-EINVAL); 1007 1008 rc = tf_session_get_session_internal(tfp, &tfs); 1009 if (rc) 1010 return rc; 1011 1012 tfs->tcam_shared_db_handle = tcam_shared_db_handle; 1013 return rc; 1014 } 1015 #endif /* TF_TCAM_SHARED */ 1016