xref: /dpdk/drivers/net/bnxt/tf_core/tf_session.c (revision 7917b0d38e92e8b9ec5a870415b791420e10f11a)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2023 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <string.h>
7 #include <rte_common.h>
8 #include "tf_session.h"
9 #include "tf_common.h"
10 #include "tf_msg.h"
11 #include "tfp.h"
12 #include "bnxt.h"
13 
14 struct tf_session_client_create_parms {
15 	/**
16 	 * [in] Pointer to the control channel name string
17 	 */
18 	char *ctrl_chan_name;
19 
20 	/**
21 	 * [out] Firmware Session Client ID
22 	 */
23 	union tf_session_client_id *session_client_id;
24 };
25 
26 struct tf_session_client_destroy_parms {
27 	/**
28 	 * FW Session Client Identifier
29 	 */
30 	union tf_session_client_id session_client_id;
31 };
32 
33 /**
34  * Creates a Session and the associated client.
35  *
36  * [in] tfp
37  *   Pointer to TF handle
38  *
39  * [in] parms
40  *   Pointer to session client create parameters
41  *
42  * Returns
43  *   - (0) if successful.
44  *   - (-EINVAL) on failure.
45  *   - (-ENOMEM) if max session clients has been reached.
46  */
47 static int
48 tf_session_create(struct tf *tfp,
49 		  struct tf_session_open_session_parms *parms)
50 {
51 	int rc;
52 	struct tf_session *session = NULL;
53 	struct tf_session_client *client;
54 	struct tfp_calloc_parms cparms;
55 	uint8_t fw_session_id;
56 	uint8_t fw_session_client_id;
57 	union tf_session_id *session_id;
58 	struct tf_dev_info dev;
59 	bool shared_session_creator;
60 	char *shared_name;
61 	char *tcam_session_name;
62 	char *pool_session_name;
63 
64 	TF_CHECK_PARMS2(tfp, parms);
65 
66 	tf_dev_bind_ops(parms->open_cfg->device_type,
67 			&dev);
68 
69 	/* Open FW session and get a new session_id */
70 	rc = tf_msg_session_open(parms->open_cfg->bp,
71 				 parms->open_cfg->ctrl_chan_name,
72 				 &fw_session_id,
73 				 &fw_session_client_id,
74 				 &dev,
75 				 &shared_session_creator);
76 	if (rc) {
77 		/* Log error */
78 		if (rc == -EEXIST)
79 			TFP_DRV_LOG(ERR,
80 				    "Session is already open, rc:%s\n",
81 				    strerror(-rc));
82 		else
83 			TFP_DRV_LOG(ERR,
84 				    "Open message send failed, rc:%s\n",
85 				    strerror(-rc));
86 
87 		parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
88 		return rc;
89 	}
90 
91 	/* Allocate session */
92 	cparms.nitems = 1;
93 	cparms.size = sizeof(struct tf_session_info);
94 	cparms.alignment = 0;
95 	rc = tfp_calloc(&cparms);
96 	if (rc) {
97 		/* Log error */
98 		TFP_DRV_LOG(ERR,
99 			    "Failed to allocate session info, rc:%s\n",
100 			    strerror(-rc));
101 		goto cleanup;
102 	}
103 	tfp->session = (struct tf_session_info *)cparms.mem_va;
104 
105 	/* Allocate core data for the session */
106 	cparms.nitems = 1;
107 	cparms.size = sizeof(struct tf_session);
108 	cparms.alignment = 0;
109 	rc = tfp_calloc(&cparms);
110 	if (rc) {
111 		/* Log error */
112 		TFP_DRV_LOG(ERR,
113 			    "Failed to allocate session data, rc:%s\n",
114 			    strerror(-rc));
115 		goto cleanup;
116 	}
117 	tfp->session->core_data = cparms.mem_va;
118 	session_id = &parms->open_cfg->session_id;
119 
120 	/* Update Session Info, which is what is visible to the caller */
121 	tfp->session->ver.major = 0;
122 	tfp->session->ver.minor = 0;
123 	tfp->session->ver.update = 0;
124 
125 	tfp->session->session_id.internal.domain = session_id->internal.domain;
126 	tfp->session->session_id.internal.bus = session_id->internal.bus;
127 	tfp->session->session_id.internal.device = session_id->internal.device;
128 	tfp->session->session_id.internal.fw_session_id = fw_session_id;
129 
130 	/* Initialize Session and Device, which is private */
131 	session = (struct tf_session *)tfp->session->core_data;
132 	session->ver.major = 0;
133 	session->ver.minor = 0;
134 	session->ver.update = 0;
135 
136 	session->session_id.internal.domain = session_id->internal.domain;
137 	session->session_id.internal.bus = session_id->internal.bus;
138 	session->session_id.internal.device = session_id->internal.device;
139 	session->session_id.internal.fw_session_id = fw_session_id;
140 	/* Return the allocated session id */
141 	session_id->id = session->session_id.id;
142 
143 	/* Init session client list */
144 	ll_init(&session->client_ll);
145 
146 	/* Create the local session client, initialize and attach to
147 	 * the session
148 	 */
149 	cparms.nitems = 1;
150 	cparms.size = sizeof(struct tf_session_client);
151 	cparms.alignment = 0;
152 	rc = tfp_calloc(&cparms);
153 	if (rc) {
154 		/* Log error */
155 		TFP_DRV_LOG(ERR,
156 			    "Failed to allocate session client, rc:%s\n",
157 			    strerror(-rc));
158 		goto cleanup;
159 	}
160 	client = cparms.mem_va;
161 
162 	/* Register FID with the client */
163 	rc = tfp_get_fid(tfp, &client->fw_fid);
164 	if (rc)
165 		return rc;
166 
167 	client->session_client_id.internal.fw_session_id = fw_session_id;
168 	client->session_client_id.internal.fw_session_client_id =
169 		fw_session_client_id;
170 
171 	tfp_memcpy(client->ctrl_chan_name,
172 		   parms->open_cfg->ctrl_chan_name,
173 		   TF_SESSION_NAME_MAX);
174 
175 	ll_insert(&session->client_ll, &client->ll_entry);
176 	session->ref_count++;
177 
178 	/* Init session em_ext_db */
179 	session->em_ext_db_handle = NULL;
180 
181 	/* Populate the request */
182 	shared_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared");
183 	if (shared_name) {
184 		session->shared_session = true;
185 		/*
186 		 * "tf_shared-wc_tcam" is defined for tf_fw version 1.0.0.
187 		 * "tf_shared-pool" is defined for version 1.0.1.
188 		 */
189 		tcam_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-wc_tcam");
190 		pool_session_name = strstr(parms->open_cfg->ctrl_chan_name, "tf_shared-pool");
191 		if (tcam_session_name || pool_session_name)
192 			session->shared_session_hotup = true;
193 	}
194 
195 	if (session->shared_session && shared_session_creator) {
196 		session->shared_session_creator = true;
197 		parms->open_cfg->shared_session_creator = true;
198 	}
199 
200 	rc = tf_dev_bind(tfp,
201 			 parms->open_cfg->device_type,
202 			 &parms->open_cfg->resources,
203 			 parms->open_cfg->wc_num_slices,
204 			 &session->dev);
205 
206 	/* Logging handled by dev_bind */
207 	if (rc)
208 		goto cleanup;
209 
210 	if (session->dev.ops->tf_dev_get_mailbox == NULL) {
211 		/* Log error */
212 		TFP_DRV_LOG(ERR,
213 			    "No tf_dev_get_mailbox() defined for device\n");
214 		goto cleanup;
215 	}
216 
217 	session->dev_init = true;
218 
219 	return 0;
220 
221  cleanup:
222 	rc = tf_msg_session_close(tfp,
223 			fw_session_id,
224 			dev.ops->tf_dev_get_mailbox());
225 	if (rc) {
226 		/* Log error */
227 		TFP_DRV_LOG(ERR,
228 			    "FW Session close failed, rc:%s\n",
229 			    strerror(-rc));
230 	}
231 	if (tfp->session) {
232 		tfp_free(tfp->session->core_data);
233 		tfp_free(tfp->session);
234 		tfp->session = NULL;
235 	}
236 
237 	return rc;
238 }
239 
240 /**
241  * Creates a Session Client on an existing Session.
242  *
243  * [in] tfp
244  *   Pointer to TF handle
245  *
246  * [in] parms
247  *   Pointer to session client create parameters
248  *
249  * Returns
250  *   - (0) if successful.
251  *   - (-EINVAL) on failure.
252  *   - (-ENOMEM) if max session clients has been reached.
253  */
254 static int
255 tf_session_client_create(struct tf *tfp,
256 			 struct tf_session_client_create_parms *parms)
257 {
258 	int rc;
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;
263 
264 	TF_CHECK_PARMS2(tfp, parms);
265 
266 	/* Using internal version as session client may not exist yet */
267 	rc = tf_session_get_session_internal(tfp, &session);
268 	if (rc) {
269 		TFP_DRV_LOG(ERR,
270 			    "Failed to lookup session, rc:%s\n",
271 			    strerror(-rc));
272 		return rc;
273 	}
274 
275 	client = tf_session_find_session_client_by_name(session,
276 							parms->ctrl_chan_name);
277 	if (client) {
278 		TFP_DRV_LOG(ERR,
279 			    "Client %s, already registered with this session\n",
280 			    parms->ctrl_chan_name);
281 		return -EOPNOTSUPP;
282 	}
283 
284 	rc = tf_msg_session_client_register
285 		    (tfp,
286 		     session,
287 		     parms->ctrl_chan_name,
288 		     &session_client_id.internal.fw_session_client_id);
289 	if (rc) {
290 		TFP_DRV_LOG(ERR,
291 			    "Failed to create client on session, rc:%s\n",
292 			    strerror(-rc));
293 		return rc;
294 	}
295 
296 	/* Create the local session client, initialize and attach to
297 	 * the session
298 	 */
299 	cparms.nitems = 1;
300 	cparms.size = sizeof(struct tf_session_client);
301 	cparms.alignment = 0;
302 	rc = tfp_calloc(&cparms);
303 	if (rc) {
304 		TFP_DRV_LOG(ERR,
305 			    "Failed to allocate session client, rc:%s\n",
306 			    strerror(-rc));
307 		goto cleanup;
308 	}
309 	client = cparms.mem_va;
310 
311 	/* Register FID with the client */
312 	rc = tfp_get_fid(tfp, &client->fw_fid);
313 	if (rc)
314 		return rc;
315 
316 	/* Build the Session Client ID by adding the fw_session_id */
317 	rc = tf_session_get_fw_session_id
318 			(tfp,
319 			&session_client_id.internal.fw_session_id);
320 	if (rc) {
321 		TFP_DRV_LOG(ERR,
322 			    "Session Firmware id lookup failed, rc:%s\n",
323 			    strerror(-rc));
324 		return rc;
325 	}
326 
327 	tfp_memcpy(client->ctrl_chan_name,
328 		   parms->ctrl_chan_name,
329 		   TF_SESSION_NAME_MAX);
330 
331 	client->session_client_id.id = session_client_id.id;
332 
333 	ll_insert(&session->client_ll, &client->ll_entry);
334 
335 	session->ref_count++;
336 
337 	/* Build the return value */
338 	parms->session_client_id->id = session_client_id.id;
339 
340  cleanup:
341 	/* TBD - Add code to unregister newly create client from fw */
342 
343 	return rc;
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%08x\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 	/* Record the session we're closing so the caller knows the
539 	 * details.
540 	 */
541 	*parms->session_id = tfs->session_id;
542 
543 	/* In case multiple clients we chose to close those first */
544 	if (tfs->ref_count > 1) {
545 		/* Linaro gcc can't static init this structure */
546 		memset(&scdparms,
547 		       0,
548 		       sizeof(struct tf_session_client_destroy_parms));
549 
550 		scdparms.session_client_id = client->session_client_id;
551 		/* Destroy requested client so its no longer
552 		 * registered with this session.
553 		 */
554 		rc = tf_session_client_destroy(tfp, &scdparms);
555 		if (rc) {
556 			TFP_DRV_LOG(ERR,
557 				    "Failed to unregister Client %d, rc:%s\n",
558 				    client->session_client_id.id,
559 				    strerror(-rc));
560 			return rc;
561 		}
562 
563 		TFP_DRV_LOG(INFO,
564 			    "Closed session client, session_client_id:%d\n",
565 			    client->session_client_id.id);
566 
567 		TFP_DRV_LOG(INFO,
568 			    "session_id:0x%08x, ref_count:%d\n",
569 			    tfs->session_id.id,
570 			    tfs->ref_count);
571 
572 		return 0;
573 	}
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 int tf_session_get(struct tf *tfp,
709 		   struct tf_session **tfs,
710 		   struct tf_dev_info **tfd)
711 {
712 	int rc;
713 	rc = tf_session_get_session_internal(tfp, tfs);
714 
715 	/* Logging done by tf_session_get_session_internal */
716 	if (rc)
717 		return rc;
718 
719 	rc = tf_session_get_device(*tfs, tfd);
720 
721 	return rc;
722 }
723 
724 struct tf_session_client *
725 tf_session_get_session_client(struct tf_session *tfs,
726 			      union tf_session_client_id session_client_id)
727 {
728 	struct ll_entry *c_entry;
729 	struct tf_session_client *client;
730 
731 	/* Skip using the check macro as we just want to return */
732 	if (tfs == NULL)
733 		return NULL;
734 
735 	for (c_entry = tfs->client_ll.head;
736 	     c_entry != NULL;
737 	     c_entry = c_entry->next) {
738 		client = (struct tf_session_client *)c_entry;
739 		if (client->session_client_id.id == session_client_id.id)
740 			return client;
741 	}
742 
743 	return NULL;
744 }
745 
746 struct tf_session_client *
747 tf_session_find_session_client_by_name(struct tf_session *tfs,
748 				       const char *ctrl_chan_name)
749 {
750 	struct ll_entry *c_entry;
751 	struct tf_session_client *client;
752 
753 	/* Skip using the check macro as we just want to return */
754 	if (tfs == NULL || ctrl_chan_name == NULL)
755 		return NULL;
756 
757 	for (c_entry = tfs->client_ll.head;
758 	     c_entry != NULL;
759 	     c_entry = c_entry->next) {
760 		client = (struct tf_session_client *)c_entry;
761 		if (strncmp(client->ctrl_chan_name,
762 			    ctrl_chan_name,
763 			    TF_SESSION_NAME_MAX) == 0)
764 			return client;
765 	}
766 
767 	return NULL;
768 }
769 
770 struct tf_session_client *
771 tf_session_find_session_client_by_fid(struct tf_session *tfs,
772 				      uint16_t fid)
773 {
774 	struct ll_entry *c_entry;
775 	struct tf_session_client *client;
776 
777 	/* Skip using the check macro as we just want to return */
778 	if (tfs == NULL)
779 		return NULL;
780 
781 	for (c_entry = tfs->client_ll.head;
782 	     c_entry != NULL;
783 	     c_entry = c_entry->next) {
784 		client = (struct tf_session_client *)c_entry;
785 		if (client->fw_fid == fid)
786 			return client;
787 	}
788 
789 	return NULL;
790 }
791 
792 int
793 tf_session_get_device(struct tf_session *tfs,
794 		      struct tf_dev_info **tfd)
795 {
796 	*tfd = &tfs->dev;
797 
798 	return 0;
799 }
800 
801 int
802 tf_session_get_fw_session_id(struct tf *tfp,
803 			     uint8_t *fw_session_id)
804 {
805 	int rc;
806 	struct tf_session *tfs = NULL;
807 
808 	/* Skip using the check macro as we want to control the error msg */
809 	if (tfp->session == NULL) {
810 		rc = -EINVAL;
811 		TFP_DRV_LOG(ERR,
812 			    "Session not created, rc:%s\n",
813 			    strerror(-rc));
814 		return rc;
815 	}
816 
817 	if (fw_session_id == NULL) {
818 		rc = -EINVAL;
819 		TFP_DRV_LOG(ERR,
820 			    "Invalid Argument(s), rc:%s\n",
821 			    strerror(-rc));
822 		return rc;
823 	}
824 
825 	rc = tf_session_get_session_internal(tfp, &tfs);
826 	if (rc)
827 		return rc;
828 
829 	*fw_session_id = tfs->session_id.internal.fw_session_id;
830 
831 	return 0;
832 }
833 
834 int
835 tf_session_get_session_id(struct tf *tfp,
836 			  union tf_session_id *session_id)
837 {
838 	int rc;
839 	struct tf_session *tfs = NULL;
840 
841 	if (tfp->session == NULL) {
842 		rc = -EINVAL;
843 		TFP_DRV_LOG(ERR,
844 			    "Session not created, rc:%s\n",
845 			    strerror(-rc));
846 		return rc;
847 	}
848 
849 	if (session_id == NULL) {
850 		rc = -EINVAL;
851 		TFP_DRV_LOG(ERR,
852 			    "Invalid Argument(s), rc:%s\n",
853 			    strerror(-rc));
854 		return rc;
855 	}
856 
857 	/* Using internal version as session client may not exist yet */
858 	rc = tf_session_get_session_internal(tfp, &tfs);
859 	if (rc)
860 		return rc;
861 
862 	*session_id = tfs->session_id;
863 
864 	return 0;
865 }
866 
867 int
868 tf_session_get_em_ext_db(struct tf *tfp,
869 			 void **em_ext_db_handle)
870 {
871 	struct tf_session *tfs = NULL;
872 	int rc = 0;
873 
874 	*em_ext_db_handle = NULL;
875 
876 	if (tfp == NULL)
877 		return (-EINVAL);
878 
879 	rc = tf_session_get_session_internal(tfp, &tfs);
880 	if (rc)
881 		return rc;
882 
883 	*em_ext_db_handle = tfs->em_ext_db_handle;
884 	return rc;
885 }
886 
887 int
888 tf_session_set_em_ext_db(struct tf *tfp,
889 			 void *em_ext_db_handle)
890 {
891 	struct tf_session *tfs = NULL;
892 	int rc = 0;
893 
894 	if (tfp == NULL)
895 		return (-EINVAL);
896 
897 	rc = tf_session_get_session_internal(tfp, &tfs);
898 	if (rc)
899 		return rc;
900 
901 	tfs->em_ext_db_handle = em_ext_db_handle;
902 	return rc;
903 }
904 
905 int
906 tf_session_get_db(struct tf *tfp,
907 		  enum tf_module_type type,
908 		  void **db_handle)
909 {
910 	struct tf_session *tfs = NULL;
911 	int rc = 0;
912 
913 	*db_handle = NULL;
914 
915 	if (tfp == NULL)
916 		return (-EINVAL);
917 
918 	rc = tf_session_get_session_internal(tfp, &tfs);
919 	if (rc)
920 		return rc;
921 
922 	switch (type) {
923 	case TF_MODULE_TYPE_IDENTIFIER:
924 		if (tfs->id_db_handle)
925 			*db_handle = tfs->id_db_handle;
926 		else
927 			rc = -ENOMEM;
928 		break;
929 	case TF_MODULE_TYPE_TABLE:
930 		if (tfs->tbl_db_handle)
931 			*db_handle = tfs->tbl_db_handle;
932 		else
933 			rc = -ENOMEM;
934 
935 		break;
936 	case TF_MODULE_TYPE_TCAM:
937 		if (tfs->tcam_db_handle)
938 			*db_handle = tfs->tcam_db_handle;
939 		else
940 			rc = -ENOMEM;
941 		break;
942 	case TF_MODULE_TYPE_EM:
943 		if (tfs->em_db_handle)
944 			*db_handle = tfs->em_db_handle;
945 		else
946 			rc = -ENOMEM;
947 		break;
948 	default:
949 		rc = -EINVAL;
950 		break;
951 	}
952 
953 	return rc;
954 }
955 
956 int
957 tf_session_set_db(struct tf *tfp,
958 		  enum tf_module_type type,
959 		  void *db_handle)
960 {
961 	struct tf_session *tfs = NULL;
962 	int rc = 0;
963 
964 	if (tfp == NULL)
965 		return (-EINVAL);
966 
967 	rc = tf_session_get_session_internal(tfp, &tfs);
968 	if (rc)
969 		return rc;
970 
971 	switch (type) {
972 	case TF_MODULE_TYPE_IDENTIFIER:
973 		tfs->id_db_handle = db_handle;
974 		break;
975 	case TF_MODULE_TYPE_TABLE:
976 		tfs->tbl_db_handle = db_handle;
977 		break;
978 	case TF_MODULE_TYPE_TCAM:
979 		tfs->tcam_db_handle = db_handle;
980 		break;
981 	case TF_MODULE_TYPE_EM:
982 		tfs->em_db_handle = db_handle;
983 		break;
984 	default:
985 		rc = -EINVAL;
986 		break;
987 	}
988 
989 	return rc;
990 }
991 
992 int
993 tf_session_get_tcam_shared_db(struct tf *tfp,
994 			      void **tcam_shared_db_handle)
995 {
996 	struct tf_session *tfs = NULL;
997 	int rc = 0;
998 
999 	*tcam_shared_db_handle = NULL;
1000 
1001 	if (tfp == NULL)
1002 		return (-EINVAL);
1003 
1004 	rc = tf_session_get_session_internal(tfp, &tfs);
1005 	if (rc)
1006 		return rc;
1007 
1008 	*tcam_shared_db_handle = tfs->tcam_shared_db_handle;
1009 	return rc;
1010 }
1011 
1012 int
1013 tf_session_set_tcam_shared_db(struct tf *tfp,
1014 			 void *tcam_shared_db_handle)
1015 {
1016 	struct tf_session *tfs = NULL;
1017 	int rc = 0;
1018 
1019 	if (tfp == NULL)
1020 		return (-EINVAL);
1021 
1022 	rc = tf_session_get_session_internal(tfp, &tfs);
1023 	if (rc)
1024 		return rc;
1025 
1026 	tfs->tcam_shared_db_handle = tcam_shared_db_handle;
1027 	return rc;
1028 }
1029 
1030 int
1031 tf_session_get_sram_db(struct tf *tfp,
1032 		       void **sram_handle)
1033 {
1034 	struct tf_session *tfs = NULL;
1035 	int rc = 0;
1036 
1037 	*sram_handle = NULL;
1038 
1039 	if (tfp == NULL)
1040 		return (-EINVAL);
1041 
1042 	rc = tf_session_get_session_internal(tfp, &tfs);
1043 	if (rc)
1044 		return rc;
1045 
1046 	*sram_handle = tfs->sram_handle;
1047 	return rc;
1048 }
1049 
1050 int
1051 tf_session_set_sram_db(struct tf *tfp,
1052 		       void *sram_handle)
1053 {
1054 	struct tf_session *tfs = NULL;
1055 	int rc = 0;
1056 
1057 	if (tfp == NULL)
1058 		return (-EINVAL);
1059 
1060 	rc = tf_session_get_session_internal(tfp, &tfs);
1061 	if (rc)
1062 		return rc;
1063 
1064 	tfs->sram_handle = sram_handle;
1065 	return rc;
1066 }
1067 
1068 int
1069 tf_session_get_global_db(struct tf *tfp,
1070 			 void **global_handle)
1071 {
1072 	struct tf_session *tfs = NULL;
1073 	int rc = 0;
1074 
1075 	*global_handle = NULL;
1076 
1077 	if (tfp == NULL)
1078 		return (-EINVAL);
1079 
1080 	rc = tf_session_get_session_internal(tfp, &tfs);
1081 	if (rc)
1082 		return rc;
1083 
1084 	*global_handle = tfs->global_db_handle;
1085 	return rc;
1086 }
1087 
1088 int
1089 tf_session_set_global_db(struct tf *tfp,
1090 			 void *global_handle)
1091 {
1092 	struct tf_session *tfs = NULL;
1093 	int rc = 0;
1094 
1095 	if (tfp == NULL)
1096 		return (-EINVAL);
1097 
1098 	rc = tf_session_get_session_internal(tfp, &tfs);
1099 	if (rc)
1100 		return rc;
1101 
1102 	tfs->global_db_handle = global_handle;
1103 	return rc;
1104 }
1105 
1106 int
1107 tf_session_get_if_tbl_db(struct tf *tfp,
1108 			 void **if_tbl_handle)
1109 {
1110 	struct tf_session *tfs = NULL;
1111 	int rc = 0;
1112 
1113 	*if_tbl_handle = NULL;
1114 
1115 	if (tfp == NULL)
1116 		return (-EINVAL);
1117 
1118 	rc = tf_session_get_session_internal(tfp, &tfs);
1119 	if (rc)
1120 		return rc;
1121 
1122 	*if_tbl_handle = tfs->if_tbl_db_handle;
1123 	return rc;
1124 }
1125 
1126 int
1127 tf_session_set_if_tbl_db(struct tf *tfp,
1128 			 void *if_tbl_handle)
1129 {
1130 	struct tf_session *tfs = NULL;
1131 	int rc = 0;
1132 
1133 	if (tfp == NULL)
1134 		return (-EINVAL);
1135 
1136 	rc = tf_session_get_session_internal(tfp, &tfs);
1137 	if (rc)
1138 		return rc;
1139 
1140 	tfs->if_tbl_db_handle = if_tbl_handle;
1141 	return rc;
1142 }
1143 
1144 int
1145 tf_session_set_hotup_state(struct tf *tfp,
1146 			   struct tf_set_session_hotup_state_parms *parms)
1147 {
1148 	int rc = 0;
1149 	struct tf_session *tfs = NULL;
1150 
1151 	rc = tf_session_get_session(tfp, &tfs);
1152 	if (rc) {
1153 		TFP_DRV_LOG(ERR,
1154 			    "Session lookup failed, rc:%s\n",
1155 			    strerror(-rc));
1156 		return rc;
1157 	}
1158 
1159 	if (!tf_session_is_shared_session(tfs)) {
1160 		rc = -EINVAL;
1161 		TFP_DRV_LOG(ERR,
1162 			    "Only shared session able to set state, rc:%s\n",
1163 			    strerror(-rc));
1164 		return rc;
1165 	}
1166 
1167 	rc = tf_msg_session_set_hotup_state(tfp, parms->state);
1168 	if (rc) {
1169 		/* Log error */
1170 		TFP_DRV_LOG(ERR,
1171 			    "Set session hot upgrade state failed, rc:%s\n",
1172 			    strerror(-rc));
1173 	}
1174 
1175 	return rc;
1176 }
1177 
1178 int
1179 tf_session_get_hotup_state(struct tf *tfp,
1180 			   struct tf_get_session_hotup_state_parms *parms)
1181 {
1182 	int rc = 0;
1183 	struct tf_session *tfs = NULL;
1184 
1185 	rc = tf_session_get_session(tfp, &tfs);
1186 	if (rc) {
1187 		TFP_DRV_LOG(ERR,
1188 			    "Session lookup failed, rc:%s\n",
1189 			    strerror(-rc));
1190 		return rc;
1191 	}
1192 
1193 	if (!tf_session_is_shared_session(tfs)) {
1194 		rc = -EINVAL;
1195 		TFP_DRV_LOG(ERR,
1196 			    "Only shared session able to get state, rc:%s\n",
1197 			    strerror(-rc));
1198 		return rc;
1199 	}
1200 
1201 	rc = tf_msg_session_get_hotup_state(tfp, &parms->state, &parms->ref_cnt);
1202 	if (rc) {
1203 		/* Log error */
1204 		TFP_DRV_LOG(ERR,
1205 			    "Get session hot upgrade state failed, rc:%s\n",
1206 			    strerror(-rc));
1207 	}
1208 
1209 	return rc;
1210 }
1211