+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;
+}
+