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