X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fbnxt%2Ftf_ulp%2Fulp_mapper.c;h=059ee9983743aa4f546837d723b4489869d2ad39;hb=92ef4b8f1688ded571fb2085727e5e82f2afe5d6;hp=7378a0a90de7f0ec3e2c561abf4854782d6a1243;hpb=52799debdf1c3d9c25a5585c591e8b8959495c23;p=dpdk.git diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c index 7378a0a90d..059ee99837 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c +++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2014-2020 Broadcom + * Copyright(c) 2014-2021 Broadcom * All rights reserved. */ #include #include #include "bnxt.h" -#include "ulp_template_db.h" +#include "ulp_template_db_enum.h" #include "ulp_template_struct.h" #include "bnxt_tf_common.h" #include "ulp_utils.h" @@ -14,15 +14,50 @@ #include "tfp.h" #include "tf_ext_flow_handle.h" #include "ulp_mark_mgr.h" -#include "ulp_flow_db.h" #include "ulp_mapper.h" +#include "ulp_flow_db.h" +#include "tf_util.h" +#include "ulp_template_db_tbl.h" +#include "ulp_port_db.h" +#include "ulp_ha_mgr.h" +#include "bnxt_tf_pmd_shim.h" + +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#include "ulp_template_debug_proto.h" +#include "ulp_tf_debug.h" +#endif + +static uint8_t mapper_fld_zeros[16] = { 0 }; + +static uint8_t mapper_fld_ones[16] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static uint8_t mapper_fld_one[16] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 +}; + +static const char * +ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type) +{ + switch (tmpl_type) { + case BNXT_ULP_TEMPLATE_TYPE_CLASS: + return "class"; + case BNXT_ULP_TEMPLATE_TYPE_ACTION: + return "action"; + default: + return "invalid template type"; + } +} static struct bnxt_ulp_glb_resource_info * ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries) { if (!num_entries) return NULL; - *num_entries = BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ; + *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; return ulp_glb_resource_tbl; } @@ -37,13 +72,15 @@ static int32_t ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data, enum tf_dir dir, uint16_t idx, - uint64_t *regval) + uint64_t *regval, + bool *shared) { - if (!mapper_data || !regval || - dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_REGFILE_INDEX_LAST) + if (!mapper_data || !regval || !shared || + dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST) return -EINVAL; *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl; + *shared = mapper_data->glb_res_tbl[dir][idx].shared; return 0; } @@ -57,13 +94,13 @@ ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data, static int32_t ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, struct bnxt_ulp_glb_resource_info *res, - uint64_t regval) + uint64_t regval, bool shared) { struct bnxt_ulp_mapper_glb_resource_entry *ent; /* validate the arguments */ if (!data || res->direction >= TF_DIR_MAX || - res->glb_regfile_index >= BNXT_ULP_GLB_REGFILE_INDEX_LAST) + res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST) return -EINVAL; /* write to the mapper data */ @@ -71,6 +108,7 @@ ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, ent->resource_func = res->resource_func; ent->resource_type = res->resource_type; ent->resource_hndl = regval; + ent->shared = shared; return 0; } @@ -80,15 +118,20 @@ ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, * returns 0 on success */ static int32_t -ulp_mapper_resource_ident_allocate(struct tf *tfp, +ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx, struct bnxt_ulp_mapper_data *mapper_data, struct bnxt_ulp_glb_resource_info *glb_res) { struct tf_alloc_identifier_parms iparms = { 0 }; struct tf_free_identifier_parms fparms; uint64_t regval; + struct tf *tfp; int32_t rc = 0; + tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); + if (!tfp) + return -EINVAL; + iparms.ident_type = glb_res->resource_type; iparms.dir = glb_res->direction; @@ -96,15 +139,19 @@ ulp_mapper_resource_ident_allocate(struct tf *tfp, rc = tf_alloc_identifier(tfp, &iparms); if (rc) { BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", - (iparms.dir == TF_DIR_RX) ? "RX" : "TX", + tf_dir_2_str(iparms.dir), iparms.ident_type); return rc; } /* entries are stored as big-endian format */ regval = tfp_cpu_to_be_64((uint64_t)iparms.id); - /* write to the mapper global resource */ - rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval); + /* + * write to the mapper global resource + * Shared resources are never allocated through this method, so the + * shared flag is always false. + */ + rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false); if (rc) { BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); /* Free the identifier when update failed */ @@ -115,21 +162,106 @@ ulp_mapper_resource_ident_allocate(struct tf *tfp, return rc; } #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG - BNXT_TF_DBG(DEBUG, "Allocated Glb Res[%s][%d][%d] = 0x%04x\n", - (iparms.dir == TF_DIR_RX) ? "RX" : "TX", +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + BNXT_TF_DBG(DEBUG, "Allocated Glb Res Ident [%s][%d][%d] = 0x%04x\n", + tf_dir_2_str(iparms.dir), glb_res->glb_regfile_index, iparms.ident_type, iparms.id); +#endif #endif return rc; } -/* Retrieve the cache initialization parameters for the tbl_idx */ -static struct bnxt_ulp_cache_tbl_params * -ulp_mapper_cache_tbl_params_get(uint32_t tbl_idx) +/* + * Internal function to allocate index tbl resource and store it in mapper data. + * + * returns 0 on success + */ +static int32_t +ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx, + struct bnxt_ulp_mapper_data *mapper_data, + struct bnxt_ulp_glb_resource_info *glb_res) { - if (tbl_idx >= BNXT_ULP_CACHE_TBL_MAX_SZ) - return NULL; + struct tf_alloc_tbl_entry_parms aparms = { 0 }; + struct tf_free_tbl_entry_parms free_parms = { 0 }; + uint64_t regval; + struct tf *tfp; + uint32_t tbl_scope_id; + int32_t rc = 0; - return &ulp_cache_tbl_params[tbl_idx]; + tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); + if (!tfp) + return -EINVAL; + + /* Get the scope id */ + rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); + return rc; + } + + aparms.type = glb_res->resource_type; + aparms.dir = glb_res->direction; + aparms.tbl_scope_id = tbl_scope_id; + + /* Allocate the index tbl using tf api */ + rc = tf_alloc_tbl_entry(tfp, &aparms); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to alloc index table [%s][%d]\n", + tf_dir_2_str(aparms.dir), aparms.type); + return rc; + } + + /* entries are stored as big-endian format */ + regval = tfp_cpu_to_be_64((uint64_t)aparms.idx); + /* + * write to the mapper global resource + * Shared resources are never allocated through this method, so the + * shared flag is always false. + */ + rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); + /* Free the identifier when update failed */ + free_parms.dir = aparms.dir; + free_parms.type = aparms.type; + free_parms.idx = aparms.idx; + tf_free_tbl_entry(tfp, &free_parms); + return rc; + } +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + BNXT_TF_DBG(DEBUG, "Allocated Glb Res Index [%s][%d][%d] = 0x%04x\n", + tf_dir_2_str(aparms.dir), + glb_res->glb_regfile_index, aparms.type, aparms.idx); +#endif +#endif + return rc; +} + +static int32_t +ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms, + uint32_t operand, + uint8_t *val) +{ + uint32_t t_idx; + + t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT + + BNXT_ULP_HDR_SIG_ID_SHIFT + + BNXT_ULP_GLB_FIELD_TBL_SHIFT); + t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT + + BNXT_ULP_GLB_FIELD_TBL_SHIFT); + t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) << + BNXT_ULP_GLB_FIELD_TBL_SHIFT; + t_idx += operand; + + if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) { + BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n", + parms->class_tid, t_idx, operand); + *val = 0; + return -EINVAL; /* error */ + } + *val = ulp_glb_field_tbl[t_idx]; + return 0; } /* @@ -147,47 +279,45 @@ ulp_mapper_act_prop_size_get(uint32_t idx) return ulp_act_prop_map_table[idx]; } -/* - * Get the list of result fields that implement the flow action. - * Gets a device dependent list of tables that implement the action template id. - * - * dev_id [in] The device id of the forwarding element - * - * tid [in] The action template id that matches the flow - * - * num_tbls [out] The number of action tables in the returned array - * - * Returns An array of action tables to implement the flow, or NULL on error. - */ -static struct bnxt_ulp_mapper_act_tbl_info * -ulp_mapper_action_tbl_list_get(uint32_t dev_id, - uint32_t tid, - uint32_t *num_tbls) +static struct bnxt_ulp_mapper_cond_info * +ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms, + uint32_t tid, + uint32_t *num_tbls, + enum bnxt_ulp_cond_list_opc *opc) { - uint32_t idx; - uint32_t tidx; + uint32_t idx; + const struct bnxt_ulp_template_device_tbls *dev_tbls; - if (!num_tbls) { - BNXT_TF_DBG(ERR, "Invalid arguments\n"); - return NULL; - } + dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; + *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums; + *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode; + idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx; - /* template shift and device mask */ - tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id); + return &dev_tbls->cond_list[idx]; +} - /* NOTE: Need to have something from template compiler to help validate - * range of dev_id and act_tid - */ - idx = ulp_act_tmpl_list[tidx].start_tbl_idx; - *num_tbls = ulp_act_tmpl_list[tidx].num_tbls; +static struct bnxt_ulp_mapper_cond_info * +ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms, + struct bnxt_ulp_mapper_tbl_info *tbl, + uint32_t *num_tbls, + enum bnxt_ulp_cond_list_opc *opc) +{ + uint32_t idx; + const struct bnxt_ulp_template_device_tbls *dev_tbls; + + dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; + *num_tbls = tbl->execute_info.cond_nums; + *opc = tbl->execute_info.cond_list_opcode; + idx = tbl->execute_info.cond_start_idx; - return &ulp_act_tbl_list[idx]; + return &dev_tbls->cond_list[idx]; } -/** Get a list of classifier tables that implement the flow +/* + * Get a list of classifier tables that implement the flow * Gets a device dependent list of tables that implement the class template id * - * dev_id [in] The device id of the forwarding element + * mparms [in] The mappers parms with data related to the flow. * * tid [in] The template id that matches the flow * @@ -196,30 +326,26 @@ ulp_mapper_action_tbl_list_get(uint32_t dev_id, * returns An array of classifier tables to implement the flow, or NULL on * error */ -static struct bnxt_ulp_mapper_class_tbl_info * -ulp_mapper_class_tbl_list_get(uint32_t dev_id, - uint32_t tid, - uint32_t *num_tbls) +static struct bnxt_ulp_mapper_tbl_info * +ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms, + uint32_t tid, + uint32_t *num_tbls) { uint32_t idx; - uint32_t tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id); + const struct bnxt_ulp_template_device_tbls *dev_tbls; - if (!num_tbls) - return NULL; + dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; - /* NOTE: Need to have something from template compiler to help validate - * range of dev_id and tid - */ - idx = ulp_class_tmpl_list[tidx].start_tbl_idx; - *num_tbls = ulp_class_tmpl_list[tidx].num_tbls; + idx = dev_tbls->tmpl_list[tid].start_tbl_idx; + *num_tbls = dev_tbls->tmpl_list[tid].num_tbls; - return &ulp_class_tbl_list[idx]; + return &dev_tbls->tbl_list[idx]; } /* * Get the list of key fields that implement the flow. * - * ctxt [in] The ulp context + * mparms [in] The mapper parms with information about the flow * * tbl [in] A single table instance to get the key fields from * @@ -227,74 +353,60 @@ ulp_mapper_class_tbl_list_get(uint32_t dev_id, * * Returns array of Key fields, or NULL on error. */ -static struct bnxt_ulp_mapper_class_key_field_info * -ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl, +static struct bnxt_ulp_mapper_key_info * +ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms, + struct bnxt_ulp_mapper_tbl_info *tbl, uint32_t *num_flds) { uint32_t idx; + const struct bnxt_ulp_template_device_tbls *dev_tbls; - if (!tbl || !num_flds) + dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; + if (!dev_tbls->key_info_list) { + *num_flds = 0; return NULL; + } idx = tbl->key_start_idx; *num_flds = tbl->key_num_fields; - /* NOTE: Need template to provide range checking define */ - return &ulp_class_key_field_list[idx]; + return &dev_tbls->key_info_list[idx]; } /* * Get the list of data fields that implement the flow. * - * ctxt [in] The ulp context + * mparms [in] The mapper parms with information about the flow * * tbl [in] A single table instance to get the data fields from * * num_flds [out] The number of data fields in the returned array. * - * Returns array of data fields, or NULL on error. - */ -static struct bnxt_ulp_mapper_result_field_info * -ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl, - uint32_t *num_flds) -{ - uint32_t idx; - - if (!tbl || !num_flds) - return NULL; - - idx = tbl->result_start_idx; - *num_flds = tbl->result_num_fields; - - /* NOTE: Need template to provide range checking define */ - return &ulp_class_result_field_list[idx]; -} - -/* - * Get the list of result fields that implement the flow action. - * - * tbl [in] A single table instance to get the results fields - * from num_flds [out] The number of data fields in the returned - * array. + * num_encap_flds [out] The number of encap fields in the returned array. * * Returns array of data fields, or NULL on error. */ -static struct bnxt_ulp_mapper_result_field_info * -ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_act_tbl_info *tbl, - uint32_t *num_rslt_flds, - uint32_t *num_encap_flds) +static struct bnxt_ulp_mapper_field_info * +ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms, + struct bnxt_ulp_mapper_tbl_info *tbl, + uint32_t *num_flds, + uint32_t *num_encap_flds) { uint32_t idx; + const struct bnxt_ulp_template_device_tbls *dev_tbls; - if (!tbl || !num_rslt_flds || !num_encap_flds) + dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; + if (!dev_tbls->result_field_list) { + *num_flds = 0; + *num_encap_flds = 0; return NULL; + } idx = tbl->result_start_idx; - *num_rslt_flds = tbl->result_num_fields; + *num_flds = tbl->result_num_fields; *num_encap_flds = tbl->encap_num_fields; - /* NOTE: Need template to provide range checking define */ - return &ulp_act_result_field_list[idx]; + return &dev_tbls->result_field_list[idx]; } /* @@ -307,138 +419,98 @@ ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_act_tbl_info *tbl, * returns array of ident fields, or NULL on error */ static struct bnxt_ulp_mapper_ident_info * -ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl, +ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms, + struct bnxt_ulp_mapper_tbl_info *tbl, uint32_t *num_flds) { uint32_t idx; + const struct bnxt_ulp_template_device_tbls *dev_tbls; - if (!tbl || !num_flds) + dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; + if (!dev_tbls->ident_list) { + *num_flds = 0; return NULL; + } idx = tbl->ident_start_idx; *num_flds = tbl->ident_nums; - /* NOTE: Need template to provide range checking define */ - return &ulp_ident_list[idx]; + return &dev_tbls->ident_list[idx]; } -static struct bnxt_ulp_mapper_cache_entry * -ulp_mapper_cache_entry_get(struct bnxt_ulp_context *ulp, - uint32_t id, - uint16_t key) +static enum tf_tbl_type +ulp_mapper_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *mparms, + struct bnxt_ulp_mapper_tbl_info *tbl, + struct ulp_blob *bdata, + uint16_t *out_len) { - struct bnxt_ulp_mapper_data *mapper_data; + struct bnxt_ulp_device_params *d_params = mparms->device_params; + uint16_t blob_len = ulp_blob_data_len_get(bdata); + struct bnxt_ulp_dyn_size_map *size_map; + uint32_t i; - mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp); - if (!mapper_data || id >= BNXT_ULP_CACHE_TBL_MAX_SZ || - !mapper_data->cache_tbl[id]) { - BNXT_TF_DBG(ERR, "Unable to acquire the cache tbl (%d)\n", id); - return NULL; + if (d_params->dynamic_sram_en) { + switch (tbl->resource_type) { + case TF_TBL_TYPE_ACT_ENCAP_8B: + case TF_TBL_TYPE_ACT_ENCAP_16B: + case TF_TBL_TYPE_ACT_ENCAP_32B: + case TF_TBL_TYPE_ACT_ENCAP_64B: + size_map = d_params->dyn_encap_sizes; + for (i = 0; i < d_params->dyn_encap_list_size; i++) { + if (blob_len <= size_map[i].slab_size) { + *out_len = size_map[i].slab_size; + return size_map[i].tbl_type; + } + } + break; + case TF_TBL_TYPE_ACT_MODIFY_8B: + case TF_TBL_TYPE_ACT_MODIFY_16B: + case TF_TBL_TYPE_ACT_MODIFY_32B: + case TF_TBL_TYPE_ACT_MODIFY_64B: + size_map = d_params->dyn_modify_sizes; + for (i = 0; i < d_params->dyn_modify_list_size; i++) { + if (blob_len <= size_map[i].slab_size) { + *out_len = size_map[i].slab_size; + return size_map[i].tbl_type; + } + } + break; + default: + break; + } } - - return &mapper_data->cache_tbl[id][key]; -} - -/* - * Concatenates the tbl_type and tbl_id into a 32bit value for storing in the - * resource_type. This is done to conserve memory since both the tbl_type and - * tbl_id are 16bit. - */ -static inline void -ulp_mapper_cache_res_type_set(struct ulp_flow_db_res_params *res, - uint16_t tbl_type, - uint16_t tbl_id) -{ - res->resource_type = tbl_type; - res->resource_sub_type = tbl_id; -} - -/* Extracts the tbl_type and tbl_id from the 32bit resource type. */ -static inline void -ulp_mapper_cache_res_type_get(struct ulp_flow_db_res_params *res, - uint16_t *tbl_type, - uint16_t *tbl_id) -{ - *tbl_type = res->resource_type; - *tbl_id = res->resource_sub_type; + return tbl->resource_type; } -static int32_t -ulp_mapper_cache_entry_free(struct bnxt_ulp_context *ulp, - struct tf *tfp, - struct ulp_flow_db_res_params *res) +static uint16_t +ulp_mapper_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms, + struct bnxt_ulp_mapper_tbl_info *tbl) { - struct bnxt_ulp_mapper_cache_entry *cache_entry; - struct tf_free_identifier_parms ident_parms; - struct tf_free_tcam_entry_parms tcam_parms; - uint16_t table_id, table_type; - int32_t rc, trc, i; - - /* - * The table id, used for cache, and table_type, used for tcam, are - * both encoded within the resource. We must first extract them to - * formulate the args for tf calls. - */ - ulp_mapper_cache_res_type_get(res, &table_type, &table_id); - cache_entry = ulp_mapper_cache_entry_get(ulp, table_id, - (uint16_t)res->resource_hndl); - if (!cache_entry || !cache_entry->ref_count) { - BNXT_TF_DBG(ERR, "Cache entry (%d:%d) not valid on free.\n", - table_id, (uint16_t)res->resource_hndl); - return -EINVAL; - } - - /* - * See if we need to delete the entry. The tcam and identifiers are all - * tracked by the cached entries reference count. All are deleted when - * the reference count hit zero. - */ - cache_entry->ref_count--; - if (cache_entry->ref_count) - return 0; - - /* - * Need to delete the tcam entry and the allocated identifiers. - * In the event of a failure, need to try to delete the remaining - * resources before returning error. - */ - tcam_parms.dir = res->direction; - tcam_parms.tcam_tbl_type = table_type; - tcam_parms.idx = cache_entry->tcam_idx; - rc = tf_free_tcam_entry(tfp, &tcam_parms); - if (rc) - BNXT_TF_DBG(ERR, "Failed to free tcam [%d][%s][0x%04x] rc=%d\n", - table_type, - (res->direction == TF_DIR_RX) ? "RX" : "TX", - tcam_parms.idx, rc); - - /* - * Free the identifiers associated with the tcam entry. Entries with - * negative one are considered uninitialized. - */ - for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) { - if (cache_entry->idents[i] == ULP_IDENTS_INVALID) - continue; - - ident_parms.dir = res->direction; - ident_parms.ident_type = cache_entry->ident_types[i]; - ident_parms.id = cache_entry->idents[i]; - trc = tf_free_identifier(tfp, &ident_parms); - if (trc) { - BNXT_TF_DBG(ERR, "Failed to free identifier " - "[%d][%s][0x%04x] rc=%d\n", - ident_parms.ident_type, - (res->direction == TF_DIR_RX) ? "RX" : "TX", - ident_parms.id, trc); - rc = trc; + struct bnxt_ulp_device_params *d_params = mparms->device_params; + + if (d_params->dynamic_sram_en) { + switch (tbl->resource_type) { + case TF_TBL_TYPE_ACT_ENCAP_8B: + case TF_TBL_TYPE_ACT_ENCAP_16B: + case TF_TBL_TYPE_ACT_ENCAP_32B: + case TF_TBL_TYPE_ACT_ENCAP_64B: + case TF_TBL_TYPE_ACT_MODIFY_8B: + case TF_TBL_TYPE_ACT_MODIFY_16B: + case TF_TBL_TYPE_ACT_MODIFY_32B: + case TF_TBL_TYPE_ACT_MODIFY_64B: + /* return max size */ + return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; + default: + break; } + } else if (tbl->encap_num_fields) { + return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; } - - return rc; + return tbl->result_bit_size; } static inline int32_t -ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused, +ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp, struct tf *tfp, struct ulp_flow_db_res_params *res) { @@ -448,6 +520,30 @@ ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused, .idx = (uint16_t)res->resource_hndl }; + /* If HA is enabled, we may have to remap the TF Type */ + if (bnxt_ulp_cntxt_ha_enabled(ulp)) { + enum ulp_ha_mgr_region region; + int32_t rc; + + switch (res->resource_type) { + case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH: + case TF_TCAM_TBL_TYPE_WC_TCAM_LOW: + rc = ulp_ha_mgr_region_get(ulp, ®ion); + if (rc) + /* Log this, but assume region is correct */ + BNXT_TF_DBG(ERR, + "Unable to get HA region (%d)\n", + rc); + else + fparms.tcam_tbl_type = + (region == ULP_HA_REGION_LOW) ? + TF_TCAM_TBL_TYPE_WC_TCAM_LOW : + TF_TCAM_TBL_TYPE_WC_TCAM_HIGH; + break; + default: + break; + } + } return tf_free_tcam_entry(tfp, &fparms); } @@ -463,24 +559,23 @@ ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp, }; /* - * Just set the table scope, it will be ignored if not necessary + * Just get the table scope, it will be ignored if not necessary * by the tf_free_tbl_entry */ - bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); + (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); return tf_free_tbl_entry(tfp, &fparms); } static inline int32_t -ulp_mapper_eem_entry_free(struct bnxt_ulp_context *ulp, - struct tf *tfp, - struct ulp_flow_db_res_params *res) +ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp, + struct tf *tfp, + struct ulp_flow_db_res_params *res) { struct tf_delete_em_entry_parms fparms = { 0 }; int32_t rc; fparms.dir = res->direction; - fparms.mem = TF_MEM_EXTERNAL; fparms.flow_handle = res->resource_hndl; rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); @@ -515,6 +610,211 @@ ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, res->resource_hndl); } +static inline int32_t +ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp, + uint32_t parent_fid, + struct ulp_flow_db_res_params *res) +{ + uint32_t pc_idx; + + pc_idx = (uint32_t)res->resource_hndl; + + /* reset the child flow bitset*/ + if (ulp_flow_db_pc_db_parent_flow_set(ulp, pc_idx, parent_fid, 0)) { + BNXT_TF_DBG(ERR, "error in reset parent flow bitset %x:%x\n", + pc_idx, parent_fid); + return -EINVAL; + } + return 0; +} + +static inline int32_t +ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp, + uint32_t child_fid, + struct ulp_flow_db_res_params *res) +{ + uint32_t pc_idx; + + pc_idx = (uint32_t)res->resource_hndl; + + /* reset the child flow bitset*/ + if (ulp_flow_db_pc_db_child_flow_set(ulp, pc_idx, child_fid, 0)) { + BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n", + pc_idx, child_fid); + return -EINVAL; + } + return 0; +} + +/* + * Process the flow database opcode alloc action. + * returns 0 on success + */ +static int32_t +ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + uint32_t rid = 0; + uint64_t val64; + int32_t rc = 0; + + /* allocate a new fid */ + rc = ulp_flow_db_fid_alloc(parms->ulp_ctx, + BNXT_ULP_FDB_TYPE_RID, + 0, &rid); + if (rc) { + BNXT_TF_DBG(ERR, + "Unable to allocate flow table entry\n"); + return -EINVAL; + } + /* Store the allocated fid in regfile*/ + val64 = rid; + rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand, + tfp_cpu_to_be_64(val64)); + if (rc) { + BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", + tbl->fdb_operand); + ulp_flow_db_fid_free(parms->ulp_ctx, + BNXT_ULP_FDB_TYPE_RID, rid); + return -EINVAL; + } + return 0; +} + +/* + * Process the flow database opcode action. + * returns 0 on success. + */ +static int32_t +ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + struct ulp_flow_db_res_params *fid_parms) +{ + uint32_t push_fid; + uint64_t val64; + enum bnxt_ulp_fdb_type flow_type; + int32_t rc = 0; + + switch (tbl->fdb_opcode) { + case BNXT_ULP_FDB_OPC_PUSH_FID: + push_fid = parms->fid; + flow_type = parms->flow_type; + break; + case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE: + /* get the fid from the regfile */ + rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand, + &val64); + if (!rc) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", + tbl->fdb_operand); + return -EINVAL; + } + /* Use the extracted fid to update the flow resource */ + push_fid = (uint32_t)tfp_be_to_cpu_64(val64); + flow_type = BNXT_ULP_FDB_TYPE_RID; + break; + default: + return rc; /* Nothing to be done */ + } + + /* Add the resource to the flow database */ + rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type, + push_fid, fid_parms); + if (rc) + BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n", + push_fid, rc); + return rc; +} + +/* + * Process the flow database opcode action. + * returns 0 on success. + */ +static int32_t +ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + uint32_t *priority) +{ + int32_t rc = 0; + + switch (tbl->pri_opcode) { + case BNXT_ULP_PRI_OPC_NOT_USED: + *priority = 0; + break; + case BNXT_ULP_PRI_OPC_CONST: + *priority = tbl->pri_operand; + break; + case BNXT_ULP_PRI_OPC_APP_PRI: + *priority = parms->app_priority; + break; + default: + BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n", + tbl->pri_opcode); + rc = -EINVAL; + break; + } + return rc; +} + +/* + * Process the identifier list in the given table. + * Extract the ident from the table entry and + * write it to the reg file. + * returns 0 on success. + */ +static int32_t +ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + uint8_t *byte_data, + uint32_t byte_data_size, + enum bnxt_ulp_byte_order byte_order) +{ + struct bnxt_ulp_mapper_ident_info *idents; + uint32_t i, num_idents = 0; + uint64_t val64; + + /* validate the null arguments */ + if (!byte_data) { + BNXT_TF_DBG(ERR, "invalid argument\n"); + return -EINVAL; + } + + /* Get the ident list and process each one */ + idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); + + for (i = 0; i < num_idents; i++) { + /* check the size of the buffer for validation */ + if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) > + ULP_BYTE_2_BITS(byte_data_size) || + idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) { + BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n", + idents[i].ident_bit_pos, + idents[i].ident_bit_size, + byte_data_size); + return -EINVAL; + } + val64 = 0; + if (byte_order == BNXT_ULP_BYTE_ORDER_LE) + ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64, + sizeof(val64), + idents[i].ident_bit_pos, + idents[i].ident_bit_size); + else + ulp_bs_pull_msb(byte_data, (uint8_t *)&val64, + idents[i].ident_bit_pos, + idents[i].ident_bit_size); + + /* Write it to the regfile, val64 is already in big-endian*/ + if (ulp_regfile_write(parms->regfile, + idents[i].regfile_idx, val64)) { + BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", + idents[i].regfile_idx); + return -EINVAL; + } + } + return 0; +} + /* * Process the identifier instruction and either store it in the flow database * or return it in the val (if not NULL) on success. If val is NULL, the @@ -522,7 +822,7 @@ ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, */ static int32_t ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_class_tbl_info *tbl, + struct bnxt_ulp_mapper_tbl_info *tbl, struct bnxt_ulp_mapper_ident_info *ident, uint16_t *val) { @@ -534,27 +834,30 @@ ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, struct tf *tfp; int rc; - tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); if (!tfp) { BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); return -EINVAL; } - idx = ident->regfile_wr_idx; + idx = ident->regfile_idx; iparms.ident_type = ident->ident_type; iparms.dir = tbl->direction; rc = tf_alloc_identifier(tfp, &iparms); if (rc) { - BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n", - (iparms.dir == TF_DIR_RX) ? "RX" : "TX", - iparms.ident_type); + BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n", + tf_dir_2_str(iparms.dir), + tf_ident_2_str(iparms.ident_type)); return rc; } + BNXT_TF_INF("Alloc ident %s:%s.success.\n", + tf_dir_2_str(iparms.dir), + tf_ident_2_str(iparms.ident_type)); id = (uint64_t)tfp_cpu_to_be_64(iparms.id); - if (!ulp_regfile_write(parms->regfile, idx, id)) { + if (ulp_regfile_write(parms->regfile, idx, id)) { BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); rc = -EINVAL; /* Need to free the identifier, so goto error */ @@ -568,12 +871,10 @@ ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, fid_parms.resource_func = ident->resource_func; fid_parms.resource_type = ident->ident_type; fid_parms.resource_hndl = iparms.id; - fid_parms.critical_resource = 0; + fid_parms.critical_resource = tbl->critical_resource; + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); if (rc) { BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", rc); @@ -583,7 +884,11 @@ ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, } else { *val = iparms.id; } - +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_ident_field_dump("Ident", ident, tbl, iparms.id); +#endif +#endif return 0; error: @@ -596,96 +901,255 @@ error: BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n", ident->description, - (tbl->direction == TF_DIR_RX) ? "RX" : "TX"); + tf_dir_2_str(tbl->direction)); return rc; } +/* + * Process the identifier instruction and extract it from result blob. + * Increment the identifier reference count and store it in the flow database. + */ static int32_t -ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms, - enum tf_dir dir, - struct bnxt_ulp_mapper_result_field_info *fld, - struct ulp_blob *blob, - const char *name) -{ - uint16_t idx, size_idx; - uint8_t *val = NULL; - uint64_t regval; - uint32_t val_size = 0, field_size = 0; - uint64_t act_bit; - uint8_t act_val; - - switch (fld->result_opcode) { - case BNXT_ULP_RESULT_OPC_SET_TO_CONSTANT: - val = fld->result_operand; - if (!ulp_blob_push(blob, val, fld->field_bit_size)) { - BNXT_TF_DBG(ERR, "%s failed to add field\n", name); - return -EINVAL; +ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + struct bnxt_ulp_mapper_ident_info *ident, + struct ulp_blob *res_blob) +{ + struct ulp_flow_db_res_params fid_parms; + uint64_t id = 0; + uint32_t idx = 0; + struct tf_search_identifier_parms sparms = { 0 }; + struct tf_free_identifier_parms free_parms = { 0 }; + struct tf *tfp; + int rc; + + /* Get the tfp from ulp context */ + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); + if (!tfp) { + BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); + return -EINVAL; + } + + /* Extract the index from the result blob */ + rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx), + ident->ident_bit_pos, ident->ident_bit_size); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n"); + return -EIO; + } + + /* populate the search params and search identifier shadow table */ + sparms.ident_type = ident->ident_type; + sparms.dir = tbl->direction; + /* convert the idx into cpu format */ + sparms.search_id = tfp_be_to_cpu_32(idx); + + /* Search identifier also increase the reference count */ + rc = tf_search_identifier(tfp, &sparms); + if (rc) { + BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n", + tf_dir_2_str(sparms.dir), + tf_ident_2_str(sparms.ident_type), + sparms.search_id); + return rc; + } + BNXT_TF_INF("Search ident %s:%s:%x.success.\n", + tf_dir_2_str(sparms.dir), + tf_tbl_type_2_str(sparms.ident_type), + sparms.search_id); + + /* Write it to the regfile */ + id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id); + if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) { + BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); + rc = -EINVAL; + /* Need to free the identifier, so goto error */ + goto error; + } + + /* Link the resource to the flow in the flow db */ + memset(&fid_parms, 0, sizeof(fid_parms)); + fid_parms.direction = tbl->direction; + fid_parms.resource_func = ident->resource_func; + fid_parms.resource_type = ident->ident_type; + fid_parms.resource_hndl = sparms.search_id; + fid_parms.critical_resource = tbl->critical_resource; + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); + + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", + rc); + /* Need to free the identifier, so goto error */ + goto error; + } + +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_ident_field_dump("Ident", ident, tbl, sparms.search_id); +#endif +#endif + return 0; + +error: + /* Need to free the identifier */ + free_parms.dir = tbl->direction; + free_parms.ident_type = ident->ident_type; + free_parms.id = sparms.search_id; + (void)tf_free_identifier(tfp, &free_parms); + BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n", + ident->description, + tf_dir_2_str(tbl->direction), sparms.search_id); + return rc; +} + +static int32_t +ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms, + uint32_t port_id, + uint16_t val16, + uint8_t **val) +{ + enum bnxt_ulp_port_table port_data = val16; + + switch (port_data) { + case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC: + if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id, + val)) { + BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); + return -EINVAL; + } + break; + case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC: + if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id, + val)) { + BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); + return -EINVAL; } break; - case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP: - if (!ulp_operand_read(fld->result_operand, + case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC: + if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id, + val)) { + BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); + return -EINVAL; + } + break; + default: + BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data); + return -EINVAL; + } + return 0; +} + +static int32_t +ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms, + enum bnxt_ulp_field_src field_src, + uint8_t *field_opr, + enum tf_dir dir, + uint8_t is_key, + uint32_t bitlen, + uint8_t **val, + uint32_t *val_len, + uint64_t *value) +{ + struct bnxt_ulp_mapper_data *m; + uint8_t bit; + uint32_t port_id, val_size, field_size; + uint16_t idx, size_idx, offset; + uint32_t bytelen = ULP_BITS_2_BYTE(bitlen); + uint8_t *buffer; + uint64_t lregval; + bool shared; + + *val_len = bitlen; + *value = 0; + /* Perform the action */ + switch (field_src) { + case BNXT_ULP_FIELD_SRC_ZERO: + *val = mapper_fld_zeros; + break; + case BNXT_ULP_FIELD_SRC_CONST: + *val = field_opr; + break; + case BNXT_ULP_FIELD_SRC_ONES: + *val = mapper_fld_ones; + *value = 1; + break; + case BNXT_ULP_FIELD_SRC_CF: + if (!ulp_operand_read(field_opr, (uint8_t *)&idx, sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s operand read failed\n", name); + BNXT_TF_DBG(ERR, "CF operand read failed\n"); return -EINVAL; } idx = tfp_be_to_cpu_16(idx); - - if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { - BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx); + if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) { + BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx, + bytelen); return -EINVAL; } - val = &parms->act_prop->act_details[idx]; - field_size = ulp_mapper_act_prop_size_get(idx); - if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) { - field_size = field_size - - ((fld->field_bit_size + 7) / 8); - val += field_size; + buffer = (uint8_t *)&parms->comp_fld[idx]; + *val = &buffer[sizeof(uint64_t) - bytelen]; + *value = ULP_COMP_FLD_IDX_RD(parms, idx); + break; + case BNXT_ULP_FIELD_SRC_RF: + if (!ulp_operand_read(field_opr, + (uint8_t *)&idx, sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "RF operand read failed\n"); + return -EINVAL; } - if (!ulp_blob_push(blob, val, fld->field_bit_size)) { - BNXT_TF_DBG(ERR, "%s push field failed\n", name); + + idx = tfp_be_to_cpu_16(idx); + /* Uninitialized regfile entries return 0 */ + if (!ulp_regfile_read(parms->regfile, idx, &lregval) || + sizeof(uint64_t) < bytelen) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx, + bytelen); return -EINVAL; } + buffer = (uint8_t *)&parms->regfile->entry[idx].data; + *val = &buffer[sizeof(uint64_t) - bytelen]; + *value = tfp_be_to_cpu_64(lregval); break; - case BNXT_ULP_RESULT_OPC_SET_TO_ACT_BIT: - if (!ulp_operand_read(fld->result_operand, - (uint8_t *)&act_bit, sizeof(uint64_t))) { - BNXT_TF_DBG(ERR, "%s operand read failed\n", name); + case BNXT_ULP_FIELD_SRC_ACT_PROP: + if (!ulp_operand_read(field_opr, + (uint8_t *)&idx, sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "Action operand read failed\n"); return -EINVAL; } - act_bit = tfp_be_to_cpu_64(act_bit); - act_val = ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit); - if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) { - BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name); + idx = tfp_be_to_cpu_16(idx); + if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { + BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx); return -EINVAL; } - if (!ulp_blob_push(blob, &act_val, fld->field_bit_size)) { - BNXT_TF_DBG(ERR, "%s push field failed\n", name); + buffer = &parms->act_prop->act_details[idx]; + field_size = ulp_mapper_act_prop_size_get(idx); + if (bytelen > field_size) { + BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n", + idx, field_size); return -EINVAL; } - val = &act_val; + *val = &buffer[field_size - bytelen]; break; - case BNXT_ULP_RESULT_OPC_SET_TO_ENCAP_ACT_PROP_SZ: - if (!ulp_operand_read(fld->result_operand, + case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ: + if (!ulp_operand_read(field_opr, (uint8_t *)&idx, sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s operand read failed\n", name); + BNXT_TF_DBG(ERR, "Action sz operand read failed\n"); return -EINVAL; } idx = tfp_be_to_cpu_16(idx); if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { - BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx); + BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx); return -EINVAL; } - val = &parms->act_prop->act_details[idx]; + *val = &parms->act_prop->act_details[idx]; /* get the size index next */ - if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)], + if (!ulp_operand_read(&field_opr[sizeof(uint16_t)], (uint8_t *)&size_idx, sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s operand read failed\n", name); + BNXT_TF_DBG(ERR, "Action sz operand read failed\n"); return -EINVAL; } size_idx = tfp_be_to_cpu_16(size_idx); - if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx); return -EINVAL; @@ -693,344 +1157,562 @@ ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms, memcpy(&val_size, &parms->act_prop->act_details[size_idx], sizeof(uint32_t)); val_size = tfp_be_to_cpu_32(val_size); - val_size = ULP_BYTE_2_BITS(val_size); - ulp_blob_push_encap(blob, val, val_size); + *val_len = ULP_BYTE_2_BITS(val_size); break; - case BNXT_ULP_RESULT_OPC_SET_TO_REGFILE: - if (!ulp_operand_read(fld->result_operand, + case BNXT_ULP_FIELD_SRC_GLB_RF: + if (!ulp_operand_read(field_opr, (uint8_t *)&idx, sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s operand read failed\n", name); + BNXT_TF_DBG(ERR, "Global regfile read failed\n"); return -EINVAL; } - idx = tfp_be_to_cpu_16(idx); - /* Uninitialized regfile entries return 0 */ - if (!ulp_regfile_read(parms->regfile, idx, ®val)) { - BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n", - name, idx); - return -EINVAL; - } - - val = ulp_blob_push_64(blob, ®val, fld->field_bit_size); - if (!val) { - BNXT_TF_DBG(ERR, "%s push field failed\n", name); + if (ulp_mapper_glb_resource_read(parms->mapper_data, + dir, idx, &lregval, &shared) || + sizeof(uint64_t) < bytelen) { + BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n", + idx, bytelen); return -EINVAL; } + m = parms->mapper_data; + buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl; + *val = &buffer[sizeof(uint64_t) - bytelen]; + *value = tfp_be_to_cpu_64(lregval); break; - case BNXT_ULP_RESULT_OPC_SET_TO_GLB_REGFILE: - if (!ulp_operand_read(fld->result_operand, - (uint8_t *)&idx, - sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); + case BNXT_ULP_FIELD_SRC_HF: + case BNXT_ULP_FIELD_SRC_SUB_HF: + if (!ulp_operand_read(field_opr, + (uint8_t *)&idx, sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "Header field read failed\n"); return -EINVAL; } idx = tfp_be_to_cpu_16(idx); - if (ulp_mapper_glb_resource_read(parms->mapper_data, - dir, - idx, ®val)) { - BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", - name, idx); + /* get the index from the global field list */ + if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) { + BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", + idx); return -EINVAL; } - val = ulp_blob_push_64(blob, ®val, fld->field_bit_size); - if (!val) { - BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); + if (is_key) + buffer = parms->hdr_field[bit].spec; + else + buffer = parms->hdr_field[bit].mask; + + field_size = parms->hdr_field[bit].size; + if (bytelen > field_size) { + BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n", + bit, field_size); return -EINVAL; } + if (field_src == BNXT_ULP_FIELD_SRC_HF) { + *val = &buffer[field_size - bytelen]; + } else { + /* get the offset next */ + if (!ulp_operand_read(&field_opr[sizeof(uint16_t)], + (uint8_t *)&offset, + sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "Hdr fld size read failed\n"); + return -EINVAL; + } + offset = tfp_be_to_cpu_16(offset); + offset = ULP_BITS_2_BYTE_NR(offset); + if ((offset + bytelen) > field_size) { + BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit); + return -EINVAL; + } + *val = &buffer[offset]; + } break; - case BNXT_ULP_RESULT_OPC_SET_TO_COMP_FIELD: - if (!ulp_operand_read(fld->result_operand, - (uint8_t *)&idx, - sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); + case BNXT_ULP_FIELD_SRC_HDR_BIT: + if (!ulp_operand_read(field_opr, + (uint8_t *)&lregval, sizeof(uint64_t))) { + BNXT_TF_DBG(ERR, "Header bit read failed\n"); return -EINVAL; } - idx = tfp_be_to_cpu_16(idx); - if (idx < BNXT_ULP_CF_IDX_LAST) - val = ulp_blob_push_32(blob, &parms->comp_fld[idx], - fld->field_bit_size); - if (!val) { - BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); - return -EINVAL; + lregval = tfp_be_to_cpu_64(lregval); + if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) { + *val = mapper_fld_one; + *value = 1; + } else { + *val = mapper_fld_zeros; } break; - default: - return -EINVAL; - } - return 0; -} - -/* Function to alloc action record and set the table. */ -static int32_t -ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms, - enum tf_dir dir, - struct bnxt_ulp_mapper_class_key_field_info *f, - struct ulp_blob *blob, - uint8_t is_key, - const char *name) -{ - uint64_t val64; - uint16_t idx, bitlen; - uint32_t opcode; - uint8_t *operand; - struct ulp_regfile *regfile = parms->regfile; - uint8_t *val = NULL; - struct bnxt_ulp_mapper_class_key_field_info *fld = f; - uint32_t field_size; - - if (is_key) { - operand = fld->spec_operand; - opcode = fld->spec_opcode; - } else { - operand = fld->mask_operand; - opcode = fld->mask_opcode; - } - - bitlen = fld->field_bit_size; - - switch (opcode) { - case BNXT_ULP_SPEC_OPC_SET_TO_CONSTANT: - val = operand; - if (!ulp_blob_push(blob, val, bitlen)) { - BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); + case BNXT_ULP_FIELD_SRC_ACT_BIT: + if (!ulp_operand_read(field_opr, + (uint8_t *)&lregval, sizeof(uint64_t))) { + BNXT_TF_DBG(ERR, "Action bit read failed\n"); return -EINVAL; } - break; - case BNXT_ULP_SPEC_OPC_ADD_PAD: - if (!ulp_blob_pad_push(blob, bitlen)) { - BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name); - return -EINVAL; + lregval = tfp_be_to_cpu_64(lregval); + if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) { + *val = mapper_fld_one; + *value = 1; + } else { + *val = mapper_fld_zeros; } - break; - case BNXT_ULP_SPEC_OPC_SET_TO_HDR_FIELD: - if (!ulp_operand_read(operand, (uint8_t *)&idx, - sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); + case BNXT_ULP_FIELD_SRC_FIELD_BIT: + if (!ulp_operand_read(field_opr, + (uint8_t *)&idx, sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "Field bit read failed\n"); return -EINVAL; } idx = tfp_be_to_cpu_16(idx); - if (is_key) - val = parms->hdr_field[idx].spec; - else - val = parms->hdr_field[idx].mask; - - /* - * Need to account for how much data was pushed to the header - * field vs how much is to be inserted in the key/mask. - */ - field_size = parms->hdr_field[idx].size; - if (bitlen < ULP_BYTE_2_BITS(field_size)) { - field_size = field_size - ((bitlen + 7) / 8); - val += field_size; - } - - if (!ulp_blob_push(blob, val, bitlen)) { - BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); + /* get the index from the global field list */ + if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) { + BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", + idx); return -EINVAL; } + if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) { + *val = mapper_fld_one; + *value = 1; + } else { + *val = mapper_fld_zeros; + } break; - case BNXT_ULP_SPEC_OPC_SET_TO_COMP_FIELD: - if (!ulp_operand_read(operand, (uint8_t *)&idx, - sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); + case BNXT_ULP_FIELD_SRC_PORT_TABLE: + /* The port id is present in the comp field list */ + port_id = ULP_COMP_FLD_IDX_RD(parms, + BNXT_ULP_CF_IDX_DEV_PORT_ID); + /* get the port table enum */ + if (!ulp_operand_read(field_opr, + (uint8_t *)&idx, sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "Port table enum read failed\n"); return -EINVAL; } idx = tfp_be_to_cpu_16(idx); - if (idx < BNXT_ULP_CF_IDX_LAST) - val = ulp_blob_push_32(blob, &parms->comp_fld[idx], - bitlen); - if (!val) { - BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); + if (ulp_mapper_field_port_db_process(parms, port_id, idx, + val)) { + BNXT_TF_DBG(ERR, "field port table failed\n"); return -EINVAL; } break; - case BNXT_ULP_SPEC_OPC_SET_TO_REGFILE: - if (!ulp_operand_read(operand, (uint8_t *)&idx, - sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); - return -EINVAL; - } - idx = tfp_be_to_cpu_16(idx); - - if (!ulp_regfile_read(regfile, idx, &val64)) { - BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", - name, idx); + case BNXT_ULP_FIELD_SRC_ENC_HDR_BIT: + if (!ulp_operand_read(field_opr, + (uint8_t *)&lregval, sizeof(uint64_t))) { + BNXT_TF_DBG(ERR, "Header bit read failed\n"); return -EINVAL; } - - val = ulp_blob_push_64(blob, &val64, bitlen); - if (!val) { - BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); - return -EINVAL; + lregval = tfp_be_to_cpu_64(lregval); + if (ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, lregval)) { + *val = mapper_fld_one; + *value = 1; + } else { + *val = mapper_fld_zeros; } break; - case BNXT_ULP_SPEC_OPC_SET_TO_GLB_REGFILE: - if (!ulp_operand_read(operand, (uint8_t *)&idx, - sizeof(uint16_t))) { - BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); + case BNXT_ULP_FIELD_SRC_ENC_FIELD: + if (!ulp_operand_read(field_opr, + (uint8_t *)&idx, sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "Header field read failed\n"); return -EINVAL; } idx = tfp_be_to_cpu_16(idx); - if (ulp_mapper_glb_resource_read(parms->mapper_data, - dir, - idx, &val64)) { - BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", - name, idx); + /* get the index from the global field list */ + if (idx >= BNXT_ULP_ENC_FIELD_LAST) { + BNXT_TF_DBG(ERR, "invalid encap field tbl idx %d\n", + idx); return -EINVAL; } - val = ulp_blob_push_64(blob, &val64, bitlen); - if (!val) { - BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); + buffer = parms->enc_field[idx].spec; + field_size = parms->enc_field[idx].size; + if (bytelen > field_size) { + BNXT_TF_DBG(ERR, "Encap field[%d] size small %u\n", + idx, field_size); return -EINVAL; } + *val = &buffer[field_size - bytelen]; break; - default: + case BNXT_ULP_FIELD_SRC_SKIP: + /* do nothing */ + *val = mapper_fld_zeros; + *val_len = 0; break; + case BNXT_ULP_FIELD_SRC_REJECT: + return -EINVAL; + default: + BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src); + return -EINVAL; } - return 0; } -/* Function to alloc action record and set the table. */ -static int32_t -ulp_mapper_action_alloc_and_set(struct bnxt_ulp_mapper_parms *parms, - struct ulp_blob *blob) -{ - struct ulp_flow_db_res_params fid_parms; - struct tf_alloc_tbl_entry_parms alloc_parms = { 0 }; - struct tf_free_tbl_entry_parms free_parms = { 0 }; - struct bnxt_ulp_mapper_act_tbl_info *atbls = parms->atbls; - int32_t rc = 0; - int32_t trc; - uint64_t idx; - uint32_t tbl_scope_id; - - bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); - - /* Set the allocation parameters for the table*/ - alloc_parms.dir = atbls->direction; - alloc_parms.type = atbls->resource_type; - alloc_parms.search_enable = atbls->srch_b4_alloc; - alloc_parms.result = ulp_blob_data_get(blob, - &alloc_parms.result_sz_in_bytes); - alloc_parms.tbl_scope_id = tbl_scope_id; - if (!alloc_parms.result) { - BNXT_TF_DBG(ERR, "blob is not populated\n"); +static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen, + uint64_t *output) +{ + uint16_t val_16; + uint32_t val_32; + uint64_t val_64; + uint32_t bytelen; + + bytelen = ULP_BITS_2_BYTE(bitlen); + if (bytelen == sizeof(uint8_t)) { + *output = *((uint8_t *)buffer); + } else if (bytelen == sizeof(uint16_t)) { + val_16 = *((uint16_t *)buffer); + *output = tfp_be_to_cpu_16(val_16); + } else if (bytelen == sizeof(uint32_t)) { + val_32 = *((uint32_t *)buffer); + *output = tfp_be_to_cpu_32(val_32); + } else if (bytelen == sizeof(val_64)) { + val_64 = *((uint64_t *)buffer); + *output = tfp_be_to_cpu_64(val_64); + } else { + *output = 0; return -EINVAL; } + return 0; +} - rc = tf_alloc_tbl_entry(parms->tfp, &alloc_parms); - if (rc) { - BNXT_TF_DBG(ERR, "table type= [%d] dir = [%s] alloc failed\n", - alloc_parms.type, - (alloc_parms.dir == TF_DIR_RX) ? "RX" : "TX"); - return rc; +static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src, + struct ulp_blob *blob, + uint8_t *val, + uint32_t val_len, + uint8_t **out_val) +{ + if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) { + if (ulp_blob_pad_push(blob, val_len) < 0) { + BNXT_TF_DBG(ERR, "too large for blob\n"); + return -EINVAL; + } + } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) { + if (ulp_blob_push_encap(blob, val, val_len) < 0) { + BNXT_TF_DBG(ERR, "encap blob push failed\n"); + return -EINVAL; + } + } else if (fld_src == BNXT_ULP_FIELD_SRC_SKIP) { + /* do nothing */ + } else { + if (!ulp_blob_push(blob, val, val_len)) { + BNXT_TF_DBG(ERR, "push of val1 failed\n"); + return -EINVAL; + } } + *out_val = val; + return 0; +} - /* Need to calculate the idx for the result record */ - uint64_t tmpidx = alloc_parms.idx; - - if (atbls->resource_type == TF_TBL_TYPE_EXT) - tmpidx = TF_ACT_REC_OFFSET_2_PTR(alloc_parms.idx); - else - tmpidx = alloc_parms.idx; - - idx = tfp_cpu_to_be_64(tmpidx); +static int32_t +ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms, + enum tf_dir dir, + struct bnxt_ulp_mapper_field_info *fld, + struct ulp_blob *blob, + uint8_t is_key, + const char *name) +{ + uint16_t write_idx = blob->write_idx; + uint8_t *val = NULL, *val1, *val2, *val3; + uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0; + uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0; + uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0; + uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0; + uint64_t value1 = 0, value2 = 0, value3 = 0; + int32_t rc = 0; - /* Store the allocated index for future use in the regfile */ - rc = ulp_regfile_write(parms->regfile, atbls->regfile_wr_idx, idx); - if (!rc) { - BNXT_TF_DBG(ERR, "regfile[%d] write failed\n", - atbls->regfile_wr_idx); - rc = -EINVAL; - goto error; + /* prepare the field source and values */ + switch (fld->field_opc) { + case BNXT_ULP_FIELD_OPC_SRC1: + process_src1 = 1; + break; + case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: + process_src1 = 1; + break; + case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: + case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: + process_src3 = 1; + eval_src3 = 1; + process_src1 = 1; + process_src2 = 1; + eval_src1 = 1; + eval_src2 = 1; + break; + case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: + case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: + case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: + case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: + case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: + case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: + process_src1 = 1; + process_src2 = 1; + eval_src1 = 1; + eval_src2 = 1; + break; + default: + break; } - /* - * The set_tbl_entry API if search is not enabled or searched entry - * is not found. - */ - if (!atbls->srch_b4_alloc || !alloc_parms.hit) { - struct tf_set_tbl_entry_parms set_parm = { 0 }; - uint16_t length; + /* process the src1 opcode */ + if (process_src1) { + if (ulp_mapper_field_src_process(parms, fld->field_src1, + fld->field_opr1, dir, is_key, + fld->field_bit_size, &val1, + &val1_len, &value1)) { + BNXT_TF_DBG(ERR, "fld src1 process failed\n"); + goto error; + } + if (eval_src1) { + if (ulp_mapper_field_buffer_eval(val1, val1_len, + &val1_int)) { + BNXT_TF_DBG(ERR, "fld src1 eval failed\n"); + goto error; + } + } + } - set_parm.dir = atbls->direction; - set_parm.type = atbls->resource_type; - set_parm.idx = alloc_parms.idx; - set_parm.data = ulp_blob_data_get(blob, &length); - set_parm.data_sz_in_bytes = length / 8; + /* for "if then clause" set the correct process */ + if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) { + if (value1) + process_src2 = 1; + else + process_src3 = 1; + } - if (set_parm.type == TF_TBL_TYPE_EXT) - set_parm.tbl_scope_id = tbl_scope_id; + /* process src2 opcode */ + if (process_src2) { + if (ulp_mapper_field_src_process(parms, fld->field_src2, + fld->field_opr2, dir, is_key, + fld->field_bit_size, &val2, + &val2_len, &value2)) { + BNXT_TF_DBG(ERR, "fld src2 process failed\n"); + goto error; + } + if (eval_src2) { + if (ulp_mapper_field_buffer_eval(val2, val2_len, + &val2_int)) { + BNXT_TF_DBG(ERR, "fld src2 eval failed\n"); + goto error; + } + } + } - /* set the table entry */ - rc = tf_set_tbl_entry(parms->tfp, &set_parm); - if (rc) { - BNXT_TF_DBG(ERR, "table[%d][%s][%d] set failed\n", - set_parm.type, - (set_parm.dir == TF_DIR_RX) ? "RX" : "TX", - set_parm.idx); + /* process src3 opcode */ + if (process_src3) { + if (ulp_mapper_field_src_process(parms, fld->field_src3, + fld->field_opr3, dir, is_key, + fld->field_bit_size, &val3, + &val3_len, &value3)) { + BNXT_TF_DBG(ERR, "fld src3 process failed\n"); goto error; } + if (eval_src3) { + if (ulp_mapper_field_buffer_eval(val3, val3_len, + &val3_int)) { + BNXT_TF_DBG(ERR, "fld src3 eval failed\n"); + goto error; + } + } } - /* Link the resource to the flow in the flow db */ - memset(&fid_parms, 0, sizeof(fid_parms)); - fid_parms.direction = atbls->direction; - fid_parms.resource_func = atbls->resource_func; - fid_parms.resource_type = atbls->resource_type; - fid_parms.resource_hndl = alloc_parms.idx; - fid_parms.critical_resource = 0; - - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); - if (rc) { - BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", - rc); + val_len = fld->field_bit_size; + /* process the field opcodes */ + switch (fld->field_opc) { + case BNXT_ULP_FIELD_OPC_SRC1: + rc = ulp_mapper_field_blob_write(fld->field_src1, + blob, val1, val1_len, &val); + val_len = val1_len; + break; + case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: + if (value1) { + rc = ulp_mapper_field_blob_write(fld->field_src2, blob, + val2, val2_len, &val); + val_len = val2_len; + } else { + rc = ulp_mapper_field_blob_write(fld->field_src3, blob, + val3, val3_len, &val); + val_len = val3_len; + } + break; + case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: + case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: + val_int = val1_int + val2_int; + val_int = tfp_cpu_to_be_64(val_int); + val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); + if (!val) + rc = -EINVAL; + break; + case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: + case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: + val_int = val1_int - val2_int; + val_int = tfp_cpu_to_be_64(val_int); + val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); + if (!val) + rc = -EINVAL; + break; + case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: + val_int = val1_int | val2_int; + val_int = tfp_cpu_to_be_64(val_int); + val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); + if (!val) + rc = -EINVAL; + break; + case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: + val_int = val1_int | val2_int | val3_int; + val_int = tfp_cpu_to_be_64(val_int); + val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); + if (!val) + rc = -EINVAL; + break; + case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: + val_int = val1_int & val2_int; + val_int = tfp_cpu_to_be_64(val_int); + val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); + if (!val) + rc = -EINVAL; + break; + case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: + val_int = val1_int & (val2_int | val3_int); + val_int = tfp_cpu_to_be_64(val_int); + val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); + if (!val) + rc = -EINVAL; + break; + case BNXT_ULP_FIELD_OPC_SKIP: + break; + default: + BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc); rc = -EINVAL; - goto error; + break; } - return 0; + if (!rc) { +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + if (fld->field_src1 != BNXT_ULP_FIELD_SRC_ZERO && val_len) + ulp_mapper_field_dump(name, fld, blob, write_idx, val, + val_len); +#endif +#endif + return rc; + } error: - - free_parms.dir = alloc_parms.dir; - free_parms.type = alloc_parms.type; - free_parms.idx = alloc_parms.idx; - - trc = tf_free_tbl_entry(parms->tfp, &free_parms); - if (trc) - BNXT_TF_DBG(ERR, "Failed to free table entry on failure\n"); - - return rc; + BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name, + fld->description, (val) ? write_idx : 0, val_len); + return -EINVAL; } +/* + * Result table process and fill the result blob. + * data [out] - the result blob data + */ static int32_t -ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_class_tbl_info *tbl, - uint64_t flow_id) +ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + struct ulp_blob *data, + const char *name) { - struct ulp_flow_db_res_params fid_parms; - uint32_t vfr_flag, mark, gfid, mark_flag; + struct bnxt_ulp_mapper_field_info *dflds; + uint32_t i = 0, num_flds = 0, encap_flds = 0; + struct ulp_blob encap_blob; int32_t rc = 0; - vfr_flag = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_VFR_FLAG); - if (!(tbl->mark_enable && - (ULP_BITMAP_ISSET(parms->act_bitmap->bits, - BNXT_ULP_ACTION_BIT_MARK) || vfr_flag))) - return rc; /* no need to perform gfid process */ + /* Get the result field list */ + dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, + &encap_flds); + + /* validate the result field list counts */ + if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && + (!num_flds && !encap_flds)) || !dflds || + (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && + (!num_flds || encap_flds))) { + BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n", + num_flds, encap_flds); + return -EINVAL; + } - /* Get the mark id details from action property */ - memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], - sizeof(mark)); - mark = tfp_be_to_cpu_32(mark); + /* process the result fields */ + for (i = 0; i < num_flds; i++) { + rc = ulp_mapper_field_opc_process(parms, tbl->direction, + &dflds[i], data, 0, name); + if (rc) { + BNXT_TF_DBG(ERR, "result field processing failed\n"); + return rc; + } + } + + /* process encap fields if any */ + if (encap_flds) { + uint32_t pad = 0; + /* Initialize the encap blob */ + if (!tbl->record_size && + !parms->device_params->dynamic_sram_en) { + BNXT_TF_DBG(ERR, "Encap tbl record size incorrect\n"); + return -EINVAL; + } + if (!ulp_blob_init(&encap_blob, + ULP_BYTE_2_BITS(tbl->record_size), + parms->device_params->encap_byte_order)) { + BNXT_TF_DBG(ERR, "blob inits failed.\n"); + return -EINVAL; + } + for (; i < encap_flds; i++) { + rc = ulp_mapper_field_opc_process(parms, tbl->direction, + &dflds[i], + &encap_blob, 0, name); + if (rc) { + BNXT_TF_DBG(ERR, + "encap field processing failed\n"); + return rc; + } + } + /* add the dynamic pad push */ + if (parms->device_params->dynamic_sram_en) { + uint16_t rec_s = ULP_BYTE_2_BITS(tbl->record_size); + + (void)ulp_mapper_dyn_tbl_type_get(parms, tbl, + &encap_blob, &rec_s); + pad = rec_s - ulp_blob_data_len_get(&encap_blob); + } else { + pad = ULP_BYTE_2_BITS(tbl->record_size) - + ulp_blob_data_len_get(&encap_blob); + } + if (ulp_blob_pad_push(&encap_blob, pad) < 0) { + BNXT_TF_DBG(ERR, "encap buffer padding failed\n"); + return -EINVAL; + } + + + /* perform the 64 bit byte swap */ + ulp_blob_perform_64B_byte_swap(&encap_blob); + /* Append encap blob to the result blob */ + rc = ulp_blob_buffer_copy(data, &encap_blob); + if (rc) { + BNXT_TF_DBG(ERR, "encap buffer copy failed\n"); + return rc; + } + } +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + BNXT_TF_DBG(DEBUG, "Result dump\n"); + ulp_mapper_blob_dump(data); +#endif +#endif + return rc; +} + +static int32_t +ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + uint64_t flow_id) +{ + struct ulp_flow_db_res_params fid_parms; + uint32_t mark, gfid, mark_flag; + enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; + int32_t rc = 0; + + if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || + !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && + ULP_BITMAP_ISSET(parms->act_bitmap->bits, + BNXT_ULP_ACT_BIT_MARK))) + return rc; /* no need to perform gfid process */ + + /* Get the mark id details from action property */ + memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], + sizeof(mark)); + mark = tfp_be_to_cpu_32(mark); TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid); mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID; - mark_flag |= (vfr_flag) ? BNXT_ULP_MARK_VFR_ID : 0; + rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, gfid, mark); if (rc) { @@ -1039,13 +1721,12 @@ ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, } fid_parms.direction = tbl->direction; fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; - fid_parms.critical_resource = 0; + fid_parms.critical_resource = tbl->critical_resource; fid_parms.resource_type = mark_flag; fid_parms.resource_hndl = gfid; - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); + + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); if (rc) BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); return rc; @@ -1053,17 +1734,18 @@ ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, static int32_t ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_class_tbl_info *tbl) + struct bnxt_ulp_mapper_tbl_info *tbl) { struct ulp_flow_db_res_params fid_parms; - uint32_t vfr_flag, act_idx, mark, mark_flag; + uint32_t act_idx, mark, mark_flag; uint64_t val64; + enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; int32_t rc = 0; - vfr_flag = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_VFR_FLAG); - if (!(tbl->mark_enable && - (ULP_BITMAP_ISSET(parms->act_bitmap->bits, - BNXT_ULP_ACTION_BIT_MARK) || vfr_flag))) + if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || + !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && + ULP_BITMAP_ISSET(parms->act_bitmap->bits, + BNXT_ULP_ACT_BIT_MARK))) return rc; /* no need to perform mark action process */ /* Get the mark id details from action property */ @@ -1072,14 +1754,13 @@ ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, mark = tfp_be_to_cpu_32(mark); if (!ulp_regfile_read(parms->regfile, - BNXT_ULP_REGFILE_INDEX_ACTION_PTR_MAIN, + BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, &val64)) { BNXT_TF_DBG(ERR, "read action ptr main failed\n"); return -EINVAL; } act_idx = tfp_be_to_cpu_64(val64); mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID; - mark_flag |= (vfr_flag) ? BNXT_ULP_MARK_VFR_ID : 0; rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, act_idx, mark); if (rc) { @@ -1088,115 +1769,345 @@ ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, } fid_parms.direction = tbl->direction; fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; - fid_parms.critical_resource = 0; + fid_parms.critical_resource = tbl->critical_resource; + fid_parms.resource_type = mark_flag; + fid_parms.resource_hndl = act_idx; + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); + + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); + if (rc) + BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); + return rc; +} + +static int32_t +ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + struct ulp_flow_db_res_params fid_parms; + uint32_t act_idx, mark, mark_flag; + uint64_t val64; + enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; + int32_t rc = 0; + + if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || + mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION) + return rc; /* no need to perform mark action process */ + + /* Get the mark id details from the computed field of dev port id */ + mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID); + + /* Get the main action pointer */ + if (!ulp_regfile_read(parms->regfile, + BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, + &val64)) { + BNXT_TF_DBG(ERR, "read action ptr main failed\n"); + return -EINVAL; + } + act_idx = tfp_be_to_cpu_64(val64); + + /* Set the mark flag to local fid and vfr flag */ + mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; + + rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, + act_idx, mark); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); + return rc; + } + fid_parms.direction = tbl->direction; + fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; + fid_parms.critical_resource = tbl->critical_resource; fid_parms.resource_type = mark_flag; fid_parms.resource_hndl = act_idx; - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); + + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); if (rc) BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); return rc; } +/* Tcam table scan the identifier list and allocate each identifier */ +static int32_t +ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + struct bnxt_ulp_mapper_ident_info *idents; + uint32_t num_idents; + uint32_t i; + + idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); + for (i = 0; i < num_idents; i++) { + if (ulp_mapper_ident_process(parms, tbl, + &idents[i], NULL)) + return -EINVAL; + } + return 0; +} + /* - * Function to process the action Info. Iterate through the list - * action info templates and process it. + * Tcam table scan the identifier list and extract the identifier from + * the result blob. */ static int32_t -ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_act_tbl_info *tbl) -{ - struct ulp_blob blob; - struct bnxt_ulp_mapper_result_field_info *flds, *fld; - uint32_t num_flds = 0; - uint32_t encap_flds = 0; - uint32_t i; - int32_t rc; - uint16_t bit_size; - - if (!tbl || !parms->act_prop || !parms->act_bitmap || !parms->regfile) +ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + struct ulp_blob *data) +{ + struct bnxt_ulp_mapper_ident_info *idents; + uint32_t num_idents = 0, i; + int32_t rc = 0; + + /* + * Extract the listed identifiers from the result field, + * no need to allocate them. + */ + idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); + for (i = 0; i < num_idents; i++) { + rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data); + if (rc) { + BNXT_TF_DBG(ERR, "Error in identifier extraction\n"); + return rc; + } + } + return rc; +} + +/* Internal function to write the tcam entry */ +static int32_t +ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + struct ulp_blob *key, + struct ulp_blob *mask, + struct ulp_blob *data, + uint16_t idx) +{ + struct tf_set_tcam_entry_parms sparms = { 0 }; + struct tf *tfp; + uint16_t tmplen; + int32_t rc; + + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); + if (!tfp) { + BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); return -EINVAL; + } - /* use the max size if encap is enabled */ - if (tbl->encap_num_fields) - bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; - else - bit_size = tbl->result_bit_size; - if (!ulp_blob_init(&blob, bit_size, parms->order)) { - BNXT_TF_DBG(ERR, "action blob init failed\n"); + sparms.dir = tbl->direction; + sparms.tcam_tbl_type = tbl->resource_type; + sparms.idx = idx; + sparms.key = ulp_blob_data_get(key, &tmplen); + sparms.key_sz_in_bits = tmplen; + sparms.mask = ulp_blob_data_get(mask, &tmplen); + sparms.result = ulp_blob_data_get(data, &tmplen); + sparms.result_sz_in_bits = tmplen; + if (tf_set_tcam_entry(tfp, &sparms)) { + BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n", + tf_tcam_tbl_2_str(sparms.tcam_tbl_type), + tf_dir_2_str(sparms.dir), sparms.idx); + return -EIO; + } + BNXT_TF_INF("tcam[%s][%s][%x] write success.\n", + tf_tcam_tbl_2_str(sparms.tcam_tbl_type), + tf_dir_2_str(sparms.dir), sparms.idx); + + /* Mark action */ + rc = ulp_mapper_mark_act_ptr_process(parms, tbl); + if (rc) { + BNXT_TF_DBG(ERR, "failed mark action processing\n"); + return rc; + } + +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_tcam_entry_dump("TCAM", idx, tbl, key, mask, data); +#endif +#endif + return rc; +} + +/* + * internal function to post process key/mask blobs for dynamic pad WC tcam tbl + * + * parms [in] The mappers parms with data related to the flow. + * + * key [in] The original key to be transformed + * + * mask [in] The original mask to be transformed + * + * tkey [in/out] The transformed key + * + * tmask [in/out] The transformed mask + * + * returns zero on success, non-zero on failure + */ +static uint32_t +ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms, + struct ulp_blob *key, + struct ulp_blob *mask, + struct ulp_blob *tkey, + struct ulp_blob *tmask) +{ + uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset; + uint32_t cword, i, rc; + int32_t pad; + uint8_t *val; + + slice_width = dparms->wc_slice_width; + clen = dparms->wc_ctl_size_bits; + max_slices = dparms->wc_max_slices; + blen = ulp_blob_data_len_get(key); + + /* Get the length of the key based on number of slices and width */ + num_slices = 1; + tlen = slice_width; + while (tlen < blen && + num_slices <= max_slices) { + num_slices = num_slices << 1; + tlen = tlen << 1; + } + + if (num_slices > max_slices) { + BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen); + return -EINVAL; + } + + /* The key/mask may not be on a natural slice boundary, pad it */ + pad = tlen - blen; + if (ulp_blob_pad_push(key, pad) < 0 || + ulp_blob_pad_push(mask, pad) < 0) { + BNXT_TF_DBG(ERR, "Unable to pad key/mask\n"); return -EINVAL; } - flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, &encap_flds); - if (!flds || !num_flds) { - BNXT_TF_DBG(ERR, "Template undefined for action\n"); + /* The new length accounts for the ctrl word length and num slices */ + tlen = tlen + clen * num_slices; + if (!ulp_blob_init(tkey, tlen, key->byte_order) || + !ulp_blob_init(tmask, tlen, mask->byte_order)) { + BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n"); return -EINVAL; } - for (i = 0; i < (num_flds + encap_flds); i++) { - fld = &flds[i]; - rc = ulp_mapper_result_field_process(parms, - tbl->direction, - fld, - &blob, - "Action"); + /* Build the transformed key/mask */ + cword = dparms->wc_mode_list[num_slices - 1]; + cword = tfp_cpu_to_be_32(cword); + offset = 0; + for (i = 0; i < num_slices; i++) { + val = ulp_blob_push_32(tkey, &cword, clen); + if (!val) { + BNXT_TF_DBG(ERR, "Key ctrl word push failed\n"); + return -EINVAL; + } + val = ulp_blob_push_32(tmask, &cword, clen); + if (!val) { + BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n"); + return -EINVAL; + } + rc = ulp_blob_append(tkey, key, offset, slice_width); if (rc) { - BNXT_TF_DBG(ERR, "Action field failed\n"); + BNXT_TF_DBG(ERR, "Key blob append failed\n"); return rc; } - /* set the swap index if 64 bit swap is enabled */ - if (parms->encap_byte_swap && encap_flds) { - if ((i + 1) == num_flds) - ulp_blob_encap_swap_idx_set(&blob); - /* if 64 bit swap is enabled perform the 64bit swap */ - if ((i + 1) == (num_flds + encap_flds)) - ulp_blob_perform_encap_swap(&blob); + rc = ulp_blob_append(tmask, mask, offset, slice_width); + if (rc) { + BNXT_TF_DBG(ERR, "Mask blob append failed\n"); + return rc; } + offset += slice_width; } - rc = ulp_mapper_action_alloc_and_set(parms, &blob); - return rc; + /* The key/mask are byte reversed on every 4 byte chunk */ + ulp_blob_perform_byte_reverse(tkey, 4); + ulp_blob_perform_byte_reverse(tmask, 4); + + return 0; +} + +/* internal function to post process the key/mask blobs for wildcard tcam tbl */ +static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob) +{ + ulp_blob_perform_64B_word_swap(blob); + ulp_blob_perform_64B_byte_swap(blob); +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + BNXT_TF_DBG(INFO, "Dump after wc tcam post process\n"); + ulp_mapper_blob_dump(blob); +#endif +#endif +} + +static int32_t ulp_mapper_tcam_is_wc_tcam(struct bnxt_ulp_mapper_tbl_info *tbl) +{ + if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM || + tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH || + tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW) + return 1; + return 0; } static int32_t ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_class_tbl_info *tbl) + struct bnxt_ulp_mapper_tbl_info *tbl) { - struct bnxt_ulp_mapper_class_key_field_info *kflds; - struct ulp_blob key, mask, data; + struct bnxt_ulp_mapper_key_info *kflds; + struct ulp_blob okey, omask, data, update_data; + struct ulp_blob tkey, tmask; /* transform key and mask */ + struct ulp_blob *key, *mask; uint32_t i, num_kflds; struct tf *tfp; int32_t rc, trc; + struct bnxt_ulp_device_params *dparms = parms->device_params; struct tf_alloc_tcam_entry_parms aparms = { 0 }; - struct tf_set_tcam_entry_parms sparms = { 0 }; + struct tf_search_tcam_entry_parms searchparms = { 0 }; struct ulp_flow_db_res_params fid_parms = { 0 }; struct tf_free_tcam_entry_parms free_parms = { 0 }; uint32_t hit = 0; uint16_t tmplen = 0; - - /* Skip this if was handled by the cache. */ - if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) { - parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; + uint16_t idx; + enum bnxt_ulp_byte_order key_byte_order; + + /* Set the key and mask to the original key and mask. */ + key = &okey; + mask = &omask; + + /* Skip this if table opcode is NOP */ + if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED || + tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) { + BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n", + tbl->tbl_opcode); return 0; } - tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); if (!tfp) { BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); return -EINVAL; } - kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); + /* If only allocation of identifier then perform and exit */ + if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT) { + rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); + return rc; + } + + kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); if (!kflds || !num_kflds) { BNXT_TF_DBG(ERR, "Failed to get key fields\n"); return -EINVAL; } - if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order) || - !ulp_blob_init(&mask, tbl->key_bit_size, parms->order) || - !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) { + if (ulp_mapper_tcam_is_wc_tcam(tbl)) + key_byte_order = dparms->wc_key_byte_order; + else + key_byte_order = dparms->key_byte_order; + + if (!ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) || + !ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) || + !ulp_blob_init(&data, tbl->result_bit_size, + dparms->result_byte_order) || + !ulp_blob_init(&update_data, tbl->result_bit_size, + dparms->result_byte_order)) { BNXT_TF_DBG(ERR, "blob inits failed.\n"); return -EINVAL; } @@ -1208,212 +2119,204 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, */ for (i = 0; i < num_kflds; i++) { /* Setup the key */ - rc = ulp_mapper_keymask_field_process(parms, tbl->direction, - &kflds[i], - &key, 1, "TCAM Key"); + rc = ulp_mapper_field_opc_process(parms, tbl->direction, + &kflds[i].field_info_spec, + key, 1, "TCAM Key"); if (rc) { - BNXT_TF_DBG(ERR, "Key field set failed.\n"); + BNXT_TF_DBG(ERR, "Key field set failed %s\n", + kflds[i].field_info_spec.description); return rc; } /* Setup the mask */ - rc = ulp_mapper_keymask_field_process(parms, tbl->direction, - &kflds[i], - &mask, 0, "TCAM Mask"); + rc = ulp_mapper_field_opc_process(parms, tbl->direction, + &kflds[i].field_info_mask, + mask, 0, "TCAM Mask"); if (rc) { - BNXT_TF_DBG(ERR, "Mask field set failed.\n"); + BNXT_TF_DBG(ERR, "Mask field set failed %s\n", + kflds[i].field_info_mask.description); return rc; } } - aparms.dir = tbl->direction; - aparms.tcam_tbl_type = tbl->resource_type; - aparms.search_enable = tbl->srch_b4_alloc; - aparms.key_sz_in_bits = tbl->key_bit_size; - aparms.key = ulp_blob_data_get(&key, &tmplen); - if (tbl->key_bit_size != tmplen) { - BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n", - tmplen, tbl->key_bit_size); - return -EINVAL; - } - - aparms.mask = ulp_blob_data_get(&mask, &tmplen); - if (tbl->key_bit_size != tmplen) { - BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n", - tmplen, tbl->key_bit_size); - return -EINVAL; - } - - aparms.priority = tbl->priority; - - /* - * All failures after this succeeds require the entry to be freed. - * cannot return directly on failure, but needs to goto error - */ - rc = tf_alloc_tcam_entry(tfp, &aparms); - if (rc) { - BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); - return rc; - } - - hit = aparms.hit; - - /* Build the result */ - if (!tbl->srch_b4_alloc || !hit) { - struct bnxt_ulp_mapper_result_field_info *dflds; - struct bnxt_ulp_mapper_ident_info *idents; - uint32_t num_dflds, num_idents; - - /* - * Since the cache entry is responsible for allocating - * identifiers when in use, allocate the identifiers only - * during normal processing. - */ - if (parms->tcam_tbl_opc == - BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) { - idents = ulp_mapper_ident_fields_get(tbl, &num_idents); - - for (i = 0; i < num_idents; i++) { - rc = ulp_mapper_ident_process(parms, tbl, - &idents[i], NULL); - /* Already logged the error, just return */ - if (rc) - goto error; + /* For wild card tcam perform the post process to swap the blob */ + if (ulp_mapper_tcam_is_wc_tcam(tbl)) { + if (dparms->dynamic_pad_en) { + /* Sets up the slices for writing to the WC TCAM */ + rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms, + key, mask, + &tkey, + &tmask); + if (rc) { + BNXT_TF_DBG(ERR, + "Failed to post proc WC entry.\n"); + return rc; } + /* Now need to use the transform Key/Mask */ + key = &tkey; + mask = &tmask; + } else { + ulp_mapper_wc_tcam_tbl_post_process(key); + ulp_mapper_wc_tcam_tbl_post_process(mask); } - /* Create the result data blob */ - dflds = ulp_mapper_result_fields_get(tbl, &num_dflds); - if (!dflds || !num_dflds) { - BNXT_TF_DBG(ERR, "Failed to get data fields.\n"); - rc = -EINVAL; - goto error; - } + } - for (i = 0; i < num_dflds; i++) { - rc = ulp_mapper_result_field_process(parms, - tbl->direction, - &dflds[i], - &data, - "TCAM Result"); - if (rc) { - BNXT_TF_DBG(ERR, "Failed to set data fields\n"); - goto error; - } + if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { + /* allocate the tcam index */ + aparms.dir = tbl->direction; + aparms.tcam_tbl_type = tbl->resource_type; + aparms.key = ulp_blob_data_get(key, &tmplen); + aparms.key_sz_in_bits = tmplen; + aparms.mask = ulp_blob_data_get(mask, &tmplen); + + /* calculate the entry priority */ + rc = ulp_mapper_priority_opc_process(parms, tbl, + &aparms.priority); + if (rc) { + BNXT_TF_DBG(ERR, "entry priority process failed\n"); + return rc; } - sparms.dir = aparms.dir; - sparms.tcam_tbl_type = aparms.tcam_tbl_type; - sparms.idx = aparms.idx; - /* Already verified the key/mask lengths */ - sparms.key = ulp_blob_data_get(&key, &tmplen); - sparms.mask = ulp_blob_data_get(&mask, &tmplen); - sparms.key_sz_in_bits = tbl->key_bit_size; - sparms.result = ulp_blob_data_get(&data, &tmplen); - - if (tbl->result_bit_size != tmplen) { - BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n", - tmplen, tbl->result_bit_size); - rc = -EINVAL; - goto error; + rc = tf_alloc_tcam_entry(tfp, &aparms); + if (rc) { + BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); + return rc; + } + idx = aparms.idx; + hit = aparms.hit; + } else { + /* + * Searching before allocation to see if we already have an + * entry. This allows re-use of a constrained resource. + */ + searchparms.dir = tbl->direction; + searchparms.tcam_tbl_type = tbl->resource_type; + searchparms.key = ulp_blob_data_get(key, &tmplen); + searchparms.key_sz_in_bits = tbl->key_bit_size; + searchparms.mask = ulp_blob_data_get(mask, &tmplen); + searchparms.alloc = 1; + searchparms.result = ulp_blob_data_get(&data, &tmplen); + searchparms.result_sz_in_bits = tbl->result_bit_size; + + /* calculate the entry priority */ + rc = ulp_mapper_priority_opc_process(parms, tbl, + &searchparms.priority); + if (rc) { + BNXT_TF_DBG(ERR, "entry priority process failed\n"); + return rc; } - sparms.result_sz_in_bits = tbl->result_bit_size; - rc = tf_set_tcam_entry(tfp, &sparms); + rc = tf_search_tcam_entry(tfp, &searchparms); if (rc) { - BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n", - sparms.tcam_tbl_type, - (sparms.dir == TF_DIR_RX) ? "RX" : "TX", - sparms.idx); - goto error; + BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc); + return rc; } - /* Update cache with TCAM index if the was cache allocated. */ - if (parms->tcam_tbl_opc == - BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) { - if (!parms->cache_ptr) { - BNXT_TF_DBG(ERR, "Unable to update cache"); - rc = -EINVAL; - goto error; - } - parms->cache_ptr->tcam_idx = aparms.idx; + /* Successful search, check the result */ + if (searchparms.search_status == REJECT) { + BNXT_TF_DBG(ERR, "tcam alloc rejected\n"); + return -ENOMEM; } + idx = searchparms.idx; + hit = searchparms.hit; + } - } else { - BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n"); + /* Write the tcam index into the regfile*/ + if (ulp_regfile_write(parms->regfile, tbl->tbl_operand, + (uint64_t)tfp_cpu_to_be_64(idx))) { + BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", + tbl->tbl_operand); rc = -EINVAL; + /* Need to free the tcam idx, so goto error */ goto error; } - /* - * Only link the entry to the flow db in the event that cache was not - * used. - */ - if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) { - fid_parms.direction = tbl->direction; - fid_parms.resource_func = tbl->resource_func; - fid_parms.resource_type = tbl->resource_type; - fid_parms.critical_resource = tbl->critical_resource; - fid_parms.resource_hndl = aparms.idx; - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); - if (rc) { - BNXT_TF_DBG(ERR, - "Failed to link resource to flow rc = %d\n", - rc); - /* Need to free the identifier, so goto error */ - goto error; - } + /* if it is miss then it is same as no search before alloc */ + if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { + /*Scan identifier list, allocate identifier and update regfile*/ + rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); + /* Create the result blob */ + if (!rc) + rc = ulp_mapper_tbl_result_build(parms, tbl, &data, + "TCAM Result"); + /* write the tcam entry */ + if (!rc) + rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key, + mask, &data, idx); } else { - /* - * Reset the tcam table opcode to normal in case the next tcam - * entry does not use cache. - */ - parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; - parms->cache_ptr = NULL; + /*Scan identifier list, extract identifier and update regfile*/ + rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); + } + if (rc) + goto error; + + /* Add the tcam index to the flow database */ + fid_parms.direction = tbl->direction; + fid_parms.resource_func = tbl->resource_func; + fid_parms.resource_type = tbl->resource_type; + fid_parms.critical_resource = tbl->critical_resource; + fid_parms.resource_hndl = idx; + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); + + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", + rc); + /* Need to free the identifier, so goto error */ + goto error; } return 0; error: - parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; free_parms.dir = tbl->direction; free_parms.tcam_tbl_type = tbl->resource_type; - free_parms.idx = aparms.idx; + free_parms.idx = idx; trc = tf_free_tcam_entry(tfp, &free_parms); if (trc) BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", - tbl->resource_type, tbl->direction, aparms.idx); - + tbl->resource_type, tbl->direction, idx); return rc; } static int32_t ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_class_tbl_info *tbl) + struct bnxt_ulp_mapper_tbl_info *tbl) { - struct bnxt_ulp_mapper_class_key_field_info *kflds; - struct bnxt_ulp_mapper_result_field_info *dflds; + struct bnxt_ulp_mapper_key_info *kflds; struct ulp_blob key, data; - uint32_t i, num_kflds, num_dflds; + uint32_t i, num_kflds; uint16_t tmplen; - struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); + struct tf *tfp; struct ulp_flow_db_res_params fid_parms = { 0 }; struct tf_insert_em_entry_parms iparms = { 0 }; struct tf_delete_em_entry_parms free_parms = { 0 }; + enum bnxt_ulp_flow_mem_type mtype; + struct bnxt_ulp_device_params *dparms = parms->device_params; int32_t trc; int32_t rc = 0; + int32_t pad = 0; + enum bnxt_ulp_byte_order key_order, res_order; + + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); + rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n"); + return -EINVAL; + } - kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); + kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); if (!kflds || !num_kflds) { BNXT_TF_DBG(ERR, "Failed to get key fields\n"); return -EINVAL; } + key_order = dparms->em_byte_order; + res_order = dparms->em_byte_order; + /* Initialize the key/result blobs */ - if (!ulp_blob_init(&key, tbl->blob_key_bit_size, parms->order) || - !ulp_blob_init(&data, tbl->result_bit_size, parms->order)) { + if (!ulp_blob_init(&key, tbl->blob_key_bit_size, key_order) || + !ulp_blob_init(&data, tbl->result_bit_size, res_order)) { BNXT_TF_DBG(ERR, "blob inits failed.\n"); return -EINVAL; } @@ -1421,41 +2324,76 @@ ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, /* create the key */ for (i = 0; i < num_kflds; i++) { /* Setup the key */ - rc = ulp_mapper_keymask_field_process(parms, tbl->direction, - &kflds[i], - &key, 1, "EM Key"); + rc = ulp_mapper_field_opc_process(parms, tbl->direction, + &kflds[i].field_info_spec, + &key, 1, "EM Key"); if (rc) { BNXT_TF_DBG(ERR, "Key field set failed.\n"); return rc; } } - /* - * TBD: Normally should process identifiers in case of using recycle or - * loopback. Not supporting recycle for now. - */ + /* if dynamic padding is enabled then add padding to result data */ + if (dparms->dynamic_pad_en) { + /* add padding to make sure key is at byte boundary */ + ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS); - /* Create the result data blob */ - dflds = ulp_mapper_result_fields_get(tbl, &num_dflds); - if (!dflds || !num_dflds) { - BNXT_TF_DBG(ERR, "Failed to get data fields.\n"); - return -EINVAL; + /* add the pad */ + pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits; + if (pad < 0) { + BNXT_TF_DBG(ERR, "Invalid em blk size and align\n"); + return -EINVAL; + } + ulp_blob_pad_push(&data, (uint32_t)pad); } - for (i = 0; i < num_dflds; i++) { - struct bnxt_ulp_mapper_result_field_info *fld; - - fld = &dflds[i]; - - rc = ulp_mapper_result_field_process(parms, - tbl->direction, - fld, - &data, - "EM Result"); - if (rc) { - BNXT_TF_DBG(ERR, "Failed to set data fields.\n"); - return rc; + /* Create the result data blob */ + rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result"); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); + return rc; + } +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_result_dump("EM Result", tbl, &data); +#endif +#endif + if (dparms->dynamic_pad_en) { + uint32_t abits = dparms->em_blk_align_bits; + + /* when dynamic padding is enabled merge result + key */ + rc = ulp_blob_block_merge(&data, &key, abits, pad); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to merge the result blob\n"); + return rc; + } + + /* add padding to make sure merged result is at slice boundary*/ + ulp_blob_pad_align(&data, abits); + + ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits)); +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_result_dump("EM Merged Result", tbl, &data); +#endif +#endif + } + + /* do the transpose for the internal EM keys */ + if (tbl->resource_type == TF_MEM_INTERNAL) { + if (dparms->em_key_align_bytes) { + int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes); + + tmplen = ulp_blob_data_len_get(&key); + ulp_blob_pad_push(&key, b - tmplen); } + tmplen = ulp_blob_data_len_get(&key); + ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen)); +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_result_dump("EM Key Transpose", tbl, &key); +#endif +#endif } rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, @@ -1475,7 +2413,10 @@ ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, iparms.key = ulp_blob_data_get(&key, &tmplen); iparms.key_sz_in_bits = tbl->key_bit_size; iparms.em_record = ulp_blob_data_get(&data, &tmplen); - iparms.em_record_sz_in_bits = tbl->result_bit_size; + if (tbl->result_bit_size) + iparms.em_record_sz_in_bits = tbl->result_bit_size; + else + iparms.em_record_sz_in_bits = tmplen; rc = tf_insert_em_entry(tfp, &iparms); if (rc) { @@ -1483,11 +2424,17 @@ ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, return rc; } +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_em_dump("EM", &key, &data, &iparms); + /* tf_dump_tables(tfp, iparms.tbl_scope_id); */ +#endif +#endif /* Mark action process */ - if (parms->device_params->global_fid_enable && + if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && tbl->resource_type == TF_MEM_EXTERNAL) rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); - else if (!parms->device_params->global_fid_enable && + else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && tbl->resource_type == TF_MEM_INTERNAL) rc = ulp_mapper_mark_act_ptr_process(parms, tbl); if (rc) { @@ -1503,10 +2450,7 @@ ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, fid_parms.critical_resource = tbl->critical_resource; fid_parms.resource_hndl = iparms.flow_handle; - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); if (rc) { BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); @@ -1530,120 +2474,304 @@ error: static int32_t ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_class_tbl_info *tbl) + struct bnxt_ulp_mapper_tbl_info *tbl) { - struct bnxt_ulp_mapper_result_field_info *flds; - struct ulp_flow_db_res_params fid_parms; + struct ulp_flow_db_res_params fid_parms; struct ulp_blob data; - uint64_t idx; + uint64_t regval = 0; uint16_t tmplen; - uint32_t i, num_flds; + uint32_t index; int32_t rc = 0, trc = 0; - struct tf_alloc_tbl_entry_parms aparms = { 0 }; - struct tf_set_tbl_entry_parms sparms = { 0 }; - struct tf_free_tbl_entry_parms free_parms = { 0 }; + struct tf_alloc_tbl_entry_parms aparms = { 0 }; + struct tf_set_tbl_entry_parms sparms = { 0 }; + struct tf_get_tbl_entry_parms gparms = { 0 }; + struct tf_free_tbl_entry_parms free_parms = { 0 }; uint32_t tbl_scope_id; - struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); - - bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); - - if (!ulp_blob_init(&data, tbl->result_bit_size, parms->order)) { - BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); + struct tf *tfp; + struct bnxt_ulp_glb_resource_info glb_res = { 0 }; + uint16_t bit_size; + bool alloc = false; + bool write = false; + bool global = false; + uint64_t act_rec_size; + bool shared = false; + enum tf_tbl_type tbl_type = tbl->resource_type; + + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); + /* compute the blob size */ + bit_size = ulp_mapper_dyn_blob_size_get(parms, tbl); + + /* Initialize the blob data */ + if (!ulp_blob_init(&data, bit_size, + parms->device_params->result_byte_order)) { + BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n"); return -EINVAL; } - flds = ulp_mapper_result_fields_get(tbl, &num_flds); - if (!flds || !num_flds) { - BNXT_TF_DBG(ERR, "Template undefined for action\n"); + /* Get the scope id first */ + rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); + return rc; + } + + switch (tbl->tbl_opcode) { + case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE: + alloc = true; + break; + case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE: + /* + * Build the entry, alloc an index, write the table, and store + * the data in the regfile. + */ + alloc = true; + write = true; + break; + case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE: + /* + * get the index to write to from the regfile and then write + * the table entry. + */ + if (!ulp_regfile_read(parms->regfile, + tbl->tbl_operand, + ®val)) { + BNXT_TF_DBG(ERR, + "Failed to get tbl idx from regfile[%d].\n", + tbl->tbl_operand); + return -EINVAL; + } + index = tfp_be_to_cpu_64(regval); + /* For external, we need to reverse shift */ + if (tbl->resource_type == TF_TBL_TYPE_EXT) + index = TF_ACT_REC_PTR_2_OFFSET(index); + + write = true; + break; + case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE: + /* + * Build the entry, alloc an index, write the table, and store + * the data in the global regfile. + */ + alloc = true; + global = true; + write = true; + glb_res.direction = tbl->direction; + glb_res.resource_func = tbl->resource_func; + glb_res.resource_type = tbl->resource_type; + glb_res.glb_regfile_index = tbl->tbl_operand; + break; + case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE: + if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) { + BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n"); + return -EINVAL; + } + /* + * get the index to write to from the global regfile and then + * write the table. + */ + if (ulp_mapper_glb_resource_read(parms->mapper_data, + tbl->direction, + tbl->tbl_operand, + ®val, &shared)) { + BNXT_TF_DBG(ERR, + "Failed to get tbl idx from Glb RF[%d].\n", + tbl->tbl_operand); + return -EINVAL; + } + index = tfp_be_to_cpu_64(regval); + /* For external, we need to reverse shift */ + if (tbl->resource_type == TF_TBL_TYPE_EXT) + index = TF_ACT_REC_PTR_2_OFFSET(index); + write = true; + break; + case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE: + /* + * The read is different from the rest and can be handled here + * instead of trying to use common code. Simply read the table + * with the index from the regfile, scan and store the + * identifiers, and return. + */ + if (tbl->resource_type == TF_TBL_TYPE_EXT) { + /* Not currently supporting with EXT */ + BNXT_TF_DBG(ERR, + "Ext Table Read Opcode not supported.\n"); + return -EINVAL; + } + if (!ulp_regfile_read(parms->regfile, + tbl->tbl_operand, ®val)) { + BNXT_TF_DBG(ERR, + "Failed to get tbl idx from regfile[%d]\n", + tbl->tbl_operand); + return -EINVAL; + } + index = tfp_be_to_cpu_64(regval); + gparms.dir = tbl->direction; + gparms.type = tbl->resource_type; + gparms.data = ulp_blob_data_get(&data, &tmplen); + gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); + gparms.idx = index; + rc = tf_get_tbl_entry(tfp, &gparms); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n", + tbl->resource_type, index); + return rc; + } + /* + * Scan the fields in the entry and push them into the regfile. + */ + rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, + gparms.data, + gparms.data_sz_in_bytes, + data.byte_order); + if (rc) { + BNXT_TF_DBG(ERR, + "Failed to get flds on tbl read rc=%d\n", + rc); + return rc; + } + return 0; + default: + BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n", + tbl->tbl_opcode); return -EINVAL; } - for (i = 0; i < num_flds; i++) { - rc = ulp_mapper_result_field_process(parms, - tbl->direction, - &flds[i], - &data, - "Indexed Result"); + if (write) { + /* Get the result fields list */ + rc = ulp_mapper_tbl_result_build(parms, + tbl, + &data, + "Indexed Result"); if (rc) { - BNXT_TF_DBG(ERR, "data field failed\n"); + BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); return rc; } } - aparms.dir = tbl->direction; - aparms.type = tbl->resource_type; - aparms.search_enable = tbl->srch_b4_alloc; - aparms.result = ulp_blob_data_get(&data, &tmplen); - aparms.result_sz_in_bytes = ULP_SZ_BITS2BYTES(tbl->result_bit_size); - aparms.tbl_scope_id = tbl_scope_id; + if (alloc) { + aparms.dir = tbl->direction; + tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl, + &data, &tmplen); + aparms.type = tbl_type; + aparms.tbl_scope_id = tbl_scope_id; - /* All failures after the alloc succeeds require a free */ - rc = tf_alloc_tbl_entry(tfp, &aparms); - if (rc) { - BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n", - tbl->resource_type, - (tbl->direction == TF_DIR_RX) ? "RX" : "TX", - rc); - return rc; - } + /* All failures after the alloc succeeds require a free */ + rc = tf_alloc_tbl_entry(tfp, &aparms); + if (rc) { + BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", + tf_tbl_type_2_str(aparms.type), + tf_dir_2_str(tbl->direction), rc); + return rc; + } + index = aparms.idx; - /* Always storing values in Regfile in BE */ - idx = tfp_cpu_to_be_64(aparms.idx); - rc = ulp_regfile_write(parms->regfile, tbl->regfile_wr_idx, idx); - if (!rc) { - BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", - tbl->regfile_wr_idx); - goto error; - } + /* + * Store the index in the regfile since we either allocated it + * or it was a hit. + * + * Calculate the idx for the result record, for external EM the + * offset needs to be shifted accordingly. + * If external non-inline table types are used then need to + * revisit this logic. + */ + if (tbl->resource_type == TF_TBL_TYPE_EXT) + regval = TF_ACT_REC_OFFSET_2_PTR(index); + else + regval = index; + regval = tfp_cpu_to_be_64(regval); - if (!tbl->srch_b4_alloc) { - sparms.dir = tbl->direction; - sparms.type = tbl->resource_type; - sparms.data = ulp_blob_data_get(&data, &tmplen); - sparms.data_sz_in_bytes = - ULP_SZ_BITS2BYTES(tbl->result_bit_size); - sparms.idx = aparms.idx; - sparms.tbl_scope_id = tbl_scope_id; + if (global) { + /* + * Shared resources are never allocated through this + * method, so the shared flag is always false. + */ + rc = ulp_mapper_glb_resource_write(parms->mapper_data, + &glb_res, regval, + false); + } else { + rc = ulp_regfile_write(parms->regfile, + tbl->tbl_operand, regval); + } + if (rc) { + BNXT_TF_DBG(ERR, + "Failed to write %s regfile[%d] rc=%d\n", + (global) ? "global" : "reg", + tbl->tbl_operand, rc); + goto error; + } + } + if (write) { + sparms.dir = tbl->direction; + sparms.data = ulp_blob_data_get(&data, &tmplen); + tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl, &data, + &tmplen); + sparms.type = tbl_type; + sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); + sparms.idx = index; + sparms.tbl_scope_id = tbl_scope_id; + if (shared) + tfp = bnxt_ulp_cntxt_shared_tfp_get(parms->ulp_ctx); rc = tf_set_tbl_entry(tfp, &sparms); if (rc) { - BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n", - tbl->resource_type, - (tbl->direction == TF_DIR_RX) ? "RX" : "TX", - sparms.idx, - rc); - + BNXT_TF_DBG(ERR, + "Index table[%s][%s][%x] write fail rc=%d\n", + tf_tbl_type_2_str(sparms.type), + tf_dir_2_str(sparms.dir), + sparms.idx, rc); goto error; } + BNXT_TF_INF("Index table[%s][%s][%x] write successful.\n", + tf_tbl_type_2_str(sparms.type), + tf_dir_2_str(sparms.dir), sparms.idx); + + /* Calculate action record size */ + if (tbl->resource_type == TF_TBL_TYPE_EXT) { + act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16; + act_rec_size--; + if (ulp_regfile_write(parms->regfile, + BNXT_ULP_RF_IDX_ACTION_REC_SIZE, + tfp_cpu_to_be_64(act_rec_size))) + BNXT_TF_DBG(ERR, + "Failed write the act rec size\n"); + } } /* Link the resource to the flow in the flow db */ memset(&fid_parms, 0, sizeof(fid_parms)); fid_parms.direction = tbl->direction; fid_parms.resource_func = tbl->resource_func; - fid_parms.resource_type = tbl->resource_type; - fid_parms.resource_hndl = aparms.idx; - fid_parms.critical_resource = 0; + fid_parms.resource_type = tbl_type; + fid_parms.resource_sub_type = tbl->resource_sub_type; + fid_parms.resource_hndl = index; + fid_parms.critical_resource = tbl->critical_resource; + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); if (rc) { BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", rc); goto error; } + /* Perform the VF rep action */ + rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); + goto error; + } return rc; error: + /* Shared resources are not freed */ + if (shared) + return rc; /* * Free the allocated resource since we failed to either * write to the entry or link the flow */ free_parms.dir = tbl->direction; - free_parms.type = tbl->resource_type; - free_parms.idx = aparms.idx; + free_parms.type = tbl_type; + free_parms.idx = index; free_parms.tbl_scope_id = tbl_scope_id; trc = tf_free_tbl_entry(tfp, &free_parms); @@ -1654,234 +2782,1012 @@ error: } static int32_t -ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms, - struct bnxt_ulp_mapper_class_tbl_info *tbl) +ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + struct ulp_blob data, res_blob; + uint64_t idx; + uint16_t tmplen; + int32_t rc = 0; + struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; + struct tf_get_if_tbl_entry_parms get_parms = { 0 }; + struct tf *tfp; + enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode; + uint32_t res_size; + + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); + /* Initialize the blob data */ + if (!ulp_blob_init(&data, tbl->result_bit_size, + parms->device_params->result_byte_order)) { + BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); + return -EINVAL; + } + + /* create the result blob */ + rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result"); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); + return rc; + } + + /* Get the index details */ + switch (if_opc) { + case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD: + idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); + break; + case BNXT_ULP_IF_TBL_OPC_WR_REGFILE: + if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", + tbl->tbl_operand); + return -EINVAL; + } + idx = tfp_be_to_cpu_64(idx); + break; + case BNXT_ULP_IF_TBL_OPC_WR_CONST: + idx = tbl->tbl_operand; + break; + case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD: + /* Initialize the result blob */ + if (!ulp_blob_init(&res_blob, tbl->result_bit_size, + parms->device_params->result_byte_order)) { + BNXT_TF_DBG(ERR, "Failed initial result blob\n"); + return -EINVAL; + } + + /* read the interface table */ + idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); + res_size = ULP_BITS_2_BYTE(tbl->result_bit_size); + get_parms.dir = tbl->direction; + get_parms.type = tbl->resource_type; + get_parms.idx = idx; + get_parms.data = ulp_blob_data_get(&res_blob, &tmplen); + get_parms.data_sz_in_bytes = res_size; + + rc = tf_get_if_tbl_entry(tfp, &get_parms); + if (rc) { + BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n", + get_parms.type, + tf_dir_2_str(get_parms.dir), + get_parms.idx, rc); + return rc; + } + rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, + res_blob.data, + res_size, + res_blob.byte_order); + if (rc) + BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc); + return rc; + case BNXT_ULP_IF_TBL_OPC_NOT_USED: + return rc; /* skip it */ + default: + BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); + return -EINVAL; + } + + /* Perform the tf table set by filling the set params */ + iftbl_params.dir = tbl->direction; + iftbl_params.type = tbl->resource_type; + iftbl_params.data = ulp_blob_data_get(&data, &tmplen); + iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); + iftbl_params.idx = idx; + + rc = tf_set_if_tbl_entry(tfp, &iftbl_params); + if (rc) { + BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n", + iftbl_params.type,/* TBD: add tf_if_tbl_2_str */ + tf_dir_2_str(iftbl_params.dir), + iftbl_params.idx, rc); + return rc; + } + BNXT_TF_INF("Set table[%s][%s][%x] success.\n", + tf_if_tbl_2_str(iftbl_params.type), + tf_dir_2_str(iftbl_params.dir), + iftbl_params.idx); + + /* + * TBD: Need to look at the need to store idx in flow db for restore + * the table to its original state on deletion of this entry. + */ + return rc; +} + +static int32_t +ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + struct ulp_mapper_gen_tbl_list *gen_tbl_list; + struct bnxt_ulp_mapper_key_info *kflds; + struct ulp_flow_db_res_params fid_parms; + struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g; + struct ulp_gen_hash_entry_params hash_entry; + uint16_t tmplen = 0; + struct ulp_blob key, data; + uint8_t *cache_key; + int32_t tbl_idx; + uint32_t i, num_kflds = 0, key_index = 0; + uint32_t gen_tbl_miss = 1, fdb_write = 0; + uint8_t *byte_data; + int32_t rc = 0; + + /* Get the key fields list and build the key. */ + kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); + if (!kflds || !num_kflds) { + BNXT_TF_DBG(ERR, "Failed to get key fields\n"); + return -EINVAL; + } + + if (!ulp_blob_init(&key, tbl->key_bit_size, + parms->device_params->key_byte_order)) { + BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); + return -EINVAL; + } + for (i = 0; i < num_kflds; i++) { + /* Setup the key */ + rc = ulp_mapper_field_opc_process(parms, tbl->direction, + &kflds[i].field_info_spec, + &key, 1, "Gen Tbl Key"); + if (rc) { + BNXT_TF_DBG(ERR, + "Failed to create key for Gen tbl rc=%d\n", + rc); + return -EINVAL; + } + } + + /* Calculate the table index for the generic table*/ + tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type, + tbl->direction); + if (tbl_idx < 0) { + BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n", + tbl->resource_sub_type, tbl->direction); + return -EINVAL; + } + + /* The_key is a byte array convert it to a search index */ + cache_key = ulp_blob_data_get(&key, &tmplen); +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_gen_tbl_dump(tbl->resource_sub_type, tbl->direction, &key); +#endif +#endif + /* get the generic table */ + gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx]; + + /* Check if generic hash table */ + if (gen_tbl_list->hash_tbl) { + if (tbl->gen_tbl_lkup_type != + BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) { + BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n", + gen_tbl_list->gen_tbl_name); + return -EINVAL; + } + hash_entry.key_data = cache_key; + hash_entry.key_length = ULP_BITS_2_BYTE(tmplen); + rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl, + &hash_entry); + if (rc) { + BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n", + gen_tbl_list->gen_tbl_name); + return rc; + } + if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) { + key_index = hash_entry.key_idx; + /* Get the generic table entry */ + if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, + key_index, + &gen_tbl_ent)) + return -EINVAL; + /* store the hash index in the fdb */ + key_index = hash_entry.hash_index; + } + } else { + /* convert key to index directly */ + if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) { + BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n", + gen_tbl_list->gen_tbl_name); + return -EINVAL; + } + memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen)); + /* Get the generic table entry */ + if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index, + &gen_tbl_ent)) + return -EINVAL; + } + switch (tbl->tbl_opcode) { + case BNXT_ULP_GENERIC_TBL_OPC_READ: + if (gen_tbl_list->hash_tbl) { + if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND) + break; /* nothing to be done , no entry */ + } + + /* check the reference count */ + if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { + g = &gen_tbl_ent; + /* Scan ident list and create the result blob*/ + rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, + g->byte_data, + g->byte_data_size, + g->byte_order); + if (rc) { + BNXT_TF_DBG(ERR, + "Failed to scan ident list\n"); + return -EINVAL; + } + if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) { + /* increment the reference count */ + ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); + } + + /* it is a hit */ + gen_tbl_miss = 0; + fdb_write = 1; + } + break; + case BNXT_ULP_GENERIC_TBL_OPC_WRITE: + if (gen_tbl_list->hash_tbl) { + rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list, + &hash_entry, + &gen_tbl_ent); + if (rc) + return rc; + /* store the hash index in the fdb */ + key_index = hash_entry.hash_index; + } + /* check the reference count */ + if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { + /* a hit then error */ + BNXT_TF_DBG(ERR, "generic entry already present\n"); + return -EINVAL; /* success */ + } + + /* Initialize the blob data */ + if (!ulp_blob_init(&data, tbl->result_bit_size, + gen_tbl_ent.byte_order)) { + BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); + return -EINVAL; + } + + /* Get the result fields list */ + rc = ulp_mapper_tbl_result_build(parms, tbl, &data, + "Gen tbl Result"); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); + return rc; + } + byte_data = ulp_blob_data_get(&data, &tmplen); + rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent, + tmplen, byte_data, + ULP_BITS_2_BYTE(tmplen)); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to write generic table\n"); + return -EINVAL; + } + + /* increment the reference count */ + ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); + fdb_write = 1; + parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index; + break; + default: + BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode); + return -EINVAL; + } + + /* Set the generic entry hit */ + rc = ulp_regfile_write(parms->regfile, + BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, + tfp_cpu_to_be_64(gen_tbl_miss)); + if (rc) { + BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", + BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); + return -EIO; + } + + /* add the entry to the flow database */ + if (fdb_write) { + memset(&fid_parms, 0, sizeof(fid_parms)); + fid_parms.direction = tbl->direction; + fid_parms.resource_func = tbl->resource_func; + fid_parms.resource_sub_type = tbl->resource_sub_type; + fid_parms.resource_hndl = key_index; + fid_parms.critical_resource = tbl->critical_resource; + ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); + + rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); + if (rc) + BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc); + } + return rc; +} + +static int32_t +ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + int32_t rc = 0; + + /* process the fdb opcode for alloc push */ + if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) { + rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n"); + return rc; + } + } + return rc; +} + +static int32_t +ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, + struct bnxt_ulp_mapper_data *mapper_data) +{ + struct bnxt_ulp_glb_resource_info *glb_res; + uint32_t num_glb_res_ids, idx, dev_id; + uint8_t app_id; + int32_t rc = 0; + + glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); + if (!glb_res || !num_glb_res_ids) { + BNXT_TF_DBG(ERR, "Invalid Arguments\n"); + return -EINVAL; + } + + rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n", + rc); + return rc; + } + + rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n", + rc); + return rc; + } + + /* Iterate the global resources and process each one */ + for (idx = 0; idx < num_glb_res_ids; idx++) { + if (dev_id != glb_res[idx].device_id || + glb_res[idx].app_id != app_id) + continue; + switch (glb_res[idx].resource_func) { + case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: + rc = ulp_mapper_resource_ident_allocate(ulp_ctx, + mapper_data, + &glb_res[idx]); + break; + case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: + rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, + mapper_data, + &glb_res[idx]); + break; + default: + BNXT_TF_DBG(ERR, "Global resource %x not supported\n", + glb_res[idx].resource_func); + rc = -EINVAL; + break; + } + if (rc) + return rc; + } + return rc; +} + +/* + * Iterate over the shared resources assigned during tf_open_session and store + * them in the global regfile with the shared flag. + */ +static int32_t +ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, + struct bnxt_ulp_mapper_data *mapper_data) +{ + struct tf_get_shared_tbl_increment_parms iparms; + struct bnxt_ulp_glb_resource_info *glb_res; + struct tf_get_session_info_parms sparms; + uint32_t num_entries, i, dev_id, res; + struct tf_resource_info *res_info; + uint32_t addend; + uint64_t regval; + enum tf_dir dir; + int32_t rc = 0; + struct tf *tfp; + uint8_t app_id; + + memset(&sparms, 0, sizeof(sparms)); + glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries); + if (!glb_res || !num_entries) { + BNXT_TF_DBG(ERR, "Invalid Arguments\n"); + return -EINVAL; + } + tfp = bnxt_ulp_cntxt_shared_tfp_get(ulp_ctx); + if (!tfp) { + BNXT_TF_DBG(ERR, "Failed to get tfp for app global init"); + return -EINVAL; + } + /* + * Retrieve the resources that were assigned during the shared session + * creation. + */ + rc = tf_get_session_info(tfp, &sparms); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get session info (%d)\n", rc); + return rc; + } + + rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get the app id in glb init (%d).\n", + rc); + return rc; + } + + rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to get dev id for app glb init (%d)\n", + rc); + return rc; + } + + /* Store all the app global resources */ + for (i = 0; i < num_entries; i++) { + if (dev_id != glb_res[i].device_id || + app_id != glb_res[i].app_id) + continue; + dir = glb_res[i].direction; + res = glb_res[i].resource_type; + addend = 1; + + switch (glb_res[i].resource_func) { + case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: + res_info = &sparms.session_info.ident[dir].info[res]; + break; + case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: + /* + * Tables may have various strides for the allocations. + * Need to account. + */ + memset(&iparms, 0, sizeof(iparms)); + iparms.dir = dir; + iparms.type = res; + rc = tf_get_shared_tbl_increment(tfp, &iparms); + if (rc) { + BNXT_TF_DBG(ERR, + "Failed to get addend for %s[%s] rc=(%d)\n", + tf_tbl_type_2_str(res), + tf_dir_2_str(dir), rc); + return rc; + } + addend = iparms.increment_cnt; + res_info = &sparms.session_info.tbl[dir].info[res]; + break; + case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: + res_info = &sparms.session_info.tcam[dir].info[res]; + break; + case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: + res_info = &sparms.session_info.em[dir].info[res]; + break; + default: + BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n", + glb_res[i].resource_func); + continue; + } + regval = tfp_cpu_to_be_64((uint64_t)res_info->start); + res_info->start += addend; + /* + * All resources written to the global regfile are shared for + * this function. + */ + rc = ulp_mapper_glb_resource_write(mapper_data, &glb_res[i], + regval, true); + if (rc) + return rc; + } + + return rc; +} + +/* + * Common conditional opcode process routine that is used for both the template + * rejection and table conditional execution. + */ +static int32_t +ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms, + enum bnxt_ulp_cond_opc opc, + uint32_t operand, + int32_t *res) +{ + enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT; + int32_t rc = 0; + uint8_t bit; + uint64_t regval; + + switch (opc) { + case BNXT_ULP_COND_OPC_CF_IS_SET: + if (operand < BNXT_ULP_CF_IDX_LAST) { + *res = ULP_COMP_FLD_IDX_RD(parms, operand); + } else { + BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + case BNXT_ULP_COND_OPC_CF_NOT_SET: + if (operand < BNXT_ULP_CF_IDX_LAST) { + *res = !ULP_COMP_FLD_IDX_RD(parms, operand); + } else { + BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET: + if (operand < BNXT_ULP_ACT_BIT_LAST) { + *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits, + operand); + } else { + BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET: + if (operand < BNXT_ULP_ACT_BIT_LAST) { + *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits, + operand); + } else { + BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET: + if (operand < BNXT_ULP_HDR_BIT_LAST) { + *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, + operand); + } else { + BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET: + if (operand < BNXT_ULP_HDR_BIT_LAST) { + *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, + operand); + } else { + BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET: + rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); + if (rc) { + BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", + operand); + return -EINVAL; + } + *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); + break; + case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET: + rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); + if (rc) { + BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", + operand); + return -EINVAL; + } + *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); + break; + case BNXT_ULP_COND_OPC_RF_IS_SET: + if (!ulp_regfile_read(parms->regfile, operand, ®val)) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); + return -EINVAL; + } + *res = regval != 0; + break; + case BNXT_ULP_COND_OPC_RF_NOT_SET: + if (!ulp_regfile_read(parms->regfile, operand, ®val)) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); + return -EINVAL; + } + *res = regval == 0; + break; + case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH: + *res = parms->flow_pattern_id == operand; + break; + case BNXT_ULP_COND_OPC_ACT_PAT_MATCH: + *res = parms->act_pattern_id == operand; + break; + case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET: + if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) { + BNXT_TF_DBG(ERR, "Failed to get the mem type\n"); + return -EINVAL; + } + *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1; + break; + case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET: + if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) { + BNXT_TF_DBG(ERR, "Failed to get the mem type\n"); + return -EINVAL; + } + *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0; + break; + case BNXT_ULP_COND_OPC_ENC_HDR_BIT_IS_SET: + if (operand < BNXT_ULP_HDR_BIT_LAST) { + *res = ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, + operand); + } else { + BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + case BNXT_ULP_COND_OPC_ENC_HDR_BIT_NOT_SET: + if (operand < BNXT_ULP_HDR_BIT_LAST) { + *res = !ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, + operand); + } else { + BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", + operand); + rc = -EINVAL; + } + break; + default: + BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc); + rc = -EINVAL; + break; + } + return (rc); +} + +static int32_t +ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms, + enum tf_dir dir, + enum bnxt_ulp_func_src func_src, + uint16_t func_opr, + uint64_t *result) { - struct bnxt_ulp_mapper_class_key_field_info *kflds; - struct bnxt_ulp_mapper_cache_entry *cache_entry; - struct bnxt_ulp_mapper_ident_info *idents; - uint32_t i, num_kflds = 0, num_idents = 0; - struct ulp_flow_db_res_params fid_parms; - struct tf_free_identifier_parms fparms; - uint16_t tmplen, tmp_ident; - struct ulp_blob key; - uint8_t *cache_key; uint64_t regval; - uint16_t *ckey; - int32_t rc; + bool shared; - /* Get the key fields list and build the key. */ - kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); - if (!kflds || !num_kflds) { - BNXT_TF_DBG(ERR, "Failed to get key fields\n"); - return -EINVAL; - } - if (!ulp_blob_init(&key, tbl->key_bit_size, parms->order)) { - BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); - return -EINVAL; - } - for (i = 0; i < num_kflds; i++) { - /* Setup the key */ - rc = ulp_mapper_keymask_field_process(parms, tbl->direction, - &kflds[i], - &key, 1, "Cache Key"); - if (rc) { - BNXT_TF_DBG(ERR, - "Failed to create key for Cache rc=%d\n", - rc); + *result = false; + switch (func_src) { + case BNXT_ULP_FUNC_SRC_COMP_FIELD: + if (func_opr >= BNXT_ULP_CF_IDX_LAST) { + BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr); return -EINVAL; } - } - - /* - * Perform the lookup in the cache table with constructed key. The - * cache_key is a byte array of tmplen, it needs to be converted to a - * index for the cache table. - */ - cache_key = ulp_blob_data_get(&key, &tmplen); - ckey = (uint16_t *)cache_key; - - /* - * The id computed based on resource sub type and direction where - * dir is the bit0 and rest of the bits come from resource - * sub type. - */ - cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx, - (tbl->resource_sub_type << 1 | - (tbl->direction & 0x1)), - *ckey); - - /* - * Get the identifier list for processing by both the hit and miss - * processing. - */ - idents = ulp_mapper_ident_fields_get(tbl, &num_idents); - - if (!cache_entry->ref_count) { - /* Initialize the cache entry */ - cache_entry->tcam_idx = 0; - cache_entry->ref_count = 0; - for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) - cache_entry->idents[i] = ULP_IDENTS_INVALID; - - /* Need to allocate identifiers for storing in the cache. */ - for (i = 0; i < num_idents; i++) { - /* - * Since we are using the cache, the identifier does not - * get added to the flow db. Pass in the pointer to the - * tmp_ident. - */ - rc = ulp_mapper_ident_process(parms, tbl, - &idents[i], &tmp_ident); - if (rc) - goto error; - - cache_entry->ident_types[i] = idents[i].ident_type; - cache_entry->idents[i] = tmp_ident; + *result = ULP_COMP_FLD_IDX_RD(parms, func_opr); + break; + case BNXT_ULP_FUNC_SRC_REGFILE: + if (!ulp_regfile_read(parms->regfile, func_opr, ®val)) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr); + return -EINVAL; } - - /* Tell the TCAM processor to alloc an entry */ - parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC; - /* Store the cache key for use by the tcam process code */ - parms->cache_ptr = cache_entry; - } else { - /* Cache hit, get values from result. */ - for (i = 0; i < num_idents; i++) { - regval = (uint64_t)cache_entry->idents[i]; - if (!ulp_regfile_write(parms->regfile, - idents[i].regfile_wr_idx, - tfp_cpu_to_be_64(regval))) { - BNXT_TF_DBG(ERR, - "Failed to write to regfile\n"); - return -EINVAL; - } + *result = tfp_be_to_cpu_64(regval); + break; + case BNXT_ULP_FUNC_SRC_GLB_REGFILE: + if (ulp_mapper_glb_resource_read(parms->mapper_data, dir, + func_opr, ®val, &shared)) { + BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n", + func_opr); + return -EINVAL; } - /* - * The cached entry is being used, so let the tcam processing - * know not to process this table. - */ - parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP; + *result = tfp_be_to_cpu_64(regval); + break; + case BNXT_ULP_FUNC_SRC_CONST: + *result = func_opr; + break; + default: + BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src); + return -EINVAL; } + return 0; +} - /* Made through the cache processing, increment the reference count. */ - cache_entry->ref_count++; +static int32_t +ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info; + uint64_t res = 0, res1 = 0, res2 = 0; + int32_t rc = 0; + uint32_t process_src1 = 0, process_src2 = 0; - /* Link the cache to the flow db. */ - memset(&fid_parms, 0, sizeof(fid_parms)); - fid_parms.direction = tbl->direction; - fid_parms.resource_func = tbl->resource_func; + /* determine which functional operands to compute */ + switch (func_info->func_opc) { + case BNXT_ULP_FUNC_OPC_NOP: + return rc; + case BNXT_ULP_FUNC_OPC_EQ: + case BNXT_ULP_FUNC_OPC_NE: + case BNXT_ULP_FUNC_OPC_GE: + case BNXT_ULP_FUNC_OPC_GT: + case BNXT_ULP_FUNC_OPC_LE: + case BNXT_ULP_FUNC_OPC_LT: + process_src1 = 1; + process_src2 = 1; + break; + case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: + process_src1 = 1; + break; + default: + break; + } - /* - * Cache resource type is composed of table_type, resource - * sub type and direction, it needs to set appropriately via setter. - */ - ulp_mapper_cache_res_type_set(&fid_parms, - tbl->resource_type, - (tbl->resource_sub_type << 1 | - (tbl->direction & 0x1))); - fid_parms.resource_hndl = (uint64_t)*ckey; - fid_parms.critical_resource = tbl->critical_resource; - rc = ulp_flow_db_resource_add(parms->ulp_ctx, - parms->tbl_idx, - parms->fid, - &fid_parms); - if (rc) - BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n"); + if (process_src1) { + rc = ulp_mapper_func_opr_compute(parms, tbl->direction, + func_info->func_src1, + func_info->func_opr1, &res1); + if (rc) + return rc; + } - return rc; -error: - /* - * This error handling only gets called when the idents are being - * allocated for the cache on misses. Using the num_idents that was - * previously set. - */ - for (i = 0; i < num_idents; i++) { - if (cache_entry->idents[i] == ULP_IDENTS_INVALID) - continue; + if (process_src2) { + rc = ulp_mapper_func_opr_compute(parms, tbl->direction, + func_info->func_src2, + func_info->func_opr2, &res2); + if (rc) + return rc; + } - fparms.dir = tbl->direction; - fparms.ident_type = idents[i].ident_type; - fparms.id = cache_entry->idents[i]; - tf_free_identifier(parms->tfp, &fparms); + /* perform the functional opcode operations */ + switch (func_info->func_opc) { + case BNXT_ULP_FUNC_OPC_EQ: + if (res1 == res2) + res = 1; + break; + case BNXT_ULP_FUNC_OPC_NE: + if (res1 != res2) + res = 1; + break; + case BNXT_ULP_FUNC_OPC_GE: + if (res1 >= res2) + res = 1; + break; + case BNXT_ULP_FUNC_OPC_GT: + if (res1 > res2) + res = 1; + break; + case BNXT_ULP_FUNC_OPC_LE: + if (res1 <= res2) + res = 1; + break; + case BNXT_ULP_FUNC_OPC_LT: + if (res1 < res2) + res = 1; + break; + case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: + res = res1; + break; + case BNXT_ULP_FUNC_OPC_RSS_CONFIG: + /* apply the rss config using pmd method */ + return bnxt_rss_config_action_apply(parms); + case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR: + rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res); + if (rc) + return -EINVAL; + res = tfp_be_to_cpu_64(res); + break; + default: + BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc); + return -EINVAL; + } + if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr, + tfp_cpu_to_be_64(res))) { + BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n", + func_info->func_dst_opr); + return -EINVAL; } return rc; } +/* + * Processes a list of conditions and returns both a status and result of the + * list. The status must be checked prior to verifying the result. + * + * returns 0 for success, negative on failure + * returns res = 1 for true, res = 0 for false. + */ static int32_t -ulp_mapper_glb_resource_info_init(struct tf *tfp, - struct bnxt_ulp_mapper_data *mapper_data) +ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms, + enum bnxt_ulp_cond_list_opc list_opc, + struct bnxt_ulp_mapper_cond_info *list, + uint32_t num, + int32_t *res) { - struct bnxt_ulp_glb_resource_info *glb_res; - uint32_t num_glb_res_ids, idx; - int32_t rc = 0; + uint32_t i; + int32_t rc = 0, trc = 0; - glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); - if (!glb_res || !num_glb_res_ids) { - BNXT_TF_DBG(ERR, "Invalid Arguments\n"); + switch (list_opc) { + case BNXT_ULP_COND_LIST_OPC_AND: + /* AND Defaults to true. */ + *res = 1; + break; + case BNXT_ULP_COND_LIST_OPC_OR: + /* OR Defaults to false. */ + *res = 0; + break; + case BNXT_ULP_COND_LIST_OPC_TRUE: + *res = 1; + return rc; + case BNXT_ULP_COND_LIST_OPC_FALSE: + *res = 0; + return rc; + default: + BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n", + list_opc); + *res = 0; return -EINVAL; } - /* Iterate the global resources and process each one */ - for (idx = 0; idx < num_glb_res_ids; idx++) { - switch (glb_res[idx].resource_func) { - case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: - rc = ulp_mapper_resource_ident_allocate(tfp, - mapper_data, - &glb_res[idx]); - break; - default: - BNXT_TF_DBG(ERR, "Global resource %x not supported\n", - glb_res[idx].resource_func); - break; + for (i = 0; i < num; i++) { + rc = ulp_mapper_cond_opc_process(parms, + list[i].cond_opcode, + list[i].cond_operand, + &trc); + if (rc) + return rc; + + if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) { + /* early return if result is ever zero */ + if (!trc) { + *res = trc; + return rc; + } + } else { + /* early return if result is ever non-zero */ + if (trc) { + *res = trc; + return rc; + } } } + return rc; } /* - * Function to process the action template. Iterate through the list - * action info templates and process it. + * Processes conflict resolution and returns both a status and result. + * The status must be checked prior to verifying the result. + * + * returns 0 for success, negative on failure + * returns res = 1 for true, res = 0 for false. */ static int32_t -ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms) +ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl, + int32_t *res) { - uint32_t i; - int32_t rc = 0; + int32_t rc = 0; + uint64_t regval; + uint64_t comp_sig; - if (!parms->atbls || !parms->num_atbls) { - BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n", - parms->dev_id, parms->act_tid); + *res = 0; + switch (tbl->accept_opcode) { + case BNXT_ULP_ACCEPT_OPC_ALWAYS: + *res = 1; + break; + case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH: + /* perform the signature validation*/ + if (tbl->resource_func == + BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) { + /* Perform the check that generic table is hit or not */ + if (!ulp_regfile_read(parms->regfile, + BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, + ®val)) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", + BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); + return -EINVAL; + } + if (regval) { + /* not a hit so no need to check flow sign*/ + *res = 1; + return rc; + } + } + /* compare the new flow signature against stored one */ + if (!ulp_regfile_read(parms->regfile, + BNXT_ULP_RF_IDX_FLOW_SIG_ID, + ®val)) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", + BNXT_ULP_RF_IDX_FLOW_SIG_ID); + return -EINVAL; + } + comp_sig = ULP_COMP_FLD_IDX_RD(parms, + BNXT_ULP_CF_IDX_FLOW_SIG_ID); + regval = tfp_be_to_cpu_64(regval); + if (comp_sig == regval) + *res = 1; + else + BNXT_TF_DBG(ERR, "failed signature match 0x%016" + PRIX64 ":%x\n", comp_sig, (uint32_t)regval); + break; + default: + BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n", + tbl->accept_opcode); return -EINVAL; } - - for (i = 0; i < parms->num_atbls; i++) { - rc = ulp_mapper_action_info_process(parms, &parms->atbls[i]); - if (rc) - return rc; - } - return rc; } -/* Create the classifier table entries for a flow. */ static int32_t -ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms) +ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid) { - uint32_t i; - int32_t rc = 0; + struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL; + enum bnxt_ulp_cond_list_opc cond_opc; + struct bnxt_ulp_mapper_tbl_info *tbls; + struct bnxt_ulp_mapper_tbl_info *tbl; + uint32_t num_tbls, tbl_idx, num_cond_tbls; + int32_t rc = -EINVAL, cond_rc = 0; + int32_t cond_goto = 1; + + cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid, + &num_cond_tbls, + &cond_opc); + /* + * Process the reject list if exists, otherwise assume that the + * template is allowed. + */ + if (cond_tbls && num_cond_tbls) { + rc = ulp_mapper_cond_opc_list_process(parms, + cond_opc, + cond_tbls, + num_cond_tbls, + &cond_rc); + if (rc) + return rc; - if (!parms) - return -EINVAL; + /* Reject the template if True */ + if (cond_rc) { + BNXT_TF_DBG(ERR, "%s Template %d rejected.\n", + ulp_mapper_tmpl_name_str(parms->tmpl_type), + tid); + return -EINVAL; + } + } - if (!parms->ctbls || !parms->num_ctbls) { - BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n", - parms->dev_id, parms->class_tid); + tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls); + if (!tbls || !num_tbls) { + BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n", + ulp_mapper_tmpl_name_str(parms->tmpl_type), + parms->dev_id, tid); return -EINVAL; } - for (i = 0; i < parms->num_ctbls; i++) { - struct bnxt_ulp_mapper_class_tbl_info *tbl = &parms->ctbls[i]; + for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) { + tbl = &tbls[tbl_idx]; + cond_goto = tbl->execute_info.cond_true_goto; +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG +#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER + ulp_mapper_table_dump(tbl, tbl_idx); +#endif +#endif + /* Process the conditional func code opcodes */ + if (ulp_mapper_func_info_process(parms, tbl)) { + BNXT_TF_DBG(ERR, "Failed to process cond update\n"); + rc = -EINVAL; + goto error; + } + + cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl, + &num_cond_tbls, + &cond_opc); + rc = ulp_mapper_cond_opc_list_process(parms, cond_opc, + cond_tbls, num_cond_tbls, + &cond_rc); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n", + rc); + goto error; + } + /* Skip the table if False */ + if (!cond_rc) { + cond_goto = tbl->execute_info.cond_false_goto; + goto next_iteration; + } switch (tbl->resource_func) { case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: @@ -1893,27 +3799,79 @@ ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms) case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: rc = ulp_mapper_index_tbl_process(parms, tbl); break; - case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: - rc = ulp_mapper_cache_tbl_process(parms, tbl); + case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: + rc = ulp_mapper_if_tbl_process(parms, tbl); + break; + case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: + rc = ulp_mapper_gen_tbl_process(parms, tbl); + break; + case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE: + rc = ulp_mapper_ctrl_tbl_process(parms, tbl); + break; + case BNXT_ULP_RESOURCE_FUNC_INVALID: + rc = 0; break; default: - BNXT_TF_DBG(ERR, "Unexpected class resource %d\n", + BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n", tbl->resource_func); - return -EINVAL; + rc = -EINVAL; + goto error; } if (rc) { BNXT_TF_DBG(ERR, "Resource type %d failed\n", tbl->resource_func); - return rc; + goto error; + } + + /* perform the post table process */ + rc = ulp_mapper_conflict_resolution_process(parms, tbl, + &cond_rc); + if (rc || !cond_rc) { + BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n"); + rc = -EINVAL; + goto error; + } +next_iteration: + if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) { + BNXT_TF_DBG(ERR, "reject the flow\n"); + rc = -EINVAL; + goto error; + } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) { + uint32_t rf_idx; + uint64_t regval; + + /* least significant 16 bits from reg_file index */ + rf_idx = (uint32_t)(cond_goto & 0xFFFF); + if (!ulp_regfile_read(parms->regfile, rf_idx, + ®val)) { + BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", + rf_idx); + rc = -EINVAL; + goto error; + } + cond_goto = (int32_t)regval; + } + + if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) { + BNXT_TF_DBG(ERR, "invalid conditional goto %d\n", + cond_goto); + goto error; } + tbl_idx += cond_goto; } return rc; +error: + BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n", + ulp_mapper_tmpl_name_str(parms->tmpl_type), + parms->dev_id, tid); + return rc; } static int32_t ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, + uint32_t fid, struct ulp_flow_db_res_params *res) { struct tf *tfp; @@ -1923,22 +3881,21 @@ ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, BNXT_TF_DBG(ERR, "Unable to free resource\n "); return -EINVAL; } - - tfp = bnxt_ulp_cntxt_tfp_get(ulp); + if (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION) + tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_YES); + else + tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_NO); if (!tfp) { BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n"); return -EINVAL; } switch (res->resource_func) { - case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: - rc = ulp_mapper_cache_entry_free(ulp, tfp, res); - break; case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: rc = ulp_mapper_tcam_entry_free(ulp, tfp, res); break; case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: - rc = ulp_mapper_eem_entry_free(ulp, tfp, res); + rc = ulp_mapper_em_entry_free(ulp, tfp, res); break; case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: rc = ulp_mapper_index_entry_free(ulp, tfp, res); @@ -1949,6 +3906,15 @@ ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, case BNXT_ULP_RESOURCE_FUNC_HW_FID: rc = ulp_mapper_mark_free(ulp, res); break; + case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW: + rc = ulp_mapper_parent_flow_free(ulp, fid, res); + break; + case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW: + rc = ulp_mapper_child_flow_free(ulp, fid, res); + break; + case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: + rc = ulp_mapper_gen_tbl_res_free(ulp, res); + break; default: break; } @@ -1957,12 +3923,12 @@ ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, } int32_t -ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, - uint32_t fid, - enum bnxt_ulp_flow_db_tables tbl_type) +ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, + enum bnxt_ulp_fdb_type flow_type, + uint32_t fid) { - struct ulp_flow_db_res_params res_parms = { 0 }; - int32_t rc, trc; + struct ulp_flow_db_res_params res_parms = { 0 }; + int32_t rc, trc; if (!ulp_ctx) { BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); @@ -1973,8 +3939,9 @@ ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, * Set the critical resource on the first resource del, then iterate * while status is good */ - res_parms.critical_resource = 1; - rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms); + res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; + + rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms); if (rc) { /* @@ -1982,34 +3949,34 @@ ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, * It likely means that the flow did not exist in the flow db. */ BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", - tbl_type, fid, rc); + flow_type, fid, rc); return rc; } while (!rc) { - trc = ulp_mapper_resource_free(ulp_ctx, &res_parms); + trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms); if (trc) /* * On fail, we still need to attempt to free the * remaining resources. Don't return */ BNXT_TF_DBG(ERR, - "Flow[%d][0x%x] Res[%d][0x%016" PRIx64 + "Flow[%d][0x%x] Res[%d][0x%016" PRIX64 "] failed rc=%d.\n", - tbl_type, fid, res_parms.resource_func, + flow_type, fid, res_parms.resource_func, res_parms.resource_hndl, trc); - /* All subsequent call require the critical_resource be zero */ - res_parms.critical_resource = 0; + /* All subsequent call require the non-critical_resource */ + res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; rc = ulp_flow_db_resource_del(ulp_ctx, - tbl_type, + flow_type, fid, &res_parms); } /* Free the Flow ID since we've removed all resources */ - rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid); + rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid); return rc; } @@ -2024,33 +3991,38 @@ ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, /* Iterate the global resources and process each one */ for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { - for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_INFO_TBL_MAX_SZ; - idx++) { + for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) { ent = &mapper_data->glb_res_tbl[dir][idx]; if (ent->resource_func == - BNXT_ULP_RESOURCE_FUNC_INVALID) + BNXT_ULP_RESOURCE_FUNC_INVALID || + ent->shared) continue; memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); res.resource_func = ent->resource_func; res.direction = dir; res.resource_type = ent->resource_type; - res.resource_hndl = ent->resource_hndl; - ulp_mapper_resource_free(ulp_ctx, &res); + /*convert it from BE to cpu */ + res.resource_hndl = + tfp_be_to_cpu_64(ent->resource_hndl); + ulp_mapper_resource_free(ulp_ctx, 0, &res); } } } int32_t -ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid) +ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, + enum bnxt_ulp_fdb_type flow_type, + uint32_t fid) { + int32_t rc; + if (!ulp_ctx) { BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); return -EINVAL; } - return ulp_mapper_resources_free(ulp_ctx, - fid, - BNXT_ULP_REGULAR_FLOW_TABLE); + rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid); + return rc; } /* Function to handle the mapping of the Flow to be compatible @@ -2058,13 +4030,11 @@ ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid) */ int32_t ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, - struct bnxt_ulp_mapper_create_parms *cparms, - uint32_t *flowid) + struct bnxt_ulp_mapper_create_parms *cparms) { - struct bnxt_ulp_device_params *device_params; struct bnxt_ulp_mapper_parms parms; struct ulp_regfile regfile; - int32_t rc, trc; + int32_t rc = 0, trc; if (!ulp_ctx || !cparms) return -EINVAL; @@ -2073,12 +4043,26 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, memset(&parms, 0, sizeof(parms)); parms.act_prop = cparms->act_prop; parms.act_bitmap = cparms->act; + parms.hdr_bitmap = cparms->hdr_bitmap; + parms.enc_hdr_bitmap = cparms->enc_hdr_bitmap; parms.regfile = ®file; parms.hdr_field = cparms->hdr_field; + parms.enc_field = cparms->enc_field; + parms.fld_bitmap = cparms->fld_bitmap; parms.comp_fld = cparms->comp_fld; - parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); parms.ulp_ctx = ulp_ctx; - parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; + parms.act_tid = cparms->act_tid; + parms.class_tid = cparms->class_tid; + parms.flow_type = cparms->flow_type; + parms.parent_flow = cparms->parent_flow; + parms.child_flow = cparms->child_flow; + parms.fid = cparms->flow_id; + parms.tun_idx = cparms->tun_idx; + parms.app_priority = cparms->app_priority; + parms.flow_pattern_id = cparms->flow_pattern_id; + parms.act_pattern_id = cparms->act_pattern_id; + parms.app_id = cparms->app_id; + parms.port_id = cparms->port_id; /* Get the device id from the ulp context */ if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { @@ -2086,6 +4070,14 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, return -EINVAL; } + /* Get the device params, it will be used in later processing */ + parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); + if (!parms.device_params) { + BNXT_TF_DBG(ERR, "No device parms for device id %d\n", + parms.dev_id); + return -EINVAL; + } + /* * Get the mapper data for dynamic mapper data such as default * ids. @@ -2097,88 +4089,50 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, return -EINVAL; } - /* Get the action table entry from device id and act context id */ - parms.act_tid = cparms->act_tid; - parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id, - parms.act_tid, - &parms.num_atbls); - if (!parms.atbls || !parms.num_atbls) { - BNXT_TF_DBG(ERR, "No action tables for %d:%d\n", - parms.dev_id, parms.act_tid); - return -EINVAL; - } - - /* Get the class table entry from device id and act context id */ - parms.class_tid = cparms->class_tid; - parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id, - parms.class_tid, - &parms.num_ctbls); - if (!parms.ctbls || !parms.num_ctbls) { - BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", - parms.dev_id, parms.class_tid); - return -EINVAL; - } - - /* Get the byte order for the further processing from device params */ - device_params = bnxt_ulp_device_params_get(parms.dev_id); - if (!device_params) { - BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", - parms.dev_id, parms.class_tid); - return -EINVAL; - } - parms.order = device_params->byte_order; - parms.encap_byte_swap = device_params->encap_byte_swap; - /* initialize the registry file for further processing */ if (!ulp_regfile_init(parms.regfile)) { BNXT_TF_DBG(ERR, "regfile initialization failed.\n"); return -EINVAL; } - rc = ulp_regfile_write(parms.regfile, - BNXT_ULP_REGFILE_INDEX_CLASS_TID, - tfp_cpu_to_be_64((uint64_t)parms.class_tid)); - if (!rc) { - BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n"); - return -EINVAL; + /* Process the action template list from the selected action table*/ + if (parms.act_tid) { + parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION; + /* Process the action template tables */ + rc = ulp_mapper_tbls_process(&parms, parms.act_tid); + if (rc) + goto flow_error; + cparms->shared_hndl = parms.shared_hndl; } - /* Allocate a Flow ID for attaching all resources for the flow to. - * Once allocated, all errors have to walk the list of resources and - * free each of them. - */ - rc = ulp_flow_db_fid_alloc(ulp_ctx, - BNXT_ULP_REGULAR_FLOW_TABLE, - cparms->func_id, - &parms.fid); - if (rc) { - BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n"); - return rc; - } + if (parms.class_tid) { + parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; - /* Process the action template list from the selected action table*/ - rc = ulp_mapper_action_tbls_process(&parms); - if (rc) { - BNXT_TF_DBG(ERR, "action tables failed creation for %d:%d\n", - parms.dev_id, parms.act_tid); - goto flow_error; + /* Process the class template tables.*/ + rc = ulp_mapper_tbls_process(&parms, parms.class_tid); + if (rc) + goto flow_error; } - /* All good. Now process the class template */ - rc = ulp_mapper_class_tbls_process(&parms); - if (rc) { - BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n", - parms.dev_id, parms.class_tid); - goto flow_error; + /* setup the parent-child details */ + if (parms.parent_flow) { + /* create a parent flow details */ + rc = ulp_flow_db_parent_flow_create(&parms); + if (rc) + goto flow_error; + } else if (parms.child_flow) { + /* create a child flow details */ + rc = ulp_flow_db_child_flow_create(&parms); + if (rc) + goto flow_error; } - *flowid = parms.fid; - return rc; flow_error: /* Free all resources that were allocated during flow creation */ - trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid); + trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type, + parms.fid); if (trc) BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); @@ -2188,16 +4142,14 @@ flow_error: int32_t ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) { - struct bnxt_ulp_cache_tbl_params *tbl; struct bnxt_ulp_mapper_data *data; - uint32_t i; struct tf *tfp; - int32_t rc, csize; + int32_t rc; if (!ulp_ctx) return -EINVAL; - tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); + tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); if (!tfp) return -EINVAL; @@ -2216,32 +4168,29 @@ ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) } /* Allocate the global resource ids */ - rc = ulp_mapper_glb_resource_info_init(tfp, data); + rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); if (rc) { BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n"); goto error; } - /* Allocate the ulp cache tables. */ - for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { - tbl = ulp_mapper_cache_tbl_params_get(i); - if (!tbl) { - BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)", - i); + /* + * Only initialize the app global resources if a shared session was + * created. + */ + if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) { + rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to init app glb resources\n"); goto error; } - if (tbl->num_entries != 0) { - csize = sizeof(struct bnxt_ulp_mapper_cache_entry) * - tbl->num_entries; - data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl", - csize, 0); - if (!data->cache_tbl[i]) { - BNXT_TF_DBG(ERR, "Failed to allocate Cache " - "table %d.\n", i); - rc = -ENOMEM; - goto error; - } - } + } + + /* Allocate the generic table list */ + rc = ulp_mapper_generic_tbl_list_init(data); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n"); + goto error; } return 0; @@ -2255,13 +4204,11 @@ void ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) { struct bnxt_ulp_mapper_data *data; - uint32_t i; struct tf *tfp; if (!ulp_ctx) { BNXT_TF_DBG(ERR, - "Failed to acquire ulp context, so data may " - "not be released.\n"); + "Failed to acquire ulp context, so data may not be released.\n"); return; } @@ -2273,7 +4220,7 @@ ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) return; } - tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); + tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); if (!tfp) { BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); /* Free the mapper data regardless of errors. */ @@ -2284,11 +4231,8 @@ ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); free_mapper_data: - /* Free the ulp cache tables */ - for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { - rte_free(data->cache_tbl[i]); - data->cache_tbl[i] = NULL; - } + /* Free the generic table */ + (void)ulp_mapper_generic_tbl_list_deinit(data); rte_free(data); /* Reset the data pointer within the ulp_ctx. */