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;
63 TF_CHECK_PARMS2(tfp, parms);
65 tf_dev_bind_ops(parms->open_cfg->device_type,
68 /* Open FW session and get a new session_id */
69 rc = tf_msg_session_open(parms->open_cfg->bp,
70 parms->open_cfg->ctrl_chan_name,
72 &fw_session_client_id,
74 &shared_session_creator);
79 "Session is already open, rc:%s\n",
83 "Open message send failed, rc:%s\n",
86 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
90 /* Allocate session */
92 cparms.size = sizeof(struct tf_session_info);
94 rc = tfp_calloc(&cparms);
98 "Failed to allocate session info, rc:%s\n",
102 tfp->session = (struct tf_session_info *)cparms.mem_va;
104 /* Allocate core data for the session */
106 cparms.size = sizeof(struct tf_session);
107 cparms.alignment = 0;
108 rc = tfp_calloc(&cparms);
112 "Failed to allocate session data, rc:%s\n",
116 tfp->session->core_data = cparms.mem_va;
117 session_id = &parms->open_cfg->session_id;
119 /* Update Session Info, which is what is visible to the caller */
120 tfp->session->ver.major = 0;
121 tfp->session->ver.minor = 0;
122 tfp->session->ver.update = 0;
124 tfp->session->session_id.internal.domain = session_id->internal.domain;
125 tfp->session->session_id.internal.bus = session_id->internal.bus;
126 tfp->session->session_id.internal.device = session_id->internal.device;
127 tfp->session->session_id.internal.fw_session_id = fw_session_id;
129 /* Initialize Session and Device, which is private */
130 session = (struct tf_session *)tfp->session->core_data;
131 session->ver.major = 0;
132 session->ver.minor = 0;
133 session->ver.update = 0;
135 session->session_id.internal.domain = session_id->internal.domain;
136 session->session_id.internal.bus = session_id->internal.bus;
137 session->session_id.internal.device = session_id->internal.device;
138 session->session_id.internal.fw_session_id = fw_session_id;
139 /* Return the allocated session id */
140 session_id->id = session->session_id.id;
142 session->shadow_copy = parms->open_cfg->shadow_copy;
143 session->bp = parms->open_cfg->bp;
145 /* Init session client list */
146 ll_init(&session->client_ll);
148 /* Create the local session client, initialize and attach to
152 cparms.size = sizeof(struct tf_session_client);
153 cparms.alignment = 0;
154 rc = tfp_calloc(&cparms);
158 "Failed to allocate session client, rc:%s\n",
162 client = cparms.mem_va;
164 /* Register FID with the client */
165 rc = tfp_get_fid(tfp, &client->fw_fid);
169 client->session_client_id.internal.fw_session_id = fw_session_id;
170 client->session_client_id.internal.fw_session_client_id =
171 fw_session_client_id;
173 tfp_memcpy(client->ctrl_chan_name,
174 parms->open_cfg->ctrl_chan_name,
175 TF_SESSION_NAME_MAX);
177 ll_insert(&session->client_ll, &client->ll_entry);
178 session->ref_count++;
180 /* Init session em_ext_db */
181 session->em_ext_db_handle = NULL;
182 if (!strcmp(parms->open_cfg->ctrl_chan_name, "tf_share"))
183 session->shared_session = true;
185 if (session->shared_session && shared_session_creator) {
186 session->shared_session_creator = true;
187 parms->open_cfg->shared_session_creator = true;
190 rc = tf_dev_bind(tfp,
191 parms->open_cfg->device_type,
192 session->shadow_copy,
193 &parms->open_cfg->resources,
196 /* Logging handled by dev_bind */
200 if (session->dev.ops->tf_dev_get_mailbox == NULL) {
203 "No tf_dev_get_mailbox() defined for device\n");
207 session->dev_init = true;
212 tfp_free(tfp->session->core_data);
213 tfp_free(tfp->session);
219 * Creates a Session Client on an existing Session.
222 * Pointer to TF handle
225 * Pointer to session client create parameters
228 * - (0) if successful.
229 * - (-EINVAL) on failure.
230 * - (-ENOMEM) if max session clients has been reached.
233 tf_session_client_create(struct tf *tfp,
234 struct tf_session_client_create_parms *parms)
237 struct tf_session *session = NULL;
238 struct tf_session_client *client;
239 struct tfp_calloc_parms cparms;
240 union tf_session_client_id session_client_id;
242 TF_CHECK_PARMS2(tfp, parms);
244 /* Using internal version as session client may not exist yet */
245 rc = tf_session_get_session_internal(tfp, &session);
248 "Failed to lookup session, rc:%s\n",
253 client = tf_session_find_session_client_by_name(session,
254 parms->ctrl_chan_name);
257 "Client %s, already registered with this session\n",
258 parms->ctrl_chan_name);
262 rc = tf_msg_session_client_register
265 parms->ctrl_chan_name,
266 &session_client_id.internal.fw_session_client_id);
269 "Failed to create client on session, rc:%s\n",
274 /* Create the local session client, initialize and attach to
278 cparms.size = sizeof(struct tf_session_client);
279 cparms.alignment = 0;
280 rc = tfp_calloc(&cparms);
283 "Failed to allocate session client, rc:%s\n",
287 client = cparms.mem_va;
289 /* Register FID with the client */
290 rc = tfp_get_fid(tfp, &client->fw_fid);
294 /* Build the Session Client ID by adding the fw_session_id */
295 rc = tf_session_get_fw_session_id
297 &session_client_id.internal.fw_session_id);
300 "Session Firmware id lookup failed, rc:%s\n",
305 tfp_memcpy(client->ctrl_chan_name,
306 parms->ctrl_chan_name,
307 TF_SESSION_NAME_MAX);
309 client->session_client_id.id = session_client_id.id;
311 ll_insert(&session->client_ll, &client->ll_entry);
313 session->ref_count++;
315 /* Build the return value */
316 parms->session_client_id->id = session_client_id.id;
319 /* TBD - Add code to unregister newly create client from fw */
326 * Destroys a Session Client on an existing Session.
329 * Pointer to TF handle
332 * Pointer to the session client destroy parameters
335 * - (0) if successful.
336 * - (-EINVAL) on failure.
337 * - (-ENOTFOUND) error, client not owned by the session.
338 * - (-ENOTSUPP) error, unable to destroy client as its the last
339 * client. Please use the tf_session_close().
342 tf_session_client_destroy(struct tf *tfp,
343 struct tf_session_client_destroy_parms *parms)
346 struct tf_session *tfs;
347 struct tf_session_client *client;
349 TF_CHECK_PARMS2(tfp, parms);
351 rc = tf_session_get_session(tfp, &tfs);
354 "Failed to lookup session, rc:%s\n",
359 /* Check session owns this client and that we're not the last client */
360 client = tf_session_get_session_client(tfs,
361 parms->session_client_id);
362 if (client == NULL) {
364 "Client %d, not found within this session\n",
365 parms->session_client_id.id);
369 /* If last client the request is rejected and cleanup should
370 * be done by session close.
372 if (tfs->ref_count == 1)
375 rc = tf_msg_session_client_unregister
378 parms->session_client_id.internal.fw_session_client_id);
380 /* Log error, but continue. If FW fails we do not really have
381 * a way to fix this but the client would no longer be valid
382 * thus we remove from the session.
386 "Client destroy on FW Failed, rc:%s\n",
390 ll_delete(&tfs->client_ll, &client->ll_entry);
392 /* Decrement the session ref_count */
401 tf_session_open_session(struct tf *tfp,
402 struct tf_session_open_session_parms *parms)
405 struct tf_session_client_create_parms scparms;
407 TF_CHECK_PARMS2(tfp, parms);
409 /* Decide if we're creating a new session or session client */
410 if (tfp->session == NULL) {
411 rc = tf_session_create(tfp, parms);
414 "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
415 parms->open_cfg->ctrl_chan_name,
421 "Session created, session_client_id:%d, session_id:%d\n",
422 parms->open_cfg->session_client_id.id,
423 parms->open_cfg->session_id.id);
425 scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
426 scparms.session_client_id = &parms->open_cfg->session_client_id;
428 /* Create the new client and get it associated with
431 rc = tf_session_client_create(tfp, &scparms);
434 "Failed to create client on session %d, rc:%s\n",
435 parms->open_cfg->session_id.id,
441 "Session Client:%d created on session:%d\n",
442 parms->open_cfg->session_client_id.id,
443 parms->open_cfg->session_id.id);
450 tf_session_attach_session(struct tf *tfp __rte_unused,
451 struct tf_session_attach_session_parms *parms __rte_unused)
453 int rc = -EOPNOTSUPP;
455 TF_CHECK_PARMS2(tfp, parms);
458 "Attach not yet supported, rc:%s\n",
464 tf_session_close_session(struct tf *tfp,
465 struct tf_session_close_session_parms *parms)
468 struct tf_session *tfs = NULL;
469 struct tf_session_client *client;
470 struct tf_dev_info *tfd = NULL;
471 struct tf_session_client_destroy_parms scdparms;
474 TF_CHECK_PARMS2(tfp, parms);
476 rc = tf_session_get_session(tfp, &tfs);
479 "Session lookup failed, rc:%s\n",
484 if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
487 "Invalid session id, unable to close, rc:%s\n",
492 /* Get the client, we need it independently of the closure
493 * type (client or session closure).
495 * We find the client by way of the fid. Thus one cannot close
496 * a client on behalf of someone else.
498 rc = tfp_get_fid(tfp, &fid);
502 client = tf_session_find_session_client_by_fid(tfs,
507 "Client not part of the session, unable to close, rc:%s\n",
512 /* In case multiple clients we chose to close those first */
513 if (tfs->ref_count > 1) {
514 /* Linaro gcc can't static init this structure */
517 sizeof(struct tf_session_client_destroy_parms));
519 scdparms.session_client_id = client->session_client_id;
520 /* Destroy requested client so its no longer
521 * registered with this session.
523 rc = tf_session_client_destroy(tfp, &scdparms);
526 "Failed to unregister Client %d, rc:%s\n",
527 client->session_client_id.id,
533 "Closed session client, session_client_id:%d\n",
534 client->session_client_id.id);
537 "session_id:%d, ref_count:%d\n",
544 /* Record the session we're closing so the caller knows the
547 *parms->session_id = tfs->session_id;
549 rc = tf_session_get_device(tfs, &tfd);
552 "Device lookup failed, rc:%s\n",
557 /* Unbind the device */
558 rc = tf_dev_unbind(tfp, tfd);
562 "Device unbind failed, rc:%s\n",
566 rc = tf_msg_session_close(tfp, tfs);
570 "FW Session close failed, rc:%s\n",
574 /* Final cleanup as we're last user of the session thus we
575 * also delete the last client.
577 ll_delete(&tfs->client_ll, &client->ll_entry);
583 "Closed session, session_id:%d, ref_count:%d\n",
587 tfs->dev_init = false;
589 tfp_free(tfp->session->core_data);
590 tfp_free(tfp->session);
597 tf_session_is_fid_supported(struct tf_session *tfs,
600 struct ll_entry *c_entry;
601 struct tf_session_client *client;
603 for (c_entry = tfs->client_ll.head;
605 c_entry = c_entry->next) {
606 client = (struct tf_session_client *)c_entry;
607 if (client->fw_fid == fid)
615 tf_session_get_session_internal(struct tf *tfp,
616 struct tf_session **tfs)
620 /* Skip using the check macro as we want to control the error msg */
621 if (tfp->session == NULL || tfp->session->core_data == NULL) {
624 "Session not created, rc:%s\n",
629 *tfs = (struct tf_session *)(tfp->session->core_data);
635 tf_session_get_session(struct tf *tfp,
636 struct tf_session **tfs)
640 bool supported = false;
642 rc = tf_session_get_session_internal(tfp,
644 /* Logging done by tf_session_get_session_internal */
648 /* As session sharing among functions aka 'individual clients'
649 * is supported we have to assure that the client is indeed
650 * registered before we get deep in the TruFlow api stack.
652 rc = tfp_get_fid(tfp, &fw_fid);
655 "Internal FID lookup\n, rc:%s\n",
660 supported = tf_session_is_fid_supported(*tfs, fw_fid);
664 "Ctrl channel not registered with session\n, rc:%s\n",
672 struct tf_session_client *
673 tf_session_get_session_client(struct tf_session *tfs,
674 union tf_session_client_id session_client_id)
676 struct ll_entry *c_entry;
677 struct tf_session_client *client;
679 /* Skip using the check macro as we just want to return */
683 for (c_entry = tfs->client_ll.head;
685 c_entry = c_entry->next) {
686 client = (struct tf_session_client *)c_entry;
687 if (client->session_client_id.id == session_client_id.id)
694 struct tf_session_client *
695 tf_session_find_session_client_by_name(struct tf_session *tfs,
696 const char *ctrl_chan_name)
698 struct ll_entry *c_entry;
699 struct tf_session_client *client;
701 /* Skip using the check macro as we just want to return */
702 if (tfs == NULL || ctrl_chan_name == NULL)
705 for (c_entry = tfs->client_ll.head;
707 c_entry = c_entry->next) {
708 client = (struct tf_session_client *)c_entry;
709 if (strncmp(client->ctrl_chan_name,
711 TF_SESSION_NAME_MAX) == 0)
718 struct tf_session_client *
719 tf_session_find_session_client_by_fid(struct tf_session *tfs,
722 struct ll_entry *c_entry;
723 struct tf_session_client *client;
725 /* Skip using the check macro as we just want to return */
729 for (c_entry = tfs->client_ll.head;
731 c_entry = c_entry->next) {
732 client = (struct tf_session_client *)c_entry;
733 if (client->fw_fid == fid)
741 tf_session_get_device(struct tf_session *tfs,
742 struct tf_dev_info **tfd)
750 tf_session_get_fw_session_id(struct tf *tfp,
751 uint8_t *fw_session_id)
754 struct tf_session *tfs = NULL;
756 /* Skip using the check macro as we want to control the error msg */
757 if (tfp->session == NULL) {
760 "Session not created, rc:%s\n",
765 if (fw_session_id == NULL) {
768 "Invalid Argument(s), rc:%s\n",
773 rc = tf_session_get_session_internal(tfp, &tfs);
777 *fw_session_id = tfs->session_id.internal.fw_session_id;
783 tf_session_get_session_id(struct tf *tfp,
784 union tf_session_id *session_id)
787 struct tf_session *tfs = NULL;
789 if (tfp->session == NULL) {
792 "Session not created, rc:%s\n",
797 if (session_id == NULL) {
800 "Invalid Argument(s), rc:%s\n",
805 /* Using internal version as session client may not exist yet */
806 rc = tf_session_get_session_internal(tfp, &tfs);
810 *session_id = tfs->session_id;
816 tf_session_get_em_ext_db(struct tf *tfp,
817 void **em_ext_db_handle)
819 struct tf_session *tfs = NULL;
822 *em_ext_db_handle = NULL;
827 rc = tf_session_get_session_internal(tfp, &tfs);
831 *em_ext_db_handle = tfs->em_ext_db_handle;
836 tf_session_set_em_ext_db(struct tf *tfp,
837 void *em_ext_db_handle)
839 struct tf_session *tfs = NULL;
845 rc = tf_session_get_session_internal(tfp, &tfs);
849 tfs->em_ext_db_handle = em_ext_db_handle;
854 tf_session_get_db(struct tf *tfp,
855 enum tf_module_type type,
858 struct tf_session *tfs = NULL;
866 rc = tf_session_get_session_internal(tfp, &tfs);
871 case TF_MODULE_TYPE_IDENTIFIER:
872 if (tfs->id_db_handle)
873 *db_handle = tfs->id_db_handle;
877 case TF_MODULE_TYPE_TABLE:
878 if (tfs->tbl_db_handle)
879 *db_handle = tfs->tbl_db_handle;
884 case TF_MODULE_TYPE_TCAM:
885 if (tfs->tcam_db_handle)
886 *db_handle = tfs->tcam_db_handle;
890 case TF_MODULE_TYPE_EM:
891 if (tfs->em_db_handle)
892 *db_handle = tfs->em_db_handle;
905 tf_session_set_db(struct tf *tfp,
906 enum tf_module_type type,
909 struct tf_session *tfs = NULL;
915 rc = tf_session_get_session_internal(tfp, &tfs);
920 case TF_MODULE_TYPE_IDENTIFIER:
921 tfs->id_db_handle = db_handle;
923 case TF_MODULE_TYPE_TABLE:
924 tfs->tbl_db_handle = db_handle;
926 case TF_MODULE_TYPE_TCAM:
927 tfs->tcam_db_handle = db_handle;
929 case TF_MODULE_TYPE_EM:
930 tfs->em_db_handle = db_handle;