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