1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_log.h> 7 #include <rte_malloc.h> 8 #include "bnxt.h" 9 #include "ulp_template_db_enum.h" 10 #include "ulp_template_struct.h" 11 #include "bnxt_tf_common.h" 12 #include "ulp_utils.h" 13 #include "bnxt_ulp.h" 14 #include "tfp.h" 15 #include "tf_ext_flow_handle.h" 16 #include "ulp_mark_mgr.h" 17 #include "ulp_mapper.h" 18 #include "ulp_flow_db.h" 19 #include "tf_util.h" 20 #include "ulp_template_db_tbl.h" 21 #include "ulp_port_db.h" 22 #include "ulp_ha_mgr.h" 23 #include "bnxt_tf_pmd_shim.h" 24 25 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 26 #include "ulp_template_debug_proto.h" 27 #include "ulp_tf_debug.h" 28 #endif 29 30 static uint8_t mapper_fld_zeros[16] = { 0 }; 31 32 static uint8_t mapper_fld_ones[16] = { 33 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 34 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 35 }; 36 37 static uint8_t mapper_fld_one[16] = { 38 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 39 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 40 }; 41 42 static const char * 43 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type) 44 { 45 switch (tmpl_type) { 46 case BNXT_ULP_TEMPLATE_TYPE_CLASS: 47 return "class"; 48 case BNXT_ULP_TEMPLATE_TYPE_ACTION: 49 return "action"; 50 default: 51 return "invalid template type"; 52 } 53 } 54 55 static struct bnxt_ulp_glb_resource_info * 56 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries) 57 { 58 if (!num_entries) 59 return NULL; 60 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 61 return ulp_glb_resource_tbl; 62 } 63 64 /* 65 * Read the global resource from the mapper global resource list 66 * 67 * The regval is always returned in big-endian. 68 * 69 * returns 0 on success 70 */ 71 static int32_t 72 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data, 73 enum tf_dir dir, 74 uint16_t idx, 75 uint64_t *regval, 76 bool *shared) 77 { 78 if (!mapper_data || !regval || !shared || 79 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST) 80 return -EINVAL; 81 82 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl; 83 *shared = mapper_data->glb_res_tbl[dir][idx].shared; 84 return 0; 85 } 86 87 /* 88 * Write a global resource to the mapper global resource list 89 * 90 * The regval value must be in big-endian. 91 * 92 * return 0 on success. 93 */ 94 static int32_t 95 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, 96 struct bnxt_ulp_glb_resource_info *res, 97 uint64_t regval, bool shared) 98 { 99 struct bnxt_ulp_mapper_glb_resource_entry *ent; 100 101 /* validate the arguments */ 102 if (!data || res->direction >= TF_DIR_MAX || 103 res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST) 104 return -EINVAL; 105 106 /* write to the mapper data */ 107 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index]; 108 ent->resource_func = res->resource_func; 109 ent->resource_type = res->resource_type; 110 ent->resource_hndl = regval; 111 ent->shared = shared; 112 return 0; 113 } 114 115 /* 116 * Internal function to allocate identity resource and store it in mapper data. 117 * 118 * returns 0 on success 119 */ 120 static int32_t 121 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx, 122 struct bnxt_ulp_mapper_data *mapper_data, 123 struct bnxt_ulp_glb_resource_info *glb_res) 124 { 125 struct tf_alloc_identifier_parms iparms = { 0 }; 126 struct tf_free_identifier_parms fparms; 127 uint64_t regval; 128 struct tf *tfp; 129 int32_t rc = 0; 130 131 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 132 if (!tfp) 133 return -EINVAL; 134 135 iparms.ident_type = glb_res->resource_type; 136 iparms.dir = glb_res->direction; 137 138 /* Allocate the Identifier using tf api */ 139 rc = tf_alloc_identifier(tfp, &iparms); 140 if (rc) { 141 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", 142 tf_dir_2_str(iparms.dir), 143 iparms.ident_type); 144 return rc; 145 } 146 147 /* entries are stored as big-endian format */ 148 regval = tfp_cpu_to_be_64((uint64_t)iparms.id); 149 /* 150 * write to the mapper global resource 151 * Shared resources are never allocated through this method, so the 152 * shared flag is always false. 153 */ 154 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false); 155 if (rc) { 156 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 157 /* Free the identifier when update failed */ 158 fparms.dir = iparms.dir; 159 fparms.ident_type = iparms.ident_type; 160 fparms.id = iparms.id; 161 tf_free_identifier(tfp, &fparms); 162 return rc; 163 } 164 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 165 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 166 BNXT_TF_DBG(DEBUG, "Allocated Glb Res Ident [%s][%d][%d] = 0x%04x\n", 167 tf_dir_2_str(iparms.dir), 168 glb_res->glb_regfile_index, iparms.ident_type, iparms.id); 169 #endif 170 #endif 171 return rc; 172 } 173 174 /* 175 * Internal function to allocate index tbl resource and store it in mapper data. 176 * 177 * returns 0 on success 178 */ 179 static int32_t 180 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx, 181 struct bnxt_ulp_mapper_data *mapper_data, 182 struct bnxt_ulp_glb_resource_info *glb_res) 183 { 184 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 185 struct tf_free_tbl_entry_parms free_parms = { 0 }; 186 uint64_t regval; 187 struct tf *tfp; 188 uint32_t tbl_scope_id; 189 int32_t rc = 0; 190 191 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 192 if (!tfp) 193 return -EINVAL; 194 195 /* Get the scope id */ 196 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id); 197 if (rc) { 198 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 199 return rc; 200 } 201 202 aparms.type = glb_res->resource_type; 203 aparms.dir = glb_res->direction; 204 aparms.tbl_scope_id = tbl_scope_id; 205 206 /* Allocate the index tbl using tf api */ 207 rc = tf_alloc_tbl_entry(tfp, &aparms); 208 if (rc) { 209 BNXT_TF_DBG(ERR, "Failed to alloc index table [%s][%d]\n", 210 tf_dir_2_str(aparms.dir), aparms.type); 211 return rc; 212 } 213 214 /* entries are stored as big-endian format */ 215 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx); 216 /* 217 * write to the mapper global resource 218 * Shared resources are never allocated through this method, so the 219 * shared flag is always false. 220 */ 221 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false); 222 if (rc) { 223 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 224 /* Free the identifier when update failed */ 225 free_parms.dir = aparms.dir; 226 free_parms.type = aparms.type; 227 free_parms.idx = aparms.idx; 228 tf_free_tbl_entry(tfp, &free_parms); 229 return rc; 230 } 231 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 232 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 233 BNXT_TF_DBG(DEBUG, "Allocated Glb Res Index [%s][%d][%d] = 0x%04x\n", 234 tf_dir_2_str(aparms.dir), 235 glb_res->glb_regfile_index, aparms.type, aparms.idx); 236 #endif 237 #endif 238 return rc; 239 } 240 241 static int32_t 242 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms, 243 uint32_t operand, 244 uint8_t *val) 245 { 246 uint32_t t_idx; 247 248 t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT + 249 BNXT_ULP_HDR_SIG_ID_SHIFT + 250 BNXT_ULP_GLB_FIELD_TBL_SHIFT); 251 t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT + 252 BNXT_ULP_GLB_FIELD_TBL_SHIFT); 253 t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) << 254 BNXT_ULP_GLB_FIELD_TBL_SHIFT; 255 t_idx += operand; 256 257 if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) { 258 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n", 259 parms->class_tid, t_idx, operand); 260 *val = 0; 261 return -EINVAL; /* error */ 262 } 263 *val = ulp_glb_field_tbl[t_idx]; 264 return 0; 265 } 266 267 /* 268 * Get the size of the action property for a given index. 269 * 270 * idx [in] The index for the action property 271 * 272 * returns the size of the action property. 273 */ 274 static uint32_t 275 ulp_mapper_act_prop_size_get(uint32_t idx) 276 { 277 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) 278 return 0; 279 return ulp_act_prop_map_table[idx]; 280 } 281 282 static struct bnxt_ulp_mapper_cond_info * 283 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms, 284 uint32_t tid, 285 uint32_t *num_tbls, 286 enum bnxt_ulp_cond_list_opc *opc) 287 { 288 uint32_t idx; 289 const struct bnxt_ulp_template_device_tbls *dev_tbls; 290 291 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 292 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums; 293 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode; 294 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx; 295 296 return &dev_tbls->cond_list[idx]; 297 } 298 299 static struct bnxt_ulp_mapper_cond_info * 300 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms, 301 struct bnxt_ulp_mapper_tbl_info *tbl, 302 uint32_t *num_tbls, 303 enum bnxt_ulp_cond_list_opc *opc) 304 { 305 uint32_t idx; 306 const struct bnxt_ulp_template_device_tbls *dev_tbls; 307 308 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 309 *num_tbls = tbl->execute_info.cond_nums; 310 *opc = tbl->execute_info.cond_list_opcode; 311 idx = tbl->execute_info.cond_start_idx; 312 313 return &dev_tbls->cond_list[idx]; 314 } 315 316 /* 317 * Get a list of classifier tables that implement the flow 318 * Gets a device dependent list of tables that implement the class template id 319 * 320 * mparms [in] The mappers parms with data related to the flow. 321 * 322 * tid [in] The template id that matches the flow 323 * 324 * num_tbls [out] The number of classifier tables in the returned array 325 * 326 * returns An array of classifier tables to implement the flow, or NULL on 327 * error 328 */ 329 static struct bnxt_ulp_mapper_tbl_info * 330 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms, 331 uint32_t tid, 332 uint32_t *num_tbls) 333 { 334 uint32_t idx; 335 const struct bnxt_ulp_template_device_tbls *dev_tbls; 336 337 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 338 339 idx = dev_tbls->tmpl_list[tid].start_tbl_idx; 340 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls; 341 342 return &dev_tbls->tbl_list[idx]; 343 } 344 345 /* 346 * Get the list of key fields that implement the flow. 347 * 348 * mparms [in] The mapper parms with information about the flow 349 * 350 * tbl [in] A single table instance to get the key fields from 351 * 352 * num_flds [out] The number of key fields in the returned array 353 * 354 * Returns array of Key fields, or NULL on error. 355 */ 356 static struct bnxt_ulp_mapper_key_info * 357 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms, 358 struct bnxt_ulp_mapper_tbl_info *tbl, 359 uint32_t *num_flds) 360 { 361 uint32_t idx; 362 const struct bnxt_ulp_template_device_tbls *dev_tbls; 363 364 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 365 if (!dev_tbls->key_info_list) { 366 *num_flds = 0; 367 return NULL; 368 } 369 370 idx = tbl->key_start_idx; 371 *num_flds = tbl->key_num_fields; 372 373 return &dev_tbls->key_info_list[idx]; 374 } 375 376 /* 377 * Get the list of data fields that implement the flow. 378 * 379 * mparms [in] The mapper parms with information about the flow 380 * 381 * tbl [in] A single table instance to get the data fields from 382 * 383 * num_flds [out] The number of data fields in the returned array. 384 * 385 * num_encap_flds [out] The number of encap fields in the returned array. 386 * 387 * Returns array of data fields, or NULL on error. 388 */ 389 static struct bnxt_ulp_mapper_field_info * 390 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms, 391 struct bnxt_ulp_mapper_tbl_info *tbl, 392 uint32_t *num_flds, 393 uint32_t *num_encap_flds) 394 { 395 uint32_t idx; 396 const struct bnxt_ulp_template_device_tbls *dev_tbls; 397 398 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 399 if (!dev_tbls->result_field_list) { 400 *num_flds = 0; 401 *num_encap_flds = 0; 402 return NULL; 403 } 404 405 idx = tbl->result_start_idx; 406 *num_flds = tbl->result_num_fields; 407 *num_encap_flds = tbl->encap_num_fields; 408 409 return &dev_tbls->result_field_list[idx]; 410 } 411 412 /* 413 * Get the list of ident fields that implement the flow 414 * 415 * tbl [in] A single table instance to get the ident fields from 416 * 417 * num_flds [out] The number of ident fields in the returned array 418 * 419 * returns array of ident fields, or NULL on error 420 */ 421 static struct bnxt_ulp_mapper_ident_info * 422 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms, 423 struct bnxt_ulp_mapper_tbl_info *tbl, 424 uint32_t *num_flds) 425 { 426 uint32_t idx; 427 const struct bnxt_ulp_template_device_tbls *dev_tbls; 428 429 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 430 if (!dev_tbls->ident_list) { 431 *num_flds = 0; 432 return NULL; 433 } 434 435 idx = tbl->ident_start_idx; 436 *num_flds = tbl->ident_nums; 437 438 return &dev_tbls->ident_list[idx]; 439 } 440 441 static enum tf_tbl_type 442 ulp_mapper_dyn_tbl_type_get(struct bnxt_ulp_mapper_parms *mparms, 443 struct bnxt_ulp_mapper_tbl_info *tbl, 444 struct ulp_blob *bdata, 445 uint16_t *out_len) 446 { 447 struct bnxt_ulp_device_params *d_params = mparms->device_params; 448 uint16_t blob_len = ulp_blob_data_len_get(bdata); 449 struct bnxt_ulp_dyn_size_map *size_map; 450 uint32_t i; 451 452 if (d_params->dynamic_sram_en) { 453 switch (tbl->resource_type) { 454 case TF_TBL_TYPE_ACT_ENCAP_8B: 455 case TF_TBL_TYPE_ACT_ENCAP_16B: 456 case TF_TBL_TYPE_ACT_ENCAP_32B: 457 case TF_TBL_TYPE_ACT_ENCAP_64B: 458 size_map = d_params->dyn_encap_sizes; 459 for (i = 0; i < d_params->dyn_encap_list_size; i++) { 460 if (blob_len <= size_map[i].slab_size) { 461 *out_len = size_map[i].slab_size; 462 return size_map[i].tbl_type; 463 } 464 } 465 break; 466 case TF_TBL_TYPE_ACT_MODIFY_8B: 467 case TF_TBL_TYPE_ACT_MODIFY_16B: 468 case TF_TBL_TYPE_ACT_MODIFY_32B: 469 case TF_TBL_TYPE_ACT_MODIFY_64B: 470 size_map = d_params->dyn_modify_sizes; 471 for (i = 0; i < d_params->dyn_modify_list_size; i++) { 472 if (blob_len <= size_map[i].slab_size) { 473 *out_len = size_map[i].slab_size; 474 return size_map[i].tbl_type; 475 } 476 } 477 break; 478 default: 479 break; 480 } 481 } 482 return tbl->resource_type; 483 } 484 485 static uint16_t 486 ulp_mapper_dyn_blob_size_get(struct bnxt_ulp_mapper_parms *mparms, 487 struct bnxt_ulp_mapper_tbl_info *tbl) 488 { 489 struct bnxt_ulp_device_params *d_params = mparms->device_params; 490 491 if (d_params->dynamic_sram_en) { 492 switch (tbl->resource_type) { 493 case TF_TBL_TYPE_ACT_ENCAP_8B: 494 case TF_TBL_TYPE_ACT_ENCAP_16B: 495 case TF_TBL_TYPE_ACT_ENCAP_32B: 496 case TF_TBL_TYPE_ACT_ENCAP_64B: 497 case TF_TBL_TYPE_ACT_MODIFY_8B: 498 case TF_TBL_TYPE_ACT_MODIFY_16B: 499 case TF_TBL_TYPE_ACT_MODIFY_32B: 500 case TF_TBL_TYPE_ACT_MODIFY_64B: 501 /* return max size */ 502 return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 503 default: 504 break; 505 } 506 } else if (tbl->encap_num_fields) { 507 return BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 508 } 509 return tbl->result_bit_size; 510 } 511 512 static inline int32_t 513 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp, 514 struct tf *tfp, 515 struct ulp_flow_db_res_params *res) 516 { 517 struct tf_free_tcam_entry_parms fparms = { 518 .dir = res->direction, 519 .tcam_tbl_type = res->resource_type, 520 .idx = (uint16_t)res->resource_hndl 521 }; 522 523 /* If HA is enabled, we may have to remap the TF Type */ 524 if (bnxt_ulp_cntxt_ha_enabled(ulp)) { 525 enum ulp_ha_mgr_region region; 526 int32_t rc; 527 528 switch (res->resource_type) { 529 case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH: 530 case TF_TCAM_TBL_TYPE_WC_TCAM_LOW: 531 rc = ulp_ha_mgr_region_get(ulp, ®ion); 532 if (rc) 533 /* Log this, but assume region is correct */ 534 BNXT_TF_DBG(ERR, 535 "Unable to get HA region (%d)\n", 536 rc); 537 else 538 fparms.tcam_tbl_type = 539 (region == ULP_HA_REGION_LOW) ? 540 TF_TCAM_TBL_TYPE_WC_TCAM_LOW : 541 TF_TCAM_TBL_TYPE_WC_TCAM_HIGH; 542 break; 543 default: 544 break; 545 } 546 } 547 return tf_free_tcam_entry(tfp, &fparms); 548 } 549 550 static inline int32_t 551 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp, 552 struct tf *tfp, 553 struct ulp_flow_db_res_params *res) 554 { 555 struct tf_free_tbl_entry_parms fparms = { 556 .dir = res->direction, 557 .type = res->resource_type, 558 .idx = (uint32_t)res->resource_hndl 559 }; 560 561 /* 562 * Just get the table scope, it will be ignored if not necessary 563 * by the tf_free_tbl_entry 564 */ 565 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 566 567 return tf_free_tbl_entry(tfp, &fparms); 568 } 569 570 static inline int32_t 571 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp, 572 struct tf *tfp, 573 struct ulp_flow_db_res_params *res) 574 { 575 struct tf_delete_em_entry_parms fparms = { 0 }; 576 int32_t rc; 577 578 fparms.dir = res->direction; 579 fparms.flow_handle = res->resource_hndl; 580 581 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 582 if (rc) { 583 BNXT_TF_DBG(ERR, "Failed to get table scope\n"); 584 return -EINVAL; 585 } 586 587 return tf_delete_em_entry(tfp, &fparms); 588 } 589 590 static inline int32_t 591 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused, 592 struct tf *tfp, 593 struct ulp_flow_db_res_params *res) 594 { 595 struct tf_free_identifier_parms fparms = { 596 .dir = res->direction, 597 .ident_type = res->resource_type, 598 .id = (uint16_t)res->resource_hndl 599 }; 600 601 return tf_free_identifier(tfp, &fparms); 602 } 603 604 static inline int32_t 605 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, 606 struct ulp_flow_db_res_params *res) 607 { 608 return ulp_mark_db_mark_del(ulp, 609 res->resource_type, 610 res->resource_hndl); 611 } 612 613 static inline int32_t 614 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp, 615 uint32_t parent_fid, 616 struct ulp_flow_db_res_params *res) 617 { 618 uint32_t pc_idx; 619 620 pc_idx = (uint32_t)res->resource_hndl; 621 622 /* reset the child flow bitset*/ 623 if (ulp_flow_db_pc_db_parent_flow_set(ulp, pc_idx, parent_fid, 0)) { 624 BNXT_TF_DBG(ERR, "error in reset parent flow bitset %x:%x\n", 625 pc_idx, parent_fid); 626 return -EINVAL; 627 } 628 return 0; 629 } 630 631 static inline int32_t 632 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp, 633 uint32_t child_fid, 634 struct ulp_flow_db_res_params *res) 635 { 636 uint32_t pc_idx; 637 638 pc_idx = (uint32_t)res->resource_hndl; 639 640 /* reset the child flow bitset*/ 641 if (ulp_flow_db_pc_db_child_flow_set(ulp, pc_idx, child_fid, 0)) { 642 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n", 643 pc_idx, child_fid); 644 return -EINVAL; 645 } 646 return 0; 647 } 648 649 /* 650 * Process the flow database opcode alloc action. 651 * returns 0 on success 652 */ 653 static int32_t 654 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms, 655 struct bnxt_ulp_mapper_tbl_info *tbl) 656 { 657 uint32_t rid = 0; 658 uint64_t val64; 659 int32_t rc = 0; 660 661 /* allocate a new fid */ 662 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx, 663 BNXT_ULP_FDB_TYPE_RID, 664 0, &rid); 665 if (rc) { 666 BNXT_TF_DBG(ERR, 667 "Unable to allocate flow table entry\n"); 668 return -EINVAL; 669 } 670 /* Store the allocated fid in regfile*/ 671 val64 = rid; 672 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand, 673 tfp_cpu_to_be_64(val64)); 674 if (rc) { 675 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 676 tbl->fdb_operand); 677 ulp_flow_db_fid_free(parms->ulp_ctx, 678 BNXT_ULP_FDB_TYPE_RID, rid); 679 return -EINVAL; 680 } 681 return 0; 682 } 683 684 /* 685 * Process the flow database opcode action. 686 * returns 0 on success. 687 */ 688 static int32_t 689 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms, 690 struct bnxt_ulp_mapper_tbl_info *tbl, 691 struct ulp_flow_db_res_params *fid_parms) 692 { 693 uint32_t push_fid; 694 uint64_t val64; 695 enum bnxt_ulp_fdb_type flow_type; 696 int32_t rc = 0; 697 698 switch (tbl->fdb_opcode) { 699 case BNXT_ULP_FDB_OPC_PUSH_FID: 700 push_fid = parms->fid; 701 flow_type = parms->flow_type; 702 break; 703 case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE: 704 /* get the fid from the regfile */ 705 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand, 706 &val64); 707 if (!rc) { 708 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 709 tbl->fdb_operand); 710 return -EINVAL; 711 } 712 /* Use the extracted fid to update the flow resource */ 713 push_fid = (uint32_t)tfp_be_to_cpu_64(val64); 714 flow_type = BNXT_ULP_FDB_TYPE_RID; 715 break; 716 default: 717 return rc; /* Nothing to be done */ 718 } 719 720 /* Add the resource to the flow database */ 721 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type, 722 push_fid, fid_parms); 723 if (rc) 724 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n", 725 push_fid, rc); 726 return rc; 727 } 728 729 /* 730 * Process the flow database opcode action. 731 * returns 0 on success. 732 */ 733 static int32_t 734 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms, 735 struct bnxt_ulp_mapper_tbl_info *tbl, 736 uint32_t *priority) 737 { 738 int32_t rc = 0; 739 740 switch (tbl->pri_opcode) { 741 case BNXT_ULP_PRI_OPC_NOT_USED: 742 *priority = 0; 743 break; 744 case BNXT_ULP_PRI_OPC_CONST: 745 *priority = tbl->pri_operand; 746 break; 747 case BNXT_ULP_PRI_OPC_APP_PRI: 748 *priority = parms->app_priority; 749 break; 750 default: 751 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n", 752 tbl->pri_opcode); 753 rc = -EINVAL; 754 break; 755 } 756 return rc; 757 } 758 759 /* 760 * Process the identifier list in the given table. 761 * Extract the ident from the table entry and 762 * write it to the reg file. 763 * returns 0 on success. 764 */ 765 static int32_t 766 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms, 767 struct bnxt_ulp_mapper_tbl_info *tbl, 768 uint8_t *byte_data, 769 uint32_t byte_data_size, 770 enum bnxt_ulp_byte_order byte_order) 771 { 772 struct bnxt_ulp_mapper_ident_info *idents; 773 uint32_t i, num_idents = 0; 774 uint64_t val64; 775 776 /* validate the null arguments */ 777 if (!byte_data) { 778 BNXT_TF_DBG(ERR, "invalid argument\n"); 779 return -EINVAL; 780 } 781 782 /* Get the ident list and process each one */ 783 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 784 785 for (i = 0; i < num_idents; i++) { 786 /* check the size of the buffer for validation */ 787 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) > 788 ULP_BYTE_2_BITS(byte_data_size) || 789 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) { 790 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n", 791 idents[i].ident_bit_pos, 792 idents[i].ident_bit_size, 793 byte_data_size); 794 return -EINVAL; 795 } 796 val64 = 0; 797 if (byte_order == BNXT_ULP_BYTE_ORDER_LE) 798 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64, 799 sizeof(val64), 800 idents[i].ident_bit_pos, 801 idents[i].ident_bit_size); 802 else 803 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64, 804 idents[i].ident_bit_pos, 805 idents[i].ident_bit_size); 806 807 /* Write it to the regfile, val64 is already in big-endian*/ 808 if (ulp_regfile_write(parms->regfile, 809 idents[i].regfile_idx, val64)) { 810 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", 811 idents[i].regfile_idx); 812 return -EINVAL; 813 } 814 } 815 return 0; 816 } 817 818 /* 819 * Process the identifier instruction and either store it in the flow database 820 * or return it in the val (if not NULL) on success. If val is NULL, the 821 * identifier is to be stored in the flow database. 822 */ 823 static int32_t 824 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, 825 struct bnxt_ulp_mapper_tbl_info *tbl, 826 struct bnxt_ulp_mapper_ident_info *ident, 827 uint16_t *val) 828 { 829 struct ulp_flow_db_res_params fid_parms; 830 uint64_t id = 0; 831 int32_t idx; 832 struct tf_alloc_identifier_parms iparms = { 0 }; 833 struct tf_free_identifier_parms free_parms = { 0 }; 834 struct tf *tfp; 835 int rc; 836 837 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 838 if (!tfp) { 839 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 840 return -EINVAL; 841 } 842 843 idx = ident->regfile_idx; 844 845 iparms.ident_type = ident->ident_type; 846 iparms.dir = tbl->direction; 847 848 rc = tf_alloc_identifier(tfp, &iparms); 849 if (rc) { 850 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n", 851 tf_dir_2_str(iparms.dir), 852 tf_ident_2_str(iparms.ident_type)); 853 return rc; 854 } 855 BNXT_TF_INF("Alloc ident %s:%s.success.\n", 856 tf_dir_2_str(iparms.dir), 857 tf_ident_2_str(iparms.ident_type)); 858 859 id = (uint64_t)tfp_cpu_to_be_64(iparms.id); 860 if (ulp_regfile_write(parms->regfile, idx, id)) { 861 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 862 rc = -EINVAL; 863 /* Need to free the identifier, so goto error */ 864 goto error; 865 } 866 867 /* Link the resource to the flow in the flow db */ 868 if (!val) { 869 memset(&fid_parms, 0, sizeof(fid_parms)); 870 fid_parms.direction = tbl->direction; 871 fid_parms.resource_func = ident->resource_func; 872 fid_parms.resource_type = ident->ident_type; 873 fid_parms.resource_hndl = iparms.id; 874 fid_parms.critical_resource = tbl->critical_resource; 875 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 876 877 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 878 if (rc) { 879 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 880 rc); 881 /* Need to free the identifier, so goto error */ 882 goto error; 883 } 884 } else { 885 *val = iparms.id; 886 } 887 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 888 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 889 ulp_mapper_ident_field_dump("Ident", ident, tbl, iparms.id); 890 #endif 891 #endif 892 return 0; 893 894 error: 895 /* Need to free the identifier */ 896 free_parms.dir = tbl->direction; 897 free_parms.ident_type = ident->ident_type; 898 free_parms.id = iparms.id; 899 900 (void)tf_free_identifier(tfp, &free_parms); 901 902 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n", 903 ident->description, 904 tf_dir_2_str(tbl->direction)); 905 return rc; 906 } 907 908 /* 909 * Process the identifier instruction and extract it from result blob. 910 * Increment the identifier reference count and store it in the flow database. 911 */ 912 static int32_t 913 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms, 914 struct bnxt_ulp_mapper_tbl_info *tbl, 915 struct bnxt_ulp_mapper_ident_info *ident, 916 struct ulp_blob *res_blob) 917 { 918 struct ulp_flow_db_res_params fid_parms; 919 uint64_t id = 0; 920 uint32_t idx = 0; 921 struct tf_search_identifier_parms sparms = { 0 }; 922 struct tf_free_identifier_parms free_parms = { 0 }; 923 struct tf *tfp; 924 int rc; 925 926 /* Get the tfp from ulp context */ 927 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 928 if (!tfp) { 929 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 930 return -EINVAL; 931 } 932 933 /* Extract the index from the result blob */ 934 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx), 935 ident->ident_bit_pos, ident->ident_bit_size); 936 if (rc) { 937 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n"); 938 return -EIO; 939 } 940 941 /* populate the search params and search identifier shadow table */ 942 sparms.ident_type = ident->ident_type; 943 sparms.dir = tbl->direction; 944 /* convert the idx into cpu format */ 945 sparms.search_id = tfp_be_to_cpu_32(idx); 946 947 /* Search identifier also increase the reference count */ 948 rc = tf_search_identifier(tfp, &sparms); 949 if (rc) { 950 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n", 951 tf_dir_2_str(sparms.dir), 952 tf_ident_2_str(sparms.ident_type), 953 sparms.search_id); 954 return rc; 955 } 956 BNXT_TF_INF("Search ident %s:%s:%x.success.\n", 957 tf_dir_2_str(sparms.dir), 958 tf_tbl_type_2_str(sparms.ident_type), 959 sparms.search_id); 960 961 /* Write it to the regfile */ 962 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id); 963 if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) { 964 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 965 rc = -EINVAL; 966 /* Need to free the identifier, so goto error */ 967 goto error; 968 } 969 970 /* Link the resource to the flow in the flow db */ 971 memset(&fid_parms, 0, sizeof(fid_parms)); 972 fid_parms.direction = tbl->direction; 973 fid_parms.resource_func = ident->resource_func; 974 fid_parms.resource_type = ident->ident_type; 975 fid_parms.resource_hndl = sparms.search_id; 976 fid_parms.critical_resource = tbl->critical_resource; 977 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 978 979 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 980 if (rc) { 981 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 982 rc); 983 /* Need to free the identifier, so goto error */ 984 goto error; 985 } 986 987 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 988 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 989 ulp_mapper_ident_field_dump("Ident", ident, tbl, sparms.search_id); 990 #endif 991 #endif 992 return 0; 993 994 error: 995 /* Need to free the identifier */ 996 free_parms.dir = tbl->direction; 997 free_parms.ident_type = ident->ident_type; 998 free_parms.id = sparms.search_id; 999 (void)tf_free_identifier(tfp, &free_parms); 1000 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n", 1001 ident->description, 1002 tf_dir_2_str(tbl->direction), sparms.search_id); 1003 return rc; 1004 } 1005 1006 static int32_t 1007 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms, 1008 uint32_t port_id, 1009 uint16_t val16, 1010 uint8_t **val) 1011 { 1012 enum bnxt_ulp_port_table port_data = val16; 1013 1014 switch (port_data) { 1015 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC: 1016 if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id, 1017 val)) { 1018 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); 1019 return -EINVAL; 1020 } 1021 break; 1022 case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC: 1023 if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id, 1024 val)) { 1025 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); 1026 return -EINVAL; 1027 } 1028 break; 1029 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC: 1030 if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id, 1031 val)) { 1032 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); 1033 return -EINVAL; 1034 } 1035 break; 1036 default: 1037 BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data); 1038 return -EINVAL; 1039 } 1040 return 0; 1041 } 1042 1043 static int32_t 1044 ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms, 1045 enum bnxt_ulp_field_src field_src, 1046 uint8_t *field_opr, 1047 enum tf_dir dir, 1048 uint8_t is_key, 1049 uint32_t bitlen, 1050 uint8_t **val, 1051 uint32_t *val_len, 1052 uint64_t *value) 1053 { 1054 struct bnxt_ulp_mapper_data *m; 1055 uint8_t bit; 1056 uint32_t port_id, val_size, field_size; 1057 uint16_t idx, size_idx, offset; 1058 uint32_t bytelen = ULP_BITS_2_BYTE(bitlen); 1059 uint8_t *buffer; 1060 uint64_t lregval; 1061 bool shared; 1062 1063 *val_len = bitlen; 1064 *value = 0; 1065 /* Perform the action */ 1066 switch (field_src) { 1067 case BNXT_ULP_FIELD_SRC_ZERO: 1068 *val = mapper_fld_zeros; 1069 break; 1070 case BNXT_ULP_FIELD_SRC_CONST: 1071 *val = field_opr; 1072 break; 1073 case BNXT_ULP_FIELD_SRC_ONES: 1074 *val = mapper_fld_ones; 1075 *value = 1; 1076 break; 1077 case BNXT_ULP_FIELD_SRC_CF: 1078 if (!ulp_operand_read(field_opr, 1079 (uint8_t *)&idx, sizeof(uint16_t))) { 1080 BNXT_TF_DBG(ERR, "CF operand read failed\n"); 1081 return -EINVAL; 1082 } 1083 idx = tfp_be_to_cpu_16(idx); 1084 if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) { 1085 BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx, 1086 bytelen); 1087 return -EINVAL; 1088 } 1089 buffer = (uint8_t *)&parms->comp_fld[idx]; 1090 *val = &buffer[sizeof(uint64_t) - bytelen]; 1091 *value = ULP_COMP_FLD_IDX_RD(parms, idx); 1092 break; 1093 case BNXT_ULP_FIELD_SRC_RF: 1094 if (!ulp_operand_read(field_opr, 1095 (uint8_t *)&idx, sizeof(uint16_t))) { 1096 BNXT_TF_DBG(ERR, "RF operand read failed\n"); 1097 return -EINVAL; 1098 } 1099 1100 idx = tfp_be_to_cpu_16(idx); 1101 /* Uninitialized regfile entries return 0 */ 1102 if (!ulp_regfile_read(parms->regfile, idx, &lregval) || 1103 sizeof(uint64_t) < bytelen) { 1104 BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx, 1105 bytelen); 1106 return -EINVAL; 1107 } 1108 buffer = (uint8_t *)&parms->regfile->entry[idx].data; 1109 *val = &buffer[sizeof(uint64_t) - bytelen]; 1110 *value = tfp_be_to_cpu_64(lregval); 1111 break; 1112 case BNXT_ULP_FIELD_SRC_ACT_PROP: 1113 if (!ulp_operand_read(field_opr, 1114 (uint8_t *)&idx, sizeof(uint16_t))) { 1115 BNXT_TF_DBG(ERR, "Action operand read failed\n"); 1116 return -EINVAL; 1117 } 1118 idx = tfp_be_to_cpu_16(idx); 1119 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1120 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx); 1121 return -EINVAL; 1122 } 1123 buffer = &parms->act_prop->act_details[idx]; 1124 field_size = ulp_mapper_act_prop_size_get(idx); 1125 if (bytelen > field_size) { 1126 BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n", 1127 idx, field_size); 1128 return -EINVAL; 1129 } 1130 *val = &buffer[field_size - bytelen]; 1131 break; 1132 case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ: 1133 if (!ulp_operand_read(field_opr, 1134 (uint8_t *)&idx, sizeof(uint16_t))) { 1135 BNXT_TF_DBG(ERR, "Action sz operand read failed\n"); 1136 return -EINVAL; 1137 } 1138 idx = tfp_be_to_cpu_16(idx); 1139 1140 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1141 BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx); 1142 return -EINVAL; 1143 } 1144 *val = &parms->act_prop->act_details[idx]; 1145 1146 /* get the size index next */ 1147 if (!ulp_operand_read(&field_opr[sizeof(uint16_t)], 1148 (uint8_t *)&size_idx, sizeof(uint16_t))) { 1149 BNXT_TF_DBG(ERR, "Action sz operand read failed\n"); 1150 return -EINVAL; 1151 } 1152 size_idx = tfp_be_to_cpu_16(size_idx); 1153 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1154 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx); 1155 return -EINVAL; 1156 } 1157 memcpy(&val_size, &parms->act_prop->act_details[size_idx], 1158 sizeof(uint32_t)); 1159 val_size = tfp_be_to_cpu_32(val_size); 1160 *val_len = ULP_BYTE_2_BITS(val_size); 1161 break; 1162 case BNXT_ULP_FIELD_SRC_GLB_RF: 1163 if (!ulp_operand_read(field_opr, 1164 (uint8_t *)&idx, sizeof(uint16_t))) { 1165 BNXT_TF_DBG(ERR, "Global regfile read failed\n"); 1166 return -EINVAL; 1167 } 1168 idx = tfp_be_to_cpu_16(idx); 1169 if (ulp_mapper_glb_resource_read(parms->mapper_data, 1170 dir, idx, &lregval, &shared) || 1171 sizeof(uint64_t) < bytelen) { 1172 BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n", 1173 idx, bytelen); 1174 return -EINVAL; 1175 } 1176 m = parms->mapper_data; 1177 buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl; 1178 *val = &buffer[sizeof(uint64_t) - bytelen]; 1179 *value = tfp_be_to_cpu_64(lregval); 1180 break; 1181 case BNXT_ULP_FIELD_SRC_HF: 1182 case BNXT_ULP_FIELD_SRC_SUB_HF: 1183 if (!ulp_operand_read(field_opr, 1184 (uint8_t *)&idx, sizeof(uint16_t))) { 1185 BNXT_TF_DBG(ERR, "Header field read failed\n"); 1186 return -EINVAL; 1187 } 1188 idx = tfp_be_to_cpu_16(idx); 1189 /* get the index from the global field list */ 1190 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) { 1191 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 1192 idx); 1193 return -EINVAL; 1194 } 1195 if (is_key) 1196 buffer = parms->hdr_field[bit].spec; 1197 else 1198 buffer = parms->hdr_field[bit].mask; 1199 1200 field_size = parms->hdr_field[bit].size; 1201 if (bytelen > field_size) { 1202 BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n", 1203 bit, field_size); 1204 return -EINVAL; 1205 } 1206 if (field_src == BNXT_ULP_FIELD_SRC_HF) { 1207 *val = &buffer[field_size - bytelen]; 1208 } else { 1209 /* get the offset next */ 1210 if (!ulp_operand_read(&field_opr[sizeof(uint16_t)], 1211 (uint8_t *)&offset, 1212 sizeof(uint16_t))) { 1213 BNXT_TF_DBG(ERR, "Hdr fld size read failed\n"); 1214 return -EINVAL; 1215 } 1216 offset = tfp_be_to_cpu_16(offset); 1217 offset = ULP_BITS_2_BYTE_NR(offset); 1218 if ((offset + bytelen) > field_size) { 1219 BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit); 1220 return -EINVAL; 1221 } 1222 *val = &buffer[offset]; 1223 } 1224 break; 1225 case BNXT_ULP_FIELD_SRC_HDR_BIT: 1226 if (!ulp_operand_read(field_opr, 1227 (uint8_t *)&lregval, sizeof(uint64_t))) { 1228 BNXT_TF_DBG(ERR, "Header bit read failed\n"); 1229 return -EINVAL; 1230 } 1231 lregval = tfp_be_to_cpu_64(lregval); 1232 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) { 1233 *val = mapper_fld_one; 1234 *value = 1; 1235 } else { 1236 *val = mapper_fld_zeros; 1237 } 1238 break; 1239 case BNXT_ULP_FIELD_SRC_ACT_BIT: 1240 if (!ulp_operand_read(field_opr, 1241 (uint8_t *)&lregval, sizeof(uint64_t))) { 1242 BNXT_TF_DBG(ERR, "Action bit read failed\n"); 1243 return -EINVAL; 1244 } 1245 lregval = tfp_be_to_cpu_64(lregval); 1246 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) { 1247 *val = mapper_fld_one; 1248 *value = 1; 1249 } else { 1250 *val = mapper_fld_zeros; 1251 } 1252 break; 1253 case BNXT_ULP_FIELD_SRC_FIELD_BIT: 1254 if (!ulp_operand_read(field_opr, 1255 (uint8_t *)&idx, sizeof(uint16_t))) { 1256 BNXT_TF_DBG(ERR, "Field bit read failed\n"); 1257 return -EINVAL; 1258 } 1259 idx = tfp_be_to_cpu_16(idx); 1260 /* get the index from the global field list */ 1261 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) { 1262 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 1263 idx); 1264 return -EINVAL; 1265 } 1266 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) { 1267 *val = mapper_fld_one; 1268 *value = 1; 1269 } else { 1270 *val = mapper_fld_zeros; 1271 } 1272 break; 1273 case BNXT_ULP_FIELD_SRC_PORT_TABLE: 1274 /* The port id is present in the comp field list */ 1275 port_id = ULP_COMP_FLD_IDX_RD(parms, 1276 BNXT_ULP_CF_IDX_DEV_PORT_ID); 1277 /* get the port table enum */ 1278 if (!ulp_operand_read(field_opr, 1279 (uint8_t *)&idx, sizeof(uint16_t))) { 1280 BNXT_TF_DBG(ERR, "Port table enum read failed\n"); 1281 return -EINVAL; 1282 } 1283 idx = tfp_be_to_cpu_16(idx); 1284 if (ulp_mapper_field_port_db_process(parms, port_id, idx, 1285 val)) { 1286 BNXT_TF_DBG(ERR, "field port table failed\n"); 1287 return -EINVAL; 1288 } 1289 break; 1290 case BNXT_ULP_FIELD_SRC_ENC_HDR_BIT: 1291 if (!ulp_operand_read(field_opr, 1292 (uint8_t *)&lregval, sizeof(uint64_t))) { 1293 BNXT_TF_DBG(ERR, "Header bit read failed\n"); 1294 return -EINVAL; 1295 } 1296 lregval = tfp_be_to_cpu_64(lregval); 1297 if (ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, lregval)) { 1298 *val = mapper_fld_one; 1299 *value = 1; 1300 } else { 1301 *val = mapper_fld_zeros; 1302 } 1303 break; 1304 case BNXT_ULP_FIELD_SRC_ENC_FIELD: 1305 if (!ulp_operand_read(field_opr, 1306 (uint8_t *)&idx, sizeof(uint16_t))) { 1307 BNXT_TF_DBG(ERR, "Header field read failed\n"); 1308 return -EINVAL; 1309 } 1310 idx = tfp_be_to_cpu_16(idx); 1311 /* get the index from the global field list */ 1312 if (idx >= BNXT_ULP_ENC_FIELD_LAST) { 1313 BNXT_TF_DBG(ERR, "invalid encap field tbl idx %d\n", 1314 idx); 1315 return -EINVAL; 1316 } 1317 buffer = parms->enc_field[idx].spec; 1318 field_size = parms->enc_field[idx].size; 1319 if (bytelen > field_size) { 1320 BNXT_TF_DBG(ERR, "Encap field[%d] size small %u\n", 1321 idx, field_size); 1322 return -EINVAL; 1323 } 1324 *val = &buffer[field_size - bytelen]; 1325 break; 1326 case BNXT_ULP_FIELD_SRC_SKIP: 1327 /* do nothing */ 1328 *val = mapper_fld_zeros; 1329 *val_len = 0; 1330 break; 1331 case BNXT_ULP_FIELD_SRC_REJECT: 1332 return -EINVAL; 1333 default: 1334 BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src); 1335 return -EINVAL; 1336 } 1337 return 0; 1338 } 1339 1340 static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen, 1341 uint64_t *output) 1342 { 1343 uint16_t val_16; 1344 uint32_t val_32; 1345 uint64_t val_64; 1346 uint32_t bytelen; 1347 1348 bytelen = ULP_BITS_2_BYTE(bitlen); 1349 if (bytelen == sizeof(uint8_t)) { 1350 *output = *((uint8_t *)buffer); 1351 } else if (bytelen == sizeof(uint16_t)) { 1352 val_16 = *((uint16_t *)buffer); 1353 *output = tfp_be_to_cpu_16(val_16); 1354 } else if (bytelen == sizeof(uint32_t)) { 1355 val_32 = *((uint32_t *)buffer); 1356 *output = tfp_be_to_cpu_32(val_32); 1357 } else if (bytelen == sizeof(val_64)) { 1358 val_64 = *((uint64_t *)buffer); 1359 *output = tfp_be_to_cpu_64(val_64); 1360 } else { 1361 *output = 0; 1362 return -EINVAL; 1363 } 1364 return 0; 1365 } 1366 1367 static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src, 1368 struct ulp_blob *blob, 1369 uint8_t *val, 1370 uint32_t val_len, 1371 uint8_t **out_val) 1372 { 1373 if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) { 1374 if (ulp_blob_pad_push(blob, val_len) < 0) { 1375 BNXT_TF_DBG(ERR, "too large for blob\n"); 1376 return -EINVAL; 1377 } 1378 } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) { 1379 if (ulp_blob_push_encap(blob, val, val_len) < 0) { 1380 BNXT_TF_DBG(ERR, "encap blob push failed\n"); 1381 return -EINVAL; 1382 } 1383 } else if (fld_src == BNXT_ULP_FIELD_SRC_SKIP) { 1384 /* do nothing */ 1385 } else { 1386 if (!ulp_blob_push(blob, val, val_len)) { 1387 BNXT_TF_DBG(ERR, "push of val1 failed\n"); 1388 return -EINVAL; 1389 } 1390 } 1391 *out_val = val; 1392 return 0; 1393 } 1394 1395 static int32_t 1396 ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms, 1397 enum tf_dir dir, 1398 struct bnxt_ulp_mapper_field_info *fld, 1399 struct ulp_blob *blob, 1400 uint8_t is_key, 1401 const char *name) 1402 { 1403 uint16_t write_idx = blob->write_idx; 1404 uint8_t *val = NULL, *val1, *val2, *val3; 1405 uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0; 1406 uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0; 1407 uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0; 1408 uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0; 1409 uint64_t value1 = 0, value2 = 0, value3 = 0; 1410 int32_t rc = 0; 1411 1412 /* prepare the field source and values */ 1413 switch (fld->field_opc) { 1414 case BNXT_ULP_FIELD_OPC_SRC1: 1415 process_src1 = 1; 1416 break; 1417 case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: 1418 process_src1 = 1; 1419 break; 1420 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: 1421 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: 1422 process_src3 = 1; 1423 eval_src3 = 1; 1424 process_src1 = 1; 1425 process_src2 = 1; 1426 eval_src1 = 1; 1427 eval_src2 = 1; 1428 break; 1429 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: 1430 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: 1431 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: 1432 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: 1433 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: 1434 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: 1435 process_src1 = 1; 1436 process_src2 = 1; 1437 eval_src1 = 1; 1438 eval_src2 = 1; 1439 break; 1440 default: 1441 break; 1442 } 1443 1444 /* process the src1 opcode */ 1445 if (process_src1) { 1446 if (ulp_mapper_field_src_process(parms, fld->field_src1, 1447 fld->field_opr1, dir, is_key, 1448 fld->field_bit_size, &val1, 1449 &val1_len, &value1)) { 1450 BNXT_TF_DBG(ERR, "fld src1 process failed\n"); 1451 goto error; 1452 } 1453 if (eval_src1) { 1454 if (ulp_mapper_field_buffer_eval(val1, val1_len, 1455 &val1_int)) { 1456 BNXT_TF_DBG(ERR, "fld src1 eval failed\n"); 1457 goto error; 1458 } 1459 } 1460 } 1461 1462 /* for "if then clause" set the correct process */ 1463 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) { 1464 if (value1) 1465 process_src2 = 1; 1466 else 1467 process_src3 = 1; 1468 } 1469 1470 /* process src2 opcode */ 1471 if (process_src2) { 1472 if (ulp_mapper_field_src_process(parms, fld->field_src2, 1473 fld->field_opr2, dir, is_key, 1474 fld->field_bit_size, &val2, 1475 &val2_len, &value2)) { 1476 BNXT_TF_DBG(ERR, "fld src2 process failed\n"); 1477 goto error; 1478 } 1479 if (eval_src2) { 1480 if (ulp_mapper_field_buffer_eval(val2, val2_len, 1481 &val2_int)) { 1482 BNXT_TF_DBG(ERR, "fld src2 eval failed\n"); 1483 goto error; 1484 } 1485 } 1486 } 1487 1488 /* process src3 opcode */ 1489 if (process_src3) { 1490 if (ulp_mapper_field_src_process(parms, fld->field_src3, 1491 fld->field_opr3, dir, is_key, 1492 fld->field_bit_size, &val3, 1493 &val3_len, &value3)) { 1494 BNXT_TF_DBG(ERR, "fld src3 process failed\n"); 1495 goto error; 1496 } 1497 if (eval_src3) { 1498 if (ulp_mapper_field_buffer_eval(val3, val3_len, 1499 &val3_int)) { 1500 BNXT_TF_DBG(ERR, "fld src3 eval failed\n"); 1501 goto error; 1502 } 1503 } 1504 } 1505 1506 val_len = fld->field_bit_size; 1507 /* process the field opcodes */ 1508 switch (fld->field_opc) { 1509 case BNXT_ULP_FIELD_OPC_SRC1: 1510 rc = ulp_mapper_field_blob_write(fld->field_src1, 1511 blob, val1, val1_len, &val); 1512 val_len = val1_len; 1513 break; 1514 case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: 1515 if (value1) { 1516 rc = ulp_mapper_field_blob_write(fld->field_src2, blob, 1517 val2, val2_len, &val); 1518 val_len = val2_len; 1519 } else { 1520 rc = ulp_mapper_field_blob_write(fld->field_src3, blob, 1521 val3, val3_len, &val); 1522 val_len = val3_len; 1523 } 1524 break; 1525 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: 1526 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: 1527 val_int = val1_int + val2_int; 1528 val_int = tfp_cpu_to_be_64(val_int); 1529 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1530 if (!val) 1531 rc = -EINVAL; 1532 break; 1533 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: 1534 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: 1535 val_int = val1_int - val2_int; 1536 val_int = tfp_cpu_to_be_64(val_int); 1537 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1538 if (!val) 1539 rc = -EINVAL; 1540 break; 1541 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: 1542 val_int = val1_int | val2_int; 1543 val_int = tfp_cpu_to_be_64(val_int); 1544 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1545 if (!val) 1546 rc = -EINVAL; 1547 break; 1548 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: 1549 val_int = val1_int | val2_int | val3_int; 1550 val_int = tfp_cpu_to_be_64(val_int); 1551 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1552 if (!val) 1553 rc = -EINVAL; 1554 break; 1555 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: 1556 val_int = val1_int & val2_int; 1557 val_int = tfp_cpu_to_be_64(val_int); 1558 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1559 if (!val) 1560 rc = -EINVAL; 1561 break; 1562 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: 1563 val_int = val1_int & (val2_int | val3_int); 1564 val_int = tfp_cpu_to_be_64(val_int); 1565 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1566 if (!val) 1567 rc = -EINVAL; 1568 break; 1569 case BNXT_ULP_FIELD_OPC_SKIP: 1570 break; 1571 default: 1572 BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc); 1573 rc = -EINVAL; 1574 break; 1575 } 1576 1577 if (!rc) { 1578 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1579 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1580 if (fld->field_src1 != BNXT_ULP_FIELD_SRC_ZERO && val_len) 1581 ulp_mapper_field_dump(name, fld, blob, write_idx, val, 1582 val_len); 1583 #endif 1584 #endif 1585 return rc; 1586 } 1587 error: 1588 BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name, 1589 fld->description, (val) ? write_idx : 0, val_len); 1590 return -EINVAL; 1591 } 1592 1593 /* 1594 * Result table process and fill the result blob. 1595 * data [out] - the result blob data 1596 */ 1597 static int32_t 1598 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms, 1599 struct bnxt_ulp_mapper_tbl_info *tbl, 1600 struct ulp_blob *data, 1601 const char *name) 1602 { 1603 struct bnxt_ulp_mapper_field_info *dflds; 1604 uint32_t i = 0, num_flds = 0, encap_flds = 0; 1605 struct ulp_blob encap_blob; 1606 int32_t rc = 0; 1607 1608 /* Get the result field list */ 1609 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, 1610 &encap_flds); 1611 1612 /* validate the result field list counts */ 1613 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && 1614 (!num_flds && !encap_flds)) || !dflds || 1615 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && 1616 (!num_flds || encap_flds))) { 1617 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n", 1618 num_flds, encap_flds); 1619 return -EINVAL; 1620 } 1621 1622 /* process the result fields */ 1623 for (i = 0; i < num_flds; i++) { 1624 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 1625 &dflds[i], data, 0, name); 1626 if (rc) { 1627 BNXT_TF_DBG(ERR, "result field processing failed\n"); 1628 return rc; 1629 } 1630 } 1631 1632 /* process encap fields if any */ 1633 if (encap_flds) { 1634 uint32_t pad = 0; 1635 /* Initialize the encap blob */ 1636 if (!tbl->record_size && 1637 !parms->device_params->dynamic_sram_en) { 1638 BNXT_TF_DBG(ERR, "Encap tbl record size incorrect\n"); 1639 return -EINVAL; 1640 } 1641 if (!ulp_blob_init(&encap_blob, 1642 ULP_BYTE_2_BITS(tbl->record_size), 1643 parms->device_params->encap_byte_order)) { 1644 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1645 return -EINVAL; 1646 } 1647 for (; i < encap_flds; i++) { 1648 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 1649 &dflds[i], 1650 &encap_blob, 0, name); 1651 if (rc) { 1652 BNXT_TF_DBG(ERR, 1653 "encap field processing failed\n"); 1654 return rc; 1655 } 1656 } 1657 /* add the dynamic pad push */ 1658 if (parms->device_params->dynamic_sram_en) { 1659 uint16_t rec_s = ULP_BYTE_2_BITS(tbl->record_size); 1660 1661 (void)ulp_mapper_dyn_tbl_type_get(parms, tbl, 1662 &encap_blob, &rec_s); 1663 pad = rec_s - ulp_blob_data_len_get(&encap_blob); 1664 } else { 1665 pad = ULP_BYTE_2_BITS(tbl->record_size) - 1666 ulp_blob_data_len_get(&encap_blob); 1667 } 1668 if (ulp_blob_pad_push(&encap_blob, pad) < 0) { 1669 BNXT_TF_DBG(ERR, "encap buffer padding failed\n"); 1670 return -EINVAL; 1671 } 1672 1673 1674 /* perform the 64 bit byte swap */ 1675 ulp_blob_perform_64B_byte_swap(&encap_blob); 1676 /* Append encap blob to the result blob */ 1677 rc = ulp_blob_buffer_copy(data, &encap_blob); 1678 if (rc) { 1679 BNXT_TF_DBG(ERR, "encap buffer copy failed\n"); 1680 return rc; 1681 } 1682 } 1683 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1684 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1685 BNXT_TF_DBG(DEBUG, "Result dump\n"); 1686 ulp_mapper_blob_dump(data); 1687 #endif 1688 #endif 1689 return rc; 1690 } 1691 1692 static int32_t 1693 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, 1694 struct bnxt_ulp_mapper_tbl_info *tbl, 1695 uint64_t flow_id) 1696 { 1697 struct ulp_flow_db_res_params fid_parms; 1698 uint32_t mark, gfid, mark_flag; 1699 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1700 int32_t rc = 0; 1701 1702 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1703 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 1704 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1705 BNXT_ULP_ACT_BIT_MARK))) 1706 return rc; /* no need to perform gfid process */ 1707 1708 /* Get the mark id details from action property */ 1709 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1710 sizeof(mark)); 1711 mark = tfp_be_to_cpu_32(mark); 1712 1713 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid); 1714 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID; 1715 1716 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1717 gfid, mark); 1718 if (rc) { 1719 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1720 return rc; 1721 } 1722 fid_parms.direction = tbl->direction; 1723 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1724 fid_parms.critical_resource = tbl->critical_resource; 1725 fid_parms.resource_type = mark_flag; 1726 fid_parms.resource_hndl = gfid; 1727 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 1728 1729 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1730 if (rc) 1731 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1732 return rc; 1733 } 1734 1735 static int32_t 1736 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, 1737 struct bnxt_ulp_mapper_tbl_info *tbl) 1738 { 1739 struct ulp_flow_db_res_params fid_parms; 1740 uint32_t act_idx, mark, mark_flag; 1741 uint64_t val64; 1742 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1743 int32_t rc = 0; 1744 1745 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1746 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 1747 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1748 BNXT_ULP_ACT_BIT_MARK))) 1749 return rc; /* no need to perform mark action process */ 1750 1751 /* Get the mark id details from action property */ 1752 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1753 sizeof(mark)); 1754 mark = tfp_be_to_cpu_32(mark); 1755 1756 if (!ulp_regfile_read(parms->regfile, 1757 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 1758 &val64)) { 1759 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1760 return -EINVAL; 1761 } 1762 act_idx = tfp_be_to_cpu_64(val64); 1763 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID; 1764 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1765 act_idx, mark); 1766 if (rc) { 1767 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1768 return rc; 1769 } 1770 fid_parms.direction = tbl->direction; 1771 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1772 fid_parms.critical_resource = tbl->critical_resource; 1773 fid_parms.resource_type = mark_flag; 1774 fid_parms.resource_hndl = act_idx; 1775 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 1776 1777 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1778 if (rc) 1779 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1780 return rc; 1781 } 1782 1783 static int32_t 1784 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms, 1785 struct bnxt_ulp_mapper_tbl_info *tbl) 1786 { 1787 struct ulp_flow_db_res_params fid_parms; 1788 uint32_t act_idx, mark, mark_flag; 1789 uint64_t val64; 1790 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1791 int32_t rc = 0; 1792 1793 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1794 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION) 1795 return rc; /* no need to perform mark action process */ 1796 1797 /* Get the mark id details from the computed field of dev port id */ 1798 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID); 1799 1800 /* Get the main action pointer */ 1801 if (!ulp_regfile_read(parms->regfile, 1802 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 1803 &val64)) { 1804 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1805 return -EINVAL; 1806 } 1807 act_idx = tfp_be_to_cpu_64(val64); 1808 1809 /* Set the mark flag to local fid and vfr flag */ 1810 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; 1811 1812 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1813 act_idx, mark); 1814 if (rc) { 1815 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1816 return rc; 1817 } 1818 fid_parms.direction = tbl->direction; 1819 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1820 fid_parms.critical_resource = tbl->critical_resource; 1821 fid_parms.resource_type = mark_flag; 1822 fid_parms.resource_hndl = act_idx; 1823 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 1824 1825 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1826 if (rc) 1827 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1828 return rc; 1829 } 1830 1831 /* Tcam table scan the identifier list and allocate each identifier */ 1832 static int32_t 1833 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms, 1834 struct bnxt_ulp_mapper_tbl_info *tbl) 1835 { 1836 struct bnxt_ulp_mapper_ident_info *idents; 1837 uint32_t num_idents; 1838 uint32_t i; 1839 1840 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 1841 for (i = 0; i < num_idents; i++) { 1842 if (ulp_mapper_ident_process(parms, tbl, 1843 &idents[i], NULL)) 1844 return -EINVAL; 1845 } 1846 return 0; 1847 } 1848 1849 /* 1850 * Tcam table scan the identifier list and extract the identifier from 1851 * the result blob. 1852 */ 1853 static int32_t 1854 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms, 1855 struct bnxt_ulp_mapper_tbl_info *tbl, 1856 struct ulp_blob *data) 1857 { 1858 struct bnxt_ulp_mapper_ident_info *idents; 1859 uint32_t num_idents = 0, i; 1860 int32_t rc = 0; 1861 1862 /* 1863 * Extract the listed identifiers from the result field, 1864 * no need to allocate them. 1865 */ 1866 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 1867 for (i = 0; i < num_idents; i++) { 1868 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data); 1869 if (rc) { 1870 BNXT_TF_DBG(ERR, "Error in identifier extraction\n"); 1871 return rc; 1872 } 1873 } 1874 return rc; 1875 } 1876 1877 /* Internal function to write the tcam entry */ 1878 static int32_t 1879 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms, 1880 struct bnxt_ulp_mapper_tbl_info *tbl, 1881 struct ulp_blob *key, 1882 struct ulp_blob *mask, 1883 struct ulp_blob *data, 1884 uint16_t idx) 1885 { 1886 struct tf_set_tcam_entry_parms sparms = { 0 }; 1887 struct tf *tfp; 1888 uint16_t tmplen; 1889 int32_t rc; 1890 1891 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 1892 if (!tfp) { 1893 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1894 return -EINVAL; 1895 } 1896 1897 sparms.dir = tbl->direction; 1898 sparms.tcam_tbl_type = tbl->resource_type; 1899 sparms.idx = idx; 1900 sparms.key = ulp_blob_data_get(key, &tmplen); 1901 sparms.key_sz_in_bits = tmplen; 1902 sparms.mask = ulp_blob_data_get(mask, &tmplen); 1903 sparms.result = ulp_blob_data_get(data, &tmplen); 1904 sparms.result_sz_in_bits = tmplen; 1905 if (tf_set_tcam_entry(tfp, &sparms)) { 1906 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n", 1907 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 1908 tf_dir_2_str(sparms.dir), sparms.idx); 1909 return -EIO; 1910 } 1911 BNXT_TF_INF("tcam[%s][%s][%x] write success.\n", 1912 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 1913 tf_dir_2_str(sparms.dir), sparms.idx); 1914 1915 /* Mark action */ 1916 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1917 if (rc) { 1918 BNXT_TF_DBG(ERR, "failed mark action processing\n"); 1919 return rc; 1920 } 1921 1922 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1923 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1924 ulp_mapper_tcam_entry_dump("TCAM", idx, tbl, key, mask, data); 1925 #endif 1926 #endif 1927 return rc; 1928 } 1929 1930 /* 1931 * internal function to post process key/mask blobs for dynamic pad WC tcam tbl 1932 * 1933 * parms [in] The mappers parms with data related to the flow. 1934 * 1935 * key [in] The original key to be transformed 1936 * 1937 * mask [in] The original mask to be transformed 1938 * 1939 * tkey [in/out] The transformed key 1940 * 1941 * tmask [in/out] The transformed mask 1942 * 1943 * returns zero on success, non-zero on failure 1944 */ 1945 static uint32_t 1946 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms, 1947 struct ulp_blob *key, 1948 struct ulp_blob *mask, 1949 struct ulp_blob *tkey, 1950 struct ulp_blob *tmask) 1951 { 1952 uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset; 1953 uint32_t cword, i, rc; 1954 int32_t pad; 1955 uint8_t *val; 1956 1957 slice_width = dparms->wc_slice_width; 1958 clen = dparms->wc_ctl_size_bits; 1959 max_slices = dparms->wc_max_slices; 1960 blen = ulp_blob_data_len_get(key); 1961 1962 /* Get the length of the key based on number of slices and width */ 1963 num_slices = 1; 1964 tlen = slice_width; 1965 while (tlen < blen && 1966 num_slices <= max_slices) { 1967 num_slices = num_slices << 1; 1968 tlen = tlen << 1; 1969 } 1970 1971 if (num_slices > max_slices) { 1972 BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen); 1973 return -EINVAL; 1974 } 1975 1976 /* The key/mask may not be on a natural slice boundary, pad it */ 1977 pad = tlen - blen; 1978 if (ulp_blob_pad_push(key, pad) < 0 || 1979 ulp_blob_pad_push(mask, pad) < 0) { 1980 BNXT_TF_DBG(ERR, "Unable to pad key/mask\n"); 1981 return -EINVAL; 1982 } 1983 1984 /* The new length accounts for the ctrl word length and num slices */ 1985 tlen = tlen + clen * num_slices; 1986 if (!ulp_blob_init(tkey, tlen, key->byte_order) || 1987 !ulp_blob_init(tmask, tlen, mask->byte_order)) { 1988 BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n"); 1989 return -EINVAL; 1990 } 1991 1992 /* Build the transformed key/mask */ 1993 cword = dparms->wc_mode_list[num_slices - 1]; 1994 cword = tfp_cpu_to_be_32(cword); 1995 offset = 0; 1996 for (i = 0; i < num_slices; i++) { 1997 val = ulp_blob_push_32(tkey, &cword, clen); 1998 if (!val) { 1999 BNXT_TF_DBG(ERR, "Key ctrl word push failed\n"); 2000 return -EINVAL; 2001 } 2002 val = ulp_blob_push_32(tmask, &cword, clen); 2003 if (!val) { 2004 BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n"); 2005 return -EINVAL; 2006 } 2007 rc = ulp_blob_append(tkey, key, offset, slice_width); 2008 if (rc) { 2009 BNXT_TF_DBG(ERR, "Key blob append failed\n"); 2010 return rc; 2011 } 2012 rc = ulp_blob_append(tmask, mask, offset, slice_width); 2013 if (rc) { 2014 BNXT_TF_DBG(ERR, "Mask blob append failed\n"); 2015 return rc; 2016 } 2017 offset += slice_width; 2018 } 2019 2020 /* The key/mask are byte reversed on every 4 byte chunk */ 2021 ulp_blob_perform_byte_reverse(tkey, 4); 2022 ulp_blob_perform_byte_reverse(tmask, 4); 2023 2024 return 0; 2025 } 2026 2027 /* internal function to post process the key/mask blobs for wildcard tcam tbl */ 2028 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob) 2029 { 2030 ulp_blob_perform_64B_word_swap(blob); 2031 ulp_blob_perform_64B_byte_swap(blob); 2032 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 2033 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 2034 BNXT_TF_DBG(INFO, "Dump after wc tcam post process\n"); 2035 ulp_mapper_blob_dump(blob); 2036 #endif 2037 #endif 2038 } 2039 2040 static int32_t ulp_mapper_tcam_is_wc_tcam(struct bnxt_ulp_mapper_tbl_info *tbl) 2041 { 2042 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM || 2043 tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH || 2044 tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW) 2045 return 1; 2046 return 0; 2047 } 2048 2049 static int32_t 2050 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2051 struct bnxt_ulp_mapper_tbl_info *tbl) 2052 { 2053 struct bnxt_ulp_mapper_key_info *kflds; 2054 struct ulp_blob okey, omask, data, update_data; 2055 struct ulp_blob tkey, tmask; /* transform key and mask */ 2056 struct ulp_blob *key, *mask; 2057 uint32_t i, num_kflds; 2058 struct tf *tfp; 2059 int32_t rc, trc; 2060 struct bnxt_ulp_device_params *dparms = parms->device_params; 2061 struct tf_alloc_tcam_entry_parms aparms = { 0 }; 2062 struct tf_search_tcam_entry_parms searchparms = { 0 }; 2063 struct ulp_flow_db_res_params fid_parms = { 0 }; 2064 struct tf_free_tcam_entry_parms free_parms = { 0 }; 2065 uint32_t hit = 0; 2066 uint16_t tmplen = 0; 2067 uint16_t idx; 2068 enum bnxt_ulp_byte_order key_byte_order; 2069 2070 /* Set the key and mask to the original key and mask. */ 2071 key = &okey; 2072 mask = &omask; 2073 2074 /* Skip this if table opcode is NOP */ 2075 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED || 2076 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) { 2077 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n", 2078 tbl->tbl_opcode); 2079 return 0; 2080 } 2081 2082 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 2083 if (!tfp) { 2084 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 2085 return -EINVAL; 2086 } 2087 2088 /* If only allocation of identifier then perform and exit */ 2089 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_IDENT) { 2090 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); 2091 return rc; 2092 } 2093 2094 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2095 if (!kflds || !num_kflds) { 2096 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2097 return -EINVAL; 2098 } 2099 2100 if (ulp_mapper_tcam_is_wc_tcam(tbl)) 2101 key_byte_order = dparms->wc_key_byte_order; 2102 else 2103 key_byte_order = dparms->key_byte_order; 2104 2105 if (!ulp_blob_init(key, tbl->blob_key_bit_size, key_byte_order) || 2106 !ulp_blob_init(mask, tbl->blob_key_bit_size, key_byte_order) || 2107 !ulp_blob_init(&data, tbl->result_bit_size, 2108 dparms->result_byte_order) || 2109 !ulp_blob_init(&update_data, tbl->result_bit_size, 2110 dparms->result_byte_order)) { 2111 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 2112 return -EINVAL; 2113 } 2114 2115 /* create the key/mask */ 2116 /* 2117 * NOTE: The WC table will require some kind of flag to handle the 2118 * mode bits within the key/mask 2119 */ 2120 for (i = 0; i < num_kflds; i++) { 2121 /* Setup the key */ 2122 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2123 &kflds[i].field_info_spec, 2124 key, 1, "TCAM Key"); 2125 if (rc) { 2126 BNXT_TF_DBG(ERR, "Key field set failed %s\n", 2127 kflds[i].field_info_spec.description); 2128 return rc; 2129 } 2130 2131 /* Setup the mask */ 2132 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2133 &kflds[i].field_info_mask, 2134 mask, 0, "TCAM Mask"); 2135 if (rc) { 2136 BNXT_TF_DBG(ERR, "Mask field set failed %s\n", 2137 kflds[i].field_info_mask.description); 2138 return rc; 2139 } 2140 } 2141 2142 /* For wild card tcam perform the post process to swap the blob */ 2143 if (ulp_mapper_tcam_is_wc_tcam(tbl)) { 2144 if (dparms->dynamic_pad_en) { 2145 /* Sets up the slices for writing to the WC TCAM */ 2146 rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms, 2147 key, mask, 2148 &tkey, 2149 &tmask); 2150 if (rc) { 2151 BNXT_TF_DBG(ERR, 2152 "Failed to post proc WC entry.\n"); 2153 return rc; 2154 } 2155 /* Now need to use the transform Key/Mask */ 2156 key = &tkey; 2157 mask = &tmask; 2158 } else { 2159 ulp_mapper_wc_tcam_tbl_post_process(key); 2160 ulp_mapper_wc_tcam_tbl_post_process(mask); 2161 } 2162 2163 } 2164 2165 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 2166 /* allocate the tcam index */ 2167 aparms.dir = tbl->direction; 2168 aparms.tcam_tbl_type = tbl->resource_type; 2169 aparms.key = ulp_blob_data_get(key, &tmplen); 2170 aparms.key_sz_in_bits = tmplen; 2171 aparms.mask = ulp_blob_data_get(mask, &tmplen); 2172 2173 /* calculate the entry priority */ 2174 rc = ulp_mapper_priority_opc_process(parms, tbl, 2175 &aparms.priority); 2176 if (rc) { 2177 BNXT_TF_DBG(ERR, "entry priority process failed\n"); 2178 return rc; 2179 } 2180 2181 rc = tf_alloc_tcam_entry(tfp, &aparms); 2182 if (rc) { 2183 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); 2184 return rc; 2185 } 2186 idx = aparms.idx; 2187 hit = aparms.hit; 2188 } else { 2189 /* 2190 * Searching before allocation to see if we already have an 2191 * entry. This allows re-use of a constrained resource. 2192 */ 2193 searchparms.dir = tbl->direction; 2194 searchparms.tcam_tbl_type = tbl->resource_type; 2195 searchparms.key = ulp_blob_data_get(key, &tmplen); 2196 searchparms.key_sz_in_bits = tbl->key_bit_size; 2197 searchparms.mask = ulp_blob_data_get(mask, &tmplen); 2198 searchparms.alloc = 1; 2199 searchparms.result = ulp_blob_data_get(&data, &tmplen); 2200 searchparms.result_sz_in_bits = tbl->result_bit_size; 2201 2202 /* calculate the entry priority */ 2203 rc = ulp_mapper_priority_opc_process(parms, tbl, 2204 &searchparms.priority); 2205 if (rc) { 2206 BNXT_TF_DBG(ERR, "entry priority process failed\n"); 2207 return rc; 2208 } 2209 2210 rc = tf_search_tcam_entry(tfp, &searchparms); 2211 if (rc) { 2212 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc); 2213 return rc; 2214 } 2215 2216 /* Successful search, check the result */ 2217 if (searchparms.search_status == REJECT) { 2218 BNXT_TF_DBG(ERR, "tcam alloc rejected\n"); 2219 return -ENOMEM; 2220 } 2221 idx = searchparms.idx; 2222 hit = searchparms.hit; 2223 } 2224 2225 /* Write the tcam index into the regfile*/ 2226 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand, 2227 (uint64_t)tfp_cpu_to_be_64(idx))) { 2228 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", 2229 tbl->tbl_operand); 2230 rc = -EINVAL; 2231 /* Need to free the tcam idx, so goto error */ 2232 goto error; 2233 } 2234 2235 /* if it is miss then it is same as no search before alloc */ 2236 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 2237 /*Scan identifier list, allocate identifier and update regfile*/ 2238 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); 2239 /* Create the result blob */ 2240 if (!rc) 2241 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 2242 "TCAM Result"); 2243 /* write the tcam entry */ 2244 if (!rc) 2245 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key, 2246 mask, &data, idx); 2247 } else { 2248 /*Scan identifier list, extract identifier and update regfile*/ 2249 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); 2250 } 2251 if (rc) 2252 goto error; 2253 2254 /* Add the tcam index to the flow database */ 2255 fid_parms.direction = tbl->direction; 2256 fid_parms.resource_func = tbl->resource_func; 2257 fid_parms.resource_type = tbl->resource_type; 2258 fid_parms.critical_resource = tbl->critical_resource; 2259 fid_parms.resource_hndl = idx; 2260 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 2261 2262 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2263 if (rc) { 2264 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2265 rc); 2266 /* Need to free the identifier, so goto error */ 2267 goto error; 2268 } 2269 2270 return 0; 2271 error: 2272 free_parms.dir = tbl->direction; 2273 free_parms.tcam_tbl_type = tbl->resource_type; 2274 free_parms.idx = idx; 2275 trc = tf_free_tcam_entry(tfp, &free_parms); 2276 if (trc) 2277 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", 2278 tbl->resource_type, tbl->direction, idx); 2279 return rc; 2280 } 2281 2282 static int32_t 2283 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2284 struct bnxt_ulp_mapper_tbl_info *tbl) 2285 { 2286 struct bnxt_ulp_mapper_key_info *kflds; 2287 struct ulp_blob key, data; 2288 uint32_t i, num_kflds; 2289 uint16_t tmplen; 2290 struct tf *tfp; 2291 struct ulp_flow_db_res_params fid_parms = { 0 }; 2292 struct tf_insert_em_entry_parms iparms = { 0 }; 2293 struct tf_delete_em_entry_parms free_parms = { 0 }; 2294 enum bnxt_ulp_flow_mem_type mtype; 2295 struct bnxt_ulp_device_params *dparms = parms->device_params; 2296 int32_t trc; 2297 int32_t rc = 0; 2298 int32_t pad = 0; 2299 enum bnxt_ulp_byte_order key_order, res_order; 2300 2301 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 2302 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); 2303 if (rc) { 2304 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n"); 2305 return -EINVAL; 2306 } 2307 2308 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2309 if (!kflds || !num_kflds) { 2310 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2311 return -EINVAL; 2312 } 2313 2314 key_order = dparms->em_byte_order; 2315 res_order = dparms->em_byte_order; 2316 2317 /* Initialize the key/result blobs */ 2318 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, key_order) || 2319 !ulp_blob_init(&data, tbl->result_bit_size, res_order)) { 2320 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 2321 return -EINVAL; 2322 } 2323 2324 /* create the key */ 2325 for (i = 0; i < num_kflds; i++) { 2326 /* Setup the key */ 2327 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2328 &kflds[i].field_info_spec, 2329 &key, 1, "EM Key"); 2330 if (rc) { 2331 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 2332 return rc; 2333 } 2334 } 2335 2336 /* if dynamic padding is enabled then add padding to result data */ 2337 if (dparms->dynamic_pad_en) { 2338 /* add padding to make sure key is at byte boundary */ 2339 ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS); 2340 2341 /* add the pad */ 2342 pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits; 2343 if (pad < 0) { 2344 BNXT_TF_DBG(ERR, "Invalid em blk size and align\n"); 2345 return -EINVAL; 2346 } 2347 ulp_blob_pad_push(&data, (uint32_t)pad); 2348 } 2349 2350 /* Create the result data blob */ 2351 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result"); 2352 if (rc) { 2353 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2354 return rc; 2355 } 2356 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 2357 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 2358 ulp_mapper_result_dump("EM Result", tbl, &data); 2359 #endif 2360 #endif 2361 if (dparms->dynamic_pad_en) { 2362 uint32_t abits = dparms->em_blk_align_bits; 2363 2364 /* when dynamic padding is enabled merge result + key */ 2365 rc = ulp_blob_block_merge(&data, &key, abits, pad); 2366 if (rc) { 2367 BNXT_TF_DBG(ERR, "Failed to merge the result blob\n"); 2368 return rc; 2369 } 2370 2371 /* add padding to make sure merged result is at slice boundary*/ 2372 ulp_blob_pad_align(&data, abits); 2373 2374 ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits)); 2375 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 2376 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 2377 ulp_mapper_result_dump("EM Merged Result", tbl, &data); 2378 #endif 2379 #endif 2380 } 2381 2382 /* do the transpose for the internal EM keys */ 2383 if (tbl->resource_type == TF_MEM_INTERNAL) { 2384 if (dparms->em_key_align_bytes) { 2385 int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes); 2386 2387 tmplen = ulp_blob_data_len_get(&key); 2388 ulp_blob_pad_push(&key, b - tmplen); 2389 } 2390 tmplen = ulp_blob_data_len_get(&key); 2391 ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen)); 2392 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 2393 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 2394 ulp_mapper_result_dump("EM Key Transpose", tbl, &key); 2395 #endif 2396 #endif 2397 } 2398 2399 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, 2400 &iparms.tbl_scope_id); 2401 if (rc) { 2402 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 2403 return rc; 2404 } 2405 2406 /* 2407 * NOTE: the actual blob size will differ from the size in the tbl 2408 * entry due to the padding. 2409 */ 2410 iparms.dup_check = 0; 2411 iparms.dir = tbl->direction; 2412 iparms.mem = tbl->resource_type; 2413 iparms.key = ulp_blob_data_get(&key, &tmplen); 2414 iparms.key_sz_in_bits = tbl->key_bit_size; 2415 iparms.em_record = ulp_blob_data_get(&data, &tmplen); 2416 if (tbl->result_bit_size) 2417 iparms.em_record_sz_in_bits = tbl->result_bit_size; 2418 else 2419 iparms.em_record_sz_in_bits = tmplen; 2420 2421 rc = tf_insert_em_entry(tfp, &iparms); 2422 if (rc) { 2423 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc); 2424 return rc; 2425 } 2426 2427 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 2428 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 2429 ulp_mapper_em_dump("EM", &key, &data, &iparms); 2430 /* tf_dump_tables(tfp, iparms.tbl_scope_id); */ 2431 #endif 2432 #endif 2433 /* Mark action process */ 2434 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && 2435 tbl->resource_type == TF_MEM_EXTERNAL) 2436 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); 2437 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && 2438 tbl->resource_type == TF_MEM_INTERNAL) 2439 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 2440 if (rc) { 2441 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 2442 goto error; 2443 } 2444 2445 /* Link the EM resource to the flow in the flow db */ 2446 memset(&fid_parms, 0, sizeof(fid_parms)); 2447 fid_parms.direction = tbl->direction; 2448 fid_parms.resource_func = tbl->resource_func; 2449 fid_parms.resource_type = tbl->resource_type; 2450 fid_parms.critical_resource = tbl->critical_resource; 2451 fid_parms.resource_hndl = iparms.flow_handle; 2452 2453 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2454 if (rc) { 2455 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", 2456 rc); 2457 /* Need to free the identifier, so goto error */ 2458 goto error; 2459 } 2460 2461 return 0; 2462 error: 2463 free_parms.dir = iparms.dir; 2464 free_parms.mem = iparms.mem; 2465 free_parms.tbl_scope_id = iparms.tbl_scope_id; 2466 free_parms.flow_handle = iparms.flow_handle; 2467 2468 trc = tf_delete_em_entry(tfp, &free_parms); 2469 if (trc) 2470 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n"); 2471 2472 return rc; 2473 } 2474 2475 static int32_t 2476 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2477 struct bnxt_ulp_mapper_tbl_info *tbl) 2478 { 2479 struct ulp_flow_db_res_params fid_parms; 2480 struct ulp_blob data; 2481 uint64_t regval = 0; 2482 uint16_t tmplen; 2483 uint32_t index; 2484 int32_t rc = 0, trc = 0; 2485 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 2486 struct tf_set_tbl_entry_parms sparms = { 0 }; 2487 struct tf_get_tbl_entry_parms gparms = { 0 }; 2488 struct tf_free_tbl_entry_parms free_parms = { 0 }; 2489 uint32_t tbl_scope_id; 2490 struct tf *tfp; 2491 struct bnxt_ulp_glb_resource_info glb_res = { 0 }; 2492 uint16_t bit_size; 2493 bool alloc = false; 2494 bool write = false; 2495 bool global = false; 2496 uint64_t act_rec_size; 2497 bool shared = false; 2498 enum tf_tbl_type tbl_type = tbl->resource_type; 2499 2500 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 2501 /* compute the blob size */ 2502 bit_size = ulp_mapper_dyn_blob_size_get(parms, tbl); 2503 2504 /* Initialize the blob data */ 2505 if (!ulp_blob_init(&data, bit_size, 2506 parms->device_params->result_byte_order)) { 2507 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n"); 2508 return -EINVAL; 2509 } 2510 2511 /* Get the scope id first */ 2512 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); 2513 if (rc) { 2514 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 2515 return rc; 2516 } 2517 2518 switch (tbl->tbl_opcode) { 2519 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE: 2520 alloc = true; 2521 break; 2522 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE: 2523 /* 2524 * Build the entry, alloc an index, write the table, and store 2525 * the data in the regfile. 2526 */ 2527 alloc = true; 2528 write = true; 2529 break; 2530 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE: 2531 /* 2532 * get the index to write to from the regfile and then write 2533 * the table entry. 2534 */ 2535 if (!ulp_regfile_read(parms->regfile, 2536 tbl->tbl_operand, 2537 ®val)) { 2538 BNXT_TF_DBG(ERR, 2539 "Failed to get tbl idx from regfile[%d].\n", 2540 tbl->tbl_operand); 2541 return -EINVAL; 2542 } 2543 index = tfp_be_to_cpu_64(regval); 2544 /* For external, we need to reverse shift */ 2545 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2546 index = TF_ACT_REC_PTR_2_OFFSET(index); 2547 2548 write = true; 2549 break; 2550 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE: 2551 /* 2552 * Build the entry, alloc an index, write the table, and store 2553 * the data in the global regfile. 2554 */ 2555 alloc = true; 2556 global = true; 2557 write = true; 2558 glb_res.direction = tbl->direction; 2559 glb_res.resource_func = tbl->resource_func; 2560 glb_res.resource_type = tbl->resource_type; 2561 glb_res.glb_regfile_index = tbl->tbl_operand; 2562 break; 2563 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE: 2564 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) { 2565 BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n"); 2566 return -EINVAL; 2567 } 2568 /* 2569 * get the index to write to from the global regfile and then 2570 * write the table. 2571 */ 2572 if (ulp_mapper_glb_resource_read(parms->mapper_data, 2573 tbl->direction, 2574 tbl->tbl_operand, 2575 ®val, &shared)) { 2576 BNXT_TF_DBG(ERR, 2577 "Failed to get tbl idx from Glb RF[%d].\n", 2578 tbl->tbl_operand); 2579 return -EINVAL; 2580 } 2581 index = tfp_be_to_cpu_64(regval); 2582 /* For external, we need to reverse shift */ 2583 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2584 index = TF_ACT_REC_PTR_2_OFFSET(index); 2585 write = true; 2586 break; 2587 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE: 2588 /* 2589 * The read is different from the rest and can be handled here 2590 * instead of trying to use common code. Simply read the table 2591 * with the index from the regfile, scan and store the 2592 * identifiers, and return. 2593 */ 2594 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 2595 /* Not currently supporting with EXT */ 2596 BNXT_TF_DBG(ERR, 2597 "Ext Table Read Opcode not supported.\n"); 2598 return -EINVAL; 2599 } 2600 if (!ulp_regfile_read(parms->regfile, 2601 tbl->tbl_operand, ®val)) { 2602 BNXT_TF_DBG(ERR, 2603 "Failed to get tbl idx from regfile[%d]\n", 2604 tbl->tbl_operand); 2605 return -EINVAL; 2606 } 2607 index = tfp_be_to_cpu_64(regval); 2608 gparms.dir = tbl->direction; 2609 gparms.type = tbl->resource_type; 2610 gparms.data = ulp_blob_data_get(&data, &tmplen); 2611 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2612 gparms.idx = index; 2613 rc = tf_get_tbl_entry(tfp, &gparms); 2614 if (rc) { 2615 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n", 2616 tbl->resource_type, index); 2617 return rc; 2618 } 2619 /* 2620 * Scan the fields in the entry and push them into the regfile. 2621 */ 2622 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2623 gparms.data, 2624 gparms.data_sz_in_bytes, 2625 data.byte_order); 2626 if (rc) { 2627 BNXT_TF_DBG(ERR, 2628 "Failed to get flds on tbl read rc=%d\n", 2629 rc); 2630 return rc; 2631 } 2632 return 0; 2633 default: 2634 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n", 2635 tbl->tbl_opcode); 2636 return -EINVAL; 2637 } 2638 2639 if (write) { 2640 /* Get the result fields list */ 2641 rc = ulp_mapper_tbl_result_build(parms, 2642 tbl, 2643 &data, 2644 "Indexed Result"); 2645 if (rc) { 2646 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2647 return rc; 2648 } 2649 } 2650 2651 if (alloc) { 2652 aparms.dir = tbl->direction; 2653 tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl, 2654 &data, &tmplen); 2655 aparms.type = tbl_type; 2656 aparms.tbl_scope_id = tbl_scope_id; 2657 2658 /* All failures after the alloc succeeds require a free */ 2659 rc = tf_alloc_tbl_entry(tfp, &aparms); 2660 if (rc) { 2661 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2662 tf_tbl_type_2_str(aparms.type), 2663 tf_dir_2_str(tbl->direction), rc); 2664 return rc; 2665 } 2666 index = aparms.idx; 2667 2668 /* 2669 * Store the index in the regfile since we either allocated it 2670 * or it was a hit. 2671 * 2672 * Calculate the idx for the result record, for external EM the 2673 * offset needs to be shifted accordingly. 2674 * If external non-inline table types are used then need to 2675 * revisit this logic. 2676 */ 2677 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2678 regval = TF_ACT_REC_OFFSET_2_PTR(index); 2679 else 2680 regval = index; 2681 regval = tfp_cpu_to_be_64(regval); 2682 2683 if (global) { 2684 /* 2685 * Shared resources are never allocated through this 2686 * method, so the shared flag is always false. 2687 */ 2688 rc = ulp_mapper_glb_resource_write(parms->mapper_data, 2689 &glb_res, regval, 2690 false); 2691 } else { 2692 rc = ulp_regfile_write(parms->regfile, 2693 tbl->tbl_operand, regval); 2694 } 2695 if (rc) { 2696 BNXT_TF_DBG(ERR, 2697 "Failed to write %s regfile[%d] rc=%d\n", 2698 (global) ? "global" : "reg", 2699 tbl->tbl_operand, rc); 2700 goto error; 2701 } 2702 } 2703 2704 if (write) { 2705 sparms.dir = tbl->direction; 2706 sparms.data = ulp_blob_data_get(&data, &tmplen); 2707 tbl_type = ulp_mapper_dyn_tbl_type_get(parms, tbl, &data, 2708 &tmplen); 2709 sparms.type = tbl_type; 2710 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2711 sparms.idx = index; 2712 sparms.tbl_scope_id = tbl_scope_id; 2713 if (shared) 2714 tfp = bnxt_ulp_cntxt_shared_tfp_get(parms->ulp_ctx); 2715 rc = tf_set_tbl_entry(tfp, &sparms); 2716 if (rc) { 2717 BNXT_TF_DBG(ERR, 2718 "Index table[%s][%s][%x] write fail rc=%d\n", 2719 tf_tbl_type_2_str(sparms.type), 2720 tf_dir_2_str(sparms.dir), 2721 sparms.idx, rc); 2722 goto error; 2723 } 2724 BNXT_TF_INF("Index table[%s][%s][%x] write successful.\n", 2725 tf_tbl_type_2_str(sparms.type), 2726 tf_dir_2_str(sparms.dir), sparms.idx); 2727 2728 /* Calculate action record size */ 2729 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 2730 act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16; 2731 act_rec_size--; 2732 if (ulp_regfile_write(parms->regfile, 2733 BNXT_ULP_RF_IDX_ACTION_REC_SIZE, 2734 tfp_cpu_to_be_64(act_rec_size))) 2735 BNXT_TF_DBG(ERR, 2736 "Failed write the act rec size\n"); 2737 } 2738 } 2739 2740 /* Link the resource to the flow in the flow db */ 2741 memset(&fid_parms, 0, sizeof(fid_parms)); 2742 fid_parms.direction = tbl->direction; 2743 fid_parms.resource_func = tbl->resource_func; 2744 fid_parms.resource_type = tbl_type; 2745 fid_parms.resource_sub_type = tbl->resource_sub_type; 2746 fid_parms.resource_hndl = index; 2747 fid_parms.critical_resource = tbl->critical_resource; 2748 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 2749 2750 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2751 if (rc) { 2752 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2753 rc); 2754 goto error; 2755 } 2756 2757 /* Perform the VF rep action */ 2758 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 2759 if (rc) { 2760 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 2761 goto error; 2762 } 2763 return rc; 2764 error: 2765 /* Shared resources are not freed */ 2766 if (shared) 2767 return rc; 2768 /* 2769 * Free the allocated resource since we failed to either 2770 * write to the entry or link the flow 2771 */ 2772 free_parms.dir = tbl->direction; 2773 free_parms.type = tbl_type; 2774 free_parms.idx = index; 2775 free_parms.tbl_scope_id = tbl_scope_id; 2776 2777 trc = tf_free_tbl_entry(tfp, &free_parms); 2778 if (trc) 2779 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n"); 2780 2781 return rc; 2782 } 2783 2784 static int32_t 2785 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2786 struct bnxt_ulp_mapper_tbl_info *tbl) 2787 { 2788 struct ulp_blob data, res_blob; 2789 uint64_t idx; 2790 uint16_t tmplen; 2791 int32_t rc = 0; 2792 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; 2793 struct tf_get_if_tbl_entry_parms get_parms = { 0 }; 2794 struct tf *tfp; 2795 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode; 2796 uint32_t res_size; 2797 2798 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 2799 /* Initialize the blob data */ 2800 if (!ulp_blob_init(&data, tbl->result_bit_size, 2801 parms->device_params->result_byte_order)) { 2802 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 2803 return -EINVAL; 2804 } 2805 2806 /* create the result blob */ 2807 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result"); 2808 if (rc) { 2809 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2810 return rc; 2811 } 2812 2813 /* Get the index details */ 2814 switch (if_opc) { 2815 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD: 2816 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 2817 break; 2818 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE: 2819 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) { 2820 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 2821 tbl->tbl_operand); 2822 return -EINVAL; 2823 } 2824 idx = tfp_be_to_cpu_64(idx); 2825 break; 2826 case BNXT_ULP_IF_TBL_OPC_WR_CONST: 2827 idx = tbl->tbl_operand; 2828 break; 2829 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD: 2830 /* Initialize the result blob */ 2831 if (!ulp_blob_init(&res_blob, tbl->result_bit_size, 2832 parms->device_params->result_byte_order)) { 2833 BNXT_TF_DBG(ERR, "Failed initial result blob\n"); 2834 return -EINVAL; 2835 } 2836 2837 /* read the interface table */ 2838 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 2839 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size); 2840 get_parms.dir = tbl->direction; 2841 get_parms.type = tbl->resource_type; 2842 get_parms.idx = idx; 2843 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen); 2844 get_parms.data_sz_in_bytes = res_size; 2845 2846 rc = tf_get_if_tbl_entry(tfp, &get_parms); 2847 if (rc) { 2848 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n", 2849 get_parms.type, 2850 tf_dir_2_str(get_parms.dir), 2851 get_parms.idx, rc); 2852 return rc; 2853 } 2854 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2855 res_blob.data, 2856 res_size, 2857 res_blob.byte_order); 2858 if (rc) 2859 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc); 2860 return rc; 2861 case BNXT_ULP_IF_TBL_OPC_NOT_USED: 2862 return rc; /* skip it */ 2863 default: 2864 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); 2865 return -EINVAL; 2866 } 2867 2868 /* Perform the tf table set by filling the set params */ 2869 iftbl_params.dir = tbl->direction; 2870 iftbl_params.type = tbl->resource_type; 2871 iftbl_params.data = ulp_blob_data_get(&data, &tmplen); 2872 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2873 iftbl_params.idx = idx; 2874 2875 rc = tf_set_if_tbl_entry(tfp, &iftbl_params); 2876 if (rc) { 2877 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n", 2878 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */ 2879 tf_dir_2_str(iftbl_params.dir), 2880 iftbl_params.idx, rc); 2881 return rc; 2882 } 2883 BNXT_TF_INF("Set table[%s][%s][%x] success.\n", 2884 tf_if_tbl_2_str(iftbl_params.type), 2885 tf_dir_2_str(iftbl_params.dir), 2886 iftbl_params.idx); 2887 2888 /* 2889 * TBD: Need to look at the need to store idx in flow db for restore 2890 * the table to its original state on deletion of this entry. 2891 */ 2892 return rc; 2893 } 2894 2895 static int32_t 2896 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2897 struct bnxt_ulp_mapper_tbl_info *tbl) 2898 { 2899 struct ulp_mapper_gen_tbl_list *gen_tbl_list; 2900 struct bnxt_ulp_mapper_key_info *kflds; 2901 struct ulp_flow_db_res_params fid_parms; 2902 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g; 2903 struct ulp_gen_hash_entry_params hash_entry; 2904 uint16_t tmplen = 0; 2905 struct ulp_blob key, data; 2906 uint8_t *cache_key; 2907 int32_t tbl_idx; 2908 uint32_t i, num_kflds = 0, key_index = 0; 2909 uint32_t gen_tbl_miss = 1, fdb_write = 0; 2910 uint8_t *byte_data; 2911 int32_t rc = 0; 2912 2913 /* Get the key fields list and build the key. */ 2914 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2915 if (!kflds || !num_kflds) { 2916 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2917 return -EINVAL; 2918 } 2919 2920 if (!ulp_blob_init(&key, tbl->key_bit_size, 2921 parms->device_params->key_byte_order)) { 2922 BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); 2923 return -EINVAL; 2924 } 2925 for (i = 0; i < num_kflds; i++) { 2926 /* Setup the key */ 2927 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2928 &kflds[i].field_info_spec, 2929 &key, 1, "Gen Tbl Key"); 2930 if (rc) { 2931 BNXT_TF_DBG(ERR, 2932 "Failed to create key for Gen tbl rc=%d\n", 2933 rc); 2934 return -EINVAL; 2935 } 2936 } 2937 2938 /* Calculate the table index for the generic table*/ 2939 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type, 2940 tbl->direction); 2941 if (tbl_idx < 0) { 2942 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n", 2943 tbl->resource_sub_type, tbl->direction); 2944 return -EINVAL; 2945 } 2946 2947 /* The_key is a byte array convert it to a search index */ 2948 cache_key = ulp_blob_data_get(&key, &tmplen); 2949 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 2950 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 2951 ulp_mapper_gen_tbl_dump(tbl->resource_sub_type, tbl->direction, &key); 2952 #endif 2953 #endif 2954 /* get the generic table */ 2955 gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx]; 2956 2957 /* Check if generic hash table */ 2958 if (gen_tbl_list->hash_tbl) { 2959 if (tbl->gen_tbl_lkup_type != 2960 BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) { 2961 BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n", 2962 gen_tbl_list->gen_tbl_name); 2963 return -EINVAL; 2964 } 2965 hash_entry.key_data = cache_key; 2966 hash_entry.key_length = ULP_BITS_2_BYTE(tmplen); 2967 rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl, 2968 &hash_entry); 2969 if (rc) { 2970 BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n", 2971 gen_tbl_list->gen_tbl_name); 2972 return rc; 2973 } 2974 if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) { 2975 key_index = hash_entry.key_idx; 2976 /* Get the generic table entry */ 2977 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, 2978 key_index, 2979 &gen_tbl_ent)) 2980 return -EINVAL; 2981 /* store the hash index in the fdb */ 2982 key_index = hash_entry.hash_index; 2983 } 2984 } else { 2985 /* convert key to index directly */ 2986 if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) { 2987 BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n", 2988 gen_tbl_list->gen_tbl_name); 2989 return -EINVAL; 2990 } 2991 memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen)); 2992 /* Get the generic table entry */ 2993 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index, 2994 &gen_tbl_ent)) 2995 return -EINVAL; 2996 } 2997 switch (tbl->tbl_opcode) { 2998 case BNXT_ULP_GENERIC_TBL_OPC_READ: 2999 if (gen_tbl_list->hash_tbl) { 3000 if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND) 3001 break; /* nothing to be done , no entry */ 3002 } 3003 3004 /* check the reference count */ 3005 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { 3006 g = &gen_tbl_ent; 3007 /* Scan ident list and create the result blob*/ 3008 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 3009 g->byte_data, 3010 g->byte_data_size, 3011 g->byte_order); 3012 if (rc) { 3013 BNXT_TF_DBG(ERR, 3014 "Failed to scan ident list\n"); 3015 return -EINVAL; 3016 } 3017 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) { 3018 /* increment the reference count */ 3019 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); 3020 } 3021 3022 /* it is a hit */ 3023 gen_tbl_miss = 0; 3024 fdb_write = 1; 3025 } 3026 break; 3027 case BNXT_ULP_GENERIC_TBL_OPC_WRITE: 3028 if (gen_tbl_list->hash_tbl) { 3029 rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list, 3030 &hash_entry, 3031 &gen_tbl_ent); 3032 if (rc) 3033 return rc; 3034 /* store the hash index in the fdb */ 3035 key_index = hash_entry.hash_index; 3036 } 3037 /* check the reference count */ 3038 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { 3039 /* a hit then error */ 3040 BNXT_TF_DBG(ERR, "generic entry already present\n"); 3041 return -EINVAL; /* success */ 3042 } 3043 3044 /* Initialize the blob data */ 3045 if (!ulp_blob_init(&data, tbl->result_bit_size, 3046 gen_tbl_ent.byte_order)) { 3047 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 3048 return -EINVAL; 3049 } 3050 3051 /* Get the result fields list */ 3052 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 3053 "Gen tbl Result"); 3054 if (rc) { 3055 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 3056 return rc; 3057 } 3058 byte_data = ulp_blob_data_get(&data, &tmplen); 3059 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent, 3060 tmplen, byte_data, 3061 ULP_BITS_2_BYTE(tmplen)); 3062 if (rc) { 3063 BNXT_TF_DBG(ERR, "Failed to write generic table\n"); 3064 return -EINVAL; 3065 } 3066 3067 /* increment the reference count */ 3068 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); 3069 fdb_write = 1; 3070 parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index; 3071 break; 3072 default: 3073 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode); 3074 return -EINVAL; 3075 } 3076 3077 /* Set the generic entry hit */ 3078 rc = ulp_regfile_write(parms->regfile, 3079 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, 3080 tfp_cpu_to_be_64(gen_tbl_miss)); 3081 if (rc) { 3082 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 3083 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); 3084 return -EIO; 3085 } 3086 3087 /* add the entry to the flow database */ 3088 if (fdb_write) { 3089 memset(&fid_parms, 0, sizeof(fid_parms)); 3090 fid_parms.direction = tbl->direction; 3091 fid_parms.resource_func = tbl->resource_func; 3092 fid_parms.resource_sub_type = tbl->resource_sub_type; 3093 fid_parms.resource_hndl = key_index; 3094 fid_parms.critical_resource = tbl->critical_resource; 3095 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 3096 3097 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 3098 if (rc) 3099 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc); 3100 } 3101 return rc; 3102 } 3103 3104 static int32_t 3105 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms, 3106 struct bnxt_ulp_mapper_tbl_info *tbl) 3107 { 3108 int32_t rc = 0; 3109 3110 /* process the fdb opcode for alloc push */ 3111 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) { 3112 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl); 3113 if (rc) { 3114 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n"); 3115 return rc; 3116 } 3117 } 3118 return rc; 3119 } 3120 3121 static int32_t 3122 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 3123 struct bnxt_ulp_mapper_data *mapper_data) 3124 { 3125 struct bnxt_ulp_glb_resource_info *glb_res; 3126 uint32_t num_glb_res_ids, idx, dev_id; 3127 uint8_t app_id; 3128 int32_t rc = 0; 3129 3130 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); 3131 if (!glb_res || !num_glb_res_ids) { 3132 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 3133 return -EINVAL; 3134 } 3135 3136 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 3137 if (rc) { 3138 BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n", 3139 rc); 3140 return rc; 3141 } 3142 3143 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 3144 if (rc) { 3145 BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n", 3146 rc); 3147 return rc; 3148 } 3149 3150 /* Iterate the global resources and process each one */ 3151 for (idx = 0; idx < num_glb_res_ids; idx++) { 3152 if (dev_id != glb_res[idx].device_id || 3153 glb_res[idx].app_id != app_id) 3154 continue; 3155 switch (glb_res[idx].resource_func) { 3156 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 3157 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 3158 mapper_data, 3159 &glb_res[idx]); 3160 break; 3161 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 3162 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 3163 mapper_data, 3164 &glb_res[idx]); 3165 break; 3166 default: 3167 BNXT_TF_DBG(ERR, "Global resource %x not supported\n", 3168 glb_res[idx].resource_func); 3169 rc = -EINVAL; 3170 break; 3171 } 3172 if (rc) 3173 return rc; 3174 } 3175 return rc; 3176 } 3177 3178 /* 3179 * Iterate over the shared resources assigned during tf_open_session and store 3180 * them in the global regfile with the shared flag. 3181 */ 3182 static int32_t 3183 ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 3184 struct bnxt_ulp_mapper_data *mapper_data) 3185 { 3186 struct tf_get_shared_tbl_increment_parms iparms; 3187 struct bnxt_ulp_glb_resource_info *glb_res; 3188 struct tf_get_session_info_parms sparms; 3189 uint32_t num_entries, i, dev_id, res; 3190 struct tf_resource_info *res_info; 3191 uint32_t addend; 3192 uint64_t regval; 3193 enum tf_dir dir; 3194 int32_t rc = 0; 3195 struct tf *tfp; 3196 uint8_t app_id; 3197 3198 memset(&sparms, 0, sizeof(sparms)); 3199 glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries); 3200 if (!glb_res || !num_entries) { 3201 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 3202 return -EINVAL; 3203 } 3204 tfp = bnxt_ulp_cntxt_shared_tfp_get(ulp_ctx); 3205 if (!tfp) { 3206 BNXT_TF_DBG(ERR, "Failed to get tfp for app global init"); 3207 return -EINVAL; 3208 } 3209 /* 3210 * Retrieve the resources that were assigned during the shared session 3211 * creation. 3212 */ 3213 rc = tf_get_session_info(tfp, &sparms); 3214 if (rc) { 3215 BNXT_TF_DBG(ERR, "Failed to get session info (%d)\n", rc); 3216 return rc; 3217 } 3218 3219 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 3220 if (rc) { 3221 BNXT_TF_DBG(ERR, "Failed to get the app id in glb init (%d).\n", 3222 rc); 3223 return rc; 3224 } 3225 3226 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 3227 if (rc) { 3228 BNXT_TF_DBG(ERR, "Failed to get dev id for app glb init (%d)\n", 3229 rc); 3230 return rc; 3231 } 3232 3233 /* Store all the app global resources */ 3234 for (i = 0; i < num_entries; i++) { 3235 if (dev_id != glb_res[i].device_id || 3236 app_id != glb_res[i].app_id) 3237 continue; 3238 dir = glb_res[i].direction; 3239 res = glb_res[i].resource_type; 3240 addend = 1; 3241 3242 switch (glb_res[i].resource_func) { 3243 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 3244 res_info = &sparms.session_info.ident[dir].info[res]; 3245 break; 3246 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 3247 /* 3248 * Tables may have various strides for the allocations. 3249 * Need to account. 3250 */ 3251 memset(&iparms, 0, sizeof(iparms)); 3252 iparms.dir = dir; 3253 iparms.type = res; 3254 rc = tf_get_shared_tbl_increment(tfp, &iparms); 3255 if (rc) { 3256 BNXT_TF_DBG(ERR, 3257 "Failed to get addend for %s[%s] rc=(%d)\n", 3258 tf_tbl_type_2_str(res), 3259 tf_dir_2_str(dir), rc); 3260 return rc; 3261 } 3262 addend = iparms.increment_cnt; 3263 res_info = &sparms.session_info.tbl[dir].info[res]; 3264 break; 3265 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 3266 res_info = &sparms.session_info.tcam[dir].info[res]; 3267 break; 3268 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 3269 res_info = &sparms.session_info.em[dir].info[res]; 3270 break; 3271 default: 3272 BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n", 3273 glb_res[i].resource_func); 3274 continue; 3275 } 3276 regval = tfp_cpu_to_be_64((uint64_t)res_info->start); 3277 res_info->start += addend; 3278 /* 3279 * All resources written to the global regfile are shared for 3280 * this function. 3281 */ 3282 rc = ulp_mapper_glb_resource_write(mapper_data, &glb_res[i], 3283 regval, true); 3284 if (rc) 3285 return rc; 3286 } 3287 3288 return rc; 3289 } 3290 3291 /* 3292 * Common conditional opcode process routine that is used for both the template 3293 * rejection and table conditional execution. 3294 */ 3295 static int32_t 3296 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms, 3297 enum bnxt_ulp_cond_opc opc, 3298 uint32_t operand, 3299 int32_t *res) 3300 { 3301 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT; 3302 int32_t rc = 0; 3303 uint8_t bit; 3304 uint64_t regval; 3305 3306 switch (opc) { 3307 case BNXT_ULP_COND_OPC_CF_IS_SET: 3308 if (operand < BNXT_ULP_CF_IDX_LAST) { 3309 *res = ULP_COMP_FLD_IDX_RD(parms, operand); 3310 } else { 3311 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", 3312 operand); 3313 rc = -EINVAL; 3314 } 3315 break; 3316 case BNXT_ULP_COND_OPC_CF_NOT_SET: 3317 if (operand < BNXT_ULP_CF_IDX_LAST) { 3318 *res = !ULP_COMP_FLD_IDX_RD(parms, operand); 3319 } else { 3320 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", 3321 operand); 3322 rc = -EINVAL; 3323 } 3324 break; 3325 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET: 3326 if (operand < BNXT_ULP_ACT_BIT_LAST) { 3327 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits, 3328 operand); 3329 } else { 3330 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", 3331 operand); 3332 rc = -EINVAL; 3333 } 3334 break; 3335 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET: 3336 if (operand < BNXT_ULP_ACT_BIT_LAST) { 3337 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits, 3338 operand); 3339 } else { 3340 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", 3341 operand); 3342 rc = -EINVAL; 3343 } 3344 break; 3345 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET: 3346 if (operand < BNXT_ULP_HDR_BIT_LAST) { 3347 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 3348 operand); 3349 } else { 3350 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 3351 operand); 3352 rc = -EINVAL; 3353 } 3354 break; 3355 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET: 3356 if (operand < BNXT_ULP_HDR_BIT_LAST) { 3357 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 3358 operand); 3359 } else { 3360 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 3361 operand); 3362 rc = -EINVAL; 3363 } 3364 break; 3365 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET: 3366 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3367 if (rc) { 3368 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 3369 operand); 3370 return -EINVAL; 3371 } 3372 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 3373 break; 3374 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET: 3375 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3376 if (rc) { 3377 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 3378 operand); 3379 return -EINVAL; 3380 } 3381 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 3382 break; 3383 case BNXT_ULP_COND_OPC_RF_IS_SET: 3384 if (!ulp_regfile_read(parms->regfile, operand, ®val)) { 3385 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); 3386 return -EINVAL; 3387 } 3388 *res = regval != 0; 3389 break; 3390 case BNXT_ULP_COND_OPC_RF_NOT_SET: 3391 if (!ulp_regfile_read(parms->regfile, operand, ®val)) { 3392 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); 3393 return -EINVAL; 3394 } 3395 *res = regval == 0; 3396 break; 3397 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH: 3398 *res = parms->flow_pattern_id == operand; 3399 break; 3400 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH: 3401 *res = parms->act_pattern_id == operand; 3402 break; 3403 case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET: 3404 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) { 3405 BNXT_TF_DBG(ERR, "Failed to get the mem type\n"); 3406 return -EINVAL; 3407 } 3408 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1; 3409 break; 3410 case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET: 3411 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) { 3412 BNXT_TF_DBG(ERR, "Failed to get the mem type\n"); 3413 return -EINVAL; 3414 } 3415 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0; 3416 break; 3417 case BNXT_ULP_COND_OPC_ENC_HDR_BIT_IS_SET: 3418 if (operand < BNXT_ULP_HDR_BIT_LAST) { 3419 *res = ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, 3420 operand); 3421 } else { 3422 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 3423 operand); 3424 rc = -EINVAL; 3425 } 3426 break; 3427 case BNXT_ULP_COND_OPC_ENC_HDR_BIT_NOT_SET: 3428 if (operand < BNXT_ULP_HDR_BIT_LAST) { 3429 *res = !ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, 3430 operand); 3431 } else { 3432 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 3433 operand); 3434 rc = -EINVAL; 3435 } 3436 break; 3437 default: 3438 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc); 3439 rc = -EINVAL; 3440 break; 3441 } 3442 return (rc); 3443 } 3444 3445 static int32_t 3446 ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms, 3447 enum tf_dir dir, 3448 enum bnxt_ulp_func_src func_src, 3449 uint16_t func_opr, 3450 uint64_t *result) 3451 { 3452 uint64_t regval; 3453 bool shared; 3454 3455 *result = false; 3456 switch (func_src) { 3457 case BNXT_ULP_FUNC_SRC_COMP_FIELD: 3458 if (func_opr >= BNXT_ULP_CF_IDX_LAST) { 3459 BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr); 3460 return -EINVAL; 3461 } 3462 *result = ULP_COMP_FLD_IDX_RD(parms, func_opr); 3463 break; 3464 case BNXT_ULP_FUNC_SRC_REGFILE: 3465 if (!ulp_regfile_read(parms->regfile, func_opr, ®val)) { 3466 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr); 3467 return -EINVAL; 3468 } 3469 *result = tfp_be_to_cpu_64(regval); 3470 break; 3471 case BNXT_ULP_FUNC_SRC_GLB_REGFILE: 3472 if (ulp_mapper_glb_resource_read(parms->mapper_data, dir, 3473 func_opr, ®val, &shared)) { 3474 BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n", 3475 func_opr); 3476 return -EINVAL; 3477 } 3478 *result = tfp_be_to_cpu_64(regval); 3479 break; 3480 case BNXT_ULP_FUNC_SRC_CONST: 3481 *result = func_opr; 3482 break; 3483 default: 3484 BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src); 3485 return -EINVAL; 3486 } 3487 return 0; 3488 } 3489 3490 static int32_t 3491 ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms, 3492 struct bnxt_ulp_mapper_tbl_info *tbl) 3493 { 3494 struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info; 3495 uint64_t res = 0, res1 = 0, res2 = 0; 3496 int32_t rc = 0; 3497 uint32_t process_src1 = 0, process_src2 = 0; 3498 3499 /* determine which functional operands to compute */ 3500 switch (func_info->func_opc) { 3501 case BNXT_ULP_FUNC_OPC_NOP: 3502 return rc; 3503 case BNXT_ULP_FUNC_OPC_EQ: 3504 case BNXT_ULP_FUNC_OPC_NE: 3505 case BNXT_ULP_FUNC_OPC_GE: 3506 case BNXT_ULP_FUNC_OPC_GT: 3507 case BNXT_ULP_FUNC_OPC_LE: 3508 case BNXT_ULP_FUNC_OPC_LT: 3509 process_src1 = 1; 3510 process_src2 = 1; 3511 break; 3512 case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: 3513 process_src1 = 1; 3514 break; 3515 default: 3516 break; 3517 } 3518 3519 if (process_src1) { 3520 rc = ulp_mapper_func_opr_compute(parms, tbl->direction, 3521 func_info->func_src1, 3522 func_info->func_opr1, &res1); 3523 if (rc) 3524 return rc; 3525 } 3526 3527 if (process_src2) { 3528 rc = ulp_mapper_func_opr_compute(parms, tbl->direction, 3529 func_info->func_src2, 3530 func_info->func_opr2, &res2); 3531 if (rc) 3532 return rc; 3533 } 3534 3535 /* perform the functional opcode operations */ 3536 switch (func_info->func_opc) { 3537 case BNXT_ULP_FUNC_OPC_EQ: 3538 if (res1 == res2) 3539 res = 1; 3540 break; 3541 case BNXT_ULP_FUNC_OPC_NE: 3542 if (res1 != res2) 3543 res = 1; 3544 break; 3545 case BNXT_ULP_FUNC_OPC_GE: 3546 if (res1 >= res2) 3547 res = 1; 3548 break; 3549 case BNXT_ULP_FUNC_OPC_GT: 3550 if (res1 > res2) 3551 res = 1; 3552 break; 3553 case BNXT_ULP_FUNC_OPC_LE: 3554 if (res1 <= res2) 3555 res = 1; 3556 break; 3557 case BNXT_ULP_FUNC_OPC_LT: 3558 if (res1 < res2) 3559 res = 1; 3560 break; 3561 case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: 3562 res = res1; 3563 break; 3564 case BNXT_ULP_FUNC_OPC_RSS_CONFIG: 3565 /* apply the rss config using pmd method */ 3566 return bnxt_rss_config_action_apply(parms); 3567 case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR: 3568 rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res); 3569 if (rc) 3570 return -EINVAL; 3571 res = tfp_be_to_cpu_64(res); 3572 break; 3573 default: 3574 BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc); 3575 return -EINVAL; 3576 } 3577 if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr, 3578 tfp_cpu_to_be_64(res))) { 3579 BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n", 3580 func_info->func_dst_opr); 3581 return -EINVAL; 3582 } 3583 3584 return rc; 3585 } 3586 3587 /* 3588 * Processes a list of conditions and returns both a status and result of the 3589 * list. The status must be checked prior to verifying the result. 3590 * 3591 * returns 0 for success, negative on failure 3592 * returns res = 1 for true, res = 0 for false. 3593 */ 3594 static int32_t 3595 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms, 3596 enum bnxt_ulp_cond_list_opc list_opc, 3597 struct bnxt_ulp_mapper_cond_info *list, 3598 uint32_t num, 3599 int32_t *res) 3600 { 3601 uint32_t i; 3602 int32_t rc = 0, trc = 0; 3603 3604 switch (list_opc) { 3605 case BNXT_ULP_COND_LIST_OPC_AND: 3606 /* AND Defaults to true. */ 3607 *res = 1; 3608 break; 3609 case BNXT_ULP_COND_LIST_OPC_OR: 3610 /* OR Defaults to false. */ 3611 *res = 0; 3612 break; 3613 case BNXT_ULP_COND_LIST_OPC_TRUE: 3614 *res = 1; 3615 return rc; 3616 case BNXT_ULP_COND_LIST_OPC_FALSE: 3617 *res = 0; 3618 return rc; 3619 default: 3620 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n", 3621 list_opc); 3622 *res = 0; 3623 return -EINVAL; 3624 } 3625 3626 for (i = 0; i < num; i++) { 3627 rc = ulp_mapper_cond_opc_process(parms, 3628 list[i].cond_opcode, 3629 list[i].cond_operand, 3630 &trc); 3631 if (rc) 3632 return rc; 3633 3634 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) { 3635 /* early return if result is ever zero */ 3636 if (!trc) { 3637 *res = trc; 3638 return rc; 3639 } 3640 } else { 3641 /* early return if result is ever non-zero */ 3642 if (trc) { 3643 *res = trc; 3644 return rc; 3645 } 3646 } 3647 } 3648 3649 return rc; 3650 } 3651 3652 /* 3653 * Processes conflict resolution and returns both a status and result. 3654 * The status must be checked prior to verifying the result. 3655 * 3656 * returns 0 for success, negative on failure 3657 * returns res = 1 for true, res = 0 for false. 3658 */ 3659 static int32_t 3660 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms, 3661 struct bnxt_ulp_mapper_tbl_info *tbl, 3662 int32_t *res) 3663 { 3664 int32_t rc = 0; 3665 uint64_t regval; 3666 uint64_t comp_sig; 3667 3668 *res = 0; 3669 switch (tbl->accept_opcode) { 3670 case BNXT_ULP_ACCEPT_OPC_ALWAYS: 3671 *res = 1; 3672 break; 3673 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH: 3674 /* perform the signature validation*/ 3675 if (tbl->resource_func == 3676 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) { 3677 /* Perform the check that generic table is hit or not */ 3678 if (!ulp_regfile_read(parms->regfile, 3679 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, 3680 ®val)) { 3681 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 3682 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); 3683 return -EINVAL; 3684 } 3685 if (regval) { 3686 /* not a hit so no need to check flow sign*/ 3687 *res = 1; 3688 return rc; 3689 } 3690 } 3691 /* compare the new flow signature against stored one */ 3692 if (!ulp_regfile_read(parms->regfile, 3693 BNXT_ULP_RF_IDX_FLOW_SIG_ID, 3694 ®val)) { 3695 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 3696 BNXT_ULP_RF_IDX_FLOW_SIG_ID); 3697 return -EINVAL; 3698 } 3699 comp_sig = ULP_COMP_FLD_IDX_RD(parms, 3700 BNXT_ULP_CF_IDX_FLOW_SIG_ID); 3701 regval = tfp_be_to_cpu_64(regval); 3702 if (comp_sig == regval) 3703 *res = 1; 3704 else 3705 BNXT_TF_DBG(ERR, "failed signature match 0x%016" 3706 PRIX64 ":%x\n", comp_sig, (uint32_t)regval); 3707 break; 3708 default: 3709 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n", 3710 tbl->accept_opcode); 3711 return -EINVAL; 3712 } 3713 return rc; 3714 } 3715 3716 static int32_t 3717 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid) 3718 { 3719 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL; 3720 enum bnxt_ulp_cond_list_opc cond_opc; 3721 struct bnxt_ulp_mapper_tbl_info *tbls; 3722 struct bnxt_ulp_mapper_tbl_info *tbl; 3723 uint32_t num_tbls, tbl_idx, num_cond_tbls; 3724 int32_t rc = -EINVAL, cond_rc = 0; 3725 int32_t cond_goto = 1; 3726 3727 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid, 3728 &num_cond_tbls, 3729 &cond_opc); 3730 /* 3731 * Process the reject list if exists, otherwise assume that the 3732 * template is allowed. 3733 */ 3734 if (cond_tbls && num_cond_tbls) { 3735 rc = ulp_mapper_cond_opc_list_process(parms, 3736 cond_opc, 3737 cond_tbls, 3738 num_cond_tbls, 3739 &cond_rc); 3740 if (rc) 3741 return rc; 3742 3743 /* Reject the template if True */ 3744 if (cond_rc) { 3745 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n", 3746 ulp_mapper_tmpl_name_str(parms->tmpl_type), 3747 tid); 3748 return -EINVAL; 3749 } 3750 } 3751 3752 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls); 3753 if (!tbls || !num_tbls) { 3754 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n", 3755 ulp_mapper_tmpl_name_str(parms->tmpl_type), 3756 parms->dev_id, tid); 3757 return -EINVAL; 3758 } 3759 3760 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) { 3761 tbl = &tbls[tbl_idx]; 3762 cond_goto = tbl->execute_info.cond_true_goto; 3763 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 3764 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 3765 ulp_mapper_table_dump(tbl, tbl_idx); 3766 #endif 3767 #endif 3768 /* Process the conditional func code opcodes */ 3769 if (ulp_mapper_func_info_process(parms, tbl)) { 3770 BNXT_TF_DBG(ERR, "Failed to process cond update\n"); 3771 rc = -EINVAL; 3772 goto error; 3773 } 3774 3775 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl, 3776 &num_cond_tbls, 3777 &cond_opc); 3778 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc, 3779 cond_tbls, num_cond_tbls, 3780 &cond_rc); 3781 if (rc) { 3782 BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n", 3783 rc); 3784 goto error; 3785 } 3786 /* Skip the table if False */ 3787 if (!cond_rc) { 3788 cond_goto = tbl->execute_info.cond_false_goto; 3789 goto next_iteration; 3790 } 3791 3792 switch (tbl->resource_func) { 3793 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 3794 rc = ulp_mapper_tcam_tbl_process(parms, tbl); 3795 break; 3796 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 3797 rc = ulp_mapper_em_tbl_process(parms, tbl); 3798 break; 3799 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 3800 rc = ulp_mapper_index_tbl_process(parms, tbl); 3801 break; 3802 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: 3803 rc = ulp_mapper_if_tbl_process(parms, tbl); 3804 break; 3805 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 3806 rc = ulp_mapper_gen_tbl_process(parms, tbl); 3807 break; 3808 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE: 3809 rc = ulp_mapper_ctrl_tbl_process(parms, tbl); 3810 break; 3811 case BNXT_ULP_RESOURCE_FUNC_INVALID: 3812 rc = 0; 3813 break; 3814 default: 3815 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n", 3816 tbl->resource_func); 3817 rc = -EINVAL; 3818 goto error; 3819 } 3820 3821 if (rc) { 3822 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 3823 tbl->resource_func); 3824 goto error; 3825 } 3826 3827 /* perform the post table process */ 3828 rc = ulp_mapper_conflict_resolution_process(parms, tbl, 3829 &cond_rc); 3830 if (rc || !cond_rc) { 3831 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n"); 3832 rc = -EINVAL; 3833 goto error; 3834 } 3835 next_iteration: 3836 if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) { 3837 BNXT_TF_DBG(ERR, "reject the flow\n"); 3838 rc = -EINVAL; 3839 goto error; 3840 } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) { 3841 uint32_t rf_idx; 3842 uint64_t regval; 3843 3844 /* least significant 16 bits from reg_file index */ 3845 rf_idx = (uint32_t)(cond_goto & 0xFFFF); 3846 if (!ulp_regfile_read(parms->regfile, rf_idx, 3847 ®val)) { 3848 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 3849 rf_idx); 3850 rc = -EINVAL; 3851 goto error; 3852 } 3853 cond_goto = (int32_t)regval; 3854 } 3855 3856 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) { 3857 BNXT_TF_DBG(ERR, "invalid conditional goto %d\n", 3858 cond_goto); 3859 goto error; 3860 } 3861 tbl_idx += cond_goto; 3862 } 3863 3864 return rc; 3865 error: 3866 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n", 3867 ulp_mapper_tmpl_name_str(parms->tmpl_type), 3868 parms->dev_id, tid); 3869 return rc; 3870 } 3871 3872 static int32_t 3873 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 3874 uint32_t fid, 3875 struct ulp_flow_db_res_params *res) 3876 { 3877 struct tf *tfp; 3878 int32_t rc = 0; 3879 3880 if (!res || !ulp) { 3881 BNXT_TF_DBG(ERR, "Unable to free resource\n "); 3882 return -EINVAL; 3883 } 3884 if (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION) 3885 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_YES); 3886 else 3887 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_NO); 3888 if (!tfp) { 3889 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n"); 3890 return -EINVAL; 3891 } 3892 3893 switch (res->resource_func) { 3894 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 3895 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res); 3896 break; 3897 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 3898 rc = ulp_mapper_em_entry_free(ulp, tfp, res); 3899 break; 3900 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 3901 rc = ulp_mapper_index_entry_free(ulp, tfp, res); 3902 break; 3903 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 3904 rc = ulp_mapper_ident_free(ulp, tfp, res); 3905 break; 3906 case BNXT_ULP_RESOURCE_FUNC_HW_FID: 3907 rc = ulp_mapper_mark_free(ulp, res); 3908 break; 3909 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW: 3910 rc = ulp_mapper_parent_flow_free(ulp, fid, res); 3911 break; 3912 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW: 3913 rc = ulp_mapper_child_flow_free(ulp, fid, res); 3914 break; 3915 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 3916 rc = ulp_mapper_gen_tbl_res_free(ulp, res); 3917 break; 3918 default: 3919 break; 3920 } 3921 3922 return rc; 3923 } 3924 3925 int32_t 3926 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, 3927 enum bnxt_ulp_fdb_type flow_type, 3928 uint32_t fid) 3929 { 3930 struct ulp_flow_db_res_params res_parms = { 0 }; 3931 int32_t rc, trc; 3932 3933 if (!ulp_ctx) { 3934 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 3935 return -EINVAL; 3936 } 3937 3938 /* 3939 * Set the critical resource on the first resource del, then iterate 3940 * while status is good 3941 */ 3942 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; 3943 3944 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms); 3945 3946 if (rc) { 3947 /* 3948 * This is unexpected on the first call to resource del. 3949 * It likely means that the flow did not exist in the flow db. 3950 */ 3951 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", 3952 flow_type, fid, rc); 3953 return rc; 3954 } 3955 3956 while (!rc) { 3957 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms); 3958 if (trc) 3959 /* 3960 * On fail, we still need to attempt to free the 3961 * remaining resources. Don't return 3962 */ 3963 BNXT_TF_DBG(ERR, 3964 "Flow[%d][0x%x] Res[%d][0x%016" PRIX64 3965 "] failed rc=%d.\n", 3966 flow_type, fid, res_parms.resource_func, 3967 res_parms.resource_hndl, trc); 3968 3969 /* All subsequent call require the non-critical_resource */ 3970 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 3971 3972 rc = ulp_flow_db_resource_del(ulp_ctx, 3973 flow_type, 3974 fid, 3975 &res_parms); 3976 } 3977 3978 /* Free the Flow ID since we've removed all resources */ 3979 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid); 3980 3981 return rc; 3982 } 3983 3984 static void 3985 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, 3986 struct bnxt_ulp_mapper_data *mapper_data) 3987 { 3988 struct bnxt_ulp_mapper_glb_resource_entry *ent; 3989 struct ulp_flow_db_res_params res; 3990 uint32_t dir, idx; 3991 3992 /* Iterate the global resources and process each one */ 3993 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { 3994 for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) { 3995 ent = &mapper_data->glb_res_tbl[dir][idx]; 3996 if (ent->resource_func == 3997 BNXT_ULP_RESOURCE_FUNC_INVALID || 3998 ent->shared) 3999 continue; 4000 memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); 4001 res.resource_func = ent->resource_func; 4002 res.direction = dir; 4003 res.resource_type = ent->resource_type; 4004 /*convert it from BE to cpu */ 4005 res.resource_hndl = 4006 tfp_be_to_cpu_64(ent->resource_hndl); 4007 ulp_mapper_resource_free(ulp_ctx, 0, &res); 4008 } 4009 } 4010 } 4011 4012 int32_t 4013 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, 4014 enum bnxt_ulp_fdb_type flow_type, 4015 uint32_t fid) 4016 { 4017 int32_t rc; 4018 4019 if (!ulp_ctx) { 4020 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 4021 return -EINVAL; 4022 } 4023 4024 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid); 4025 return rc; 4026 } 4027 4028 /* Function to handle the mapping of the Flow to be compatible 4029 * with the underlying hardware. 4030 */ 4031 int32_t 4032 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 4033 struct bnxt_ulp_mapper_create_parms *cparms) 4034 { 4035 struct bnxt_ulp_mapper_parms parms; 4036 struct ulp_regfile regfile; 4037 int32_t rc = 0, trc; 4038 4039 if (!ulp_ctx || !cparms) 4040 return -EINVAL; 4041 4042 /* Initialize the parms structure */ 4043 memset(&parms, 0, sizeof(parms)); 4044 parms.act_prop = cparms->act_prop; 4045 parms.act_bitmap = cparms->act; 4046 parms.hdr_bitmap = cparms->hdr_bitmap; 4047 parms.enc_hdr_bitmap = cparms->enc_hdr_bitmap; 4048 parms.regfile = ®file; 4049 parms.hdr_field = cparms->hdr_field; 4050 parms.enc_field = cparms->enc_field; 4051 parms.fld_bitmap = cparms->fld_bitmap; 4052 parms.comp_fld = cparms->comp_fld; 4053 parms.ulp_ctx = ulp_ctx; 4054 parms.act_tid = cparms->act_tid; 4055 parms.class_tid = cparms->class_tid; 4056 parms.flow_type = cparms->flow_type; 4057 parms.parent_flow = cparms->parent_flow; 4058 parms.child_flow = cparms->child_flow; 4059 parms.fid = cparms->flow_id; 4060 parms.tun_idx = cparms->tun_idx; 4061 parms.app_priority = cparms->app_priority; 4062 parms.flow_pattern_id = cparms->flow_pattern_id; 4063 parms.act_pattern_id = cparms->act_pattern_id; 4064 parms.app_id = cparms->app_id; 4065 parms.port_id = cparms->port_id; 4066 4067 /* Get the device id from the ulp context */ 4068 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { 4069 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 4070 return -EINVAL; 4071 } 4072 4073 /* Get the device params, it will be used in later processing */ 4074 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 4075 if (!parms.device_params) { 4076 BNXT_TF_DBG(ERR, "No device parms for device id %d\n", 4077 parms.dev_id); 4078 return -EINVAL; 4079 } 4080 4081 /* 4082 * Get the mapper data for dynamic mapper data such as default 4083 * ids. 4084 */ 4085 parms.mapper_data = (struct bnxt_ulp_mapper_data *) 4086 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 4087 if (!parms.mapper_data) { 4088 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 4089 return -EINVAL; 4090 } 4091 4092 /* initialize the registry file for further processing */ 4093 if (!ulp_regfile_init(parms.regfile)) { 4094 BNXT_TF_DBG(ERR, "regfile initialization failed.\n"); 4095 return -EINVAL; 4096 } 4097 4098 /* Process the action template list from the selected action table*/ 4099 if (parms.act_tid) { 4100 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION; 4101 /* Process the action template tables */ 4102 rc = ulp_mapper_tbls_process(&parms, parms.act_tid); 4103 if (rc) 4104 goto flow_error; 4105 cparms->shared_hndl = parms.shared_hndl; 4106 } 4107 4108 if (parms.class_tid) { 4109 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; 4110 4111 /* Process the class template tables.*/ 4112 rc = ulp_mapper_tbls_process(&parms, parms.class_tid); 4113 if (rc) 4114 goto flow_error; 4115 } 4116 4117 /* setup the parent-child details */ 4118 if (parms.parent_flow) { 4119 /* create a parent flow details */ 4120 rc = ulp_flow_db_parent_flow_create(&parms); 4121 if (rc) 4122 goto flow_error; 4123 } else if (parms.child_flow) { 4124 /* create a child flow details */ 4125 rc = ulp_flow_db_child_flow_create(&parms); 4126 if (rc) 4127 goto flow_error; 4128 } 4129 4130 return rc; 4131 4132 flow_error: 4133 /* Free all resources that were allocated during flow creation */ 4134 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type, 4135 parms.fid); 4136 if (trc) 4137 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); 4138 4139 return rc; 4140 } 4141 4142 int32_t 4143 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) 4144 { 4145 struct bnxt_ulp_mapper_data *data; 4146 struct tf *tfp; 4147 int32_t rc; 4148 4149 if (!ulp_ctx) 4150 return -EINVAL; 4151 4152 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 4153 if (!tfp) 4154 return -EINVAL; 4155 4156 data = rte_zmalloc("ulp_mapper_data", 4157 sizeof(struct bnxt_ulp_mapper_data), 0); 4158 if (!data) { 4159 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n"); 4160 return -ENOMEM; 4161 } 4162 4163 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) { 4164 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n"); 4165 /* Don't call deinit since the prof_func wasn't allocated. */ 4166 rte_free(data); 4167 return -ENOMEM; 4168 } 4169 4170 /* Allocate the global resource ids */ 4171 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); 4172 if (rc) { 4173 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n"); 4174 goto error; 4175 } 4176 4177 /* 4178 * Only initialize the app global resources if a shared session was 4179 * created. 4180 */ 4181 if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) { 4182 rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data); 4183 if (rc) { 4184 BNXT_TF_DBG(ERR, "Failed to init app glb resources\n"); 4185 goto error; 4186 } 4187 } 4188 4189 /* Allocate the generic table list */ 4190 rc = ulp_mapper_generic_tbl_list_init(data); 4191 if (rc) { 4192 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n"); 4193 goto error; 4194 } 4195 4196 return 0; 4197 error: 4198 /* Ignore the return code in favor of returning the original error. */ 4199 ulp_mapper_deinit(ulp_ctx); 4200 return rc; 4201 } 4202 4203 void 4204 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) 4205 { 4206 struct bnxt_ulp_mapper_data *data; 4207 struct tf *tfp; 4208 4209 if (!ulp_ctx) { 4210 BNXT_TF_DBG(ERR, 4211 "Failed to acquire ulp context, so data may not be released.\n"); 4212 return; 4213 } 4214 4215 data = (struct bnxt_ulp_mapper_data *) 4216 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 4217 if (!data) { 4218 /* Go ahead and return since there is no allocated data. */ 4219 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n"); 4220 return; 4221 } 4222 4223 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 4224 if (!tfp) { 4225 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); 4226 /* Free the mapper data regardless of errors. */ 4227 goto free_mapper_data; 4228 } 4229 4230 /* Free the global resource info table entries */ 4231 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); 4232 4233 free_mapper_data: 4234 /* Free the generic table */ 4235 (void)ulp_mapper_generic_tbl_list_deinit(data); 4236 4237 rte_free(data); 4238 /* Reset the data pointer within the ulp_ctx. */ 4239 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); 4240 } 4241