From a9597be79f6624f9e4a171ec2b1048f4a2e96696 Mon Sep 17 00:00:00 2001 From: Jay Ding Date: Sun, 30 May 2021 14:28:38 +0530 Subject: [PATCH] net/bnxt: support L2 context TCAM operations - Implement TCAM get in host - Add Thor support for TCAM set/free Signed-off-by: Jay Ding Signed-off-by: Randy Schacher Signed-off-by: Venkat Duvvuru Reviewed-by: Peter Spreadborough Reviewed-by: Farah Smith Reviewed-by: Ajit Khaparde --- drivers/net/bnxt/tf_core/hwrm_tf.h | 1 + drivers/net/bnxt/tf_core/tf_core.c | 65 +++++++++++++++-- drivers/net/bnxt/tf_core/tf_device.h | 12 ++++ drivers/net/bnxt/tf_core/tf_device_p4.c | 6 ++ drivers/net/bnxt/tf_core/tf_device_p58.c | 9 ++- drivers/net/bnxt/tf_core/tf_msg.c | 52 ++++++++++++++ drivers/net/bnxt/tf_core/tf_msg.h | 16 +++++ drivers/net/bnxt/tf_core/tf_tcam.c | 89 +++++++++++++++++++++++- drivers/net/bnxt/tf_core/tf_tcam.h | 4 ++ 9 files changed, 248 insertions(+), 6 deletions(-) diff --git a/drivers/net/bnxt/tf_core/hwrm_tf.h b/drivers/net/bnxt/tf_core/hwrm_tf.h index a707cd2758..9cc9a1435c 100644 --- a/drivers/net/bnxt/tf_core/hwrm_tf.h +++ b/drivers/net/bnxt/tf_core/hwrm_tf.h @@ -65,6 +65,7 @@ typedef enum tf_subtype { #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; diff --git a/drivers/net/bnxt/tf_core/tf_core.c b/drivers/net/bnxt/tf_core/tf_core.c index ebe0fc34aa..a3b6afbc88 100644 --- a/drivers/net/bnxt/tf_core/tf_core.c +++ b/drivers/net/bnxt/tf_core/tf_core.c @@ -764,7 +764,8 @@ tf_set_tcam_entry(struct tf *tfp, 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", @@ -778,7 +779,7 @@ tf_set_tcam_entry(struct tf *tfp, 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); @@ -796,10 +797,66 @@ tf_set_tcam_entry(struct tf *tfp, 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 diff --git a/drivers/net/bnxt/tf_core/tf_device.h b/drivers/net/bnxt/tf_core/tf_device.h index cbacc09ea5..4f4120c603 100644 --- a/drivers/net/bnxt/tf_core/tf_device.h +++ b/drivers/net/bnxt/tf_core/tf_device.h @@ -736,6 +736,18 @@ struct tf_dev_ops { * 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); }; /** diff --git a/drivers/net/bnxt/tf_core/tf_device_p4.c b/drivers/net/bnxt/tf_core/tf_device_p4.c index f6c8f5efd0..fbe92b7733 100644 --- a/drivers/net/bnxt/tf_core/tf_device_p4.c +++ b/drivers/net/bnxt/tf_core/tf_device_p4.c @@ -212,6 +212,10 @@ static int tf_dev_p4_get_mailbox(void) return TF_KONG_MB; } +static int tf_dev_p4_word_align(uint16_t size) +{ + return ((((size) + 31) >> 5) * 4); +} /** * Truflow P4 device specific functions @@ -250,6 +254,7 @@ const struct tf_dev_ops tf_dev_ops_p4_init = { .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, }; /** @@ -289,4 +294,5 @@ const struct tf_dev_ops tf_dev_ops_p4 = { .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, }; diff --git a/drivers/net/bnxt/tf_core/tf_device_p58.c b/drivers/net/bnxt/tf_core/tf_device_p58.c index 6cef1d5ba5..688d987cb7 100644 --- a/drivers/net/bnxt/tf_core/tf_device_p58.c +++ b/drivers/net/bnxt/tf_core/tf_device_p58.c @@ -193,6 +193,11 @@ static int tf_dev_p58_get_mailbox(void) return TF_CHIMP_MB; } +static int tf_dev_p58_word_align(uint16_t size) +{ + return ((((size) + 63) >> 6) * 8); +} + /** * Truflow P58 device specific functions */ @@ -230,6 +235,7 @@ const struct tf_dev_ops tf_dev_ops_p58_init = { .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, }; /** @@ -255,7 +261,7 @@ const struct tf_dev_ops tf_dev_ops_p58 = { .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, @@ -269,4 +275,5 @@ const struct tf_dev_ops tf_dev_ops_p58 = { .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, }; diff --git a/drivers/net/bnxt/tf_core/tf_msg.c b/drivers/net/bnxt/tf_core/tf_msg.c index 39d7e3eace..1af5c6d11c 100644 --- a/drivers/net/bnxt/tf_core/tf_msg.c +++ b/drivers/net/bnxt/tf_core/tf_msg.c @@ -1212,6 +1212,58 @@ cleanup: 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, diff --git a/drivers/net/bnxt/tf_core/tf_msg.h b/drivers/net/bnxt/tf_core/tf_msg.h index 1d82ce5049..a14bcd3927 100644 --- a/drivers/net/bnxt/tf_core/tf_msg.h +++ b/drivers/net/bnxt/tf_core/tf_msg.h @@ -412,6 +412,22 @@ int tf_msg_tcam_entry_set(struct tf *tfp, 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. * diff --git a/drivers/net/bnxt/tf_core/tf_tcam.c b/drivers/net/bnxt/tf_core/tf_tcam.c index 038aa40e92..a18d0e1e19 100644 --- a/drivers/net/bnxt/tf_core/tf_tcam.c +++ b/drivers/net/bnxt/tf_core/tf_tcam.c @@ -686,7 +686,94 @@ tf_tcam_set(struct tf *tfp __rte_unused, 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; } diff --git a/drivers/net/bnxt/tf_core/tf_tcam.h b/drivers/net/bnxt/tf_core/tf_tcam.h index 40d010b09a..b550fa43ca 100644 --- a/drivers/net/bnxt/tf_core/tf_tcam.h +++ b/drivers/net/bnxt/tf_core/tf_tcam.h @@ -207,6 +207,10 @@ struct tf_tcam_get_parms { * [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 */ -- 2.20.1