1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 Broadcom
8 #include <rte_common.h>
10 #include "tf_session.h"
11 #include "tf_common.h"
16 struct tf_session_client_create_parms {
18 * [in] Pointer to the control channel name string
23 * [out] Firmware Session Client ID
25 union tf_session_client_id *session_client_id;
28 struct tf_session_client_destroy_parms {
30 * FW Session Client Identifier
32 union tf_session_client_id session_client_id;
36 * Creates a Session and the associated client.
39 * Pointer to TF handle
42 * Pointer to session client create parameters
45 * - (0) if successful.
46 * - (-EINVAL) on failure.
47 * - (-ENOMEM) if max session clients has been reached.
50 tf_session_create(struct tf *tfp,
51 struct tf_session_open_session_parms *parms)
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;
65 TF_CHECK_PARMS2(tfp, parms);
67 tf_dev_bind_ops(parms->open_cfg->device_type,
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,
74 &fw_session_client_id,
76 &shared_session_creator);
81 "Session is already open, rc:%s\n",
85 "Open message send failed, rc:%s\n",
88 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
92 /* Allocate session */
94 cparms.size = sizeof(struct tf_session_info);
96 rc = tfp_calloc(&cparms);
100 "Failed to allocate session info, rc:%s\n",
104 tfp->session = (struct tf_session_info *)cparms.mem_va;
106 /* Allocate core data for the session */
108 cparms.size = sizeof(struct tf_session);
109 cparms.alignment = 0;
110 rc = tfp_calloc(&cparms);
114 "Failed to allocate session data, rc:%s\n",
118 tfp->session->core_data = cparms.mem_va;
119 session_id = &parms->open_cfg->session_id;
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;
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;
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;
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;
144 session->shadow_copy = parms->open_cfg->shadow_copy;
146 /* Init session client list */
147 ll_init(&session->client_ll);
149 /* Create the local session client, initialize and attach to
153 cparms.size = sizeof(struct tf_session_client);
154 cparms.alignment = 0;
155 rc = tfp_calloc(&cparms);
159 "Failed to allocate session client, rc:%s\n",
163 client = cparms.mem_va;
165 /* Register FID with the client */
166 rc = tfp_get_fid(tfp, &client->fw_fid);
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;
174 tfp_memcpy(client->ctrl_chan_name,
175 parms->open_cfg->ctrl_chan_name,
176 TF_SESSION_NAME_MAX);
178 ll_insert(&session->client_ll, &client->ll_entry);
179 session->ref_count++;
181 /* Init session em_ext_db */
182 session->em_ext_db_handle = NULL;
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;
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;
196 if (session->shared_session && shared_session_creator) {
197 session->shared_session_creator = true;
198 parms->open_cfg->shared_session_creator = true;
201 rc = tf_dev_bind(tfp,
202 parms->open_cfg->device_type,
203 session->shadow_copy,
204 &parms->open_cfg->resources,
205 parms->open_cfg->wc_num_slices,
208 /* Logging handled by dev_bind */
212 if (session->dev.ops->tf_dev_get_mailbox == NULL) {
215 "No tf_dev_get_mailbox() defined for device\n");
219 session->dev_init = true;
224 rc = tf_msg_session_close(tfp,
226 dev.ops->tf_dev_get_mailbox());
230 "FW Session close failed, rc:%s\n",
234 tfp_free(tfp->session->core_data);
235 tfp_free(tfp->session);
241 * Creates a Session Client on an existing Session.
244 * Pointer to TF handle
247 * Pointer to session client create parameters
250 * - (0) if successful.
251 * - (-EINVAL) on failure.
252 * - (-ENOMEM) if max session clients has been reached.
255 tf_session_client_create(struct tf *tfp,
256 struct tf_session_client_create_parms *parms)
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;
264 TF_CHECK_PARMS2(tfp, parms);
266 /* Using internal version as session client may not exist yet */
267 rc = tf_session_get_session_internal(tfp, &session);
270 "Failed to lookup session, rc:%s\n",
275 client = tf_session_find_session_client_by_name(session,
276 parms->ctrl_chan_name);
279 "Client %s, already registered with this session\n",
280 parms->ctrl_chan_name);
284 rc = tf_msg_session_client_register
287 parms->ctrl_chan_name,
288 &session_client_id.internal.fw_session_client_id);
291 "Failed to create client on session, rc:%s\n",
296 /* Create the local session client, initialize and attach to
300 cparms.size = sizeof(struct tf_session_client);
301 cparms.alignment = 0;
302 rc = tfp_calloc(&cparms);
305 "Failed to allocate session client, rc:%s\n",
309 client = cparms.mem_va;
311 /* Register FID with the client */
312 rc = tfp_get_fid(tfp, &client->fw_fid);
316 /* Build the Session Client ID by adding the fw_session_id */
317 rc = tf_session_get_fw_session_id
319 &session_client_id.internal.fw_session_id);
322 "Session Firmware id lookup failed, rc:%s\n",
327 tfp_memcpy(client->ctrl_chan_name,
328 parms->ctrl_chan_name,
329 TF_SESSION_NAME_MAX);
331 client->session_client_id.id = session_client_id.id;
333 ll_insert(&session->client_ll, &client->ll_entry);
335 session->ref_count++;
337 /* Build the return value */
338 parms->session_client_id->id = session_client_id.id;
341 /* TBD - Add code to unregister newly create client from fw */
348 * Destroys a Session Client on an existing Session.
351 * Pointer to TF handle
354 * Pointer to the session client destroy parameters
357 * - (0) if successful.
358 * - (-EINVAL) on failure.
359 * - (-ENOTFOUND) error, client not owned by the session.
360 * - (-ENOTSUPP) error, unable to destroy client as its the last
361 * client. Please use the tf_session_close().
364 tf_session_client_destroy(struct tf *tfp,
365 struct tf_session_client_destroy_parms *parms)
368 struct tf_session *tfs;
369 struct tf_session_client *client;
371 TF_CHECK_PARMS2(tfp, parms);
373 rc = tf_session_get_session(tfp, &tfs);
376 "Failed to lookup session, rc:%s\n",
381 /* Check session owns this client and that we're not the last client */
382 client = tf_session_get_session_client(tfs,
383 parms->session_client_id);
384 if (client == NULL) {
386 "Client %d, not found within this session\n",
387 parms->session_client_id.id);
391 /* If last client the request is rejected and cleanup should
392 * be done by session close.
394 if (tfs->ref_count == 1)
397 rc = tf_msg_session_client_unregister
400 parms->session_client_id.internal.fw_session_client_id);
402 /* Log error, but continue. If FW fails we do not really have
403 * a way to fix this but the client would no longer be valid
404 * thus we remove from the session.
408 "Client destroy on FW Failed, rc:%s\n",
412 ll_delete(&tfs->client_ll, &client->ll_entry);
414 /* Decrement the session ref_count */
423 tf_session_open_session(struct tf *tfp,
424 struct tf_session_open_session_parms *parms)
427 struct tf_session_client_create_parms scparms;
429 TF_CHECK_PARMS3(tfp, parms, parms->open_cfg->bp);
431 tfp->bp = parms->open_cfg->bp;
432 /* Decide if we're creating a new session or session client */
433 if (tfp->session == NULL) {
434 rc = tf_session_create(tfp, parms);
437 "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
438 parms->open_cfg->ctrl_chan_name,
444 "Session created, session_client_id:%d,"
445 "session_id:0x%08x, fw_session_id:%d\n",
446 parms->open_cfg->session_client_id.id,
447 parms->open_cfg->session_id.id,
448 parms->open_cfg->session_id.internal.fw_session_id);
450 scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
451 scparms.session_client_id = &parms->open_cfg->session_client_id;
453 /* Create the new client and get it associated with
456 rc = tf_session_client_create(tfp, &scparms);
459 "Failed to create client on session 0x%x, rc:%s\n",
460 parms->open_cfg->session_id.id,
466 "Session Client:%d registered on session:0x%8x\n",
467 scparms.session_client_id->internal.fw_session_client_id,
468 tfp->session->session_id.id);
475 tf_session_attach_session(struct tf *tfp __rte_unused,
476 struct tf_session_attach_session_parms *parms __rte_unused)
478 int rc = -EOPNOTSUPP;
480 TF_CHECK_PARMS2(tfp, parms);
483 "Attach not yet supported, rc:%s\n",
489 tf_session_close_session(struct tf *tfp,
490 struct tf_session_close_session_parms *parms)
493 struct tf_session *tfs = NULL;
494 struct tf_session_client *client;
495 struct tf_dev_info *tfd = NULL;
496 struct tf_session_client_destroy_parms scdparms;
498 uint8_t fw_session_id = 1;
501 TF_CHECK_PARMS2(tfp, parms);
503 rc = tf_session_get_session(tfp, &tfs);
506 "Session lookup failed, rc:%s\n",
511 if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
514 "Invalid session id, unable to close, rc:%s\n",
519 /* Get the client, we need it independently of the closure
520 * type (client or session closure).
522 * We find the client by way of the fid. Thus one cannot close
523 * a client on behalf of someone else.
525 rc = tfp_get_fid(tfp, &fid);
529 client = tf_session_find_session_client_by_fid(tfs,
534 "Client not part of the session, unable to close, rc:%s\n",
539 /* In case multiple clients we chose to close those first */
540 if (tfs->ref_count > 1) {
541 /* Linaro gcc can't static init this structure */
544 sizeof(struct tf_session_client_destroy_parms));
546 scdparms.session_client_id = client->session_client_id;
547 /* Destroy requested client so its no longer
548 * registered with this session.
550 rc = tf_session_client_destroy(tfp, &scdparms);
553 "Failed to unregister Client %d, rc:%s\n",
554 client->session_client_id.id,
560 "Closed session client, session_client_id:%d\n",
561 client->session_client_id.id);
564 "session_id:0x%08x, ref_count:%d\n",
571 /* Record the session we're closing so the caller knows the
574 *parms->session_id = tfs->session_id;
576 rc = tf_session_get_device(tfs, &tfd);
579 "Device lookup failed, rc:%s\n",
584 mailbox = tfd->ops->tf_dev_get_mailbox();
586 rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
589 "Unable to lookup FW id, rc:%s\n",
594 /* Unbind the device */
595 rc = tf_dev_unbind(tfp, tfd);
599 "Device unbind failed, rc:%s\n",
603 rc = tf_msg_session_close(tfp, fw_session_id, mailbox);
607 "FW Session close failed, rc:%s\n",
611 /* Final cleanup as we're last user of the session thus we
612 * also delete the last client.
614 ll_delete(&tfs->client_ll, &client->ll_entry);
620 "Closed session, session_id:0x%08x, ref_count:%d\n",
624 tfs->dev_init = false;
626 tfp_free(tfp->session->core_data);
627 tfp_free(tfp->session);
634 tf_session_is_fid_supported(struct tf_session *tfs,
637 struct ll_entry *c_entry;
638 struct tf_session_client *client;
640 for (c_entry = tfs->client_ll.head;
642 c_entry = c_entry->next) {
643 client = (struct tf_session_client *)c_entry;
644 if (client->fw_fid == fid)
652 tf_session_get_session_internal(struct tf *tfp,
653 struct tf_session **tfs)
657 /* Skip using the check macro as we want to control the error msg */
658 if (tfp->session == NULL || tfp->session->core_data == NULL) {
661 "Session not created, rc:%s\n",
666 *tfs = (struct tf_session *)(tfp->session->core_data);
672 tf_session_get_session(struct tf *tfp,
673 struct tf_session **tfs)
677 bool supported = false;
679 rc = tf_session_get_session_internal(tfp,
681 /* Logging done by tf_session_get_session_internal */
685 /* As session sharing among functions aka 'individual clients'
686 * is supported we have to assure that the client is indeed
687 * registered before we get deep in the TruFlow api stack.
689 rc = tfp_get_fid(tfp, &fw_fid);
692 "Internal FID lookup\n, rc:%s\n",
697 supported = tf_session_is_fid_supported(*tfs, fw_fid);
701 "Ctrl channel not registered with session\n, rc:%s\n",
709 int tf_session_get(struct tf *tfp,
710 struct tf_session **tfs,
711 struct tf_dev_info **tfd)
714 rc = tf_session_get_session_internal(tfp, tfs);
716 /* Logging done by tf_session_get_session_internal */
720 rc = tf_session_get_device(*tfs, tfd);
725 struct tf_session_client *
726 tf_session_get_session_client(struct tf_session *tfs,
727 union tf_session_client_id session_client_id)
729 struct ll_entry *c_entry;
730 struct tf_session_client *client;
732 /* Skip using the check macro as we just want to return */
736 for (c_entry = tfs->client_ll.head;
738 c_entry = c_entry->next) {
739 client = (struct tf_session_client *)c_entry;
740 if (client->session_client_id.id == session_client_id.id)
747 struct tf_session_client *
748 tf_session_find_session_client_by_name(struct tf_session *tfs,
749 const char *ctrl_chan_name)
751 struct ll_entry *c_entry;
752 struct tf_session_client *client;
754 /* Skip using the check macro as we just want to return */
755 if (tfs == NULL || ctrl_chan_name == NULL)
758 for (c_entry = tfs->client_ll.head;
760 c_entry = c_entry->next) {
761 client = (struct tf_session_client *)c_entry;
762 if (strncmp(client->ctrl_chan_name,
764 TF_SESSION_NAME_MAX) == 0)
771 struct tf_session_client *
772 tf_session_find_session_client_by_fid(struct tf_session *tfs,
775 struct ll_entry *c_entry;
776 struct tf_session_client *client;
778 /* Skip using the check macro as we just want to return */
782 for (c_entry = tfs->client_ll.head;
784 c_entry = c_entry->next) {
785 client = (struct tf_session_client *)c_entry;
786 if (client->fw_fid == fid)
794 tf_session_get_device(struct tf_session *tfs,
795 struct tf_dev_info **tfd)
803 tf_session_get_fw_session_id(struct tf *tfp,
804 uint8_t *fw_session_id)
807 struct tf_session *tfs = NULL;
809 /* Skip using the check macro as we want to control the error msg */
810 if (tfp->session == NULL) {
813 "Session not created, rc:%s\n",
818 if (fw_session_id == NULL) {
821 "Invalid Argument(s), rc:%s\n",
826 rc = tf_session_get_session_internal(tfp, &tfs);
830 *fw_session_id = tfs->session_id.internal.fw_session_id;
836 tf_session_get_session_id(struct tf *tfp,
837 union tf_session_id *session_id)
840 struct tf_session *tfs = NULL;
842 if (tfp->session == NULL) {
845 "Session not created, rc:%s\n",
850 if (session_id == NULL) {
853 "Invalid Argument(s), rc:%s\n",
858 /* Using internal version as session client may not exist yet */
859 rc = tf_session_get_session_internal(tfp, &tfs);
863 *session_id = tfs->session_id;
869 tf_session_get_em_ext_db(struct tf *tfp,
870 void **em_ext_db_handle)
872 struct tf_session *tfs = NULL;
875 *em_ext_db_handle = NULL;
880 rc = tf_session_get_session_internal(tfp, &tfs);
884 *em_ext_db_handle = tfs->em_ext_db_handle;
889 tf_session_set_em_ext_db(struct tf *tfp,
890 void *em_ext_db_handle)
892 struct tf_session *tfs = NULL;
898 rc = tf_session_get_session_internal(tfp, &tfs);
902 tfs->em_ext_db_handle = em_ext_db_handle;
907 tf_session_get_db(struct tf *tfp,
908 enum tf_module_type type,
911 struct tf_session *tfs = NULL;
919 rc = tf_session_get_session_internal(tfp, &tfs);
924 case TF_MODULE_TYPE_IDENTIFIER:
925 if (tfs->id_db_handle)
926 *db_handle = tfs->id_db_handle;
930 case TF_MODULE_TYPE_TABLE:
931 if (tfs->tbl_db_handle)
932 *db_handle = tfs->tbl_db_handle;
937 case TF_MODULE_TYPE_TCAM:
938 if (tfs->tcam_db_handle)
939 *db_handle = tfs->tcam_db_handle;
943 case TF_MODULE_TYPE_EM:
944 if (tfs->em_db_handle)
945 *db_handle = tfs->em_db_handle;
958 tf_session_set_db(struct tf *tfp,
959 enum tf_module_type type,
962 struct tf_session *tfs = NULL;
968 rc = tf_session_get_session_internal(tfp, &tfs);
973 case TF_MODULE_TYPE_IDENTIFIER:
974 tfs->id_db_handle = db_handle;
976 case TF_MODULE_TYPE_TABLE:
977 tfs->tbl_db_handle = db_handle;
979 case TF_MODULE_TYPE_TCAM:
980 tfs->tcam_db_handle = db_handle;
982 case TF_MODULE_TYPE_EM:
983 tfs->em_db_handle = db_handle;
993 #ifdef TF_TCAM_SHARED
996 tf_session_get_tcam_shared_db(struct tf *tfp,
997 void **tcam_shared_db_handle)
999 struct tf_session *tfs = NULL;
1002 *tcam_shared_db_handle = NULL;
1007 rc = tf_session_get_session_internal(tfp, &tfs);
1011 *tcam_shared_db_handle = tfs->tcam_shared_db_handle;
1016 tf_session_set_tcam_shared_db(struct tf *tfp,
1017 void *tcam_shared_db_handle)
1019 struct tf_session *tfs = NULL;
1025 rc = tf_session_get_session_internal(tfp, &tfs);
1029 tfs->tcam_shared_db_handle = tcam_shared_db_handle;
1034 tf_session_get_sram_db(struct tf *tfp,
1037 struct tf_session *tfs = NULL;
1040 *sram_handle = NULL;
1045 rc = tf_session_get_session_internal(tfp, &tfs);
1049 *sram_handle = tfs->sram_handle;
1054 tf_session_set_sram_db(struct tf *tfp,
1057 struct tf_session *tfs = NULL;
1063 rc = tf_session_get_session_internal(tfp, &tfs);
1067 tfs->sram_handle = sram_handle;
1071 #endif /* TF_TCAM_SHARED */