X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fbnxt%2Ftf_ulp%2Fulp_mapper.c;h=dc7b7ca5edfdba4633de9a6d2b6728cb942cf2ff;hb=4bc32a80556eb85ca980dcc5e82455e3ae741007;hp=f70afa47f1167e6a6fc833016ad838794bd3fc9c;hpb=aa0fa4d9f4ce3144c9ca31044deafc16f54c5604;p=dpdk.git diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c index f70afa47f1..dc7b7ca5ed 100644 --- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c +++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c @@ -4,6 +4,7 @@ */ #include +#include #include "bnxt.h" #include "ulp_template_db.h" #include "ulp_template_struct.h" @@ -16,6 +17,65 @@ #include "ulp_flow_db.h" #include "ulp_mapper.h" +static struct bnxt_ulp_def_ident_info * +ulp_mapper_def_ident_info_list_get(uint32_t *num_entries) +{ + if (!num_entries) + return NULL; + *num_entries = BNXT_ULP_DEF_IDENT_INFO_TBL_MAX_SZ; + return ulp_def_ident_tbl; +} + +/* + * Read a default identifier from the mapper regfile. + * + * The regval is always returned in big-endian. + * + * returns 0 on success + */ +static int32_t +ulp_mapper_def_regfile_read(struct bnxt_ulp_mapper_data *mapper_data, + enum tf_dir dir, + uint16_t idx, + uint64_t *regval) +{ + if (!mapper_data || !regval || + dir >= TF_DIR_MAX || idx >= BNXT_ULP_DEF_REGFILE_INDEX_LAST) + return -EINVAL; + *regval = mapper_data->dflt_ids[dir][idx].ident; + return 0; +} + +/* + * Write a default identifier to the mapper regfile + * + * The regval value must be in big-endian. + * + * return 0 on success. + */ +static int32_t +ulp_mapper_def_regfile_write(struct bnxt_ulp_mapper_data *mapper_data, + enum tf_dir dir, + uint16_t idx, + uint64_t regval) +{ + if (!mapper_data || dir >= TF_DIR_MAX || + idx >= BNXT_ULP_DEF_REGFILE_INDEX_LAST) + return -EINVAL; + mapper_data->dflt_ids[dir][idx].ident = regval; + return 0; +} + +/* 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) +{ + if (tbl_idx >= BNXT_ULP_CACHE_TBL_MAX_SZ) + return NULL; + + return &ulp_cache_tbl_params[tbl_idx]; +} + /* * Get the size of the action property for a given index. * @@ -206,6 +266,126 @@ ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_class_tbl_info *tbl, return &ulp_ident_list[idx]; } +static struct bnxt_ulp_mapper_cache_entry * +ulp_mapper_cache_entry_get(struct bnxt_ulp_context *ulp, + enum bnxt_ulp_cache_tbl_id id, + uint16_t key) +{ + struct bnxt_ulp_mapper_data *mapper_data; + + mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp); + if (!mapper_data || !mapper_data->cache_tbl[id]) { + BNXT_TF_DBG(ERR, "Unable to acquire the cache tbl (%d)\n", id); + return NULL; + } + + 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 = + ((uint32_t)tbl_id << ULP_MAPPER_CACHE_RES_TBL_ID_SHFT) | + ((uint32_t)tbl_type << ULP_MAPPER_CACHE_RES_TBL_TYPE_SHFT); +} + +/* 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 = (uint16_t)((res->resource_type >> + ULP_MAPPER_CACHE_RES_TBL_TYPE_SHFT) & + ULP_MAPPER_CACHE_RES_TBL_MASK); + *tbl_id = (uint16_t)((res->resource_type >> + ULP_MAPPER_CACHE_RES_TBL_ID_SHFT) & + ULP_MAPPER_CACHE_RES_TBL_MASK); +} + +static int32_t +ulp_mapper_cache_entry_free(struct bnxt_ulp_context *ulp, + struct tf *tfp, + struct ulp_flow_db_res_params *res) +{ + 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; + } + } + + return rc; +} + static inline int32_t ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused, struct tf *tfp, @@ -287,10 +467,16 @@ ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, 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 + * identifier is to be stored in the flow database. + */ 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_ident_info *ident) + struct bnxt_ulp_mapper_ident_info *ident, + uint16_t *val) { struct ulp_flow_db_res_params fid_parms; uint64_t id = 0; @@ -328,22 +514,26 @@ ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, } /* 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 = iparms.id; - fid_parms.critical_resource = 0; + if (!val) { + 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 = iparms.id; + 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); - /* Need to free the identifier, so goto error */ - goto error; + 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; + } + } else { + *val = iparms.id; } return 0; @@ -357,13 +547,14 @@ error: (void)tf_free_identifier(tfp, &free_parms); BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n", - ident->name, + ident->description, (tbl->direction == TF_DIR_RX) ? "RX" : "TX"); return rc; } 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) @@ -405,7 +596,7 @@ ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms, return -EINVAL; } break; - case BNXT_ULP_RESULT_OPC_SET_TO_ACT_PROP_SZ: + case BNXT_ULP_RESULT_OPC_SET_TO_ENCAP_ACT_PROP_SZ: if (!ulp_operand_read(fld->result_operand, (uint8_t *)&idx, sizeof(uint16_t))) { BNXT_TF_DBG(ERR, "%s operand read failed\n", name); @@ -458,22 +649,43 @@ ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms, return -EINVAL; } break; + case BNXT_ULP_RESULT_OPC_SET_TO_DEF_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); + return -EINVAL; + } + idx = tfp_be_to_cpu_16(idx); + if (ulp_mapper_def_regfile_read(parms->mapper_data, + dir, + idx, ®val)) { + BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", + name, 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); + return -EINVAL; + } + 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 regval; + uint64_t val64; uint16_t idx, bitlen; uint32_t opcode; uint8_t *operand; @@ -542,17 +754,38 @@ ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms, } idx = tfp_be_to_cpu_16(idx); - if (!ulp_regfile_read(regfile, idx, ®val)) { + if (!ulp_regfile_read(regfile, idx, &val64)) { BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", name, idx); return -EINVAL; } - val = ulp_blob_push_64(blob, ®val, bitlen); + val = ulp_blob_push_64(blob, &val64, bitlen); if (!val) { BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); return -EINVAL; } + break; + case BNXT_ULP_SPEC_OPC_SET_TO_DEF_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_mapper_def_regfile_read(parms->mapper_data, + dir, + idx, &val64)) { + BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", + name, 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); + return -EINVAL; + } + break; default: break; } @@ -717,6 +950,7 @@ ulp_mapper_action_info_process(struct bnxt_ulp_mapper_parms *parms, for (i = 0; i < (num_flds + encap_flds); i++) { fld = &flds[i]; rc = ulp_mapper_result_field_process(parms, + tbl->direction, fld, &blob, "Action"); @@ -754,6 +988,12 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 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; + return 0; + } + tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); if (!tfp) { BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); @@ -780,7 +1020,8 @@ 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, &kflds[i], + rc = ulp_mapper_keymask_field_process(parms, tbl->direction, + &kflds[i], &key, 1, "TCAM Key"); if (rc) { BNXT_TF_DBG(ERR, "Key field set failed.\n"); @@ -788,7 +1029,8 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, } /* Setup the mask */ - rc = ulp_mapper_keymask_field_process(parms, &kflds[i], + rc = ulp_mapper_keymask_field_process(parms, tbl->direction, + &kflds[i], &mask, 0, "TCAM Mask"); if (rc) { BNXT_TF_DBG(ERR, "Mask field set failed.\n"); @@ -834,15 +1076,22 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, struct bnxt_ulp_mapper_ident_info *idents; uint32_t num_dflds, num_idents; - /* Alloc identifiers */ - 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]); - - /* Already logged the error, just return */ - if (rc) - goto error; + /* + * 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; + } } /* Create the result data blob */ @@ -855,6 +1104,7 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, for (i = 0; i < num_dflds; i++) { rc = ulp_mapper_result_field_process(parms, + tbl->direction, &dflds[i], &data, "TCAM Result"); @@ -889,32 +1139,57 @@ ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, sparms.idx); goto error; } + + /* 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; + } + } else { BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n"); rc = -EINVAL; goto error; } - /* Link the resource to the flow in the flow db */ - fid_parms.direction = tbl->direction; - fid_parms.resource_func = tbl->resource_func; - fid_parms.resource_type = tbl->table_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; + /* + * 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->table_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; + } + } 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; } 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->table_type; free_parms.idx = aparms.idx; @@ -959,7 +1234,8 @@ 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, &kflds[i], + rc = ulp_mapper_keymask_field_process(parms, tbl->direction, + &kflds[i], &key, 1, "EM Key"); if (rc) { BNXT_TF_DBG(ERR, "Key field set failed.\n"); @@ -985,6 +1261,7 @@ ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, fld = &dflds[i]; rc = ulp_mapper_result_field_process(parms, + tbl->direction, fld, &data, "EM Result"); @@ -1135,6 +1412,7 @@ ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, for (i = 0; i < num_flds; i++) { rc = ulp_mapper_result_field_process(parms, + tbl->direction, &flds[i], &data, "Indexed Result"); @@ -1224,6 +1502,153 @@ error: return rc; } +static int32_t +ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms, + struct bnxt_ulp_mapper_class_tbl_info *tbl) +{ + 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; + + /* 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); + 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; + cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx, + tbl->cache_tbl_id, + *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; + } + + /* 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; + } + } + /* + * 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; + } + + /* Made through the cache processing, increment the reference count. */ + cache_entry->ref_count++; + + /* 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; + + /* + * Cache resource type is composed of both table_type and cache_tbl_id + * need to set it appropriately via setter. + */ + ulp_mapper_cache_res_type_set(&fid_parms, + tbl->table_type, + tbl->cache_tbl_id); + 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"); + + 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; + + fparms.dir = tbl->direction; + fparms.ident_type = idents[i].ident_type; + fparms.id = cache_entry->idents[i]; + tf_free_identifier(parms->tfp, &fparms); + } + + return rc; +} + /* * Function to process the action template. Iterate through the list * action info templates and process it. @@ -1278,6 +1703,9 @@ 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); + break; default: BNXT_TF_DBG(ERR, "Unexpected class resource %d\n", tbl->resource_func); @@ -1313,6 +1741,9 @@ ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, } 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; @@ -1430,6 +1861,7 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, parms.hdr_field = cparms->hdr_field; 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; /* Get the device id from the ulp context */ if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { @@ -1437,6 +1869,17 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, return -EINVAL; } + /* + * Get the mapper data for dynamic mapper data such as default + * ids. + */ + parms.mapper_data = (struct bnxt_ulp_mapper_data *) + bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); + if (!parms.mapper_data) { + BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); + 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, @@ -1475,12 +1918,21 @@ ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 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; + } + /* 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"); @@ -1515,3 +1967,158 @@ flow_error: return rc; } + +int32_t +ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) +{ + struct bnxt_ulp_cache_tbl_params *tbl; + struct tf_alloc_identifier_parms iparms; + struct bnxt_ulp_mapper_data *data; + struct bnxt_ulp_def_ident_info *dflt_ids; + uint32_t i, num_dflt_ids, reg_idx; + uint64_t regval; + struct tf *tfp; + int32_t rc, csize; + + if (!ulp_ctx) + return -EINVAL; + + tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); + if (!tfp) + return -EINVAL; + + data = rte_zmalloc("ulp_mapper_data", + sizeof(struct bnxt_ulp_mapper_data), 0); + if (!data) { + BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n"); + return -ENOMEM; + } + + if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) { + BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n"); + /* Don't call deinit since the prof_func wasn't allocated. */ + rte_free(data); + return -ENOMEM; + } + + /* Allocate the default ids. */ + dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids); + for (i = 0; i < num_dflt_ids; i++) { + iparms.ident_type = dflt_ids[i].ident_type; + iparms.dir = dflt_ids[i].direction; + + rc = tf_alloc_identifier(tfp, &iparms); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to alloc dflt " + "identifier [%s][%d]\n", + (iparms.dir == TF_DIR_RX) ? "RX" : "TX", + iparms.ident_type); + goto error; + } + reg_idx = dflt_ids[i].def_regfile_index; + /* All regfile entries are stored as 64bit big-endian values. */ + regval = tfp_cpu_to_be_64((uint64_t)iparms.id); + rc = ulp_mapper_def_regfile_write(data, iparms.dir, + reg_idx, regval); + if (rc) { + BNXT_TF_DBG(ERR, "Failed to write to default " + "regfile.\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); + 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; + } + } + } + + return 0; +error: + /* Ignore the return code in favor of returning the original error. */ + ulp_mapper_deinit(ulp_ctx); + return rc; +} + +void +ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) +{ + struct tf_free_identifier_parms free_parms; + struct bnxt_ulp_def_ident_info *dflt_ids; + struct bnxt_ulp_mapper_data *data; + uint32_t i, num_dflt_ids, reg_idx; + enum tf_dir dir; + uint64_t regval; + struct tf *tfp; + + if (!ulp_ctx) { + BNXT_TF_DBG(ERR, + "Failed to acquire ulp context, so data may " + "not be released.\n"); + return; + } + + data = (struct bnxt_ulp_mapper_data *) + bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); + if (!data) { + /* Go ahead and return since there is no allocated data. */ + BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n"); + return; + } + + tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); + if (!tfp) { + BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); + /* Free the mapper data regardless of errors. */ + goto free_mapper_data; + } + + /* Free the default prof func ids per direction. */ + dflt_ids = ulp_mapper_def_ident_info_list_get(&num_dflt_ids); + for (i = 0; i < num_dflt_ids; i++) { + reg_idx = dflt_ids[i].def_regfile_index; + dir = dflt_ids[i].direction; + free_parms.ident_type = dflt_ids[i].ident_type; + free_parms.dir = dir; + if (ulp_mapper_def_regfile_read(data, dir, reg_idx, ®val)) { + BNXT_TF_DBG(ERR, "Failed to read def regfile to free " + "identifier.\n"); + continue; + } + /* + * All regfile entries are stored as 64bit big-endian. Need + * to convert the value to cpu before calling tf. + */ + regval = tfp_be_to_cpu_64(regval); + free_parms.id = (uint16_t)regval; + /* Ignore errors and free the remaining identifiers. */ + tf_free_identifier(tfp, &free_parms); + } + +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; + } + + rte_free(data); + /* Reset the data pointer within the ulp_ctx. */ + bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); +}