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