+static int32_t
+ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_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->device_params->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_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;
+
+ /*
+ * 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;
+ }
+
+ /* 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_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 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");
+
+ 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;
+}
+
+static int32_t
+ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl)
+{
+ struct bnxt_ulp_mapper_result_field_info *flds;
+ struct ulp_blob data;
+ uint64_t idx;
+ uint16_t tmplen;
+ uint32_t i, num_flds;
+ int32_t rc = 0;
+ struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
+ struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
+ uint32_t encap_flds;
+
+ /* Initialize the blob data */
+ if (!ulp_blob_init(&data, tbl->result_bit_size,
+ parms->device_params->byte_order)) {
+ BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
+ return -EINVAL;
+ }
+
+ /* Get the result fields list */
+ flds = ulp_mapper_result_fields_get(tbl, &num_flds, &encap_flds);
+
+ if (!flds || !num_flds || encap_flds) {
+ BNXT_TF_DBG(ERR, "template undefined for the IF table\n");
+ return -EINVAL;
+ }
+
+ /* process the result fields, loop through them */
+ for (i = 0; i < num_flds; i++) {
+ /* Process the result fields */
+ rc = ulp_mapper_result_field_process(parms,
+ tbl->direction,
+ &flds[i],
+ &data,
+ "IFtable Result");
+ if (rc) {
+ BNXT_TF_DBG(ERR, "data field failed\n");
+ return rc;
+ }
+ }
+
+ /* Get the index details from computed 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;
+ }
+
+ /* 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][%d] failed rc=%d\n",
+ iftbl_params.type,
+ (iftbl_params.dir == TF_DIR_RX) ? "RX" : "TX",
+ iftbl_params.idx,
+ rc);
+ return rc;
+ }
+
+ /*
+ * 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_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;
+ 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;
+ }
+
+ /* 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(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;
+}
+