1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2020 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_flow_db.h" 18 #include "ulp_mapper.h" 19 #include "tf_util.h" 20 21 static struct bnxt_ulp_glb_resource_info * 22 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries) 23 { 24 if (!num_entries) 25 return NULL; 26 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 27 return ulp_glb_resource_tbl; 28 } 29 30 /* 31 * Read the global resource from the mapper global resource list 32 * 33 * The regval is always returned in big-endian. 34 * 35 * returns 0 on success 36 */ 37 static int32_t 38 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data, 39 enum tf_dir dir, 40 uint16_t idx, 41 uint64_t *regval) 42 { 43 if (!mapper_data || !regval || 44 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_REGFILE_INDEX_LAST) 45 return -EINVAL; 46 47 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl; 48 return 0; 49 } 50 51 /* 52 * Write a global resource to the mapper global resource list 53 * 54 * The regval value must be in big-endian. 55 * 56 * return 0 on success. 57 */ 58 static int32_t 59 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, 60 struct bnxt_ulp_glb_resource_info *res, 61 uint64_t regval) 62 { 63 struct bnxt_ulp_mapper_glb_resource_entry *ent; 64 65 /* validate the arguments */ 66 if (!data || res->direction >= TF_DIR_MAX || 67 res->glb_regfile_index >= BNXT_ULP_GLB_REGFILE_INDEX_LAST) 68 return -EINVAL; 69 70 /* write to the mapper data */ 71 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index]; 72 ent->resource_func = res->resource_func; 73 ent->resource_type = res->resource_type; 74 ent->resource_hndl = regval; 75 return 0; 76 } 77 78 /* 79 * Internal function to allocate identity resource and store it in mapper data. 80 * 81 * returns 0 on success 82 */ 83 static int32_t 84 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx, 85 struct bnxt_ulp_mapper_data *mapper_data, 86 struct bnxt_ulp_glb_resource_info *glb_res) 87 { 88 struct tf_alloc_identifier_parms iparms = { 0 }; 89 struct tf_free_identifier_parms fparms; 90 uint64_t regval; 91 struct tf *tfp; 92 int32_t rc = 0; 93 94 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 95 if (!tfp) 96 return -EINVAL; 97 98 iparms.ident_type = glb_res->resource_type; 99 iparms.dir = glb_res->direction; 100 101 /* Allocate the Identifier using tf api */ 102 rc = tf_alloc_identifier(tfp, &iparms); 103 if (rc) { 104 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", 105 (iparms.dir == TF_DIR_RX) ? "RX" : "TX", 106 iparms.ident_type); 107 return rc; 108 } 109 110 /* entries are stored as big-endian format */ 111 regval = tfp_cpu_to_be_64((uint64_t)iparms.id); 112 /* write to the mapper global resource */ 113 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval); 114 if (rc) { 115 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 116 /* Free the identifier when update failed */ 117 fparms.dir = iparms.dir; 118 fparms.ident_type = iparms.ident_type; 119 fparms.id = iparms.id; 120 tf_free_identifier(tfp, &fparms); 121 return rc; 122 } 123 return rc; 124 } 125 126 /* 127 * Internal function to allocate index tbl resource and store it in mapper data. 128 * 129 * returns 0 on success 130 */ 131 static int32_t 132 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx, 133 struct bnxt_ulp_mapper_data *mapper_data, 134 struct bnxt_ulp_glb_resource_info *glb_res) 135 { 136 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 137 struct tf_free_tbl_entry_parms free_parms = { 0 }; 138 uint64_t regval; 139 struct tf *tfp; 140 uint32_t tbl_scope_id; 141 int32_t rc = 0; 142 143 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 144 if (!tfp) 145 return -EINVAL; 146 147 /* Get the scope id */ 148 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id); 149 if (rc) { 150 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 151 return rc; 152 } 153 154 aparms.type = glb_res->resource_type; 155 aparms.dir = glb_res->direction; 156 aparms.search_enable = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO; 157 aparms.tbl_scope_id = tbl_scope_id; 158 159 /* Allocate the index tbl using tf api */ 160 rc = tf_alloc_tbl_entry(tfp, &aparms); 161 if (rc) { 162 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", 163 (aparms.dir == TF_DIR_RX) ? "RX" : "TX", 164 aparms.type); 165 return rc; 166 } 167 168 /* entries are stored as big-endian format */ 169 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx); 170 /* write to the mapper global resource */ 171 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval); 172 if (rc) { 173 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 174 /* Free the identifier when update failed */ 175 free_parms.dir = aparms.dir; 176 free_parms.type = aparms.type; 177 free_parms.idx = aparms.idx; 178 tf_free_tbl_entry(tfp, &free_parms); 179 return rc; 180 } 181 return rc; 182 } 183 184 /* Retrieve the cache initialization parameters for the tbl_idx */ 185 static struct bnxt_ulp_cache_tbl_params * 186 ulp_mapper_cache_tbl_params_get(uint32_t tbl_idx) 187 { 188 if (tbl_idx >= BNXT_ULP_CACHE_TBL_MAX_SZ) 189 return NULL; 190 191 return &ulp_cache_tbl_params[tbl_idx]; 192 } 193 194 /* Retrieve the global template table */ 195 static uint32_t * 196 ulp_mapper_glb_template_table_get(uint32_t *num_entries) 197 { 198 if (!num_entries) 199 return NULL; 200 *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ; 201 return ulp_glb_template_tbl; 202 } 203 204 /* 205 * Get the size of the action property for a given index. 206 * 207 * idx [in] The index for the action property 208 * 209 * returns the size of the action property. 210 */ 211 static uint32_t 212 ulp_mapper_act_prop_size_get(uint32_t idx) 213 { 214 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) 215 return 0; 216 return ulp_act_prop_map_table[idx]; 217 } 218 219 /* 220 * Get the list of result fields that implement the flow action. 221 * Gets a device dependent list of tables that implement the action template id. 222 * 223 * dev_id [in] The device id of the forwarding element 224 * 225 * tid [in] The action template id that matches the flow 226 * 227 * num_tbls [out] The number of action tables in the returned array 228 * 229 * Returns An array of action tables to implement the flow, or NULL on error. 230 */ 231 static struct bnxt_ulp_mapper_tbl_info * 232 ulp_mapper_action_tbl_list_get(uint32_t dev_id, 233 uint32_t tid, 234 uint32_t *num_tbls) 235 { 236 uint32_t idx; 237 uint32_t tidx; 238 239 if (!num_tbls) { 240 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 241 return NULL; 242 } 243 244 /* template shift and device mask */ 245 tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id); 246 247 /* NOTE: Need to have something from template compiler to help validate 248 * range of dev_id and act_tid 249 */ 250 idx = ulp_act_tmpl_list[tidx].start_tbl_idx; 251 *num_tbls = ulp_act_tmpl_list[tidx].num_tbls; 252 253 return &ulp_act_tbl_list[idx]; 254 } 255 256 /* 257 * Get a list of classifier tables that implement the flow 258 * Gets a device dependent list of tables that implement the class template id 259 * 260 * dev_id [in] The device id of the forwarding element 261 * 262 * tid [in] The template id that matches the flow 263 * 264 * num_tbls [out] The number of classifier tables in the returned array 265 * 266 * fdb_tbl_idx [out] The flow database index Regular or default 267 * 268 * returns An array of classifier tables to implement the flow, or NULL on 269 * error 270 */ 271 static struct bnxt_ulp_mapper_tbl_info * 272 ulp_mapper_class_tbl_list_get(uint32_t dev_id, 273 uint32_t tid, 274 uint32_t *num_tbls, 275 uint32_t *fdb_tbl_idx) 276 { 277 uint32_t idx; 278 uint32_t tidx = ULP_DEVICE_PARAMS_INDEX(tid, dev_id); 279 280 if (!num_tbls) 281 return NULL; 282 283 /* NOTE: Need to have something from template compiler to help validate 284 * range of dev_id and tid 285 */ 286 idx = ulp_class_tmpl_list[tidx].start_tbl_idx; 287 *num_tbls = ulp_class_tmpl_list[tidx].num_tbls; 288 *fdb_tbl_idx = ulp_class_tmpl_list[tidx].flow_db_table_type; 289 return &ulp_class_tbl_list[idx]; 290 } 291 292 /* 293 * Get the list of key fields that implement the flow. 294 * 295 * ctxt [in] The ulp context 296 * 297 * tbl [in] A single table instance to get the key fields from 298 * 299 * num_flds [out] The number of key fields in the returned array 300 * 301 * Returns array of Key fields, or NULL on error. 302 */ 303 static struct bnxt_ulp_mapper_class_key_field_info * 304 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl, 305 uint32_t *num_flds) 306 { 307 uint32_t idx; 308 309 if (!tbl || !num_flds) 310 return NULL; 311 312 idx = tbl->key_start_idx; 313 *num_flds = tbl->key_num_fields; 314 315 /* NOTE: Need template to provide range checking define */ 316 return &ulp_class_key_field_list[idx]; 317 } 318 319 /* 320 * Get the list of data fields that implement the flow. 321 * 322 * ctxt [in] The ulp context 323 * 324 * tbl [in] A single table instance to get the data fields from 325 * 326 * num_flds [out] The number of data fields in the returned array. 327 * 328 * Returns array of data fields, or NULL on error. 329 */ 330 static struct bnxt_ulp_mapper_result_field_info * 331 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl, 332 uint32_t *num_flds, 333 uint32_t *num_encap_flds) 334 { 335 uint32_t idx; 336 337 if (!tbl || !num_flds) 338 return NULL; 339 340 idx = tbl->result_start_idx; 341 *num_flds = tbl->result_num_fields; 342 *num_encap_flds = tbl->encap_num_fields; 343 344 /* NOTE: Need template to provide range checking define */ 345 return &ulp_class_result_field_list[idx]; 346 } 347 348 /* 349 * Get the list of result fields that implement the flow action. 350 * 351 * tbl [in] A single table instance to get the results fields 352 * from num_flds [out] The number of data fields in the returned 353 * array. 354 * 355 * Returns array of data fields, or NULL on error. 356 */ 357 static struct bnxt_ulp_mapper_result_field_info * 358 ulp_mapper_act_result_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl, 359 uint32_t *num_rslt_flds, 360 uint32_t *num_encap_flds) 361 { 362 uint32_t idx; 363 364 if (!tbl || !num_rslt_flds || !num_encap_flds) 365 return NULL; 366 367 idx = tbl->result_start_idx; 368 *num_rslt_flds = tbl->result_num_fields; 369 *num_encap_flds = tbl->encap_num_fields; 370 371 /* NOTE: Need template to provide range checking define */ 372 return &ulp_act_result_field_list[idx]; 373 } 374 375 /* 376 * Get the list of ident fields that implement the flow 377 * 378 * tbl [in] A single table instance to get the ident fields from 379 * 380 * num_flds [out] The number of ident fields in the returned array 381 * 382 * returns array of ident fields, or NULL on error 383 */ 384 static struct bnxt_ulp_mapper_ident_info * 385 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_tbl_info *tbl, 386 uint32_t *num_flds) 387 { 388 uint32_t idx; 389 390 if (!tbl || !num_flds) 391 return NULL; 392 393 idx = tbl->ident_start_idx; 394 *num_flds = tbl->ident_nums; 395 396 /* NOTE: Need template to provide range checking define */ 397 return &ulp_ident_list[idx]; 398 } 399 400 static struct bnxt_ulp_mapper_cache_entry * 401 ulp_mapper_cache_entry_get(struct bnxt_ulp_context *ulp, 402 uint32_t id, 403 uint16_t key) 404 { 405 struct bnxt_ulp_mapper_data *mapper_data; 406 407 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp); 408 if (!mapper_data || id >= BNXT_ULP_CACHE_TBL_MAX_SZ || 409 !mapper_data->cache_tbl[id]) { 410 BNXT_TF_DBG(ERR, "Unable to acquire the cache tbl (%d)\n", id); 411 return NULL; 412 } 413 414 return &mapper_data->cache_tbl[id][key]; 415 } 416 417 /* 418 * Concatenates the tbl_type and tbl_id into a 32bit value for storing in the 419 * resource_type. This is done to conserve memory since both the tbl_type and 420 * tbl_id are 16bit. 421 */ 422 static inline void 423 ulp_mapper_cache_res_type_set(struct ulp_flow_db_res_params *res, 424 uint16_t tbl_type, 425 uint16_t tbl_id) 426 { 427 res->resource_type = tbl_type; 428 res->resource_sub_type = tbl_id; 429 } 430 431 /* Extracts the tbl_type and tbl_id from the 32bit resource type. */ 432 static inline void 433 ulp_mapper_cache_res_type_get(struct ulp_flow_db_res_params *res, 434 uint16_t *tbl_type, 435 uint16_t *tbl_id) 436 { 437 *tbl_type = res->resource_type; 438 *tbl_id = res->resource_sub_type; 439 } 440 441 static int32_t 442 ulp_mapper_cache_entry_free(struct bnxt_ulp_context *ulp, 443 struct tf *tfp, 444 struct ulp_flow_db_res_params *res) 445 { 446 struct bnxt_ulp_mapper_cache_entry *cache_entry; 447 struct tf_free_identifier_parms ident_parms; 448 struct tf_free_tcam_entry_parms tcam_parms; 449 uint16_t table_id, table_type; 450 int32_t rc, trc, i; 451 452 /* 453 * The table id, used for cache, and table_type, used for tcam, are 454 * both encoded within the resource. We must first extract them to 455 * formulate the args for tf calls. 456 */ 457 ulp_mapper_cache_res_type_get(res, &table_type, &table_id); 458 cache_entry = ulp_mapper_cache_entry_get(ulp, table_id, 459 (uint16_t)res->resource_hndl); 460 if (!cache_entry || !cache_entry->ref_count) { 461 BNXT_TF_DBG(ERR, "Cache entry (%d:%d) not valid on free.\n", 462 table_id, (uint16_t)res->resource_hndl); 463 return -EINVAL; 464 } 465 466 /* 467 * See if we need to delete the entry. The tcam and identifiers are all 468 * tracked by the cached entries reference count. All are deleted when 469 * the reference count hit zero. 470 */ 471 cache_entry->ref_count--; 472 if (cache_entry->ref_count) 473 return 0; 474 475 /* 476 * Need to delete the tcam entry and the allocated identifiers. 477 * In the event of a failure, need to try to delete the remaining 478 * resources before returning error. 479 */ 480 tcam_parms.dir = res->direction; 481 tcam_parms.tcam_tbl_type = table_type; 482 tcam_parms.idx = cache_entry->tcam_idx; 483 rc = tf_free_tcam_entry(tfp, &tcam_parms); 484 if (rc) 485 BNXT_TF_DBG(ERR, "Failed to free tcam [%d][%s][0x%04x] rc=%d\n", 486 table_type, 487 (res->direction == TF_DIR_RX) ? "RX" : "TX", 488 tcam_parms.idx, rc); 489 490 /* 491 * Free the identifiers associated with the tcam entry. Entries with 492 * negative one are considered uninitialized. 493 */ 494 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) { 495 if (cache_entry->idents[i] == ULP_IDENTS_INVALID) 496 continue; 497 498 ident_parms.dir = res->direction; 499 ident_parms.ident_type = cache_entry->ident_types[i]; 500 ident_parms.id = cache_entry->idents[i]; 501 trc = tf_free_identifier(tfp, &ident_parms); 502 if (trc) { 503 BNXT_TF_DBG(ERR, "Failed to free identifier " 504 "[%d][%s][0x%04x] rc=%d\n", 505 ident_parms.ident_type, 506 (res->direction == TF_DIR_RX) ? "RX" : "TX", 507 ident_parms.id, trc); 508 rc = trc; 509 } 510 } 511 512 return rc; 513 } 514 515 static inline int32_t 516 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused, 517 struct tf *tfp, 518 struct ulp_flow_db_res_params *res) 519 { 520 struct tf_free_tcam_entry_parms fparms = { 521 .dir = res->direction, 522 .tcam_tbl_type = res->resource_type, 523 .idx = (uint16_t)res->resource_hndl 524 }; 525 526 return tf_free_tcam_entry(tfp, &fparms); 527 } 528 529 static inline int32_t 530 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp, 531 struct tf *tfp, 532 struct ulp_flow_db_res_params *res) 533 { 534 struct tf_free_tbl_entry_parms fparms = { 535 .dir = res->direction, 536 .type = res->resource_type, 537 .idx = (uint32_t)res->resource_hndl 538 }; 539 540 /* 541 * Just get the table scope, it will be ignored if not necessary 542 * by the tf_free_tbl_entry 543 */ 544 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 545 546 return tf_free_tbl_entry(tfp, &fparms); 547 } 548 549 static inline int32_t 550 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp, 551 struct tf *tfp, 552 struct ulp_flow_db_res_params *res) 553 { 554 struct tf_delete_em_entry_parms fparms = { 0 }; 555 int32_t rc; 556 557 fparms.dir = res->direction; 558 if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE) 559 fparms.mem = TF_MEM_EXTERNAL; 560 else 561 fparms.mem = TF_MEM_INTERNAL; 562 fparms.flow_handle = res->resource_hndl; 563 564 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 565 if (rc) { 566 BNXT_TF_DBG(ERR, "Failed to get table scope\n"); 567 return -EINVAL; 568 } 569 570 return tf_delete_em_entry(tfp, &fparms); 571 } 572 573 static inline int32_t 574 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused, 575 struct tf *tfp, 576 struct ulp_flow_db_res_params *res) 577 { 578 struct tf_free_identifier_parms fparms = { 579 .dir = res->direction, 580 .ident_type = res->resource_type, 581 .id = (uint16_t)res->resource_hndl 582 }; 583 584 return tf_free_identifier(tfp, &fparms); 585 } 586 587 static inline int32_t 588 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, 589 struct ulp_flow_db_res_params *res) 590 { 591 return ulp_mark_db_mark_del(ulp, 592 res->resource_type, 593 res->resource_hndl); 594 } 595 596 /* 597 * Process the identifier instruction and either store it in the flow database 598 * or return it in the val (if not NULL) on success. If val is NULL, the 599 * identifier is to be stored in the flow database. 600 */ 601 static int32_t 602 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, 603 struct bnxt_ulp_mapper_tbl_info *tbl, 604 struct bnxt_ulp_mapper_ident_info *ident, 605 uint16_t *val) 606 { 607 struct ulp_flow_db_res_params fid_parms; 608 uint64_t id = 0; 609 int32_t idx; 610 struct tf_alloc_identifier_parms iparms = { 0 }; 611 struct tf_free_identifier_parms free_parms = { 0 }; 612 struct tf *tfp; 613 int rc; 614 615 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 616 if (!tfp) { 617 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 618 return -EINVAL; 619 } 620 621 idx = ident->regfile_idx; 622 623 iparms.ident_type = ident->ident_type; 624 iparms.dir = tbl->direction; 625 626 rc = tf_alloc_identifier(tfp, &iparms); 627 if (rc) { 628 BNXT_TF_DBG(ERR, "Alloc ident %s:%d failed.\n", 629 (iparms.dir == TF_DIR_RX) ? "RX" : "TX", 630 iparms.ident_type); 631 return rc; 632 } 633 634 id = (uint64_t)tfp_cpu_to_be_64(iparms.id); 635 if (!ulp_regfile_write(parms->regfile, idx, id)) { 636 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 637 rc = -EINVAL; 638 /* Need to free the identifier, so goto error */ 639 goto error; 640 } 641 642 /* Link the resource to the flow in the flow db */ 643 if (!val) { 644 memset(&fid_parms, 0, sizeof(fid_parms)); 645 fid_parms.direction = tbl->direction; 646 fid_parms.resource_func = ident->resource_func; 647 fid_parms.resource_type = ident->ident_type; 648 fid_parms.resource_hndl = iparms.id; 649 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 650 651 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 652 parms->tbl_idx, 653 parms->fid, 654 &fid_parms); 655 if (rc) { 656 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 657 rc); 658 /* Need to free the identifier, so goto error */ 659 goto error; 660 } 661 } else { 662 *val = iparms.id; 663 } 664 665 return 0; 666 667 error: 668 /* Need to free the identifier */ 669 free_parms.dir = tbl->direction; 670 free_parms.ident_type = ident->ident_type; 671 free_parms.id = iparms.id; 672 673 (void)tf_free_identifier(tfp, &free_parms); 674 675 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n", 676 ident->description, 677 (tbl->direction == TF_DIR_RX) ? "RX" : "TX"); 678 return rc; 679 } 680 681 /* 682 * Process the identifier instruction and extract it from result blob. 683 * Increment the identifier reference count and store it in the flow database. 684 */ 685 static int32_t 686 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms, 687 struct bnxt_ulp_mapper_tbl_info *tbl, 688 struct bnxt_ulp_mapper_ident_info *ident, 689 struct ulp_blob *res_blob) 690 { 691 struct ulp_flow_db_res_params fid_parms; 692 uint64_t id = 0; 693 uint32_t idx = 0; 694 struct tf_search_identifier_parms sparms = { 0 }; 695 struct tf_free_identifier_parms free_parms = { 0 }; 696 struct tf *tfp; 697 int rc; 698 699 /* Get the tfp from ulp context */ 700 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 701 if (!tfp) { 702 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 703 return -EINVAL; 704 } 705 706 /* Extract the index from the result blob */ 707 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx), 708 ident->ident_bit_pos, ident->ident_bit_size); 709 if (rc) { 710 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n"); 711 return -EIO; 712 } 713 714 /* populate the search params and search identifier shadow table */ 715 sparms.ident_type = ident->ident_type; 716 sparms.dir = tbl->direction; 717 /* convert the idx into cpu format */ 718 sparms.search_id = tfp_be_to_cpu_32(idx); 719 720 /* Search identifier also increase the reference count */ 721 rc = tf_search_identifier(tfp, &sparms); 722 if (rc) { 723 BNXT_TF_DBG(ERR, "Search ident %s:%x failed.\n", 724 tf_dir_2_str(sparms.dir), 725 sparms.search_id); 726 return rc; 727 } 728 BNXT_TF_DBG(INFO, "Search ident %s:%x.success.\n", 729 tf_dir_2_str(sparms.dir), 730 sparms.search_id); 731 732 /* Write it to the regfile */ 733 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id); 734 if (!ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) { 735 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 736 rc = -EINVAL; 737 /* Need to free the identifier, so goto error */ 738 goto error; 739 } 740 741 /* Link the resource to the flow in the flow db */ 742 memset(&fid_parms, 0, sizeof(fid_parms)); 743 fid_parms.direction = tbl->direction; 744 fid_parms.resource_func = ident->resource_func; 745 fid_parms.resource_type = ident->ident_type; 746 fid_parms.resource_hndl = sparms.search_id; 747 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 748 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 749 parms->tbl_idx, 750 parms->fid, 751 &fid_parms); 752 if (rc) { 753 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 754 rc); 755 /* Need to free the identifier, so goto error */ 756 goto error; 757 } 758 759 return 0; 760 761 error: 762 /* Need to free the identifier */ 763 free_parms.dir = tbl->direction; 764 free_parms.ident_type = ident->ident_type; 765 free_parms.id = sparms.search_id; 766 (void)tf_free_identifier(tfp, &free_parms); 767 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n", 768 ident->description, 769 tf_dir_2_str(tbl->direction), sparms.search_id); 770 return rc; 771 } 772 773 static int32_t 774 ulp_mapper_result_field_process(struct bnxt_ulp_mapper_parms *parms, 775 enum tf_dir dir, 776 struct bnxt_ulp_mapper_result_field_info *fld, 777 struct ulp_blob *blob, 778 const char *name) 779 { 780 uint16_t idx, size_idx; 781 uint8_t *val = NULL; 782 uint64_t regval; 783 uint32_t val_size = 0, field_size = 0; 784 uint64_t act_bit; 785 uint8_t act_val[16]; 786 uint64_t hdr_bit; 787 788 switch (fld->result_opcode) { 789 case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT: 790 val = fld->result_operand; 791 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 792 BNXT_TF_DBG(ERR, "%s failed to add field\n", name); 793 return -EINVAL; 794 } 795 break; 796 case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_PROP: 797 if (!ulp_operand_read(fld->result_operand, 798 (uint8_t *)&idx, sizeof(uint16_t))) { 799 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 800 return -EINVAL; 801 } 802 idx = tfp_be_to_cpu_16(idx); 803 804 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 805 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx); 806 return -EINVAL; 807 } 808 val = &parms->act_prop->act_details[idx]; 809 field_size = ulp_mapper_act_prop_size_get(idx); 810 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) { 811 field_size = field_size - 812 ((fld->field_bit_size + 7) / 8); 813 val += field_size; 814 } 815 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 816 BNXT_TF_DBG(ERR, "%s push field failed\n", name); 817 return -EINVAL; 818 } 819 break; 820 case BNXT_ULP_MAPPER_OPC_SET_TO_ACT_BIT: 821 if (!ulp_operand_read(fld->result_operand, 822 (uint8_t *)&act_bit, sizeof(uint64_t))) { 823 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 824 return -EINVAL; 825 } 826 act_bit = tfp_be_to_cpu_64(act_bit); 827 memset(act_val, 0, sizeof(act_val)); 828 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) 829 act_val[0] = 1; 830 if (fld->field_bit_size > ULP_BYTE_2_BITS(sizeof(act_val))) { 831 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name); 832 return -EINVAL; 833 } 834 if (!ulp_blob_push(blob, act_val, fld->field_bit_size)) { 835 BNXT_TF_DBG(ERR, "%s push field failed\n", name); 836 return -EINVAL; 837 } 838 val = act_val; 839 break; 840 case BNXT_ULP_MAPPER_OPC_SET_TO_ENCAP_ACT_PROP_SZ: 841 if (!ulp_operand_read(fld->result_operand, 842 (uint8_t *)&idx, sizeof(uint16_t))) { 843 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 844 return -EINVAL; 845 } 846 idx = tfp_be_to_cpu_16(idx); 847 848 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 849 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx); 850 return -EINVAL; 851 } 852 val = &parms->act_prop->act_details[idx]; 853 854 /* get the size index next */ 855 if (!ulp_operand_read(&fld->result_operand[sizeof(uint16_t)], 856 (uint8_t *)&size_idx, sizeof(uint16_t))) { 857 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 858 return -EINVAL; 859 } 860 size_idx = tfp_be_to_cpu_16(size_idx); 861 862 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 863 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx); 864 return -EINVAL; 865 } 866 memcpy(&val_size, &parms->act_prop->act_details[size_idx], 867 sizeof(uint32_t)); 868 val_size = tfp_be_to_cpu_32(val_size); 869 val_size = ULP_BYTE_2_BITS(val_size); 870 ulp_blob_push_encap(blob, val, val_size); 871 break; 872 case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE: 873 if (!ulp_operand_read(fld->result_operand, 874 (uint8_t *)&idx, sizeof(uint16_t))) { 875 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 876 return -EINVAL; 877 } 878 879 idx = tfp_be_to_cpu_16(idx); 880 /* Uninitialized regfile entries return 0 */ 881 if (!ulp_regfile_read(parms->regfile, idx, ®val)) { 882 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n", 883 name, idx); 884 return -EINVAL; 885 } 886 887 val = ulp_blob_push_64(blob, ®val, fld->field_bit_size); 888 if (!val) { 889 BNXT_TF_DBG(ERR, "%s push field failed\n", name); 890 return -EINVAL; 891 } 892 break; 893 case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE: 894 if (!ulp_operand_read(fld->result_operand, 895 (uint8_t *)&idx, 896 sizeof(uint16_t))) { 897 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 898 return -EINVAL; 899 } 900 idx = tfp_be_to_cpu_16(idx); 901 if (ulp_mapper_glb_resource_read(parms->mapper_data, 902 dir, 903 idx, ®val)) { 904 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", 905 name, idx); 906 return -EINVAL; 907 } 908 val = ulp_blob_push_64(blob, ®val, fld->field_bit_size); 909 if (!val) { 910 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 911 return -EINVAL; 912 } 913 break; 914 case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD: 915 if (!ulp_operand_read(fld->result_operand, 916 (uint8_t *)&idx, 917 sizeof(uint16_t))) { 918 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 919 return -EINVAL; 920 } 921 idx = tfp_be_to_cpu_16(idx); 922 if (idx < BNXT_ULP_CF_IDX_LAST) 923 val = ulp_blob_push_32(blob, &parms->comp_fld[idx], 924 fld->field_bit_size); 925 if (!val) { 926 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 927 return -EINVAL; 928 } 929 break; 930 case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO: 931 if (ulp_blob_pad_push(blob, fld->field_bit_size) < 0) { 932 BNXT_TF_DBG(ERR, "%s too large for blob\n", name); 933 return -EINVAL; 934 } 935 936 break; 937 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST: 938 if (!ulp_operand_read(fld->result_operand, 939 (uint8_t *)&act_bit, sizeof(uint64_t))) { 940 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 941 return -EINVAL; 942 } 943 act_bit = tfp_be_to_cpu_64(act_bit); 944 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { 945 /* Action bit is set so consider operand_true */ 946 if (!ulp_operand_read(fld->result_operand_true, 947 (uint8_t *)&idx, 948 sizeof(uint16_t))) { 949 BNXT_TF_DBG(ERR, "%s operand read failed\n", 950 name); 951 return -EINVAL; 952 } 953 idx = tfp_be_to_cpu_16(idx); 954 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 955 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", 956 name, idx); 957 return -EINVAL; 958 } 959 val = &parms->act_prop->act_details[idx]; 960 field_size = ulp_mapper_act_prop_size_get(idx); 961 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) { 962 field_size = field_size - 963 ((fld->field_bit_size + 7) / 8); 964 val += field_size; 965 } 966 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 967 BNXT_TF_DBG(ERR, "%s push field failed\n", 968 name); 969 return -EINVAL; 970 } 971 } else { 972 /* action bit is not set, use the operand false */ 973 val = fld->result_operand_false; 974 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 975 BNXT_TF_DBG(ERR, "%s failed to add field\n", 976 name); 977 return -EINVAL; 978 } 979 } 980 break; 981 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST: 982 if (!ulp_operand_read(fld->result_operand, 983 (uint8_t *)&act_bit, sizeof(uint64_t))) { 984 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 985 return -EINVAL; 986 } 987 act_bit = tfp_be_to_cpu_64(act_bit); 988 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { 989 /* Action bit is set so consider operand_true */ 990 val = fld->result_operand_true; 991 } else { 992 /* action bit is not set, use the operand false */ 993 val = fld->result_operand_false; 994 } 995 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 996 BNXT_TF_DBG(ERR, "%s failed to add field\n", 997 name); 998 return -EINVAL; 999 } 1000 break; 1001 case BNXT_ULP_MAPPER_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF: 1002 if (!ulp_operand_read(fld->result_operand, 1003 (uint8_t *)&idx, 1004 sizeof(uint16_t))) { 1005 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 1006 return -EINVAL; 1007 } 1008 idx = tfp_be_to_cpu_16(idx); 1009 if (idx >= BNXT_ULP_CF_IDX_LAST) { 1010 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx); 1011 return -EINVAL; 1012 } 1013 /* check if the computed field is set */ 1014 if (ULP_COMP_FLD_IDX_RD(parms, idx)) 1015 val = fld->result_operand_true; 1016 else 1017 val = fld->result_operand_false; 1018 1019 /* read the appropriate computed field */ 1020 if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) { 1021 BNXT_TF_DBG(ERR, "%s val operand read failed\n", name); 1022 return -EINVAL; 1023 } 1024 idx = tfp_be_to_cpu_16(idx); 1025 if (idx >= BNXT_ULP_CF_IDX_LAST) { 1026 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx); 1027 return -EINVAL; 1028 } 1029 val = ulp_blob_push_32(blob, &parms->comp_fld[idx], 1030 fld->field_bit_size); 1031 if (!val) { 1032 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1033 return -EINVAL; 1034 } 1035 break; 1036 case BNXT_ULP_MAPPER_OPC_IF_HDR_BIT_THEN_CONST_ELSE_CONST: 1037 if (!ulp_operand_read(fld->result_operand, 1038 (uint8_t *)&hdr_bit, sizeof(uint64_t))) { 1039 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 1040 return -EINVAL; 1041 } 1042 hdr_bit = tfp_be_to_cpu_64(hdr_bit); 1043 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit)) { 1044 /* Header bit is set so consider operand_true */ 1045 val = fld->result_operand_true; 1046 } else { 1047 /* Header bit is not set, use the operand false */ 1048 val = fld->result_operand_false; 1049 } 1050 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 1051 BNXT_TF_DBG(ERR, "%s failed to add field\n", 1052 name); 1053 return -EINVAL; 1054 } 1055 break; 1056 default: 1057 BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x\n", 1058 fld->result_opcode); 1059 return -EINVAL; 1060 } 1061 return 0; 1062 } 1063 1064 /* Function to alloc action record and set the table. */ 1065 static int32_t 1066 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms, 1067 enum tf_dir dir, 1068 struct bnxt_ulp_mapper_class_key_field_info *f, 1069 struct ulp_blob *blob, 1070 uint8_t is_key, 1071 const char *name) 1072 { 1073 uint64_t val64; 1074 uint16_t idx, bitlen; 1075 uint32_t opcode; 1076 uint8_t *operand; 1077 struct ulp_regfile *regfile = parms->regfile; 1078 uint8_t *val = NULL; 1079 struct bnxt_ulp_mapper_class_key_field_info *fld = f; 1080 uint32_t field_size; 1081 1082 if (is_key) { 1083 operand = fld->spec_operand; 1084 opcode = fld->spec_opcode; 1085 } else { 1086 operand = fld->mask_operand; 1087 opcode = fld->mask_opcode; 1088 } 1089 1090 bitlen = fld->field_bit_size; 1091 1092 switch (opcode) { 1093 case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT: 1094 val = operand; 1095 if (!ulp_blob_push(blob, val, bitlen)) { 1096 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1097 return -EINVAL; 1098 } 1099 break; 1100 case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO: 1101 if (ulp_blob_pad_push(blob, bitlen) < 0) { 1102 BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name); 1103 return -EINVAL; 1104 } 1105 1106 break; 1107 case BNXT_ULP_MAPPER_OPC_SET_TO_HDR_FIELD: 1108 if (!ulp_operand_read(operand, (uint8_t *)&idx, 1109 sizeof(uint16_t))) { 1110 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 1111 return -EINVAL; 1112 } 1113 idx = tfp_be_to_cpu_16(idx); 1114 if (is_key) 1115 val = parms->hdr_field[idx].spec; 1116 else 1117 val = parms->hdr_field[idx].mask; 1118 1119 /* 1120 * Need to account for how much data was pushed to the header 1121 * field vs how much is to be inserted in the key/mask. 1122 */ 1123 field_size = parms->hdr_field[idx].size; 1124 if (bitlen < ULP_BYTE_2_BITS(field_size)) { 1125 field_size = field_size - ((bitlen + 7) / 8); 1126 val += field_size; 1127 } 1128 1129 if (!ulp_blob_push(blob, val, bitlen)) { 1130 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1131 return -EINVAL; 1132 } 1133 break; 1134 case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD: 1135 if (!ulp_operand_read(operand, (uint8_t *)&idx, 1136 sizeof(uint16_t))) { 1137 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 1138 return -EINVAL; 1139 } 1140 idx = tfp_be_to_cpu_16(idx); 1141 if (idx < BNXT_ULP_CF_IDX_LAST) 1142 val = ulp_blob_push_32(blob, &parms->comp_fld[idx], 1143 bitlen); 1144 if (!val) { 1145 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1146 return -EINVAL; 1147 } 1148 break; 1149 case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE: 1150 if (!ulp_operand_read(operand, (uint8_t *)&idx, 1151 sizeof(uint16_t))) { 1152 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 1153 return -EINVAL; 1154 } 1155 idx = tfp_be_to_cpu_16(idx); 1156 1157 if (!ulp_regfile_read(regfile, idx, &val64)) { 1158 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", 1159 name, idx); 1160 return -EINVAL; 1161 } 1162 1163 val = ulp_blob_push_64(blob, &val64, bitlen); 1164 if (!val) { 1165 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1166 return -EINVAL; 1167 } 1168 break; 1169 case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE: 1170 if (!ulp_operand_read(operand, (uint8_t *)&idx, 1171 sizeof(uint16_t))) { 1172 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 1173 return -EINVAL; 1174 } 1175 idx = tfp_be_to_cpu_16(idx); 1176 if (ulp_mapper_glb_resource_read(parms->mapper_data, 1177 dir, 1178 idx, &val64)) { 1179 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", 1180 name, idx); 1181 return -EINVAL; 1182 } 1183 val = ulp_blob_push_64(blob, &val64, bitlen); 1184 if (!val) { 1185 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1186 return -EINVAL; 1187 } 1188 break; 1189 default: 1190 BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n", 1191 opcode); 1192 return -EINVAL; 1193 break; 1194 } 1195 1196 return 0; 1197 } 1198 1199 static int32_t 1200 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, 1201 struct bnxt_ulp_mapper_tbl_info *tbl, 1202 uint64_t flow_id) 1203 { 1204 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode; 1205 struct ulp_flow_db_res_params fid_parms; 1206 uint32_t mark, gfid, mark_flag; 1207 int32_t rc = 0; 1208 1209 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP || 1210 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION && 1211 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1212 BNXT_ULP_ACTION_BIT_MARK))) 1213 return rc; /* no need to perform gfid process */ 1214 1215 /* Get the mark id details from action property */ 1216 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1217 sizeof(mark)); 1218 mark = tfp_be_to_cpu_32(mark); 1219 1220 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid); 1221 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID; 1222 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1223 gfid, mark); 1224 if (rc) { 1225 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1226 return rc; 1227 } 1228 fid_parms.direction = tbl->direction; 1229 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1230 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1231 fid_parms.resource_type = mark_flag; 1232 fid_parms.resource_hndl = gfid; 1233 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1234 parms->tbl_idx, 1235 parms->fid, 1236 &fid_parms); 1237 if (rc) 1238 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1239 return rc; 1240 } 1241 1242 static int32_t 1243 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, 1244 struct bnxt_ulp_mapper_tbl_info *tbl) 1245 { 1246 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode; 1247 struct ulp_flow_db_res_params fid_parms; 1248 uint32_t act_idx, mark, mark_flag; 1249 uint64_t val64; 1250 int32_t rc = 0; 1251 1252 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP || 1253 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION && 1254 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1255 BNXT_ULP_ACTION_BIT_MARK))) 1256 return rc; /* no need to perform mark action process */ 1257 1258 /* Get the mark id details from action property */ 1259 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1260 sizeof(mark)); 1261 mark = tfp_be_to_cpu_32(mark); 1262 1263 if (!ulp_regfile_read(parms->regfile, 1264 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR, 1265 &val64)) { 1266 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1267 return -EINVAL; 1268 } 1269 act_idx = tfp_be_to_cpu_64(val64); 1270 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID; 1271 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1272 act_idx, mark); 1273 if (rc) { 1274 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1275 return rc; 1276 } 1277 fid_parms.direction = tbl->direction; 1278 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1279 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1280 fid_parms.resource_type = mark_flag; 1281 fid_parms.resource_hndl = act_idx; 1282 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1283 parms->tbl_idx, 1284 parms->fid, 1285 &fid_parms); 1286 if (rc) 1287 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1288 return rc; 1289 } 1290 1291 static int32_t 1292 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms, 1293 struct bnxt_ulp_mapper_tbl_info *tbl) 1294 { 1295 struct ulp_flow_db_res_params fid_parms; 1296 uint32_t act_idx, mark, mark_flag; 1297 uint64_t val64; 1298 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode; 1299 int32_t rc = 0; 1300 1301 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP || 1302 mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION) 1303 return rc; /* no need to perform mark action process */ 1304 1305 /* Get the mark id details from the computed field of dev port id */ 1306 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID); 1307 1308 /* Get the main action pointer */ 1309 if (!ulp_regfile_read(parms->regfile, 1310 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR, 1311 &val64)) { 1312 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1313 return -EINVAL; 1314 } 1315 act_idx = tfp_be_to_cpu_64(val64); 1316 1317 /* Set the mark flag to local fid and vfr flag */ 1318 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; 1319 1320 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1321 act_idx, mark); 1322 if (rc) { 1323 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1324 return rc; 1325 } 1326 fid_parms.direction = tbl->direction; 1327 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1328 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1329 fid_parms.resource_type = mark_flag; 1330 fid_parms.resource_hndl = act_idx; 1331 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1332 parms->tbl_idx, 1333 parms->fid, 1334 &fid_parms); 1335 if (rc) 1336 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1337 return rc; 1338 } 1339 1340 /* 1341 * Tcam table - create the result blob. 1342 * data [out] - the result blob data 1343 */ 1344 static int32_t 1345 ulp_mapper_tcam_tbl_result_create(struct bnxt_ulp_mapper_parms *parms, 1346 struct bnxt_ulp_mapper_tbl_info *tbl, 1347 struct ulp_blob *data) 1348 { 1349 struct bnxt_ulp_mapper_result_field_info *dflds; 1350 uint32_t num_dflds; 1351 uint32_t encap_flds = 0; 1352 uint32_t i; 1353 int32_t rc = 0; 1354 1355 /* Create the result data blob */ 1356 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds, 1357 &encap_flds); 1358 if (!dflds || !num_dflds || encap_flds) { 1359 BNXT_TF_DBG(ERR, "Failed to get data fields.\n"); 1360 return -EINVAL; 1361 } 1362 1363 for (i = 0; i < num_dflds; i++) { 1364 rc = ulp_mapper_result_field_process(parms, 1365 tbl->direction, 1366 &dflds[i], 1367 data, 1368 "TCAM Result"); 1369 if (rc) { 1370 BNXT_TF_DBG(ERR, "Failed to set data fields\n"); 1371 return -EINVAL; 1372 } 1373 } 1374 return rc; 1375 } 1376 1377 /* Tcam table scan the identifier list and allocate each identifier */ 1378 static int32_t 1379 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms, 1380 struct bnxt_ulp_mapper_tbl_info *tbl) 1381 { 1382 struct bnxt_ulp_mapper_ident_info *idents; 1383 uint32_t num_idents; 1384 uint32_t i; 1385 1386 /* 1387 * Since the cache entry is responsible for allocating 1388 * identifiers when in use, allocate the identifiers only 1389 * during normal processing. 1390 */ 1391 if (parms->tcam_tbl_opc == 1392 BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) { 1393 idents = ulp_mapper_ident_fields_get(tbl, &num_idents); 1394 1395 for (i = 0; i < num_idents; i++) { 1396 if (ulp_mapper_ident_process(parms, tbl, 1397 &idents[i], NULL)) 1398 return -EINVAL; 1399 } 1400 } 1401 return 0; 1402 } 1403 1404 /* 1405 * Tcam table scan the identifier list and extract the identifier from 1406 * the result blob. 1407 */ 1408 static int32_t 1409 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms, 1410 struct bnxt_ulp_mapper_tbl_info *tbl, 1411 struct ulp_blob *data) 1412 { 1413 struct bnxt_ulp_mapper_ident_info *idents; 1414 uint32_t num_idents = 0, i; 1415 int32_t rc = 0; 1416 1417 /* 1418 * Extract the listed identifiers from the result field, 1419 * no need to allocate them. 1420 */ 1421 idents = ulp_mapper_ident_fields_get(tbl, &num_idents); 1422 for (i = 0; i < num_idents; i++) { 1423 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data); 1424 if (rc) { 1425 BNXT_TF_DBG(ERR, "Error in identifier extraction\n"); 1426 return rc; 1427 } 1428 } 1429 return rc; 1430 } 1431 1432 /* Internal function to write the tcam entry */ 1433 static int32_t 1434 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms, 1435 struct bnxt_ulp_mapper_tbl_info *tbl, 1436 struct ulp_blob *key, 1437 struct ulp_blob *mask, 1438 struct ulp_blob *data, 1439 uint16_t idx) 1440 { 1441 struct tf_set_tcam_entry_parms sparms = { 0 }; 1442 struct tf *tfp; 1443 uint16_t tmplen; 1444 int32_t rc; 1445 1446 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1447 if (!tfp) { 1448 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1449 return -EINVAL; 1450 } 1451 1452 sparms.dir = tbl->direction; 1453 sparms.tcam_tbl_type = tbl->resource_type; 1454 sparms.idx = idx; 1455 /* Already verified the key/mask lengths */ 1456 sparms.key = ulp_blob_data_get(key, &tmplen); 1457 sparms.mask = ulp_blob_data_get(mask, &tmplen); 1458 sparms.key_sz_in_bits = tbl->key_bit_size; 1459 sparms.result = ulp_blob_data_get(data, &tmplen); 1460 1461 if (tbl->result_bit_size != tmplen) { 1462 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n", 1463 tmplen, tbl->result_bit_size); 1464 return -EINVAL; 1465 } 1466 sparms.result_sz_in_bits = tbl->result_bit_size; 1467 if (tf_set_tcam_entry(tfp, &sparms)) { 1468 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n", 1469 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 1470 tf_dir_2_str(sparms.dir), sparms.idx); 1471 return -EIO; 1472 } 1473 BNXT_TF_DBG(INFO, "tcam[%s][%s][%x] write success.\n", 1474 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 1475 tf_dir_2_str(sparms.dir), sparms.idx); 1476 1477 /* Update cache with TCAM index if the was cache allocated. */ 1478 if (parms->tcam_tbl_opc == 1479 BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) { 1480 if (!parms->cache_ptr) { 1481 BNXT_TF_DBG(ERR, "Unable to update cache"); 1482 return -EINVAL; 1483 } 1484 parms->cache_ptr->tcam_idx = idx; 1485 } 1486 1487 /* Mark action */ 1488 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1489 if (rc) { 1490 BNXT_TF_DBG(ERR, "failed mark action processing\n"); 1491 return rc; 1492 } 1493 1494 return rc; 1495 } 1496 1497 static int32_t 1498 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1499 struct bnxt_ulp_mapper_tbl_info *tbl) 1500 { 1501 struct bnxt_ulp_mapper_class_key_field_info *kflds; 1502 struct ulp_blob key, mask, data, update_data; 1503 uint32_t i, num_kflds; 1504 struct tf *tfp; 1505 int32_t rc, trc; 1506 struct tf_alloc_tcam_entry_parms aparms = { 0 }; 1507 struct tf_search_tcam_entry_parms searchparms = { 0 }; 1508 struct ulp_flow_db_res_params fid_parms = { 0 }; 1509 struct tf_free_tcam_entry_parms free_parms = { 0 }; 1510 enum bnxt_ulp_search_before_alloc search_flag; 1511 uint32_t hit = 0; 1512 uint16_t tmplen = 0; 1513 uint16_t idx; 1514 1515 /* Skip this if was handled by the cache. */ 1516 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) { 1517 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1518 return 0; 1519 } 1520 1521 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1522 if (!tfp) { 1523 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1524 return -EINVAL; 1525 } 1526 1527 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); 1528 if (!kflds || !num_kflds) { 1529 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1530 return -EINVAL; 1531 } 1532 1533 if (!ulp_blob_init(&key, tbl->key_bit_size, 1534 parms->device_params->byte_order) || 1535 !ulp_blob_init(&mask, tbl->key_bit_size, 1536 parms->device_params->byte_order) || 1537 !ulp_blob_init(&data, tbl->result_bit_size, 1538 parms->device_params->byte_order) || 1539 !ulp_blob_init(&update_data, tbl->result_bit_size, 1540 parms->device_params->byte_order)) { 1541 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1542 return -EINVAL; 1543 } 1544 1545 /* create the key/mask */ 1546 /* 1547 * NOTE: The WC table will require some kind of flag to handle the 1548 * mode bits within the key/mask 1549 */ 1550 for (i = 0; i < num_kflds; i++) { 1551 /* Setup the key */ 1552 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1553 &kflds[i], 1554 &key, 1, "TCAM Key"); 1555 if (rc) { 1556 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 1557 return rc; 1558 } 1559 1560 /* Setup the mask */ 1561 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1562 &kflds[i], 1563 &mask, 0, "TCAM Mask"); 1564 if (rc) { 1565 BNXT_TF_DBG(ERR, "Mask field set failed.\n"); 1566 return rc; 1567 } 1568 } 1569 1570 if (tbl->srch_b4_alloc == BNXT_ULP_SEARCH_BEFORE_ALLOC_NO) { 1571 /* 1572 * No search for re-use is requested, so simply allocate the 1573 * tcam index. 1574 */ 1575 aparms.dir = tbl->direction; 1576 aparms.tcam_tbl_type = tbl->resource_type; 1577 aparms.search_enable = tbl->srch_b4_alloc; 1578 aparms.key_sz_in_bits = tbl->key_bit_size; 1579 aparms.key = ulp_blob_data_get(&key, &tmplen); 1580 if (tbl->key_bit_size != tmplen) { 1581 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n", 1582 tmplen, tbl->key_bit_size); 1583 return -EINVAL; 1584 } 1585 1586 aparms.mask = ulp_blob_data_get(&mask, &tmplen); 1587 if (tbl->key_bit_size != tmplen) { 1588 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n", 1589 tmplen, tbl->key_bit_size); 1590 return -EINVAL; 1591 } 1592 1593 aparms.priority = tbl->priority; 1594 1595 /* 1596 * All failures after this succeeds require the entry to be 1597 * freed. cannot return directly on failure, but needs to goto 1598 * error. 1599 */ 1600 rc = tf_alloc_tcam_entry(tfp, &aparms); 1601 if (rc) { 1602 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); 1603 return rc; 1604 } 1605 idx = aparms.idx; 1606 hit = aparms.hit; 1607 } else { 1608 /* 1609 * Searching before allocation to see if we already have an 1610 * entry. This allows re-use of a constrained resource. 1611 */ 1612 searchparms.dir = tbl->direction; 1613 searchparms.tcam_tbl_type = tbl->resource_type; 1614 searchparms.key = ulp_blob_data_get(&key, &tmplen); 1615 searchparms.key_sz_in_bits = tbl->key_bit_size; 1616 searchparms.mask = ulp_blob_data_get(&mask, &tmplen); 1617 searchparms.priority = tbl->priority; 1618 searchparms.alloc = 1; 1619 searchparms.result = ulp_blob_data_get(&data, &tmplen); 1620 searchparms.result_sz_in_bits = tbl->result_bit_size; 1621 1622 rc = tf_search_tcam_entry(tfp, &searchparms); 1623 if (rc) { 1624 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc); 1625 return rc; 1626 } 1627 1628 /* Successful search, check the result */ 1629 if (searchparms.search_status == REJECT) { 1630 BNXT_TF_DBG(ERR, "tcam alloc rejected\n"); 1631 return -ENOMEM; 1632 } 1633 idx = searchparms.idx; 1634 hit = searchparms.hit; 1635 } 1636 1637 /* if it is miss then it is same as no search before alloc */ 1638 if (!hit) 1639 search_flag = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO; 1640 else 1641 search_flag = tbl->srch_b4_alloc; 1642 1643 switch (search_flag) { 1644 case BNXT_ULP_SEARCH_BEFORE_ALLOC_NO: 1645 /*Scan identifier list, allocate identifier and update regfile*/ 1646 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); 1647 /* Create the result blob */ 1648 if (!rc) 1649 rc = ulp_mapper_tcam_tbl_result_create(parms, tbl, 1650 &data); 1651 /* write the tcam entry */ 1652 if (!rc) 1653 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key, 1654 &mask, &data, idx); 1655 break; 1656 case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_SKIP: 1657 /*Scan identifier list, extract identifier and update regfile*/ 1658 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); 1659 break; 1660 case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_UPDATE: 1661 /*Scan identifier list, extract identifier and update regfile*/ 1662 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); 1663 /* Create the result blob */ 1664 if (!rc) 1665 rc = ulp_mapper_tcam_tbl_result_create(parms, tbl, 1666 &update_data); 1667 /* Update/overwrite the tcam entry */ 1668 if (!rc) 1669 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key, 1670 &mask, 1671 &update_data, idx); 1672 break; 1673 default: 1674 BNXT_TF_DBG(ERR, "invalid search opcode\n"); 1675 rc = -EINVAL; 1676 break; 1677 } 1678 if (rc) 1679 goto error; 1680 1681 /* 1682 * Only link the entry to the flow db in the event that cache was not 1683 * used. 1684 */ 1685 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) { 1686 fid_parms.direction = tbl->direction; 1687 fid_parms.resource_func = tbl->resource_func; 1688 fid_parms.resource_type = tbl->resource_type; 1689 fid_parms.critical_resource = tbl->critical_resource; 1690 fid_parms.resource_hndl = idx; 1691 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1692 parms->tbl_idx, 1693 parms->fid, 1694 &fid_parms); 1695 if (rc) { 1696 BNXT_TF_DBG(ERR, 1697 "Failed to link resource to flow rc = %d\n", 1698 rc); 1699 /* Need to free the identifier, so goto error */ 1700 goto error; 1701 } 1702 } else { 1703 /* 1704 * Reset the tcam table opcode to normal in case the next tcam 1705 * entry does not use cache. 1706 */ 1707 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1708 parms->cache_ptr = NULL; 1709 } 1710 1711 return 0; 1712 error: 1713 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1714 free_parms.dir = tbl->direction; 1715 free_parms.tcam_tbl_type = tbl->resource_type; 1716 free_parms.idx = idx; 1717 trc = tf_free_tcam_entry(tfp, &free_parms); 1718 if (trc) 1719 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", 1720 tbl->resource_type, tbl->direction, idx); 1721 1722 return rc; 1723 } 1724 1725 static int32_t 1726 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1727 struct bnxt_ulp_mapper_tbl_info *tbl) 1728 { 1729 struct bnxt_ulp_mapper_class_key_field_info *kflds; 1730 struct bnxt_ulp_mapper_result_field_info *dflds; 1731 struct ulp_blob key, data; 1732 uint32_t i, num_kflds, num_dflds; 1733 uint16_t tmplen; 1734 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1735 struct ulp_flow_db_res_params fid_parms = { 0 }; 1736 struct tf_insert_em_entry_parms iparms = { 0 }; 1737 struct tf_delete_em_entry_parms free_parms = { 0 }; 1738 int32_t trc; 1739 enum bnxt_ulp_flow_mem_type mtype = parms->device_params->flow_mem_type; 1740 int32_t rc = 0; 1741 uint32_t encap_flds = 0; 1742 1743 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); 1744 if (!kflds || !num_kflds) { 1745 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1746 return -EINVAL; 1747 } 1748 1749 /* Initialize the key/result blobs */ 1750 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, 1751 parms->device_params->byte_order) || 1752 !ulp_blob_init(&data, tbl->result_bit_size, 1753 parms->device_params->byte_order)) { 1754 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1755 return -EINVAL; 1756 } 1757 1758 /* create the key */ 1759 for (i = 0; i < num_kflds; i++) { 1760 /* Setup the key */ 1761 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1762 &kflds[i], 1763 &key, 1, "EM Key"); 1764 if (rc) { 1765 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 1766 return rc; 1767 } 1768 } 1769 1770 /* 1771 * TBD: Normally should process identifiers in case of using recycle or 1772 * loopback. Not supporting recycle for now. 1773 */ 1774 1775 /* Create the result data blob */ 1776 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds, &encap_flds); 1777 if (!dflds || !num_dflds || encap_flds) { 1778 BNXT_TF_DBG(ERR, "Failed to get data fields.\n"); 1779 return -EINVAL; 1780 } 1781 1782 for (i = 0; i < num_dflds; i++) { 1783 struct bnxt_ulp_mapper_result_field_info *fld; 1784 1785 fld = &dflds[i]; 1786 1787 rc = ulp_mapper_result_field_process(parms, 1788 tbl->direction, 1789 fld, 1790 &data, 1791 "EM Result"); 1792 if (rc) { 1793 BNXT_TF_DBG(ERR, "Failed to set data fields.\n"); 1794 return rc; 1795 } 1796 } 1797 1798 /* do the transpose for the internal EM keys */ 1799 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) 1800 ulp_blob_perform_byte_reverse(&key); 1801 1802 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, 1803 &iparms.tbl_scope_id); 1804 if (rc) { 1805 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1806 return rc; 1807 } 1808 1809 /* 1810 * NOTE: the actual blob size will differ from the size in the tbl 1811 * entry due to the padding. 1812 */ 1813 iparms.dup_check = 0; 1814 iparms.dir = tbl->direction; 1815 iparms.mem = tbl->resource_type; 1816 iparms.key = ulp_blob_data_get(&key, &tmplen); 1817 iparms.key_sz_in_bits = tbl->key_bit_size; 1818 iparms.em_record = ulp_blob_data_get(&data, &tmplen); 1819 iparms.em_record_sz_in_bits = tbl->result_bit_size; 1820 1821 rc = tf_insert_em_entry(tfp, &iparms); 1822 if (rc) { 1823 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc); 1824 return rc; 1825 } 1826 1827 /* Mark action process */ 1828 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && 1829 tbl->resource_type == TF_MEM_EXTERNAL) 1830 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); 1831 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && 1832 tbl->resource_type == TF_MEM_INTERNAL) 1833 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1834 if (rc) { 1835 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1836 goto error; 1837 } 1838 1839 /* Link the EM resource to the flow in the flow db */ 1840 memset(&fid_parms, 0, sizeof(fid_parms)); 1841 fid_parms.direction = tbl->direction; 1842 fid_parms.resource_func = tbl->resource_func; 1843 fid_parms.resource_type = tbl->resource_type; 1844 fid_parms.critical_resource = tbl->critical_resource; 1845 fid_parms.resource_hndl = iparms.flow_handle; 1846 1847 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1848 parms->tbl_idx, 1849 parms->fid, 1850 &fid_parms); 1851 if (rc) { 1852 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", 1853 rc); 1854 /* Need to free the identifier, so goto error */ 1855 goto error; 1856 } 1857 1858 return 0; 1859 error: 1860 free_parms.dir = iparms.dir; 1861 free_parms.mem = iparms.mem; 1862 free_parms.tbl_scope_id = iparms.tbl_scope_id; 1863 free_parms.flow_handle = iparms.flow_handle; 1864 1865 trc = tf_delete_em_entry(tfp, &free_parms); 1866 if (trc) 1867 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n"); 1868 1869 return rc; 1870 } 1871 1872 static int32_t 1873 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1874 struct bnxt_ulp_mapper_tbl_info *tbl, 1875 bool is_class_tbl) 1876 { 1877 struct bnxt_ulp_mapper_result_field_info *flds; 1878 struct ulp_flow_db_res_params fid_parms; 1879 struct ulp_blob data; 1880 uint64_t idx = 0; 1881 uint16_t tmplen; 1882 uint32_t i, num_flds, index, hit; 1883 int32_t rc = 0, trc = 0; 1884 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 1885 struct tf_search_tbl_entry_parms srchparms = { 0 }; 1886 struct tf_set_tbl_entry_parms sparms = { 0 }; 1887 struct tf_free_tbl_entry_parms free_parms = { 0 }; 1888 uint32_t tbl_scope_id; 1889 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1890 uint16_t bit_size; 1891 uint32_t encap_flds = 0; 1892 1893 /* Get the scope id first */ 1894 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); 1895 if (rc) { 1896 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1897 return rc; 1898 } 1899 1900 /* use the max size if encap is enabled */ 1901 if (tbl->encap_num_fields) 1902 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 1903 else 1904 bit_size = tbl->result_bit_size; 1905 1906 /* Initialize the blob data */ 1907 if (!ulp_blob_init(&data, bit_size, 1908 parms->device_params->byte_order)) { 1909 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 1910 return -EINVAL; 1911 } 1912 1913 /* Get the result fields list */ 1914 if (is_class_tbl) 1915 flds = ulp_mapper_result_fields_get(tbl, &num_flds, 1916 &encap_flds); 1917 else 1918 flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, 1919 &encap_flds); 1920 1921 if (!flds || (!num_flds && !encap_flds)) { 1922 BNXT_TF_DBG(ERR, "template undefined for the index table\n"); 1923 return -EINVAL; 1924 } 1925 1926 /* process the result fields, loop through them */ 1927 for (i = 0; i < (num_flds + encap_flds); i++) { 1928 /* set the swap index if encap swap bit is enabled */ 1929 if (parms->device_params->encap_byte_swap && encap_flds && 1930 (i == num_flds)) 1931 ulp_blob_encap_swap_idx_set(&data); 1932 1933 /* Process the result fields */ 1934 rc = ulp_mapper_result_field_process(parms, 1935 tbl->direction, 1936 &flds[i], 1937 &data, 1938 "Indexed Result"); 1939 if (rc) { 1940 BNXT_TF_DBG(ERR, "data field failed\n"); 1941 return rc; 1942 } 1943 } 1944 1945 /* if encap bit swap is enabled perform the bit swap */ 1946 if (parms->device_params->encap_byte_swap && encap_flds) { 1947 ulp_blob_perform_encap_swap(&data); 1948 } 1949 1950 /* 1951 * Check for index opcode, if it is Global then 1952 * no need to allocate the table, just set the table 1953 * and exit since it is not maintained in the flow db. 1954 */ 1955 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_GLOBAL) { 1956 /* get the index from index operand */ 1957 if (tbl->index_operand < BNXT_ULP_GLB_REGFILE_INDEX_LAST && 1958 ulp_mapper_glb_resource_read(parms->mapper_data, 1959 tbl->direction, 1960 tbl->index_operand, 1961 &idx)) { 1962 BNXT_TF_DBG(ERR, "Glbl regfile[%d] read failed.\n", 1963 tbl->index_operand); 1964 return -EINVAL; 1965 } 1966 /* set the Tf index table */ 1967 sparms.dir = tbl->direction; 1968 sparms.type = tbl->resource_type; 1969 sparms.data = ulp_blob_data_get(&data, &tmplen); 1970 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 1971 sparms.idx = tfp_be_to_cpu_64(idx); 1972 sparms.tbl_scope_id = tbl_scope_id; 1973 1974 rc = tf_set_tbl_entry(tfp, &sparms); 1975 if (rc) { 1976 BNXT_TF_DBG(ERR, 1977 "Glbl Set table[%d][%s][%d] failed rc=%d\n", 1978 sparms.type, 1979 (sparms.dir == TF_DIR_RX) ? "RX" : "TX", 1980 sparms.idx, 1981 rc); 1982 return rc; 1983 } 1984 return 0; /* success */ 1985 } 1986 1987 index = 0; 1988 hit = 0; 1989 /* Perform the tf table allocation by filling the alloc params */ 1990 if (tbl->srch_b4_alloc) { 1991 memset(&srchparms, 0, sizeof(srchparms)); 1992 srchparms.dir = tbl->direction; 1993 srchparms.type = tbl->resource_type; 1994 srchparms.alloc = 1; 1995 srchparms.result = ulp_blob_data_get(&data, &tmplen); 1996 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 1997 srchparms.tbl_scope_id = tbl_scope_id; 1998 rc = tf_search_tbl_entry(tfp, &srchparms); 1999 if (rc) { 2000 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2001 tf_tbl_type_2_str(tbl->resource_type), 2002 tf_dir_2_str(tbl->direction), rc); 2003 return rc; 2004 } 2005 if (srchparms.search_status == REJECT) { 2006 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n", 2007 tf_tbl_type_2_str(tbl->resource_type), 2008 tf_dir_2_str(tbl->direction)); 2009 return -ENOMEM; 2010 } 2011 index = srchparms.idx; 2012 hit = srchparms.hit; 2013 } else { 2014 aparms.dir = tbl->direction; 2015 aparms.type = tbl->resource_type; 2016 aparms.search_enable = tbl->srch_b4_alloc; 2017 aparms.result = ulp_blob_data_get(&data, &tmplen); 2018 aparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2019 aparms.tbl_scope_id = tbl_scope_id; 2020 2021 /* All failures after the alloc succeeds require a free */ 2022 rc = tf_alloc_tbl_entry(tfp, &aparms); 2023 if (rc) { 2024 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2025 tf_tbl_type_2_str(tbl->resource_type), 2026 tf_dir_2_str(tbl->direction), rc); 2027 return rc; 2028 } 2029 index = aparms.idx; 2030 } 2031 /* 2032 * calculate the idx for the result record, for external EM the offset 2033 * needs to be shifted accordingly. If external non-inline table types 2034 * are used then need to revisit this logic. 2035 */ 2036 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2037 idx = TF_ACT_REC_OFFSET_2_PTR(index); 2038 else 2039 idx = index; 2040 2041 /* Always storing values in Regfile in BE */ 2042 idx = tfp_cpu_to_be_64(idx); 2043 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_ALLOCATE) { 2044 rc = ulp_regfile_write(parms->regfile, tbl->index_operand, idx); 2045 if (!rc) { 2046 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 2047 tbl->index_operand); 2048 goto error; 2049 } 2050 } 2051 2052 /* Perform the tf table set by filling the set params */ 2053 if (!tbl->srch_b4_alloc || !hit) { 2054 sparms.dir = tbl->direction; 2055 sparms.type = tbl->resource_type; 2056 sparms.data = ulp_blob_data_get(&data, &tmplen); 2057 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2058 sparms.idx = index; 2059 sparms.tbl_scope_id = tbl_scope_id; 2060 2061 rc = tf_set_tbl_entry(tfp, &sparms); 2062 if (rc) { 2063 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n", 2064 sparms.type, 2065 (sparms.dir == TF_DIR_RX) ? "RX" : "TX", 2066 sparms.idx, 2067 rc); 2068 goto error; 2069 } 2070 } 2071 2072 /* Link the resource to the flow in the flow db */ 2073 memset(&fid_parms, 0, sizeof(fid_parms)); 2074 fid_parms.direction = tbl->direction; 2075 fid_parms.resource_func = tbl->resource_func; 2076 fid_parms.resource_type = tbl->resource_type; 2077 fid_parms.resource_sub_type = tbl->resource_sub_type; 2078 fid_parms.resource_hndl = index; 2079 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 2080 2081 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 2082 parms->tbl_idx, 2083 parms->fid, 2084 &fid_parms); 2085 if (rc) { 2086 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2087 rc); 2088 goto error; 2089 } 2090 2091 /* Perform the VF rep action */ 2092 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 2093 if (rc) { 2094 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 2095 goto error; 2096 } 2097 return rc; 2098 error: 2099 /* 2100 * Free the allocated resource since we failed to either 2101 * write to the entry or link the flow 2102 */ 2103 free_parms.dir = tbl->direction; 2104 free_parms.type = tbl->resource_type; 2105 free_parms.idx = index; 2106 free_parms.tbl_scope_id = tbl_scope_id; 2107 2108 trc = tf_free_tbl_entry(tfp, &free_parms); 2109 if (trc) 2110 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n"); 2111 2112 return rc; 2113 } 2114 2115 static int32_t 2116 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2117 struct bnxt_ulp_mapper_tbl_info *tbl) 2118 { 2119 struct bnxt_ulp_mapper_class_key_field_info *kflds; 2120 struct bnxt_ulp_mapper_cache_entry *cache_entry; 2121 struct bnxt_ulp_mapper_ident_info *idents; 2122 uint32_t i, num_kflds = 0, num_idents = 0; 2123 struct ulp_flow_db_res_params fid_parms; 2124 struct tf_free_identifier_parms fparms; 2125 uint16_t tmplen, tmp_ident; 2126 struct ulp_blob key; 2127 uint8_t *cache_key; 2128 uint64_t regval; 2129 uint16_t *ckey; 2130 int32_t rc; 2131 2132 /* Get the key fields list and build the key. */ 2133 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); 2134 if (!kflds || !num_kflds) { 2135 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2136 return -EINVAL; 2137 } 2138 if (!ulp_blob_init(&key, tbl->key_bit_size, 2139 parms->device_params->byte_order)) { 2140 BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); 2141 return -EINVAL; 2142 } 2143 for (i = 0; i < num_kflds; i++) { 2144 /* Setup the key */ 2145 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 2146 &kflds[i], 2147 &key, 1, "Cache Key"); 2148 if (rc) { 2149 BNXT_TF_DBG(ERR, 2150 "Failed to create key for Cache rc=%d\n", 2151 rc); 2152 return -EINVAL; 2153 } 2154 } 2155 2156 /* 2157 * Perform the lookup in the cache table with constructed key. The 2158 * cache_key is a byte array of tmplen, it needs to be converted to a 2159 * index for the cache table. 2160 */ 2161 cache_key = ulp_blob_data_get(&key, &tmplen); 2162 ckey = (uint16_t *)cache_key; 2163 2164 /* 2165 * The id computed based on resource sub type and direction where 2166 * dir is the bit0 and rest of the bits come from resource 2167 * sub type. 2168 */ 2169 cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx, 2170 (tbl->resource_sub_type << 1 | 2171 (tbl->direction & 0x1)), 2172 *ckey); 2173 2174 /* 2175 * Get the identifier list for processing by both the hit and miss 2176 * processing. 2177 */ 2178 idents = ulp_mapper_ident_fields_get(tbl, &num_idents); 2179 2180 if (!cache_entry->ref_count) { 2181 /* Initialize the cache entry */ 2182 cache_entry->tcam_idx = 0; 2183 cache_entry->ref_count = 0; 2184 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) 2185 cache_entry->idents[i] = ULP_IDENTS_INVALID; 2186 2187 /* Need to allocate identifiers for storing in the cache. */ 2188 for (i = 0; i < num_idents; i++) { 2189 /* 2190 * Since we are using the cache, the identifier does not 2191 * get added to the flow db. Pass in the pointer to the 2192 * tmp_ident. 2193 */ 2194 rc = ulp_mapper_ident_process(parms, tbl, 2195 &idents[i], &tmp_ident); 2196 if (rc) 2197 goto error; 2198 2199 cache_entry->ident_types[i] = idents[i].ident_type; 2200 cache_entry->idents[i] = tmp_ident; 2201 } 2202 2203 /* Tell the TCAM processor to alloc an entry */ 2204 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC; 2205 /* Store the cache key for use by the tcam process code */ 2206 parms->cache_ptr = cache_entry; 2207 } else { 2208 /* Cache hit, get values from result. */ 2209 for (i = 0; i < num_idents; i++) { 2210 regval = (uint64_t)cache_entry->idents[i]; 2211 if (!ulp_regfile_write(parms->regfile, 2212 idents[i].regfile_idx, 2213 tfp_cpu_to_be_64(regval))) { 2214 BNXT_TF_DBG(ERR, 2215 "Failed to write to regfile\n"); 2216 return -EINVAL; 2217 } 2218 } 2219 /* 2220 * The cached entry is being used, so let the tcam processing 2221 * know not to process this table. 2222 */ 2223 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP; 2224 } 2225 2226 /* Made through the cache processing, increment the reference count. */ 2227 cache_entry->ref_count++; 2228 2229 /* Link the cache to the flow db. */ 2230 memset(&fid_parms, 0, sizeof(fid_parms)); 2231 fid_parms.direction = tbl->direction; 2232 fid_parms.resource_func = tbl->resource_func; 2233 2234 /* 2235 * Cache resource type is composed of table_type, resource 2236 * sub type and direction, it needs to set appropriately via setter. 2237 */ 2238 ulp_mapper_cache_res_type_set(&fid_parms, 2239 tbl->resource_type, 2240 (tbl->resource_sub_type << 1 | 2241 (tbl->direction & 0x1))); 2242 fid_parms.resource_hndl = (uint64_t)*ckey; 2243 fid_parms.critical_resource = tbl->critical_resource; 2244 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 2245 parms->tbl_idx, 2246 parms->fid, 2247 &fid_parms); 2248 if (rc) 2249 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n"); 2250 2251 return rc; 2252 error: 2253 /* 2254 * This error handling only gets called when the idents are being 2255 * allocated for the cache on misses. Using the num_idents that was 2256 * previously set. 2257 */ 2258 for (i = 0; i < num_idents; i++) { 2259 if (cache_entry->idents[i] == ULP_IDENTS_INVALID) 2260 continue; 2261 2262 fparms.dir = tbl->direction; 2263 fparms.ident_type = idents[i].ident_type; 2264 fparms.id = cache_entry->idents[i]; 2265 tf_free_identifier(parms->tfp, &fparms); 2266 } 2267 2268 return rc; 2269 } 2270 2271 static int32_t 2272 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2273 struct bnxt_ulp_mapper_tbl_info *tbl) 2274 { 2275 struct bnxt_ulp_mapper_result_field_info *flds; 2276 struct ulp_blob data; 2277 uint64_t idx; 2278 uint16_t tmplen; 2279 uint32_t i, num_flds; 2280 int32_t rc = 0; 2281 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; 2282 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 2283 uint32_t encap_flds; 2284 2285 /* Initialize the blob data */ 2286 if (!ulp_blob_init(&data, tbl->result_bit_size, 2287 parms->device_params->byte_order)) { 2288 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 2289 return -EINVAL; 2290 } 2291 2292 /* Get the result fields list */ 2293 flds = ulp_mapper_result_fields_get(tbl, &num_flds, &encap_flds); 2294 2295 if (!flds || !num_flds || encap_flds) { 2296 BNXT_TF_DBG(ERR, "template undefined for the IF table\n"); 2297 return -EINVAL; 2298 } 2299 2300 /* process the result fields, loop through them */ 2301 for (i = 0; i < num_flds; i++) { 2302 /* Process the result fields */ 2303 rc = ulp_mapper_result_field_process(parms, 2304 tbl->direction, 2305 &flds[i], 2306 &data, 2307 "IFtable Result"); 2308 if (rc) { 2309 BNXT_TF_DBG(ERR, "data field failed\n"); 2310 return rc; 2311 } 2312 } 2313 2314 /* Get the index details from computed field */ 2315 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_COMP_FIELD) { 2316 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand); 2317 } else if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_CONSTANT) { 2318 idx = tbl->index_operand; 2319 } else { 2320 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); 2321 return -EINVAL; 2322 } 2323 2324 /* Perform the tf table set by filling the set params */ 2325 iftbl_params.dir = tbl->direction; 2326 iftbl_params.type = tbl->resource_type; 2327 iftbl_params.data = ulp_blob_data_get(&data, &tmplen); 2328 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2329 iftbl_params.idx = idx; 2330 2331 rc = tf_set_if_tbl_entry(tfp, &iftbl_params); 2332 if (rc) { 2333 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n", 2334 iftbl_params.type, 2335 (iftbl_params.dir == TF_DIR_RX) ? "RX" : "TX", 2336 iftbl_params.idx, 2337 rc); 2338 return rc; 2339 } 2340 2341 /* 2342 * TBD: Need to look at the need to store idx in flow db for restore 2343 * the table to its original state on deletion of this entry. 2344 */ 2345 return rc; 2346 } 2347 2348 static int32_t 2349 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 2350 struct bnxt_ulp_mapper_data *mapper_data) 2351 { 2352 struct bnxt_ulp_glb_resource_info *glb_res; 2353 uint32_t num_glb_res_ids, idx; 2354 int32_t rc = 0; 2355 2356 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); 2357 if (!glb_res || !num_glb_res_ids) { 2358 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 2359 return -EINVAL; 2360 } 2361 2362 /* Iterate the global resources and process each one */ 2363 for (idx = 0; idx < num_glb_res_ids; idx++) { 2364 switch (glb_res[idx].resource_func) { 2365 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2366 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 2367 mapper_data, 2368 &glb_res[idx]); 2369 break; 2370 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2371 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 2372 mapper_data, 2373 &glb_res[idx]); 2374 break; 2375 default: 2376 BNXT_TF_DBG(ERR, "Global resource %x not supported\n", 2377 glb_res[idx].resource_func); 2378 rc = -EINVAL; 2379 break; 2380 } 2381 if (rc) 2382 return rc; 2383 } 2384 return rc; 2385 } 2386 2387 /* 2388 * Function to process the conditional opcode of the mapper table. 2389 * returns 1 to skip the table. 2390 * return 0 to continue processing the table. 2391 */ 2392 static int32_t 2393 ulp_mapper_tbl_cond_opcode_process(struct bnxt_ulp_mapper_parms *parms, 2394 struct bnxt_ulp_mapper_tbl_info *tbl) 2395 { 2396 int32_t rc = 1; 2397 2398 switch (tbl->cond_opcode) { 2399 case BNXT_ULP_COND_OPCODE_NOP: 2400 rc = 0; 2401 break; 2402 case BNXT_ULP_COND_OPCODE_COMP_FIELD_IS_SET: 2403 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && 2404 ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) 2405 rc = 0; 2406 break; 2407 case BNXT_ULP_COND_OPCODE_ACTION_BIT_IS_SET: 2408 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2409 tbl->cond_operand)) 2410 rc = 0; 2411 break; 2412 case BNXT_ULP_COND_OPCODE_HDR_BIT_IS_SET: 2413 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2414 tbl->cond_operand)) 2415 rc = 0; 2416 break; 2417 case BNXT_ULP_COND_OPCODE_COMP_FIELD_NOT_SET: 2418 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && 2419 !ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) 2420 rc = 0; 2421 break; 2422 case BNXT_ULP_COND_OPCODE_ACTION_BIT_NOT_SET: 2423 if (!ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2424 tbl->cond_operand)) 2425 rc = 0; 2426 break; 2427 case BNXT_ULP_COND_OPCODE_HDR_BIT_NOT_SET: 2428 if (!ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2429 tbl->cond_operand)) 2430 rc = 0; 2431 break; 2432 default: 2433 BNXT_TF_DBG(ERR, 2434 "Invalid arg in mapper tbl for cond opcode\n"); 2435 break; 2436 } 2437 return rc; 2438 } 2439 2440 /* 2441 * Function to process the action template. Iterate through the list 2442 * action info templates and process it. 2443 */ 2444 static int32_t 2445 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms) 2446 { 2447 uint32_t i; 2448 int32_t rc = 0; 2449 struct bnxt_ulp_mapper_tbl_info *tbl; 2450 2451 if (!parms->atbls || !parms->num_atbls) { 2452 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n", 2453 parms->dev_id, parms->act_tid); 2454 return -EINVAL; 2455 } 2456 2457 for (i = 0; i < parms->num_atbls; i++) { 2458 tbl = &parms->atbls[i]; 2459 if (ulp_mapper_tbl_cond_opcode_process(parms, tbl)) 2460 continue; 2461 2462 switch (tbl->resource_func) { 2463 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2464 rc = ulp_mapper_index_tbl_process(parms, tbl, false); 2465 if (rc) { 2466 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 2467 tbl->resource_func); 2468 return rc; 2469 } 2470 break; 2471 default: 2472 BNXT_TF_DBG(ERR, "Unexpected action resource %d\n", 2473 tbl->resource_func); 2474 return -EINVAL; 2475 } 2476 } 2477 2478 return rc; 2479 } 2480 2481 /* Create the classifier table entries for a flow. */ 2482 static int32_t 2483 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms) 2484 { 2485 uint32_t i; 2486 int32_t rc = 0; 2487 2488 if (!parms) 2489 return -EINVAL; 2490 2491 if (!parms->ctbls || !parms->num_ctbls) { 2492 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n", 2493 parms->dev_id, parms->class_tid); 2494 return -EINVAL; 2495 } 2496 2497 for (i = 0; i < parms->num_ctbls; i++) { 2498 struct bnxt_ulp_mapper_tbl_info *tbl = &parms->ctbls[i]; 2499 2500 if (ulp_mapper_tbl_cond_opcode_process(parms, tbl)) 2501 continue; 2502 2503 switch (tbl->resource_func) { 2504 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2505 rc = ulp_mapper_tcam_tbl_process(parms, tbl); 2506 break; 2507 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2508 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2509 rc = ulp_mapper_em_tbl_process(parms, tbl); 2510 break; 2511 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2512 rc = ulp_mapper_index_tbl_process(parms, tbl, true); 2513 break; 2514 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: 2515 rc = ulp_mapper_cache_tbl_process(parms, tbl); 2516 break; 2517 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: 2518 rc = ulp_mapper_if_tbl_process(parms, tbl); 2519 break; 2520 default: 2521 BNXT_TF_DBG(ERR, "Unexpected class resource %d\n", 2522 tbl->resource_func); 2523 return -EINVAL; 2524 } 2525 2526 if (rc) { 2527 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 2528 tbl->resource_func); 2529 return rc; 2530 } 2531 } 2532 2533 return rc; 2534 } 2535 2536 static int32_t 2537 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 2538 struct ulp_flow_db_res_params *res) 2539 { 2540 struct tf *tfp; 2541 int32_t rc = 0; 2542 2543 if (!res || !ulp) { 2544 BNXT_TF_DBG(ERR, "Unable to free resource\n "); 2545 return -EINVAL; 2546 } 2547 2548 tfp = bnxt_ulp_cntxt_tfp_get(ulp); 2549 if (!tfp) { 2550 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n"); 2551 return -EINVAL; 2552 } 2553 2554 switch (res->resource_func) { 2555 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: 2556 rc = ulp_mapper_cache_entry_free(ulp, tfp, res); 2557 break; 2558 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2559 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res); 2560 break; 2561 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2562 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2563 rc = ulp_mapper_em_entry_free(ulp, tfp, res); 2564 break; 2565 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2566 rc = ulp_mapper_index_entry_free(ulp, tfp, res); 2567 break; 2568 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2569 rc = ulp_mapper_ident_free(ulp, tfp, res); 2570 break; 2571 case BNXT_ULP_RESOURCE_FUNC_HW_FID: 2572 rc = ulp_mapper_mark_free(ulp, res); 2573 break; 2574 default: 2575 break; 2576 } 2577 2578 return rc; 2579 } 2580 2581 int32_t 2582 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, 2583 uint32_t fid, 2584 enum bnxt_ulp_flow_db_tables tbl_type) 2585 { 2586 struct ulp_flow_db_res_params res_parms = { 0 }; 2587 int32_t rc, trc; 2588 2589 if (!ulp_ctx) { 2590 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 2591 return -EINVAL; 2592 } 2593 2594 /* 2595 * Set the critical resource on the first resource del, then iterate 2596 * while status is good 2597 */ 2598 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; 2599 rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms); 2600 2601 if (rc) { 2602 /* 2603 * This is unexpected on the first call to resource del. 2604 * It likely means that the flow did not exist in the flow db. 2605 */ 2606 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", 2607 tbl_type, fid, rc); 2608 return rc; 2609 } 2610 2611 while (!rc) { 2612 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms); 2613 if (trc) 2614 /* 2615 * On fail, we still need to attempt to free the 2616 * remaining resources. Don't return 2617 */ 2618 BNXT_TF_DBG(ERR, 2619 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64 2620 "] failed rc=%d.\n", 2621 tbl_type, fid, res_parms.resource_func, 2622 res_parms.resource_hndl, trc); 2623 2624 /* All subsequent call require the non-critical_resource */ 2625 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 2626 2627 rc = ulp_flow_db_resource_del(ulp_ctx, 2628 tbl_type, 2629 fid, 2630 &res_parms); 2631 } 2632 2633 /* Free the Flow ID since we've removed all resources */ 2634 rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid); 2635 2636 return rc; 2637 } 2638 2639 static void 2640 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, 2641 struct bnxt_ulp_mapper_data *mapper_data) 2642 { 2643 struct bnxt_ulp_mapper_glb_resource_entry *ent; 2644 struct ulp_flow_db_res_params res; 2645 uint32_t dir, idx; 2646 2647 /* Iterate the global resources and process each one */ 2648 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { 2649 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 2650 idx++) { 2651 ent = &mapper_data->glb_res_tbl[dir][idx]; 2652 if (ent->resource_func == 2653 BNXT_ULP_RESOURCE_FUNC_INVALID) 2654 continue; 2655 memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); 2656 res.resource_func = ent->resource_func; 2657 res.direction = dir; 2658 res.resource_type = ent->resource_type; 2659 /*convert it from BE to cpu */ 2660 res.resource_hndl = 2661 tfp_be_to_cpu_64(ent->resource_hndl); 2662 ulp_mapper_resource_free(ulp_ctx, &res); 2663 } 2664 } 2665 } 2666 2667 int32_t 2668 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid, 2669 enum bnxt_ulp_flow_db_tables flow_tbl_type) 2670 { 2671 int32_t rc; 2672 2673 if (!ulp_ctx) { 2674 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 2675 return -EINVAL; 2676 } 2677 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 2678 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n"); 2679 return -EINVAL; 2680 } 2681 2682 rc = ulp_mapper_resources_free(ulp_ctx, fid, flow_tbl_type); 2683 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 2684 return rc; 2685 2686 } 2687 2688 /* Function to handle the default global templates that are allocated during 2689 * the startup and reused later. 2690 */ 2691 static int32_t 2692 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx) 2693 { 2694 uint32_t *glbl_tmpl_list; 2695 uint32_t num_glb_tmpls, idx, dev_id; 2696 struct bnxt_ulp_mapper_parms parms; 2697 struct bnxt_ulp_mapper_data *mapper_data; 2698 int32_t rc = 0; 2699 2700 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls); 2701 if (!glbl_tmpl_list || !num_glb_tmpls) 2702 return rc; /* No global templates to process */ 2703 2704 /* Get the device id from the ulp context */ 2705 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 2706 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 2707 return -EINVAL; 2708 } 2709 2710 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2711 if (!mapper_data) { 2712 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 2713 return -EINVAL; 2714 } 2715 2716 /* Iterate the global resources and process each one */ 2717 for (idx = 0; idx < num_glb_tmpls; idx++) { 2718 /* Initialize the parms structure */ 2719 memset(&parms, 0, sizeof(parms)); 2720 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2721 parms.ulp_ctx = ulp_ctx; 2722 parms.dev_id = dev_id; 2723 parms.mapper_data = mapper_data; 2724 2725 /* Get the class table entry from dev id and class id */ 2726 parms.class_tid = glbl_tmpl_list[idx]; 2727 parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id, 2728 parms.class_tid, 2729 &parms.num_ctbls, 2730 &parms.tbl_idx); 2731 if (!parms.ctbls || !parms.num_ctbls) { 2732 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2733 parms.dev_id, parms.class_tid); 2734 return -EINVAL; 2735 } 2736 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 2737 if (!parms.device_params) { 2738 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2739 parms.dev_id, parms.class_tid); 2740 return -EINVAL; 2741 } 2742 rc = ulp_mapper_class_tbls_process(&parms); 2743 if (rc) { 2744 BNXT_TF_DBG(ERR, 2745 "class tables failed creation for %d:%d\n", 2746 parms.dev_id, parms.class_tid); 2747 return rc; 2748 } 2749 } 2750 return rc; 2751 } 2752 2753 /* Function to handle the mapping of the Flow to be compatible 2754 * with the underlying hardware. 2755 */ 2756 int32_t 2757 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 2758 struct bnxt_ulp_mapper_create_parms *cparms, 2759 uint32_t *flowid) 2760 { 2761 struct bnxt_ulp_mapper_parms parms; 2762 struct ulp_regfile regfile; 2763 int32_t rc, trc; 2764 2765 if (!ulp_ctx || !cparms) 2766 return -EINVAL; 2767 2768 /* Initialize the parms structure */ 2769 memset(&parms, 0, sizeof(parms)); 2770 parms.act_prop = cparms->act_prop; 2771 parms.act_bitmap = cparms->act; 2772 parms.hdr_bitmap = cparms->hdr_bitmap; 2773 parms.regfile = ®file; 2774 parms.hdr_field = cparms->hdr_field; 2775 parms.comp_fld = cparms->comp_fld; 2776 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2777 parms.ulp_ctx = ulp_ctx; 2778 parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 2779 2780 /* Get the device id from the ulp context */ 2781 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { 2782 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 2783 return -EINVAL; 2784 } 2785 2786 /* 2787 * Get the mapper data for dynamic mapper data such as default 2788 * ids. 2789 */ 2790 parms.mapper_data = (struct bnxt_ulp_mapper_data *) 2791 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2792 if (!parms.mapper_data) { 2793 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 2794 return -EINVAL; 2795 } 2796 2797 /* Get the action table entry from device id and act context id */ 2798 parms.act_tid = cparms->act_tid; 2799 2800 /* 2801 * Perform the action table get only if act template is not zero 2802 * for act template zero like for default rules ignore the action 2803 * table processing. 2804 */ 2805 if (parms.act_tid) { 2806 parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id, 2807 parms.act_tid, 2808 &parms.num_atbls); 2809 if (!parms.atbls || !parms.num_atbls) { 2810 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n", 2811 parms.dev_id, parms.act_tid); 2812 return -EINVAL; 2813 } 2814 } 2815 2816 /* Get the class table entry from device id and act context id */ 2817 parms.class_tid = cparms->class_tid; 2818 parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id, 2819 parms.class_tid, 2820 &parms.num_ctbls, 2821 &parms.tbl_idx); 2822 if (!parms.ctbls || !parms.num_ctbls) { 2823 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2824 parms.dev_id, parms.class_tid); 2825 return -EINVAL; 2826 } 2827 2828 /* Get the device params, it will be used in later processing */ 2829 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 2830 if (!parms.device_params) { 2831 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2832 parms.dev_id, parms.class_tid); 2833 return -EINVAL; 2834 } 2835 2836 /* initialize the registry file for further processing */ 2837 if (!ulp_regfile_init(parms.regfile)) { 2838 BNXT_TF_DBG(ERR, "regfile initialization failed.\n"); 2839 return -EINVAL; 2840 } 2841 2842 rc = ulp_regfile_write(parms.regfile, 2843 BNXT_ULP_REGFILE_INDEX_CLASS_TID, 2844 tfp_cpu_to_be_64((uint64_t)parms.class_tid)); 2845 if (!rc) { 2846 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n"); 2847 return -EINVAL; 2848 } 2849 2850 /* Protect flow creation */ 2851 if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) { 2852 BNXT_TF_DBG(ERR, "Flow db lock acquire failed\n"); 2853 return -EINVAL; 2854 } 2855 2856 /* Allocate a Flow ID for attaching all resources for the flow to. 2857 * Once allocated, all errors have to walk the list of resources and 2858 * free each of them. 2859 */ 2860 rc = ulp_flow_db_fid_alloc(ulp_ctx, 2861 parms.tbl_idx, 2862 cparms->func_id, 2863 &parms.fid); 2864 if (rc) { 2865 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n"); 2866 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 2867 return rc; 2868 } 2869 2870 /* Process the action template list from the selected action table*/ 2871 if (parms.act_tid) { 2872 rc = ulp_mapper_action_tbls_process(&parms); 2873 if (rc) { 2874 BNXT_TF_DBG(ERR, 2875 "action tables failed creation for %d:%d\n", 2876 parms.dev_id, parms.act_tid); 2877 goto flow_error; 2878 } 2879 } 2880 2881 /* All good. Now process the class template */ 2882 rc = ulp_mapper_class_tbls_process(&parms); 2883 if (rc) { 2884 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n", 2885 parms.dev_id, parms.class_tid); 2886 goto flow_error; 2887 } 2888 2889 *flowid = parms.fid; 2890 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 2891 2892 return rc; 2893 2894 flow_error: 2895 bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx); 2896 /* Free all resources that were allocated during flow creation */ 2897 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid, 2898 BNXT_ULP_REGULAR_FLOW_TABLE); 2899 if (trc) 2900 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); 2901 2902 return rc; 2903 } 2904 2905 int32_t 2906 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) 2907 { 2908 struct bnxt_ulp_cache_tbl_params *tbl; 2909 struct bnxt_ulp_mapper_data *data; 2910 uint32_t i; 2911 struct tf *tfp; 2912 int32_t rc, csize; 2913 2914 if (!ulp_ctx) 2915 return -EINVAL; 2916 2917 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2918 if (!tfp) 2919 return -EINVAL; 2920 2921 data = rte_zmalloc("ulp_mapper_data", 2922 sizeof(struct bnxt_ulp_mapper_data), 0); 2923 if (!data) { 2924 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n"); 2925 return -ENOMEM; 2926 } 2927 2928 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) { 2929 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n"); 2930 /* Don't call deinit since the prof_func wasn't allocated. */ 2931 rte_free(data); 2932 return -ENOMEM; 2933 } 2934 2935 /* Allocate the global resource ids */ 2936 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); 2937 if (rc) { 2938 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n"); 2939 goto error; 2940 } 2941 2942 /* Allocate the ulp cache tables. */ 2943 for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { 2944 tbl = ulp_mapper_cache_tbl_params_get(i); 2945 if (!tbl) { 2946 BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)", 2947 i); 2948 goto error; 2949 } 2950 if (tbl->num_entries != 0) { 2951 csize = sizeof(struct bnxt_ulp_mapper_cache_entry) * 2952 tbl->num_entries; 2953 data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl", 2954 csize, 0); 2955 if (!data->cache_tbl[i]) { 2956 BNXT_TF_DBG(ERR, "Failed to allocate Cache " 2957 "table %d.\n", i); 2958 rc = -ENOMEM; 2959 goto error; 2960 } 2961 } 2962 } 2963 2964 rc = ulp_mapper_glb_template_table_init(ulp_ctx); 2965 if (rc) { 2966 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n"); 2967 goto error; 2968 } 2969 2970 return 0; 2971 error: 2972 /* Ignore the return code in favor of returning the original error. */ 2973 ulp_mapper_deinit(ulp_ctx); 2974 return rc; 2975 } 2976 2977 void 2978 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) 2979 { 2980 struct bnxt_ulp_mapper_data *data; 2981 uint32_t i; 2982 struct tf *tfp; 2983 2984 if (!ulp_ctx) { 2985 BNXT_TF_DBG(ERR, 2986 "Failed to acquire ulp context, so data may " 2987 "not be released.\n"); 2988 return; 2989 } 2990 2991 data = (struct bnxt_ulp_mapper_data *) 2992 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2993 if (!data) { 2994 /* Go ahead and return since there is no allocated data. */ 2995 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n"); 2996 return; 2997 } 2998 2999 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 3000 if (!tfp) { 3001 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); 3002 /* Free the mapper data regardless of errors. */ 3003 goto free_mapper_data; 3004 } 3005 3006 /* Free the global resource info table entries */ 3007 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); 3008 3009 free_mapper_data: 3010 /* Free the ulp cache tables */ 3011 for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { 3012 rte_free(data->cache_tbl[i]); 3013 data->cache_tbl[i] = NULL; 3014 } 3015 3016 rte_free(data); 3017 /* Reset the data pointer within the ulp_ctx. */ 3018 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); 3019 } 3020