X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fbnxt%2Ftf_ulp%2Fulp_mapper.c;h=4dee65971ce1c65eac5c703a68d95b2cf6d3e28d;hb=65b98f6e3847467af721a45d92eba13c1862a453;hp=01514d8c985f18f04c22e90d808b3875d788742b;hpb=4369d847b2fa72f85a171cf4d3a5e41a3ec9d8d6;p=dpdk.git diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c index 01514d8c98..4dee65971c 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c +++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c @@ -16,13 +16,14 @@ #include "ulp_mark_mgr.h" #include "ulp_flow_db.h" #include "ulp_mapper.h" +#include "tf_util.h" 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; } @@ -80,15 +81,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); + if (!tfp) + return -EINVAL; + iparms.ident_type = glb_res->resource_type; iparms.dir = glb_res->direction; @@ -114,11 +120,64 @@ ulp_mapper_resource_ident_allocate(struct tf *tfp, tf_free_identifier(tfp, &fparms); 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", - glb_res->glb_regfile_index, iparms.ident_type, iparms.id); -#endif + return rc; +} + +/* + * 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) +{ + 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; + + tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); + 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.search_enable = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO; + 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 identifier [%s][%d]\n", + (aparms.dir == TF_DIR_RX) ? "RX" : "TX", + 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 */ + rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval); + 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; + } return rc; } @@ -132,6 +191,16 @@ ulp_mapper_cache_tbl_params_get(uint32_t tbl_idx) return &ulp_cache_tbl_params[tbl_idx]; } +/* Retrieve the global template table */ +static uint32_t * +ulp_mapper_glb_template_table_get(uint32_t *num_entries) +{ + if (!num_entries) + return NULL; + *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ; + return ulp_glb_template_tbl; +} + /* * Get the size of the action property for a given index. * @@ -469,24 +538,27 @@ 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; + if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE) + fparms.mem = TF_MEM_EXTERNAL; + else + fparms.mem = TF_MEM_INTERNAL; fparms.flow_handle = res->resource_hndl; rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); @@ -606,6 +678,98 @@ error: 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_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); + 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:%x failed.\n", + tf_dir_2_str(sparms.dir), + sparms.search_id); + return rc; + } + BNXT_TF_DBG(INFO, "Search ident %s:%x.success.\n", + tf_dir_2_str(sparms.dir), + 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 = BNXT_ULP_CRITICAL_RESOURCE_NO; + 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 res to flow rc = %d\n", + rc); + /* Need to free the identifier, so goto error */ + goto error; + } + + 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_result_field_process(struct bnxt_ulp_mapper_parms *parms, enum tf_dir dir, @@ -659,7 +823,10 @@ ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms, return -EINVAL; } act_bit = tfp_be_to_cpu_64(act_bit); - act_val = ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit); + if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) + act_val = 1; + else + act_val = 0; if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) { BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name); return -EINVAL; @@ -766,8 +933,109 @@ ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms, return -EINVAL; } + break; + case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST: + if (!ulp_operand_read(fld->result_operand, + (uint8_t *)&act_bit, sizeof(uint64_t))) { + BNXT_TF_DBG(ERR, "%s operand read failed\n", name); + return -EINVAL; + } + act_bit = tfp_be_to_cpu_64(act_bit); + if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { + /* Action bit is set so consider operand_true */ + if (!ulp_operand_read(fld->result_operand_true, + (uint8_t *)&idx, + sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "%s operand read failed\n", + name); + 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); + 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; + } + if (!ulp_blob_push(blob, val, fld->field_bit_size)) { + BNXT_TF_DBG(ERR, "%s push field failed\n", + name); + return -EINVAL; + } + } else { + /* action bit is not set, use the operand false */ + val = fld->result_operand_false; + if (!ulp_blob_push(blob, val, fld->field_bit_size)) { + BNXT_TF_DBG(ERR, "%s failed to add field\n", + name); + return -EINVAL; + } + } + break; + case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST: + if (!ulp_operand_read(fld->result_operand, + (uint8_t *)&act_bit, sizeof(uint64_t))) { + BNXT_TF_DBG(ERR, "%s operand read failed\n", name); + return -EINVAL; + } + act_bit = tfp_be_to_cpu_64(act_bit); + if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { + /* Action bit is set so consider operand_true */ + val = fld->result_operand_true; + } else { + /* action bit is not set, use the operand false */ + val = fld->result_operand_false; + } + if (!ulp_blob_push(blob, val, fld->field_bit_size)) { + BNXT_TF_DBG(ERR, "%s failed to add field\n", + name); + return -EINVAL; + } + break; + case BNXT_ULP_MAPPER_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF: + if (!ulp_operand_read(fld->result_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 (idx >= BNXT_ULP_CF_IDX_LAST) { + BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx); + return -EINVAL; + } + /* check if the computed field is set */ + if (ULP_COMP_FLD_IDX_RD(parms, idx)) + val = fld->result_operand_true; + else + val = fld->result_operand_false; + + /* read the appropriate computed field */ + if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) { + BNXT_TF_DBG(ERR, "%s val operand read failed\n", name); + return -EINVAL; + } + idx = tfp_be_to_cpu_16(idx); + if (idx >= BNXT_ULP_CF_IDX_LAST) { + BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx); + return -EINVAL; + } + 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; + } break; default: + BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x\n", + fld->result_opcode); return -EINVAL; } return 0; @@ -899,6 +1167,9 @@ ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms, } break; default: + BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n", + opcode); + return -EINVAL; break; } @@ -1056,11 +1327,13 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, struct tf *tfp; int32_t rc, trc; struct tf_alloc_tcam_entry_parms aparms = { 0 }; + struct tf_search_tcam_entry_parms searchparms = { 0 }; struct tf_set_tcam_entry_parms sparms = { 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; + uint16_t idx; /* Skip this if was handled by the cache. */ if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) { @@ -1115,37 +1388,72 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, } } - 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; - } + if (!tbl->srch_b4_alloc) { + /* + * No search for re-use is requested, so simply allocate the + * tcam index. + */ + 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.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; + 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; - } + /* + * 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; + } + 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.priority = tbl->priority; + searchparms.alloc = 1; + searchparms.result = ulp_blob_data_get(&data, &tmplen); + searchparms.result_sz_in_bits = tbl->result_bit_size; + + rc = tf_search_tcam_entry(tfp, &searchparms); + if (rc) { + BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc); + return rc; + } - hit = aparms.hit; + /* 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; + } /* Build the result */ if (!tbl->srch_b4_alloc || !hit) { @@ -1193,9 +1501,9 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, } } - sparms.dir = aparms.dir; - sparms.tcam_tbl_type = aparms.tcam_tbl_type; - sparms.idx = aparms.idx; + sparms.dir = tbl->direction; + sparms.tcam_tbl_type = tbl->resource_type; + sparms.idx = idx; /* Already verified the key/mask lengths */ sparms.key = ulp_blob_data_get(&key, &tmplen); sparms.mask = ulp_blob_data_get(&mask, &tmplen); @@ -1227,7 +1535,7 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, rc = -EINVAL; goto error; } - parms->cache_ptr->tcam_idx = aparms.idx; + parms->cache_ptr->tcam_idx = idx; } /* Mark action */ @@ -1236,9 +1544,23 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, goto error; } else { - BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n"); - rc = -EINVAL; - goto error; + struct bnxt_ulp_mapper_ident_info *idents; + uint32_t num_idents; + + /* + * Extract the listed identifiers from the result field, + * no need to allocate them. + */ + idents = ulp_mapper_ident_fields_get(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 ident extraction\n"); + goto error; + } + } } /* @@ -1250,7 +1572,7 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 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; + fid_parms.resource_hndl = idx; rc = ulp_flow_db_resource_add(parms->ulp_ctx, parms->tbl_idx, parms->fid, @@ -1357,12 +1679,9 @@ ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, return rc; } } -#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG - ulp_mapper_result_dump("EEM Result", tbl, &data); -#endif /* do the transpose for the internal EM keys */ - if (tbl->resource_type == TF_MEM_INTERNAL) + if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) ulp_blob_perform_byte_reverse(&key); rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, @@ -1445,9 +1764,10 @@ ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, struct ulp_blob data; uint64_t idx = 0; uint16_t tmplen; - uint32_t i, num_flds; + uint32_t i, num_flds, index, hit; int32_t rc = 0, trc = 0; struct tf_alloc_tbl_entry_parms aparms = { 0 }; + struct tf_search_tbl_entry_parms srchparms = { 0 }; struct tf_set_tbl_entry_parms sparms = { 0 }; struct tf_free_tbl_entry_parms free_parms = { 0 }; uint32_t tbl_scope_id; @@ -1510,10 +1830,6 @@ ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, /* if encap bit swap is enabled perform the bit swap */ if (parms->device_params->encap_byte_swap && encap_flds) { ulp_blob_perform_encap_swap(&data); -#ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG - BNXT_TF_DBG(INFO, "Dump after encap swap\n"); - ulp_mapper_blob_dump(&data); -#endif } /* @@ -1552,33 +1868,60 @@ ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, } return 0; /* success */ } + + index = 0; + hit = 0; /* Perform the tf table allocation by filling the alloc params */ - 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_BITS_2_BYTE(tmplen); - 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", - aparms.type, - (aparms.dir == TF_DIR_RX) ? "RX" : "TX", - rc); - return rc; + if (tbl->srch_b4_alloc) { + memset(&srchparms, 0, sizeof(srchparms)); + srchparms.dir = tbl->direction; + srchparms.type = tbl->resource_type; + srchparms.alloc = 1; + srchparms.result = ulp_blob_data_get(&data, &tmplen); + srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); + srchparms.tbl_scope_id = tbl_scope_id; + rc = tf_search_tbl_entry(tfp, &srchparms); + if (rc) { + BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", + tf_tbl_type_2_str(tbl->resource_type), + tf_dir_2_str(tbl->direction), rc); + return rc; + } + if (srchparms.search_status == REJECT) { + BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n", + tf_tbl_type_2_str(tbl->resource_type), + tf_dir_2_str(tbl->direction)); + return -ENOMEM; + } + index = srchparms.idx; + hit = srchparms.hit; + } else { + 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_BITS_2_BYTE(tmplen); + 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[%s][%s] failed rc=%d\n", + tf_tbl_type_2_str(tbl->resource_type), + tf_dir_2_str(tbl->direction), rc); + return rc; + } + index = aparms.idx; } - /* * 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 (aparms.type == TF_TBL_TYPE_EXT) - idx = TF_ACT_REC_OFFSET_2_PTR(aparms.idx); + if (tbl->resource_type == TF_TBL_TYPE_EXT) + idx = TF_ACT_REC_OFFSET_2_PTR(index); else - idx = aparms.idx; + idx = index; /* Always storing values in Regfile in BE */ idx = tfp_cpu_to_be_64(idx); @@ -1592,12 +1935,12 @@ ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, } /* Perform the tf table set by filling the set params */ - if (!tbl->srch_b4_alloc || !aparms.hit) { + if (!tbl->srch_b4_alloc || !hit) { sparms.dir = tbl->direction; sparms.type = tbl->resource_type; sparms.data = ulp_blob_data_get(&data, &tmplen); sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); - sparms.idx = aparms.idx; + sparms.idx = index; sparms.tbl_scope_id = tbl_scope_id; rc = tf_set_tbl_entry(tfp, &sparms); @@ -1616,7 +1959,8 @@ ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *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.resource_sub_type = tbl->resource_sub_type; + fid_parms.resource_hndl = index; fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; rc = ulp_flow_db_resource_add(parms->ulp_ctx, @@ -1643,7 +1987,7 @@ error: */ free_parms.dir = tbl->direction; free_parms.type = tbl->resource_type; - free_parms.idx = aparms.idx; + free_parms.idx = index; free_parms.tbl_scope_id = tbl_scope_id; trc = tf_free_tbl_entry(tfp, &free_parms); @@ -1853,11 +2197,14 @@ ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, } /* Get the index details from computed field */ - if (tbl->index_opcode != BNXT_ULP_INDEX_OPCODE_COMP_FIELD) { + if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_COMP_FIELD) { + idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand); + } else if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_CONSTANT) { + idx = tbl->index_operand; + } else { BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); return -EINVAL; } - idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand); /* Perform the tf table set by filling the set params */ iftbl_params.dir = tbl->direction; @@ -1884,7 +2231,7 @@ ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, } static int32_t -ulp_mapper_glb_resource_info_init(struct tf *tfp, +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; @@ -1901,15 +2248,76 @@ ulp_mapper_glb_resource_info_init(struct tf *tfp, 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, + 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; +} + +/* + * Function to process the conditional opcode of the mapper table. + * returns 1 to skip the table. + * return 0 to continue processing the table. + */ +static int32_t +ulp_mapper_tbl_cond_opcode_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_tbl_info *tbl) +{ + int32_t rc = 1; + + switch (tbl->cond_opcode) { + case BNXT_ULP_COND_OPCODE_NOP: + rc = 0; + break; + case BNXT_ULP_COND_OPCODE_COMP_FIELD_IS_SET: + if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && + ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) + rc = 0; + break; + case BNXT_ULP_COND_OPCODE_ACTION_BIT_IS_SET: + if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, + tbl->cond_operand)) + rc = 0; + break; + case BNXT_ULP_COND_OPCODE_HDR_BIT_IS_SET: + if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, + tbl->cond_operand)) + rc = 0; + break; + case BNXT_ULP_COND_OPCODE_COMP_FIELD_NOT_SET: + if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && + !ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) + rc = 0; + break; + case BNXT_ULP_COND_OPCODE_ACTION_BIT_NOT_SET: + if (!ULP_BITMAP_ISSET(parms->act_bitmap->bits, + tbl->cond_operand)) + rc = 0; + break; + case BNXT_ULP_COND_OPCODE_HDR_BIT_NOT_SET: + if (!ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, + tbl->cond_operand)) + rc = 0; + break; + default: + BNXT_TF_DBG(ERR, + "Invalid arg in mapper tbl for cond opcode\n"); + break; } return rc; } @@ -1933,6 +2341,9 @@ ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms) for (i = 0; i < parms->num_atbls; i++) { tbl = &parms->atbls[i]; + if (ulp_mapper_tbl_cond_opcode_process(parms, tbl)) + continue; + switch (tbl->resource_func) { case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: rc = ulp_mapper_index_tbl_process(parms, tbl, false); @@ -1971,11 +2382,15 @@ ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms) for (i = 0; i < parms->num_ctbls; i++) { struct bnxt_ulp_mapper_tbl_info *tbl = &parms->ctbls[i]; + if (ulp_mapper_tbl_cond_opcode_process(parms, tbl)) + continue; + switch (tbl->resource_func) { case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: rc = ulp_mapper_tcam_tbl_process(parms, tbl); break; - case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: + case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: + case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: rc = ulp_mapper_em_tbl_process(parms, tbl); break; case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: @@ -2028,8 +2443,9 @@ ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 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); + case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: + case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: + 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); @@ -2115,7 +2531,7 @@ 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; + for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; idx++) { ent = &mapper_data->glb_res_tbl[dir][idx]; if (ent->resource_func == @@ -2125,23 +2541,89 @@ ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, res.resource_func = ent->resource_func; res.direction = dir; res.resource_type = ent->resource_type; - res.resource_hndl = ent->resource_hndl; + /*convert it from BE to cpu */ + res.resource_hndl = + tfp_be_to_cpu_64(ent->resource_hndl); ulp_mapper_resource_free(ulp_ctx, &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, uint32_t fid, + enum bnxt_ulp_flow_db_tables flow_tbl_type) { 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); + return ulp_mapper_resources_free(ulp_ctx, fid, flow_tbl_type); +} + +/* Function to handle the default global templates that are allocated during + * the startup and reused later. + */ +static int32_t +ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx) +{ + uint32_t *glbl_tmpl_list; + uint32_t num_glb_tmpls, idx, dev_id; + struct bnxt_ulp_mapper_parms parms; + struct bnxt_ulp_mapper_data *mapper_data; + int32_t rc = 0; + + glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls); + if (!glbl_tmpl_list || !num_glb_tmpls) + return rc; /* No global templates to process */ + + /* Get the device id from the ulp context */ + if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { + BNXT_TF_DBG(ERR, "Invalid ulp context\n"); + return -EINVAL; + } + + mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); + if (!mapper_data) { + BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); + return -EINVAL; + } + + /* Iterate the global resources and process each one */ + for (idx = 0; idx < num_glb_tmpls; idx++) { + /* Initialize the parms structure */ + memset(&parms, 0, sizeof(parms)); + parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); + parms.ulp_ctx = ulp_ctx; + parms.dev_id = dev_id; + parms.mapper_data = mapper_data; + + /* Get the class table entry from dev id and class id */ + parms.class_tid = glbl_tmpl_list[idx]; + parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id, + parms.class_tid, + &parms.num_ctbls, + &parms.tbl_idx); + 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; + } + parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); + if (!parms.device_params) { + BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", + parms.dev_id, parms.class_tid); + return -EINVAL; + } + 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); + return rc; + } + } + return rc; } /* Function to handle the mapping of the Flow to be compatible @@ -2163,6 +2645,7 @@ 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.regfile = ®file; parms.hdr_field = cparms->hdr_field; parms.comp_fld = cparms->comp_fld; @@ -2278,7 +2761,8 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 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.fid, + BNXT_ULP_REGULAR_FLOW_TABLE); if (trc) BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); @@ -2316,7 +2800,7 @@ 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; @@ -2344,6 +2828,12 @@ ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) } } + rc = ulp_mapper_glb_template_table_init(ulp_ctx); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to initialize global templates\n"); + goto error; + } + return 0; error: /* Ignore the return code in favor of returning the original error. */