1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include "ulp_mapper.h" 7 #include "ulp_flow_db.h" 8 #include "ulp_ha_mgr.h" 9 #include "tfp.h" 10 #include "tf_util.h" 11 #include "bnxt_ulp_utils.h" 12 #include "bnxt_ulp_tf.h" 13 14 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 15 #include "ulp_template_debug_proto.h" 16 #include "ulp_tf_debug.h" 17 #endif 18 19 /* Internal function to write the tcam entry */ 20 static int32_t 21 ulp_mapper_tf_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms, 22 struct bnxt_ulp_mapper_tbl_info *tbl, 23 struct ulp_blob *key, 24 struct ulp_blob *mask, 25 struct ulp_blob *data, 26 uint16_t idx) 27 { 28 struct tf_set_tcam_entry_parms sparms = { 0 }; 29 struct tf *tfp; 30 uint16_t tmplen; 31 int32_t rc; 32 33 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type); 34 if (!tfp) { 35 BNXT_DRV_DBG(ERR, "Failed to get truflow pointer\n"); 36 return -EINVAL; 37 } 38 39 sparms.dir = tbl->direction; 40 sparms.tcam_tbl_type = tbl->resource_type; 41 sparms.idx = idx; 42 sparms.key = ulp_blob_data_get(key, &tmplen); 43 sparms.key_sz_in_bits = tmplen; 44 sparms.mask = ulp_blob_data_get(mask, &tmplen); 45 sparms.result = ulp_blob_data_get(data, &tmplen); 46 sparms.result_sz_in_bits = tmplen; 47 if (tf_set_tcam_entry(tfp, &sparms)) { 48 BNXT_DRV_DBG(ERR, "tcam[%s][%s][%x] write failed.\n", 49 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 50 tf_dir_2_str(sparms.dir), sparms.idx); 51 return -EIO; 52 } 53 BNXT_DRV_INF("tcam[%s][%s][%x] write success.\n", 54 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 55 tf_dir_2_str(sparms.dir), sparms.idx); 56 57 /* Mark action */ 58 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 59 if (rc) { 60 BNXT_DRV_DBG(ERR, "failed mark action processing\n"); 61 return rc; 62 } 63 64 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 65 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 66 ulp_mapper_tcam_entry_dump("TCAM", idx, tbl, key, mask, data); 67 #endif 68 #endif 69 return rc; 70 } 71 72 static 73 int32_t ulp_mapper_tf_tcam_is_wc_tcam(struct bnxt_ulp_mapper_tbl_info *tbl) 74 { 75 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM || 76 tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH || 77 tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW) 78 return 1; 79 return 0; 80 } 81 82 static int32_t 83 ulp_mapper_tf_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 84 struct bnxt_ulp_mapper_tbl_info *tbl) 85 { 86 struct bnxt_ulp_mapper_key_info *kflds; 87 struct ulp_blob okey, omask, data, update_data; 88 struct ulp_blob tkey, tmask; /* transform key and mask */ 89 struct ulp_blob *key, *mask; 90 uint32_t i, num_kflds; 91 struct tf *tfp; 92 int32_t rc, trc; 93 struct bnxt_ulp_device_params *dparms = parms->device_params; 94 struct tf_alloc_tcam_entry_parms aparms = { 0 }; 95 struct ulp_flow_db_res_params fid_parms = { 0 }; 96 struct tf_free_tcam_entry_parms free_parms = { 0 }; 97 uint16_t tmplen = 0; 98 uint16_t idx = 0; 99 enum bnxt_ulp_byte_order key_byte_order; 100 101 /* Set the key and mask to the original key and mask. */ 102 key = &okey; 103 mask = &omask; 104 105 /* Skip this tcam table opcode is NOP */ 106 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED || 107 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) { 108 BNXT_DRV_DBG(ERR, "Invalid tcam table opcode %d\n", 109 tbl->tbl_opcode); 110 return 0; 111 } 112 113 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type); 114 if (!tfp) { 115 BNXT_DRV_DBG(ERR, "Failed to get truflow pointer\n"); 116 return -EINVAL; 117 } 118 119 /* If only allocation of identifier then perform and exit */ 120 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT) { 121 rc = ulp_mapper_tcam_tbl_ident_alloc(parms, tbl); 122 return rc; 123 } 124 125 if (tbl->key_recipe_opcode == BNXT_ULP_KEY_RECIPE_OPC_DYN_KEY) 126 kflds = ulp_mapper_key_recipe_fields_get(parms, tbl, &num_kflds); 127 else 128 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 129 if (!kflds || !num_kflds) { 130 BNXT_DRV_DBG(ERR, "Failed to get key fields\n"); 131 return -EINVAL; 132 } 133 134 if (ulp_mapper_tf_tcam_is_wc_tcam(tbl)) 135 key_byte_order = dparms->wc_key_byte_order; 136 else 137 key_byte_order = dparms->key_byte_order; 138 139 if (ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) || 140 ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) || 141 ulp_blob_init(&data, tbl->result_bit_size, 142 dparms->result_byte_order) || 143 ulp_blob_init(&update_data, tbl->result_bit_size, 144 dparms->result_byte_order)) { 145 BNXT_DRV_DBG(ERR, "blob inits failed.\n"); 146 return -EINVAL; 147 } 148 149 /* create the key/mask */ 150 /* 151 * NOTE: The WC table will require some kind of flag to handle the 152 * mode bits within the key/mask 153 */ 154 for (i = 0; i < num_kflds; i++) { 155 /* Setup the key */ 156 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 157 &kflds[i].field_info_spec, 158 key, 1, "TCAM Key"); 159 if (rc) { 160 BNXT_DRV_DBG(ERR, "Key field set failed %s\n", 161 kflds[i].field_info_spec.description); 162 return rc; 163 } 164 165 /* Setup the mask */ 166 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 167 &kflds[i].field_info_mask, 168 mask, 0, "TCAM Mask"); 169 if (rc) { 170 BNXT_DRV_DBG(ERR, "Mask field set failed %s\n", 171 kflds[i].field_info_mask.description); 172 return rc; 173 } 174 } 175 176 /* For wild card tcam perform the post process to swap the blob */ 177 if (ulp_mapper_tf_tcam_is_wc_tcam(tbl)) { 178 if (dparms->wc_dynamic_pad_en) { 179 /* Sets up the slices for writing to the WC TCAM */ 180 rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms, 181 key, mask, 182 &tkey, 183 &tmask); 184 if (rc) { 185 BNXT_DRV_DBG(ERR, 186 "Failed to post proc WC entry.\n"); 187 return rc; 188 } 189 /* Now need to use the transform Key/Mask */ 190 key = &tkey; 191 mask = &tmask; 192 } else { 193 ulp_mapper_wc_tcam_tbl_post_process(key); 194 ulp_mapper_wc_tcam_tbl_post_process(mask); 195 } 196 } 197 198 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 199 /* allocate the tcam index */ 200 aparms.dir = tbl->direction; 201 aparms.tcam_tbl_type = tbl->resource_type; 202 aparms.key = ulp_blob_data_get(key, &tmplen); 203 aparms.key_sz_in_bits = tmplen; 204 aparms.mask = ulp_blob_data_get(mask, &tmplen); 205 206 /* calculate the entry priority */ 207 rc = ulp_mapper_priority_opc_process(parms, tbl, 208 &aparms.priority); 209 if (rc) { 210 BNXT_DRV_DBG(ERR, "entry priority process failed\n"); 211 return rc; 212 } 213 214 rc = tf_alloc_tcam_entry(tfp, &aparms); 215 if (rc) { 216 BNXT_DRV_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); 217 return rc; 218 } 219 idx = aparms.idx; 220 } 221 222 /* Write the tcam index into the regfile*/ 223 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand, 224 (uint64_t)tfp_cpu_to_be_64(idx))) { 225 BNXT_DRV_DBG(ERR, "Regfile[%d] write failed.\n", 226 tbl->tbl_operand); 227 rc = -EINVAL; 228 /* Need to free the tcam idx, so goto error */ 229 goto error; 230 } 231 232 /* if it is miss then it is same as no search before alloc */ 233 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 234 /*Scan identifier list, allocate identifier and update regfile*/ 235 rc = ulp_mapper_tcam_tbl_ident_alloc(parms, tbl); 236 /* Create the result blob */ 237 if (!rc) 238 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 239 "TCAM Result"); 240 /* write the tcam entry */ 241 if (!rc) 242 rc = ulp_mapper_tf_tcam_tbl_entry_write(parms, tbl, key, 243 mask, &data, 244 idx); 245 } 246 247 if (rc) 248 goto error; 249 250 /* Add the tcam index to the flow database */ 251 fid_parms.direction = tbl->direction; 252 fid_parms.resource_func = tbl->resource_func; 253 fid_parms.resource_type = tbl->resource_type; 254 fid_parms.critical_resource = tbl->critical_resource; 255 fid_parms.resource_hndl = idx; 256 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 257 258 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 259 if (rc) { 260 BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 261 rc); 262 /* Need to free the identifier, so goto error */ 263 goto error; 264 } 265 266 return 0; 267 error: 268 free_parms.dir = tbl->direction; 269 free_parms.tcam_tbl_type = tbl->resource_type; 270 free_parms.idx = idx; 271 trc = tf_free_tcam_entry(tfp, &free_parms); 272 if (trc) 273 BNXT_DRV_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", 274 tbl->resource_type, tbl->direction, idx); 275 return rc; 276 } 277 278 static int32_t 279 ulp_mapper_tf_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 280 struct bnxt_ulp_mapper_tbl_info *tbl, 281 void *error) 282 { 283 struct bnxt_ulp_mapper_key_info *kflds; 284 struct ulp_blob key, data; 285 uint32_t i, num_kflds; 286 uint16_t tmplen; 287 struct tf *tfp; 288 struct ulp_flow_db_res_params fid_parms = { 0 }; 289 struct tf_insert_em_entry_parms iparms = { 0 }; 290 struct tf_delete_em_entry_parms free_parms = { 0 }; 291 enum bnxt_ulp_flow_mem_type mtype; 292 struct bnxt_ulp_device_params *dparms = parms->device_params; 293 int32_t trc; 294 int32_t rc = 0; 295 int32_t pad = 0; 296 enum bnxt_ulp_byte_order key_order, res_order; 297 298 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type); 299 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); 300 if (rc) { 301 BNXT_DRV_DBG(ERR, "Failed to get the mem type for EM\n"); 302 return -EINVAL; 303 } 304 305 if (tbl->key_recipe_opcode == BNXT_ULP_KEY_RECIPE_OPC_DYN_KEY) 306 kflds = ulp_mapper_key_recipe_fields_get(parms, tbl, &num_kflds); 307 else 308 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 309 if (!kflds || !num_kflds) { 310 BNXT_DRV_DBG(ERR, "Failed to get key fields\n"); 311 return -EINVAL; 312 } 313 314 key_order = dparms->em_byte_order; 315 res_order = dparms->em_byte_order; 316 317 /* Initialize the key/result blobs */ 318 if (ulp_blob_init(&key, tbl->blob_key_bit_size, key_order) || 319 ulp_blob_init(&data, tbl->result_bit_size, res_order)) { 320 BNXT_DRV_DBG(ERR, "blob inits failed.\n"); 321 return -EINVAL; 322 } 323 324 /* create the key */ 325 for (i = 0; i < num_kflds; i++) { 326 /* Setup the key */ 327 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 328 &kflds[i].field_info_spec, 329 &key, 1, "EM Key"); 330 if (rc) { 331 BNXT_DRV_DBG(ERR, "Key field set failed.\n"); 332 return rc; 333 } 334 } 335 336 /* if dynamic padding is enabled then add padding to result data */ 337 if (dparms->em_dynamic_pad_en) { 338 /* add padding to make sure key is at byte boundary */ 339 ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS); 340 341 /* add the pad */ 342 pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits; 343 if (pad < 0) { 344 BNXT_DRV_DBG(ERR, "Invalid em blk size and align\n"); 345 return -EINVAL; 346 } 347 ulp_blob_pad_push(&data, (uint32_t)pad); 348 } 349 350 /* Create the result data blob */ 351 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result"); 352 if (rc) { 353 BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 354 return rc; 355 } 356 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 357 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 358 ulp_mapper_result_dump("EM Result", tbl, &data); 359 #endif 360 #endif 361 if (dparms->em_dynamic_pad_en) { 362 uint32_t abits = dparms->em_blk_align_bits; 363 364 /* when dynamic padding is enabled merge result + key */ 365 rc = ulp_blob_block_merge(&data, &key, abits, pad); 366 if (rc) { 367 BNXT_DRV_DBG(ERR, "Failed to merge the result blob\n"); 368 return rc; 369 } 370 371 /* add padding to make sure merged result is at slice boundary*/ 372 ulp_blob_pad_align(&data, abits); 373 374 ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits)); 375 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 376 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 377 ulp_mapper_result_dump("EM Merged Result", tbl, &data); 378 #endif 379 #endif 380 } 381 382 /* do the transpose for the internal EM keys */ 383 if (tbl->resource_type == TF_MEM_INTERNAL) { 384 if (dparms->em_key_align_bytes) { 385 int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes); 386 387 tmplen = ulp_blob_data_len_get(&key); 388 ulp_blob_pad_push(&key, b - tmplen); 389 } 390 tmplen = ulp_blob_data_len_get(&key); 391 ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen)); 392 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 393 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 394 ulp_mapper_result_dump("EM Key Transpose", tbl, &key); 395 #endif 396 #endif 397 } 398 399 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, 400 &iparms.tbl_scope_id); 401 if (rc) { 402 BNXT_DRV_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 403 return rc; 404 } 405 406 /* 407 * NOTE: the actual blob size will differ from the size in the tbl 408 * entry due to the padding. 409 */ 410 iparms.dup_check = 0; 411 iparms.dir = tbl->direction; 412 iparms.mem = tbl->resource_type; 413 iparms.key = ulp_blob_data_get(&key, &tmplen); 414 iparms.key_sz_in_bits = tbl->key_bit_size; 415 iparms.em_record = ulp_blob_data_get(&data, &tmplen); 416 if (tbl->result_bit_size) 417 iparms.em_record_sz_in_bits = tbl->result_bit_size; 418 else 419 iparms.em_record_sz_in_bits = tmplen; 420 421 rc = tf_insert_em_entry(tfp, &iparms); 422 if (rc) { 423 /* Set the error flag in reg file */ 424 if (tbl->tbl_opcode == BNXT_ULP_EM_TBL_OPC_WR_REGFILE) { 425 uint64_t val = 0; 426 427 /* over max flows or hash collision */ 428 if (rc == -EIO || rc == -ENOMEM) { 429 val = 1; 430 rc = 0; 431 BNXT_DRV_DBG(DEBUG, 432 "Fail to insert EM, shall add to wc\n"); 433 } 434 ulp_regfile_write(parms->regfile, tbl->tbl_operand, 435 tfp_cpu_to_be_64(val)); 436 } 437 if (rc) 438 BNXT_DRV_DBG(ERR, 439 "Failed to insert em entry rc=%d.\n", rc); 440 if (rc && error != NULL) 441 rte_flow_error_set((struct rte_flow_error *)error, EIO, 442 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 443 "error adding EM entry"); 444 return rc; 445 } 446 447 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 448 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 449 ulp_mapper_em_dump("EM", &key, &data, &iparms); 450 /* tf_dump_tables(tfp, iparms.tbl_scope_id); */ 451 #endif 452 #endif 453 /* Mark action process */ 454 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && 455 tbl->resource_type == TF_MEM_EXTERNAL) 456 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); 457 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && 458 tbl->resource_type == TF_MEM_INTERNAL) 459 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 460 if (rc) { 461 BNXT_DRV_DBG(ERR, "Failed to add mark to flow\n"); 462 goto error; 463 } 464 465 /* Link the EM resource to the flow in the flow db */ 466 memset(&fid_parms, 0, sizeof(fid_parms)); 467 fid_parms.direction = tbl->direction; 468 fid_parms.resource_func = tbl->resource_func; 469 fid_parms.resource_type = tbl->resource_type; 470 fid_parms.critical_resource = tbl->critical_resource; 471 fid_parms.resource_hndl = iparms.flow_handle; 472 473 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 474 if (rc) { 475 BNXT_DRV_DBG(ERR, "Fail to link res to flow rc = %d\n", 476 rc); 477 /* Need to free the identifier, so goto error */ 478 goto error; 479 } 480 481 return 0; 482 error: 483 free_parms.dir = iparms.dir; 484 free_parms.mem = iparms.mem; 485 free_parms.tbl_scope_id = iparms.tbl_scope_id; 486 free_parms.flow_handle = iparms.flow_handle; 487 488 trc = tf_delete_em_entry(tfp, &free_parms); 489 if (trc) 490 BNXT_DRV_DBG(ERR, "Failed to delete EM entry on failed add\n"); 491 492 if (error != NULL) 493 rte_flow_error_set((struct rte_flow_error *)error, EIO, 494 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 495 "error adding EM entry"); 496 return rc; 497 } 498 499 static uint16_t 500 ulp_mapper_tf_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms, 501 struct bnxt_ulp_mapper_tbl_info *tbl) 502 { 503 struct bnxt_ulp_device_params *d_params = mparms->device_params; 504 505 if (d_params->dynamic_sram_en) { 506 switch (tbl->resource_type) { 507 case TF_TBL_TYPE_ACT_ENCAP_8B: 508 case TF_TBL_TYPE_ACT_ENCAP_16B: 509 case TF_TBL_TYPE_ACT_ENCAP_32B: 510 case TF_TBL_TYPE_ACT_ENCAP_64B: 511 case TF_TBL_TYPE_ACT_MODIFY_8B: 512 case TF_TBL_TYPE_ACT_MODIFY_16B: 513 case TF_TBL_TYPE_ACT_MODIFY_32B: 514 case TF_TBL_TYPE_ACT_MODIFY_64B: 515 /* return max size */ 516 return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 517 default: 518 break; 519 } 520 } else if (tbl->encap_num_fields) { 521 return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 522 } 523 return tbl->result_bit_size; 524 } 525 526 static int32_t 527 ulp_mapper_tf_em_entry_free(struct bnxt_ulp_context *ulp, 528 struct ulp_flow_db_res_params *res, 529 __rte_unused void *error) 530 { 531 struct tf_delete_em_entry_parms fparms = { 0 }; 532 struct tf *tfp; 533 uint32_t session_type; 534 int32_t rc; 535 536 session_type = ulp_flow_db_shared_session_get(res); 537 tfp = bnxt_ulp_cntxt_tfp_get(ulp, session_type); 538 if (!tfp) { 539 BNXT_DRV_DBG(ERR, "Failed to get tf pointer\n"); 540 return -EINVAL; 541 } 542 543 fparms.dir = res->direction; 544 fparms.flow_handle = res->resource_hndl; 545 546 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 547 if (rc) { 548 BNXT_DRV_DBG(ERR, "Failed to get table scope\n"); 549 return -EINVAL; 550 } 551 552 return tf_delete_em_entry(tfp, &fparms); 553 } 554 555 static uint32_t 556 ulp_mapper_tf_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *mparms, 557 struct bnxt_ulp_mapper_tbl_info *tbl, 558 uint16_t blob_len, 559 uint16_t *out_len) 560 { 561 struct bnxt_ulp_device_params *d_params = mparms->device_params; 562 struct bnxt_ulp_dyn_size_map *size_map; 563 uint32_t i; 564 565 if (d_params->dynamic_sram_en) { 566 switch (tbl->resource_type) { 567 case TF_TBL_TYPE_ACT_ENCAP_8B: 568 case TF_TBL_TYPE_ACT_ENCAP_16B: 569 case TF_TBL_TYPE_ACT_ENCAP_32B: 570 case TF_TBL_TYPE_ACT_ENCAP_64B: 571 case TF_TBL_TYPE_ACT_ENCAP_128B: 572 size_map = d_params->dyn_encap_sizes; 573 for (i = 0; i < d_params->dyn_encap_list_size; i++) { 574 if (blob_len <= size_map[i].slab_size) { 575 *out_len = size_map[i].slab_size; 576 return size_map[i].tbl_type; 577 } 578 } 579 break; 580 case TF_TBL_TYPE_ACT_MODIFY_8B: 581 case TF_TBL_TYPE_ACT_MODIFY_16B: 582 case TF_TBL_TYPE_ACT_MODIFY_32B: 583 case TF_TBL_TYPE_ACT_MODIFY_64B: 584 size_map = d_params->dyn_modify_sizes; 585 for (i = 0; i < d_params->dyn_modify_list_size; i++) { 586 if (blob_len <= size_map[i].slab_size) { 587 *out_len = size_map[i].slab_size; 588 return size_map[i].tbl_type; 589 } 590 } 591 break; 592 default: 593 break; 594 } 595 } 596 return tbl->resource_type; 597 } 598 599 static int32_t 600 ulp_mapper_tf_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 601 struct bnxt_ulp_mapper_tbl_info *tbl) 602 { 603 struct ulp_flow_db_res_params fid_parms; 604 struct ulp_blob data; 605 uint64_t regval = 0; 606 uint16_t tmplen; 607 uint32_t index; 608 int32_t rc = 0, trc = 0; 609 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 610 struct tf_set_tbl_entry_parms sparms = { 0 }; 611 struct tf_get_tbl_entry_parms gparms = { 0 }; 612 struct tf_free_tbl_entry_parms free_parms = { 0 }; 613 uint32_t tbl_scope_id; 614 struct tf *tfp; 615 struct bnxt_ulp_glb_resource_info glb_res = { 0 }; 616 uint16_t bit_size; 617 bool alloc = false; 618 bool write = false; 619 bool global = false; 620 uint64_t act_rec_size; 621 bool shared = false; 622 enum tf_tbl_type tbl_type = tbl->resource_type; 623 uint16_t blob_len; 624 625 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type); 626 /* compute the blob size */ 627 bit_size = ulp_mapper_tf_dyn_blob_size_get(parms, tbl); 628 629 /* Initialize the blob data */ 630 if (ulp_blob_init(&data, bit_size, 631 parms->device_params->result_byte_order)) { 632 BNXT_DRV_DBG(ERR, "Failed to initialize index table blob\n"); 633 return -EINVAL; 634 } 635 636 /* Get the scope id first */ 637 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); 638 if (rc) { 639 BNXT_DRV_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 640 return rc; 641 } 642 643 switch (tbl->tbl_opcode) { 644 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE: 645 alloc = true; 646 break; 647 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE: 648 /* 649 * Build the entry, alloc an index, write the table, and store 650 * the data in the regfile. 651 */ 652 alloc = true; 653 write = true; 654 break; 655 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE: 656 /* 657 * get the index to write to from the regfile and then write 658 * the table entry. 659 */ 660 if (ulp_regfile_read(parms->regfile, 661 tbl->tbl_operand, 662 ®val)) { 663 BNXT_DRV_DBG(ERR, 664 "Failed to get tbl idx from regfile[%d].\n", 665 tbl->tbl_operand); 666 return -EINVAL; 667 } 668 index = tfp_be_to_cpu_64(regval); 669 /* For external, we need to reverse shift */ 670 if (tbl->resource_type == TF_TBL_TYPE_EXT) 671 index = TF_ACT_REC_PTR_2_OFFSET(index); 672 673 write = true; 674 break; 675 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE: 676 /* 677 * Build the entry, alloc an index, write the table, and store 678 * the data in the global regfile. 679 */ 680 alloc = true; 681 global = true; 682 write = true; 683 glb_res.direction = tbl->direction; 684 glb_res.resource_func = tbl->resource_func; 685 glb_res.resource_type = tbl->resource_type; 686 glb_res.glb_regfile_index = tbl->tbl_operand; 687 break; 688 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE: 689 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) { 690 BNXT_DRV_DBG(ERR, "Template error, wrong fdb opcode\n"); 691 return -EINVAL; 692 } 693 /* 694 * get the index to write to from the global regfile and then 695 * write the table. 696 */ 697 if (ulp_mapper_glb_resource_read(parms->mapper_data, 698 tbl->direction, 699 tbl->tbl_operand, 700 ®val, &shared)) { 701 BNXT_DRV_DBG(ERR, 702 "Failed to get tbl idx from Glb RF[%d].\n", 703 tbl->tbl_operand); 704 return -EINVAL; 705 } 706 index = tfp_be_to_cpu_64(regval); 707 /* For external, we need to reverse shift */ 708 if (tbl->resource_type == TF_TBL_TYPE_EXT) 709 index = TF_ACT_REC_PTR_2_OFFSET(index); 710 write = true; 711 break; 712 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE: 713 /* 714 * The read is different from the rest and can be handled here 715 * instead of trying to use common code. Simply read the table 716 * with the index from the regfile, scan and store the 717 * identifiers, and return. 718 */ 719 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 720 /* Not currently supporting with EXT */ 721 BNXT_DRV_DBG(ERR, 722 "Ext Table Read Opcode not supported.\n"); 723 return -EINVAL; 724 } 725 if (ulp_regfile_read(parms->regfile, 726 tbl->tbl_operand, ®val)) { 727 BNXT_DRV_DBG(ERR, 728 "Failed to get tbl idx from regfile[%d]\n", 729 tbl->tbl_operand); 730 return -EINVAL; 731 } 732 index = tfp_be_to_cpu_64(regval); 733 gparms.dir = tbl->direction; 734 gparms.type = tbl->resource_type; 735 gparms.data = ulp_blob_data_get(&data, &tmplen); 736 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size); 737 gparms.idx = index; 738 rc = tf_get_tbl_entry(tfp, &gparms); 739 if (rc) { 740 BNXT_DRV_DBG(ERR, 741 "Failed to read the tbl entry %d:%d\n", 742 tbl->resource_type, index); 743 return rc; 744 } 745 /* 746 * Scan the fields in the entry and push them into the regfile. 747 */ 748 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 749 gparms.data, 750 gparms.data_sz_in_bytes, 751 data.byte_order); 752 if (rc) { 753 BNXT_DRV_DBG(ERR, 754 "Failed to get flds on tbl read rc=%d\n", 755 rc); 756 return rc; 757 } 758 return 0; 759 default: 760 BNXT_DRV_DBG(ERR, "Invalid index table opcode %d\n", 761 tbl->tbl_opcode); 762 return -EINVAL; 763 } 764 765 if (write) { 766 /* Get the result fields list */ 767 rc = ulp_mapper_tbl_result_build(parms, 768 tbl, 769 &data, 770 "Indexed Result"); 771 if (rc) { 772 BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 773 return rc; 774 } 775 } 776 777 if (alloc) { 778 aparms.dir = tbl->direction; 779 blob_len = ulp_blob_data_len_get(&data); 780 tbl_type = ulp_mapper_tf_dyn_tbl_type_get(parms, tbl, 781 blob_len, 782 &tmplen); 783 aparms.type = tbl_type; 784 aparms.tbl_scope_id = tbl_scope_id; 785 786 /* All failures after the alloc succeeds require a free */ 787 rc = tf_alloc_tbl_entry(tfp, &aparms); 788 if (rc) { 789 BNXT_DRV_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 790 tf_tbl_type_2_str(aparms.type), 791 tf_dir_2_str(tbl->direction), rc); 792 return rc; 793 } 794 index = aparms.idx; 795 796 /* 797 * Store the index in the regfile since we either allocated it 798 * or it was a hit. 799 * 800 * Calculate the idx for the result record, for external EM the 801 * offset needs to be shifted accordingly. 802 * If external non-inline table types are used then need to 803 * revisit this logic. 804 */ 805 if (tbl->resource_type == TF_TBL_TYPE_EXT) 806 regval = TF_ACT_REC_OFFSET_2_PTR(index); 807 else 808 regval = index; 809 regval = tfp_cpu_to_be_64(regval); 810 811 if (global) { 812 /* 813 * Shared resources are never allocated through this 814 * method, so the shared flag is always false. 815 */ 816 rc = ulp_mapper_glb_resource_write(parms->mapper_data, 817 &glb_res, regval, 818 false); 819 } else { 820 rc = ulp_regfile_write(parms->regfile, 821 tbl->tbl_operand, regval); 822 } 823 if (rc) { 824 BNXT_DRV_DBG(ERR, 825 "Failed to write %s regfile[%d] rc=%d\n", 826 (global) ? "global" : "reg", 827 tbl->tbl_operand, rc); 828 goto error; 829 } 830 } 831 832 if (write) { 833 sparms.dir = tbl->direction; 834 sparms.data = ulp_blob_data_get(&data, &tmplen); 835 blob_len = ulp_blob_data_len_get(&data); 836 tbl_type = ulp_mapper_tf_dyn_tbl_type_get(parms, tbl, 837 blob_len, 838 &tmplen); 839 sparms.type = tbl_type; 840 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 841 sparms.idx = index; 842 sparms.tbl_scope_id = tbl_scope_id; 843 if (shared) 844 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, 845 tbl->session_type); 846 rc = tf_set_tbl_entry(tfp, &sparms); 847 if (rc) { 848 BNXT_DRV_DBG(ERR, 849 "Index table[%s][%s][%x] write fail rc=%d\n", 850 tf_tbl_type_2_str(sparms.type), 851 tf_dir_2_str(sparms.dir), 852 sparms.idx, rc); 853 goto error; 854 } 855 BNXT_DRV_INF("Index table[%s][%s][%x] write successful.\n", 856 tf_tbl_type_2_str(sparms.type), 857 tf_dir_2_str(sparms.dir), sparms.idx); 858 859 /* Calculate action record size */ 860 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 861 act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16; 862 act_rec_size--; 863 if (ulp_regfile_write(parms->regfile, 864 BNXT_ULP_RF_IDX_ACTION_REC_SIZE, 865 tfp_cpu_to_be_64(act_rec_size))) 866 BNXT_DRV_DBG(ERR, 867 "Failed write the act rec size\n"); 868 } 869 } 870 871 /* Link the resource to the flow in the flow db */ 872 memset(&fid_parms, 0, sizeof(fid_parms)); 873 fid_parms.direction = tbl->direction; 874 fid_parms.resource_func = tbl->resource_func; 875 fid_parms.resource_type = tbl_type; 876 fid_parms.resource_sub_type = tbl->resource_sub_type; 877 fid_parms.resource_hndl = index; 878 fid_parms.critical_resource = tbl->critical_resource; 879 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 880 881 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 882 if (rc) { 883 BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 884 rc); 885 goto error; 886 } 887 888 /* Perform the VF rep action */ 889 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 890 if (rc) { 891 BNXT_DRV_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 892 goto error; 893 } 894 return rc; 895 error: 896 /* Shared resources are not freed */ 897 if (shared) 898 return rc; 899 /* 900 * Free the allocated resource since we failed to either 901 * write to the entry or link the flow 902 */ 903 free_parms.dir = tbl->direction; 904 free_parms.type = tbl_type; 905 free_parms.idx = index; 906 free_parms.tbl_scope_id = tbl_scope_id; 907 908 trc = tf_free_tbl_entry(tfp, &free_parms); 909 if (trc) 910 BNXT_DRV_DBG(ERR, "Failed to free tbl entry on failure\n"); 911 912 return rc; 913 } 914 915 static int32_t 916 ulp_mapper_tf_cmm_tbl_process(struct bnxt_ulp_mapper_parms *parms __rte_unused, 917 struct bnxt_ulp_mapper_tbl_info *tbl __rte_unused, 918 void *error __rte_unused) 919 { 920 /* CMM does not exist in TF library*/ 921 BNXT_DRV_DBG(ERR, "Invalid resource func,CMM is not supported on TF\n"); 922 return 0; 923 } 924 925 static int32_t 926 ulp_mapper_tf_cmm_entry_free(struct bnxt_ulp_context *ulp __rte_unused, 927 struct ulp_flow_db_res_params *res __rte_unused, 928 void *error __rte_unused) 929 { 930 /* CMM does not exist in TF library*/ 931 BNXT_DRV_DBG(ERR, "Invalid resource func,CMM is not supported on TF\n"); 932 return 0; 933 } 934 935 static int32_t 936 ulp_mapper_tf_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 937 struct bnxt_ulp_mapper_tbl_info *tbl) 938 { 939 struct ulp_blob data, res_blob; 940 uint64_t idx = 0; 941 uint16_t tmplen; 942 int32_t rc = 0; 943 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; 944 struct tf_get_if_tbl_entry_parms get_parms = { 0 }; 945 struct tf *tfp; 946 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode; 947 uint32_t res_size; 948 949 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->session_type); 950 /* Initialize the blob data */ 951 if (ulp_blob_init(&data, tbl->result_bit_size, 952 parms->device_params->result_byte_order)) { 953 BNXT_DRV_DBG(ERR, "Failed initial index table blob\n"); 954 return -EINVAL; 955 } 956 957 /* create the result blob */ 958 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result"); 959 if (rc) { 960 BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 961 return rc; 962 } 963 964 /* Get the index details */ 965 switch (if_opc) { 966 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD: 967 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 968 break; 969 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE: 970 if (ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) { 971 BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n", 972 tbl->tbl_operand); 973 return -EINVAL; 974 } 975 idx = tfp_be_to_cpu_64(idx); 976 break; 977 case BNXT_ULP_IF_TBL_OPC_WR_CONST: 978 idx = tbl->tbl_operand; 979 break; 980 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD: 981 /* Initialize the result blob */ 982 if (ulp_blob_init(&res_blob, tbl->result_bit_size, 983 parms->device_params->result_byte_order)) { 984 BNXT_DRV_DBG(ERR, "Failed initial result blob\n"); 985 return -EINVAL; 986 } 987 988 /* read the interface table */ 989 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 990 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size); 991 get_parms.dir = tbl->direction; 992 get_parms.type = tbl->resource_type; 993 get_parms.idx = idx; 994 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen); 995 get_parms.data_sz_in_bytes = res_size; 996 997 rc = tf_get_if_tbl_entry(tfp, &get_parms); 998 if (rc) { 999 BNXT_DRV_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n", 1000 get_parms.type, 1001 tf_dir_2_str(get_parms.dir), 1002 get_parms.idx, rc); 1003 return rc; 1004 } 1005 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 1006 res_blob.data, 1007 res_size, 1008 res_blob.byte_order); 1009 if (rc) 1010 BNXT_DRV_DBG(ERR, "Scan and extract failed rc=%d\n", 1011 rc); 1012 return rc; 1013 case BNXT_ULP_IF_TBL_OPC_NOT_USED: 1014 return rc; /* skip it */ 1015 default: 1016 BNXT_DRV_DBG(ERR, "Invalid tbl index opcode\n"); 1017 return -EINVAL; 1018 } 1019 1020 /* Perform the tf table set by filling the set params */ 1021 iftbl_params.dir = tbl->direction; 1022 iftbl_params.type = tbl->resource_type; 1023 iftbl_params.data = ulp_blob_data_get(&data, &tmplen); 1024 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 1025 iftbl_params.idx = idx; 1026 1027 rc = tf_set_if_tbl_entry(tfp, &iftbl_params); 1028 if (rc) { 1029 BNXT_DRV_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n", 1030 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */ 1031 tf_dir_2_str(iftbl_params.dir), 1032 iftbl_params.idx, rc); 1033 return rc; 1034 } 1035 BNXT_DRV_INF("Set table[%s][%s][%x] success.\n", 1036 tf_if_tbl_2_str(iftbl_params.type), 1037 tf_dir_2_str(iftbl_params.dir), 1038 iftbl_params.idx); 1039 1040 /* 1041 * TBD: Need to look at the need to store idx in flow db for restore 1042 * the table to its original state on deletion of this entry. 1043 */ 1044 return rc; 1045 } 1046 1047 static int32_t 1048 ulp_mapper_tf_ident_alloc(struct bnxt_ulp_context *ulp_ctx, 1049 uint32_t session_type, 1050 uint16_t ident_type, 1051 uint8_t direction, 1052 enum cfa_track_type tt __rte_unused, 1053 uint64_t *identifier_id) 1054 { 1055 struct tf_alloc_identifier_parms iparms = {0}; 1056 struct tf *tfp; 1057 int32_t rc = 0; 1058 1059 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, session_type); 1060 if (!tfp) { 1061 BNXT_DRV_DBG(ERR, "Failed to get tf pointer\n"); 1062 return -EINVAL; 1063 } 1064 1065 iparms.ident_type = ident_type; 1066 iparms.dir = direction; 1067 1068 rc = tf_alloc_identifier(tfp, &iparms); 1069 if (rc) { 1070 BNXT_DRV_DBG(ERR, "Alloc ident %s:%s failed.\n", 1071 tf_dir_2_str(iparms.dir), 1072 tf_ident_2_str(iparms.ident_type)); 1073 return rc; 1074 } 1075 *identifier_id = iparms.id; 1076 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1077 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1078 BNXT_DRV_INF("Allocated Identifier [%s]:[%s] = 0x%X\n", 1079 tf_dir_2_str(iparms.dir), 1080 tf_ident_2_str(iparms.ident_type), iparms.id); 1081 #endif 1082 #endif 1083 return rc; 1084 } 1085 1086 static int32_t 1087 ulp_mapper_tf_ident_free(struct bnxt_ulp_context *ulp_ctx, 1088 struct ulp_flow_db_res_params *res) 1089 { 1090 struct tf_free_identifier_parms free_parms = { 0 }; 1091 uint32_t session_type; 1092 struct tf *tfp; 1093 int32_t rc = 0; 1094 1095 session_type = ulp_flow_db_shared_session_get(res); 1096 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, session_type); 1097 if (!tfp) { 1098 BNXT_DRV_DBG(ERR, "Failed to get tf pointer\n"); 1099 return -EINVAL; 1100 } 1101 1102 free_parms.ident_type = res->resource_type; 1103 free_parms.dir = res->direction; 1104 free_parms.id = res->resource_hndl; 1105 1106 (void)tf_free_identifier(tfp, &free_parms); 1107 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1108 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1109 BNXT_DRV_INF("Freed Identifier [%s]:[%s] = 0x%X\n", 1110 tf_dir_2_str(free_parms.dir), 1111 tf_ident_2_str(free_parms.ident_type), 1112 (uint32_t)free_parms.id); 1113 #endif 1114 #endif 1115 return rc; 1116 } 1117 1118 static inline int32_t 1119 ulp_mapper_tf_tcam_entry_free(struct bnxt_ulp_context *ulp, 1120 struct ulp_flow_db_res_params *res) 1121 { 1122 struct tf *tfp; 1123 struct tf_free_tcam_entry_parms fparms = { 1124 .dir = res->direction, 1125 .tcam_tbl_type = res->resource_type, 1126 .idx = (uint16_t)res->resource_hndl 1127 }; 1128 1129 tfp = bnxt_ulp_cntxt_tfp_get(ulp, ulp_flow_db_shared_session_get(res)); 1130 if (!tfp) { 1131 BNXT_DRV_DBG(ERR, "Unable to free resource failed to get tfp\n"); 1132 return -EINVAL; 1133 } 1134 1135 /* If HA is enabled, we may have to remap the TF Type */ 1136 if (bnxt_ulp_cntxt_ha_enabled(ulp)) { 1137 enum ulp_ha_mgr_region region; 1138 int32_t rc; 1139 1140 switch (res->resource_type) { 1141 case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH: 1142 case TF_TCAM_TBL_TYPE_WC_TCAM_LOW: 1143 rc = ulp_ha_mgr_region_get(ulp, ®ion); 1144 if (rc) 1145 /* Log this, but assume region is correct */ 1146 BNXT_DRV_DBG(ERR, 1147 "Unable to get HA region (%d)\n", 1148 rc); 1149 else 1150 fparms.tcam_tbl_type = 1151 (region == ULP_HA_REGION_LOW) ? 1152 TF_TCAM_TBL_TYPE_WC_TCAM_LOW : 1153 TF_TCAM_TBL_TYPE_WC_TCAM_HIGH; 1154 break; 1155 default: 1156 break; 1157 } 1158 } 1159 return tf_free_tcam_entry(tfp, &fparms); 1160 } 1161 1162 static int32_t 1163 ulp_mapper_clear_full_action_record(struct tf *tfp, 1164 struct bnxt_ulp_context *ulp_ctx, 1165 struct tf_free_tbl_entry_parms *fparms) 1166 { 1167 struct tf_set_tbl_entry_parms sparms = { 0 }; 1168 static uint8_t fld_zeros[16] = { 0 }; 1169 uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST; 1170 int32_t rc = 0; 1171 1172 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 1173 if (rc) { 1174 BNXT_DRV_DBG(ERR, "Unable to get the dev id from ulp.\n"); 1175 return rc; 1176 } 1177 1178 if (dev_id == BNXT_ULP_DEVICE_ID_THOR) { 1179 sparms.dir = fparms->dir; 1180 sparms.data = fld_zeros; 1181 sparms.type = fparms->type; 1182 sparms.data_sz_in_bytes = 16; /* FULL ACT REC SIZE - THOR */ 1183 sparms.idx = fparms->idx; 1184 sparms.tbl_scope_id = fparms->tbl_scope_id; 1185 rc = tf_set_tbl_entry(tfp, &sparms); 1186 if (rc) { 1187 BNXT_DRV_DBG(ERR, 1188 "Index table[%s][%s][%x] write fail %d\n", 1189 tf_tbl_type_2_str(sparms.type), 1190 tf_dir_2_str(sparms.dir), 1191 sparms.idx, rc); 1192 return rc; 1193 } 1194 } 1195 return 0; 1196 } 1197 1198 static inline int32_t 1199 ulp_mapper_tf_index_entry_free(struct bnxt_ulp_context *ulp, 1200 struct ulp_flow_db_res_params *res) 1201 { 1202 struct tf *tfp; 1203 struct tf_free_tbl_entry_parms fparms = { 1204 .dir = res->direction, 1205 .type = res->resource_type, 1206 .idx = (uint32_t)res->resource_hndl 1207 }; 1208 1209 tfp = bnxt_ulp_cntxt_tfp_get(ulp, ulp_flow_db_shared_session_get(res)); 1210 if (!tfp) { 1211 BNXT_DRV_DBG(ERR, 1212 "Unable to free resource failed to get tfp\n"); 1213 return -EINVAL; 1214 } 1215 1216 /* Get the table scope, it may be ignored */ 1217 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 1218 1219 if (fparms.type == TF_TBL_TYPE_FULL_ACT_RECORD) 1220 (void)ulp_mapper_clear_full_action_record(tfp, ulp, &fparms); 1221 1222 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1223 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1224 BNXT_DRV_INF("Free index table [%s]:[%s] = 0x%X\n", 1225 tf_dir_2_str(fparms.dir), 1226 tf_tbl_type_2_str(fparms.type), 1227 (uint32_t)fparms.idx); 1228 #endif 1229 #endif 1230 return tf_free_tbl_entry(tfp, &fparms); 1231 } 1232 1233 static int32_t 1234 ulp_mapper_tf_index_tbl_alloc_process(struct bnxt_ulp_context *ulp, 1235 uint32_t session_type, 1236 uint16_t table_type, 1237 uint8_t direction, 1238 uint64_t *index) 1239 { 1240 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 1241 struct tf *tfp; 1242 uint32_t tbl_scope_id; 1243 int32_t rc = 0; 1244 1245 tfp = bnxt_ulp_cntxt_tfp_get(ulp, session_type); 1246 if (!tfp) 1247 return -EINVAL; 1248 1249 /* Get the scope id */ 1250 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &tbl_scope_id); 1251 if (rc) { 1252 BNXT_DRV_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1253 return rc; 1254 } 1255 1256 aparms.type = table_type; 1257 aparms.dir = direction; 1258 aparms.tbl_scope_id = tbl_scope_id; 1259 1260 /* Allocate the index tbl using tf api */ 1261 rc = tf_alloc_tbl_entry(tfp, &aparms); 1262 if (rc) { 1263 BNXT_DRV_DBG(ERR, "Failed to alloc index table [%s][%d]\n", 1264 tf_dir_2_str(aparms.dir), aparms.type); 1265 return rc; 1266 } 1267 1268 *index = aparms.idx; 1269 1270 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1271 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1272 BNXT_DRV_DBG(DEBUG, "Allocated Table Index [%s][%s] = 0x%04x\n", 1273 tf_tbl_type_2_str(aparms.type), 1274 tf_dir_2_str(aparms.dir), 1275 aparms.idx); 1276 #endif 1277 #endif 1278 return rc; 1279 } 1280 1281 static int32_t 1282 ulp_mapper_tf_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 1283 struct bnxt_ulp_mapper_data *mapper_data) 1284 { 1285 struct bnxt_ulp_glb_resource_info *glb_res; 1286 uint32_t num_entries, idx, dev_id; 1287 uint8_t app_id; 1288 int32_t rc = 0; 1289 1290 glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries); 1291 /* Check if there are no resources */ 1292 if (!num_entries) 1293 return 0; 1294 1295 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 1296 if (rc) { 1297 BNXT_DRV_DBG(ERR, "Failed to get device id for glb init (%d)\n", 1298 rc); 1299 return rc; 1300 } 1301 1302 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 1303 if (rc) { 1304 BNXT_DRV_DBG(ERR, "Failed to get app id for glb init (%d)\n", 1305 rc); 1306 return rc; 1307 } 1308 1309 /* Iterate the global resources and process each one */ 1310 for (idx = 0; idx < num_entries; idx++) { 1311 if (dev_id != glb_res[idx].device_id || 1312 glb_res[idx].app_id != app_id) 1313 continue; 1314 switch (glb_res[idx].resource_func) { 1315 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 1316 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 1317 mapper_data, 1318 &glb_res[idx], 1319 true); 1320 break; 1321 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 1322 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 1323 mapper_data, 1324 &glb_res[idx], 1325 true); 1326 break; 1327 default: 1328 BNXT_DRV_DBG(ERR, "Global resource %x not supported\n", 1329 glb_res[idx].resource_func); 1330 rc = -EINVAL; 1331 break; 1332 } 1333 if (rc) 1334 return rc; 1335 } 1336 return rc; 1337 } 1338 1339 static int32_t 1340 ulp_mapper_tf_handle_to_offset(struct bnxt_ulp_mapper_parms *parms __rte_unused, 1341 uint64_t handle __rte_unused, 1342 uint32_t offset __rte_unused, 1343 uint64_t *result __rte_unused) 1344 { 1345 BNXT_DRV_DBG(ERR, "handle to offset not supported in tf\n"); 1346 return -EINVAL; 1347 } 1348 1349 static int 1350 ulp_mapper_tf_mpc_batch_start(struct tfc_mpc_batch_info_t *batch_info __rte_unused) 1351 { 1352 return 0; 1353 } 1354 1355 static int 1356 ulp_mapper_tf_mpc_batch_end(struct tfc *tfcp __rte_unused, 1357 struct tfc_mpc_batch_info_t *batch_info __rte_unused) 1358 { 1359 return 0; 1360 } 1361 1362 static bool 1363 ulp_mapper_tf_mpc_batch_started(struct tfc_mpc_batch_info_t *batch_info __rte_unused) 1364 { 1365 return false; 1366 } 1367 1368 const struct ulp_mapper_core_ops ulp_mapper_tf_core_ops = { 1369 .ulp_mapper_core_tcam_tbl_process = ulp_mapper_tf_tcam_tbl_process, 1370 .ulp_mapper_core_tcam_entry_free = ulp_mapper_tf_tcam_entry_free, 1371 .ulp_mapper_core_em_tbl_process = ulp_mapper_tf_em_tbl_process, 1372 .ulp_mapper_core_em_entry_free = ulp_mapper_tf_em_entry_free, 1373 .ulp_mapper_core_index_tbl_process = ulp_mapper_tf_index_tbl_process, 1374 .ulp_mapper_core_index_entry_free = ulp_mapper_tf_index_entry_free, 1375 .ulp_mapper_core_cmm_tbl_process = ulp_mapper_tf_cmm_tbl_process, 1376 .ulp_mapper_core_cmm_entry_free = ulp_mapper_tf_cmm_entry_free, 1377 .ulp_mapper_core_if_tbl_process = ulp_mapper_tf_if_tbl_process, 1378 .ulp_mapper_core_ident_alloc_process = ulp_mapper_tf_ident_alloc, 1379 .ulp_mapper_core_ident_free = ulp_mapper_tf_ident_free, 1380 .ulp_mapper_core_dyn_tbl_type_get = ulp_mapper_tf_dyn_tbl_type_get, 1381 .ulp_mapper_core_index_tbl_alloc_process = 1382 ulp_mapper_tf_index_tbl_alloc_process, 1383 .ulp_mapper_core_app_glb_res_info_init = 1384 ulp_mapper_tf_app_glb_resource_info_init, 1385 .ulp_mapper_core_handle_to_offset = ulp_mapper_tf_handle_to_offset, 1386 .ulp_mapper_mpc_batch_started = ulp_mapper_tf_mpc_batch_started, 1387 .ulp_mapper_mpc_batch_start = ulp_mapper_tf_mpc_batch_start, 1388 .ulp_mapper_mpc_batch_end = ulp_mapper_tf_mpc_batch_end 1389 }; 1390