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"
15 struct tf_session_client_create_parms {
17 * [in] Pointer to the control channel name string
22 * [out] Firmware Session Client ID
24 union tf_session_client_id *session_client_id;
27 struct tf_session_client_destroy_parms {
29 * FW Session Client Identifier
31 union tf_session_client_id session_client_id;
35 * Creates a Session and the associated client.
38 * Pointer to TF handle
41 * Pointer to session client create parameters
44 * - (0) if successful.
45 * - (-EINVAL) on failure.
46 * - (-ENOMEM) if max session clients has been reached.
49 tf_session_create(struct tf *tfp,
50 struct tf_session_open_session_parms *parms)
53 struct tf_session *session = NULL;
54 struct tf_session_client *client;
55 struct tfp_calloc_parms cparms;
56 uint8_t fw_session_id;
57 uint8_t fw_session_client_id;
58 union tf_session_id *session_id;
59 struct tf_dev_info dev;
61 TF_CHECK_PARMS2(tfp, parms);
63 tf_dev_bind_ops(parms->open_cfg->device_type,
66 /* Open FW session and get a new session_id */
67 rc = tf_msg_session_open(tfp,
68 parms->open_cfg->ctrl_chan_name,
70 &fw_session_client_id,
76 "Session is already open, rc:%s\n",
80 "Open message send failed, rc:%s\n",
83 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
87 /* Allocate session */
89 cparms.size = sizeof(struct tf_session_info);
91 rc = tfp_calloc(&cparms);
95 "Failed to allocate session info, rc:%s\n",
99 tfp->session = (struct tf_session_info *)cparms.mem_va;
101 /* Allocate core data for the session */
103 cparms.size = sizeof(struct tf_session);
104 cparms.alignment = 0;
105 rc = tfp_calloc(&cparms);
109 "Failed to allocate session data, rc:%s\n",
113 tfp->session->core_data = cparms.mem_va;
114 session_id = &parms->open_cfg->session_id;
116 /* Update Session Info, which is what is visible to the caller */
117 tfp->session->ver.major = 0;
118 tfp->session->ver.minor = 0;
119 tfp->session->ver.update = 0;
121 tfp->session->session_id.internal.domain = session_id->internal.domain;
122 tfp->session->session_id.internal.bus = session_id->internal.bus;
123 tfp->session->session_id.internal.device = session_id->internal.device;
124 tfp->session->session_id.internal.fw_session_id = fw_session_id;
126 /* Initialize Session and Device, which is private */
127 session = (struct tf_session *)tfp->session->core_data;
128 session->ver.major = 0;
129 session->ver.minor = 0;
130 session->ver.update = 0;
132 session->session_id.internal.domain = session_id->internal.domain;
133 session->session_id.internal.bus = session_id->internal.bus;
134 session->session_id.internal.device = session_id->internal.device;
135 session->session_id.internal.fw_session_id = fw_session_id;
136 /* Return the allocated session id */
137 session_id->id = session->session_id.id;
139 session->shadow_copy = parms->open_cfg->shadow_copy;
141 /* Init session client list */
142 ll_init(&session->client_ll);
144 /* Create the local session client, initialize and attach to
148 cparms.size = sizeof(struct tf_session_client);
149 cparms.alignment = 0;
150 rc = tfp_calloc(&cparms);
154 "Failed to allocate session client, rc:%s\n",
158 client = cparms.mem_va;
160 /* Register FID with the client */
161 rc = tfp_get_fid(tfp, &client->fw_fid);
165 client->session_client_id.internal.fw_session_id = fw_session_id;
166 client->session_client_id.internal.fw_session_client_id =
167 fw_session_client_id;
169 tfp_memcpy(client->ctrl_chan_name,
170 parms->open_cfg->ctrl_chan_name,
171 TF_SESSION_NAME_MAX);
173 ll_insert(&session->client_ll, &client->ll_entry);
174 session->ref_count++;
176 rc = tf_dev_bind(tfp,
177 parms->open_cfg->device_type,
178 session->shadow_copy,
179 &parms->open_cfg->resources,
181 /* Logging handled by dev_bind */
185 if (session->dev.ops->tf_dev_get_mailbox == NULL) {
188 "No tf_dev_get_mailbox() defined for device\n");
192 session->dev_init = true;
197 tfp_free(tfp->session->core_data);
198 tfp_free(tfp->session);
204 * Creates a Session Client on an existing Session.
207 * Pointer to TF handle
210 * Pointer to session client create parameters
213 * - (0) if successful.
214 * - (-EINVAL) on failure.
215 * - (-ENOMEM) if max session clients has been reached.
218 tf_session_client_create(struct tf *tfp,
219 struct tf_session_client_create_parms *parms)
222 struct tf_session *session = NULL;
223 struct tf_session_client *client;
224 struct tfp_calloc_parms cparms;
225 union tf_session_client_id session_client_id;
227 TF_CHECK_PARMS2(tfp, parms);
229 /* Using internal version as session client may not exist yet */
230 rc = tf_session_get_session_internal(tfp, &session);
233 "Failed to lookup session, rc:%s\n",
238 client = tf_session_find_session_client_by_name(session,
239 parms->ctrl_chan_name);
242 "Client %s, already registered with this session\n",
243 parms->ctrl_chan_name);
247 rc = tf_msg_session_client_register
250 parms->ctrl_chan_name,
251 &session_client_id.internal.fw_session_client_id);
254 "Failed to create client on session, rc:%s\n",
259 /* Create the local session client, initialize and attach to
263 cparms.size = sizeof(struct tf_session_client);
264 cparms.alignment = 0;
265 rc = tfp_calloc(&cparms);
268 "Failed to allocate session client, rc:%s\n",
272 client = cparms.mem_va;
274 /* Register FID with the client */
275 rc = tfp_get_fid(tfp, &client->fw_fid);
279 /* Build the Session Client ID by adding the fw_session_id */
280 rc = tf_session_get_fw_session_id
282 &session_client_id.internal.fw_session_id);
285 "Session Firmware id lookup failed, rc:%s\n",
290 tfp_memcpy(client->ctrl_chan_name,
291 parms->ctrl_chan_name,
292 TF_SESSION_NAME_MAX);
294 client->session_client_id.id = session_client_id.id;
296 ll_insert(&session->client_ll, &client->ll_entry);
298 session->ref_count++;
300 /* Build the return value */
301 parms->session_client_id->id = session_client_id.id;
304 /* TBD - Add code to unregister newly create client from fw */
311 * Destroys a Session Client on an existing Session.
314 * Pointer to TF handle
317 * Pointer to the session client destroy parameters
320 * - (0) if successful.
321 * - (-EINVAL) on failure.
322 * - (-ENOTFOUND) error, client not owned by the session.
323 * - (-ENOTSUPP) error, unable to destroy client as its the last
324 * client. Please use the tf_session_close().
327 tf_session_client_destroy(struct tf *tfp,
328 struct tf_session_client_destroy_parms *parms)
331 struct tf_session *tfs;
332 struct tf_session_client *client;
334 TF_CHECK_PARMS2(tfp, parms);
336 rc = tf_session_get_session(tfp, &tfs);
339 "Failed to lookup session, rc:%s\n",
344 /* Check session owns this client and that we're not the last client */
345 client = tf_session_get_session_client(tfs,
346 parms->session_client_id);
347 if (client == NULL) {
349 "Client %d, not found within this session\n",
350 parms->session_client_id.id);
354 /* If last client the request is rejected and cleanup should
355 * be done by session close.
357 if (tfs->ref_count == 1)
360 rc = tf_msg_session_client_unregister
363 parms->session_client_id.internal.fw_session_client_id);
365 /* Log error, but continue. If FW fails we do not really have
366 * a way to fix this but the client would no longer be valid
367 * thus we remove from the session.
371 "Client destroy on FW Failed, rc:%s\n",
375 ll_delete(&tfs->client_ll, &client->ll_entry);
377 /* Decrement the session ref_count */
386 tf_session_open_session(struct tf *tfp,
387 struct tf_session_open_session_parms *parms)
390 struct tf_session_client_create_parms scparms;
392 TF_CHECK_PARMS2(tfp, parms);
394 /* Decide if we're creating a new session or session client */
395 if (tfp->session == NULL) {
396 rc = tf_session_create(tfp, parms);
399 "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
400 parms->open_cfg->ctrl_chan_name,
406 "Session created, session_client_id:%d, session_id:%d\n",
407 parms->open_cfg->session_client_id.id,
408 parms->open_cfg->session_id.id);
410 scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
411 scparms.session_client_id = &parms->open_cfg->session_client_id;
413 /* Create the new client and get it associated with
416 rc = tf_session_client_create(tfp, &scparms);
419 "Failed to create client on session %d, rc:%s\n",
420 parms->open_cfg->session_id.id,
426 "Session Client:%d created on session:%d\n",
427 parms->open_cfg->session_client_id.id,
428 parms->open_cfg->session_id.id);
435 tf_session_attach_session(struct tf *tfp __rte_unused,
436 struct tf_session_attach_session_parms *parms __rte_unused)
438 int rc = -EOPNOTSUPP;
440 TF_CHECK_PARMS2(tfp, parms);
443 "Attach not yet supported, rc:%s\n",
449 tf_session_close_session(struct tf *tfp,
450 struct tf_session_close_session_parms *parms)
453 struct tf_session *tfs = NULL;
454 struct tf_session_client *client;
455 struct tf_dev_info *tfd = NULL;
456 struct tf_session_client_destroy_parms scdparms;
459 TF_CHECK_PARMS2(tfp, parms);
461 rc = tf_session_get_session(tfp, &tfs);
464 "Session lookup failed, rc:%s\n",
469 if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
472 "Invalid session id, unable to close, rc:%s\n",
477 /* Get the client, we need it independently of the closure
478 * type (client or session closure).
480 * We find the client by way of the fid. Thus one cannot close
481 * a client on behalf of someone else.
483 rc = tfp_get_fid(tfp, &fid);
487 client = tf_session_find_session_client_by_fid(tfs,
492 "Client not part of the session, unable to close, rc:%s\n",
497 /* In case multiple clients we chose to close those first */
498 if (tfs->ref_count > 1) {
499 /* Linaro gcc can't static init this structure */
502 sizeof(struct tf_session_client_destroy_parms));
504 scdparms.session_client_id = client->session_client_id;
505 /* Destroy requested client so its no longer
506 * registered with this session.
508 rc = tf_session_client_destroy(tfp, &scdparms);
511 "Failed to unregister Client %d, rc:%s\n",
512 client->session_client_id.id,
518 "Closed session client, session_client_id:%d\n",
519 client->session_client_id.id);
522 "session_id:%d, ref_count:%d\n",
529 /* Record the session we're closing so the caller knows the
532 *parms->session_id = tfs->session_id;
534 rc = tf_session_get_device(tfs, &tfd);
537 "Device lookup failed, rc:%s\n",
542 /* Unbind the device */
543 rc = tf_dev_unbind(tfp, tfd);
547 "Device unbind failed, rc:%s\n",
551 rc = tf_msg_session_close(tfp, tfs);
555 "FW Session close failed, rc:%s\n",
559 /* Final cleanup as we're last user of the session thus we
560 * also delete the last client.
562 ll_delete(&tfs->client_ll, &client->ll_entry);
568 "Closed session, session_id:%d, ref_count:%d\n",
572 tfs->dev_init = false;
574 tfp_free(tfp->session->core_data);
575 tfp_free(tfp->session);
582 tf_session_is_fid_supported(struct tf_session *tfs,
585 struct ll_entry *c_entry;
586 struct tf_session_client *client;
588 for (c_entry = tfs->client_ll.head;
590 c_entry = c_entry->next) {
591 client = (struct tf_session_client *)c_entry;
592 if (client->fw_fid == fid)
600 tf_session_get_session_internal(struct tf *tfp,
601 struct tf_session **tfs)
605 /* Skip using the check macro as we want to control the error msg */
606 if (tfp->session == NULL || tfp->session->core_data == NULL) {
609 "Session not created, rc:%s\n",
614 *tfs = (struct tf_session *)(tfp->session->core_data);
620 tf_session_get_session(struct tf *tfp,
621 struct tf_session **tfs)
625 bool supported = false;
627 rc = tf_session_get_session_internal(tfp,
629 /* Logging done by tf_session_get_session_internal */
633 /* As session sharing among functions aka 'individual clients'
634 * is supported we have to assure that the client is indeed
635 * registered before we get deep in the TruFlow api stack.
637 rc = tfp_get_fid(tfp, &fw_fid);
640 "Internal FID lookup\n, rc:%s\n",
645 supported = tf_session_is_fid_supported(*tfs, fw_fid);
649 "Ctrl channel not registered with session\n, rc:%s\n",
657 struct tf_session_client *
658 tf_session_get_session_client(struct tf_session *tfs,
659 union tf_session_client_id session_client_id)
661 struct ll_entry *c_entry;
662 struct tf_session_client *client;
664 /* Skip using the check macro as we just want to return */
668 for (c_entry = tfs->client_ll.head;
670 c_entry = c_entry->next) {
671 client = (struct tf_session_client *)c_entry;
672 if (client->session_client_id.id == session_client_id.id)
679 struct tf_session_client *
680 tf_session_find_session_client_by_name(struct tf_session *tfs,
681 const char *ctrl_chan_name)
683 struct ll_entry *c_entry;
684 struct tf_session_client *client;
686 /* Skip using the check macro as we just want to return */
687 if (tfs == NULL || ctrl_chan_name == NULL)
690 for (c_entry = tfs->client_ll.head;
692 c_entry = c_entry->next) {
693 client = (struct tf_session_client *)c_entry;
694 if (strncmp(client->ctrl_chan_name,
696 TF_SESSION_NAME_MAX) == 0)
703 struct tf_session_client *
704 tf_session_find_session_client_by_fid(struct tf_session *tfs,
707 struct ll_entry *c_entry;
708 struct tf_session_client *client;
710 /* Skip using the check macro as we just want to return */
714 for (c_entry = tfs->client_ll.head;
716 c_entry = c_entry->next) {
717 client = (struct tf_session_client *)c_entry;
718 if (client->fw_fid == fid)
726 tf_session_get_device(struct tf_session *tfs,
727 struct tf_dev_info **tfd)
735 tf_session_get_fw_session_id(struct tf *tfp,
736 uint8_t *fw_session_id)
739 struct tf_session *tfs = NULL;
741 /* Skip using the check macro as we want to control the error msg */
742 if (tfp->session == NULL) {
745 "Session not created, rc:%s\n",
750 if (fw_session_id == NULL) {
753 "Invalid Argument(s), rc:%s\n",
758 rc = tf_session_get_session_internal(tfp, &tfs);
762 *fw_session_id = tfs->session_id.internal.fw_session_id;
768 tf_session_get_session_id(struct tf *tfp,
769 union tf_session_id *session_id)
772 struct tf_session *tfs = NULL;
774 if (tfp->session == NULL) {
777 "Session not created, rc:%s\n",
782 if (session_id == NULL) {
785 "Invalid Argument(s), rc:%s\n",
790 /* Using internal version as session client may not exist yet */
791 rc = tf_session_get_session_internal(tfp, &tfs);
795 *session_id = tfs->session_id;