1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_log.h> 7 #include <rte_malloc.h> 8 #include "bnxt.h" 9 #include "ulp_template_db_enum.h" 10 #include "ulp_template_struct.h" 11 #include "bnxt_tf_common.h" 12 #include "ulp_utils.h" 13 #include "bnxt_ulp.h" 14 #include "tfp.h" 15 #include "tf_ext_flow_handle.h" 16 #include "ulp_mark_mgr.h" 17 #include "ulp_mapper.h" 18 #include "ulp_flow_db.h" 19 #include "tf_util.h" 20 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 #define BNXT_ULP_WC_TCAM_SLICE_SIZE 80 1501 /* internal function to post process the key/mask blobs for wildcard tcam tbl */ 1502 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob, 1503 uint32_t len) 1504 { 1505 uint8_t mode[2] = {0x0, 0x0}; 1506 uint32_t mode_len = len / BNXT_ULP_WC_TCAM_SLICE_SIZE; 1507 uint32_t size, idx; 1508 1509 /* Add the mode bits to the key and mask*/ 1510 if (mode_len == 2) 1511 mode[1] = 2; 1512 else if (mode_len > 2) 1513 mode[1] = 3; 1514 1515 size = BNXT_ULP_WC_TCAM_SLICE_SIZE + ULP_BYTE_2_BITS(sizeof(mode)); 1516 for (idx = 0; idx < mode_len; idx++) 1517 ulp_blob_insert(blob, (size * idx), mode, 1518 ULP_BYTE_2_BITS(sizeof(mode))); 1519 ulp_blob_perform_64B_word_swap(blob); 1520 ulp_blob_perform_64B_byte_swap(blob); 1521 } 1522 1523 static int32_t 1524 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1525 struct bnxt_ulp_mapper_tbl_info *tbl) 1526 { 1527 struct bnxt_ulp_mapper_key_field_info *kflds; 1528 struct ulp_blob key, mask, data, update_data; 1529 uint32_t i, num_kflds; 1530 struct tf *tfp; 1531 int32_t rc, trc; 1532 struct tf_alloc_tcam_entry_parms aparms = { 0 }; 1533 struct tf_search_tcam_entry_parms searchparms = { 0 }; 1534 struct ulp_flow_db_res_params fid_parms = { 0 }; 1535 struct tf_free_tcam_entry_parms free_parms = { 0 }; 1536 enum bnxt_ulp_search_before_alloc search_flag; 1537 uint32_t hit = 0; 1538 uint16_t tmplen = 0; 1539 uint16_t idx; 1540 1541 /* Skip this if was handled by the cache. */ 1542 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) { 1543 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1544 return 0; 1545 } 1546 1547 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1548 if (!tfp) { 1549 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1550 return -EINVAL; 1551 } 1552 1553 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 1554 if (!kflds || !num_kflds) { 1555 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1556 return -EINVAL; 1557 } 1558 1559 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, 1560 parms->device_params->byte_order) || 1561 !ulp_blob_init(&mask, tbl->blob_key_bit_size, 1562 parms->device_params->byte_order) || 1563 !ulp_blob_init(&data, tbl->result_bit_size, 1564 parms->device_params->byte_order) || 1565 !ulp_blob_init(&update_data, tbl->result_bit_size, 1566 parms->device_params->byte_order)) { 1567 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1568 return -EINVAL; 1569 } 1570 1571 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) { 1572 key.byte_order = BNXT_ULP_BYTE_ORDER_BE; 1573 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE; 1574 } 1575 1576 /* create the key/mask */ 1577 /* 1578 * NOTE: The WC table will require some kind of flag to handle the 1579 * mode bits within the key/mask 1580 */ 1581 for (i = 0; i < num_kflds; i++) { 1582 /* Setup the key */ 1583 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1584 &kflds[i], 1585 &key, 1, "TCAM Key"); 1586 if (rc) { 1587 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 1588 return rc; 1589 } 1590 1591 /* Setup the mask */ 1592 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1593 &kflds[i], 1594 &mask, 0, "TCAM Mask"); 1595 if (rc) { 1596 BNXT_TF_DBG(ERR, "Mask field set failed.\n"); 1597 return rc; 1598 } 1599 } 1600 1601 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) { 1602 ulp_mapper_wc_tcam_tbl_post_process(&key, tbl->key_bit_size); 1603 ulp_mapper_wc_tcam_tbl_post_process(&mask, tbl->key_bit_size); 1604 } 1605 1606 if (tbl->srch_b4_alloc == BNXT_ULP_SEARCH_BEFORE_ALLOC_NO) { 1607 /* 1608 * No search for re-use is requested, so simply allocate the 1609 * tcam index. 1610 */ 1611 aparms.dir = tbl->direction; 1612 aparms.tcam_tbl_type = tbl->resource_type; 1613 aparms.search_enable = tbl->srch_b4_alloc; 1614 aparms.key = ulp_blob_data_get(&key, &tmplen); 1615 aparms.key_sz_in_bits = tmplen; 1616 if (tbl->blob_key_bit_size != tmplen) { 1617 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n", 1618 tmplen, tbl->blob_key_bit_size); 1619 return -EINVAL; 1620 } 1621 1622 aparms.mask = ulp_blob_data_get(&mask, &tmplen); 1623 if (tbl->blob_key_bit_size != tmplen) { 1624 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n", 1625 tmplen, tbl->blob_key_bit_size); 1626 return -EINVAL; 1627 } 1628 1629 aparms.priority = tbl->priority; 1630 1631 /* 1632 * All failures after this succeeds require the entry to be 1633 * freed. cannot return directly on failure, but needs to goto 1634 * error. 1635 */ 1636 rc = tf_alloc_tcam_entry(tfp, &aparms); 1637 if (rc) { 1638 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); 1639 return rc; 1640 } 1641 idx = aparms.idx; 1642 hit = aparms.hit; 1643 } else { 1644 /* 1645 * Searching before allocation to see if we already have an 1646 * entry. This allows re-use of a constrained resource. 1647 */ 1648 searchparms.dir = tbl->direction; 1649 searchparms.tcam_tbl_type = tbl->resource_type; 1650 searchparms.key = ulp_blob_data_get(&key, &tmplen); 1651 searchparms.key_sz_in_bits = tbl->key_bit_size; 1652 searchparms.mask = ulp_blob_data_get(&mask, &tmplen); 1653 searchparms.priority = tbl->priority; 1654 searchparms.alloc = 1; 1655 searchparms.result = ulp_blob_data_get(&data, &tmplen); 1656 searchparms.result_sz_in_bits = tbl->result_bit_size; 1657 1658 rc = tf_search_tcam_entry(tfp, &searchparms); 1659 if (rc) { 1660 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc); 1661 return rc; 1662 } 1663 1664 /* Successful search, check the result */ 1665 if (searchparms.search_status == REJECT) { 1666 BNXT_TF_DBG(ERR, "tcam alloc rejected\n"); 1667 return -ENOMEM; 1668 } 1669 idx = searchparms.idx; 1670 hit = searchparms.hit; 1671 } 1672 1673 /* if it is miss then it is same as no search before alloc */ 1674 if (!hit) 1675 search_flag = BNXT_ULP_SEARCH_BEFORE_ALLOC_NO; 1676 else 1677 search_flag = tbl->srch_b4_alloc; 1678 1679 switch (search_flag) { 1680 case BNXT_ULP_SEARCH_BEFORE_ALLOC_NO: 1681 /*Scan identifier list, allocate identifier and update regfile*/ 1682 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); 1683 /* Create the result blob */ 1684 if (!rc) 1685 rc = ulp_mapper_tcam_tbl_result_create(parms, tbl, 1686 &data); 1687 /* write the tcam entry */ 1688 if (!rc) 1689 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key, 1690 &mask, &data, idx); 1691 break; 1692 case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_SKIP: 1693 /*Scan identifier list, extract identifier and update regfile*/ 1694 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); 1695 break; 1696 case BNXT_ULP_SEARCH_BEFORE_ALLOC_SEARCH_IF_HIT_UPDATE: 1697 /*Scan identifier list, extract identifier and update regfile*/ 1698 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); 1699 /* Create the result blob */ 1700 if (!rc) 1701 rc = ulp_mapper_tcam_tbl_result_create(parms, tbl, 1702 &update_data); 1703 /* Update/overwrite the tcam entry */ 1704 if (!rc) 1705 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key, 1706 &mask, 1707 &update_data, idx); 1708 break; 1709 default: 1710 BNXT_TF_DBG(ERR, "invalid search opcode\n"); 1711 rc = -EINVAL; 1712 break; 1713 } 1714 if (rc) 1715 goto error; 1716 1717 /* 1718 * Only link the entry to the flow db in the event that cache was not 1719 * used. 1720 */ 1721 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) { 1722 fid_parms.direction = tbl->direction; 1723 fid_parms.resource_func = tbl->resource_func; 1724 fid_parms.resource_type = tbl->resource_type; 1725 fid_parms.critical_resource = tbl->critical_resource; 1726 fid_parms.resource_hndl = idx; 1727 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1728 parms->flow_type, 1729 parms->fid, 1730 &fid_parms); 1731 if (rc) { 1732 BNXT_TF_DBG(ERR, 1733 "Failed to link resource to flow rc = %d\n", 1734 rc); 1735 /* Need to free the identifier, so goto error */ 1736 goto error; 1737 } 1738 } else { 1739 /* 1740 * Reset the tcam table opcode to normal in case the next tcam 1741 * entry does not use cache. 1742 */ 1743 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1744 parms->cache_ptr = NULL; 1745 } 1746 1747 return 0; 1748 error: 1749 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1750 free_parms.dir = tbl->direction; 1751 free_parms.tcam_tbl_type = tbl->resource_type; 1752 free_parms.idx = idx; 1753 trc = tf_free_tcam_entry(tfp, &free_parms); 1754 if (trc) 1755 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", 1756 tbl->resource_type, tbl->direction, idx); 1757 1758 return rc; 1759 } 1760 1761 static int32_t 1762 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1763 struct bnxt_ulp_mapper_tbl_info *tbl) 1764 { 1765 struct bnxt_ulp_mapper_key_field_info *kflds; 1766 struct bnxt_ulp_mapper_result_field_info *dflds; 1767 struct ulp_blob key, data; 1768 uint32_t i, num_kflds, num_dflds; 1769 uint16_t tmplen; 1770 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1771 struct ulp_flow_db_res_params fid_parms = { 0 }; 1772 struct tf_insert_em_entry_parms iparms = { 0 }; 1773 struct tf_delete_em_entry_parms free_parms = { 0 }; 1774 enum bnxt_ulp_flow_mem_type mtype; 1775 int32_t trc; 1776 int32_t rc = 0; 1777 uint32_t encap_flds = 0; 1778 1779 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); 1780 if (rc) { 1781 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n"); 1782 return -EINVAL; 1783 } 1784 1785 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 1786 if (!kflds || !num_kflds) { 1787 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1788 return -EINVAL; 1789 } 1790 1791 /* Initialize the key/result blobs */ 1792 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, 1793 parms->device_params->byte_order) || 1794 !ulp_blob_init(&data, tbl->result_bit_size, 1795 parms->device_params->byte_order)) { 1796 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1797 return -EINVAL; 1798 } 1799 1800 /* create the key */ 1801 for (i = 0; i < num_kflds; i++) { 1802 /* Setup the key */ 1803 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1804 &kflds[i], 1805 &key, 1, "EM Key"); 1806 if (rc) { 1807 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 1808 return rc; 1809 } 1810 } 1811 1812 /* 1813 * TBD: Normally should process identifiers in case of using recycle or 1814 * loopback. Not supporting recycle for now. 1815 */ 1816 1817 /* Create the result data blob */ 1818 dflds = ulp_mapper_result_fields_get(parms, tbl, 1819 &num_dflds, &encap_flds); 1820 if (!dflds || !num_dflds || encap_flds) { 1821 BNXT_TF_DBG(ERR, "Failed to get data fields.\n"); 1822 return -EINVAL; 1823 } 1824 1825 for (i = 0; i < num_dflds; i++) { 1826 struct bnxt_ulp_mapper_result_field_info *fld; 1827 1828 fld = &dflds[i]; 1829 1830 rc = ulp_mapper_result_field_process(parms, 1831 tbl->direction, 1832 fld, 1833 &data, 1834 "EM Result"); 1835 if (rc) { 1836 BNXT_TF_DBG(ERR, "Failed to set data fields.\n"); 1837 return rc; 1838 } 1839 } 1840 1841 /* do the transpose for the internal EM keys */ 1842 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) 1843 ulp_blob_perform_byte_reverse(&key); 1844 1845 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, 1846 &iparms.tbl_scope_id); 1847 if (rc) { 1848 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1849 return rc; 1850 } 1851 1852 /* 1853 * NOTE: the actual blob size will differ from the size in the tbl 1854 * entry due to the padding. 1855 */ 1856 iparms.dup_check = 0; 1857 iparms.dir = tbl->direction; 1858 iparms.mem = tbl->resource_type; 1859 iparms.key = ulp_blob_data_get(&key, &tmplen); 1860 iparms.key_sz_in_bits = tbl->key_bit_size; 1861 iparms.em_record = ulp_blob_data_get(&data, &tmplen); 1862 iparms.em_record_sz_in_bits = tbl->result_bit_size; 1863 1864 rc = tf_insert_em_entry(tfp, &iparms); 1865 if (rc) { 1866 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc); 1867 return rc; 1868 } 1869 1870 /* Mark action process */ 1871 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && 1872 tbl->resource_type == TF_MEM_EXTERNAL) 1873 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); 1874 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && 1875 tbl->resource_type == TF_MEM_INTERNAL) 1876 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1877 if (rc) { 1878 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1879 goto error; 1880 } 1881 1882 /* Link the EM resource to the flow in the flow db */ 1883 memset(&fid_parms, 0, sizeof(fid_parms)); 1884 fid_parms.direction = tbl->direction; 1885 fid_parms.resource_func = tbl->resource_func; 1886 fid_parms.resource_type = tbl->resource_type; 1887 fid_parms.critical_resource = tbl->critical_resource; 1888 fid_parms.resource_hndl = iparms.flow_handle; 1889 1890 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1891 parms->flow_type, 1892 parms->fid, 1893 &fid_parms); 1894 if (rc) { 1895 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", 1896 rc); 1897 /* Need to free the identifier, so goto error */ 1898 goto error; 1899 } 1900 1901 return 0; 1902 error: 1903 free_parms.dir = iparms.dir; 1904 free_parms.mem = iparms.mem; 1905 free_parms.tbl_scope_id = iparms.tbl_scope_id; 1906 free_parms.flow_handle = iparms.flow_handle; 1907 1908 trc = tf_delete_em_entry(tfp, &free_parms); 1909 if (trc) 1910 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n"); 1911 1912 return rc; 1913 } 1914 1915 static int32_t 1916 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1917 struct bnxt_ulp_mapper_tbl_info *tbl) 1918 { 1919 struct bnxt_ulp_mapper_result_field_info *flds; 1920 struct ulp_flow_db_res_params fid_parms; 1921 struct ulp_blob data; 1922 uint64_t idx = 0; 1923 uint16_t tmplen; 1924 uint32_t i, num_flds, index, hit; 1925 int32_t rc = 0, trc = 0; 1926 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 1927 struct tf_search_tbl_entry_parms srchparms = { 0 }; 1928 struct tf_set_tbl_entry_parms sparms = { 0 }; 1929 struct tf_free_tbl_entry_parms free_parms = { 0 }; 1930 uint32_t tbl_scope_id; 1931 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1932 uint16_t bit_size; 1933 uint32_t encap_flds = 0; 1934 1935 /* Get the scope id first */ 1936 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); 1937 if (rc) { 1938 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1939 return rc; 1940 } 1941 1942 /* use the max size if encap is enabled */ 1943 if (tbl->encap_num_fields) 1944 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 1945 else 1946 bit_size = tbl->result_bit_size; 1947 1948 /* Initialize the blob data */ 1949 if (!ulp_blob_init(&data, bit_size, 1950 parms->device_params->byte_order)) { 1951 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 1952 return -EINVAL; 1953 } 1954 1955 /* Get the result fields list */ 1956 flds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, &encap_flds); 1957 1958 if (!flds || (!num_flds && !encap_flds)) { 1959 BNXT_TF_DBG(ERR, "template undefined for the index table\n"); 1960 return -EINVAL; 1961 } 1962 1963 /* process the result fields, loop through them */ 1964 for (i = 0; i < (num_flds + encap_flds); i++) { 1965 /* set the swap index if encap swap bit is enabled */ 1966 if (parms->device_params->encap_byte_swap && encap_flds && 1967 (i == num_flds)) 1968 ulp_blob_encap_swap_idx_set(&data); 1969 1970 /* Process the result fields */ 1971 rc = ulp_mapper_result_field_process(parms, 1972 tbl->direction, 1973 &flds[i], 1974 &data, 1975 "Indexed Result"); 1976 if (rc) { 1977 BNXT_TF_DBG(ERR, "data field failed\n"); 1978 return rc; 1979 } 1980 } 1981 1982 /* if encap bit swap is enabled perform the bit swap */ 1983 if (parms->device_params->encap_byte_swap && encap_flds) { 1984 ulp_blob_perform_encap_swap(&data); 1985 } 1986 1987 /* 1988 * Check for index opcode, if it is Global then 1989 * no need to allocate the table, just set the table 1990 * and exit since it is not maintained in the flow db. 1991 */ 1992 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_GLOBAL) { 1993 /* get the index from index operand */ 1994 if (tbl->index_operand < BNXT_ULP_GLB_REGFILE_INDEX_LAST && 1995 ulp_mapper_glb_resource_read(parms->mapper_data, 1996 tbl->direction, 1997 tbl->index_operand, 1998 &idx)) { 1999 BNXT_TF_DBG(ERR, "Glbl regfile[%d] read failed.\n", 2000 tbl->index_operand); 2001 return -EINVAL; 2002 } 2003 /* set the Tf index table */ 2004 sparms.dir = tbl->direction; 2005 sparms.type = tbl->resource_type; 2006 sparms.data = ulp_blob_data_get(&data, &tmplen); 2007 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2008 sparms.idx = tfp_be_to_cpu_64(idx); 2009 sparms.tbl_scope_id = tbl_scope_id; 2010 2011 rc = tf_set_tbl_entry(tfp, &sparms); 2012 if (rc) { 2013 BNXT_TF_DBG(ERR, 2014 "Glbl Set table[%d][%s][%d] failed rc=%d\n", 2015 sparms.type, 2016 (sparms.dir == TF_DIR_RX) ? "RX" : "TX", 2017 sparms.idx, 2018 rc); 2019 return rc; 2020 } 2021 return 0; /* success */ 2022 } 2023 2024 index = 0; 2025 hit = 0; 2026 /* Perform the tf table allocation by filling the alloc params */ 2027 if (tbl->srch_b4_alloc) { 2028 memset(&srchparms, 0, sizeof(srchparms)); 2029 srchparms.dir = tbl->direction; 2030 srchparms.type = tbl->resource_type; 2031 srchparms.alloc = 1; 2032 srchparms.result = ulp_blob_data_get(&data, &tmplen); 2033 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2034 srchparms.tbl_scope_id = tbl_scope_id; 2035 rc = tf_search_tbl_entry(tfp, &srchparms); 2036 if (rc) { 2037 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2038 tf_tbl_type_2_str(tbl->resource_type), 2039 tf_dir_2_str(tbl->direction), rc); 2040 return rc; 2041 } 2042 if (srchparms.search_status == REJECT) { 2043 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n", 2044 tf_tbl_type_2_str(tbl->resource_type), 2045 tf_dir_2_str(tbl->direction)); 2046 return -ENOMEM; 2047 } 2048 index = srchparms.idx; 2049 hit = srchparms.hit; 2050 } else { 2051 aparms.dir = tbl->direction; 2052 aparms.type = tbl->resource_type; 2053 aparms.search_enable = tbl->srch_b4_alloc; 2054 aparms.result = ulp_blob_data_get(&data, &tmplen); 2055 aparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2056 aparms.tbl_scope_id = tbl_scope_id; 2057 2058 /* All failures after the alloc succeeds require a free */ 2059 rc = tf_alloc_tbl_entry(tfp, &aparms); 2060 if (rc) { 2061 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2062 tf_tbl_type_2_str(tbl->resource_type), 2063 tf_dir_2_str(tbl->direction), rc); 2064 return rc; 2065 } 2066 index = aparms.idx; 2067 } 2068 /* 2069 * calculate the idx for the result record, for external EM the offset 2070 * needs to be shifted accordingly. If external non-inline table types 2071 * are used then need to revisit this logic. 2072 */ 2073 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2074 idx = TF_ACT_REC_OFFSET_2_PTR(index); 2075 else 2076 idx = index; 2077 2078 /* Always storing values in Regfile in BE */ 2079 idx = tfp_cpu_to_be_64(idx); 2080 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_ALLOCATE) { 2081 rc = ulp_regfile_write(parms->regfile, tbl->index_operand, idx); 2082 if (!rc) { 2083 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 2084 tbl->index_operand); 2085 goto error; 2086 } 2087 } 2088 2089 /* Perform the tf table set by filling the set params */ 2090 if (!tbl->srch_b4_alloc || !hit) { 2091 sparms.dir = tbl->direction; 2092 sparms.type = tbl->resource_type; 2093 sparms.data = ulp_blob_data_get(&data, &tmplen); 2094 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2095 sparms.idx = index; 2096 sparms.tbl_scope_id = tbl_scope_id; 2097 2098 rc = tf_set_tbl_entry(tfp, &sparms); 2099 if (rc) { 2100 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n", 2101 sparms.type, 2102 (sparms.dir == TF_DIR_RX) ? "RX" : "TX", 2103 sparms.idx, 2104 rc); 2105 goto error; 2106 } 2107 } 2108 2109 /* Link the resource to the flow in the flow db */ 2110 memset(&fid_parms, 0, sizeof(fid_parms)); 2111 fid_parms.direction = tbl->direction; 2112 fid_parms.resource_func = tbl->resource_func; 2113 fid_parms.resource_type = tbl->resource_type; 2114 fid_parms.resource_sub_type = tbl->resource_sub_type; 2115 fid_parms.resource_hndl = index; 2116 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 2117 2118 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 2119 parms->flow_type, 2120 parms->fid, 2121 &fid_parms); 2122 if (rc) { 2123 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2124 rc); 2125 goto error; 2126 } 2127 2128 /* Perform the VF rep action */ 2129 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 2130 if (rc) { 2131 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 2132 goto error; 2133 } 2134 return rc; 2135 error: 2136 /* 2137 * Free the allocated resource since we failed to either 2138 * write to the entry or link the flow 2139 */ 2140 free_parms.dir = tbl->direction; 2141 free_parms.type = tbl->resource_type; 2142 free_parms.idx = index; 2143 free_parms.tbl_scope_id = tbl_scope_id; 2144 2145 trc = tf_free_tbl_entry(tfp, &free_parms); 2146 if (trc) 2147 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n"); 2148 2149 return rc; 2150 } 2151 2152 static int32_t 2153 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2154 struct bnxt_ulp_mapper_tbl_info *tbl) 2155 { 2156 struct bnxt_ulp_mapper_key_field_info *kflds; 2157 struct bnxt_ulp_mapper_cache_entry *cache_entry; 2158 struct bnxt_ulp_mapper_ident_info *idents; 2159 uint32_t i, num_kflds = 0, num_idents = 0; 2160 struct ulp_flow_db_res_params fid_parms; 2161 struct tf_free_identifier_parms fparms; 2162 uint16_t tmplen, tmp_ident; 2163 struct ulp_blob key; 2164 uint8_t *cache_key; 2165 uint64_t regval; 2166 uint16_t *ckey; 2167 int32_t rc; 2168 2169 /* Get the key fields list and build the key. */ 2170 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2171 if (!kflds || !num_kflds) { 2172 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2173 return -EINVAL; 2174 } 2175 if (!ulp_blob_init(&key, tbl->key_bit_size, 2176 parms->device_params->byte_order)) { 2177 BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); 2178 return -EINVAL; 2179 } 2180 for (i = 0; i < num_kflds; i++) { 2181 /* Setup the key */ 2182 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 2183 &kflds[i], 2184 &key, 1, "Cache Key"); 2185 if (rc) { 2186 BNXT_TF_DBG(ERR, 2187 "Failed to create key for Cache rc=%d\n", 2188 rc); 2189 return -EINVAL; 2190 } 2191 } 2192 2193 /* 2194 * Perform the lookup in the cache table with constructed key. The 2195 * cache_key is a byte array of tmplen, it needs to be converted to a 2196 * index for the cache table. 2197 */ 2198 cache_key = ulp_blob_data_get(&key, &tmplen); 2199 ckey = (uint16_t *)cache_key; 2200 2201 /* 2202 * The id computed based on resource sub type and direction where 2203 * dir is the bit0 and rest of the bits come from resource 2204 * sub type. 2205 */ 2206 cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx, 2207 (tbl->resource_sub_type << 1 | 2208 (tbl->direction & 0x1)), 2209 *ckey); 2210 2211 /* 2212 * Get the identifier list for processing by both the hit and miss 2213 * processing. 2214 */ 2215 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 2216 2217 if (!cache_entry->ref_count) { 2218 /* Initialize the cache entry */ 2219 cache_entry->tcam_idx = 0; 2220 cache_entry->ref_count = 0; 2221 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) 2222 cache_entry->idents[i] = ULP_IDENTS_INVALID; 2223 2224 /* Need to allocate identifiers for storing in the cache. */ 2225 for (i = 0; i < num_idents; i++) { 2226 /* 2227 * Since we are using the cache, the identifier does not 2228 * get added to the flow db. Pass in the pointer to the 2229 * tmp_ident. 2230 */ 2231 rc = ulp_mapper_ident_process(parms, tbl, 2232 &idents[i], &tmp_ident); 2233 if (rc) 2234 goto error; 2235 2236 cache_entry->ident_types[i] = idents[i].ident_type; 2237 cache_entry->idents[i] = tmp_ident; 2238 } 2239 2240 /* Tell the TCAM processor to alloc an entry */ 2241 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC; 2242 /* Store the cache key for use by the tcam process code */ 2243 parms->cache_ptr = cache_entry; 2244 } else { 2245 /* Cache hit, get values from result. */ 2246 for (i = 0; i < num_idents; i++) { 2247 regval = (uint64_t)cache_entry->idents[i]; 2248 if (!ulp_regfile_write(parms->regfile, 2249 idents[i].regfile_idx, 2250 tfp_cpu_to_be_64(regval))) { 2251 BNXT_TF_DBG(ERR, 2252 "Failed to write to regfile\n"); 2253 return -EINVAL; 2254 } 2255 } 2256 /* 2257 * The cached entry is being used, so let the tcam processing 2258 * know not to process this table. 2259 */ 2260 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP; 2261 } 2262 2263 /* Made through the cache processing, increment the reference count. */ 2264 cache_entry->ref_count++; 2265 2266 /* Link the cache to the flow db. */ 2267 memset(&fid_parms, 0, sizeof(fid_parms)); 2268 fid_parms.direction = tbl->direction; 2269 fid_parms.resource_func = tbl->resource_func; 2270 2271 /* 2272 * Cache resource type is composed of table_type, resource 2273 * sub type and direction, it needs to set appropriately via setter. 2274 */ 2275 ulp_mapper_cache_res_type_set(&fid_parms, 2276 tbl->resource_type, 2277 (tbl->resource_sub_type << 1 | 2278 (tbl->direction & 0x1))); 2279 fid_parms.resource_hndl = (uint64_t)*ckey; 2280 fid_parms.critical_resource = tbl->critical_resource; 2281 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 2282 parms->flow_type, 2283 parms->fid, 2284 &fid_parms); 2285 if (rc) 2286 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n"); 2287 2288 return rc; 2289 error: 2290 /* 2291 * This error handling only gets called when the idents are being 2292 * allocated for the cache on misses. Using the num_idents that was 2293 * previously set. 2294 */ 2295 for (i = 0; i < num_idents; i++) { 2296 if (cache_entry->idents[i] == ULP_IDENTS_INVALID) 2297 continue; 2298 2299 fparms.dir = tbl->direction; 2300 fparms.ident_type = idents[i].ident_type; 2301 fparms.id = cache_entry->idents[i]; 2302 tf_free_identifier(parms->tfp, &fparms); 2303 } 2304 2305 return rc; 2306 } 2307 2308 static int32_t 2309 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2310 struct bnxt_ulp_mapper_tbl_info *tbl) 2311 { 2312 struct bnxt_ulp_mapper_result_field_info *flds; 2313 struct ulp_blob data; 2314 uint64_t idx; 2315 uint16_t tmplen; 2316 uint32_t i, num_flds; 2317 int32_t rc = 0; 2318 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; 2319 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 2320 uint32_t encap_flds; 2321 2322 /* Initialize the blob data */ 2323 if (!ulp_blob_init(&data, tbl->result_bit_size, 2324 parms->device_params->byte_order)) { 2325 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 2326 return -EINVAL; 2327 } 2328 2329 /* Get the result fields list */ 2330 flds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, &encap_flds); 2331 2332 if (!flds || !num_flds || encap_flds) { 2333 BNXT_TF_DBG(ERR, "template undefined for the IF table\n"); 2334 return -EINVAL; 2335 } 2336 2337 /* process the result fields, loop through them */ 2338 for (i = 0; i < num_flds; i++) { 2339 /* Process the result fields */ 2340 rc = ulp_mapper_result_field_process(parms, 2341 tbl->direction, 2342 &flds[i], 2343 &data, 2344 "IFtable Result"); 2345 if (rc) { 2346 BNXT_TF_DBG(ERR, "data field failed\n"); 2347 return rc; 2348 } 2349 } 2350 2351 /* Get the index details from computed field */ 2352 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_COMP_FIELD) { 2353 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand); 2354 } else if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_CONSTANT) { 2355 idx = tbl->index_operand; 2356 } else { 2357 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); 2358 return -EINVAL; 2359 } 2360 2361 /* Perform the tf table set by filling the set params */ 2362 iftbl_params.dir = tbl->direction; 2363 iftbl_params.type = tbl->resource_type; 2364 iftbl_params.data = ulp_blob_data_get(&data, &tmplen); 2365 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2366 iftbl_params.idx = idx; 2367 2368 rc = tf_set_if_tbl_entry(tfp, &iftbl_params); 2369 if (rc) { 2370 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n", 2371 iftbl_params.type, 2372 (iftbl_params.dir == TF_DIR_RX) ? "RX" : "TX", 2373 iftbl_params.idx, 2374 rc); 2375 return rc; 2376 } 2377 2378 /* 2379 * TBD: Need to look at the need to store idx in flow db for restore 2380 * the table to its original state on deletion of this entry. 2381 */ 2382 return rc; 2383 } 2384 2385 static int32_t 2386 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 2387 struct bnxt_ulp_mapper_data *mapper_data) 2388 { 2389 struct bnxt_ulp_glb_resource_info *glb_res; 2390 uint32_t num_glb_res_ids, idx; 2391 int32_t rc = 0; 2392 2393 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); 2394 if (!glb_res || !num_glb_res_ids) { 2395 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 2396 return -EINVAL; 2397 } 2398 2399 /* Iterate the global resources and process each one */ 2400 for (idx = 0; idx < num_glb_res_ids; idx++) { 2401 switch (glb_res[idx].resource_func) { 2402 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2403 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 2404 mapper_data, 2405 &glb_res[idx]); 2406 break; 2407 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2408 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 2409 mapper_data, 2410 &glb_res[idx]); 2411 break; 2412 default: 2413 BNXT_TF_DBG(ERR, "Global resource %x not supported\n", 2414 glb_res[idx].resource_func); 2415 rc = -EINVAL; 2416 break; 2417 } 2418 if (rc) 2419 return rc; 2420 } 2421 return rc; 2422 } 2423 2424 /* 2425 * Function to process the conditional opcode of the mapper table. 2426 * returns 1 to skip the table. 2427 * return 0 to continue processing the table. 2428 * 2429 * defaults to skip 2430 */ 2431 static int32_t 2432 ulp_mapper_tbl_cond_opcode_process(struct bnxt_ulp_mapper_parms *parms, 2433 struct bnxt_ulp_mapper_tbl_info *tbl) 2434 { 2435 int32_t rc = 1; 2436 2437 switch (tbl->cond_opcode) { 2438 case BNXT_ULP_COND_OPCODE_NOP: 2439 rc = 0; 2440 break; 2441 case BNXT_ULP_COND_OPCODE_COMP_FIELD_IS_SET: 2442 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && 2443 ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) 2444 rc = 0; 2445 break; 2446 case BNXT_ULP_COND_OPCODE_ACTION_BIT_IS_SET: 2447 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2448 tbl->cond_operand)) 2449 rc = 0; 2450 break; 2451 case BNXT_ULP_COND_OPCODE_HDR_BIT_IS_SET: 2452 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2453 tbl->cond_operand)) 2454 rc = 0; 2455 break; 2456 case BNXT_ULP_COND_OPCODE_COMP_FIELD_NOT_SET: 2457 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && 2458 !ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) 2459 rc = 0; 2460 break; 2461 case BNXT_ULP_COND_OPCODE_ACTION_BIT_NOT_SET: 2462 if (!ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2463 tbl->cond_operand)) 2464 rc = 0; 2465 break; 2466 case BNXT_ULP_COND_OPCODE_HDR_BIT_NOT_SET: 2467 if (!ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2468 tbl->cond_operand)) 2469 rc = 0; 2470 break; 2471 default: 2472 BNXT_TF_DBG(ERR, 2473 "Invalid arg in mapper tbl for cond opcode\n"); 2474 break; 2475 } 2476 return rc; 2477 } 2478 2479 /* 2480 * Function to process the memtype opcode of the mapper table. 2481 * returns 1 to skip the table. 2482 * return 0 to continue processing the table. 2483 * 2484 * defaults to skip 2485 */ 2486 static int32_t 2487 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms, 2488 struct bnxt_ulp_mapper_tbl_info *tbl) 2489 { 2490 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT; 2491 int32_t rc = 1; 2492 2493 bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); 2494 2495 switch (tbl->mem_type_opcode) { 2496 case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_INT: 2497 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) 2498 rc = 0; 2499 break; 2500 case BNXT_ULP_MEM_TYPE_OPCODE_EXECUTE_IF_EXT: 2501 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT) 2502 rc = 0; 2503 break; 2504 case BNXT_ULP_MEM_TYPE_OPCODE_NOP: 2505 rc = 0; 2506 break; 2507 default: 2508 BNXT_TF_DBG(ERR, 2509 "Invalid arg in mapper in memtype opcode\n"); 2510 break; 2511 } 2512 return rc; 2513 } 2514 2515 static int32_t 2516 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid) 2517 { 2518 struct bnxt_ulp_mapper_tbl_info *tbls; 2519 uint32_t num_tbls, i; 2520 int32_t rc = -EINVAL; 2521 2522 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls); 2523 if (!tbls || !num_tbls) { 2524 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n", 2525 (parms->tmpl_type == BNXT_ULP_TEMPLATE_TYPE_CLASS) ? 2526 "class" : "action", parms->dev_id, tid); 2527 return -EINVAL; 2528 } 2529 2530 for (i = 0; i < num_tbls; i++) { 2531 struct bnxt_ulp_mapper_tbl_info *tbl = &tbls[i]; 2532 2533 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl)) 2534 continue; 2535 if (ulp_mapper_tbl_cond_opcode_process(parms, tbl)) 2536 continue; 2537 2538 switch (tbl->resource_func) { 2539 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2540 rc = ulp_mapper_tcam_tbl_process(parms, tbl); 2541 break; 2542 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2543 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2544 rc = ulp_mapper_em_tbl_process(parms, tbl); 2545 break; 2546 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2547 rc = ulp_mapper_index_tbl_process(parms, tbl); 2548 break; 2549 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: 2550 rc = ulp_mapper_cache_tbl_process(parms, tbl); 2551 break; 2552 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: 2553 rc = ulp_mapper_if_tbl_process(parms, tbl); 2554 break; 2555 default: 2556 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n", 2557 tbl->resource_func); 2558 rc = -EINVAL; 2559 goto error; 2560 } 2561 2562 if (rc) { 2563 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 2564 tbl->resource_func); 2565 goto error; 2566 } 2567 } 2568 2569 return rc; 2570 error: 2571 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n", 2572 (parms->tmpl_type == BNXT_ULP_TEMPLATE_TYPE_CLASS) ? 2573 "class" : "action", parms->dev_id, tid); 2574 return rc; 2575 } 2576 2577 static int32_t 2578 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 2579 uint32_t fid, 2580 struct ulp_flow_db_res_params *res) 2581 { 2582 struct tf *tfp; 2583 int32_t rc = 0; 2584 2585 if (!res || !ulp) { 2586 BNXT_TF_DBG(ERR, "Unable to free resource\n "); 2587 return -EINVAL; 2588 } 2589 2590 tfp = bnxt_ulp_cntxt_tfp_get(ulp); 2591 if (!tfp) { 2592 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n"); 2593 return -EINVAL; 2594 } 2595 2596 switch (res->resource_func) { 2597 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: 2598 rc = ulp_mapper_cache_entry_free(ulp, tfp, res); 2599 break; 2600 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2601 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res); 2602 break; 2603 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2604 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2605 rc = ulp_mapper_em_entry_free(ulp, tfp, res); 2606 break; 2607 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2608 rc = ulp_mapper_index_entry_free(ulp, tfp, res); 2609 break; 2610 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2611 rc = ulp_mapper_ident_free(ulp, tfp, res); 2612 break; 2613 case BNXT_ULP_RESOURCE_FUNC_HW_FID: 2614 rc = ulp_mapper_mark_free(ulp, res); 2615 break; 2616 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW: 2617 rc = ulp_mapper_parent_flow_free(ulp, fid, res); 2618 break; 2619 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW: 2620 rc = ulp_mapper_child_flow_free(ulp, fid, res); 2621 break; 2622 default: 2623 break; 2624 } 2625 2626 return rc; 2627 } 2628 2629 int32_t 2630 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, 2631 enum bnxt_ulp_fdb_type flow_type, 2632 uint32_t fid) 2633 { 2634 struct ulp_flow_db_res_params res_parms = { 0 }; 2635 int32_t rc, trc; 2636 2637 if (!ulp_ctx) { 2638 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 2639 return -EINVAL; 2640 } 2641 2642 /* 2643 * Set the critical resource on the first resource del, then iterate 2644 * while status is good 2645 */ 2646 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; 2647 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms); 2648 2649 if (rc) { 2650 /* 2651 * This is unexpected on the first call to resource del. 2652 * It likely means that the flow did not exist in the flow db. 2653 */ 2654 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", 2655 flow_type, fid, rc); 2656 return rc; 2657 } 2658 2659 while (!rc) { 2660 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms); 2661 if (trc) 2662 /* 2663 * On fail, we still need to attempt to free the 2664 * remaining resources. Don't return 2665 */ 2666 BNXT_TF_DBG(ERR, 2667 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64 2668 "] failed rc=%d.\n", 2669 flow_type, fid, res_parms.resource_func, 2670 res_parms.resource_hndl, trc); 2671 2672 /* All subsequent call require the non-critical_resource */ 2673 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 2674 2675 rc = ulp_flow_db_resource_del(ulp_ctx, 2676 flow_type, 2677 fid, 2678 &res_parms); 2679 } 2680 2681 /* Free the Flow ID since we've removed all resources */ 2682 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid); 2683 2684 return rc; 2685 } 2686 2687 static void 2688 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, 2689 struct bnxt_ulp_mapper_data *mapper_data) 2690 { 2691 struct bnxt_ulp_mapper_glb_resource_entry *ent; 2692 struct ulp_flow_db_res_params res; 2693 uint32_t dir, idx; 2694 2695 /* Iterate the global resources and process each one */ 2696 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { 2697 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 2698 idx++) { 2699 ent = &mapper_data->glb_res_tbl[dir][idx]; 2700 if (ent->resource_func == 2701 BNXT_ULP_RESOURCE_FUNC_INVALID) 2702 continue; 2703 memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); 2704 res.resource_func = ent->resource_func; 2705 res.direction = dir; 2706 res.resource_type = ent->resource_type; 2707 /*convert it from BE to cpu */ 2708 res.resource_hndl = 2709 tfp_be_to_cpu_64(ent->resource_hndl); 2710 ulp_mapper_resource_free(ulp_ctx, 0, &res); 2711 } 2712 } 2713 } 2714 2715 int32_t 2716 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, 2717 enum bnxt_ulp_fdb_type flow_type, 2718 uint32_t fid) 2719 { 2720 int32_t rc; 2721 2722 if (!ulp_ctx) { 2723 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 2724 return -EINVAL; 2725 } 2726 2727 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid); 2728 return rc; 2729 } 2730 2731 /* Function to handle the default global templates that are allocated during 2732 * the startup and reused later. 2733 */ 2734 static int32_t 2735 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx) 2736 { 2737 uint32_t *glbl_tmpl_list; 2738 uint32_t num_glb_tmpls, idx, dev_id; 2739 struct bnxt_ulp_mapper_parms parms; 2740 struct bnxt_ulp_mapper_data *mapper_data; 2741 int32_t rc = 0; 2742 2743 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls); 2744 if (!glbl_tmpl_list || !num_glb_tmpls) 2745 return rc; /* No global templates to process */ 2746 2747 /* Get the device id from the ulp context */ 2748 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 2749 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 2750 return -EINVAL; 2751 } 2752 2753 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2754 if (!mapper_data) { 2755 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 2756 return -EINVAL; 2757 } 2758 2759 /* Iterate the global resources and process each one */ 2760 for (idx = 0; idx < num_glb_tmpls; idx++) { 2761 /* Initialize the parms structure */ 2762 memset(&parms, 0, sizeof(parms)); 2763 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2764 parms.ulp_ctx = ulp_ctx; 2765 parms.dev_id = dev_id; 2766 parms.mapper_data = mapper_data; 2767 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT; 2768 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; 2769 2770 /* Get the class table entry from dev id and class id */ 2771 parms.class_tid = glbl_tmpl_list[idx]; 2772 2773 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 2774 if (!parms.device_params) { 2775 BNXT_TF_DBG(ERR, "No device for device id %d\n", 2776 parms.dev_id); 2777 return -EINVAL; 2778 } 2779 2780 rc = ulp_mapper_tbls_process(&parms, parms.class_tid); 2781 if (rc) 2782 return rc; 2783 } 2784 return rc; 2785 } 2786 2787 /* Function to handle the mapping of the Flow to be compatible 2788 * with the underlying hardware. 2789 */ 2790 int32_t 2791 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 2792 struct bnxt_ulp_mapper_create_parms *cparms) 2793 { 2794 struct bnxt_ulp_mapper_parms parms; 2795 struct ulp_regfile regfile; 2796 int32_t rc, trc; 2797 2798 if (!ulp_ctx || !cparms) 2799 return -EINVAL; 2800 2801 /* Initialize the parms structure */ 2802 memset(&parms, 0, sizeof(parms)); 2803 parms.act_prop = cparms->act_prop; 2804 parms.act_bitmap = cparms->act; 2805 parms.hdr_bitmap = cparms->hdr_bitmap; 2806 parms.regfile = ®file; 2807 parms.hdr_field = cparms->hdr_field; 2808 parms.comp_fld = cparms->comp_fld; 2809 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2810 parms.ulp_ctx = ulp_ctx; 2811 parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 2812 parms.act_tid = cparms->act_tid; 2813 parms.class_tid = cparms->class_tid; 2814 parms.flow_type = cparms->flow_type; 2815 parms.parent_flow = cparms->parent_flow; 2816 parms.parent_fid = cparms->parent_fid; 2817 parms.fid = cparms->flow_id; 2818 parms.tun_idx = cparms->tun_idx; 2819 2820 /* Get the device id from the ulp context */ 2821 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { 2822 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 2823 return -EINVAL; 2824 } 2825 2826 /* Get the device params, it will be used in later processing */ 2827 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 2828 if (!parms.device_params) { 2829 BNXT_TF_DBG(ERR, "No device parms for device id %d\n", 2830 parms.dev_id); 2831 return -EINVAL; 2832 } 2833 2834 /* 2835 * Get the mapper data for dynamic mapper data such as default 2836 * ids. 2837 */ 2838 parms.mapper_data = (struct bnxt_ulp_mapper_data *) 2839 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2840 if (!parms.mapper_data) { 2841 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 2842 return -EINVAL; 2843 } 2844 2845 /* initialize the registry file for further processing */ 2846 if (!ulp_regfile_init(parms.regfile)) { 2847 BNXT_TF_DBG(ERR, "regfile initialization failed.\n"); 2848 return -EINVAL; 2849 } 2850 2851 rc = ulp_regfile_write(parms.regfile, 2852 BNXT_ULP_REGFILE_INDEX_CLASS_TID, 2853 tfp_cpu_to_be_64((uint64_t)parms.class_tid)); 2854 if (!rc) { 2855 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n"); 2856 return -EINVAL; 2857 } 2858 2859 /* Process the action template list from the selected action table*/ 2860 if (parms.act_tid) { 2861 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION; 2862 /* Process the action template tables */ 2863 rc = ulp_mapper_tbls_process(&parms, parms.act_tid); 2864 if (rc) 2865 goto flow_error; 2866 } 2867 2868 if (parms.class_tid) { 2869 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; 2870 2871 /* Process the class template tables.*/ 2872 rc = ulp_mapper_tbls_process(&parms, parms.class_tid); 2873 if (rc) 2874 goto flow_error; 2875 } 2876 2877 /* setup the parent-child details */ 2878 if (parms.parent_flow) { 2879 /* create a parent flow details */ 2880 rc = ulp_flow_db_parent_flow_create(&parms); 2881 if (rc) 2882 goto flow_error; 2883 } else if (parms.parent_fid) { 2884 /* create a child flow details */ 2885 rc = ulp_flow_db_child_flow_create(&parms); 2886 if (rc) 2887 goto flow_error; 2888 } 2889 2890 return rc; 2891 2892 flow_error: 2893 /* Free all resources that were allocated during flow creation */ 2894 trc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR, 2895 parms.fid); 2896 if (trc) 2897 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); 2898 2899 return rc; 2900 } 2901 2902 int32_t 2903 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) 2904 { 2905 struct bnxt_ulp_cache_tbl_params *tbl; 2906 struct bnxt_ulp_mapper_data *data; 2907 uint32_t i; 2908 struct tf *tfp; 2909 int32_t rc, csize; 2910 2911 if (!ulp_ctx) 2912 return -EINVAL; 2913 2914 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2915 if (!tfp) 2916 return -EINVAL; 2917 2918 data = rte_zmalloc("ulp_mapper_data", 2919 sizeof(struct bnxt_ulp_mapper_data), 0); 2920 if (!data) { 2921 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n"); 2922 return -ENOMEM; 2923 } 2924 2925 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) { 2926 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n"); 2927 /* Don't call deinit since the prof_func wasn't allocated. */ 2928 rte_free(data); 2929 return -ENOMEM; 2930 } 2931 2932 /* Allocate the global resource ids */ 2933 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); 2934 if (rc) { 2935 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n"); 2936 goto error; 2937 } 2938 2939 /* Allocate the ulp cache tables. */ 2940 for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { 2941 tbl = ulp_mapper_cache_tbl_params_get(i); 2942 if (!tbl) { 2943 BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)", 2944 i); 2945 goto error; 2946 } 2947 if (tbl->num_entries != 0) { 2948 csize = sizeof(struct bnxt_ulp_mapper_cache_entry) * 2949 tbl->num_entries; 2950 data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl", 2951 csize, 0); 2952 if (!data->cache_tbl[i]) { 2953 BNXT_TF_DBG(ERR, "Failed to allocate Cache " 2954 "table %d.\n", i); 2955 rc = -ENOMEM; 2956 goto error; 2957 } 2958 } 2959 } 2960 2961 rc = ulp_mapper_glb_template_table_init(ulp_ctx); 2962 if (rc) { 2963 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n"); 2964 goto error; 2965 } 2966 2967 return 0; 2968 error: 2969 /* Ignore the return code in favor of returning the original error. */ 2970 ulp_mapper_deinit(ulp_ctx); 2971 return rc; 2972 } 2973 2974 void 2975 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) 2976 { 2977 struct bnxt_ulp_mapper_data *data; 2978 uint32_t i; 2979 struct tf *tfp; 2980 2981 if (!ulp_ctx) { 2982 BNXT_TF_DBG(ERR, 2983 "Failed to acquire ulp context, so data may " 2984 "not be released.\n"); 2985 return; 2986 } 2987 2988 data = (struct bnxt_ulp_mapper_data *) 2989 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2990 if (!data) { 2991 /* Go ahead and return since there is no allocated data. */ 2992 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n"); 2993 return; 2994 } 2995 2996 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2997 if (!tfp) { 2998 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); 2999 /* Free the mapper data regardless of errors. */ 3000 goto free_mapper_data; 3001 } 3002 3003 /* Free the global resource info table entries */ 3004 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); 3005 3006 free_mapper_data: 3007 /* Free the ulp cache tables */ 3008 for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { 3009 rte_free(data->cache_tbl[i]); 3010 data->cache_tbl[i] = NULL; 3011 } 3012 3013 rte_free(data); 3014 /* Reset the data pointer within the ulp_ctx. */ 3015 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); 3016 } 3017