struct tf;
/* Forward declarations */
-static int dev_unbind_p4(struct tf *tfp);
+static int tf_dev_unbind_p4(struct tf *tfp);
/**
* Device specific bind function, WH+
* - (-EINVAL) on parameter or internal failure.
*/
static int
-dev_bind_p4(struct tf *tfp,
- bool shadow_copy,
- struct tf_session_resources *resources,
- struct tf_dev_info *dev_handle)
+tf_dev_bind_p4(struct tf *tfp,
+ bool shadow_copy,
+ struct tf_session_resources *resources,
+ struct tf_dev_info *dev_handle)
{
int rc;
int frc;
fail:
/* Cleanup of already created modules */
- frc = dev_unbind_p4(tfp);
+ frc = tf_dev_unbind_p4(tfp);
if (frc)
return frc;
* - (-EINVAL) on failure.
*/
static int
-dev_unbind_p4(struct tf *tfp)
+tf_dev_unbind_p4(struct tf *tfp)
{
int rc = 0;
bool fail = false;
/* Unbind all the support modules. As this is only done on
* close we only report errors as everything has to be cleaned
* up regardless.
+ *
+ * In case of residuals TCAMs are cleaned up first as to
+ * invalidate the pipeline in a clean manner.
*/
- rc = tf_ident_unbind(tfp);
+ rc = tf_tcam_unbind(tfp);
if (rc) {
TFP_DRV_LOG(ERR,
- "Device unbind failed, Identifier\n");
+ "Device unbind failed, TCAM\n");
fail = true;
}
- rc = tf_tbl_unbind(tfp);
+ rc = tf_ident_unbind(tfp);
if (rc) {
TFP_DRV_LOG(ERR,
- "Device unbind failed, Table Type\n");
+ "Device unbind failed, Identifier\n");
fail = true;
}
- rc = tf_tcam_unbind(tfp);
+ rc = tf_tbl_unbind(tfp);
if (rc) {
TFP_DRV_LOG(ERR,
- "Device unbind failed, TCAM\n");
+ "Device unbind failed, Table Type\n");
fail = true;
}
}
int
-dev_bind(struct tf *tfp __rte_unused,
- enum tf_device_type type,
- bool shadow_copy,
- struct tf_session_resources *resources,
- struct tf_dev_info *dev_handle)
+tf_dev_bind(struct tf *tfp __rte_unused,
+ enum tf_device_type type,
+ bool shadow_copy,
+ struct tf_session_resources *resources,
+ struct tf_dev_info *dev_handle)
{
switch (type) {
case TF_DEVICE_TYPE_WH:
- return dev_bind_p4(tfp,
- shadow_copy,
- resources,
- dev_handle);
+ return tf_dev_bind_p4(tfp,
+ shadow_copy,
+ resources,
+ dev_handle);
default:
TFP_DRV_LOG(ERR,
"No such device\n");
}
int
-dev_unbind(struct tf *tfp,
- struct tf_dev_info *dev_handle)
+tf_dev_unbind(struct tf *tfp,
+ struct tf_dev_info *dev_handle)
{
switch (dev_handle->type) {
case TF_DEVICE_TYPE_WH:
- return dev_unbind_p4(tfp);
+ return tf_dev_unbind_p4(tfp);
default:
TFP_DRV_LOG(ERR,
"No such device\n");
struct tf;
struct tf_session;
+/**
+ *
+ */
+enum tf_device_module_type {
+ TF_DEVICE_MODULE_TYPE_IDENTIFIER,
+ TF_DEVICE_MODULE_TYPE_TABLE,
+ TF_DEVICE_MODULE_TYPE_TCAM,
+ TF_DEVICE_MODULE_TYPE_EM,
+ TF_DEVICE_MODULE_TYPE_MAX
+};
+
/**
* The Device module provides a general device template. A supported
* device type should implement one or more of the listed function
* - (-EINVAL) parameter failure.
* - (-ENODEV) no such device supported.
*/
-int dev_bind(struct tf *tfp,
- enum tf_device_type type,
- bool shadow_copy,
- struct tf_session_resources *resources,
- struct tf_dev_info *dev_handle);
+int tf_dev_bind(struct tf *tfp,
+ enum tf_device_type type,
+ bool shadow_copy,
+ struct tf_session_resources *resources,
+ struct tf_dev_info *dev_handle);
/**
* Device release handles cleanup of the device specific information.
* - (-EINVAL) parameter failure.
* - (-ENODEV) no such device supported.
*/
-int dev_unbind(struct tf *tfp,
- struct tf_dev_info *dev_handle);
+int tf_dev_unbind(struct tf *tfp,
+ struct tf_dev_info *dev_handle);
/**
* Truflow device specific function hooks structure
/* CFA_RESOURCE_TYPE_P4_EXT */
{ TF_RM_ELEM_CFG_NULL, CFA_RESOURCE_TYPE_INVALID }
};
-
#endif /* _TF_DEVICE_P4_H_ */
return -EINVAL;
}
+ db_cfg.type = TF_DEVICE_MODULE_TYPE_IDENTIFIER;
db_cfg.num_elements = parms->num_elements;
+ db_cfg.cfg = parms->cfg;
for (i = 0; i < TF_DIR_MAX; i++) {
db_cfg.dir = i;
- db_cfg.num_elements = parms->num_elements;
- db_cfg.cfg = parms->cfg;
db_cfg.alloc_cnt = parms->resources->ident_cnt[i].cnt;
db_cfg.rm_db = &ident_db[i];
rc = tf_rm_create_db(tfp, &db_cfg);
fparms.dir = i;
fparms.rm_db = ident_db[i];
rc = tf_rm_free_db(tfp, &fparms);
- if (rc)
- return rc;
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "rm free failed on unbind\n");
+ }
ident_db[i] = NULL;
}
return rc;
}
+int
+tf_msg_session_resc_flush(struct tf *tfp,
+ enum tf_dir dir,
+ uint16_t size,
+ struct tf_rm_resc_entry *resv)
+{
+ int rc;
+ int i;
+ struct tfp_send_msg_parms parms = { 0 };
+ struct hwrm_tf_session_resc_flush_input req = { 0 };
+ struct hwrm_tf_session_resc_flush_output resp = { 0 };
+ uint8_t fw_session_id;
+ struct tf_msg_dma_buf resv_buf = { 0 };
+ struct tf_rm_resc_entry *resv_data;
+ int dma_size;
+
+ TF_CHECK_PARMS2(tfp, resv);
+
+ rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: Unable to lookup FW id, rc:%s\n",
+ tf_dir_2_str(dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Prepare DMA buffers */
+ dma_size = size * sizeof(struct tf_rm_resc_entry);
+ rc = tf_msg_alloc_dma_buf(&resv_buf, dma_size);
+ if (rc)
+ return rc;
+
+ /* Populate the request */
+ req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
+ req.flags = tfp_cpu_to_le_16(dir);
+ req.flush_size = size;
+
+ resv_data = (struct tf_rm_resc_entry *)resv_buf.va_addr;
+ for (i = 0; i < size; i++) {
+ resv_data[i].type = tfp_cpu_to_le_32(resv[i].type);
+ resv_data[i].start = tfp_cpu_to_le_16(resv[i].start);
+ resv_data[i].stride = tfp_cpu_to_le_16(resv[i].stride);
+ }
+
+ req.flush_addr = tfp_cpu_to_le_64(resv_buf.pa_addr);
+
+ parms.tf_type = HWRM_TF_SESSION_RESC_FLUSH;
+ parms.req_data = (uint32_t *)&req;
+ parms.req_size = sizeof(req);
+ parms.resp_data = (uint32_t *)&resp;
+ parms.resp_size = sizeof(resp);
+ parms.mailbox = TF_KONG_MB;
+
+ rc = tfp_send_msg_direct(tfp, &parms);
+ if (rc)
+ return rc;
+
+ tf_msg_free_dma_buf(&resv_buf);
+
+ return rc;
+}
+
/**
* Sends EM mem register request to Firmware
*/
uint8_t *data = NULL;
int data_size = 0;
- rc = tf_tcam_tbl_2_hwrm(parms->type, &req.type);
- if (rc != 0)
- return rc;
+ req.type = parms->type;
req.idx = tfp_cpu_to_le_16(parms->idx);
if (parms->dir == TF_DIR_TX)
struct tf_rm_resc_req_entry *request,
struct tf_rm_resc_entry *resv);
+/**
+ * Sends session resource flush request to TF Firmware
+ */
+int tf_msg_session_resc_flush(struct tf *tfp,
+ enum tf_dir dir,
+ uint16_t size,
+ struct tf_rm_resc_entry *resv);
/**
* Sends EM internal insert request to Firmware
*/
*/
enum tf_dir dir;
+ /**
+ * Module type, used for logging purposes.
+ */
+ enum tf_device_module_type type;
+
/**
* The DB consists of an array of elements
*/
return rc;
}
+/**
+ * Logs an array of found residual entries to the console.
+ *
+ * [in] dir
+ * Receive or transmit direction
+ *
+ * [in] type
+ * Type of Device Module
+ *
+ * [in] count
+ * Number of entries in the residual array
+ *
+ * [in] residuals
+ * Pointer to an array of residual entries. Array is index same as
+ * the DB in which this function is used. Each entry holds residual
+ * value for that entry.
+ */
+static void
+tf_rm_log_residuals(enum tf_dir dir,
+ enum tf_device_module_type type,
+ uint16_t count,
+ uint16_t *residuals)
+{
+ int i;
+
+ /* Walk the residual array and log the types that wasn't
+ * cleaned up to the console.
+ */
+ for (i = 0; i < count; i++) {
+ if (residuals[i] != 0)
+ TFP_DRV_LOG(ERR,
+ "%s, %s was not cleaned up, %d outstanding\n",
+ tf_dir_2_str(dir),
+ tf_device_module_type_subtype_2_str(type, i),
+ residuals[i]);
+ }
+}
+
+/**
+ * Performs a check of the passed in DB for any lingering elements. If
+ * a resource type was found to not have been cleaned up by the caller
+ * then its residual values are recorded, logged and passed back in an
+ * allocate reservation array that the caller can pass to the FW for
+ * cleanup.
+ *
+ * [in] db
+ * Pointer to the db, used for the lookup
+ *
+ * [out] resv_size
+ * Pointer to the reservation size of the generated reservation
+ * array.
+ *
+ * [in/out] resv
+ * Pointer Pointer to a reservation array. The reservation array is
+ * allocated after the residual scan and holds any found residual
+ * entries. Thus it can be smaller than the DB that the check was
+ * performed on. Array must be freed by the caller.
+ *
+ * [out] residuals_present
+ * Pointer to a bool flag indicating if residual was present in the
+ * DB
+ *
+ * Returns:
+ * 0 - Success
+ * - EOPNOTSUPP - Operation not supported
+ */
+static int
+tf_rm_check_residuals(struct tf_rm_new_db *rm_db,
+ uint16_t *resv_size,
+ struct tf_rm_resc_entry **resv,
+ bool *residuals_present)
+{
+ int rc;
+ int i;
+ int f;
+ uint16_t count;
+ uint16_t found;
+ uint16_t *residuals = NULL;
+ uint16_t hcapi_type;
+ struct tf_rm_get_inuse_count_parms iparms;
+ struct tf_rm_get_alloc_info_parms aparms;
+ struct tf_rm_get_hcapi_parms hparms;
+ struct tf_rm_alloc_info info;
+ struct tfp_calloc_parms cparms;
+ struct tf_rm_resc_entry *local_resv = NULL;
+
+ /* Create array to hold the entries that have residuals */
+ cparms.nitems = rm_db->num_entries;
+ cparms.size = sizeof(uint16_t);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc)
+ return rc;
+
+ residuals = (uint16_t *)cparms.mem_va;
+
+ /* Traverse the DB and collect any residual elements */
+ iparms.rm_db = rm_db;
+ iparms.count = &count;
+ for (i = 0, found = 0; i < rm_db->num_entries; i++) {
+ iparms.db_index = i;
+ rc = tf_rm_get_inuse_count(&iparms);
+ /* Not a device supported entry, just skip */
+ if (rc == -ENOTSUP)
+ continue;
+ if (rc)
+ goto cleanup_residuals;
+
+ if (count) {
+ found++;
+ residuals[i] = count;
+ *residuals_present = true;
+ }
+ }
+
+ if (*residuals_present) {
+ /* Populate a reduced resv array with only the entries
+ * that have residuals.
+ */
+ cparms.nitems = found;
+ cparms.size = sizeof(struct tf_rm_resc_entry);
+ cparms.alignment = 0;
+ rc = tfp_calloc(&cparms);
+ if (rc)
+ return rc;
+
+ local_resv = (struct tf_rm_resc_entry *)cparms.mem_va;
+
+ aparms.rm_db = rm_db;
+ hparms.rm_db = rm_db;
+ hparms.hcapi_type = &hcapi_type;
+ for (i = 0, f = 0; i < rm_db->num_entries; i++) {
+ if (residuals[i] == 0)
+ continue;
+ aparms.db_index = i;
+ aparms.info = &info;
+ rc = tf_rm_get_info(&aparms);
+ if (rc)
+ goto cleanup_all;
+
+ hparms.db_index = i;
+ rc = tf_rm_get_hcapi_type(&hparms);
+ if (rc)
+ goto cleanup_all;
+
+ local_resv[f].type = hcapi_type;
+ local_resv[f].start = info.entry.start;
+ local_resv[f].stride = info.entry.stride;
+ f++;
+ }
+ *resv_size = found;
+ }
+
+ tf_rm_log_residuals(rm_db->dir,
+ rm_db->type,
+ rm_db->num_entries,
+ residuals);
+
+ tfp_free((void *)residuals);
+ *resv = local_resv;
+
+ return 0;
+
+ cleanup_all:
+ tfp_free((void *)local_resv);
+ *resv = NULL;
+ cleanup_residuals:
+ tfp_free((void *)residuals);
+
+ return rc;
+}
+
int
tf_rm_create_db(struct tf *tfp,
struct tf_rm_create_db_parms *parms)
rm_db->num_entries = i;
rm_db->dir = parms->dir;
+ rm_db->type = parms->type;
*parms->rm_db = (void *)rm_db;
tfp_free((void *)req);
}
int
-tf_rm_free_db(struct tf *tfp __rte_unused,
+tf_rm_free_db(struct tf *tfp,
struct tf_rm_free_db_parms *parms)
{
- int rc = 0;
+ int rc;
int i;
+ uint16_t resv_size = 0;
struct tf_rm_new_db *rm_db;
+ struct tf_rm_resc_entry *resv;
+ bool residuals_found = false;
- TF_CHECK_PARMS1(parms);
+ TF_CHECK_PARMS2(parms, parms->rm_db);
- /* Traverse the DB and clear each pool.
- * NOTE:
- * Firmware is not cleared. It will be cleared on close only.
+ /* Device unbind happens when the TF Session is closed and the
+ * session ref count is 0. Device unbind will cleanup each of
+ * its support modules, i.e. Identifier, thus we're ending up
+ * here to close the DB.
+ *
+ * On TF Session close it is assumed that the session has already
+ * cleaned up all its resources, individually, while
+ * destroying its flows.
+ *
+ * To assist in the 'cleanup checking' the DB is checked for any
+ * remaining elements and logged if found to be the case.
+ *
+ * Any such elements will need to be 'cleared' ahead of
+ * returning the resources to the HCAPI RM.
+ *
+ * RM will signal FW to flush the DB resources. FW will
+ * perform the invalidation. TF Session close will return the
+ * previous allocated elements to the RM and then close the
+ * HCAPI RM registration. That then saves several 'free' msgs
+ * from being required.
*/
+
rm_db = (struct tf_rm_new_db *)parms->rm_db;
+
+ /* Check for residuals that the client didn't clean up */
+ rc = tf_rm_check_residuals(rm_db,
+ &resv_size,
+ &resv,
+ &residuals_found);
+ if (rc)
+ return rc;
+
+ /* Invalidate any residuals followed by a DB traversal for
+ * pool cleanup.
+ */
+ if (residuals_found) {
+ rc = tf_msg_session_resc_flush(tfp,
+ parms->dir,
+ resv_size,
+ resv);
+ tfp_free((void *)resv);
+ /* On failure we still have to cleanup so we can only
+ * log that FW failed.
+ */
+ if (rc)
+ TFP_DRV_LOG(ERR,
+ "%s: Internal Flush error, module:%s\n",
+ tf_dir_2_str(parms->dir),
+ tf_device_module_type_2_str(rm_db->type));
+ }
+
for (i = 0; i < rm_db->num_entries; i++)
tfp_free((void *)rm_db->db[i].pool);
int
tf_rm_allocate(struct tf_rm_allocate_parms *parms)
{
- int rc = 0;
+ int rc;
int id;
uint32_t index;
struct tf_rm_new_db *rm_db;
id = ba_alloc(rm_db->db[parms->db_index].pool);
if (id == BA_FAIL) {
+ rc = -ENOMEM;
TFP_DRV_LOG(ERR,
"%s: Allocation failed, rc:%s\n",
tf_dir_2_str(rm_db->dir),
strerror(-rc));
- return -ENOMEM;
+ return rc;
}
/* Adjust for any non zero start value */
int
tf_rm_free(struct tf_rm_free_parms *parms)
{
- int rc = 0;
+ int rc;
uint32_t adj_index;
struct tf_rm_new_db *rm_db;
enum tf_rm_elem_cfg_type cfg_type;
int
tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms)
{
- int rc = 0;
+ int rc;
uint32_t adj_index;
struct tf_rm_new_db *rm_db;
enum tf_rm_elem_cfg_type cfg_type;
int
tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms)
{
- int rc = 0;
struct tf_rm_new_db *rm_db;
enum tf_rm_elem_cfg_type cfg_type;
cfg_type != TF_RM_ELEM_CFG_PRIVATE)
return -ENOTSUP;
- parms->info = &rm_db->db[parms->db_index].alloc;
+ memcpy(parms->info,
+ &rm_db->db[parms->db_index].alloc,
+ sizeof(struct tf_rm_alloc_info));
- return rc;
+ return 0;
}
int
tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms)
{
- int rc = 0;
struct tf_rm_new_db *rm_db;
enum tf_rm_elem_cfg_type cfg_type;
*parms->hcapi_type = rm_db->db[parms->db_index].hcapi_type;
+ return 0;
+}
+
+int
+tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms)
+{
+ int rc = 0;
+ struct tf_rm_new_db *rm_db;
+ enum tf_rm_elem_cfg_type cfg_type;
+
+ TF_CHECK_PARMS2(parms, parms->rm_db);
+
+ rm_db = (struct tf_rm_new_db *)parms->rm_db;
+ cfg_type = rm_db->db[parms->db_index].cfg_type;
+
+ /* Bail out if not controlled by RM */
+ if (cfg_type != TF_RM_ELEM_CFG_HCAPI &&
+ cfg_type != TF_RM_ELEM_CFG_PRIVATE)
+ return -ENOTSUP;
+
+ /* Bail silently (no logging), if the pool is not valid there
+ * was no elements allocated for it.
+ */
+ if (rm_db->db[parms->db_index].pool == NULL) {
+ *parms->count = 0;
+ return 0;
+ }
+
+ *parms->count = ba_inuse_count(rm_db->db[parms->db_index].pool);
+
return rc;
+
}
#include "tf_core.h"
#include "bitalloc.h"
+#include "tf_device.h"
struct tf;
enum tf_rm_elem_cfg_type {
/** No configuration */
TF_RM_ELEM_CFG_NULL,
- /** HCAPI 'controlled' */
+ /** HCAPI 'controlled', uses a Pool for internal storage */
TF_RM_ELEM_CFG_HCAPI,
- /** Private thus not HCAPI 'controlled' */
+ /** Private thus not HCAPI 'controlled', creates a Pool for storage */
TF_RM_ELEM_CFG_PRIVATE,
/**
* Shared element thus it belongs to a shared FW Session and
*/
struct tf_rm_create_db_parms {
/**
- * [in] Receive or transmit direction
+ * [in] Device module type. Used for logging purposes.
+ */
+ enum tf_device_module_type type;
+ /**
+ * [in] Receive or transmit direction.
*/
enum tf_dir dir;
/**
uint16_t *hcapi_type;
};
+/**
+ * Get InUse count parameters for single element
+ */
+struct tf_rm_get_inuse_count_parms {
+ /**
+ * [in] RM DB Handle
+ */
+ void *rm_db;
+ /**
+ * [in] DB Index, indicates which DB entry to perform the
+ * action on.
+ */
+ uint16_t db_index;
+ /**
+ * [out] Pointer to the inuse count for the specified db_index
+ */
+ uint16_t *count;
+};
+
/**
* @page rm Resource Manager
*
* @ref tf_rm_get_info
*
* @ref tf_rm_get_hcapi_type
+ *
+ * @ref tf_rm_get_inuse_count
*/
/**
*/
int tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms);
+/**
+ * Performs a lookup in the Resource Manager DB and retrieves the
+ * requested HCAPI RM type inuse count.
+ *
+ * [in] parms
+ * Pointer to get inuse parameters
+ *
+ * Returns
+ * - (0) if successful.
+ * - (-EINVAL) on failure.
+ */
+int tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms);
+
#endif /* TF_RM_NEW_H_ */
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);
+ 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)
return rc;
return rc;
}
+ tfs->ref_count--;
+
/* Record the session we're closing so the caller knows the
* details.
*/
return rc;
}
+ if (tfs->ref_count > 0) {
+ /* In case we're attached only the session client gets
+ * closed.
+ */
+ rc = tf_msg_session_close(tfp);
+ if (rc) {
+ /* Log error */
+ TFP_DRV_LOG(ERR,
+ "FW Session close failed, rc:%s\n",
+ strerror(-rc));
+ }
+
+ return 0;
+ }
+
+ /* Final cleanup as we're last user of the session */
+
+ /* 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));
+ }
+
/* In case we're attached only the session client gets closed */
rc = tf_msg_session_close(tfp);
if (rc) {
strerror(-rc));
}
- 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_free(tfp->session->core_data);
- tfp_free(tfp->session);
- tfp->session = NULL;
- }
+ tfp_free(tfp->session->core_data);
+ tfp_free(tfp->session);
+ tfp->session = NULL;
return 0;
}
}
db_cfg.num_elements = parms->num_elements;
+ db_cfg.type = TF_DEVICE_MODULE_TYPE_TABLE;
+ db_cfg.num_elements = parms->num_elements;
+ db_cfg.cfg = parms->cfg;
for (i = 0; i < TF_DIR_MAX; i++) {
db_cfg.dir = i;
- db_cfg.num_elements = parms->num_elements;
- db_cfg.cfg = parms->cfg;
db_cfg.alloc_cnt = parms->resources->tbl_cnt[i].cnt;
db_cfg.rm_db = &tbl_db[i];
rc = tf_rm_create_db(tfp, &db_cfg);
}
db_cfg.num_elements = parms->num_elements;
+ db_cfg.type = TF_DEVICE_MODULE_TYPE_TCAM;
+ db_cfg.num_elements = parms->num_elements;
+ db_cfg.cfg = parms->cfg;
for (i = 0; i < TF_DIR_MAX; i++) {
db_cfg.dir = i;
- db_cfg.num_elements = parms->num_elements;
- db_cfg.cfg = parms->cfg;
db_cfg.alloc_cnt = parms->resources->tcam_cnt[i].cnt;
db_cfg.rm_db = &tcam_db[i];
rc = tf_rm_create_db(tfp, &db_cfg);
* [in] Type of object to set
*/
enum tf_tcam_tbl_type type;
+ /**
+ * [in] Type of HCAPI
+ */
+ uint16_t hcapi_type;
/**
* [in] Entry index to write to
*/
#include "tf_util.h"
-const char
-*tf_dir_2_str(enum tf_dir dir)
+const char *
+tf_dir_2_str(enum tf_dir dir)
{
switch (dir) {
case TF_DIR_RX:
}
}
-const char
-*tf_ident_2_str(enum tf_identifier_type id_type)
+const char *
+tf_ident_2_str(enum tf_identifier_type id_type)
{
switch (id_type) {
case TF_IDENT_TYPE_L2_CTXT:
}
}
-const char
-*tf_tcam_tbl_2_str(enum tf_tcam_tbl_type tcam_type)
+const char *
+tf_tcam_tbl_2_str(enum tf_tcam_tbl_type tcam_type)
{
switch (tcam_type) {
case TF_TCAM_TBL_TYPE_L2_CTXT_TCAM:
}
}
-const char
-*tf_tbl_type_2_str(enum tf_tbl_type tbl_type)
+const char *
+tf_tbl_type_2_str(enum tf_tbl_type tbl_type)
{
switch (tbl_type) {
case TF_TBL_TYPE_FULL_ACT_RECORD:
}
}
-const char
-*tf_em_tbl_type_2_str(enum tf_em_tbl_type em_type)
+const char *
+tf_em_tbl_type_2_str(enum tf_em_tbl_type em_type)
{
switch (em_type) {
case TF_EM_TBL_TYPE_EM_RECORD:
return "Invalid EM type";
}
}
+
+const char *
+tf_device_module_type_subtype_2_str(enum tf_device_module_type dm_type,
+ uint16_t mod_type)
+{
+ switch (dm_type) {
+ case TF_DEVICE_MODULE_TYPE_IDENTIFIER:
+ return tf_ident_2_str(mod_type);
+ case TF_DEVICE_MODULE_TYPE_TABLE:
+ return tf_tcam_tbl_2_str(mod_type);
+ case TF_DEVICE_MODULE_TYPE_TCAM:
+ return tf_tbl_type_2_str(mod_type);
+ case TF_DEVICE_MODULE_TYPE_EM:
+ return tf_em_tbl_type_2_str(mod_type);
+ default:
+ return "Invalid Device Module type";
+ }
+}
+
+const char *
+tf_device_module_type_2_str(enum tf_device_module_type dm_type)
+{
+ switch (dm_type) {
+ case TF_DEVICE_MODULE_TYPE_IDENTIFIER:
+ return "Identifier";
+ case TF_DEVICE_MODULE_TYPE_TABLE:
+ return "Table";
+ case TF_DEVICE_MODULE_TYPE_TCAM:
+ return "TCAM";
+ case TF_DEVICE_MODULE_TYPE_EM:
+ return "EM";
+ default:
+ return "Invalid Device Module type";
+ }
+}
#define _TF_UTIL_H_
#include "tf_core.h"
+#include "tf_device.h"
/**
* Helper function converting direction to text string
*/
const char *tf_em_tbl_type_2_str(enum tf_em_tbl_type em_type);
+/**
+ * Helper function converting device module type and module type to
+ * text string.
+ *
+ * [in] dm_type
+ * Device Module type
+ *
+ * [in] mod_type
+ * Module specific type
+ *
+ * Returns:
+ * Pointer to a char string holding the string for the EM type
+ */
+const char *tf_device_module_type_subtype_2_str
+ (enum tf_device_module_type dm_type,
+ uint16_t mod_type);
+
+/**
+ * Helper function converting device module type to text string
+ *
+ * [in] dm_type
+ * Device Module type
+ *
+ * [in] mod_type
+ * Module specific type
+ *
+ * Returns:
+ * Pointer to a char string holding the string for the EM type
+ */
+const char *tf_device_module_type_2_str(enum tf_device_module_type dm_type);
+
#endif /* _TF_UTIL_H_ */