1dd0191d5SShuanglin Wang /* SPDX-License-Identifier: BSD-3-Clause 2dd0191d5SShuanglin Wang * Copyright(c) 2014-2023 Broadcom 3dd0191d5SShuanglin Wang * All rights reserved. 4dd0191d5SShuanglin Wang */ 5dd0191d5SShuanglin Wang #include <rte_byteorder.h> 6dd0191d5SShuanglin Wang #include "ulp_mapper.h" 7dd0191d5SShuanglin Wang #include "ulp_flow_db.h" 8dd0191d5SShuanglin Wang #include "cfa_resources.h" 9dd0191d5SShuanglin Wang #include "cfa_bld.h" 10dd0191d5SShuanglin Wang #include "tfc_util.h" 11dd0191d5SShuanglin Wang #include "bnxt_ulp_tfc.h" 12*0c036a14SPeter Spreadborough #include "bnxt_ulp_utils.h" 13dd0191d5SShuanglin Wang #include "tfc_action_handle.h" 14dd0191d5SShuanglin Wang 15dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 16dd0191d5SShuanglin Wang #include "ulp_template_debug_proto.h" 17dd0191d5SShuanglin Wang #include "ulp_tf_debug.h" 18dd0191d5SShuanglin Wang #include "tfc_debug.h" 19dd0191d5SShuanglin Wang #endif 20dd0191d5SShuanglin Wang 21dd0191d5SShuanglin Wang /* Internal function to write the tcam entry */ 22dd0191d5SShuanglin Wang static int32_t 23dd0191d5SShuanglin Wang ulp_mapper_tfc_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms, 24dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl, 25dd0191d5SShuanglin Wang struct ulp_blob *key, 26dd0191d5SShuanglin Wang struct ulp_blob *mask, 27dd0191d5SShuanglin Wang struct ulp_blob *remap, 28dd0191d5SShuanglin Wang uint16_t idx) 29dd0191d5SShuanglin Wang { 30dd0191d5SShuanglin Wang struct tfc_tcam_info tfc_info = {0}; 31dd0191d5SShuanglin Wang struct tfc_tcam_data tfc_data = {0}; 32dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 33dd0191d5SShuanglin Wang uint16_t key_size = 0, mask_size = 0, remap_size = 0; 34dd0191d5SShuanglin Wang int32_t rc; 35dd0191d5SShuanglin Wang uint16_t fw_fid; 36dd0191d5SShuanglin Wang 37dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx); 38*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 39dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 40dd0191d5SShuanglin Wang return -EINVAL; 41dd0191d5SShuanglin Wang } 42dd0191d5SShuanglin Wang 43dd0191d5SShuanglin Wang rc = bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid); 44*0c036a14SPeter Spreadborough if (unlikely(rc)) 45dd0191d5SShuanglin Wang return rc; 46dd0191d5SShuanglin Wang 47dd0191d5SShuanglin Wang tfc_info.dir = tbl->direction; 48dd0191d5SShuanglin Wang tfc_info.rsubtype = tbl->resource_type; 49dd0191d5SShuanglin Wang tfc_info.id = idx; 50dd0191d5SShuanglin Wang tfc_data.key = ulp_blob_data_get(key, &key_size); 51dd0191d5SShuanglin Wang tfc_data.key_sz_in_bytes = ULP_BITS_2_BYTE(key_size); 52dd0191d5SShuanglin Wang tfc_data.mask = ulp_blob_data_get(mask, &mask_size); 53dd0191d5SShuanglin Wang tfc_data.remap = ulp_blob_data_get(remap, &remap_size); 54dd0191d5SShuanglin Wang remap_size = ULP_BITS_2_BYTE(remap_size); 55dd0191d5SShuanglin Wang tfc_data.remap_sz_in_bytes = remap_size; 56dd0191d5SShuanglin Wang 57*0c036a14SPeter Spreadborough if (unlikely(tfc_tcam_set(tfcp, fw_fid, &tfc_info, &tfc_data))) { 58dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "tcam[%s][%s][%x] write failed.\n", 59dd0191d5SShuanglin Wang tfc_tcam_2_str(tfc_info.rsubtype), 60dd0191d5SShuanglin Wang tfc_dir_2_str(tfc_info.dir), tfc_info.id); 61dd0191d5SShuanglin Wang return -EIO; 62dd0191d5SShuanglin Wang } 63dd0191d5SShuanglin Wang PMD_DRV_LOG_LINE(INFO, "tcam[%s][%s][%x] write success.", 64dd0191d5SShuanglin Wang tfc_tcam_2_str(tfc_info.rsubtype), 65dd0191d5SShuanglin Wang tfc_dir_2_str(tfc_info.dir), tfc_info.id); 66dd0191d5SShuanglin Wang 67dd0191d5SShuanglin Wang /* Mark action */ 68dd0191d5SShuanglin Wang rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 69*0c036a14SPeter Spreadborough if (unlikely(rc)) { 70dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "failed mark action processing\n"); 71dd0191d5SShuanglin Wang return rc; 72dd0191d5SShuanglin Wang } 73dd0191d5SShuanglin Wang 74dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 75dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 76dd0191d5SShuanglin Wang ulp_mapper_tcam_entry_dump("TCAM", idx, tbl, key, mask, remap); 77dd0191d5SShuanglin Wang #endif 78dd0191d5SShuanglin Wang #endif 79dd0191d5SShuanglin Wang return rc; 80dd0191d5SShuanglin Wang } 81dd0191d5SShuanglin Wang 82dd0191d5SShuanglin Wang static uint32_t 83dd0191d5SShuanglin Wang ulp_mapper_tfc_wc_tcam_post_process(struct bnxt_ulp_device_params *dparms, 84dd0191d5SShuanglin Wang struct ulp_blob *key, 85dd0191d5SShuanglin Wang struct ulp_blob *tkey) 86dd0191d5SShuanglin Wang { 87dd0191d5SShuanglin Wang uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset; 88dd0191d5SShuanglin Wang uint32_t cword, i, rc; 89dd0191d5SShuanglin Wang int32_t pad; 90dd0191d5SShuanglin Wang uint8_t *val; 91dd0191d5SShuanglin Wang 92dd0191d5SShuanglin Wang slice_width = dparms->wc_slice_width; 93dd0191d5SShuanglin Wang clen = dparms->wc_ctl_size_bits; 94dd0191d5SShuanglin Wang max_slices = dparms->wc_max_slices; 95dd0191d5SShuanglin Wang blen = ulp_blob_data_len_get(key); 96dd0191d5SShuanglin Wang 97dd0191d5SShuanglin Wang /* Get the length of the key based on number of slices and width */ 98dd0191d5SShuanglin Wang num_slices = 1; 99dd0191d5SShuanglin Wang tlen = slice_width; 100dd0191d5SShuanglin Wang while (tlen < blen && 101dd0191d5SShuanglin Wang num_slices <= max_slices) { 102dd0191d5SShuanglin Wang num_slices = num_slices << 1; 103dd0191d5SShuanglin Wang tlen = tlen << 1; 104dd0191d5SShuanglin Wang } 105dd0191d5SShuanglin Wang 106*0c036a14SPeter Spreadborough if (unlikely(num_slices > max_slices)) { 107dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Key size (%d) too large for WC\n", blen); 108dd0191d5SShuanglin Wang return -EINVAL; 109dd0191d5SShuanglin Wang } 110dd0191d5SShuanglin Wang 111dd0191d5SShuanglin Wang /* The key/mask may not be on a natural slice boundary, pad it */ 112dd0191d5SShuanglin Wang pad = tlen - blen; 113*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_pad_push(key, pad) < 0)) { 114dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Unable to pad key/mask\n"); 115dd0191d5SShuanglin Wang return -EINVAL; 116dd0191d5SShuanglin Wang } 117dd0191d5SShuanglin Wang 118dd0191d5SShuanglin Wang /* The new length accounts for the ctrl word length and num slices */ 119dd0191d5SShuanglin Wang tlen = tlen + (clen + 1) * num_slices; 120*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_init(tkey, tlen, key->byte_order))) { 121dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Unable to post process wc tcam entry\n"); 122dd0191d5SShuanglin Wang return -EINVAL; 123dd0191d5SShuanglin Wang } 124dd0191d5SShuanglin Wang 125dd0191d5SShuanglin Wang /* pad any remaining bits to do byte alignment */ 126dd0191d5SShuanglin Wang pad = (slice_width + clen) * num_slices; 127dd0191d5SShuanglin Wang pad = ULP_BYTE_ROUND_OFF_8(pad) - pad; 128*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_pad_push(tkey, pad) < 0)) { 129dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Unable to pad key/mask\n"); 130dd0191d5SShuanglin Wang return -EINVAL; 131dd0191d5SShuanglin Wang } 132dd0191d5SShuanglin Wang 133dd0191d5SShuanglin Wang /* Build the transformed key/mask */ 134dd0191d5SShuanglin Wang cword = dparms->wc_mode_list[num_slices - 1]; 135dd0191d5SShuanglin Wang cword = rte_cpu_to_be_32(cword); 136dd0191d5SShuanglin Wang offset = 0; 137dd0191d5SShuanglin Wang for (i = 0; i < num_slices; i++) { 138dd0191d5SShuanglin Wang val = ulp_blob_push_32(tkey, &cword, clen); 139*0c036a14SPeter Spreadborough if (unlikely(!val)) { 140dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Key ctrl word push failed\n"); 141dd0191d5SShuanglin Wang return -EINVAL; 142dd0191d5SShuanglin Wang } 143dd0191d5SShuanglin Wang rc = ulp_blob_append(tkey, key, offset, slice_width); 144*0c036a14SPeter Spreadborough if (unlikely(rc)) { 145dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Key blob append failed\n"); 146dd0191d5SShuanglin Wang return rc; 147dd0191d5SShuanglin Wang } 148dd0191d5SShuanglin Wang offset += slice_width; 149dd0191d5SShuanglin Wang } 150dd0191d5SShuanglin Wang blen = ulp_blob_data_len_get(tkey); 151dd0191d5SShuanglin Wang /* reverse the blob byte wise in reverse */ 152dd0191d5SShuanglin Wang ulp_blob_perform_byte_reverse(tkey, ULP_BITS_2_BYTE(blen)); 153dd0191d5SShuanglin Wang return 0; 154dd0191d5SShuanglin Wang } 155dd0191d5SShuanglin Wang 156dd0191d5SShuanglin Wang static int32_t 157dd0191d5SShuanglin Wang ulp_mapper_tfc_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 158dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl) 159dd0191d5SShuanglin Wang { 160dd0191d5SShuanglin Wang struct bnxt_ulp_device_params *dparms = parms->device_params; 161dd0191d5SShuanglin Wang struct ulp_blob okey, omask, *key, *mask, data; 162dd0191d5SShuanglin Wang struct ulp_blob tkey, tmask; /* transform key and mask */ 163dd0191d5SShuanglin Wang uint32_t alloc_tcam = 0, alloc_ident = 0, write_tcam = 0; 164dd0191d5SShuanglin Wang struct ulp_flow_db_res_params fid_parms = { 0 }; 1652aa70990SKishore Padmanabha enum cfa_track_type tt = tbl->track_type; 166dd0191d5SShuanglin Wang enum bnxt_ulp_byte_order key_byte_order; 167dd0191d5SShuanglin Wang enum bnxt_ulp_byte_order res_byte_order; 168dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_key_info *kflds; 169dd0191d5SShuanglin Wang struct tfc_tcam_info tfc_inf = {0}; 170dd0191d5SShuanglin Wang uint16_t key_sz_in_words = 0, key_sz_in_bits = 0; 171dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 172dd0191d5SShuanglin Wang uint32_t num_kflds, i; 173dd0191d5SShuanglin Wang uint32_t priority; 174dd0191d5SShuanglin Wang int32_t rc = 0, free_rc = 0; 175dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 176dd0191d5SShuanglin Wang 177dd0191d5SShuanglin Wang /* Set the key and mask to the original key and mask. */ 178dd0191d5SShuanglin Wang key = &okey; 179dd0191d5SShuanglin Wang mask = &omask; 180dd0191d5SShuanglin Wang 181dd0191d5SShuanglin Wang switch (tbl->tbl_opcode) { 182dd0191d5SShuanglin Wang case BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT: 183dd0191d5SShuanglin Wang alloc_ident = 1; 184dd0191d5SShuanglin Wang break; 185dd0191d5SShuanglin Wang case BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE: 186dd0191d5SShuanglin Wang alloc_ident = 1; 187dd0191d5SShuanglin Wang alloc_tcam = 1; 188dd0191d5SShuanglin Wang write_tcam = 1; 189dd0191d5SShuanglin Wang break; 190dd0191d5SShuanglin Wang case BNXT_ULP_TCAM_TBL_OPC_NOT_USED: 191dd0191d5SShuanglin Wang case BNXT_ULP_TCAM_TBL_OPC_LAST: 192dd0191d5SShuanglin Wang default: 193dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Invalid tcam table opcode %d\n", 194dd0191d5SShuanglin Wang tbl->tbl_opcode); 195dd0191d5SShuanglin Wang return -EINVAL; 196dd0191d5SShuanglin Wang } 197dd0191d5SShuanglin Wang 198dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx); 199*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 200dd0191d5SShuanglin Wang PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer"); 201dd0191d5SShuanglin Wang return -EINVAL; 202dd0191d5SShuanglin Wang } 203dd0191d5SShuanglin Wang 204*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid))) { 205dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 206dd0191d5SShuanglin Wang return -EINVAL; 207dd0191d5SShuanglin Wang } 208dd0191d5SShuanglin Wang 209dd0191d5SShuanglin Wang /* Allocate the identifiers */ 210dd0191d5SShuanglin Wang if (alloc_ident) { 211dd0191d5SShuanglin Wang rc = ulp_mapper_tcam_tbl_ident_alloc(parms, tbl); 212*0c036a14SPeter Spreadborough if (unlikely(rc)) { 213dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to alloc identifier\n"); 214dd0191d5SShuanglin Wang return rc; 215dd0191d5SShuanglin Wang } 216dd0191d5SShuanglin Wang } 217dd0191d5SShuanglin Wang 218dd0191d5SShuanglin Wang /* If no allocation or write is needed, then just exit */ 219*0c036a14SPeter Spreadborough if (unlikely(!alloc_tcam && !write_tcam)) 220dd0191d5SShuanglin Wang return rc; 221dd0191d5SShuanglin Wang 222dd0191d5SShuanglin Wang /* Initialize the blobs for write */ 223dd0191d5SShuanglin Wang if (tbl->resource_type == CFA_RSUBTYPE_TCAM_WC) 224dd0191d5SShuanglin Wang key_byte_order = dparms->wc_key_byte_order; 225dd0191d5SShuanglin Wang else 226dd0191d5SShuanglin Wang key_byte_order = dparms->key_byte_order; 227dd0191d5SShuanglin Wang 228dd0191d5SShuanglin Wang res_byte_order = dparms->result_byte_order; 229*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) || 230c569279aSShuanglin Wang ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) || 231*0c036a14SPeter Spreadborough ulp_blob_init(&data, tbl->result_bit_size, res_byte_order))) { 232dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "blob inits failed.\n"); 233dd0191d5SShuanglin Wang return -EINVAL; 234dd0191d5SShuanglin Wang } 235dd0191d5SShuanglin Wang 236dd0191d5SShuanglin Wang /* Get the key fields and update the key blob */ 237dd0191d5SShuanglin Wang if (tbl->key_recipe_opcode == BNXT_ULP_KEY_RECIPE_OPC_DYN_KEY) 238dd0191d5SShuanglin Wang kflds = ulp_mapper_key_recipe_fields_get(parms, tbl, &num_kflds); 239dd0191d5SShuanglin Wang else 240dd0191d5SShuanglin Wang kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 241*0c036a14SPeter Spreadborough if (unlikely(!kflds || !num_kflds)) { 242dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get key fields\n"); 243dd0191d5SShuanglin Wang return -EINVAL; 244dd0191d5SShuanglin Wang } 245dd0191d5SShuanglin Wang 246dd0191d5SShuanglin Wang for (i = 0; i < num_kflds; i++) { 247dd0191d5SShuanglin Wang /* Setup the key */ 248dd0191d5SShuanglin Wang rc = ulp_mapper_field_opc_process(parms, tbl->direction, 249dd0191d5SShuanglin Wang &kflds[i].field_info_spec, 250dd0191d5SShuanglin Wang key, 1, "TCAM Key"); 251*0c036a14SPeter Spreadborough if (unlikely(rc)) { 252dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Key field set failed %s\n", 253dd0191d5SShuanglin Wang kflds[i].field_info_spec.description); 254dd0191d5SShuanglin Wang return rc; 255dd0191d5SShuanglin Wang } 256dd0191d5SShuanglin Wang 257dd0191d5SShuanglin Wang /* Setup the mask */ 258dd0191d5SShuanglin Wang rc = ulp_mapper_field_opc_process(parms, tbl->direction, 259dd0191d5SShuanglin Wang &kflds[i].field_info_mask, 260dd0191d5SShuanglin Wang mask, 0, "TCAM Mask"); 261*0c036a14SPeter Spreadborough if (unlikely(rc)) { 262dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Mask field set failed %s\n", 263dd0191d5SShuanglin Wang kflds[i].field_info_mask.description); 264dd0191d5SShuanglin Wang return rc; 265dd0191d5SShuanglin Wang } 266dd0191d5SShuanglin Wang } 267dd0191d5SShuanglin Wang 268dd0191d5SShuanglin Wang /* For wild card tcam perform the post process to swap the blob */ 269dd0191d5SShuanglin Wang if (tbl->resource_type == CFA_RSUBTYPE_TCAM_WC) { 270dd0191d5SShuanglin Wang /* Sets up the slices for writing to the WC TCAM */ 271dd0191d5SShuanglin Wang rc = ulp_mapper_tfc_wc_tcam_post_process(dparms, key, &tkey); 272*0c036a14SPeter Spreadborough if (unlikely(rc)) { 273dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 274dd0191d5SShuanglin Wang "Failed to post proc WC key.\n"); 275dd0191d5SShuanglin Wang return rc; 276dd0191d5SShuanglin Wang } 277dd0191d5SShuanglin Wang /* Sets up the slices for writing to the WC TCAM */ 278dd0191d5SShuanglin Wang rc = ulp_mapper_tfc_wc_tcam_post_process(dparms, mask, &tmask); 279*0c036a14SPeter Spreadborough if (unlikely(rc)) { 280dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 281dd0191d5SShuanglin Wang "Failed to post proc WC mask.\n"); 282dd0191d5SShuanglin Wang return rc; 283dd0191d5SShuanglin Wang } 284dd0191d5SShuanglin Wang key = &tkey; 285dd0191d5SShuanglin Wang mask = &tmask; 286dd0191d5SShuanglin Wang } 287dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 288dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 289dd0191d5SShuanglin Wang ulp_mapper_tcam_entry_dump("TCAM", 0, tbl, key, mask, &data); 290dd0191d5SShuanglin Wang #endif 291dd0191d5SShuanglin Wang #endif 292dd0191d5SShuanglin Wang 293dd0191d5SShuanglin Wang if (alloc_tcam) { 294dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx); 295*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 296dd0191d5SShuanglin Wang PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer"); 297dd0191d5SShuanglin Wang return -EINVAL; 298dd0191d5SShuanglin Wang } 299dd0191d5SShuanglin Wang /* calculate the entry priority*/ 300dd0191d5SShuanglin Wang rc = ulp_mapper_priority_opc_process(parms, tbl, 301dd0191d5SShuanglin Wang &priority); 302*0c036a14SPeter Spreadborough if (unlikely(rc)) { 303dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "entry priority process failed\n"); 304dd0191d5SShuanglin Wang return rc; 305dd0191d5SShuanglin Wang } 306dd0191d5SShuanglin Wang 307dd0191d5SShuanglin Wang /* allocate the tcam entry, only need the length */ 308dd0191d5SShuanglin Wang (void)ulp_blob_data_get(key, &key_sz_in_bits); 309dd0191d5SShuanglin Wang key_sz_in_words = ULP_BITS_2_BYTE(key_sz_in_bits); 310dd0191d5SShuanglin Wang tfc_inf.dir = tbl->direction; /* PKB.need an api */ 311dd0191d5SShuanglin Wang tfc_inf.rsubtype = tbl->resource_type; 312dd0191d5SShuanglin Wang 313dd0191d5SShuanglin Wang rc = tfc_tcam_alloc(tfcp, fw_fid, tt, priority, 314dd0191d5SShuanglin Wang key_sz_in_words, &tfc_inf); 315*0c036a14SPeter Spreadborough if (unlikely(rc)) { 316dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "TCAM Alloc failed, status:%d\n", rc); 317dd0191d5SShuanglin Wang return rc; 318dd0191d5SShuanglin Wang } 319dd0191d5SShuanglin Wang 320dd0191d5SShuanglin Wang /* Write the tcam index into the regfile*/ 321*0c036a14SPeter Spreadborough if (unlikely(ulp_regfile_write(parms->regfile, tbl->tbl_operand, 322*0c036a14SPeter Spreadborough (uint64_t)rte_cpu_to_be_64(tfc_inf.id)))) { 323dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Regfile[%d] write failed.\n", 324dd0191d5SShuanglin Wang tbl->tbl_operand); 325dd0191d5SShuanglin Wang /* Need to free the tcam idx, so goto error */ 326dd0191d5SShuanglin Wang goto error; 327dd0191d5SShuanglin Wang } 328dd0191d5SShuanglin Wang } 329dd0191d5SShuanglin Wang 330dd0191d5SShuanglin Wang if (write_tcam) { 331dd0191d5SShuanglin Wang /* Create the result blob */ 332dd0191d5SShuanglin Wang rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 333dd0191d5SShuanglin Wang "TCAM Result"); 334dd0191d5SShuanglin Wang /* write the tcam entry */ 335dd0191d5SShuanglin Wang if (!rc) 336dd0191d5SShuanglin Wang rc = ulp_mapper_tfc_tcam_tbl_entry_write(parms, 337dd0191d5SShuanglin Wang tbl, key, 338dd0191d5SShuanglin Wang mask, &data, 339dd0191d5SShuanglin Wang tfc_inf.id); 340dd0191d5SShuanglin Wang } 341dd0191d5SShuanglin Wang if (rc) 342dd0191d5SShuanglin Wang goto error; 343dd0191d5SShuanglin Wang 344dd0191d5SShuanglin Wang /* Add the tcam index to the flow database */ 345dd0191d5SShuanglin Wang fid_parms.direction = tbl->direction; 346dd0191d5SShuanglin Wang fid_parms.resource_func = tbl->resource_func; 347dd0191d5SShuanglin Wang fid_parms.resource_type = tbl->resource_type; 348dd0191d5SShuanglin Wang fid_parms.critical_resource = tbl->critical_resource; 349dd0191d5SShuanglin Wang fid_parms.resource_hndl = tfc_inf.id; 350dd0191d5SShuanglin Wang ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 351dd0191d5SShuanglin Wang 352dd0191d5SShuanglin Wang rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 353*0c036a14SPeter Spreadborough if (unlikely(rc)) { 354dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 355dd0191d5SShuanglin Wang rc); 356dd0191d5SShuanglin Wang /* Need to free the identifier, so goto error */ 357dd0191d5SShuanglin Wang goto error; 358dd0191d5SShuanglin Wang } 359dd0191d5SShuanglin Wang 360dd0191d5SShuanglin Wang return 0; 361dd0191d5SShuanglin Wang error: 362dd0191d5SShuanglin Wang free_rc = tfc_tcam_free(tfcp, fw_fid, &tfc_inf); 363dd0191d5SShuanglin Wang if (free_rc) 364dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "TCAM free failed on error, status:%d\n", 365dd0191d5SShuanglin Wang free_rc); 366dd0191d5SShuanglin Wang return rc; 367dd0191d5SShuanglin Wang } 368dd0191d5SShuanglin Wang 369dd0191d5SShuanglin Wang static const char * const mpc_error_str[] = { 370dd0191d5SShuanglin Wang "OK", 371dd0191d5SShuanglin Wang "Unsupported Opcode", 372dd0191d5SShuanglin Wang "Bad Format", 373dd0191d5SShuanglin Wang "Invalid Scope", 374dd0191d5SShuanglin Wang "Bad Address", 375dd0191d5SShuanglin Wang "Cache Error", 376dd0191d5SShuanglin Wang "EM Miss", 377dd0191d5SShuanglin Wang "Duplicate Entry", 378dd0191d5SShuanglin Wang "No Events", 379dd0191d5SShuanglin Wang "EM Abort" 380dd0191d5SShuanglin Wang }; 381dd0191d5SShuanglin Wang 382dd0191d5SShuanglin Wang /* 383dd0191d5SShuanglin Wang * TBD: Temporary swap until a more generic solution is designed 384dd0191d5SShuanglin Wang * 385dd0191d5SShuanglin Wang * blob [inout] A byte array that is being edited in-place 386dd0191d5SShuanglin Wang * block_sz [in] The size of the blocks in bytes to swap 387dd0191d5SShuanglin Wang * 388dd0191d5SShuanglin Wang * The length of the blob is assumed to be a multiple of block_sz 389dd0191d5SShuanglin Wang */ 390dd0191d5SShuanglin Wang static int32_t 391dd0191d5SShuanglin Wang ulp_mapper_blob_block_swap(struct ulp_blob *blob, uint32_t block_sz) 392dd0191d5SShuanglin Wang { 393dd0191d5SShuanglin Wang uint8_t data[block_sz]; /* size of a block for temp storage */ 394dd0191d5SShuanglin Wang uint16_t num_words, data_sz; 395dd0191d5SShuanglin Wang uint8_t *pdata; 396dd0191d5SShuanglin Wang int i; 397dd0191d5SShuanglin Wang 398dd0191d5SShuanglin Wang /* Shouldn't happen since it is internal function, but check anyway */ 399*0c036a14SPeter Spreadborough if (unlikely(blob == NULL || !block_sz)) { 400dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Invalid arguments\n"); 401dd0191d5SShuanglin Wang return -EINVAL; 402dd0191d5SShuanglin Wang } 403dd0191d5SShuanglin Wang 404dd0191d5SShuanglin Wang pdata = ulp_blob_data_get(blob, &data_sz); 405dd0191d5SShuanglin Wang data_sz = ULP_BITS_2_BYTE(data_sz); 406*0c036a14SPeter Spreadborough if (unlikely(!data_sz || (data_sz % block_sz) != 0)) { 407dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "length(%d) not a multiple of %d\n", 408dd0191d5SShuanglin Wang data_sz, block_sz); 409dd0191d5SShuanglin Wang return -EINVAL; 410dd0191d5SShuanglin Wang } 411dd0191d5SShuanglin Wang 412dd0191d5SShuanglin Wang num_words = data_sz / block_sz; 413dd0191d5SShuanglin Wang for (i = 0; i < num_words / 2; i++) { 414dd0191d5SShuanglin Wang memcpy(data, &pdata[i * block_sz], block_sz); 415dd0191d5SShuanglin Wang memcpy(&pdata[i * block_sz], 416dd0191d5SShuanglin Wang &pdata[(num_words - 1 - i) * block_sz], block_sz); 417dd0191d5SShuanglin Wang memcpy(&pdata[(num_words - 1 - i) * block_sz], 418dd0191d5SShuanglin Wang data, block_sz); 419dd0191d5SShuanglin Wang } 420dd0191d5SShuanglin Wang return 0; 421dd0191d5SShuanglin Wang } 422dd0191d5SShuanglin Wang 423dd0191d5SShuanglin Wang static int 424dd0191d5SShuanglin Wang ulp_mapper_tfc_mpc_batch_end(struct tfc *tfcp, 425dd0191d5SShuanglin Wang struct tfc_mpc_batch_info_t *batch_info) 426dd0191d5SShuanglin Wang { 427dd0191d5SShuanglin Wang uint32_t i; 428dd0191d5SShuanglin Wang int rc; 429dd0191d5SShuanglin Wang 430dd0191d5SShuanglin Wang rc = tfc_mpc_batch_end(tfcp, batch_info); 431dd0191d5SShuanglin Wang if (unlikely(rc)) 432dd0191d5SShuanglin Wang return rc; 433dd0191d5SShuanglin Wang 434dd0191d5SShuanglin Wang for (i = 0; i < batch_info->count; i++) { 435dd0191d5SShuanglin Wang if (!batch_info->result[i]) 436dd0191d5SShuanglin Wang continue; 437dd0191d5SShuanglin Wang 438dd0191d5SShuanglin Wang switch (batch_info->comp_info[i].type) { 439dd0191d5SShuanglin Wang case TFC_MPC_EM_INSERT: 440dd0191d5SShuanglin Wang batch_info->em_error = batch_info->result[i]; 441dd0191d5SShuanglin Wang break; 442dd0191d5SShuanglin Wang default: 443dd0191d5SShuanglin Wang if (batch_info->result[i] && !batch_info->error) 444dd0191d5SShuanglin Wang batch_info->error = batch_info->result[i]; 445dd0191d5SShuanglin Wang break; 446dd0191d5SShuanglin Wang } 447dd0191d5SShuanglin Wang } 448dd0191d5SShuanglin Wang 449dd0191d5SShuanglin Wang return rc; 450dd0191d5SShuanglin Wang } 451dd0191d5SShuanglin Wang 452dd0191d5SShuanglin Wang static bool 453dd0191d5SShuanglin Wang ulp_mapper_tfc_mpc_batch_started(struct tfc_mpc_batch_info_t *batch_info) 454dd0191d5SShuanglin Wang { 455dd0191d5SShuanglin Wang return tfc_mpc_batch_started(batch_info); 456dd0191d5SShuanglin Wang } 457dd0191d5SShuanglin Wang 458dd0191d5SShuanglin Wang static int32_t 459dd0191d5SShuanglin Wang ulp_mapper_tfc_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 460dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl, 461dd0191d5SShuanglin Wang void *error) 462dd0191d5SShuanglin Wang { 463dd0191d5SShuanglin Wang struct bnxt_ulp_device_params *dparms = parms->device_params; 464dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_key_info *kflds; 465dd0191d5SShuanglin Wang struct tfc_em_delete_parms free_parms = { 0 }; 466dd0191d5SShuanglin Wang struct tfc_em_insert_parms iparms = { 0 }; 467dd0191d5SShuanglin Wang struct ulp_flow_db_res_params fid_parms = { 0 }; 468dd0191d5SShuanglin Wang uint16_t tmplen, key_len, align_len_bits; 469dd0191d5SShuanglin Wang enum bnxt_ulp_byte_order byte_order; 470dd0191d5SShuanglin Wang struct ulp_blob key, data; 471dd0191d5SShuanglin Wang uint32_t i, num_kflds; 472dd0191d5SShuanglin Wang uint64_t handle = 0; 473dd0191d5SShuanglin Wang struct tfc *tfcp; 474dd0191d5SShuanglin Wang int32_t trc = 0; 475dd0191d5SShuanglin Wang uint8_t tsid = 0; 476dd0191d5SShuanglin Wang int32_t rc = 0; 477dd0191d5SShuanglin Wang 478dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx); 479*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 480dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 481dd0191d5SShuanglin Wang return -EINVAL; 482dd0191d5SShuanglin Wang } 483dd0191d5SShuanglin Wang 484dd0191d5SShuanglin Wang if (tbl->key_recipe_opcode == BNXT_ULP_KEY_RECIPE_OPC_DYN_KEY) 485dd0191d5SShuanglin Wang kflds = ulp_mapper_key_recipe_fields_get(parms, tbl, &num_kflds); 486dd0191d5SShuanglin Wang else 487dd0191d5SShuanglin Wang kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 488*0c036a14SPeter Spreadborough if (unlikely(!kflds || !num_kflds)) { 489dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get key fields\n"); 490dd0191d5SShuanglin Wang return -EINVAL; 491dd0191d5SShuanglin Wang } 492dd0191d5SShuanglin Wang 493dd0191d5SShuanglin Wang byte_order = dparms->em_byte_order; 494dd0191d5SShuanglin Wang /* Initialize the key/result blobs */ 495*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_init(&key, tbl->blob_key_bit_size, byte_order) || 496*0c036a14SPeter Spreadborough ulp_blob_init(&data, tbl->result_bit_size, byte_order))) { 497dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "blob inits failed.\n"); 498dd0191d5SShuanglin Wang return -EINVAL; 499dd0191d5SShuanglin Wang } 500dd0191d5SShuanglin Wang 501dd0191d5SShuanglin Wang /* create the key */ 502dd0191d5SShuanglin Wang for (i = 0; i < num_kflds; i++) { 503dd0191d5SShuanglin Wang /* Setup the key */ 504dd0191d5SShuanglin Wang rc = ulp_mapper_field_opc_process(parms, tbl->direction, 505dd0191d5SShuanglin Wang &kflds[i].field_info_spec, 506dd0191d5SShuanglin Wang &key, 1, "EM Key"); 507*0c036a14SPeter Spreadborough if (unlikely(rc)) { 508dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Key field set failed.\n"); 509dd0191d5SShuanglin Wang return rc; 510dd0191d5SShuanglin Wang } 511dd0191d5SShuanglin Wang } 512dd0191d5SShuanglin Wang /* add padding to make sure key is at record boundary */ 513dd0191d5SShuanglin Wang key_len = ulp_blob_data_len_get(&key); 514dd0191d5SShuanglin Wang if (key_len > dparms->em_blk_align_bits) { 515dd0191d5SShuanglin Wang key_len = key_len - dparms->em_blk_align_bits; 516dd0191d5SShuanglin Wang align_len_bits = dparms->em_blk_size_bits - 517dd0191d5SShuanglin Wang (key_len % dparms->em_blk_size_bits); 518dd0191d5SShuanglin Wang } else { 519dd0191d5SShuanglin Wang align_len_bits = dparms->em_blk_align_bits - key_len; 520dd0191d5SShuanglin Wang } 521dd0191d5SShuanglin Wang 522dd0191d5SShuanglin Wang ulp_blob_pad_push(&key, align_len_bits); 523dd0191d5SShuanglin Wang key_len = ULP_BITS_2_BYTE(ulp_blob_data_len_get(&key)); 524dd0191d5SShuanglin Wang ulp_blob_perform_byte_reverse(&key, key_len); 525dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 526dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 527dd0191d5SShuanglin Wang ulp_mapper_result_dump("EM Key", tbl, &key); 528dd0191d5SShuanglin Wang #endif 529dd0191d5SShuanglin Wang #endif 530dd0191d5SShuanglin Wang /* Create the result data blob */ 531dd0191d5SShuanglin Wang rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result"); 532*0c036a14SPeter Spreadborough if (unlikely(rc)) { 533dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 534dd0191d5SShuanglin Wang return rc; 535dd0191d5SShuanglin Wang } 536dd0191d5SShuanglin Wang ulp_blob_pad_align(&data, dparms->em_blk_align_bits); 537dd0191d5SShuanglin Wang key_len = ULP_BITS_2_BYTE(ulp_blob_data_len_get(&data)); 538dd0191d5SShuanglin Wang ulp_blob_perform_byte_reverse(&data, key_len); 539dd0191d5SShuanglin Wang 540dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 541dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 542dd0191d5SShuanglin Wang ulp_mapper_result_dump("EM Result", tbl, &data); 543dd0191d5SShuanglin Wang #endif 544dd0191d5SShuanglin Wang #endif 545dd0191d5SShuanglin Wang rc = ulp_blob_append(&key, &data, 0, dparms->em_blk_align_bits); 546*0c036a14SPeter Spreadborough if (unlikely(rc)) { 547dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "EM Failed to append the result to key(%d)", 548dd0191d5SShuanglin Wang rc); 549dd0191d5SShuanglin Wang return rc; 550dd0191d5SShuanglin Wang } 551dd0191d5SShuanglin Wang /* TBD: Need to come up with a more generic way to know when to swap, 552dd0191d5SShuanglin Wang * this is fine for now as this driver only supports this device. 553dd0191d5SShuanglin Wang */ 554dd0191d5SShuanglin Wang rc = ulp_mapper_blob_block_swap(&key, 555dd0191d5SShuanglin Wang ULP_BITS_2_BYTE(dparms->em_blk_size_bits)); 556dd0191d5SShuanglin Wang /* Error printed within function, just return on error */ 557*0c036a14SPeter Spreadborough if (unlikely(rc)) 558dd0191d5SShuanglin Wang return rc; 559dd0191d5SShuanglin Wang 560dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 561dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 562dd0191d5SShuanglin Wang ulp_mapper_result_dump("EM Merged Result", tbl, &key); 563dd0191d5SShuanglin Wang #endif 564dd0191d5SShuanglin Wang #endif 565dd0191d5SShuanglin Wang iparms.dir = tbl->direction; 566dd0191d5SShuanglin Wang iparms.lkup_key_data = ulp_blob_data_get(&key, &tmplen); 567dd0191d5SShuanglin Wang iparms.lkup_key_sz_words = ULP_BITS_TO_32_BYTE_WORD(tmplen); 568dd0191d5SShuanglin Wang iparms.key_data = NULL; 569dd0191d5SShuanglin Wang iparms.key_sz_bits = 0; 570dd0191d5SShuanglin Wang iparms.flow_handle = &handle; 571dd0191d5SShuanglin Wang iparms.batch_info = &parms->batch_info; 572dd0191d5SShuanglin Wang 573dd0191d5SShuanglin Wang rc = bnxt_ulp_cntxt_tsid_get(parms->ulp_ctx, &tsid); 574*0c036a14SPeter Spreadborough if (unlikely(rc)) { 575dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get the table scope\n"); 576dd0191d5SShuanglin Wang return rc; 577dd0191d5SShuanglin Wang } 578dd0191d5SShuanglin Wang 579dd0191d5SShuanglin Wang rc = tfc_em_insert(tfcp, tsid, &iparms); 580dd0191d5SShuanglin Wang 581dd0191d5SShuanglin Wang if (likely(tfc_mpc_batch_started(&parms->batch_info))) { 582dd0191d5SShuanglin Wang int trc; 583dd0191d5SShuanglin Wang int em_index = parms->batch_info.count - 1; 584dd0191d5SShuanglin Wang 585dd0191d5SShuanglin Wang parms->batch_info.em_hdl[em_index] = *iparms.flow_handle; 586dd0191d5SShuanglin Wang 587dd0191d5SShuanglin Wang trc = ulp_mapper_tfc_mpc_batch_end(tfcp, &parms->batch_info); 588dd0191d5SShuanglin Wang if (unlikely(trc)) 589dd0191d5SShuanglin Wang return trc; 590dd0191d5SShuanglin Wang 591dd0191d5SShuanglin Wang *iparms.flow_handle = parms->batch_info.em_hdl[em_index]; 592dd0191d5SShuanglin Wang 593dd0191d5SShuanglin Wang /* Has there been an error? */ 594dd0191d5SShuanglin Wang if (unlikely(parms->batch_info.error)) { 595dd0191d5SShuanglin Wang /* If there's not an EM error the entry will need to 596dd0191d5SShuanglin Wang * be deleted 597dd0191d5SShuanglin Wang */ 598dd0191d5SShuanglin Wang if (!parms->batch_info.em_error) { 599dd0191d5SShuanglin Wang rc = parms->batch_info.error; 600dd0191d5SShuanglin Wang goto error; 601dd0191d5SShuanglin Wang } 602dd0191d5SShuanglin Wang } 603dd0191d5SShuanglin Wang 604dd0191d5SShuanglin Wang rc = parms->batch_info.em_error; 605dd0191d5SShuanglin Wang } 606dd0191d5SShuanglin Wang 607dd0191d5SShuanglin Wang if (unlikely(rc)) { 608af50070eSKishore Padmanabha /* Set the error flag in reg file */ 609af50070eSKishore Padmanabha if (tbl->tbl_opcode == BNXT_ULP_EM_TBL_OPC_WR_REGFILE) { 610af50070eSKishore Padmanabha uint64_t val = 0; 611dd0191d5SShuanglin Wang 612be4732e8SMike Baucom /* hash collision */ 613*0c036a14SPeter Spreadborough if (unlikely(rc == -E2BIG)) 614be4732e8SMike Baucom BNXT_DRV_DBG(DEBUG, "Duplicate EM entry\n"); 615be4732e8SMike Baucom 616be4732e8SMike Baucom /* over max flows */ 617be4732e8SMike Baucom if (rc == -ENOMEM) { 618af50070eSKishore Padmanabha val = 1; 619af50070eSKishore Padmanabha rc = 0; 620af50070eSKishore Padmanabha BNXT_DRV_DBG(DEBUG, 621af50070eSKishore Padmanabha "Fail to insert EM, shall add to wc\n"); 622af50070eSKishore Padmanabha } 623af50070eSKishore Padmanabha ulp_regfile_write(parms->regfile, tbl->tbl_operand, 624af50070eSKishore Padmanabha rte_cpu_to_be_64(val)); 625af50070eSKishore Padmanabha } 626be4732e8SMike Baucom 627be4732e8SMike Baucom if (rc && rc != -E2BIG) 628af50070eSKishore Padmanabha BNXT_DRV_DBG(ERR, 629af50070eSKishore Padmanabha "Failed to insert em entry rc=%d.\n", rc); 630be4732e8SMike Baucom 631af50070eSKishore Padmanabha if (rc && error != NULL && tfc_is_mpc_error(rc)) 632af50070eSKishore Padmanabha rte_flow_error_set((struct rte_flow_error *)error, EIO, 633af50070eSKishore Padmanabha RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 634af50070eSKishore Padmanabha mpc_error_str[rc * -1]); 635dd0191d5SShuanglin Wang return rc; 636dd0191d5SShuanglin Wang } 637dd0191d5SShuanglin Wang 638dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 639dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 640dd0191d5SShuanglin Wang ulp_mapper_tfc_em_dump("EM", &key, &iparms); 641dd0191d5SShuanglin Wang #endif 642dd0191d5SShuanglin Wang #endif 643dd0191d5SShuanglin Wang /* Mark action process */ 644dd0191d5SShuanglin Wang rc = ulp_mapper_mark_gfid_process(parms, tbl, *iparms.flow_handle); 645*0c036a14SPeter Spreadborough if (unlikely(rc)) { 646dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to add mark to flow\n"); 647dd0191d5SShuanglin Wang goto error; 648dd0191d5SShuanglin Wang } 649dd0191d5SShuanglin Wang 650dd0191d5SShuanglin Wang /* Link the EM resource to the flow in the flow db */ 651dd0191d5SShuanglin Wang memset(&fid_parms, 0, sizeof(fid_parms)); 652dd0191d5SShuanglin Wang fid_parms.direction = tbl->direction; 653dd0191d5SShuanglin Wang fid_parms.resource_func = tbl->resource_func; 654dd0191d5SShuanglin Wang fid_parms.resource_type = tbl->resource_type; 655dd0191d5SShuanglin Wang fid_parms.critical_resource = tbl->critical_resource; 656dd0191d5SShuanglin Wang fid_parms.resource_hndl = *iparms.flow_handle; 657dd0191d5SShuanglin Wang 658dd0191d5SShuanglin Wang rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 659*0c036a14SPeter Spreadborough if (unlikely(rc)) { 660dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 661dd0191d5SShuanglin Wang /* Need to free the identifier, so goto error */ 662dd0191d5SShuanglin Wang goto error; 663dd0191d5SShuanglin Wang } 664dd0191d5SShuanglin Wang 665dd0191d5SShuanglin Wang return 0; 666dd0191d5SShuanglin Wang error: 667dd0191d5SShuanglin Wang free_parms.dir = iparms.dir; 668dd0191d5SShuanglin Wang free_parms.flow_handle = *iparms.flow_handle; 669dd0191d5SShuanglin Wang free_parms.batch_info = &parms->batch_info; 670dd0191d5SShuanglin Wang 671dd0191d5SShuanglin Wang trc = tfc_em_delete(tfcp, &free_parms); 672dd0191d5SShuanglin Wang if (trc) 673dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to delete EM entry on failed add\n"); 674dd0191d5SShuanglin Wang 675dd0191d5SShuanglin Wang return rc; 676dd0191d5SShuanglin Wang } 677dd0191d5SShuanglin Wang 678dd0191d5SShuanglin Wang static int32_t 679dd0191d5SShuanglin Wang ulp_mapper_tfc_em_entry_free(struct bnxt_ulp_context *ulp, 680dd0191d5SShuanglin Wang struct ulp_flow_db_res_params *res, 681dd0191d5SShuanglin Wang void *error) 682dd0191d5SShuanglin Wang { 683dd0191d5SShuanglin Wang struct tfc_em_delete_parms free_parms = { 0 }; 684dd0191d5SShuanglin Wang struct tfc *tfcp; 685dd0191d5SShuanglin Wang int32_t rc = 0; 686dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 687dd0191d5SShuanglin Wang struct tfc_mpc_batch_info_t batch_info; 688dd0191d5SShuanglin Wang 689dd0191d5SShuanglin Wang memset(&batch_info, 0, sizeof(batch_info)); 690dd0191d5SShuanglin Wang 691*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(ulp, &fw_fid))) { 692dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 693dd0191d5SShuanglin Wang return -EINVAL; 694dd0191d5SShuanglin Wang } 695dd0191d5SShuanglin Wang 696dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(ulp); 697*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 698dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 699dd0191d5SShuanglin Wang return -EINVAL; 700dd0191d5SShuanglin Wang } 701dd0191d5SShuanglin Wang 702dd0191d5SShuanglin Wang free_parms.dir = (enum cfa_dir)res->direction; 703dd0191d5SShuanglin Wang free_parms.flow_handle = res->resource_hndl; 704dd0191d5SShuanglin Wang free_parms.batch_info = &batch_info; 705dd0191d5SShuanglin Wang 706dd0191d5SShuanglin Wang rc = tfc_em_delete(tfcp, &free_parms); 707dd0191d5SShuanglin Wang if (rc) { 708dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 709dd0191d5SShuanglin Wang "Failed to delete EM entry, res = 0x%" PRIx64 "\n", 710dd0191d5SShuanglin Wang res->resource_hndl); 711dd0191d5SShuanglin Wang if (error != NULL && tfc_is_mpc_error(rc)) { 712dd0191d5SShuanglin Wang struct rte_flow_error *fe = (struct rte_flow_error *)error; 713dd0191d5SShuanglin Wang rte_flow_error_set(fe, 714dd0191d5SShuanglin Wang EIO, 715dd0191d5SShuanglin Wang RTE_FLOW_ERROR_TYPE_HANDLE, 716dd0191d5SShuanglin Wang NULL, 717dd0191d5SShuanglin Wang mpc_error_str[rc * -1]); 718dd0191d5SShuanglin Wang } 719dd0191d5SShuanglin Wang } else { 720dd0191d5SShuanglin Wang BNXT_DRV_DBG(DEBUG, "Deleted EM entry, res = 0x%" PRIx64 "\n", 721dd0191d5SShuanglin Wang res->resource_hndl); 722dd0191d5SShuanglin Wang } 723dd0191d5SShuanglin Wang 724dd0191d5SShuanglin Wang return rc; 725dd0191d5SShuanglin Wang } 726dd0191d5SShuanglin Wang 727dd0191d5SShuanglin Wang static uint16_t 728dd0191d5SShuanglin Wang ulp_mapper_tfc_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms, 729dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl) 730dd0191d5SShuanglin Wang { 731dd0191d5SShuanglin Wang struct bnxt_ulp_device_params *d_params = mparms->device_params; 732dd0191d5SShuanglin Wang 733dd0191d5SShuanglin Wang if (d_params->dynamic_sram_en) { 734dd0191d5SShuanglin Wang switch (tbl->resource_type) { 735dd0191d5SShuanglin Wang /* TBD: add more types here */ 736dd0191d5SShuanglin Wang case CFA_BLD_ACT_OBJ_TYPE_STAT: 737dd0191d5SShuanglin Wang case CFA_BLD_ACT_OBJ_TYPE_ENCAP: 738dd0191d5SShuanglin Wang case CFA_BLD_ACT_OBJ_TYPE_MODIFY: 739dd0191d5SShuanglin Wang /* return max size */ 740dd0191d5SShuanglin Wang return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 741dd0191d5SShuanglin Wang default: 742dd0191d5SShuanglin Wang break; 743dd0191d5SShuanglin Wang } 744dd0191d5SShuanglin Wang } else if (tbl->encap_num_fields) { 745dd0191d5SShuanglin Wang return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 746dd0191d5SShuanglin Wang } 747dd0191d5SShuanglin Wang return tbl->result_bit_size; 748dd0191d5SShuanglin Wang } 749dd0191d5SShuanglin Wang 750dd0191d5SShuanglin Wang static int32_t 751dd0191d5SShuanglin Wang ulp_mapper_tfc_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 752dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl) 753dd0191d5SShuanglin Wang { 754dd0191d5SShuanglin Wang bool alloc = false, write = false, global = false, regfile = false; 755dd0191d5SShuanglin Wang struct bnxt_ulp_glb_resource_info glb_res = { 0 }; 756dd0191d5SShuanglin Wang uint16_t bit_size, wordlen = 0, tmplen = 0; 7572aa70990SKishore Padmanabha enum cfa_track_type tt = tbl->track_type; 758dd0191d5SShuanglin Wang struct ulp_flow_db_res_params fid_parms; 759dd0191d5SShuanglin Wang struct tfc_idx_tbl_info tbl_info = { 0 }; 760dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 761dd0191d5SShuanglin Wang struct ulp_blob data; 762dd0191d5SShuanglin Wang uint64_t regval = 0; 763dd0191d5SShuanglin Wang bool shared = false; 764dd0191d5SShuanglin Wang uint32_t index = 0; 765dd0191d5SShuanglin Wang unsigned char *data_p; 766dd0191d5SShuanglin Wang int32_t rc = 0; 767dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 768dd0191d5SShuanglin Wang 769dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx); 770*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 771dd0191d5SShuanglin Wang PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer"); 772dd0191d5SShuanglin Wang return -EINVAL; 773dd0191d5SShuanglin Wang } 774dd0191d5SShuanglin Wang 775*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid))) { 776dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func id\n"); 777dd0191d5SShuanglin Wang return -EINVAL; 778dd0191d5SShuanglin Wang } 779dd0191d5SShuanglin Wang 780dd0191d5SShuanglin Wang /* compute the blob size */ 781dd0191d5SShuanglin Wang bit_size = ulp_mapper_tfc_dyn_blob_size_get(parms, tbl); 782dd0191d5SShuanglin Wang 783dd0191d5SShuanglin Wang /* Initialize the blob data */ 784*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_init(&data, bit_size, 785*0c036a14SPeter Spreadborough parms->device_params->result_byte_order))) { 786dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to initialize index table blob\n"); 787dd0191d5SShuanglin Wang return -EINVAL; 788dd0191d5SShuanglin Wang } 789dd0191d5SShuanglin Wang 790dd0191d5SShuanglin Wang switch (tbl->tbl_opcode) { 791dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE: 792dd0191d5SShuanglin Wang alloc = true; 793dd0191d5SShuanglin Wang regfile = true; 794dd0191d5SShuanglin Wang break; 795dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE: 796dd0191d5SShuanglin Wang /* 797dd0191d5SShuanglin Wang * Build the entry, alloc an index, write the table, and store 798dd0191d5SShuanglin Wang * the data in the regfile. 799dd0191d5SShuanglin Wang */ 800dd0191d5SShuanglin Wang alloc = true; 801dd0191d5SShuanglin Wang write = true; 802dd0191d5SShuanglin Wang regfile = true; 803dd0191d5SShuanglin Wang break; 804dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE: 805dd0191d5SShuanglin Wang /* 806dd0191d5SShuanglin Wang * get the index to write to from the regfile and then write 807dd0191d5SShuanglin Wang * the table entry. 808dd0191d5SShuanglin Wang */ 809dd0191d5SShuanglin Wang regfile = true; 810dd0191d5SShuanglin Wang write = true; 811dd0191d5SShuanglin Wang break; 812dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE: 813dd0191d5SShuanglin Wang /* 814dd0191d5SShuanglin Wang * Build the entry, alloc an index, write the table, and store 815dd0191d5SShuanglin Wang * the data in the global regfile. 816dd0191d5SShuanglin Wang */ 817dd0191d5SShuanglin Wang alloc = true; 818dd0191d5SShuanglin Wang global = true; 819dd0191d5SShuanglin Wang write = true; 820dd0191d5SShuanglin Wang break; 821dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE: 822*0c036a14SPeter Spreadborough if (unlikely(tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP)) { 823dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Template error, wrong fdb opcode\n"); 824dd0191d5SShuanglin Wang return -EINVAL; 825dd0191d5SShuanglin Wang } 826dd0191d5SShuanglin Wang /* 827dd0191d5SShuanglin Wang * get the index to write to from the global regfile and then 828dd0191d5SShuanglin Wang * write the table. 829dd0191d5SShuanglin Wang */ 830*0c036a14SPeter Spreadborough if (unlikely(ulp_mapper_glb_resource_read(parms->mapper_data, 831dd0191d5SShuanglin Wang tbl->direction, 832dd0191d5SShuanglin Wang tbl->tbl_operand, 833*0c036a14SPeter Spreadborough ®val, &shared))) { 834dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 835dd0191d5SShuanglin Wang "Failed to get tbl idx from Glb RF[%d].\n", 836dd0191d5SShuanglin Wang tbl->tbl_operand); 837dd0191d5SShuanglin Wang return -EINVAL; 838dd0191d5SShuanglin Wang } 839dd0191d5SShuanglin Wang index = rte_be_to_cpu_64(regval); 840dd0191d5SShuanglin Wang /* check to see if any scope id changes needs to be done*/ 841dd0191d5SShuanglin Wang write = true; 842dd0191d5SShuanglin Wang break; 843dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE: 844dd0191d5SShuanglin Wang /* 845dd0191d5SShuanglin Wang * The read is different from the rest and can be handled here 846dd0191d5SShuanglin Wang * instead of trying to use common code. Simply read the table 847dd0191d5SShuanglin Wang * with the index from the regfile, scan and store the 848dd0191d5SShuanglin Wang * identifiers, and return. 849dd0191d5SShuanglin Wang */ 850*0c036a14SPeter Spreadborough if (unlikely(ulp_regfile_read(parms->regfile, 851*0c036a14SPeter Spreadborough tbl->tbl_operand, ®val))) { 852dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 853dd0191d5SShuanglin Wang "Failed to get tbl idx from regfile[%d]\n", 854dd0191d5SShuanglin Wang tbl->tbl_operand); 855dd0191d5SShuanglin Wang return -EINVAL; 856dd0191d5SShuanglin Wang } 857dd0191d5SShuanglin Wang index = rte_be_to_cpu_64(regval); 858dd0191d5SShuanglin Wang tbl_info.dir = tbl->direction; 859dd0191d5SShuanglin Wang tbl_info.rsubtype = tbl->resource_type; 860dd0191d5SShuanglin Wang tbl_info.id = index; 861dd0191d5SShuanglin Wang /* Nothing has been pushed to blob, so push bit_size */ 862dd0191d5SShuanglin Wang tmplen = ulp_blob_pad_push(&data, bit_size); 863dd0191d5SShuanglin Wang data_p = ulp_blob_data_get(&data, &tmplen); 864dd0191d5SShuanglin Wang wordlen = ULP_BITS_2_BYTE(tmplen); 865dd0191d5SShuanglin Wang 866dd0191d5SShuanglin Wang rc = tfc_idx_tbl_get(tfcp, fw_fid, &tbl_info, (uint32_t *)data_p, 867dd0191d5SShuanglin Wang (uint8_t *)&wordlen); 868*0c036a14SPeter Spreadborough if (unlikely(rc)) { 869dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 870dd0191d5SShuanglin Wang "Failed to read the tbl entry %d:%d\n", 871dd0191d5SShuanglin Wang tbl->resource_type, index); 872dd0191d5SShuanglin Wang return rc; 873dd0191d5SShuanglin Wang } 874dd0191d5SShuanglin Wang 875dd0191d5SShuanglin Wang /* Scan the fields in the entry and push them into the regfile*/ 876dd0191d5SShuanglin Wang rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, data_p, 877dd0191d5SShuanglin Wang wordlen, data.byte_order); 878*0c036a14SPeter Spreadborough if (unlikely(rc)) { 879dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 880dd0191d5SShuanglin Wang "Failed to get flds on tbl read rc=%d\n", 881dd0191d5SShuanglin Wang rc); 882dd0191d5SShuanglin Wang return rc; 883dd0191d5SShuanglin Wang } 884dd0191d5SShuanglin Wang return 0; 88549cdf043SKishore Padmanabha case BNXT_ULP_INDEX_TBL_OPC_NOP_REGFILE: 88649cdf043SKishore Padmanabha /* Special case, where hw table processing is not being done */ 88749cdf043SKishore Padmanabha /* but only for writing the regfile into the flow database */ 88849cdf043SKishore Padmanabha regfile = true; 88949cdf043SKishore Padmanabha break; 890dd0191d5SShuanglin Wang default: 891dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Invalid index table opcode %d\n", 892dd0191d5SShuanglin Wang tbl->tbl_opcode); 893dd0191d5SShuanglin Wang return -EINVAL; 894dd0191d5SShuanglin Wang } 895dd0191d5SShuanglin Wang 896dd0191d5SShuanglin Wang /* read the CMM identifier from the regfile, it is not allocated */ 897dd0191d5SShuanglin Wang if (!alloc && regfile) { 898*0c036a14SPeter Spreadborough if (unlikely(ulp_regfile_read(parms->regfile, 899dd0191d5SShuanglin Wang tbl->tbl_operand, 900*0c036a14SPeter Spreadborough ®val))) { 901dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 902dd0191d5SShuanglin Wang "Failed to get tbl idx from regfile[%d].\n", 903dd0191d5SShuanglin Wang tbl->tbl_operand); 904dd0191d5SShuanglin Wang return -EINVAL; 905dd0191d5SShuanglin Wang } 906dd0191d5SShuanglin Wang index = rte_be_to_cpu_64(regval); 907dd0191d5SShuanglin Wang } 908dd0191d5SShuanglin Wang 909dd0191d5SShuanglin Wang /* Allocate the Action CMM identifier */ 910dd0191d5SShuanglin Wang if (alloc) { 911dd0191d5SShuanglin Wang tbl_info.dir = tbl->direction; 912dd0191d5SShuanglin Wang tbl_info.rsubtype = tbl->resource_type; 913dd0191d5SShuanglin Wang rc = tfc_idx_tbl_alloc(tfcp, fw_fid, tt, &tbl_info); 914*0c036a14SPeter Spreadborough if (unlikely(rc)) { 915dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 916dd0191d5SShuanglin Wang tfc_idx_tbl_2_str(tbl_info.rsubtype), 917dd0191d5SShuanglin Wang tfc_dir_2_str(tbl->direction), rc); 918dd0191d5SShuanglin Wang return rc; 919dd0191d5SShuanglin Wang } 920dd0191d5SShuanglin Wang index = tbl_info.id; 921dd0191d5SShuanglin Wang } 922dd0191d5SShuanglin Wang 923dd0191d5SShuanglin Wang /* update the global register value */ 924dd0191d5SShuanglin Wang if (alloc && global) { 925dd0191d5SShuanglin Wang glb_res.direction = tbl->direction; 926dd0191d5SShuanglin Wang glb_res.resource_func = tbl->resource_func; 927dd0191d5SShuanglin Wang glb_res.resource_type = tbl->resource_type; 928dd0191d5SShuanglin Wang glb_res.glb_regfile_index = tbl->tbl_operand; 929dd0191d5SShuanglin Wang regval = rte_cpu_to_be_64(index); 930dd0191d5SShuanglin Wang 931dd0191d5SShuanglin Wang /* 932dd0191d5SShuanglin Wang * Shared resources are never allocated through this 933dd0191d5SShuanglin Wang * method, so the shared flag is always false. 934dd0191d5SShuanglin Wang */ 935dd0191d5SShuanglin Wang rc = ulp_mapper_glb_resource_write(parms->mapper_data, 936dd0191d5SShuanglin Wang &glb_res, regval, 937dd0191d5SShuanglin Wang false); 938*0c036a14SPeter Spreadborough if (unlikely(rc)) { 939dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 940dd0191d5SShuanglin Wang "Failed to write %s regfile[%d] rc=%d\n", 941dd0191d5SShuanglin Wang (global) ? "global" : "reg", 942dd0191d5SShuanglin Wang tbl->tbl_operand, rc); 943dd0191d5SShuanglin Wang goto error; 944dd0191d5SShuanglin Wang } 945dd0191d5SShuanglin Wang } 946dd0191d5SShuanglin Wang 947dd0191d5SShuanglin Wang /* update the local register value */ 948dd0191d5SShuanglin Wang if (alloc && regfile) { 949dd0191d5SShuanglin Wang regval = rte_cpu_to_be_64(index); 950dd0191d5SShuanglin Wang rc = ulp_regfile_write(parms->regfile, 951dd0191d5SShuanglin Wang tbl->tbl_operand, regval); 952*0c036a14SPeter Spreadborough if (unlikely(rc)) { 953dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 954dd0191d5SShuanglin Wang "Failed to write %s regfile[%d] rc=%d\n", 955dd0191d5SShuanglin Wang (global) ? "global" : "reg", 956dd0191d5SShuanglin Wang tbl->tbl_operand, rc); 957dd0191d5SShuanglin Wang goto error; 958dd0191d5SShuanglin Wang } 959dd0191d5SShuanglin Wang } 960dd0191d5SShuanglin Wang 961dd0191d5SShuanglin Wang if (write) { 962dd0191d5SShuanglin Wang /* Get the result fields list */ 963dd0191d5SShuanglin Wang rc = ulp_mapper_tbl_result_build(parms, 964dd0191d5SShuanglin Wang tbl, 965dd0191d5SShuanglin Wang &data, 966dd0191d5SShuanglin Wang "Indexed Result"); 967*0c036a14SPeter Spreadborough if (unlikely(rc)) { 968dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 969dd0191d5SShuanglin Wang return rc; 970dd0191d5SShuanglin Wang } 971dd0191d5SShuanglin Wang data_p = ulp_blob_data_get(&data, &tmplen); 972dd0191d5SShuanglin Wang tbl_info.dir = tbl->direction; 973dd0191d5SShuanglin Wang tbl_info.rsubtype = tbl->resource_type; 974dd0191d5SShuanglin Wang tbl_info.id = index; 975dd0191d5SShuanglin Wang wordlen = ULP_BITS_2_BYTE(tmplen); 976dd0191d5SShuanglin Wang rc = tfc_idx_tbl_set(tfcp, fw_fid, &tbl_info, 977dd0191d5SShuanglin Wang (uint32_t *)data_p, wordlen); 978*0c036a14SPeter Spreadborough if (unlikely(rc)) { 979dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 980dd0191d5SShuanglin Wang "Index table[%s][%s][%x] write fail %d\n", 981dd0191d5SShuanglin Wang tfc_idx_tbl_2_str(tbl_info.rsubtype), 982dd0191d5SShuanglin Wang tfc_dir_2_str(tbl_info.dir), 983dd0191d5SShuanglin Wang tbl_info.id, rc); 984dd0191d5SShuanglin Wang goto error; 985dd0191d5SShuanglin Wang } 986dd0191d5SShuanglin Wang BNXT_DRV_DBG(DEBUG, 987dd0191d5SShuanglin Wang "Index table[%s][%d][%x] write successful\n", 988dd0191d5SShuanglin Wang tfc_idx_tbl_2_str(tbl_info.rsubtype), 989dd0191d5SShuanglin Wang tbl_info.dir, tbl_info.id); 990dd0191d5SShuanglin Wang } 991dd0191d5SShuanglin Wang /* Link the resource to the flow in the flow db */ 992dd0191d5SShuanglin Wang memset(&fid_parms, 0, sizeof(fid_parms)); 993dd0191d5SShuanglin Wang fid_parms.direction = tbl->direction; 994dd0191d5SShuanglin Wang fid_parms.resource_func = tbl->resource_func; 995dd0191d5SShuanglin Wang fid_parms.resource_type = tbl->resource_type; 996dd0191d5SShuanglin Wang fid_parms.resource_sub_type = tbl->resource_sub_type; 997dd0191d5SShuanglin Wang fid_parms.resource_hndl = index; 998dd0191d5SShuanglin Wang fid_parms.critical_resource = tbl->critical_resource; 999dd0191d5SShuanglin Wang ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 1000dd0191d5SShuanglin Wang 1001dd0191d5SShuanglin Wang rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1002*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1003dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 1004dd0191d5SShuanglin Wang rc); 1005dd0191d5SShuanglin Wang goto error; 1006dd0191d5SShuanglin Wang } 1007dd0191d5SShuanglin Wang 1008dd0191d5SShuanglin Wang /* Perform the VF rep action */ 1009dd0191d5SShuanglin Wang rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 1010*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1011dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 1012dd0191d5SShuanglin Wang goto error; 1013dd0191d5SShuanglin Wang } 1014dd0191d5SShuanglin Wang return rc; 1015dd0191d5SShuanglin Wang error: 1016dd0191d5SShuanglin Wang /* Shared resources are not freed */ 1017dd0191d5SShuanglin Wang if (shared) 1018dd0191d5SShuanglin Wang return rc; 1019dd0191d5SShuanglin Wang /* 1020dd0191d5SShuanglin Wang * Free the allocated resource since we failed to either 1021dd0191d5SShuanglin Wang * write to the entry or link the flow 1022dd0191d5SShuanglin Wang */ 1023dd0191d5SShuanglin Wang 1024dd0191d5SShuanglin Wang if (tfc_idx_tbl_free(tfcp, fw_fid, &tbl_info)) 1025dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to free index entry on failure\n"); 1026dd0191d5SShuanglin Wang return rc; 1027dd0191d5SShuanglin Wang } 1028dd0191d5SShuanglin Wang 1029dd0191d5SShuanglin Wang static inline int32_t 1030dd0191d5SShuanglin Wang ulp_mapper_tfc_index_entry_free(struct bnxt_ulp_context *ulp_ctx, 1031dd0191d5SShuanglin Wang struct ulp_flow_db_res_params *res) 1032dd0191d5SShuanglin Wang { 1033dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 1034dd0191d5SShuanglin Wang struct tfc_idx_tbl_info tbl_info = { 0 }; 1035dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 1036be4732e8SMike Baucom int32_t rc; 1037dd0191d5SShuanglin Wang 1038*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) { 1039dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 1040dd0191d5SShuanglin Wang return -EINVAL; 1041dd0191d5SShuanglin Wang } 1042dd0191d5SShuanglin Wang 1043dd0191d5SShuanglin Wang #ifndef ULP_MAPPER_TFC_TEST 1044dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx); 1045*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1046dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 1047dd0191d5SShuanglin Wang return -EINVAL; 1048dd0191d5SShuanglin Wang } 1049dd0191d5SShuanglin Wang #endif 1050dd0191d5SShuanglin Wang tbl_info.dir = (enum cfa_dir)res->direction; 1051dd0191d5SShuanglin Wang tbl_info.rsubtype = res->resource_type; 1052dd0191d5SShuanglin Wang tbl_info.id = (uint16_t)res->resource_hndl; 1053dd0191d5SShuanglin Wang 1054dd0191d5SShuanglin Wang /* TBD: check to see if the memory needs to be cleaned as well*/ 1055be4732e8SMike Baucom rc = tfc_idx_tbl_free(tfcp, fw_fid, &tbl_info); 1056be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1057be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1058be4732e8SMike Baucom if (!rc) 1059be4732e8SMike Baucom BNXT_DRV_DBG(DEBUG, "Freed Index [%s]:[%s] = 0x%X\n", 1060be4732e8SMike Baucom tfc_dir_2_str(tbl_info.dir), 1061be4732e8SMike Baucom tfc_idx_tbl_2_str(tbl_info.rsubtype), tbl_info.id); 1062be4732e8SMike Baucom #endif 1063be4732e8SMike Baucom #endif 1064be4732e8SMike Baucom return rc; 1065dd0191d5SShuanglin Wang } 1066dd0191d5SShuanglin Wang 1067dd0191d5SShuanglin Wang static int32_t 1068dd0191d5SShuanglin Wang ulp_mapper_tfc_cmm_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1069dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl, 1070dd0191d5SShuanglin Wang void *error) 1071dd0191d5SShuanglin Wang { 1072dd0191d5SShuanglin Wang bool alloc = false, write = false, global = false, regfile = false; 1073dd0191d5SShuanglin Wang struct bnxt_ulp_glb_resource_info glb_res = { 0 }; 1074dd0191d5SShuanglin Wang uint16_t bit_size, act_wordlen = 0, tmplen = 0; 1075dd0191d5SShuanglin Wang struct ulp_flow_db_res_params fid_parms; 1076dd0191d5SShuanglin Wang struct tfc_cmm_info cmm_info = { 0 }; 1077dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 1078dd0191d5SShuanglin Wang struct ulp_blob data; 1079dd0191d5SShuanglin Wang uint64_t regval = 0; 1080dd0191d5SShuanglin Wang bool shared = false; 1081dd0191d5SShuanglin Wang uint64_t handle = 0; 1082dd0191d5SShuanglin Wang const uint8_t *act_data; 1083dd0191d5SShuanglin Wang uint64_t act_rec_size = 0; 1084dd0191d5SShuanglin Wang uint8_t tsid = 0; 1085dd0191d5SShuanglin Wang int32_t rc = 0; 1086dd0191d5SShuanglin Wang 1087dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx); 1088*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1089dd0191d5SShuanglin Wang PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer"); 1090dd0191d5SShuanglin Wang return -EINVAL; 1091dd0191d5SShuanglin Wang } 1092dd0191d5SShuanglin Wang 1093dd0191d5SShuanglin Wang /* compute the blob size */ 1094dd0191d5SShuanglin Wang bit_size = ulp_mapper_tfc_dyn_blob_size_get(parms, tbl); 1095dd0191d5SShuanglin Wang 1096dd0191d5SShuanglin Wang /* Initialize the blob data */ 1097*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_init(&data, bit_size, 1098*0c036a14SPeter Spreadborough parms->device_params->result_byte_order))) { 1099dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to initialize cmm table blob\n"); 1100dd0191d5SShuanglin Wang return -EINVAL; 1101dd0191d5SShuanglin Wang } 1102dd0191d5SShuanglin Wang 1103dd0191d5SShuanglin Wang switch (tbl->tbl_opcode) { 1104dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE: 1105dd0191d5SShuanglin Wang regfile = true; 1106dd0191d5SShuanglin Wang alloc = true; 1107dd0191d5SShuanglin Wang break; 1108dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE: 1109dd0191d5SShuanglin Wang /* 1110dd0191d5SShuanglin Wang * Build the entry, alloc an index, write the table, and store 1111dd0191d5SShuanglin Wang * the data in the regfile. 1112dd0191d5SShuanglin Wang */ 1113dd0191d5SShuanglin Wang alloc = true; 1114dd0191d5SShuanglin Wang write = true; 1115dd0191d5SShuanglin Wang regfile = true; 1116dd0191d5SShuanglin Wang break; 1117dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE: 1118dd0191d5SShuanglin Wang /* 1119dd0191d5SShuanglin Wang * get the index to write to from the regfile and then write 1120dd0191d5SShuanglin Wang * the table entry. 1121dd0191d5SShuanglin Wang */ 1122dd0191d5SShuanglin Wang regfile = true; 1123dd0191d5SShuanglin Wang write = true; 1124dd0191d5SShuanglin Wang break; 1125dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE: 1126dd0191d5SShuanglin Wang /* 1127dd0191d5SShuanglin Wang * Build the entry, alloc an index, write the table, and store 1128dd0191d5SShuanglin Wang * the data in the global regfile. 1129dd0191d5SShuanglin Wang */ 1130dd0191d5SShuanglin Wang alloc = true; 1131dd0191d5SShuanglin Wang global = true; 1132dd0191d5SShuanglin Wang write = true; 1133dd0191d5SShuanglin Wang break; 1134dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE: 1135*0c036a14SPeter Spreadborough if (unlikely(tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP)) { 1136dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Template error, wrong fdb opcode\n"); 1137dd0191d5SShuanglin Wang return -EINVAL; 1138dd0191d5SShuanglin Wang } 1139dd0191d5SShuanglin Wang /* 1140dd0191d5SShuanglin Wang * get the index to write to from the global regfile and then 1141dd0191d5SShuanglin Wang * write the table. 1142dd0191d5SShuanglin Wang */ 1143*0c036a14SPeter Spreadborough if (unlikely(ulp_mapper_glb_resource_read(parms->mapper_data, 1144dd0191d5SShuanglin Wang tbl->direction, 1145dd0191d5SShuanglin Wang tbl->tbl_operand, 1146*0c036a14SPeter Spreadborough ®val, &shared))) { 1147dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1148dd0191d5SShuanglin Wang "Failed to get tbl idx from Glb RF[%d].\n", 1149dd0191d5SShuanglin Wang tbl->tbl_operand); 1150dd0191d5SShuanglin Wang return -EINVAL; 1151dd0191d5SShuanglin Wang } 1152dd0191d5SShuanglin Wang handle = rte_be_to_cpu_64(regval); 1153dd0191d5SShuanglin Wang /* check to see if any scope id changes needs to be done*/ 1154dd0191d5SShuanglin Wang write = true; 1155dd0191d5SShuanglin Wang break; 1156dd0191d5SShuanglin Wang case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE: 1157dd0191d5SShuanglin Wang /* 1158dd0191d5SShuanglin Wang * The read is different from the rest and can be handled here 1159dd0191d5SShuanglin Wang * instead of trying to use common code. Simply read the table 1160dd0191d5SShuanglin Wang * with the index from the regfile, scan and store the 1161dd0191d5SShuanglin Wang * identifiers, and return. 1162dd0191d5SShuanglin Wang */ 1163*0c036a14SPeter Spreadborough if (unlikely(ulp_regfile_read(parms->regfile, 1164*0c036a14SPeter Spreadborough tbl->tbl_operand, ®val))) { 1165dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1166dd0191d5SShuanglin Wang "Failed to get tbl idx from regfile[%d]\n", 1167dd0191d5SShuanglin Wang tbl->tbl_operand); 1168dd0191d5SShuanglin Wang return -EINVAL; 1169dd0191d5SShuanglin Wang } 1170dd0191d5SShuanglin Wang handle = rte_be_to_cpu_64(regval); 1171dd0191d5SShuanglin Wang return 0; 117249cdf043SKishore Padmanabha case BNXT_ULP_INDEX_TBL_OPC_NOP_REGFILE: 117349cdf043SKishore Padmanabha regfile = true; 117449cdf043SKishore Padmanabha alloc = false; 117549cdf043SKishore Padmanabha break; 1176dd0191d5SShuanglin Wang default: 1177dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Invalid cmm table opcode %d\n", 1178dd0191d5SShuanglin Wang tbl->tbl_opcode); 1179dd0191d5SShuanglin Wang return -EINVAL; 1180dd0191d5SShuanglin Wang } 1181dd0191d5SShuanglin Wang 1182dd0191d5SShuanglin Wang /* read the CMM handle from the regfile, it is not allocated */ 1183dd0191d5SShuanglin Wang if (!alloc && regfile) { 1184*0c036a14SPeter Spreadborough if (unlikely(ulp_regfile_read(parms->regfile, 1185dd0191d5SShuanglin Wang tbl->tbl_operand, 1186*0c036a14SPeter Spreadborough ®val))) { 1187dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1188dd0191d5SShuanglin Wang "Failed to get tbl idx from regfile[%d].\n", 1189dd0191d5SShuanglin Wang tbl->tbl_operand); 1190dd0191d5SShuanglin Wang return -EINVAL; 1191dd0191d5SShuanglin Wang } 1192dd0191d5SShuanglin Wang handle = rte_be_to_cpu_64(regval); 1193dd0191d5SShuanglin Wang } 1194dd0191d5SShuanglin Wang 1195dd0191d5SShuanglin Wang /* Get the result fields list */ 1196dd0191d5SShuanglin Wang rc = ulp_mapper_tbl_result_build(parms, 1197dd0191d5SShuanglin Wang tbl, 1198dd0191d5SShuanglin Wang &data, 1199dd0191d5SShuanglin Wang "Indexed Result"); 1200*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1201dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 1202dd0191d5SShuanglin Wang return rc; 1203dd0191d5SShuanglin Wang } 1204dd0191d5SShuanglin Wang 1205dd0191d5SShuanglin Wang /* Allocate the Action CMM identifier */ 1206dd0191d5SShuanglin Wang if (alloc) { 1207dd0191d5SShuanglin Wang cmm_info.dir = tbl->direction; 1208dd0191d5SShuanglin Wang cmm_info.rsubtype = tbl->resource_type; 1209dd0191d5SShuanglin Wang /* Only need the length for alloc, ignore the returned data */ 1210dd0191d5SShuanglin Wang act_data = ulp_blob_data_get(&data, &tmplen); 1211dd0191d5SShuanglin Wang act_wordlen = ULP_BITS_TO_32_BYTE_WORD(tmplen); 1212dd0191d5SShuanglin Wang 1213dd0191d5SShuanglin Wang rc = bnxt_ulp_cntxt_tsid_get(parms->ulp_ctx, &tsid); 1214*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1215dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get the table scope\n"); 1216dd0191d5SShuanglin Wang return rc; 1217dd0191d5SShuanglin Wang } 1218dd0191d5SShuanglin Wang /* All failures after the alloc succeeds require a free */ 1219dd0191d5SShuanglin Wang rc = tfc_act_alloc(tfcp, tsid, &cmm_info, act_wordlen); 1220*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1221dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Alloc CMM [%d][%s] failed rc=%d\n", 1222dd0191d5SShuanglin Wang cmm_info.rsubtype, 1223dd0191d5SShuanglin Wang tfc_dir_2_str(cmm_info.dir), rc); 1224dd0191d5SShuanglin Wang return rc; 1225dd0191d5SShuanglin Wang } 1226dd0191d5SShuanglin Wang handle = cmm_info.act_handle; 1227dd0191d5SShuanglin Wang 1228dd0191d5SShuanglin Wang /* Counters need to be reset when allocated to ensure counter is 1229dd0191d5SShuanglin Wang * zero 1230dd0191d5SShuanglin Wang */ 1231dd0191d5SShuanglin Wang if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_CMM_STAT) { 1232dd0191d5SShuanglin Wang rc = tfc_act_set(tfcp, 1233dd0191d5SShuanglin Wang &parms->batch_info, 1234dd0191d5SShuanglin Wang &cmm_info, act_data, 1235dd0191d5SShuanglin Wang act_wordlen); 1236*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1237dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Stat alloc/clear[%d][%s]" 1238dd0191d5SShuanglin Wang "[0x%" PRIx64 "] failed rc=%d\n", 1239dd0191d5SShuanglin Wang cmm_info.rsubtype, 1240dd0191d5SShuanglin Wang tfc_dir_2_str(cmm_info.dir), 1241dd0191d5SShuanglin Wang cmm_info.act_handle, rc); 1242dd0191d5SShuanglin Wang if (error != NULL && tfc_is_mpc_error(rc)) { 1243dd0191d5SShuanglin Wang struct rte_flow_error *fe = 1244dd0191d5SShuanglin Wang (struct rte_flow_error *)error; 1245dd0191d5SShuanglin Wang rte_flow_error_set(fe, 1246dd0191d5SShuanglin Wang EIO, 1247dd0191d5SShuanglin Wang RTE_FLOW_ERROR_TYPE_HANDLE, 1248dd0191d5SShuanglin Wang NULL, 1249dd0191d5SShuanglin Wang mpc_error_str[rc * -1]); 1250dd0191d5SShuanglin Wang } 1251dd0191d5SShuanglin Wang goto error; 1252dd0191d5SShuanglin Wang } 1253dd0191d5SShuanglin Wang } 1254dd0191d5SShuanglin Wang } 1255dd0191d5SShuanglin Wang 1256dd0191d5SShuanglin Wang /* update the global register value */ 1257dd0191d5SShuanglin Wang if (alloc && global) { 1258dd0191d5SShuanglin Wang glb_res.direction = tbl->direction; 1259dd0191d5SShuanglin Wang glb_res.resource_func = tbl->resource_func; 1260dd0191d5SShuanglin Wang glb_res.resource_type = tbl->resource_type; 1261dd0191d5SShuanglin Wang glb_res.glb_regfile_index = tbl->tbl_operand; 1262dd0191d5SShuanglin Wang regval = rte_cpu_to_be_64(handle); 1263dd0191d5SShuanglin Wang 1264dd0191d5SShuanglin Wang /* 1265dd0191d5SShuanglin Wang * Shared resources are never allocated through this 1266dd0191d5SShuanglin Wang * method, so the shared flag is always false. 1267dd0191d5SShuanglin Wang */ 1268dd0191d5SShuanglin Wang rc = ulp_mapper_glb_resource_write(parms->mapper_data, 1269dd0191d5SShuanglin Wang &glb_res, regval, 1270dd0191d5SShuanglin Wang false); 1271*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1272dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1273dd0191d5SShuanglin Wang "Failed to write %s regfile[%d] rc=%d\n", 1274dd0191d5SShuanglin Wang (global) ? "global" : "reg", 1275dd0191d5SShuanglin Wang tbl->tbl_operand, rc); 1276dd0191d5SShuanglin Wang goto error; 1277dd0191d5SShuanglin Wang } 1278dd0191d5SShuanglin Wang } 1279dd0191d5SShuanglin Wang 1280dd0191d5SShuanglin Wang /* update the local register value */ 1281dd0191d5SShuanglin Wang if (alloc && regfile) { 1282dd0191d5SShuanglin Wang regval = rte_cpu_to_be_64(handle); 1283dd0191d5SShuanglin Wang rc = ulp_regfile_write(parms->regfile, 1284dd0191d5SShuanglin Wang tbl->tbl_operand, regval); 1285*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1286dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1287dd0191d5SShuanglin Wang "Failed to write %s regfile[%d] rc=%d\n", 1288dd0191d5SShuanglin Wang (global) ? "global" : "reg", 1289dd0191d5SShuanglin Wang tbl->tbl_operand, rc); 1290dd0191d5SShuanglin Wang goto error; 1291dd0191d5SShuanglin Wang } 1292dd0191d5SShuanglin Wang } 1293dd0191d5SShuanglin Wang 1294dd0191d5SShuanglin Wang if (write) { 1295dd0191d5SShuanglin Wang act_data = ulp_blob_data_get(&data, &tmplen); 1296dd0191d5SShuanglin Wang cmm_info.dir = tbl->direction; 1297dd0191d5SShuanglin Wang cmm_info.rsubtype = tbl->resource_type; 1298dd0191d5SShuanglin Wang cmm_info.act_handle = handle; 1299dd0191d5SShuanglin Wang act_wordlen = ULP_BITS_TO_32_BYTE_WORD(tmplen); 1300dd0191d5SShuanglin Wang rc = tfc_act_set(tfcp, &parms->batch_info, &cmm_info, act_data, act_wordlen); 1301*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1302dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1303dd0191d5SShuanglin Wang "CMM table[%d][%s][0x%" PRIx64 1304dd0191d5SShuanglin Wang "] write fail %d\n", 1305dd0191d5SShuanglin Wang cmm_info.rsubtype, 1306dd0191d5SShuanglin Wang tfc_dir_2_str(cmm_info.dir), 1307dd0191d5SShuanglin Wang handle, rc); 1308dd0191d5SShuanglin Wang if (error != NULL && tfc_is_mpc_error(rc)) { 1309dd0191d5SShuanglin Wang struct rte_flow_error *fe = 1310dd0191d5SShuanglin Wang (struct rte_flow_error *)error; 1311dd0191d5SShuanglin Wang rte_flow_error_set(fe, 1312dd0191d5SShuanglin Wang EIO, 1313dd0191d5SShuanglin Wang RTE_FLOW_ERROR_TYPE_HANDLE, 1314dd0191d5SShuanglin Wang NULL, 1315dd0191d5SShuanglin Wang mpc_error_str[rc * -1]); 1316dd0191d5SShuanglin Wang } 1317dd0191d5SShuanglin Wang goto error; 1318dd0191d5SShuanglin Wang } 1319dd0191d5SShuanglin Wang BNXT_DRV_DBG(DEBUG, 1320dd0191d5SShuanglin Wang "CMM table[%d][%s][0x%" PRIx64 1321dd0191d5SShuanglin Wang "] write successful\n", 1322dd0191d5SShuanglin Wang cmm_info.rsubtype, tfc_dir_2_str(cmm_info.dir), 1323dd0191d5SShuanglin Wang handle); 1324dd0191d5SShuanglin Wang 1325dd0191d5SShuanglin Wang /* Calculate action record size */ 1326dd0191d5SShuanglin Wang if (tbl->resource_type == CFA_RSUBTYPE_CMM_ACT) { 1327dd0191d5SShuanglin Wang act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16; 1328dd0191d5SShuanglin Wang act_rec_size--; 1329dd0191d5SShuanglin Wang if (ulp_regfile_write(parms->regfile, 1330dd0191d5SShuanglin Wang BNXT_ULP_RF_IDX_ACTION_REC_SIZE, 1331dd0191d5SShuanglin Wang rte_cpu_to_be_64(act_rec_size))) 1332dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1333dd0191d5SShuanglin Wang "Failed write the act rec size\n"); 1334dd0191d5SShuanglin Wang } 1335dd0191d5SShuanglin Wang } 1336dd0191d5SShuanglin Wang /* Link the resource to the flow in the flow db */ 1337dd0191d5SShuanglin Wang memset(&fid_parms, 0, sizeof(fid_parms)); 1338dd0191d5SShuanglin Wang fid_parms.direction = tbl->direction; 1339dd0191d5SShuanglin Wang fid_parms.resource_func = tbl->resource_func; 1340dd0191d5SShuanglin Wang fid_parms.resource_type = tbl->resource_type; 1341dd0191d5SShuanglin Wang fid_parms.resource_sub_type = tbl->resource_sub_type; 1342dd0191d5SShuanglin Wang fid_parms.resource_hndl = handle; 1343dd0191d5SShuanglin Wang fid_parms.critical_resource = tbl->critical_resource; 1344dd0191d5SShuanglin Wang ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 1345dd0191d5SShuanglin Wang 1346dd0191d5SShuanglin Wang rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1347*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1348dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 1349dd0191d5SShuanglin Wang rc); 1350dd0191d5SShuanglin Wang goto error; 1351dd0191d5SShuanglin Wang } 1352dd0191d5SShuanglin Wang 1353dd0191d5SShuanglin Wang /* Perform the VF rep action */ 1354dd0191d5SShuanglin Wang rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 1355*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1356dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 1357dd0191d5SShuanglin Wang goto error; 1358dd0191d5SShuanglin Wang } 1359dd0191d5SShuanglin Wang return rc; 1360dd0191d5SShuanglin Wang error: 1361dd0191d5SShuanglin Wang /* Shared resources are not freed */ 1362dd0191d5SShuanglin Wang if (shared) 1363dd0191d5SShuanglin Wang return rc; 1364dd0191d5SShuanglin Wang /* 1365dd0191d5SShuanglin Wang * Free the allocated resource since we failed to either 1366dd0191d5SShuanglin Wang * write to the entry or link the flow 1367dd0191d5SShuanglin Wang */ 1368dd0191d5SShuanglin Wang 1369dd0191d5SShuanglin Wang if (tfc_act_free(tfcp, &cmm_info)) 1370dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to free cmm entry on failure\n"); 1371dd0191d5SShuanglin Wang 1372dd0191d5SShuanglin Wang return rc; 1373dd0191d5SShuanglin Wang } 1374dd0191d5SShuanglin Wang 1375dd0191d5SShuanglin Wang static int32_t 1376dd0191d5SShuanglin Wang ulp_mapper_tfc_cmm_entry_free(struct bnxt_ulp_context *ulp_ctx, 1377dd0191d5SShuanglin Wang struct ulp_flow_db_res_params *res, 1378dd0191d5SShuanglin Wang void *error) 1379dd0191d5SShuanglin Wang { 1380dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 1381dd0191d5SShuanglin Wang struct tfc_cmm_info cmm_info = { 0 }; 1382dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 1383dd0191d5SShuanglin Wang int32_t rc = 0; 1384dd0191d5SShuanglin Wang 1385f6e12015SKishore Padmanabha /* skip cmm processing if fdb flag is sw only */ 1386f6e12015SKishore Padmanabha if (res->fdb_flags & ULP_FDB_FLAG_SW_ONLY) 138749cdf043SKishore Padmanabha return 0; 138849cdf043SKishore Padmanabha 1389*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) { 1390dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 1391dd0191d5SShuanglin Wang return -EINVAL; 1392dd0191d5SShuanglin Wang } 1393dd0191d5SShuanglin Wang 1394dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx); 1395*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1396dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 1397dd0191d5SShuanglin Wang return -EINVAL; 1398dd0191d5SShuanglin Wang } 1399dd0191d5SShuanglin Wang 1400dd0191d5SShuanglin Wang cmm_info.dir = (enum cfa_dir)res->direction; 1401dd0191d5SShuanglin Wang cmm_info.rsubtype = res->resource_type; 1402dd0191d5SShuanglin Wang cmm_info.act_handle = res->resource_hndl; 1403dd0191d5SShuanglin Wang 1404dd0191d5SShuanglin Wang /* TBD: check to see if the memory needs to be cleaned as well*/ 1405dd0191d5SShuanglin Wang rc = tfc_act_free(tfcp, &cmm_info); 1406*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1407dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1408dd0191d5SShuanglin Wang "Failed to delete CMM entry,res = 0x%" PRIx64 "\n", 1409dd0191d5SShuanglin Wang res->resource_hndl); 1410dd0191d5SShuanglin Wang if (error != NULL && tfc_is_mpc_error(rc)) { 1411dd0191d5SShuanglin Wang struct rte_flow_error *fe = (struct rte_flow_error *)error; 1412dd0191d5SShuanglin Wang rte_flow_error_set(fe, 1413dd0191d5SShuanglin Wang EIO, 1414dd0191d5SShuanglin Wang RTE_FLOW_ERROR_TYPE_HANDLE, 1415dd0191d5SShuanglin Wang NULL, 1416dd0191d5SShuanglin Wang mpc_error_str[rc * -1]); 1417dd0191d5SShuanglin Wang } 1418dd0191d5SShuanglin Wang } else { 1419dd0191d5SShuanglin Wang BNXT_DRV_DBG(DEBUG, "Deleted CMM entry,res = 0x%" PRIx64 "\n", 1420dd0191d5SShuanglin Wang res->resource_hndl); 1421dd0191d5SShuanglin Wang } 1422dd0191d5SShuanglin Wang return rc; 1423dd0191d5SShuanglin Wang } 1424dd0191d5SShuanglin Wang 1425dd0191d5SShuanglin Wang static int32_t 1426dd0191d5SShuanglin Wang ulp_mapper_tfc_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1427dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl) 1428dd0191d5SShuanglin Wang { 1429dd0191d5SShuanglin Wang struct ulp_blob data, res_blob; 1430*0c036a14SPeter Spreadborough uint64_t idx = 0; 1431dd0191d5SShuanglin Wang int32_t rc = 0; 1432dd0191d5SShuanglin Wang struct tfc *tfcp; 1433dd0191d5SShuanglin Wang enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode; 1434dd0191d5SShuanglin Wang uint32_t res_size; 1435dd0191d5SShuanglin Wang struct tfc_if_tbl_info tbl_info = { 0 }; 1436dd0191d5SShuanglin Wang unsigned char *data_p; 1437dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 1438dd0191d5SShuanglin Wang uint8_t data_size; 1439dd0191d5SShuanglin Wang uint16_t tmplen; 1440dd0191d5SShuanglin Wang 1441*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(parms->ulp_ctx, &fw_fid))) { 1442dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 1443dd0191d5SShuanglin Wang return -EINVAL; 1444dd0191d5SShuanglin Wang } 1445dd0191d5SShuanglin Wang 1446dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(parms->ulp_ctx); 1447*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1448dd0191d5SShuanglin Wang PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer"); 1449dd0191d5SShuanglin Wang return -EINVAL; 1450dd0191d5SShuanglin Wang } 1451dd0191d5SShuanglin Wang 1452dd0191d5SShuanglin Wang /* Initialize the blob data */ 1453*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_init(&data, tbl->result_bit_size, 1454*0c036a14SPeter Spreadborough parms->device_params->result_byte_order))) { 1455dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed initial index table blob\n"); 1456dd0191d5SShuanglin Wang return -EINVAL; 1457dd0191d5SShuanglin Wang } 1458dd0191d5SShuanglin Wang 1459dd0191d5SShuanglin Wang /* create the result blob */ 1460dd0191d5SShuanglin Wang rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result"); 1461*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1462dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 1463dd0191d5SShuanglin Wang return rc; 1464dd0191d5SShuanglin Wang } 1465dd0191d5SShuanglin Wang 1466dd0191d5SShuanglin Wang /* Get the index details */ 1467dd0191d5SShuanglin Wang switch (if_opc) { 1468dd0191d5SShuanglin Wang case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD: 1469dd0191d5SShuanglin Wang idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 1470dd0191d5SShuanglin Wang break; 1471dd0191d5SShuanglin Wang case BNXT_ULP_IF_TBL_OPC_WR_REGFILE: 1472*0c036a14SPeter Spreadborough if (unlikely(ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx))) { 1473dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n", 1474dd0191d5SShuanglin Wang tbl->tbl_operand); 1475dd0191d5SShuanglin Wang return -EINVAL; 1476dd0191d5SShuanglin Wang } 1477dd0191d5SShuanglin Wang idx = rte_be_to_cpu_64(idx); 1478dd0191d5SShuanglin Wang break; 1479dd0191d5SShuanglin Wang case BNXT_ULP_IF_TBL_OPC_WR_CONST: 1480dd0191d5SShuanglin Wang idx = tbl->tbl_operand; 1481dd0191d5SShuanglin Wang break; 1482dd0191d5SShuanglin Wang case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD: 1483dd0191d5SShuanglin Wang /* Initialize the result blob */ 1484*0c036a14SPeter Spreadborough if (unlikely(ulp_blob_init(&res_blob, tbl->result_bit_size, 1485*0c036a14SPeter Spreadborough parms->device_params->result_byte_order))) { 1486dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed initial result blob\n"); 1487dd0191d5SShuanglin Wang return -EINVAL; 1488dd0191d5SShuanglin Wang } 1489dd0191d5SShuanglin Wang 1490dd0191d5SShuanglin Wang /* read the interface table */ 1491dd0191d5SShuanglin Wang idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 1492dd0191d5SShuanglin Wang res_size = ULP_BITS_2_BYTE(tbl->result_bit_size); 1493dd0191d5SShuanglin Wang rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 1494dd0191d5SShuanglin Wang res_blob.data, 1495dd0191d5SShuanglin Wang res_size, 1496dd0191d5SShuanglin Wang res_blob.byte_order); 1497*0c036a14SPeter Spreadborough if (unlikely(rc)) 1498dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Scan and extract failed rc=%d\n", 1499dd0191d5SShuanglin Wang rc); 1500dd0191d5SShuanglin Wang return rc; 1501dd0191d5SShuanglin Wang case BNXT_ULP_IF_TBL_OPC_NOT_USED: 1502dd0191d5SShuanglin Wang return rc; /* skip it */ 1503dd0191d5SShuanglin Wang default: 1504dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Invalid tbl index opcode\n"); 1505dd0191d5SShuanglin Wang return -EINVAL; 1506dd0191d5SShuanglin Wang } 1507dd0191d5SShuanglin Wang 1508dd0191d5SShuanglin Wang tbl_info.dir = tbl->direction; 1509dd0191d5SShuanglin Wang tbl_info.rsubtype = tbl->resource_type; 1510dd0191d5SShuanglin Wang tbl_info.id = (uint32_t)idx; 1511dd0191d5SShuanglin Wang data_p = ulp_blob_data_get(&data, &tmplen); 1512dd0191d5SShuanglin Wang data_size = ULP_BITS_2_BYTE(tmplen); 1513dd0191d5SShuanglin Wang 1514dd0191d5SShuanglin Wang rc = tfc_if_tbl_set(tfcp, fw_fid, &tbl_info, (uint8_t *)data_p, 1515dd0191d5SShuanglin Wang data_size); 1516*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1517dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, 1518dd0191d5SShuanglin Wang "Failed to write the if tbl entry %d:%d\n", 1519dd0191d5SShuanglin Wang tbl->resource_type, (uint32_t)idx); 1520dd0191d5SShuanglin Wang return rc; 1521dd0191d5SShuanglin Wang } 1522dd0191d5SShuanglin Wang 1523dd0191d5SShuanglin Wang return rc; 1524dd0191d5SShuanglin Wang } 1525dd0191d5SShuanglin Wang 1526dd0191d5SShuanglin Wang static int32_t 1527dd0191d5SShuanglin Wang ulp_mapper_tfc_ident_alloc(struct bnxt_ulp_context *ulp_ctx, 1528dd0191d5SShuanglin Wang uint32_t session_type __rte_unused, 1529dd0191d5SShuanglin Wang uint16_t ident_type, 1530dd0191d5SShuanglin Wang uint8_t direction, 15312aa70990SKishore Padmanabha enum cfa_track_type tt, 1532dd0191d5SShuanglin Wang uint64_t *identifier_id) 1533dd0191d5SShuanglin Wang { 1534dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 1535dd0191d5SShuanglin Wang struct tfc_identifier_info ident_info = { 0 }; 1536dd0191d5SShuanglin Wang int32_t rc = 0; 1537dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 1538dd0191d5SShuanglin Wang 1539*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) { 1540dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 1541dd0191d5SShuanglin Wang return -EINVAL; 1542dd0191d5SShuanglin Wang } 1543dd0191d5SShuanglin Wang 1544dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx); 1545*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1546dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 1547dd0191d5SShuanglin Wang return -EINVAL; 1548dd0191d5SShuanglin Wang } 1549dd0191d5SShuanglin Wang 1550dd0191d5SShuanglin Wang ident_info.dir = direction; 1551dd0191d5SShuanglin Wang ident_info.rsubtype = ident_type; 1552dd0191d5SShuanglin Wang 1553dd0191d5SShuanglin Wang rc = tfc_identifier_alloc(tfcp, fw_fid, tt, &ident_info); 1554*0c036a14SPeter Spreadborough if (unlikely(rc != 0)) { 1555dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "alloc failed %d\n", rc); 1556dd0191d5SShuanglin Wang return rc; 1557dd0191d5SShuanglin Wang } 1558dd0191d5SShuanglin Wang *identifier_id = ident_info.id; 1559dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1560dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1561dd0191d5SShuanglin Wang BNXT_DRV_INF("Allocated Identifier [%s]:[%s] = 0x%X\n", 1562dd0191d5SShuanglin Wang tfc_dir_2_str(direction), 1563dd0191d5SShuanglin Wang tfc_ident_2_str(ident_info.rsubtype), ident_info.id); 1564dd0191d5SShuanglin Wang #endif 1565dd0191d5SShuanglin Wang #endif 1566dd0191d5SShuanglin Wang 1567dd0191d5SShuanglin Wang return rc; 1568dd0191d5SShuanglin Wang } 1569dd0191d5SShuanglin Wang 1570dd0191d5SShuanglin Wang static int32_t 1571dd0191d5SShuanglin Wang ulp_mapper_tfc_ident_free(struct bnxt_ulp_context *ulp_ctx, 1572dd0191d5SShuanglin Wang struct ulp_flow_db_res_params *res) 1573dd0191d5SShuanglin Wang { 1574dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 1575dd0191d5SShuanglin Wang struct tfc_identifier_info ident_info = { 0 }; 1576dd0191d5SShuanglin Wang int32_t rc = 0; 1577dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 1578dd0191d5SShuanglin Wang 1579*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &fw_fid))) { 1580dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 1581dd0191d5SShuanglin Wang return -EINVAL; 1582dd0191d5SShuanglin Wang } 1583dd0191d5SShuanglin Wang 1584dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx); 1585*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1586dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 1587dd0191d5SShuanglin Wang return -EINVAL; 1588dd0191d5SShuanglin Wang } 1589dd0191d5SShuanglin Wang 1590dd0191d5SShuanglin Wang ident_info.dir = (enum cfa_dir)res->direction; 1591dd0191d5SShuanglin Wang ident_info.rsubtype = res->resource_type; 1592dd0191d5SShuanglin Wang ident_info.id = res->resource_hndl; 1593dd0191d5SShuanglin Wang 1594dd0191d5SShuanglin Wang rc = tfc_identifier_free(tfcp, fw_fid, &ident_info); 1595*0c036a14SPeter Spreadborough if (unlikely(rc != 0)) { 1596dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "free failed %d\n", rc); 1597dd0191d5SShuanglin Wang return rc; 1598dd0191d5SShuanglin Wang } 1599dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1600dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1601be4732e8SMike Baucom BNXT_DRV_DBG(DEBUG, "Freed Identifier [%s]:[%s] = 0x%X\n", 1602dd0191d5SShuanglin Wang tfc_dir_2_str(ident_info.dir), 1603dd0191d5SShuanglin Wang tfc_ident_2_str(ident_info.rsubtype), ident_info.id); 1604dd0191d5SShuanglin Wang #endif 1605dd0191d5SShuanglin Wang #endif 1606dd0191d5SShuanglin Wang 1607dd0191d5SShuanglin Wang return rc; 1608dd0191d5SShuanglin Wang } 1609dd0191d5SShuanglin Wang 1610dd0191d5SShuanglin Wang static inline int32_t 1611dd0191d5SShuanglin Wang ulp_mapper_tfc_tcam_entry_free(struct bnxt_ulp_context *ulp, 1612dd0191d5SShuanglin Wang struct ulp_flow_db_res_params *res) 1613dd0191d5SShuanglin Wang { 1614dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 1615dd0191d5SShuanglin Wang struct tfc_tcam_info tcam_info = { 0 }; 1616dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 1617dd0191d5SShuanglin Wang 1618*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(ulp, &fw_fid))) { 1619dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func_id\n"); 1620dd0191d5SShuanglin Wang return -EINVAL; 1621dd0191d5SShuanglin Wang } 1622dd0191d5SShuanglin Wang 1623dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(ulp); 1624*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1625dd0191d5SShuanglin Wang PMD_DRV_LOG_LINE(ERR, "Failed to get tfcp pointer"); 1626dd0191d5SShuanglin Wang return -EINVAL; 1627dd0191d5SShuanglin Wang } 1628dd0191d5SShuanglin Wang tcam_info.dir = (enum cfa_dir)res->direction; 1629dd0191d5SShuanglin Wang tcam_info.rsubtype = res->resource_type; 1630dd0191d5SShuanglin Wang tcam_info.id = (uint16_t)res->resource_hndl; 1631dd0191d5SShuanglin Wang 1632*0c036a14SPeter Spreadborough if (unlikely(!tfcp || tfc_tcam_free(tfcp, fw_fid, &tcam_info))) { 1633dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Unable to free tcam resource %u\n", 1634dd0191d5SShuanglin Wang tcam_info.id); 1635dd0191d5SShuanglin Wang return -EINVAL; 1636dd0191d5SShuanglin Wang } 1637be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1638be4732e8SMike Baucom #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1639be4732e8SMike Baucom BNXT_DRV_DBG(DEBUG, "Freed TCAM [%s]:[%s] = 0x%X\n", 1640be4732e8SMike Baucom tfc_dir_2_str(tcam_info.dir), 1641be4732e8SMike Baucom tfc_tcam_2_str(tcam_info.rsubtype), tcam_info.id); 1642be4732e8SMike Baucom #endif 1643be4732e8SMike Baucom #endif 1644dd0191d5SShuanglin Wang return 0; 1645dd0191d5SShuanglin Wang } 1646dd0191d5SShuanglin Wang 1647dd0191d5SShuanglin Wang static uint32_t 1648dd0191d5SShuanglin Wang ulp_mapper_tfc_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *parm __rte_unused, 1649dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_tbl_info *tbl, 1650dd0191d5SShuanglin Wang uint16_t blob_len, 1651dd0191d5SShuanglin Wang uint16_t *out_len) 1652dd0191d5SShuanglin Wang { 1653dd0191d5SShuanglin Wang switch (tbl->resource_type) { 1654dd0191d5SShuanglin Wang case CFA_RSUBTYPE_CMM_ACT: 1655dd0191d5SShuanglin Wang *out_len = ULP_BITS_TO_32_BYTE_WORD(blob_len); 1656dd0191d5SShuanglin Wang *out_len = *out_len * 256; 1657dd0191d5SShuanglin Wang break; 1658dd0191d5SShuanglin Wang default: 1659dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Not a dynamic table %d\n", tbl->resource_type); 1660dd0191d5SShuanglin Wang *out_len = blob_len; 1661dd0191d5SShuanglin Wang break; 1662dd0191d5SShuanglin Wang } 1663dd0191d5SShuanglin Wang 1664dd0191d5SShuanglin Wang return tbl->resource_type; 1665dd0191d5SShuanglin Wang } 1666dd0191d5SShuanglin Wang 1667dd0191d5SShuanglin Wang static int32_t 1668dd0191d5SShuanglin Wang ulp_mapper_tfc_index_tbl_alloc_process(struct bnxt_ulp_context *ulp, 1669dd0191d5SShuanglin Wang uint32_t session_type __rte_unused, 1670dd0191d5SShuanglin Wang uint16_t table_type, 1671dd0191d5SShuanglin Wang uint8_t direction, 1672dd0191d5SShuanglin Wang uint64_t *index) 1673dd0191d5SShuanglin Wang { 1674dd0191d5SShuanglin Wang enum cfa_track_type tt = CFA_TRACK_TYPE_SID; 1675dd0191d5SShuanglin Wang struct tfc_idx_tbl_info tbl_info = { 0 }; 1676dd0191d5SShuanglin Wang struct tfc *tfcp = NULL; 1677dd0191d5SShuanglin Wang uint16_t fw_fid = 0; 1678dd0191d5SShuanglin Wang int32_t rc = 0; 1679dd0191d5SShuanglin Wang 1680dd0191d5SShuanglin Wang tfcp = bnxt_ulp_cntxt_tfcp_get(ulp); 1681*0c036a14SPeter Spreadborough if (unlikely(tfcp == NULL)) { 1682dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get tfcp pointer\n"); 1683dd0191d5SShuanglin Wang return -EINVAL; 1684dd0191d5SShuanglin Wang } 1685dd0191d5SShuanglin Wang 1686*0c036a14SPeter Spreadborough if (unlikely(bnxt_ulp_cntxt_fid_get(ulp, &fw_fid))) { 1687dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Failed to get func id\n"); 1688dd0191d5SShuanglin Wang return -EINVAL; 1689dd0191d5SShuanglin Wang } 1690dd0191d5SShuanglin Wang 1691dd0191d5SShuanglin Wang tbl_info.rsubtype = table_type; 1692dd0191d5SShuanglin Wang tbl_info.dir = direction; 1693dd0191d5SShuanglin Wang rc = tfc_idx_tbl_alloc(tfcp, fw_fid, tt, &tbl_info); 1694*0c036a14SPeter Spreadborough if (unlikely(rc)) { 1695dd0191d5SShuanglin Wang BNXT_DRV_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 1696dd0191d5SShuanglin Wang tfc_idx_tbl_2_str(tbl_info.rsubtype), 1697dd0191d5SShuanglin Wang tfc_dir_2_str(direction), rc); 1698dd0191d5SShuanglin Wang return rc; 1699dd0191d5SShuanglin Wang } 1700dd0191d5SShuanglin Wang 1701dd0191d5SShuanglin Wang *index = tbl_info.id; 1702dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1703dd0191d5SShuanglin Wang #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1704dd0191d5SShuanglin Wang BNXT_DRV_DBG(DEBUG, "Allocated Table Index [%s][%s] = 0x%04x\n", 1705dd0191d5SShuanglin Wang tfc_idx_tbl_2_str(table_type), tfc_dir_2_str(direction), 1706dd0191d5SShuanglin Wang tbl_info.id); 1707dd0191d5SShuanglin Wang #endif 1708dd0191d5SShuanglin Wang #endif 1709dd0191d5SShuanglin Wang return rc; 1710dd0191d5SShuanglin Wang } 1711dd0191d5SShuanglin Wang 1712dd0191d5SShuanglin Wang static int32_t 1713dd0191d5SShuanglin Wang ulp_mapper_tfc_app_glb_resource_info_init(struct bnxt_ulp_context 1714dd0191d5SShuanglin Wang *ulp_ctx __rte_unused, 1715dd0191d5SShuanglin Wang struct bnxt_ulp_mapper_data 1716dd0191d5SShuanglin Wang *mapper_data __rte_unused) 1717dd0191d5SShuanglin Wang { 1718dd0191d5SShuanglin Wang /* Not supported Shared Apps yet on TFC API */ 1719dd0191d5SShuanglin Wang return 0; 1720dd0191d5SShuanglin Wang } 1721dd0191d5SShuanglin Wang 1722dd0191d5SShuanglin Wang static int32_t 1723dd0191d5SShuanglin Wang ulp_mapper_tfc_handle_to_offset(struct bnxt_ulp_mapper_parms *parms __rte_unused, 1724dd0191d5SShuanglin Wang uint64_t handle, 1725dd0191d5SShuanglin Wang uint32_t offset, 1726dd0191d5SShuanglin Wang uint64_t *result) 1727dd0191d5SShuanglin Wang { 1728dd0191d5SShuanglin Wang uint32_t val = 0; 1729dd0191d5SShuanglin Wang int32_t rc = 0; 1730dd0191d5SShuanglin Wang 1731dd0191d5SShuanglin Wang TFC_GET_32B_OFFSET_ACT_HANDLE(val, &handle); 1732dd0191d5SShuanglin Wang 1733dd0191d5SShuanglin Wang switch (offset) { 1734dd0191d5SShuanglin Wang case 0: 1735dd0191d5SShuanglin Wang val = val << 5; 1736dd0191d5SShuanglin Wang break; 1737dd0191d5SShuanglin Wang case 4: 1738dd0191d5SShuanglin Wang val = val << 3; 1739dd0191d5SShuanglin Wang break; 1740dd0191d5SShuanglin Wang case 8: 1741dd0191d5SShuanglin Wang val = val << 2; 1742dd0191d5SShuanglin Wang break; 1743dd0191d5SShuanglin Wang case 16: 1744dd0191d5SShuanglin Wang val = val << 1; 1745dd0191d5SShuanglin Wang break; 1746dd0191d5SShuanglin Wang case 32: 1747dd0191d5SShuanglin Wang break; 1748dd0191d5SShuanglin Wang default: 1749dd0191d5SShuanglin Wang return -EINVAL; 1750dd0191d5SShuanglin Wang } 1751dd0191d5SShuanglin Wang 1752dd0191d5SShuanglin Wang *result = val; 1753dd0191d5SShuanglin Wang return rc; 1754dd0191d5SShuanglin Wang } 1755dd0191d5SShuanglin Wang 1756dd0191d5SShuanglin Wang static int 1757dd0191d5SShuanglin Wang ulp_mapper_tfc_mpc_batch_start(struct tfc_mpc_batch_info_t *batch_info) 1758dd0191d5SShuanglin Wang { 1759dd0191d5SShuanglin Wang return tfc_mpc_batch_start(batch_info); 1760dd0191d5SShuanglin Wang } 1761dd0191d5SShuanglin Wang 1762dd0191d5SShuanglin Wang const struct ulp_mapper_core_ops ulp_mapper_tfc_core_ops = { 1763dd0191d5SShuanglin Wang .ulp_mapper_core_tcam_tbl_process = ulp_mapper_tfc_tcam_tbl_process, 1764dd0191d5SShuanglin Wang .ulp_mapper_core_tcam_entry_free = ulp_mapper_tfc_tcam_entry_free, 1765dd0191d5SShuanglin Wang .ulp_mapper_core_em_tbl_process = ulp_mapper_tfc_em_tbl_process, 1766dd0191d5SShuanglin Wang .ulp_mapper_core_em_entry_free = ulp_mapper_tfc_em_entry_free, 1767dd0191d5SShuanglin Wang .ulp_mapper_core_index_tbl_process = ulp_mapper_tfc_index_tbl_process, 1768dd0191d5SShuanglin Wang .ulp_mapper_core_index_entry_free = ulp_mapper_tfc_index_entry_free, 1769dd0191d5SShuanglin Wang .ulp_mapper_core_cmm_tbl_process = ulp_mapper_tfc_cmm_tbl_process, 1770dd0191d5SShuanglin Wang .ulp_mapper_core_cmm_entry_free = ulp_mapper_tfc_cmm_entry_free, 1771dd0191d5SShuanglin Wang .ulp_mapper_core_if_tbl_process = ulp_mapper_tfc_if_tbl_process, 1772dd0191d5SShuanglin Wang .ulp_mapper_core_ident_alloc_process = ulp_mapper_tfc_ident_alloc, 1773dd0191d5SShuanglin Wang .ulp_mapper_core_ident_free = ulp_mapper_tfc_ident_free, 1774dd0191d5SShuanglin Wang .ulp_mapper_core_dyn_tbl_type_get = ulp_mapper_tfc_dyn_tbl_type_get, 1775dd0191d5SShuanglin Wang .ulp_mapper_core_index_tbl_alloc_process = 1776dd0191d5SShuanglin Wang ulp_mapper_tfc_index_tbl_alloc_process, 1777dd0191d5SShuanglin Wang .ulp_mapper_core_app_glb_res_info_init = 1778dd0191d5SShuanglin Wang ulp_mapper_tfc_app_glb_resource_info_init, 1779dd0191d5SShuanglin Wang .ulp_mapper_core_handle_to_offset = ulp_mapper_tfc_handle_to_offset, 1780dd0191d5SShuanglin Wang .ulp_mapper_mpc_batch_start = ulp_mapper_tfc_mpc_batch_start, 1781dd0191d5SShuanglin Wang .ulp_mapper_mpc_batch_started = ulp_mapper_tfc_mpc_batch_started, 1782dd0191d5SShuanglin Wang .ulp_mapper_mpc_batch_end = ulp_mapper_tfc_mpc_batch_end 1783dd0191d5SShuanglin Wang }; 1784