/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2019-2020 Broadcom
+ * Copyright(c) 2019-2021 Broadcom
* All rights reserved.
*/
#include "tf_common.h"
#include "tf_msg.h"
#include "tfp.h"
+#include "bnxt.h"
-int
-tf_session_open_session(struct tf *tfp,
- struct tf_session_open_session_parms *parms)
+struct tf_session_client_create_parms {
+ /**
+ * [in] Pointer to the control channel name string
+ */
+ char *ctrl_chan_name;
+
+ /**
+ * [out] Firmware Session Client ID
+ */
+ union tf_session_client_id *session_client_id;
+};
+
+struct tf_session_client_destroy_parms {
+ /**
+ * FW Session Client Identifier
+ */
+ union tf_session_client_id session_client_id;
+};
+
+/**
+ * Creates a Session and the associated client.
+ *
+ * [in] tfp
+ * Pointer to TF handle
+ *
+ * [in] parms
+ * Pointer to session client create parameters
+ *
+ * Returns
+ * - (0) if successful.
+ * - (-EINVAL) on failure.
+ * - (-ENOMEM) if max session clients has been reached.
+ */
+static int
+tf_session_create(struct tf *tfp,
+ struct tf_session_open_session_parms *parms)
{
int rc;
struct tf_session *session = NULL;
+ struct tf_session_client *client;
struct tfp_calloc_parms cparms;
uint8_t fw_session_id;
+ uint8_t fw_session_client_id;
union tf_session_id *session_id;
+ struct tf_dev_info dev;
+ bool shared_session_creator;
+ int name_len;
+ char *name;
TF_CHECK_PARMS2(tfp, parms);
+ tf_dev_bind_ops(parms->open_cfg->device_type,
+ &dev);
+
/* Open FW session and get a new session_id */
- rc = tf_msg_session_open(tfp,
+ rc = tf_msg_session_open(parms->open_cfg->bp,
parms->open_cfg->ctrl_chan_name,
- &fw_session_id);
+ &fw_session_id,
+ &fw_session_client_id,
+ &dev,
+ &shared_session_creator);
if (rc) {
/* Log error */
if (rc == -EEXIST)
goto cleanup;
}
tfp->session->core_data = cparms.mem_va;
+ session_id = &parms->open_cfg->session_id;
+
+ /* Update Session Info, which is what is visible to the caller */
+ tfp->session->ver.major = 0;
+ tfp->session->ver.minor = 0;
+ tfp->session->ver.update = 0;
- /* Initialize Session and Device */
+ tfp->session->session_id.internal.domain = session_id->internal.domain;
+ tfp->session->session_id.internal.bus = session_id->internal.bus;
+ tfp->session->session_id.internal.device = session_id->internal.device;
+ tfp->session->session_id.internal.fw_session_id = fw_session_id;
+
+ /* Initialize Session and Device, which is private */
session = (struct tf_session *)tfp->session->core_data;
session->ver.major = 0;
session->ver.minor = 0;
session->ver.update = 0;
- session_id = &parms->open_cfg->session_id;
session->session_id.internal.domain = session_id->internal.domain;
session->session_id.internal.bus = session_id->internal.bus;
session->session_id.internal.device = session_id->internal.device;
session->session_id.internal.fw_session_id = fw_session_id;
- /* Return the allocated fw session id */
- session_id->internal.fw_session_id = fw_session_id;
+ /* Return the allocated session id */
+ session_id->id = session->session_id.id;
session->shadow_copy = parms->open_cfg->shadow_copy;
- tfp_memcpy(session->ctrl_chan_name,
+ /* Init session client list */
+ ll_init(&session->client_ll);
+
+ /* Create the local session client, initialize and attach to
+ * the session
+ */
+ cparms.nitems = 1;
+ cparms.size = sizeof(struct tf_session_client);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc) {
+ /* Log error */
+ TFP_DRV_LOG(ERR,
+ "Failed to allocate session client, rc:%s\n",
+ strerror(-rc));
+ goto cleanup;
+ }
+ client = cparms.mem_va;
+
+ /* Register FID with the client */
+ rc = tfp_get_fid(tfp, &client->fw_fid);
+ if (rc)
+ return rc;
+
+ client->session_client_id.internal.fw_session_id = fw_session_id;
+ client->session_client_id.internal.fw_session_client_id =
+ fw_session_client_id;
+
+ tfp_memcpy(client->ctrl_chan_name,
parms->open_cfg->ctrl_chan_name,
TF_SESSION_NAME_MAX);
- rc = dev_bind(tfp,
- parms->open_cfg->device_type,
- session->shadow_copy,
- &parms->open_cfg->resources,
- session->dev);
+ ll_insert(&session->client_ll, &client->ll_entry);
+ session->ref_count++;
+
+ /* Init session em_ext_db */
+ session->em_ext_db_handle = NULL;
+
+ /* Populate the request */
+ name_len = strnlen(parms->open_cfg->ctrl_chan_name,
+ TF_SESSION_NAME_MAX);
+ name = &parms->open_cfg->ctrl_chan_name[name_len - strlen("tf_shared")];
+ if (!strncmp(name, "tf_shared", strlen("tf_shared")))
+ session->shared_session = true;
+
+ name = &parms->open_cfg->ctrl_chan_name[name_len -
+ strlen("tf_shared-wc_tcam")];
+ if (!strncmp(name, "tf_shared-wc_tcam", strlen("tf_shared-wc_tcam")))
+ session->shared_session = true;
+
+ if (session->shared_session && shared_session_creator) {
+ session->shared_session_creator = true;
+ parms->open_cfg->shared_session_creator = true;
+ }
+
+ rc = tf_dev_bind(tfp,
+ parms->open_cfg->device_type,
+ session->shadow_copy,
+ &parms->open_cfg->resources,
+ &session->dev);
+
/* Logging handled by dev_bind */
if (rc)
+ goto cleanup;
+
+ if (session->dev.ops->tf_dev_get_mailbox == NULL) {
+ /* Log error */
+ TFP_DRV_LOG(ERR,
+ "No tf_dev_get_mailbox() defined for device\n");
+ goto cleanup;
+ }
+
+ session->dev_init = true;
+
+ return 0;
+
+ cleanup:
+ rc = tf_msg_session_close(tfp,
+ fw_session_id,
+ dev.ops->tf_dev_get_mailbox());
+ if (rc) {
+ /* Log error */
+ TFP_DRV_LOG(ERR,
+ "FW Session close failed, rc:%s\n",
+ strerror(-rc));
+ }
+
+ tfp_free(tfp->session->core_data);
+ tfp_free(tfp->session);
+ tfp->session = NULL;
+ return rc;
+}
+
+/**
+ * Creates a Session Client on an existing Session.
+ *
+ * [in] tfp
+ * Pointer to TF handle
+ *
+ * [in] parms
+ * Pointer to session client create parameters
+ *
+ * Returns
+ * - (0) if successful.
+ * - (-EINVAL) on failure.
+ * - (-ENOMEM) if max session clients has been reached.
+ */
+static int
+tf_session_client_create(struct tf *tfp,
+ struct tf_session_client_create_parms *parms)
+{
+ int rc;
+ struct tf_session *session = NULL;
+ struct tf_session_client *client;
+ struct tfp_calloc_parms cparms;
+ union tf_session_client_id session_client_id;
+
+ TF_CHECK_PARMS2(tfp, parms);
+
+ /* Using internal version as session client may not exist yet */
+ rc = tf_session_get_session_internal(tfp, &session);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Failed to lookup session, rc:%s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ client = tf_session_find_session_client_by_name(session,
+ parms->ctrl_chan_name);
+ if (client) {
+ TFP_DRV_LOG(ERR,
+ "Client %s, already registered with this session\n",
+ parms->ctrl_chan_name);
+ return -EOPNOTSUPP;
+ }
+
+ rc = tf_msg_session_client_register
+ (tfp,
+ session,
+ parms->ctrl_chan_name,
+ &session_client_id.internal.fw_session_client_id);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Failed to create client on session, rc:%s\n",
+ strerror(-rc));
return rc;
+ }
- /* Query for Session Config
+ /* Create the local session client, initialize and attach to
+ * the session
*/
- rc = tf_msg_session_qcfg(tfp);
+ cparms.nitems = 1;
+ cparms.size = sizeof(struct tf_session_client);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Failed to allocate session client, rc:%s\n",
+ strerror(-rc));
+ goto cleanup;
+ }
+ client = cparms.mem_va;
+
+ /* Register FID with the client */
+ rc = tfp_get_fid(tfp, &client->fw_fid);
+ if (rc)
+ return rc;
+
+ /* Build the Session Client ID by adding the fw_session_id */
+ rc = tf_session_get_fw_session_id
+ (tfp,
+ &session_client_id.internal.fw_session_id);
if (rc) {
TFP_DRV_LOG(ERR,
- "Query config message send failed, rc:%s\n",
+ "Session Firmware id lookup failed, rc:%s\n",
strerror(-rc));
- goto cleanup_close;
+ return rc;
}
+ tfp_memcpy(client->ctrl_chan_name,
+ parms->ctrl_chan_name,
+ TF_SESSION_NAME_MAX);
+
+ client->session_client_id.id = session_client_id.id;
+
+ ll_insert(&session->client_ll, &client->ll_entry);
+
session->ref_count++;
- return 0;
+ /* Build the return value */
+ parms->session_client_id->id = session_client_id.id;
cleanup:
- tfp_free(tfp->session->core_data);
- tfp_free(tfp->session);
- tfp->session = NULL;
+ /* TBD - Add code to unregister newly create client from fw */
+
+ return rc;
+}
+
+
+/**
+ * Destroys a Session Client on an existing Session.
+ *
+ * [in] tfp
+ * Pointer to TF handle
+ *
+ * [in] parms
+ * Pointer to the session client destroy parameters
+ *
+ * Returns
+ * - (0) if successful.
+ * - (-EINVAL) on failure.
+ * - (-ENOTFOUND) error, client not owned by the session.
+ * - (-ENOTSUPP) error, unable to destroy client as its the last
+ * client. Please use the tf_session_close().
+ */
+static int
+tf_session_client_destroy(struct tf *tfp,
+ struct tf_session_client_destroy_parms *parms)
+{
+ int rc;
+ struct tf_session *tfs;
+ struct tf_session_client *client;
+
+ TF_CHECK_PARMS2(tfp, parms);
+
+ rc = tf_session_get_session(tfp, &tfs);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Failed to lookup session, rc:%s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Check session owns this client and that we're not the last client */
+ client = tf_session_get_session_client(tfs,
+ parms->session_client_id);
+ if (client == NULL) {
+ TFP_DRV_LOG(ERR,
+ "Client %d, not found within this session\n",
+ parms->session_client_id.id);
+ return -EINVAL;
+ }
+
+ /* If last client the request is rejected and cleanup should
+ * be done by session close.
+ */
+ if (tfs->ref_count == 1)
+ return -EOPNOTSUPP;
+
+ rc = tf_msg_session_client_unregister
+ (tfp,
+ tfs,
+ parms->session_client_id.internal.fw_session_client_id);
+
+ /* Log error, but continue. If FW fails we do not really have
+ * a way to fix this but the client would no longer be valid
+ * thus we remove from the session.
+ */
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Client destroy on FW Failed, rc:%s\n",
+ strerror(-rc));
+ }
+
+ ll_delete(&tfs->client_ll, &client->ll_entry);
+
+ /* Decrement the session ref_count */
+ tfs->ref_count--;
+
+ tfp_free(client);
+
return rc;
+}
+
+int
+tf_session_open_session(struct tf *tfp,
+ struct tf_session_open_session_parms *parms)
+{
+ int rc;
+ struct tf_session_client_create_parms scparms;
+
+ TF_CHECK_PARMS3(tfp, parms, parms->open_cfg->bp);
+
+ tfp->bp = parms->open_cfg->bp;
+ /* Decide if we're creating a new session or session client */
+ if (tfp->session == NULL) {
+ rc = tf_session_create(tfp, parms);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Failed to create session, ctrl_chan_name:%s, rc:%s\n",
+ parms->open_cfg->ctrl_chan_name,
+ strerror(-rc));
+ return rc;
+ }
+
+ TFP_DRV_LOG(INFO,
+ "Session created, session_client_id:%d,"
+ "session_id:0x%08x, fw_session_id:%d\n",
+ parms->open_cfg->session_client_id.id,
+ parms->open_cfg->session_id.id,
+ parms->open_cfg->session_id.internal.fw_session_id);
+ } else {
+ scparms.ctrl_chan_name = parms->open_cfg->ctrl_chan_name;
+ scparms.session_client_id = &parms->open_cfg->session_client_id;
+
+ /* Create the new client and get it associated with
+ * the session.
+ */
+ rc = tf_session_client_create(tfp, &scparms);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Failed to create client on session 0x%x, rc:%s\n",
+ parms->open_cfg->session_id.id,
+ strerror(-rc));
+ return rc;
+ }
+
+ TFP_DRV_LOG(INFO,
+ "Session Client:%d registered on session:0x%8x\n",
+ scparms.session_client_id->internal.fw_session_client_id,
+ tfp->session->session_id.id);
+ }
- cleanup_close:
- tf_close_session(tfp);
- return -EINVAL;
+ return 0;
}
int
{
int rc;
struct tf_session *tfs = NULL;
+ struct tf_session_client *client;
struct tf_dev_info *tfd = NULL;
+ struct tf_session_client_destroy_parms scdparms;
+ uint16_t fid;
+ uint8_t fw_session_id = 1;
+ int mailbox = 0;
TF_CHECK_PARMS2(tfp, parms);
return rc;
}
+ /* Get the client, we need it independently of the closure
+ * type (client or session closure).
+ *
+ * We find the client by way of the fid. Thus one cannot close
+ * a client on behalf of someone else.
+ */
+ rc = tfp_get_fid(tfp, &fid);
+ if (rc)
+ return rc;
+
+ client = tf_session_find_session_client_by_fid(tfs,
+ fid);
+ if (!client) {
+ rc = -EINVAL;
+ TFP_DRV_LOG(ERR,
+ "Client not part of the session, unable to close, rc:%s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ /* In case multiple clients we chose to close those first */
+ if (tfs->ref_count > 1) {
+ /* Linaro gcc can't static init this structure */
+ memset(&scdparms,
+ 0,
+ sizeof(struct tf_session_client_destroy_parms));
+
+ scdparms.session_client_id = client->session_client_id;
+ /* Destroy requested client so its no longer
+ * registered with this session.
+ */
+ rc = tf_session_client_destroy(tfp, &scdparms);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Failed to unregister Client %d, rc:%s\n",
+ client->session_client_id.id,
+ strerror(-rc));
+ return rc;
+ }
+
+ TFP_DRV_LOG(INFO,
+ "Closed session client, session_client_id:%d\n",
+ client->session_client_id.id);
+
+ TFP_DRV_LOG(INFO,
+ "session_id:0x%08x, ref_count:%d\n",
+ tfs->session_id.id,
+ tfs->ref_count);
+
+ return 0;
+ }
+
/* Record the session we're closing so the caller knows the
* details.
*/
return rc;
}
- /* In case we're attached only the session client gets closed */
- rc = tf_msg_session_close(tfp);
+ mailbox = tfd->ops->tf_dev_get_mailbox();
+
+ rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "Unable to lookup FW id, rc:%s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Unbind the device */
+ rc = tf_dev_unbind(tfp, tfd);
+ if (rc) {
+ /* Log error */
+ TFP_DRV_LOG(ERR,
+ "Device unbind failed, rc:%s\n",
+ strerror(-rc));
+ }
+
+ rc = tf_msg_session_close(tfp, fw_session_id, mailbox);
if (rc) {
/* Log error */
TFP_DRV_LOG(ERR,
strerror(-rc));
}
+ /* Final cleanup as we're last user of the session thus we
+ * also delete the last client.
+ */
+ ll_delete(&tfs->client_ll, &client->ll_entry);
+ tfp_free(client);
+
tfs->ref_count--;
- /* Final cleanup as we're last user of the session */
- if (tfs->ref_count == 0) {
- /* Unbind the device */
- rc = dev_unbind(tfp, tfd);
- if (rc) {
- /* Log error */
- TFP_DRV_LOG(ERR,
- "Device unbind failed, rc:%s\n",
- strerror(-rc));
- }
+ TFP_DRV_LOG(INFO,
+ "Closed session, session_id:0x%08x, ref_count:%d\n",
+ tfs->session_id.id,
+ tfs->ref_count);
- tfp_free(tfp->session->core_data);
- tfp_free(tfp->session);
- tfp->session = NULL;
- }
+ tfs->dev_init = false;
+
+ tfp_free(tfp->session->core_data);
+ tfp_free(tfp->session);
+ tfp->session = NULL;
return 0;
}
+bool
+tf_session_is_fid_supported(struct tf_session *tfs,
+ uint16_t fid)
+{
+ struct ll_entry *c_entry;
+ struct tf_session_client *client;
+
+ for (c_entry = tfs->client_ll.head;
+ c_entry != NULL;
+ c_entry = c_entry->next) {
+ client = (struct tf_session_client *)c_entry;
+ if (client->fw_fid == fid)
+ return true;
+ }
+
+ return false;
+}
+
int
-tf_session_get_session(struct tf *tfp,
- struct tf_session **tfs)
+tf_session_get_session_internal(struct tf *tfp,
+ struct tf_session **tfs)
{
- int rc;
+ int rc = 0;
+ /* Skip using the check macro as we want to control the error msg */
if (tfp->session == NULL || tfp->session->core_data == NULL) {
rc = -EINVAL;
TFP_DRV_LOG(ERR,
*tfs = (struct tf_session *)(tfp->session->core_data);
- return 0;
+ return rc;
}
int
-tf_session_get_device(struct tf_session *tfs,
- struct tf_dev_info **tfd)
+tf_session_get_session(struct tf *tfp,
+ struct tf_session **tfs)
{
int rc;
+ uint16_t fw_fid;
+ bool supported = false;
- if (tfs->dev == NULL) {
- rc = -EINVAL;
+ rc = tf_session_get_session_internal(tfp,
+ tfs);
+ /* Logging done by tf_session_get_session_internal */
+ if (rc)
+ return rc;
+
+ /* As session sharing among functions aka 'individual clients'
+ * is supported we have to assure that the client is indeed
+ * registered before we get deep in the TruFlow api stack.
+ */
+ rc = tfp_get_fid(tfp, &fw_fid);
+ if (rc) {
TFP_DRV_LOG(ERR,
- "Device not created, rc:%s\n",
+ "Internal FID lookup\n, rc:%s\n",
strerror(-rc));
return rc;
}
- *tfd = tfs->dev;
+ supported = tf_session_is_fid_supported(*tfs, fw_fid);
+ if (!supported) {
+ TFP_DRV_LOG
+ (ERR,
+ "Ctrl channel not registered with session\n, rc:%s\n",
+ strerror(-rc));
+ return -EINVAL;
+ }
+
+ return rc;
+}
+
+struct tf_session_client *
+tf_session_get_session_client(struct tf_session *tfs,
+ union tf_session_client_id session_client_id)
+{
+ struct ll_entry *c_entry;
+ struct tf_session_client *client;
+
+ /* Skip using the check macro as we just want to return */
+ if (tfs == NULL)
+ return NULL;
+
+ for (c_entry = tfs->client_ll.head;
+ c_entry != NULL;
+ c_entry = c_entry->next) {
+ client = (struct tf_session_client *)c_entry;
+ if (client->session_client_id.id == session_client_id.id)
+ return client;
+ }
+
+ return NULL;
+}
+
+struct tf_session_client *
+tf_session_find_session_client_by_name(struct tf_session *tfs,
+ const char *ctrl_chan_name)
+{
+ struct ll_entry *c_entry;
+ struct tf_session_client *client;
+
+ /* Skip using the check macro as we just want to return */
+ if (tfs == NULL || ctrl_chan_name == NULL)
+ return NULL;
+
+ for (c_entry = tfs->client_ll.head;
+ c_entry != NULL;
+ c_entry = c_entry->next) {
+ client = (struct tf_session_client *)c_entry;
+ if (strncmp(client->ctrl_chan_name,
+ ctrl_chan_name,
+ TF_SESSION_NAME_MAX) == 0)
+ return client;
+ }
+
+ return NULL;
+}
+
+struct tf_session_client *
+tf_session_find_session_client_by_fid(struct tf_session *tfs,
+ uint16_t fid)
+{
+ struct ll_entry *c_entry;
+ struct tf_session_client *client;
+
+ /* Skip using the check macro as we just want to return */
+ if (tfs == NULL)
+ return NULL;
+
+ for (c_entry = tfs->client_ll.head;
+ c_entry != NULL;
+ c_entry = c_entry->next) {
+ client = (struct tf_session_client *)c_entry;
+ if (client->fw_fid == fid)
+ return client;
+ }
+
+ return NULL;
+}
+
+int
+tf_session_get_device(struct tf_session *tfs,
+ struct tf_dev_info **tfd)
+{
+ *tfd = &tfs->dev;
return 0;
}
int rc;
struct tf_session *tfs = NULL;
+ /* Skip using the check macro as we want to control the error msg */
if (tfp->session == NULL) {
rc = -EINVAL;
TFP_DRV_LOG(ERR,
return rc;
}
- rc = tf_session_get_session(tfp, &tfs);
+ if (fw_session_id == NULL) {
+ rc = -EINVAL;
+ TFP_DRV_LOG(ERR,
+ "Invalid Argument(s), rc:%s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ rc = tf_session_get_session_internal(tfp, &tfs);
if (rc)
return rc;
return 0;
}
+
+int
+tf_session_get_session_id(struct tf *tfp,
+ union tf_session_id *session_id)
+{
+ int rc;
+ struct tf_session *tfs = NULL;
+
+ if (tfp->session == NULL) {
+ rc = -EINVAL;
+ TFP_DRV_LOG(ERR,
+ "Session not created, rc:%s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ if (session_id == NULL) {
+ rc = -EINVAL;
+ TFP_DRV_LOG(ERR,
+ "Invalid Argument(s), rc:%s\n",
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Using internal version as session client may not exist yet */
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ *session_id = tfs->session_id;
+
+ return 0;
+}
+
+int
+tf_session_get_em_ext_db(struct tf *tfp,
+ void **em_ext_db_handle)
+{
+ struct tf_session *tfs = NULL;
+ int rc = 0;
+
+ *em_ext_db_handle = NULL;
+
+ if (tfp == NULL)
+ return (-EINVAL);
+
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ *em_ext_db_handle = tfs->em_ext_db_handle;
+ return rc;
+}
+
+int
+tf_session_set_em_ext_db(struct tf *tfp,
+ void *em_ext_db_handle)
+{
+ struct tf_session *tfs = NULL;
+ int rc = 0;
+
+ if (tfp == NULL)
+ return (-EINVAL);
+
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ tfs->em_ext_db_handle = em_ext_db_handle;
+ return rc;
+}
+
+int
+tf_session_get_db(struct tf *tfp,
+ enum tf_module_type type,
+ void **db_handle)
+{
+ struct tf_session *tfs = NULL;
+ int rc = 0;
+
+ *db_handle = NULL;
+
+ if (tfp == NULL)
+ return (-EINVAL);
+
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ switch (type) {
+ case TF_MODULE_TYPE_IDENTIFIER:
+ if (tfs->id_db_handle)
+ *db_handle = tfs->id_db_handle;
+ else
+ rc = -ENOMEM;
+ break;
+ case TF_MODULE_TYPE_TABLE:
+ if (tfs->tbl_db_handle)
+ *db_handle = tfs->tbl_db_handle;
+ else
+ rc = -ENOMEM;
+
+ break;
+ case TF_MODULE_TYPE_TCAM:
+ if (tfs->tcam_db_handle)
+ *db_handle = tfs->tcam_db_handle;
+ else
+ rc = -ENOMEM;
+ break;
+ case TF_MODULE_TYPE_EM:
+ if (tfs->em_db_handle)
+ *db_handle = tfs->em_db_handle;
+ else
+ rc = -ENOMEM;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+int
+tf_session_set_db(struct tf *tfp,
+ enum tf_module_type type,
+ void *db_handle)
+{
+ struct tf_session *tfs = NULL;
+ int rc = 0;
+
+ if (tfp == NULL)
+ return (-EINVAL);
+
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ switch (type) {
+ case TF_MODULE_TYPE_IDENTIFIER:
+ tfs->id_db_handle = db_handle;
+ break;
+ case TF_MODULE_TYPE_TABLE:
+ tfs->tbl_db_handle = db_handle;
+ break;
+ case TF_MODULE_TYPE_TCAM:
+ tfs->tcam_db_handle = db_handle;
+ break;
+ case TF_MODULE_TYPE_EM:
+ tfs->em_db_handle = db_handle;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+#ifdef TF_TCAM_SHARED
+
+int
+tf_session_get_tcam_shared_db(struct tf *tfp,
+ void **tcam_shared_db_handle)
+{
+ struct tf_session *tfs = NULL;
+ int rc = 0;
+
+ *tcam_shared_db_handle = NULL;
+
+ if (tfp == NULL)
+ return (-EINVAL);
+
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ *tcam_shared_db_handle = tfs->tcam_shared_db_handle;
+ return rc;
+}
+
+int
+tf_session_set_tcam_shared_db(struct tf *tfp,
+ void *tcam_shared_db_handle)
+{
+ struct tf_session *tfs = NULL;
+ int rc = 0;
+
+ if (tfp == NULL)
+ return (-EINVAL);
+
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ tfs->tcam_shared_db_handle = tcam_shared_db_handle;
+ return rc;
+}
+#endif /* TF_TCAM_SHARED */