#define TF_BITS2BYTES(x) (((x) + 7) >> 3)
#define TF_BITS2BYTES_WORD_ALIGN(x) ((((x) + 31) >> 5) * 4)
+#define TF_BITS2BYTES_64B_WORD_ALIGN(x) ((((x) + 63) >> 6) * 8)
struct tf_set_global_cfg_input;
struct tf_get_global_cfg_input;
return rc;
}
- if (dev->ops->tf_dev_set_tcam == NULL) {
+ if (dev->ops->tf_dev_set_tcam == NULL ||
+ dev->ops->tf_dev_word_align == NULL) {
rc = -EOPNOTSUPP;
TFP_DRV_LOG(ERR,
"%s: Operation not supported, rc:%s\n",
sparms.idx = parms->idx;
sparms.key = parms->key;
sparms.mask = parms->mask;
- sparms.key_size = TF_BITS2BYTES_WORD_ALIGN(parms->key_sz_in_bits);
+ sparms.key_size = dev->ops->tf_dev_word_align(parms->key_sz_in_bits);
sparms.result = parms->result;
sparms.result_size = TF_BITS2BYTES_WORD_ALIGN(parms->result_sz_in_bits);
int
tf_get_tcam_entry(struct tf *tfp __rte_unused,
- struct tf_get_tcam_entry_parms *parms __rte_unused)
+ struct tf_get_tcam_entry_parms *parms)
{
+ int rc;
+ struct tf_session *tfs;
+ struct tf_dev_info *dev;
+ struct tf_tcam_get_parms gparms;
+
TF_CHECK_PARMS2(tfp, parms);
- return -EOPNOTSUPP;
+
+ memset(&gparms, 0, sizeof(struct tf_tcam_get_parms));
+
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session(tfp, &tfs);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: Failed to lookup session, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Retrieve the device information */
+ rc = tf_session_get_device(tfs, &dev);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: Failed to lookup device, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ if (dev->ops->tf_dev_get_tcam == NULL) {
+ rc = -EOPNOTSUPP;
+ TFP_DRV_LOG(ERR,
+ "%s: Operation not supported, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ gparms.dir = parms->dir;
+ gparms.type = parms->tcam_tbl_type;
+ gparms.idx = parms->idx;
+ gparms.key = parms->key;
+ gparms.mask = parms->mask;
+ gparms.result = parms->result;
+
+ rc = dev->ops->tf_dev_get_tcam(tfp, &gparms);
+ if (rc) {
+ TFP_DRV_LOG(ERR,
+ "%s: TCAM get failed, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+ parms->key_sz_in_bits = gparms.key_size * 8;
+ parms->result_sz_in_bits = gparms.result_size * 8;
+
+ return 0;
}
int
* mailbox
*/
int (*tf_dev_get_mailbox)(void);
+
+ /**
+ * Convert length in bit to length in byte and align to word.
+ * The word length depends on device type.
+ *
+ * [in] size
+ * Size in bit
+ *
+ * Returns
+ * Size in byte
+ */
+ int (*tf_dev_word_align)(uint16_t size);
};
/**
return TF_KONG_MB;
}
+static int tf_dev_p4_word_align(uint16_t size)
+{
+ return ((((size) + 31) >> 5) * 4);
+}
/**
* Truflow P4 device specific functions
.tf_dev_set_global_cfg = NULL,
.tf_dev_get_global_cfg = NULL,
.tf_dev_get_mailbox = tf_dev_p4_get_mailbox,
+ .tf_dev_word_align = NULL,
};
/**
.tf_dev_set_global_cfg = tf_global_cfg_set,
.tf_dev_get_global_cfg = tf_global_cfg_get,
.tf_dev_get_mailbox = tf_dev_p4_get_mailbox,
+ .tf_dev_word_align = tf_dev_p4_word_align,
};
return TF_CHIMP_MB;
}
+static int tf_dev_p58_word_align(uint16_t size)
+{
+ return ((((size) + 63) >> 6) * 8);
+}
+
/**
* Truflow P58 device specific functions
*/
.tf_dev_set_global_cfg = NULL,
.tf_dev_get_global_cfg = NULL,
.tf_dev_get_mailbox = tf_dev_p58_get_mailbox,
+ .tf_dev_word_align = NULL,
};
/**
.tf_dev_free_tcam = tf_tcam_free,
.tf_dev_alloc_search_tcam = tf_tcam_alloc_search,
.tf_dev_set_tcam = tf_tcam_set,
- .tf_dev_get_tcam = NULL,
+ .tf_dev_get_tcam = tf_tcam_get,
.tf_dev_insert_int_em_entry = tf_em_hash_insert_int_entry,
.tf_dev_delete_int_em_entry = tf_em_hash_delete_int_entry,
.tf_dev_insert_ext_em_entry = NULL,
.tf_dev_set_global_cfg = tf_global_cfg_set,
.tf_dev_get_global_cfg = tf_global_cfg_get,
.tf_dev_get_mailbox = tf_dev_p58_get_mailbox,
+ .tf_dev_word_align = tf_dev_p58_word_align,
};
return rc;
}
+int
+tf_msg_tcam_entry_get(struct tf *tfp,
+ struct tf_dev_info *dev,
+ struct tf_tcam_get_parms *parms)
+{
+ int rc;
+ struct tfp_send_msg_parms mparms = { 0 };
+ struct hwrm_tf_tcam_get_input req = { 0 };
+ struct hwrm_tf_tcam_get_output resp = { 0 };
+ uint8_t fw_session_id;
+
+ 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(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Populate the request */
+ req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
+ req.type = parms->hcapi_type;
+ req.idx = tfp_cpu_to_le_16(parms->idx);
+ if (parms->dir == TF_DIR_TX)
+ req.flags |= HWRM_TF_TCAM_GET_INPUT_FLAGS_DIR_TX;
+
+ mparms.tf_type = HWRM_TF_TCAM_GET;
+ mparms.req_data = (uint32_t *)&req;
+ mparms.req_size = sizeof(req);
+ mparms.resp_data = (uint32_t *)&resp;
+ mparms.resp_size = sizeof(resp);
+ mparms.mailbox = dev->ops->tf_dev_get_mailbox();
+
+ rc = tfp_send_msg_direct(tfp,
+ &mparms);
+
+ if (rc != 0)
+ return rc;
+
+ if (mparms.tf_resp_code != 0)
+ return tfp_le_to_cpu_32(mparms.tf_resp_code);
+
+ parms->key_size = resp.key_size;
+ parms->result_size = resp.result_size;
+ tfp_memcpy(parms->key, resp.dev_data, resp.key_size);
+ tfp_memcpy(parms->mask, &resp.dev_data[resp.key_size], resp.key_size);
+ tfp_memcpy(parms->result, &resp.dev_data[resp.result_offset], resp.result_size);
+
+ return tfp_le_to_cpu_32(mparms.tf_resp_code);
+}
+
int
tf_msg_tcam_entry_free(struct tf *tfp,
struct tf_dev_info *dev,
struct tf_dev_info *dev,
struct tf_tcam_set_parms *parms);
+/**
+ * Sends tcam entry 'get' to the Firmware.
+ *
+ * [in] tfp
+ * Pointer to session handle
+ *
+ * [in] parms
+ * Pointer to get parameters
+ *
+ * Returns:
+ * 0 on Success else internal Truflow error
+ */
+int tf_msg_tcam_entry_get(struct tf *tfp,
+ struct tf_dev_info *dev,
+ struct tf_tcam_get_parms *parms);
+
/**
* Sends tcam entry 'free' to the Firmware.
*
int
tf_tcam_get(struct tf *tfp __rte_unused,
- struct tf_tcam_get_parms *parms __rte_unused)
+ struct tf_tcam_get_parms *parms)
{
+ int rc;
+ struct tf_session *tfs;
+ struct tf_dev_info *dev;
+ struct tf_rm_is_allocated_parms aparms;
+ struct tf_rm_get_hcapi_parms hparms;
+ uint16_t num_slice_per_row = 1;
+ int allocated = 0;
+
+ TF_CHECK_PARMS2(tfp, parms);
+
+ if (!init) {
+ TFP_DRV_LOG(ERR,
+ "%s: No TCAM DBs created\n",
+ tf_dir_2_str(parms->dir));
+ return -EINVAL;
+ }
+
+ /* Retrieve the session information */
+ rc = tf_session_get_session_internal(tfp, &tfs);
+ if (rc)
+ return rc;
+
+ /* Retrieve the device information */
+ rc = tf_session_get_device(tfs, &dev);
+ if (rc)
+ return rc;
+
+ if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
+ rc = -EOPNOTSUPP;
+ TFP_DRV_LOG(ERR,
+ "%s: Operation not supported, rc:%s\n",
+ tf_dir_2_str(parms->dir),
+ strerror(-rc));
+ return rc;
+ }
+
+ /* Need to retrieve row size etc */
+ rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
+ parms->type,
+ parms->key_size,
+ &num_slice_per_row);
+ if (rc)
+ return rc;
+
+ /* Check if element is in use */
+ memset(&aparms, 0, sizeof(aparms));
+
+ aparms.rm_db = tcam_db[parms->dir];
+ aparms.db_index = parms->type;
+ aparms.index = parms->idx / num_slice_per_row;
+ aparms.allocated = &allocated;
+ rc = tf_rm_is_allocated(&aparms);
+ if (rc)
+ return rc;
+
+ if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
+ TFP_DRV_LOG(ERR,
+ "%s: Entry is not allocated, type:%d, index:%d\n",
+ tf_dir_2_str(parms->dir),
+ parms->type,
+ parms->idx);
+ return -EINVAL;
+ }
+
+ /* Convert TF type to HCAPI RM type */
+ memset(&hparms, 0, sizeof(hparms));
+
+ hparms.rm_db = tcam_db[parms->dir];
+ hparms.db_index = parms->type;
+ hparms.hcapi_type = &parms->hcapi_type;
+
+ rc = tf_rm_get_hcapi_type(&hparms);
+ if (rc)
+ return rc;
+
+ rc = tf_msg_tcam_entry_get(tfp, dev, parms);
+ if (rc) {
+ /* Log error */
+ TFP_DRV_LOG(ERR,
+ "%s: %s: Entry %d set failed, rc:%s",
+ tf_dir_2_str(parms->dir),
+ tf_tcam_tbl_2_str(parms->type),
+ parms->idx,
+ strerror(-rc));
+ return rc;
+ }
+
return 0;
}
* [in] Type of object to get
*/
enum tf_tcam_tbl_type type;
+ /**
+ * [in] Type of HCAPI
+ */
+ uint16_t hcapi_type;
/**
* [in] Entry index to read
*/