net/bnxt: modify resource reservation strategy
[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         tfp_free(tfp->session->core_data);
219         tfp_free(tfp->session);
220         tfp->session = NULL;
221         return rc;
222 }
223
224 /**
225  * Creates a Session Client on an existing Session.
226  *
227  * [in] tfp
228  *   Pointer to TF handle
229  *
230  * [in] parms
231  *   Pointer to session client create parameters
232  *
233  * Returns
234  *   - (0) if successful.
235  *   - (-EINVAL) on failure.
236  *   - (-ENOMEM) if max session clients has been reached.
237  */
238 static int
239 tf_session_client_create(struct tf *tfp,
240                          struct tf_session_client_create_parms *parms)
241 {
242         int rc;
243         struct tf_session *session = NULL;
244         struct tf_session_client *client;
245         struct tfp_calloc_parms cparms;
246         union tf_session_client_id session_client_id;
247
248         TF_CHECK_PARMS2(tfp, parms);
249
250         /* Using internal version as session client may not exist yet */
251         rc = tf_session_get_session_internal(tfp, &session);
252         if (rc) {
253                 TFP_DRV_LOG(ERR,
254                             "Failed to lookup session, rc:%s\n",
255                             strerror(-rc));
256                 return rc;
257         }
258
259         client = tf_session_find_session_client_by_name(session,
260                                                         parms->ctrl_chan_name);
261         if (client) {
262                 TFP_DRV_LOG(ERR,
263                             "Client %s, already registered with this session\n",
264                             parms->ctrl_chan_name);
265                 return -EOPNOTSUPP;
266         }
267
268         rc = tf_msg_session_client_register
269                     (tfp,
270                      session,
271                      parms->ctrl_chan_name,
272                      &session_client_id.internal.fw_session_client_id);
273         if (rc) {
274                 TFP_DRV_LOG(ERR,
275                             "Failed to create client on session, rc:%s\n",
276                             strerror(-rc));
277                 return rc;
278         }
279
280         /* Create the local session client, initialize and attach to
281          * the session
282          */
283         cparms.nitems = 1;
284         cparms.size = sizeof(struct tf_session_client);
285         cparms.alignment = 0;
286         rc = tfp_calloc(&cparms);
287         if (rc) {
288                 TFP_DRV_LOG(ERR,
289                             "Failed to allocate session client, rc:%s\n",
290                             strerror(-rc));
291                 goto cleanup;
292         }
293         client = cparms.mem_va;
294
295         /* Register FID with the client */
296         rc = tfp_get_fid(tfp, &client->fw_fid);
297         if (rc)
298                 return rc;
299
300         /* Build the Session Client ID by adding the fw_session_id */
301         rc = tf_session_get_fw_session_id
302                         (tfp,
303                         &session_client_id.internal.fw_session_id);
304         if (rc) {
305                 TFP_DRV_LOG(ERR,
306                             "Session Firmware id lookup failed, rc:%s\n",
307                             strerror(-rc));
308                 return rc;
309         }
310
311         tfp_memcpy(client->ctrl_chan_name,
312                    parms->ctrl_chan_name,
313                    TF_SESSION_NAME_MAX);
314
315         client->session_client_id.id = session_client_id.id;
316
317         ll_insert(&session->client_ll, &client->ll_entry);
318
319         session->ref_count++;
320
321         /* Build the return value */
322         parms->session_client_id->id = session_client_id.id;
323
324  cleanup:
325         /* TBD - Add code to unregister newly create client from fw */
326
327         return rc;
328 }
329
330
331 /**
332  * Destroys a Session Client on an existing Session.
333  *
334  * [in] tfp
335  *   Pointer to TF handle
336  *
337  * [in] parms
338  *   Pointer to the session client destroy parameters
339  *
340  * Returns
341  *   - (0) if successful.
342  *   - (-EINVAL) on failure.
343  *   - (-ENOTFOUND) error, client not owned by the session.
344  *   - (-ENOTSUPP) error, unable to destroy client as its the last
345  *                 client. Please use the tf_session_close().
346  */
347 static int
348 tf_session_client_destroy(struct tf *tfp,
349                           struct tf_session_client_destroy_parms *parms)
350 {
351         int rc;
352         struct tf_session *tfs;
353         struct tf_session_client *client;
354
355         TF_CHECK_PARMS2(tfp, parms);
356
357         rc = tf_session_get_session(tfp, &tfs);
358         if (rc) {
359                 TFP_DRV_LOG(ERR,
360                             "Failed to lookup session, rc:%s\n",
361                             strerror(-rc));
362                 return rc;
363         }
364
365         /* Check session owns this client and that we're not the last client */
366         client = tf_session_get_session_client(tfs,
367                                                parms->session_client_id);
368         if (client == NULL) {
369                 TFP_DRV_LOG(ERR,
370                             "Client %d, not found within this session\n",
371                             parms->session_client_id.id);
372                 return -EINVAL;
373         }
374
375         /* If last client the request is rejected and cleanup should
376          * be done by session close.
377          */
378         if (tfs->ref_count == 1)
379                 return -EOPNOTSUPP;
380
381         rc = tf_msg_session_client_unregister
382                         (tfp,
383                         tfs,
384                         parms->session_client_id.internal.fw_session_client_id);
385
386         /* Log error, but continue. If FW fails we do not really have
387          * a way to fix this but the client would no longer be valid
388          * thus we remove from the session.
389          */
390         if (rc) {
391                 TFP_DRV_LOG(ERR,
392                             "Client destroy on FW Failed, rc:%s\n",
393                             strerror(-rc));
394         }
395
396         ll_delete(&tfs->client_ll, &client->ll_entry);
397
398         /* Decrement the session ref_count */
399         tfs->ref_count--;
400
401         tfp_free(client);
402
403         return rc;
404 }
405
406 int
407 tf_session_open_session(struct tf *tfp,
408                         struct tf_session_open_session_parms *parms)
409 {
410         int rc;
411         struct tf_session_client_create_parms scparms;
412
413         TF_CHECK_PARMS3(tfp, parms, parms->open_cfg->bp);
414
415         tfp->bp = parms->open_cfg->bp;
416         /* Decide if we're creating a new session or session client */
417         if (tfp->session == NULL) {
418                 rc = tf_session_create(tfp, parms);
419                 if (rc) {
420                         TFP_DRV_LOG(ERR,
421                                     "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
422                                     parms->open_cfg->ctrl_chan_name,
423                                     strerror(-rc));
424                         return rc;
425                 }
426
427                 TFP_DRV_LOG(INFO,
428                        "Session created, session_client_id:%d, session_id:%d\n",
429                        parms->open_cfg->session_client_id.id,
430                        parms->open_cfg->session_id.id);
431         } else {
432                 scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
433                 scparms.session_client_id = &parms->open_cfg->session_client_id;
434
435                 /* Create the new client and get it associated with
436                  * the session.
437                  */
438                 rc = tf_session_client_create(tfp, &scparms);
439                 if (rc) {
440                         TFP_DRV_LOG(ERR,
441                               "Failed to create client on session %d, rc:%s\n",
442                               parms->open_cfg->session_id.id,
443                               strerror(-rc));
444                         return rc;
445                 }
446
447                 TFP_DRV_LOG(INFO,
448                             "Session Client:%d created on session:%d\n",
449                             parms->open_cfg->session_client_id.id,
450                             parms->open_cfg->session_id.id);
451         }
452
453         return 0;
454 }
455
456 int
457 tf_session_attach_session(struct tf *tfp __rte_unused,
458                           struct tf_session_attach_session_parms *parms __rte_unused)
459 {
460         int rc = -EOPNOTSUPP;
461
462         TF_CHECK_PARMS2(tfp, parms);
463
464         TFP_DRV_LOG(ERR,
465                     "Attach not yet supported, rc:%s\n",
466                     strerror(-rc));
467         return rc;
468 }
469
470 int
471 tf_session_close_session(struct tf *tfp,
472                          struct tf_session_close_session_parms *parms)
473 {
474         int rc;
475         struct tf_session *tfs = NULL;
476         struct tf_session_client *client;
477         struct tf_dev_info *tfd = NULL;
478         struct tf_session_client_destroy_parms scdparms;
479         uint16_t fid;
480
481         TF_CHECK_PARMS2(tfp, parms);
482
483         rc = tf_session_get_session(tfp, &tfs);
484         if (rc) {
485                 TFP_DRV_LOG(ERR,
486                             "Session lookup failed, rc:%s\n",
487                             strerror(-rc));
488                 return rc;
489         }
490
491         if (tfs->session_id.id == TF_SESSION_ID_INVALID) {
492                 rc = -EINVAL;
493                 TFP_DRV_LOG(ERR,
494                             "Invalid session id, unable to close, rc:%s\n",
495                             strerror(-rc));
496                 return rc;
497         }
498
499         /* Get the client, we need it independently of the closure
500          * type (client or session closure).
501          *
502          * We find the client by way of the fid. Thus one cannot close
503          * a client on behalf of someone else.
504          */
505         rc = tfp_get_fid(tfp, &fid);
506         if (rc)
507                 return rc;
508
509         client = tf_session_find_session_client_by_fid(tfs,
510                                                        fid);
511         if (!client) {
512                 rc = -EINVAL;
513                 TFP_DRV_LOG(ERR,
514                             "Client not part of the session, unable to close, rc:%s\n",
515                             strerror(-rc));
516                 return rc;
517         }
518
519         /* In case multiple clients we chose to close those first */
520         if (tfs->ref_count > 1) {
521                 /* Linaro gcc can't static init this structure */
522                 memset(&scdparms,
523                        0,
524                        sizeof(struct tf_session_client_destroy_parms));
525
526                 scdparms.session_client_id = client->session_client_id;
527                 /* Destroy requested client so its no longer
528                  * registered with this session.
529                  */
530                 rc = tf_session_client_destroy(tfp, &scdparms);
531                 if (rc) {
532                         TFP_DRV_LOG(ERR,
533                                     "Failed to unregister Client %d, rc:%s\n",
534                                     client->session_client_id.id,
535                                     strerror(-rc));
536                         return rc;
537                 }
538
539                 TFP_DRV_LOG(INFO,
540                             "Closed session client, session_client_id:%d\n",
541                             client->session_client_id.id);
542
543                 TFP_DRV_LOG(INFO,
544                             "session_id:%d, ref_count:%d\n",
545                             tfs->session_id.id,
546                             tfs->ref_count);
547
548                 return 0;
549         }
550
551         /* Record the session we're closing so the caller knows the
552          * details.
553          */
554         *parms->session_id = tfs->session_id;
555
556         rc = tf_session_get_device(tfs, &tfd);
557         if (rc) {
558                 TFP_DRV_LOG(ERR,
559                             "Device lookup failed, rc:%s\n",
560                             strerror(-rc));
561                 return rc;
562         }
563
564         /* Unbind the device */
565         rc = tf_dev_unbind(tfp, tfd);
566         if (rc) {
567                 /* Log error */
568                 TFP_DRV_LOG(ERR,
569                             "Device unbind failed, rc:%s\n",
570                             strerror(-rc));
571         }
572
573         rc = tf_msg_session_close(tfp, tfs);
574         if (rc) {
575                 /* Log error */
576                 TFP_DRV_LOG(ERR,
577                             "FW Session close failed, rc:%s\n",
578                             strerror(-rc));
579         }
580
581         /* Final cleanup as we're last user of the session thus we
582          * also delete the last client.
583          */
584         ll_delete(&tfs->client_ll, &client->ll_entry);
585         tfp_free(client);
586
587         tfs->ref_count--;
588
589         TFP_DRV_LOG(INFO,
590                     "Closed session, session_id:%d, ref_count:%d\n",
591                     tfs->session_id.id,
592                     tfs->ref_count);
593
594         tfs->dev_init = false;
595
596         tfp_free(tfp->session->core_data);
597         tfp_free(tfp->session);
598         tfp->session = NULL;
599
600         return 0;
601 }
602
603 bool
604 tf_session_is_fid_supported(struct tf_session *tfs,
605                             uint16_t fid)
606 {
607         struct ll_entry *c_entry;
608         struct tf_session_client *client;
609
610         for (c_entry = tfs->client_ll.head;
611              c_entry != NULL;
612              c_entry = c_entry->next) {
613                 client = (struct tf_session_client *)c_entry;
614                 if (client->fw_fid == fid)
615                         return true;
616         }
617
618         return false;
619 }
620
621 int
622 tf_session_get_session_internal(struct tf *tfp,
623                                 struct tf_session **tfs)
624 {
625         int rc = 0;
626
627         /* Skip using the check macro as we want to control the error msg */
628         if (tfp->session == NULL || tfp->session->core_data == NULL) {
629                 rc = -EINVAL;
630                 TFP_DRV_LOG(ERR,
631                             "Session not created, rc:%s\n",
632                             strerror(-rc));
633                 return rc;
634         }
635
636         *tfs = (struct tf_session *)(tfp->session->core_data);
637
638         return rc;
639 }
640
641 int
642 tf_session_get_session(struct tf *tfp,
643                        struct tf_session **tfs)
644 {
645         int rc;
646         uint16_t fw_fid;
647         bool supported = false;
648
649         rc = tf_session_get_session_internal(tfp,
650                                              tfs);
651         /* Logging done by tf_session_get_session_internal */
652         if (rc)
653                 return rc;
654
655         /* As session sharing among functions aka 'individual clients'
656          * is supported we have to assure that the client is indeed
657          * registered before we get deep in the TruFlow api stack.
658          */
659         rc = tfp_get_fid(tfp, &fw_fid);
660         if (rc) {
661                 TFP_DRV_LOG(ERR,
662                             "Internal FID lookup\n, rc:%s\n",
663                             strerror(-rc));
664                 return rc;
665         }
666
667         supported = tf_session_is_fid_supported(*tfs, fw_fid);
668         if (!supported) {
669                 TFP_DRV_LOG
670                         (ERR,
671                         "Ctrl channel not registered with session\n, rc:%s\n",
672                         strerror(-rc));
673                 return -EINVAL;
674         }
675
676         return rc;
677 }
678
679 struct tf_session_client *
680 tf_session_get_session_client(struct tf_session *tfs,
681                               union tf_session_client_id session_client_id)
682 {
683         struct ll_entry *c_entry;
684         struct tf_session_client *client;
685
686         /* Skip using the check macro as we just want to return */
687         if (tfs == NULL)
688                 return NULL;
689
690         for (c_entry = tfs->client_ll.head;
691              c_entry != NULL;
692              c_entry = c_entry->next) {
693                 client = (struct tf_session_client *)c_entry;
694                 if (client->session_client_id.id == session_client_id.id)
695                         return client;
696         }
697
698         return NULL;
699 }
700
701 struct tf_session_client *
702 tf_session_find_session_client_by_name(struct tf_session *tfs,
703                                        const char *ctrl_chan_name)
704 {
705         struct ll_entry *c_entry;
706         struct tf_session_client *client;
707
708         /* Skip using the check macro as we just want to return */
709         if (tfs == NULL || ctrl_chan_name == NULL)
710                 return NULL;
711
712         for (c_entry = tfs->client_ll.head;
713              c_entry != NULL;
714              c_entry = c_entry->next) {
715                 client = (struct tf_session_client *)c_entry;
716                 if (strncmp(client->ctrl_chan_name,
717                             ctrl_chan_name,
718                             TF_SESSION_NAME_MAX) == 0)
719                         return client;
720         }
721
722         return NULL;
723 }
724
725 struct tf_session_client *
726 tf_session_find_session_client_by_fid(struct tf_session *tfs,
727                                       uint16_t fid)
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)
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 (client->fw_fid == fid)
741                         return client;
742         }
743
744         return NULL;
745 }
746
747 int
748 tf_session_get_device(struct tf_session *tfs,
749                       struct tf_dev_info **tfd)
750 {
751         *tfd = &tfs->dev;
752
753         return 0;
754 }
755
756 int
757 tf_session_get_fw_session_id(struct tf *tfp,
758                              uint8_t *fw_session_id)
759 {
760         int rc;
761         struct tf_session *tfs = NULL;
762
763         /* Skip using the check macro as we want to control the error msg */
764         if (tfp->session == NULL) {
765                 rc = -EINVAL;
766                 TFP_DRV_LOG(ERR,
767                             "Session not created, rc:%s\n",
768                             strerror(-rc));
769                 return rc;
770         }
771
772         if (fw_session_id == NULL) {
773                 rc = -EINVAL;
774                 TFP_DRV_LOG(ERR,
775                             "Invalid Argument(s), rc:%s\n",
776                             strerror(-rc));
777                 return rc;
778         }
779
780         rc = tf_session_get_session_internal(tfp, &tfs);
781         if (rc)
782                 return rc;
783
784         *fw_session_id = tfs->session_id.internal.fw_session_id;
785
786         return 0;
787 }
788
789 int
790 tf_session_get_session_id(struct tf *tfp,
791                           union tf_session_id *session_id)
792 {
793         int rc;
794         struct tf_session *tfs = NULL;
795
796         if (tfp->session == NULL) {
797                 rc = -EINVAL;
798                 TFP_DRV_LOG(ERR,
799                             "Session not created, rc:%s\n",
800                             strerror(-rc));
801                 return rc;
802         }
803
804         if (session_id == NULL) {
805                 rc = -EINVAL;
806                 TFP_DRV_LOG(ERR,
807                             "Invalid Argument(s), rc:%s\n",
808                             strerror(-rc));
809                 return rc;
810         }
811
812         /* Using internal version as session client may not exist yet */
813         rc = tf_session_get_session_internal(tfp, &tfs);
814         if (rc)
815                 return rc;
816
817         *session_id = tfs->session_id;
818
819         return 0;
820 }
821
822 int
823 tf_session_get_em_ext_db(struct tf *tfp,
824                          void **em_ext_db_handle)
825 {
826         struct tf_session *tfs = NULL;
827         int rc = 0;
828
829         *em_ext_db_handle = NULL;
830
831         if (tfp == NULL)
832                 return (-EINVAL);
833
834         rc = tf_session_get_session_internal(tfp, &tfs);
835         if (rc)
836                 return rc;
837
838         *em_ext_db_handle = tfs->em_ext_db_handle;
839         return rc;
840 }
841
842 int
843 tf_session_set_em_ext_db(struct tf *tfp,
844                          void *em_ext_db_handle)
845 {
846         struct tf_session *tfs = NULL;
847         int rc = 0;
848
849         if (tfp == NULL)
850                 return (-EINVAL);
851
852         rc = tf_session_get_session_internal(tfp, &tfs);
853         if (rc)
854                 return rc;
855
856         tfs->em_ext_db_handle = em_ext_db_handle;
857         return rc;
858 }
859
860 int
861 tf_session_get_db(struct tf *tfp,
862                   enum tf_module_type type,
863                   void **db_handle)
864 {
865         struct tf_session *tfs = NULL;
866         int rc = 0;
867
868         *db_handle = NULL;
869
870         if (tfp == NULL)
871                 return (-EINVAL);
872
873         rc = tf_session_get_session_internal(tfp, &tfs);
874         if (rc)
875                 return rc;
876
877         switch (type) {
878         case TF_MODULE_TYPE_IDENTIFIER:
879                 if (tfs->id_db_handle)
880                         *db_handle = tfs->id_db_handle;
881                 else
882                         rc = -EINVAL;
883                 break;
884         case TF_MODULE_TYPE_TABLE:
885                 if (tfs->tbl_db_handle)
886                         *db_handle = tfs->tbl_db_handle;
887                 else
888                         rc = -EINVAL;
889
890                 break;
891         case TF_MODULE_TYPE_TCAM:
892                 if (tfs->tcam_db_handle)
893                         *db_handle = tfs->tcam_db_handle;
894                 else
895                         rc = -EINVAL;
896                 break;
897         case TF_MODULE_TYPE_EM:
898                 if (tfs->em_db_handle)
899                         *db_handle = tfs->em_db_handle;
900                 else
901                         rc = -EINVAL;
902                 break;
903         default:
904                 rc = -EINVAL;
905                 break;
906         }
907
908         return rc;
909 }
910
911 int
912 tf_session_set_db(struct tf *tfp,
913                   enum tf_module_type type,
914                   void *db_handle)
915 {
916         struct tf_session *tfs = NULL;
917         int rc = 0;
918
919         if (tfp == NULL)
920                 return (-EINVAL);
921
922         rc = tf_session_get_session_internal(tfp, &tfs);
923         if (rc)
924                 return rc;
925
926         switch (type) {
927         case TF_MODULE_TYPE_IDENTIFIER:
928                 tfs->id_db_handle = db_handle;
929                 break;
930         case TF_MODULE_TYPE_TABLE:
931                 tfs->tbl_db_handle = db_handle;
932                 break;
933         case TF_MODULE_TYPE_TCAM:
934                 tfs->tcam_db_handle = db_handle;
935                 break;
936         case TF_MODULE_TYPE_EM:
937                 tfs->em_db_handle = db_handle;
938                 break;
939         default:
940                 rc = -EINVAL;
941                 break;
942         }
943
944         return rc;
945 }