xref: /dpdk/drivers/net/bnxt/tf_core/tf_session.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
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 
15 struct tf_session_client_create_parms {
16 	/**
17 	 * [in] Pointer to the control channel name string
18 	 */
19 	char *ctrl_chan_name;
20 
21 	/**
22 	 * [out] Firmware Session Client ID
23 	 */
24 	union tf_session_client_id *session_client_id;
25 };
26 
27 struct tf_session_client_destroy_parms {
28 	/**
29 	 * FW Session Client Identifier
30 	 */
31 	union tf_session_client_id session_client_id;
32 };
33 
34 /**
35  * Creates a Session and the associated client.
36  *
37  * [in] tfp
38  *   Pointer to TF handle
39  *
40  * [in] parms
41  *   Pointer to session client create parameters
42  *
43  * Returns
44  *   - (0) if successful.
45  *   - (-EINVAL) on failure.
46  *   - (-ENOMEM) if max session clients has been reached.
47  */
48 static int
49 tf_session_create(struct tf *tfp,
50 		  struct tf_session_open_session_parms *parms)
51 {
52 	int rc;
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 
60 	TF_CHECK_PARMS2(tfp, parms);
61 
62 	/* Open FW session and get a new session_id */
63 	rc = tf_msg_session_open(tfp,
64 				 parms->open_cfg->ctrl_chan_name,
65 				 &fw_session_id,
66 				 &fw_session_client_id);
67 	if (rc) {
68 		/* Log error */
69 		if (rc == -EEXIST)
70 			TFP_DRV_LOG(ERR,
71 				    "Session is already open, rc:%s\n",
72 				    strerror(-rc));
73 		else
74 			TFP_DRV_LOG(ERR,
75 				    "Open message send failed, rc:%s\n",
76 				    strerror(-rc));
77 
78 		parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
79 		return rc;
80 	}
81 
82 	/* Allocate session */
83 	cparms.nitems = 1;
84 	cparms.size = sizeof(struct tf_session_info);
85 	cparms.alignment = 0;
86 	rc = tfp_calloc(&cparms);
87 	if (rc) {
88 		/* Log error */
89 		TFP_DRV_LOG(ERR,
90 			    "Failed to allocate session info, rc:%s\n",
91 			    strerror(-rc));
92 		goto cleanup;
93 	}
94 	tfp->session = (struct tf_session_info *)cparms.mem_va;
95 
96 	/* Allocate core data for the session */
97 	cparms.nitems = 1;
98 	cparms.size = sizeof(struct tf_session);
99 	cparms.alignment = 0;
100 	rc = tfp_calloc(&cparms);
101 	if (rc) {
102 		/* Log error */
103 		TFP_DRV_LOG(ERR,
104 			    "Failed to allocate session data, rc:%s\n",
105 			    strerror(-rc));
106 		goto cleanup;
107 	}
108 	tfp->session->core_data = cparms.mem_va;
109 	session_id = &parms->open_cfg->session_id;
110 
111 	/* Update Session Info, which is what is visible to the caller */
112 	tfp->session->ver.major = 0;
113 	tfp->session->ver.minor = 0;
114 	tfp->session->ver.update = 0;
115 
116 	tfp->session->session_id.internal.domain = session_id->internal.domain;
117 	tfp->session->session_id.internal.bus = session_id->internal.bus;
118 	tfp->session->session_id.internal.device = session_id->internal.device;
119 	tfp->session->session_id.internal.fw_session_id = fw_session_id;
120 
121 	/* Initialize Session and Device, which is private */
122 	session = (struct tf_session *)tfp->session->core_data;
123 	session->ver.major = 0;
124 	session->ver.minor = 0;
125 	session->ver.update = 0;
126 
127 	session->session_id.internal.domain = session_id->internal.domain;
128 	session->session_id.internal.bus = session_id->internal.bus;
129 	session->session_id.internal.device = session_id->internal.device;
130 	session->session_id.internal.fw_session_id = fw_session_id;
131 	/* Return the allocated session id */
132 	session_id->id = session->session_id.id;
133 
134 	session->shadow_copy = parms->open_cfg->shadow_copy;
135 
136 	/* Init session client list */
137 	ll_init(&session->client_ll);
138 
139 	/* Create the local session client, initialize and attach to
140 	 * the session
141 	 */
142 	cparms.nitems = 1;
143 	cparms.size = sizeof(struct tf_session_client);
144 	cparms.alignment = 0;
145 	rc = tfp_calloc(&cparms);
146 	if (rc) {
147 		/* Log error */
148 		TFP_DRV_LOG(ERR,
149 			    "Failed to allocate session client, rc:%s\n",
150 			    strerror(-rc));
151 		goto cleanup;
152 	}
153 	client = cparms.mem_va;
154 
155 	/* Register FID with the client */
156 	rc = tfp_get_fid(tfp, &client->fw_fid);
157 	if (rc)
158 		return rc;
159 
160 	client->session_client_id.internal.fw_session_id = fw_session_id;
161 	client->session_client_id.internal.fw_session_client_id =
162 		fw_session_client_id;
163 
164 	tfp_memcpy(client->ctrl_chan_name,
165 		   parms->open_cfg->ctrl_chan_name,
166 		   TF_SESSION_NAME_MAX);
167 
168 	ll_insert(&session->client_ll, &client->ll_entry);
169 	session->ref_count++;
170 
171 	rc = tf_dev_bind(tfp,
172 			 parms->open_cfg->device_type,
173 			 session->shadow_copy,
174 			 &parms->open_cfg->resources,
175 			 &session->dev);
176 	/* Logging handled by dev_bind */
177 	if (rc)
178 		return rc;
179 
180 	session->dev_init = true;
181 
182 	return 0;
183 
184  cleanup:
185 	tfp_free(tfp->session->core_data);
186 	tfp_free(tfp->session);
187 	tfp->session = NULL;
188 	return rc;
189 }
190 
191 /**
192  * Creates a Session Client on an existing Session.
193  *
194  * [in] tfp
195  *   Pointer to TF handle
196  *
197  * [in] parms
198  *   Pointer to session client create parameters
199  *
200  * Returns
201  *   - (0) if successful.
202  *   - (-EINVAL) on failure.
203  *   - (-ENOMEM) if max session clients has been reached.
204  */
205 static int
206 tf_session_client_create(struct tf *tfp,
207 			 struct tf_session_client_create_parms *parms)
208 {
209 	int rc;
210 	struct tf_session *session = NULL;
211 	struct tf_session_client *client;
212 	struct tfp_calloc_parms cparms;
213 	union tf_session_client_id session_client_id;
214 
215 	TF_CHECK_PARMS2(tfp, parms);
216 
217 	/* Using internal version as session client may not exist yet */
218 	rc = tf_session_get_session_internal(tfp, &session);
219 	if (rc) {
220 		TFP_DRV_LOG(ERR,
221 			    "Failed to lookup session, rc:%s\n",
222 			    strerror(-rc));
223 		return rc;
224 	}
225 
226 	client = tf_session_find_session_client_by_name(session,
227 							parms->ctrl_chan_name);
228 	if (client) {
229 		TFP_DRV_LOG(ERR,
230 			    "Client %s, already registered with this session\n",
231 			    parms->ctrl_chan_name);
232 		return -EOPNOTSUPP;
233 	}
234 
235 	rc = tf_msg_session_client_register
236 		    (tfp,
237 		    parms->ctrl_chan_name,
238 		    &session_client_id.internal.fw_session_client_id);
239 	if (rc) {
240 		TFP_DRV_LOG(ERR,
241 			    "Failed to create client on session, rc:%s\n",
242 			    strerror(-rc));
243 		return rc;
244 	}
245 
246 	/* Create the local session client, initialize and attach to
247 	 * the session
248 	 */
249 	cparms.nitems = 1;
250 	cparms.size = sizeof(struct tf_session_client);
251 	cparms.alignment = 0;
252 	rc = tfp_calloc(&cparms);
253 	if (rc) {
254 		TFP_DRV_LOG(ERR,
255 			    "Failed to allocate session client, rc:%s\n",
256 			    strerror(-rc));
257 		goto cleanup;
258 	}
259 	client = cparms.mem_va;
260 
261 	/* Register FID with the client */
262 	rc = tfp_get_fid(tfp, &client->fw_fid);
263 	if (rc)
264 		return rc;
265 
266 	/* Build the Session Client ID by adding the fw_session_id */
267 	rc = tf_session_get_fw_session_id
268 			(tfp,
269 			&session_client_id.internal.fw_session_id);
270 	if (rc) {
271 		TFP_DRV_LOG(ERR,
272 			    "Session Firmware id lookup failed, rc:%s\n",
273 			    strerror(-rc));
274 		return rc;
275 	}
276 
277 	tfp_memcpy(client->ctrl_chan_name,
278 		   parms->ctrl_chan_name,
279 		   TF_SESSION_NAME_MAX);
280 
281 	client->session_client_id.id = session_client_id.id;
282 
283 	ll_insert(&session->client_ll, &client->ll_entry);
284 
285 	session->ref_count++;
286 
287 	/* Build the return value */
288 	parms->session_client_id->id = session_client_id.id;
289 
290  cleanup:
291 	/* TBD - Add code to unregister newly create client from fw */
292 
293 	return rc;
294 }
295 
296 
297 /**
298  * Destroys a Session Client on an existing Session.
299  *
300  * [in] tfp
301  *   Pointer to TF handle
302  *
303  * [in] parms
304  *   Pointer to the session client destroy parameters
305  *
306  * Returns
307  *   - (0) if successful.
308  *   - (-EINVAL) on failure.
309  *   - (-ENOTFOUND) error, client not owned by the session.
310  *   - (-ENOTSUPP) error, unable to destroy client as its the last
311  *                 client. Please use the tf_session_close().
312  */
313 static int
314 tf_session_client_destroy(struct tf *tfp,
315 			  struct tf_session_client_destroy_parms *parms)
316 {
317 	int rc;
318 	struct tf_session *tfs;
319 	struct tf_session_client *client;
320 
321 	TF_CHECK_PARMS2(tfp, parms);
322 
323 	rc = tf_session_get_session(tfp, &tfs);
324 	if (rc) {
325 		TFP_DRV_LOG(ERR,
326 			    "Failed to lookup session, rc:%s\n",
327 			    strerror(-rc));
328 		return rc;
329 	}
330 
331 	/* Check session owns this client and that we're not the last client */
332 	client = tf_session_get_session_client(tfs,
333 					       parms->session_client_id);
334 	if (client == NULL) {
335 		TFP_DRV_LOG(ERR,
336 			    "Client %d, not found within this session\n",
337 			    parms->session_client_id.id);
338 		return -EINVAL;
339 	}
340 
341 	/* If last client the request is rejected and cleanup should
342 	 * be done by session close.
343 	 */
344 	if (tfs->ref_count == 1)
345 		return -EOPNOTSUPP;
346 
347 	rc = tf_msg_session_client_unregister
348 			(tfp,
349 			parms->session_client_id.internal.fw_session_client_id);
350 
351 	/* Log error, but continue. If FW fails we do not really have
352 	 * a way to fix this but the client would no longer be valid
353 	 * thus we remove from the session.
354 	 */
355 	if (rc) {
356 		TFP_DRV_LOG(ERR,
357 			    "Client destroy on FW Failed, rc:%s\n",
358 			    strerror(-rc));
359 	}
360 
361 	ll_delete(&tfs->client_ll, &client->ll_entry);
362 
363 	/* Decrement the session ref_count */
364 	tfs->ref_count--;
365 
366 	tfp_free(client);
367 
368 	return rc;
369 }
370 
371 int
372 tf_session_open_session(struct tf *tfp,
373 			struct tf_session_open_session_parms *parms)
374 {
375 	int rc;
376 	struct tf_session_client_create_parms scparms;
377 
378 	TF_CHECK_PARMS2(tfp, parms);
379 
380 	/* Decide if we're creating a new session or session client */
381 	if (tfp->session == NULL) {
382 		rc = tf_session_create(tfp, parms);
383 		if (rc) {
384 			TFP_DRV_LOG(ERR,
385 				    "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
386 				    parms->open_cfg->ctrl_chan_name,
387 				    strerror(-rc));
388 			return rc;
389 		}
390 
391 		TFP_DRV_LOG(INFO,
392 		       "Session created, session_client_id:%d, session_id:%d\n",
393 		       parms->open_cfg->session_client_id.id,
394 		       parms->open_cfg->session_id.id);
395 	} else {
396 		scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
397 		scparms.session_client_id = &parms->open_cfg->session_client_id;
398 
399 		/* Create the new client and get it associated with
400 		 * the session.
401 		 */
402 		rc = tf_session_client_create(tfp, &scparms);
403 		if (rc) {
404 			TFP_DRV_LOG(ERR,
405 			      "Failed to create client on session %d, rc:%s\n",
406 			      parms->open_cfg->session_id.id,
407 			      strerror(-rc));
408 			return rc;
409 		}
410 
411 		TFP_DRV_LOG(INFO,
412 			    "Session Client:%d created on session:%d\n",
413 			    parms->open_cfg->session_client_id.id,
414 			    parms->open_cfg->session_id.id);
415 	}
416 
417 	return 0;
418 }
419 
420 int
421 tf_session_attach_session(struct tf *tfp __rte_unused,
422 			  struct tf_session_attach_session_parms *parms __rte_unused)
423 {
424 	int rc = -EOPNOTSUPP;
425 
426 	TF_CHECK_PARMS2(tfp, parms);
427 
428 	TFP_DRV_LOG(ERR,
429 		    "Attach not yet supported, rc:%s\n",
430 		    strerror(-rc));
431 	return rc;
432 }
433 
434 int
435 tf_session_close_session(struct tf *tfp,
436 			 struct tf_session_close_session_parms *parms)
437 {
438 	int rc;
439 	struct tf_session *tfs = NULL;
440 	struct tf_session_client *client;
441 	struct tf_dev_info *tfd = NULL;
442 	struct tf_session_client_destroy_parms scdparms;
443 	uint16_t fid;
444 
445 	TF_CHECK_PARMS2(tfp, parms);
446 
447 	rc = tf_session_get_session(tfp, &tfs);
448 	if (rc) {
449 		TFP_DRV_LOG(ERR,
450 			    "Session lookup failed, rc:%s\n",
451 			    strerror(-rc));
452 		return rc;
453 	}
454 
455 	if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
456 		rc = -EINVAL;
457 		TFP_DRV_LOG(ERR,
458 			    "Invalid session id, unable to close, rc:%s\n",
459 			    strerror(-rc));
460 		return rc;
461 	}
462 
463 	/* Get the client, we need it independently of the closure
464 	 * type (client or session closure).
465 	 *
466 	 * We find the client by way of the fid. Thus one cannot close
467 	 * a client on behalf of someone else.
468 	 */
469 	rc = tfp_get_fid(tfp, &fid);
470 	if (rc)
471 		return rc;
472 
473 	client = tf_session_find_session_client_by_fid(tfs,
474 						       fid);
475 	if (!client) {
476 		rc = -EINVAL;
477 		TFP_DRV_LOG(ERR,
478 			    "Client not part of the session, unable to close, rc:%s\n",
479 			    strerror(-rc));
480 		return rc;
481 	}
482 
483 	/* In case multiple clients we chose to close those first */
484 	if (tfs->ref_count > 1) {
485 		/* Linaro gcc can't static init this structure */
486 		memset(&scdparms,
487 		       0,
488 		       sizeof(struct tf_session_client_destroy_parms));
489 
490 		scdparms.session_client_id = client->session_client_id;
491 		/* Destroy requested client so its no longer
492 		 * registered with this session.
493 		 */
494 		rc = tf_session_client_destroy(tfp, &scdparms);
495 		if (rc) {
496 			TFP_DRV_LOG(ERR,
497 				    "Failed to unregister Client %d, rc:%s\n",
498 				    client->session_client_id.id,
499 				    strerror(-rc));
500 			return rc;
501 		}
502 
503 		TFP_DRV_LOG(INFO,
504 			    "Closed session client, session_client_id:%d\n",
505 			    client->session_client_id.id);
506 
507 		TFP_DRV_LOG(INFO,
508 			    "session_id:%d, ref_count:%d\n",
509 			    tfs->session_id.id,
510 			    tfs->ref_count);
511 
512 		return 0;
513 	}
514 
515 	/* Record the session we're closing so the caller knows the
516 	 * details.
517 	 */
518 	*parms->session_id = tfs->session_id;
519 
520 	rc = tf_session_get_device(tfs, &tfd);
521 	if (rc) {
522 		TFP_DRV_LOG(ERR,
523 			    "Device lookup failed, rc:%s\n",
524 			    strerror(-rc));
525 		return rc;
526 	}
527 
528 	/* Unbind the device */
529 	rc = tf_dev_unbind(tfp, tfd);
530 	if (rc) {
531 		/* Log error */
532 		TFP_DRV_LOG(ERR,
533 			    "Device unbind failed, rc:%s\n",
534 			    strerror(-rc));
535 	}
536 
537 	rc = tf_msg_session_close(tfp);
538 	if (rc) {
539 		/* Log error */
540 		TFP_DRV_LOG(ERR,
541 			    "FW Session close failed, rc:%s\n",
542 			    strerror(-rc));
543 	}
544 
545 	/* Final cleanup as we're last user of the session thus we
546 	 * also delete the last client.
547 	 */
548 	ll_delete(&tfs->client_ll, &client->ll_entry);
549 	tfp_free(client);
550 
551 	tfs->ref_count--;
552 
553 	TFP_DRV_LOG(INFO,
554 		    "Closed session, session_id:%d, ref_count:%d\n",
555 		    tfs->session_id.id,
556 		    tfs->ref_count);
557 
558 	tfs->dev_init = false;
559 
560 	tfp_free(tfp->session->core_data);
561 	tfp_free(tfp->session);
562 	tfp->session = NULL;
563 
564 	return 0;
565 }
566 
567 bool
568 tf_session_is_fid_supported(struct tf_session *tfs,
569 			    uint16_t fid)
570 {
571 	struct ll_entry *c_entry;
572 	struct tf_session_client *client;
573 
574 	for (c_entry = tfs->client_ll.head;
575 	     c_entry != NULL;
576 	     c_entry = c_entry->next) {
577 		client = (struct tf_session_client *)c_entry;
578 		if (client->fw_fid == fid)
579 			return true;
580 	}
581 
582 	return false;
583 }
584 
585 int
586 tf_session_get_session_internal(struct tf *tfp,
587 				struct tf_session **tfs)
588 {
589 	int rc = 0;
590 
591 	/* Skip using the check macro as we want to control the error msg */
592 	if (tfp->session == NULL || tfp->session->core_data == NULL) {
593 		rc = -EINVAL;
594 		TFP_DRV_LOG(ERR,
595 			    "Session not created, rc:%s\n",
596 			    strerror(-rc));
597 		return rc;
598 	}
599 
600 	*tfs = (struct tf_session *)(tfp->session->core_data);
601 
602 	return rc;
603 }
604 
605 int
606 tf_session_get_session(struct tf *tfp,
607 		       struct tf_session **tfs)
608 {
609 	int rc;
610 	uint16_t fw_fid;
611 	bool supported = false;
612 
613 	rc = tf_session_get_session_internal(tfp,
614 					     tfs);
615 	/* Logging done by tf_session_get_session_internal */
616 	if (rc)
617 		return rc;
618 
619 	/* As session sharing among functions aka 'individual clients'
620 	 * is supported we have to assure that the client is indeed
621 	 * registered before we get deep in the TruFlow api stack.
622 	 */
623 	rc = tfp_get_fid(tfp, &fw_fid);
624 	if (rc) {
625 		TFP_DRV_LOG(ERR,
626 			    "Internal FID lookup\n, rc:%s\n",
627 			    strerror(-rc));
628 		return rc;
629 	}
630 
631 	supported = tf_session_is_fid_supported(*tfs, fw_fid);
632 	if (!supported) {
633 		TFP_DRV_LOG
634 			(ERR,
635 			"Ctrl channel not registered with session\n, rc:%s\n",
636 			strerror(-rc));
637 		return -EINVAL;
638 	}
639 
640 	return rc;
641 }
642 
643 struct tf_session_client *
644 tf_session_get_session_client(struct tf_session *tfs,
645 			      union tf_session_client_id session_client_id)
646 {
647 	struct ll_entry *c_entry;
648 	struct tf_session_client *client;
649 
650 	/* Skip using the check macro as we just want to return */
651 	if (tfs == NULL)
652 		return NULL;
653 
654 	for (c_entry = tfs->client_ll.head;
655 	     c_entry != NULL;
656 	     c_entry = c_entry->next) {
657 		client = (struct tf_session_client *)c_entry;
658 		if (client->session_client_id.id == session_client_id.id)
659 			return client;
660 	}
661 
662 	return NULL;
663 }
664 
665 struct tf_session_client *
666 tf_session_find_session_client_by_name(struct tf_session *tfs,
667 				       const char *ctrl_chan_name)
668 {
669 	struct ll_entry *c_entry;
670 	struct tf_session_client *client;
671 
672 	/* Skip using the check macro as we just want to return */
673 	if (tfs == NULL || ctrl_chan_name == NULL)
674 		return NULL;
675 
676 	for (c_entry = tfs->client_ll.head;
677 	     c_entry != NULL;
678 	     c_entry = c_entry->next) {
679 		client = (struct tf_session_client *)c_entry;
680 		if (strncmp(client->ctrl_chan_name,
681 			    ctrl_chan_name,
682 			    TF_SESSION_NAME_MAX) == 0)
683 			return client;
684 	}
685 
686 	return NULL;
687 }
688 
689 struct tf_session_client *
690 tf_session_find_session_client_by_fid(struct tf_session *tfs,
691 				      uint16_t fid)
692 {
693 	struct ll_entry *c_entry;
694 	struct tf_session_client *client;
695 
696 	/* Skip using the check macro as we just want to return */
697 	if (tfs == NULL)
698 		return NULL;
699 
700 	for (c_entry = tfs->client_ll.head;
701 	     c_entry != NULL;
702 	     c_entry = c_entry->next) {
703 		client = (struct tf_session_client *)c_entry;
704 		if (client->fw_fid == fid)
705 			return client;
706 	}
707 
708 	return NULL;
709 }
710 
711 int
712 tf_session_get_device(struct tf_session *tfs,
713 		      struct tf_dev_info **tfd)
714 {
715 	*tfd = &tfs->dev;
716 
717 	return 0;
718 }
719 
720 int
721 tf_session_get_fw_session_id(struct tf *tfp,
722 			     uint8_t *fw_session_id)
723 {
724 	int rc;
725 	struct tf_session *tfs = NULL;
726 
727 	/* Skip using the check macro as we want to control the error msg */
728 	if (tfp->session == NULL) {
729 		rc = -EINVAL;
730 		TFP_DRV_LOG(ERR,
731 			    "Session not created, rc:%s\n",
732 			    strerror(-rc));
733 		return rc;
734 	}
735 
736 	if (fw_session_id == NULL) {
737 		rc = -EINVAL;
738 		TFP_DRV_LOG(ERR,
739 			    "Invalid Argument(s), rc:%s\n",
740 			    strerror(-rc));
741 		return rc;
742 	}
743 
744 	rc = tf_session_get_session_internal(tfp, &tfs);
745 	if (rc)
746 		return rc;
747 
748 	*fw_session_id = tfs->session_id.internal.fw_session_id;
749 
750 	return 0;
751 }
752 
753 int
754 tf_session_get_session_id(struct tf *tfp,
755 			  union tf_session_id *session_id)
756 {
757 	int rc;
758 	struct tf_session *tfs = NULL;
759 
760 	if (tfp->session == NULL) {
761 		rc = -EINVAL;
762 		TFP_DRV_LOG(ERR,
763 			    "Session not created, rc:%s\n",
764 			    strerror(-rc));
765 		return rc;
766 	}
767 
768 	if (session_id == NULL) {
769 		rc = -EINVAL;
770 		TFP_DRV_LOG(ERR,
771 			    "Invalid Argument(s), rc:%s\n",
772 			    strerror(-rc));
773 		return rc;
774 	}
775 
776 	/* Using internal version as session client may not exist yet */
777 	rc = tf_session_get_session_internal(tfp, &tfs);
778 	if (rc)
779 		return rc;
780 
781 	*session_id = tfs->session_id;
782 
783 	return 0;
784 }
785