net/bnxt: refactor host session failure cleanup
[dpdk.git] / drivers / net / bnxt / tf_core / tf_session.c
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 #include "bnxt.h"
15
16 struct tf_session_client_create_parms {
17         /**
18          * [in] Pointer to the control channel name string
19          */
20         char *ctrl_chan_name;
21
22         /**
23          * [out] Firmware Session Client ID
24          */
25         union tf_session_client_id *session_client_id;
26 };
27
28 struct tf_session_client_destroy_parms {
29         /**
30          * FW Session Client Identifier
31          */
32         union tf_session_client_id session_client_id;
33 };
34
35 /**
36  * Creates a Session and the associated client.
37  *
38  * [in] tfp
39  *   Pointer to TF handle
40  *
41  * [in] parms
42  *   Pointer to session client create parameters
43  *
44  * Returns
45  *   - (0) if successful.
46  *   - (-EINVAL) on failure.
47  *   - (-ENOMEM) if max session clients has been reached.
48  */
49 static int
50 tf_session_create(struct tf *tfp,
51                   struct tf_session_open_session_parms *parms)
52 {
53         int rc;
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;
62         int name_len;
63         char *name;
64
65         TF_CHECK_PARMS2(tfp, parms);
66
67         tf_dev_bind_ops(parms->open_cfg->device_type,
68                         &dev);
69
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,
73                                  &fw_session_id,
74                                  &fw_session_client_id,
75                                  &dev,
76                                  &shared_session_creator);
77         if (rc) {
78                 /* Log error */
79                 if (rc == -EEXIST)
80                         TFP_DRV_LOG(ERR,
81                                     "Session is already open, rc:%s\n",
82                                     strerror(-rc));
83                 else
84                         TFP_DRV_LOG(ERR,
85                                     "Open message send failed, rc:%s\n",
86                                     strerror(-rc));
87
88                 parms->open_cfg->session_id.id = TF_FW_SESSION_ID_INVALID;
89                 return rc;
90         }
91
92         /* Allocate session */
93         cparms.nitems = 1;
94         cparms.size = sizeof(struct tf_session_info);
95         cparms.alignment = 0;
96         rc = tfp_calloc(&cparms);
97         if (rc) {
98                 /* Log error */
99                 TFP_DRV_LOG(ERR,
100                             "Failed to allocate session info, rc:%s\n",
101                             strerror(-rc));
102                 goto cleanup;
103         }
104         tfp->session = (struct tf_session_info *)cparms.mem_va;
105
106         /* Allocate core data for the session */
107         cparms.nitems = 1;
108         cparms.size = sizeof(struct tf_session);
109         cparms.alignment = 0;
110         rc = tfp_calloc(&cparms);
111         if (rc) {
112                 /* Log error */
113                 TFP_DRV_LOG(ERR,
114                             "Failed to allocate session data, rc:%s\n",
115                             strerror(-rc));
116                 goto cleanup;
117         }
118         tfp->session->core_data = cparms.mem_va;
119         session_id = &parms->open_cfg->session_id;
120
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;
125
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;
130
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;
136
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;
143
144         session->shadow_copy = parms->open_cfg->shadow_copy;
145
146         /* Init session client list */
147         ll_init(&session->client_ll);
148
149         /* Create the local session client, initialize and attach to
150          * the session
151          */
152         cparms.nitems = 1;
153         cparms.size = sizeof(struct tf_session_client);
154         cparms.alignment = 0;
155         rc = tfp_calloc(&cparms);
156         if (rc) {
157                 /* Log error */
158                 TFP_DRV_LOG(ERR,
159                             "Failed to allocate session client, rc:%s\n",
160                             strerror(-rc));
161                 goto cleanup;
162         }
163         client = cparms.mem_va;
164
165         /* Register FID with the client */
166         rc = tfp_get_fid(tfp, &client->fw_fid);
167         if (rc)
168                 return rc;
169
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;
173
174         tfp_memcpy(client->ctrl_chan_name,
175                    parms->open_cfg->ctrl_chan_name,
176                    TF_SESSION_NAME_MAX);
177
178         ll_insert(&session->client_ll, &client->ll_entry);
179         session->ref_count++;
180
181         /* Init session em_ext_db */
182         session->em_ext_db_handle = NULL;
183
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;
190
191         if (session->shared_session && shared_session_creator) {
192                 session->shared_session_creator = true;
193                 parms->open_cfg->shared_session_creator = true;
194         }
195
196         rc = tf_dev_bind(tfp,
197                          parms->open_cfg->device_type,
198                          session->shadow_copy,
199                          &parms->open_cfg->resources,
200                          &session->dev);
201
202         /* Logging handled by dev_bind */
203         if (rc)
204                 goto cleanup;
205
206         if (session->dev.ops->tf_dev_get_mailbox == NULL) {
207                 /* Log error */
208                 TFP_DRV_LOG(ERR,
209                             "No tf_dev_get_mailbox() defined for device\n");
210                 goto cleanup;
211         }
212
213         session->dev_init = true;
214
215         return 0;
216
217  cleanup:
218         rc = tf_msg_session_close(tfp,
219                         fw_session_id,
220                         dev.ops->tf_dev_get_mailbox());
221         if (rc) {
222                 /* Log error */
223                 TFP_DRV_LOG(ERR,
224                             "FW Session close failed, rc:%s\n",
225                             strerror(-rc));
226         }
227
228         tfp_free(tfp->session->core_data);
229         tfp_free(tfp->session);
230         tfp->session = NULL;
231         return rc;
232 }
233
234 /**
235  * Creates a Session Client on an existing Session.
236  *
237  * [in] tfp
238  *   Pointer to TF handle
239  *
240  * [in] parms
241  *   Pointer to session client create parameters
242  *
243  * Returns
244  *   - (0) if successful.
245  *   - (-EINVAL) on failure.
246  *   - (-ENOMEM) if max session clients has been reached.
247  */
248 static int
249 tf_session_client_create(struct tf *tfp,
250                          struct tf_session_client_create_parms *parms)
251 {
252         int rc;
253         struct tf_session *session = NULL;
254         struct tf_session_client *client;
255         struct tfp_calloc_parms cparms;
256         union tf_session_client_id session_client_id;
257
258         TF_CHECK_PARMS2(tfp, parms);
259
260         /* Using internal version as session client may not exist yet */
261         rc = tf_session_get_session_internal(tfp, &session);
262         if (rc) {
263                 TFP_DRV_LOG(ERR,
264                             "Failed to lookup session, rc:%s\n",
265                             strerror(-rc));
266                 return rc;
267         }
268
269         client = tf_session_find_session_client_by_name(session,
270                                                         parms->ctrl_chan_name);
271         if (client) {
272                 TFP_DRV_LOG(ERR,
273                             "Client %s, already registered with this session\n",
274                             parms->ctrl_chan_name);
275                 return -EOPNOTSUPP;
276         }
277
278         rc = tf_msg_session_client_register
279                     (tfp,
280                      session,
281                      parms->ctrl_chan_name,
282                      &session_client_id.internal.fw_session_client_id);
283         if (rc) {
284                 TFP_DRV_LOG(ERR,
285                             "Failed to create client on session, rc:%s\n",
286                             strerror(-rc));
287                 return rc;
288         }
289
290         /* Create the local session client, initialize and attach to
291          * the session
292          */
293         cparms.nitems = 1;
294         cparms.size = sizeof(struct tf_session_client);
295         cparms.alignment = 0;
296         rc = tfp_calloc(&cparms);
297         if (rc) {
298                 TFP_DRV_LOG(ERR,
299                             "Failed to allocate session client, rc:%s\n",
300                             strerror(-rc));
301                 goto cleanup;
302         }
303         client = cparms.mem_va;
304
305         /* Register FID with the client */
306         rc = tfp_get_fid(tfp, &client->fw_fid);
307         if (rc)
308                 return rc;
309
310         /* Build the Session Client ID by adding the fw_session_id */
311         rc = tf_session_get_fw_session_id
312                         (tfp,
313                         &session_client_id.internal.fw_session_id);
314         if (rc) {
315                 TFP_DRV_LOG(ERR,
316                             "Session Firmware id lookup failed, rc:%s\n",
317                             strerror(-rc));
318                 return rc;
319         }
320
321         tfp_memcpy(client->ctrl_chan_name,
322                    parms->ctrl_chan_name,
323                    TF_SESSION_NAME_MAX);
324
325         client->session_client_id.id = session_client_id.id;
326
327         ll_insert(&session->client_ll, &client->ll_entry);
328
329         session->ref_count++;
330
331         /* Build the return value */
332         parms->session_client_id->id = session_client_id.id;
333
334  cleanup:
335         /* TBD - Add code to unregister newly create client from fw */
336
337         return rc;
338 }
339
340
341 /**
342  * Destroys a Session Client on an existing Session.
343  *
344  * [in] tfp
345  *   Pointer to TF handle
346  *
347  * [in] parms
348  *   Pointer to the session client destroy parameters
349  *
350  * Returns
351  *   - (0) if successful.
352  *   - (-EINVAL) on failure.
353  *   - (-ENOTFOUND) error, client not owned by the session.
354  *   - (-ENOTSUPP) error, unable to destroy client as its the last
355  *                 client. Please use the tf_session_close().
356  */
357 static int
358 tf_session_client_destroy(struct tf *tfp,
359                           struct tf_session_client_destroy_parms *parms)
360 {
361         int rc;
362         struct tf_session *tfs;
363         struct tf_session_client *client;
364
365         TF_CHECK_PARMS2(tfp, parms);
366
367         rc = tf_session_get_session(tfp, &tfs);
368         if (rc) {
369                 TFP_DRV_LOG(ERR,
370                             "Failed to lookup session, rc:%s\n",
371                             strerror(-rc));
372                 return rc;
373         }
374
375         /* Check session owns this client and that we're not the last client */
376         client = tf_session_get_session_client(tfs,
377                                                parms->session_client_id);
378         if (client == NULL) {
379                 TFP_DRV_LOG(ERR,
380                             "Client %d, not found within this session\n",
381                             parms->session_client_id.id);
382                 return -EINVAL;
383         }
384
385         /* If last client the request is rejected and cleanup should
386          * be done by session close.
387          */
388         if (tfs->ref_count == 1)
389                 return -EOPNOTSUPP;
390
391         rc = tf_msg_session_client_unregister
392                         (tfp,
393                         tfs,
394                         parms->session_client_id.internal.fw_session_client_id);
395
396         /* Log error, but continue. If FW fails we do not really have
397          * a way to fix this but the client would no longer be valid
398          * thus we remove from the session.
399          */
400         if (rc) {
401                 TFP_DRV_LOG(ERR,
402                             "Client destroy on FW Failed, rc:%s\n",
403                             strerror(-rc));
404         }
405
406         ll_delete(&tfs->client_ll, &client->ll_entry);
407
408         /* Decrement the session ref_count */
409         tfs->ref_count--;
410
411         tfp_free(client);
412
413         return rc;
414 }
415
416 int
417 tf_session_open_session(struct tf *tfp,
418                         struct tf_session_open_session_parms *parms)
419 {
420         int rc;
421         struct tf_session_client_create_parms scparms;
422
423         TF_CHECK_PARMS3(tfp, parms, parms->open_cfg->bp);
424
425         tfp->bp = parms->open_cfg->bp;
426         /* Decide if we're creating a new session or session client */
427         if (tfp->session == NULL) {
428                 rc = tf_session_create(tfp, parms);
429                 if (rc) {
430                         TFP_DRV_LOG(ERR,
431                                     "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
432                                     parms->open_cfg->ctrl_chan_name,
433                                     strerror(-rc));
434                         return rc;
435                 }
436
437                 TFP_DRV_LOG(INFO,
438                        "Session created, session_client_id:%d,"
439                        "session_id:0x%08x, fw_session_id:%d\n",
440                        parms->open_cfg->session_client_id.id,
441                        parms->open_cfg->session_id.id,
442                        parms->open_cfg->session_id.internal.fw_session_id);
443         } else {
444                 scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
445                 scparms.session_client_id = &parms->open_cfg->session_client_id;
446
447                 /* Create the new client and get it associated with
448                  * the session.
449                  */
450                 rc = tf_session_client_create(tfp, &scparms);
451                 if (rc) {
452                         TFP_DRV_LOG(ERR,
453                               "Failed to create client on session 0x%x, rc:%s\n",
454                               parms->open_cfg->session_id.id,
455                               strerror(-rc));
456                         return rc;
457                 }
458
459                 TFP_DRV_LOG(INFO,
460                         "Session Client:%d registered on session:0x%8x\n",
461                         scparms.session_client_id->internal.fw_session_client_id,
462                         tfp->session->session_id.id);
463         }
464
465         return 0;
466 }
467
468 int
469 tf_session_attach_session(struct tf *tfp __rte_unused,
470                           struct tf_session_attach_session_parms *parms __rte_unused)
471 {
472         int rc = -EOPNOTSUPP;
473
474         TF_CHECK_PARMS2(tfp, parms);
475
476         TFP_DRV_LOG(ERR,
477                     "Attach not yet supported, rc:%s\n",
478                     strerror(-rc));
479         return rc;
480 }
481
482 int
483 tf_session_close_session(struct tf *tfp,
484                          struct tf_session_close_session_parms *parms)
485 {
486         int rc;
487         struct tf_session *tfs = NULL;
488         struct tf_session_client *client;
489         struct tf_dev_info *tfd = NULL;
490         struct tf_session_client_destroy_parms scdparms;
491         uint16_t fid;
492         uint8_t fw_session_id = 1;
493         int mailbox = 0;
494
495         TF_CHECK_PARMS2(tfp, parms);
496
497         rc = tf_session_get_session(tfp, &tfs);
498         if (rc) {
499                 TFP_DRV_LOG(ERR,
500                             "Session lookup failed, rc:%s\n",
501                             strerror(-rc));
502                 return rc;
503         }
504
505         if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
506                 rc = -EINVAL;
507                 TFP_DRV_LOG(ERR,
508                             "Invalid session id, unable to close, rc:%s\n",
509                             strerror(-rc));
510                 return rc;
511         }
512
513         /* Get the client, we need it independently of the closure
514          * type (client or session closure).
515          *
516          * We find the client by way of the fid. Thus one cannot close
517          * a client on behalf of someone else.
518          */
519         rc = tfp_get_fid(tfp, &fid);
520         if (rc)
521                 return rc;
522
523         client = tf_session_find_session_client_by_fid(tfs,
524                                                        fid);
525         if (!client) {
526                 rc = -EINVAL;
527                 TFP_DRV_LOG(ERR,
528                             "Client not part of the session, unable to close, rc:%s\n",
529                             strerror(-rc));
530                 return rc;
531         }
532
533         /* In case multiple clients we chose to close those first */
534         if (tfs->ref_count > 1) {
535                 /* Linaro gcc can't static init this structure */
536                 memset(&scdparms,
537                        0,
538                        sizeof(struct tf_session_client_destroy_parms));
539
540                 scdparms.session_client_id = client->session_client_id;
541                 /* Destroy requested client so its no longer
542                  * registered with this session.
543                  */
544                 rc = tf_session_client_destroy(tfp, &scdparms);
545                 if (rc) {
546                         TFP_DRV_LOG(ERR,
547                                     "Failed to unregister Client %d, rc:%s\n",
548                                     client->session_client_id.id,
549                                     strerror(-rc));
550                         return rc;
551                 }
552
553                 TFP_DRV_LOG(INFO,
554                             "Closed session client, session_client_id:%d\n",
555                             client->session_client_id.id);
556
557                 TFP_DRV_LOG(INFO,
558                             "session_id:0x%08x, ref_count:%d\n",
559                             tfs->session_id.id,
560                             tfs->ref_count);
561
562                 return 0;
563         }
564
565         /* Record the session we're closing so the caller knows the
566          * details.
567          */
568         *parms->session_id = tfs->session_id;
569
570         rc = tf_session_get_device(tfs, &tfd);
571         if (rc) {
572                 TFP_DRV_LOG(ERR,
573                             "Device lookup failed, rc:%s\n",
574                             strerror(-rc));
575                 return rc;
576         }
577
578         mailbox = tfd->ops->tf_dev_get_mailbox();
579
580         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
581         if (rc) {
582                 TFP_DRV_LOG(ERR,
583                             "Unable to lookup FW id, rc:%s\n",
584                             strerror(-rc));
585                 return rc;
586         }
587
588         /* Unbind the device */
589         rc = tf_dev_unbind(tfp, tfd);
590         if (rc) {
591                 /* Log error */
592                 TFP_DRV_LOG(ERR,
593                             "Device unbind failed, rc:%s\n",
594                             strerror(-rc));
595         }
596
597         rc = tf_msg_session_close(tfp, fw_session_id, mailbox);
598         if (rc) {
599                 /* Log error */
600                 TFP_DRV_LOG(ERR,
601                             "FW Session close failed, rc:%s\n",
602                             strerror(-rc));
603         }
604
605         /* Final cleanup as we're last user of the session thus we
606          * also delete the last client.
607          */
608         ll_delete(&tfs->client_ll, &client->ll_entry);
609         tfp_free(client);
610
611         tfs->ref_count--;
612
613         TFP_DRV_LOG(INFO,
614                     "Closed session, session_id:0x%08x, ref_count:%d\n",
615                     tfs->session_id.id,
616                     tfs->ref_count);
617
618         tfs->dev_init = false;
619
620         tfp_free(tfp->session->core_data);
621         tfp_free(tfp->session);
622         tfp->session = NULL;
623
624         return 0;
625 }
626
627 bool
628 tf_session_is_fid_supported(struct tf_session *tfs,
629                             uint16_t fid)
630 {
631         struct ll_entry *c_entry;
632         struct tf_session_client *client;
633
634         for (c_entry = tfs->client_ll.head;
635              c_entry != NULL;
636              c_entry = c_entry->next) {
637                 client = (struct tf_session_client *)c_entry;
638                 if (client->fw_fid == fid)
639                         return true;
640         }
641
642         return false;
643 }
644
645 int
646 tf_session_get_session_internal(struct tf *tfp,
647                                 struct tf_session **tfs)
648 {
649         int rc = 0;
650
651         /* Skip using the check macro as we want to control the error msg */
652         if (tfp->session == NULL || tfp->session->core_data == NULL) {
653                 rc = -EINVAL;
654                 TFP_DRV_LOG(ERR,
655                             "Session not created, rc:%s\n",
656                             strerror(-rc));
657                 return rc;
658         }
659
660         *tfs = (struct tf_session *)(tfp->session->core_data);
661
662         return rc;
663 }
664
665 int
666 tf_session_get_session(struct tf *tfp,
667                        struct tf_session **tfs)
668 {
669         int rc;
670         uint16_t fw_fid;
671         bool supported = false;
672
673         rc = tf_session_get_session_internal(tfp,
674                                              tfs);
675         /* Logging done by tf_session_get_session_internal */
676         if (rc)
677                 return rc;
678
679         /* As session sharing among functions aka 'individual clients'
680          * is supported we have to assure that the client is indeed
681          * registered before we get deep in the TruFlow api stack.
682          */
683         rc = tfp_get_fid(tfp, &fw_fid);
684         if (rc) {
685                 TFP_DRV_LOG(ERR,
686                             "Internal FID lookup\n, rc:%s\n",
687                             strerror(-rc));
688                 return rc;
689         }
690
691         supported = tf_session_is_fid_supported(*tfs, fw_fid);
692         if (!supported) {
693                 TFP_DRV_LOG
694                         (ERR,
695                         "Ctrl channel not registered with session\n, rc:%s\n",
696                         strerror(-rc));
697                 return -EINVAL;
698         }
699
700         return rc;
701 }
702
703 struct tf_session_client *
704 tf_session_get_session_client(struct tf_session *tfs,
705                               union tf_session_client_id session_client_id)
706 {
707         struct ll_entry *c_entry;
708         struct tf_session_client *client;
709
710         /* Skip using the check macro as we just want to return */
711         if (tfs == NULL)
712                 return NULL;
713
714         for (c_entry = tfs->client_ll.head;
715              c_entry != NULL;
716              c_entry = c_entry->next) {
717                 client = (struct tf_session_client *)c_entry;
718                 if (client->session_client_id.id == session_client_id.id)
719                         return client;
720         }
721
722         return NULL;
723 }
724
725 struct tf_session_client *
726 tf_session_find_session_client_by_name(struct tf_session *tfs,
727                                        const char *ctrl_chan_name)
728 {
729         struct ll_entry *c_entry;
730         struct tf_session_client *client;
731
732         /* Skip using the check macro as we just want to return */
733         if (tfs == NULL || ctrl_chan_name == NULL)
734                 return NULL;
735
736         for (c_entry = tfs->client_ll.head;
737              c_entry != NULL;
738              c_entry = c_entry->next) {
739                 client = (struct tf_session_client *)c_entry;
740                 if (strncmp(client->ctrl_chan_name,
741                             ctrl_chan_name,
742                             TF_SESSION_NAME_MAX) == 0)
743                         return client;
744         }
745
746         return NULL;
747 }
748
749 struct tf_session_client *
750 tf_session_find_session_client_by_fid(struct tf_session *tfs,
751                                       uint16_t fid)
752 {
753         struct ll_entry *c_entry;
754         struct tf_session_client *client;
755
756         /* Skip using the check macro as we just want to return */
757         if (tfs == NULL)
758                 return NULL;
759
760         for (c_entry = tfs->client_ll.head;
761              c_entry != NULL;
762              c_entry = c_entry->next) {
763                 client = (struct tf_session_client *)c_entry;
764                 if (client->fw_fid == fid)
765                         return client;
766         }
767
768         return NULL;
769 }
770
771 int
772 tf_session_get_device(struct tf_session *tfs,
773                       struct tf_dev_info **tfd)
774 {
775         *tfd = &tfs->dev;
776
777         return 0;
778 }
779
780 int
781 tf_session_get_fw_session_id(struct tf *tfp,
782                              uint8_t *fw_session_id)
783 {
784         int rc;
785         struct tf_session *tfs = NULL;
786
787         /* Skip using the check macro as we want to control the error msg */
788         if (tfp->session == NULL) {
789                 rc = -EINVAL;
790                 TFP_DRV_LOG(ERR,
791                             "Session not created, rc:%s\n",
792                             strerror(-rc));
793                 return rc;
794         }
795
796         if (fw_session_id == NULL) {
797                 rc = -EINVAL;
798                 TFP_DRV_LOG(ERR,
799                             "Invalid Argument(s), rc:%s\n",
800                             strerror(-rc));
801                 return rc;
802         }
803
804         rc = tf_session_get_session_internal(tfp, &tfs);
805         if (rc)
806                 return rc;
807
808         *fw_session_id = tfs->session_id.internal.fw_session_id;
809
810         return 0;
811 }
812
813 int
814 tf_session_get_session_id(struct tf *tfp,
815                           union tf_session_id *session_id)
816 {
817         int rc;
818         struct tf_session *tfs = NULL;
819
820         if (tfp->session == NULL) {
821                 rc = -EINVAL;
822                 TFP_DRV_LOG(ERR,
823                             "Session not created, rc:%s\n",
824                             strerror(-rc));
825                 return rc;
826         }
827
828         if (session_id == NULL) {
829                 rc = -EINVAL;
830                 TFP_DRV_LOG(ERR,
831                             "Invalid Argument(s), rc:%s\n",
832                             strerror(-rc));
833                 return rc;
834         }
835
836         /* Using internal version as session client may not exist yet */
837         rc = tf_session_get_session_internal(tfp, &tfs);
838         if (rc)
839                 return rc;
840
841         *session_id = tfs->session_id;
842
843         return 0;
844 }
845
846 int
847 tf_session_get_em_ext_db(struct tf *tfp,
848                          void **em_ext_db_handle)
849 {
850         struct tf_session *tfs = NULL;
851         int rc = 0;
852
853         *em_ext_db_handle = NULL;
854
855         if (tfp == NULL)
856                 return (-EINVAL);
857
858         rc = tf_session_get_session_internal(tfp, &tfs);
859         if (rc)
860                 return rc;
861
862         *em_ext_db_handle = tfs->em_ext_db_handle;
863         return rc;
864 }
865
866 int
867 tf_session_set_em_ext_db(struct tf *tfp,
868                          void *em_ext_db_handle)
869 {
870         struct tf_session *tfs = NULL;
871         int rc = 0;
872
873         if (tfp == NULL)
874                 return (-EINVAL);
875
876         rc = tf_session_get_session_internal(tfp, &tfs);
877         if (rc)
878                 return rc;
879
880         tfs->em_ext_db_handle = em_ext_db_handle;
881         return rc;
882 }
883
884 int
885 tf_session_get_db(struct tf *tfp,
886                   enum tf_module_type type,
887                   void **db_handle)
888 {
889         struct tf_session *tfs = NULL;
890         int rc = 0;
891
892         *db_handle = NULL;
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         switch (type) {
902         case TF_MODULE_TYPE_IDENTIFIER:
903                 if (tfs->id_db_handle)
904                         *db_handle = tfs->id_db_handle;
905                 else
906                         rc = -ENOMEM;
907                 break;
908         case TF_MODULE_TYPE_TABLE:
909                 if (tfs->tbl_db_handle)
910                         *db_handle = tfs->tbl_db_handle;
911                 else
912                         rc = -ENOMEM;
913
914                 break;
915         case TF_MODULE_TYPE_TCAM:
916                 if (tfs->tcam_db_handle)
917                         *db_handle = tfs->tcam_db_handle;
918                 else
919                         rc = -ENOMEM;
920                 break;
921         case TF_MODULE_TYPE_EM:
922                 if (tfs->em_db_handle)
923                         *db_handle = tfs->em_db_handle;
924                 else
925                         rc = -ENOMEM;
926                 break;
927         default:
928                 rc = -EINVAL;
929                 break;
930         }
931
932         return rc;
933 }
934
935 int
936 tf_session_set_db(struct tf *tfp,
937                   enum tf_module_type type,
938                   void *db_handle)
939 {
940         struct tf_session *tfs = NULL;
941         int rc = 0;
942
943         if (tfp == NULL)
944                 return (-EINVAL);
945
946         rc = tf_session_get_session_internal(tfp, &tfs);
947         if (rc)
948                 return rc;
949
950         switch (type) {
951         case TF_MODULE_TYPE_IDENTIFIER:
952                 tfs->id_db_handle = db_handle;
953                 break;
954         case TF_MODULE_TYPE_TABLE:
955                 tfs->tbl_db_handle = db_handle;
956                 break;
957         case TF_MODULE_TYPE_TCAM:
958                 tfs->tcam_db_handle = db_handle;
959                 break;
960         case TF_MODULE_TYPE_EM:
961                 tfs->em_db_handle = db_handle;
962                 break;
963         default:
964                 rc = -EINVAL;
965                 break;
966         }
967
968         return rc;
969 }
970
971 #ifdef TF_TCAM_SHARED
972
973 int
974 tf_session_get_tcam_shared_db(struct tf *tfp,
975                               void **tcam_shared_db_handle)
976 {
977         struct tf_session *tfs = NULL;
978         int rc = 0;
979
980         *tcam_shared_db_handle = NULL;
981
982         if (tfp == NULL)
983                 return (-EINVAL);
984
985         rc = tf_session_get_session_internal(tfp, &tfs);
986         if (rc)
987                 return rc;
988
989         *tcam_shared_db_handle = tfs->tcam_shared_db_handle;
990         return rc;
991 }
992
993 int
994 tf_session_set_tcam_shared_db(struct tf *tfp,
995                          void *tcam_shared_db_handle)
996 {
997         struct tf_session *tfs = NULL;
998         int rc = 0;
999
1000         if (tfp == NULL)
1001                 return (-EINVAL);
1002
1003         rc = tf_session_get_session_internal(tfp, &tfs);
1004         if (rc)
1005                 return rc;
1006
1007         tfs->tcam_shared_db_handle = tcam_shared_db_handle;
1008         return rc;
1009 }
1010 #endif /* TF_TCAM_SHARED */