+ /* Mark action process */
+ 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 (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
+ tbl->resource_type == TF_MEM_INTERNAL)
+ rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
+ goto error;
+ }
+
+ /* Link the EM 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.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);
+ if (rc) {
+ BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
+ rc);
+ /* Need to free the identifier, so goto error */
+ goto error;
+ }
+
+ return 0;
+error:
+ free_parms.dir = iparms.dir;
+ free_parms.mem = iparms.mem;
+ free_parms.tbl_scope_id = iparms.tbl_scope_id;
+ free_parms.flow_handle = iparms.flow_handle;
+
+ trc = tf_delete_em_entry(tfp, &free_parms);
+ if (trc)
+ BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
+
+ return rc;
+}
+
+static int32_t
+ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
+ struct bnxt_ulp_mapper_tbl_info *tbl,
+ bool is_class_tbl)
+{
+ struct bnxt_ulp_mapper_result_field_info *flds;
+ struct ulp_flow_db_res_params fid_parms;
+ struct ulp_blob data;
+ uint64_t idx = 0;
+ uint16_t tmplen;
+ 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;
+ struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
+ uint16_t bit_size;
+ uint32_t encap_flds = 0;
+
+ /* 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;
+ }
+
+ /* 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;
+
+ /* Initialize the blob data */
+ if (!ulp_blob_init(&data, bit_size,
+ parms->device_params->byte_order)) {
+ BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
+ return -EINVAL;
+ }
+
+ /* Get the result fields list */
+ if (is_class_tbl)
+ flds = ulp_mapper_result_fields_get(tbl, &num_flds,
+ &encap_flds);
+ else
+ flds = ulp_mapper_act_result_fields_get(tbl, &num_flds,
+ &encap_flds);
+
+ if (!flds || (!num_flds && !encap_flds)) {
+ BNXT_TF_DBG(ERR, "template undefined for the index table\n");
+ return -EINVAL;
+ }
+
+ /* process the result fields, loop through them */
+ for (i = 0; i < (num_flds + encap_flds); i++) {
+ /* set the swap index if encap swap bit is enabled */
+ if (parms->device_params->encap_byte_swap && encap_flds &&
+ (i == num_flds))
+ ulp_blob_encap_swap_idx_set(&data);
+
+ /* Process the result fields */
+ rc = ulp_mapper_result_field_process(parms,
+ tbl->direction,
+ &flds[i],
+ &data,
+ "Indexed Result");
+ if (rc) {
+ BNXT_TF_DBG(ERR, "data field failed\n");
+ return rc;
+ }
+ }
+
+ /* 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);
+ }
+
+ /*
+ * Check for index opcode, if it is Global then
+ * no need to allocate the table, just set the table
+ * and exit since it is not maintained in the flow db.
+ */
+ if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_GLOBAL) {
+ /* get the index from index operand */
+ if (tbl->index_operand < BNXT_ULP_GLB_REGFILE_INDEX_LAST &&
+ ulp_mapper_glb_resource_read(parms->mapper_data,
+ tbl->direction,
+ tbl->index_operand,
+ &idx)) {
+ BNXT_TF_DBG(ERR, "Glbl regfile[%d] read failed.\n",
+ tbl->index_operand);
+ return -EINVAL;
+ }
+ /* set the Tf index table */
+ 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 = tfp_be_to_cpu_64(idx);
+ sparms.tbl_scope_id = tbl_scope_id;
+
+ rc = tf_set_tbl_entry(tfp, &sparms);
+ if (rc) {
+ BNXT_TF_DBG(ERR,
+ "Glbl Set table[%d][%s][%d] failed rc=%d\n",
+ sparms.type,
+ (sparms.dir == TF_DIR_RX) ? "RX" : "TX",
+ sparms.idx,
+ rc);
+ return rc;
+ }
+ return 0; /* success */
+ }
+
+ index = 0;
+ hit = 0;
+ /* Perform the tf table allocation by filling the alloc params */
+ 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 (tbl->resource_type == TF_TBL_TYPE_EXT)
+ idx = TF_ACT_REC_OFFSET_2_PTR(index);
+ else
+ idx = index;
+
+ /* Always storing values in Regfile in BE */
+ idx = tfp_cpu_to_be_64(idx);
+ if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_ALLOCATE) {
+ rc = ulp_regfile_write(parms->regfile, tbl->index_operand, idx);
+ if (!rc) {
+ BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
+ tbl->index_operand);