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 get the table scope, it will be ignored if not necessary 541 * by the tf_free_tbl_entry 542 */ 543 (void)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 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST: 845 if (!ulp_operand_read(fld->result_operand, 846 (uint8_t *)&act_bit, sizeof(uint64_t))) { 847 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 848 return -EINVAL; 849 } 850 act_bit = tfp_be_to_cpu_64(act_bit); 851 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { 852 /* Action bit is set so consider operand_true */ 853 if (!ulp_operand_read(fld->result_operand_true, 854 (uint8_t *)&idx, 855 sizeof(uint16_t))) { 856 BNXT_TF_DBG(ERR, "%s operand read failed\n", 857 name); 858 return -EINVAL; 859 } 860 idx = tfp_be_to_cpu_16(idx); 861 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 862 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", 863 name, idx); 864 return -EINVAL; 865 } 866 val = &parms->act_prop->act_details[idx]; 867 field_size = ulp_mapper_act_prop_size_get(idx); 868 if (fld->field_bit_size < ULP_BYTE_2_BITS(field_size)) { 869 field_size = field_size - 870 ((fld->field_bit_size + 7) / 8); 871 val += field_size; 872 } 873 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 874 BNXT_TF_DBG(ERR, "%s push field failed\n", 875 name); 876 return -EINVAL; 877 } 878 } else { 879 /* action bit is not set, use the operand false */ 880 val = fld->result_operand_false; 881 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 882 BNXT_TF_DBG(ERR, "%s failed to add field\n", 883 name); 884 return -EINVAL; 885 } 886 } 887 break; 888 case BNXT_ULP_MAPPER_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST: 889 if (!ulp_operand_read(fld->result_operand, 890 (uint8_t *)&act_bit, sizeof(uint64_t))) { 891 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 892 return -EINVAL; 893 } 894 act_bit = tfp_be_to_cpu_64(act_bit); 895 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { 896 /* Action bit is set so consider operand_true */ 897 val = fld->result_operand_true; 898 } else { 899 /* action bit is not set, use the operand false */ 900 val = fld->result_operand_false; 901 } 902 if (!ulp_blob_push(blob, val, fld->field_bit_size)) { 903 BNXT_TF_DBG(ERR, "%s failed to add field\n", 904 name); 905 return -EINVAL; 906 } 907 break; 908 default: 909 BNXT_TF_DBG(ERR, "invalid result mapper opcode 0x%x\n", 910 fld->result_opcode); 911 return -EINVAL; 912 } 913 return 0; 914 } 915 916 /* Function to alloc action record and set the table. */ 917 static int32_t 918 ulp_mapper_keymask_field_process(struct bnxt_ulp_mapper_parms *parms, 919 enum tf_dir dir, 920 struct bnxt_ulp_mapper_class_key_field_info *f, 921 struct ulp_blob *blob, 922 uint8_t is_key, 923 const char *name) 924 { 925 uint64_t val64; 926 uint16_t idx, bitlen; 927 uint32_t opcode; 928 uint8_t *operand; 929 struct ulp_regfile *regfile = parms->regfile; 930 uint8_t *val = NULL; 931 struct bnxt_ulp_mapper_class_key_field_info *fld = f; 932 uint32_t field_size; 933 934 if (is_key) { 935 operand = fld->spec_operand; 936 opcode = fld->spec_opcode; 937 } else { 938 operand = fld->mask_operand; 939 opcode = fld->mask_opcode; 940 } 941 942 bitlen = fld->field_bit_size; 943 944 switch (opcode) { 945 case BNXT_ULP_MAPPER_OPC_SET_TO_CONSTANT: 946 val = operand; 947 if (!ulp_blob_push(blob, val, bitlen)) { 948 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 949 return -EINVAL; 950 } 951 break; 952 case BNXT_ULP_MAPPER_OPC_SET_TO_ZERO: 953 if (ulp_blob_pad_push(blob, bitlen) < 0) { 954 BNXT_TF_DBG(ERR, "%s pad too large for blob\n", name); 955 return -EINVAL; 956 } 957 958 break; 959 case BNXT_ULP_MAPPER_OPC_SET_TO_HDR_FIELD: 960 if (!ulp_operand_read(operand, (uint8_t *)&idx, 961 sizeof(uint16_t))) { 962 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 963 return -EINVAL; 964 } 965 idx = tfp_be_to_cpu_16(idx); 966 if (is_key) 967 val = parms->hdr_field[idx].spec; 968 else 969 val = parms->hdr_field[idx].mask; 970 971 /* 972 * Need to account for how much data was pushed to the header 973 * field vs how much is to be inserted in the key/mask. 974 */ 975 field_size = parms->hdr_field[idx].size; 976 if (bitlen < ULP_BYTE_2_BITS(field_size)) { 977 field_size = field_size - ((bitlen + 7) / 8); 978 val += field_size; 979 } 980 981 if (!ulp_blob_push(blob, val, bitlen)) { 982 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 983 return -EINVAL; 984 } 985 break; 986 case BNXT_ULP_MAPPER_OPC_SET_TO_COMP_FIELD: 987 if (!ulp_operand_read(operand, (uint8_t *)&idx, 988 sizeof(uint16_t))) { 989 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 990 return -EINVAL; 991 } 992 idx = tfp_be_to_cpu_16(idx); 993 if (idx < BNXT_ULP_CF_IDX_LAST) 994 val = ulp_blob_push_32(blob, &parms->comp_fld[idx], 995 bitlen); 996 if (!val) { 997 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 998 return -EINVAL; 999 } 1000 break; 1001 case BNXT_ULP_MAPPER_OPC_SET_TO_REGFILE: 1002 if (!ulp_operand_read(operand, (uint8_t *)&idx, 1003 sizeof(uint16_t))) { 1004 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 1005 return -EINVAL; 1006 } 1007 idx = tfp_be_to_cpu_16(idx); 1008 1009 if (!ulp_regfile_read(regfile, idx, &val64)) { 1010 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", 1011 name, idx); 1012 return -EINVAL; 1013 } 1014 1015 val = ulp_blob_push_64(blob, &val64, bitlen); 1016 if (!val) { 1017 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1018 return -EINVAL; 1019 } 1020 break; 1021 case BNXT_ULP_MAPPER_OPC_SET_TO_GLB_REGFILE: 1022 if (!ulp_operand_read(operand, (uint8_t *)&idx, 1023 sizeof(uint16_t))) { 1024 BNXT_TF_DBG(ERR, "%s key operand read failed.\n", name); 1025 return -EINVAL; 1026 } 1027 idx = tfp_be_to_cpu_16(idx); 1028 if (ulp_mapper_glb_resource_read(parms->mapper_data, 1029 dir, 1030 idx, &val64)) { 1031 BNXT_TF_DBG(ERR, "%s regfile[%d] read failed.\n", 1032 name, idx); 1033 return -EINVAL; 1034 } 1035 val = ulp_blob_push_64(blob, &val64, bitlen); 1036 if (!val) { 1037 BNXT_TF_DBG(ERR, "%s push to key blob failed\n", name); 1038 return -EINVAL; 1039 } 1040 break; 1041 default: 1042 BNXT_TF_DBG(ERR, "invalid keymask mapper opcode 0x%x\n", 1043 opcode); 1044 return -EINVAL; 1045 break; 1046 } 1047 1048 return 0; 1049 } 1050 1051 static int32_t 1052 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, 1053 struct bnxt_ulp_mapper_tbl_info *tbl, 1054 uint64_t flow_id) 1055 { 1056 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode; 1057 struct ulp_flow_db_res_params fid_parms; 1058 uint32_t mark, gfid, mark_flag; 1059 int32_t rc = 0; 1060 1061 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP || 1062 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION && 1063 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1064 BNXT_ULP_ACTION_BIT_MARK))) 1065 return rc; /* no need to perform gfid process */ 1066 1067 /* Get the mark id details from action property */ 1068 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1069 sizeof(mark)); 1070 mark = tfp_be_to_cpu_32(mark); 1071 1072 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid); 1073 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID; 1074 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1075 gfid, mark); 1076 if (rc) { 1077 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1078 return rc; 1079 } 1080 fid_parms.direction = tbl->direction; 1081 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1082 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1083 fid_parms.resource_type = mark_flag; 1084 fid_parms.resource_hndl = gfid; 1085 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1086 parms->tbl_idx, 1087 parms->fid, 1088 &fid_parms); 1089 if (rc) 1090 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1091 return rc; 1092 } 1093 1094 static int32_t 1095 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, 1096 struct bnxt_ulp_mapper_tbl_info *tbl) 1097 { 1098 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode; 1099 struct ulp_flow_db_res_params fid_parms; 1100 uint32_t act_idx, mark, mark_flag; 1101 uint64_t val64; 1102 int32_t rc = 0; 1103 1104 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP || 1105 !(mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION && 1106 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1107 BNXT_ULP_ACTION_BIT_MARK))) 1108 return rc; /* no need to perform mark action process */ 1109 1110 /* Get the mark id details from action property */ 1111 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1112 sizeof(mark)); 1113 mark = tfp_be_to_cpu_32(mark); 1114 1115 if (!ulp_regfile_read(parms->regfile, 1116 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR, 1117 &val64)) { 1118 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1119 return -EINVAL; 1120 } 1121 act_idx = tfp_be_to_cpu_64(val64); 1122 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID; 1123 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1124 act_idx, mark); 1125 if (rc) { 1126 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1127 return rc; 1128 } 1129 fid_parms.direction = tbl->direction; 1130 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1131 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1132 fid_parms.resource_type = mark_flag; 1133 fid_parms.resource_hndl = act_idx; 1134 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1135 parms->tbl_idx, 1136 parms->fid, 1137 &fid_parms); 1138 if (rc) 1139 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1140 return rc; 1141 } 1142 1143 static int32_t 1144 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms, 1145 struct bnxt_ulp_mapper_tbl_info *tbl) 1146 { 1147 struct ulp_flow_db_res_params fid_parms; 1148 uint32_t act_idx, mark, mark_flag; 1149 uint64_t val64; 1150 enum bnxt_ulp_mark_db_opcode mark_op = tbl->mark_db_opcode; 1151 int32_t rc = 0; 1152 1153 if (mark_op == BNXT_ULP_MARK_DB_OPCODE_NOP || 1154 mark_op == BNXT_ULP_MARK_DB_OPCODE_SET_IF_MARK_ACTION) 1155 return rc; /* no need to perform mark action process */ 1156 1157 /* Get the mark id details from the computed field of dev port id */ 1158 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID); 1159 1160 /* Get the main action pointer */ 1161 if (!ulp_regfile_read(parms->regfile, 1162 BNXT_ULP_REGFILE_INDEX_MAIN_ACTION_PTR, 1163 &val64)) { 1164 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1165 return -EINVAL; 1166 } 1167 act_idx = tfp_be_to_cpu_64(val64); 1168 1169 /* Set the mark flag to local fid and vfr flag */ 1170 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; 1171 1172 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1173 act_idx, mark); 1174 if (rc) { 1175 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1176 return rc; 1177 } 1178 fid_parms.direction = tbl->direction; 1179 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1180 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1181 fid_parms.resource_type = mark_flag; 1182 fid_parms.resource_hndl = act_idx; 1183 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1184 parms->tbl_idx, 1185 parms->fid, 1186 &fid_parms); 1187 if (rc) 1188 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1189 return rc; 1190 } 1191 1192 static int32_t 1193 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1194 struct bnxt_ulp_mapper_tbl_info *tbl) 1195 { 1196 struct bnxt_ulp_mapper_class_key_field_info *kflds; 1197 struct ulp_blob key, mask, data; 1198 uint32_t i, num_kflds; 1199 struct tf *tfp; 1200 int32_t rc, trc; 1201 struct tf_alloc_tcam_entry_parms aparms = { 0 }; 1202 struct tf_set_tcam_entry_parms sparms = { 0 }; 1203 struct ulp_flow_db_res_params fid_parms = { 0 }; 1204 struct tf_free_tcam_entry_parms free_parms = { 0 }; 1205 uint32_t hit = 0; 1206 uint16_t tmplen = 0; 1207 1208 /* Skip this if was handled by the cache. */ 1209 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP) { 1210 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1211 return 0; 1212 } 1213 1214 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1215 if (!tfp) { 1216 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1217 return -EINVAL; 1218 } 1219 1220 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); 1221 if (!kflds || !num_kflds) { 1222 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1223 return -EINVAL; 1224 } 1225 1226 if (!ulp_blob_init(&key, tbl->key_bit_size, 1227 parms->device_params->byte_order) || 1228 !ulp_blob_init(&mask, tbl->key_bit_size, 1229 parms->device_params->byte_order) || 1230 !ulp_blob_init(&data, tbl->result_bit_size, 1231 parms->device_params->byte_order)) { 1232 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1233 return -EINVAL; 1234 } 1235 1236 /* create the key/mask */ 1237 /* 1238 * NOTE: The WC table will require some kind of flag to handle the 1239 * mode bits within the key/mask 1240 */ 1241 for (i = 0; i < num_kflds; i++) { 1242 /* Setup the key */ 1243 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1244 &kflds[i], 1245 &key, 1, "TCAM Key"); 1246 if (rc) { 1247 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 1248 return rc; 1249 } 1250 1251 /* Setup the mask */ 1252 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1253 &kflds[i], 1254 &mask, 0, "TCAM Mask"); 1255 if (rc) { 1256 BNXT_TF_DBG(ERR, "Mask field set failed.\n"); 1257 return rc; 1258 } 1259 } 1260 1261 aparms.dir = tbl->direction; 1262 aparms.tcam_tbl_type = tbl->resource_type; 1263 aparms.search_enable = tbl->srch_b4_alloc; 1264 aparms.key_sz_in_bits = tbl->key_bit_size; 1265 aparms.key = ulp_blob_data_get(&key, &tmplen); 1266 if (tbl->key_bit_size != tmplen) { 1267 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n", 1268 tmplen, tbl->key_bit_size); 1269 return -EINVAL; 1270 } 1271 1272 aparms.mask = ulp_blob_data_get(&mask, &tmplen); 1273 if (tbl->key_bit_size != tmplen) { 1274 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n", 1275 tmplen, tbl->key_bit_size); 1276 return -EINVAL; 1277 } 1278 1279 aparms.priority = tbl->priority; 1280 1281 /* 1282 * All failures after this succeeds require the entry to be freed. 1283 * cannot return directly on failure, but needs to goto error 1284 */ 1285 rc = tf_alloc_tcam_entry(tfp, &aparms); 1286 if (rc) { 1287 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); 1288 return rc; 1289 } 1290 1291 hit = aparms.hit; 1292 1293 /* Build the result */ 1294 if (!tbl->srch_b4_alloc || !hit) { 1295 struct bnxt_ulp_mapper_result_field_info *dflds; 1296 struct bnxt_ulp_mapper_ident_info *idents; 1297 uint32_t num_dflds, num_idents; 1298 uint32_t encap_flds = 0; 1299 1300 /* 1301 * Since the cache entry is responsible for allocating 1302 * identifiers when in use, allocate the identifiers only 1303 * during normal processing. 1304 */ 1305 if (parms->tcam_tbl_opc == 1306 BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) { 1307 idents = ulp_mapper_ident_fields_get(tbl, &num_idents); 1308 1309 for (i = 0; i < num_idents; i++) { 1310 rc = ulp_mapper_ident_process(parms, tbl, 1311 &idents[i], NULL); 1312 /* Already logged the error, just return */ 1313 if (rc) 1314 goto error; 1315 } 1316 } 1317 1318 /* Create the result data blob */ 1319 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds, 1320 &encap_flds); 1321 if (!dflds || !num_dflds || encap_flds) { 1322 BNXT_TF_DBG(ERR, "Failed to get data fields.\n"); 1323 rc = -EINVAL; 1324 goto error; 1325 } 1326 1327 for (i = 0; i < num_dflds; i++) { 1328 rc = ulp_mapper_result_field_process(parms, 1329 tbl->direction, 1330 &dflds[i], 1331 &data, 1332 "TCAM Result"); 1333 if (rc) { 1334 BNXT_TF_DBG(ERR, "Failed to set data fields\n"); 1335 goto error; 1336 } 1337 } 1338 1339 sparms.dir = aparms.dir; 1340 sparms.tcam_tbl_type = aparms.tcam_tbl_type; 1341 sparms.idx = aparms.idx; 1342 /* Already verified the key/mask lengths */ 1343 sparms.key = ulp_blob_data_get(&key, &tmplen); 1344 sparms.mask = ulp_blob_data_get(&mask, &tmplen); 1345 sparms.key_sz_in_bits = tbl->key_bit_size; 1346 sparms.result = ulp_blob_data_get(&data, &tmplen); 1347 1348 if (tbl->result_bit_size != tmplen) { 1349 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n", 1350 tmplen, tbl->result_bit_size); 1351 rc = -EINVAL; 1352 goto error; 1353 } 1354 sparms.result_sz_in_bits = tbl->result_bit_size; 1355 1356 rc = tf_set_tcam_entry(tfp, &sparms); 1357 if (rc) { 1358 BNXT_TF_DBG(ERR, "tcam[%d][%s][%d] write failed.\n", 1359 sparms.tcam_tbl_type, 1360 (sparms.dir == TF_DIR_RX) ? "RX" : "TX", 1361 sparms.idx); 1362 goto error; 1363 } 1364 1365 /* Update cache with TCAM index if the was cache allocated. */ 1366 if (parms->tcam_tbl_opc == 1367 BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC) { 1368 if (!parms->cache_ptr) { 1369 BNXT_TF_DBG(ERR, "Unable to update cache"); 1370 rc = -EINVAL; 1371 goto error; 1372 } 1373 parms->cache_ptr->tcam_idx = aparms.idx; 1374 } 1375 1376 /* Mark action */ 1377 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1378 if (rc) 1379 goto error; 1380 1381 } else { 1382 BNXT_TF_DBG(ERR, "Not supporting search before alloc now\n"); 1383 rc = -EINVAL; 1384 goto error; 1385 } 1386 1387 /* 1388 * Only link the entry to the flow db in the event that cache was not 1389 * used. 1390 */ 1391 if (parms->tcam_tbl_opc == BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL) { 1392 fid_parms.direction = tbl->direction; 1393 fid_parms.resource_func = tbl->resource_func; 1394 fid_parms.resource_type = tbl->resource_type; 1395 fid_parms.critical_resource = tbl->critical_resource; 1396 fid_parms.resource_hndl = aparms.idx; 1397 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1398 parms->tbl_idx, 1399 parms->fid, 1400 &fid_parms); 1401 if (rc) { 1402 BNXT_TF_DBG(ERR, 1403 "Failed to link resource to flow rc = %d\n", 1404 rc); 1405 /* Need to free the identifier, so goto error */ 1406 goto error; 1407 } 1408 } else { 1409 /* 1410 * Reset the tcam table opcode to normal in case the next tcam 1411 * entry does not use cache. 1412 */ 1413 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1414 parms->cache_ptr = NULL; 1415 } 1416 1417 return 0; 1418 error: 1419 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 1420 free_parms.dir = tbl->direction; 1421 free_parms.tcam_tbl_type = tbl->resource_type; 1422 free_parms.idx = aparms.idx; 1423 trc = tf_free_tcam_entry(tfp, &free_parms); 1424 if (trc) 1425 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", 1426 tbl->resource_type, tbl->direction, aparms.idx); 1427 1428 return rc; 1429 } 1430 1431 static int32_t 1432 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1433 struct bnxt_ulp_mapper_tbl_info *tbl) 1434 { 1435 struct bnxt_ulp_mapper_class_key_field_info *kflds; 1436 struct bnxt_ulp_mapper_result_field_info *dflds; 1437 struct ulp_blob key, data; 1438 uint32_t i, num_kflds, num_dflds; 1439 uint16_t tmplen; 1440 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1441 struct ulp_flow_db_res_params fid_parms = { 0 }; 1442 struct tf_insert_em_entry_parms iparms = { 0 }; 1443 struct tf_delete_em_entry_parms free_parms = { 0 }; 1444 int32_t trc; 1445 enum bnxt_ulp_flow_mem_type mtype = parms->device_params->flow_mem_type; 1446 int32_t rc = 0; 1447 uint32_t encap_flds = 0; 1448 1449 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); 1450 if (!kflds || !num_kflds) { 1451 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1452 return -EINVAL; 1453 } 1454 1455 /* Initialize the key/result blobs */ 1456 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, 1457 parms->device_params->byte_order) || 1458 !ulp_blob_init(&data, tbl->result_bit_size, 1459 parms->device_params->byte_order)) { 1460 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1461 return -EINVAL; 1462 } 1463 1464 /* create the key */ 1465 for (i = 0; i < num_kflds; i++) { 1466 /* Setup the key */ 1467 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1468 &kflds[i], 1469 &key, 1, "EM Key"); 1470 if (rc) { 1471 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 1472 return rc; 1473 } 1474 } 1475 1476 /* 1477 * TBD: Normally should process identifiers in case of using recycle or 1478 * loopback. Not supporting recycle for now. 1479 */ 1480 1481 /* Create the result data blob */ 1482 dflds = ulp_mapper_result_fields_get(tbl, &num_dflds, &encap_flds); 1483 if (!dflds || !num_dflds || encap_flds) { 1484 BNXT_TF_DBG(ERR, "Failed to get data fields.\n"); 1485 return -EINVAL; 1486 } 1487 1488 for (i = 0; i < num_dflds; i++) { 1489 struct bnxt_ulp_mapper_result_field_info *fld; 1490 1491 fld = &dflds[i]; 1492 1493 rc = ulp_mapper_result_field_process(parms, 1494 tbl->direction, 1495 fld, 1496 &data, 1497 "EM Result"); 1498 if (rc) { 1499 BNXT_TF_DBG(ERR, "Failed to set data fields.\n"); 1500 return rc; 1501 } 1502 } 1503 1504 /* do the transpose for the internal EM keys */ 1505 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) 1506 ulp_blob_perform_byte_reverse(&key); 1507 1508 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, 1509 &iparms.tbl_scope_id); 1510 if (rc) { 1511 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1512 return rc; 1513 } 1514 1515 /* 1516 * NOTE: the actual blob size will differ from the size in the tbl 1517 * entry due to the padding. 1518 */ 1519 iparms.dup_check = 0; 1520 iparms.dir = tbl->direction; 1521 iparms.mem = tbl->resource_type; 1522 iparms.key = ulp_blob_data_get(&key, &tmplen); 1523 iparms.key_sz_in_bits = tbl->key_bit_size; 1524 iparms.em_record = ulp_blob_data_get(&data, &tmplen); 1525 iparms.em_record_sz_in_bits = tbl->result_bit_size; 1526 1527 rc = tf_insert_em_entry(tfp, &iparms); 1528 if (rc) { 1529 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc); 1530 return rc; 1531 } 1532 1533 /* Mark action process */ 1534 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && 1535 tbl->resource_type == TF_MEM_EXTERNAL) 1536 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); 1537 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && 1538 tbl->resource_type == TF_MEM_INTERNAL) 1539 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1540 if (rc) { 1541 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1542 goto error; 1543 } 1544 1545 /* Link the EM resource to the flow in the flow db */ 1546 memset(&fid_parms, 0, sizeof(fid_parms)); 1547 fid_parms.direction = tbl->direction; 1548 fid_parms.resource_func = tbl->resource_func; 1549 fid_parms.resource_type = tbl->resource_type; 1550 fid_parms.critical_resource = tbl->critical_resource; 1551 fid_parms.resource_hndl = iparms.flow_handle; 1552 1553 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1554 parms->tbl_idx, 1555 parms->fid, 1556 &fid_parms); 1557 if (rc) { 1558 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", 1559 rc); 1560 /* Need to free the identifier, so goto error */ 1561 goto error; 1562 } 1563 1564 return 0; 1565 error: 1566 free_parms.dir = iparms.dir; 1567 free_parms.mem = iparms.mem; 1568 free_parms.tbl_scope_id = iparms.tbl_scope_id; 1569 free_parms.flow_handle = iparms.flow_handle; 1570 1571 trc = tf_delete_em_entry(tfp, &free_parms); 1572 if (trc) 1573 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n"); 1574 1575 return rc; 1576 } 1577 1578 static int32_t 1579 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1580 struct bnxt_ulp_mapper_tbl_info *tbl, 1581 bool is_class_tbl) 1582 { 1583 struct bnxt_ulp_mapper_result_field_info *flds; 1584 struct ulp_flow_db_res_params fid_parms; 1585 struct ulp_blob data; 1586 uint64_t idx = 0; 1587 uint16_t tmplen; 1588 uint32_t i, num_flds; 1589 int32_t rc = 0, trc = 0; 1590 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 1591 struct tf_set_tbl_entry_parms sparms = { 0 }; 1592 struct tf_free_tbl_entry_parms free_parms = { 0 }; 1593 uint32_t tbl_scope_id; 1594 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1595 uint16_t bit_size; 1596 uint32_t encap_flds = 0; 1597 1598 /* Get the scope id first */ 1599 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); 1600 if (rc) { 1601 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1602 return rc; 1603 } 1604 1605 /* use the max size if encap is enabled */ 1606 if (tbl->encap_num_fields) 1607 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 1608 else 1609 bit_size = tbl->result_bit_size; 1610 1611 /* Initialize the blob data */ 1612 if (!ulp_blob_init(&data, bit_size, 1613 parms->device_params->byte_order)) { 1614 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 1615 return -EINVAL; 1616 } 1617 1618 /* Get the result fields list */ 1619 if (is_class_tbl) 1620 flds = ulp_mapper_result_fields_get(tbl, &num_flds, 1621 &encap_flds); 1622 else 1623 flds = ulp_mapper_act_result_fields_get(tbl, &num_flds, 1624 &encap_flds); 1625 1626 if (!flds || (!num_flds && !encap_flds)) { 1627 BNXT_TF_DBG(ERR, "template undefined for the index table\n"); 1628 return -EINVAL; 1629 } 1630 1631 /* process the result fields, loop through them */ 1632 for (i = 0; i < (num_flds + encap_flds); i++) { 1633 /* set the swap index if encap swap bit is enabled */ 1634 if (parms->device_params->encap_byte_swap && encap_flds && 1635 (i == num_flds)) 1636 ulp_blob_encap_swap_idx_set(&data); 1637 1638 /* Process the result fields */ 1639 rc = ulp_mapper_result_field_process(parms, 1640 tbl->direction, 1641 &flds[i], 1642 &data, 1643 "Indexed Result"); 1644 if (rc) { 1645 BNXT_TF_DBG(ERR, "data field failed\n"); 1646 return rc; 1647 } 1648 } 1649 1650 /* if encap bit swap is enabled perform the bit swap */ 1651 if (parms->device_params->encap_byte_swap && encap_flds) { 1652 ulp_blob_perform_encap_swap(&data); 1653 } 1654 1655 /* 1656 * Check for index opcode, if it is Global then 1657 * no need to allocate the table, just set the table 1658 * and exit since it is not maintained in the flow db. 1659 */ 1660 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_GLOBAL) { 1661 /* get the index from index operand */ 1662 if (tbl->index_operand < BNXT_ULP_GLB_REGFILE_INDEX_LAST && 1663 ulp_mapper_glb_resource_read(parms->mapper_data, 1664 tbl->direction, 1665 tbl->index_operand, 1666 &idx)) { 1667 BNXT_TF_DBG(ERR, "Glbl regfile[%d] read failed.\n", 1668 tbl->index_operand); 1669 return -EINVAL; 1670 } 1671 /* set the Tf index table */ 1672 sparms.dir = tbl->direction; 1673 sparms.type = tbl->resource_type; 1674 sparms.data = ulp_blob_data_get(&data, &tmplen); 1675 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 1676 sparms.idx = tfp_be_to_cpu_64(idx); 1677 sparms.tbl_scope_id = tbl_scope_id; 1678 1679 rc = tf_set_tbl_entry(tfp, &sparms); 1680 if (rc) { 1681 BNXT_TF_DBG(ERR, 1682 "Glbl Set table[%d][%s][%d] failed rc=%d\n", 1683 sparms.type, 1684 (sparms.dir == TF_DIR_RX) ? "RX" : "TX", 1685 sparms.idx, 1686 rc); 1687 return rc; 1688 } 1689 return 0; /* success */ 1690 } 1691 1692 /* Perform the tf table allocation by filling the alloc params */ 1693 aparms.dir = tbl->direction; 1694 aparms.type = tbl->resource_type; 1695 aparms.search_enable = tbl->srch_b4_alloc; 1696 aparms.result = ulp_blob_data_get(&data, &tmplen); 1697 aparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 1698 aparms.tbl_scope_id = tbl_scope_id; 1699 1700 /* All failures after the alloc succeeds require a free */ 1701 rc = tf_alloc_tbl_entry(tfp, &aparms); 1702 if (rc) { 1703 BNXT_TF_DBG(ERR, "Alloc table[%d][%s] failed rc=%d\n", 1704 aparms.type, 1705 (aparms.dir == TF_DIR_RX) ? "RX" : "TX", 1706 rc); 1707 return rc; 1708 } 1709 1710 /* 1711 * calculate the idx for the result record, for external EM the offset 1712 * needs to be shifted accordingly. If external non-inline table types 1713 * are used then need to revisit this logic. 1714 */ 1715 if (aparms.type == TF_TBL_TYPE_EXT) 1716 idx = TF_ACT_REC_OFFSET_2_PTR(aparms.idx); 1717 else 1718 idx = aparms.idx; 1719 1720 /* Always storing values in Regfile in BE */ 1721 idx = tfp_cpu_to_be_64(idx); 1722 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_ALLOCATE) { 1723 rc = ulp_regfile_write(parms->regfile, tbl->index_operand, idx); 1724 if (!rc) { 1725 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 1726 tbl->index_operand); 1727 goto error; 1728 } 1729 } 1730 1731 /* Perform the tf table set by filling the set params */ 1732 if (!tbl->srch_b4_alloc || !aparms.hit) { 1733 sparms.dir = tbl->direction; 1734 sparms.type = tbl->resource_type; 1735 sparms.data = ulp_blob_data_get(&data, &tmplen); 1736 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 1737 sparms.idx = aparms.idx; 1738 sparms.tbl_scope_id = tbl_scope_id; 1739 1740 rc = tf_set_tbl_entry(tfp, &sparms); 1741 if (rc) { 1742 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n", 1743 sparms.type, 1744 (sparms.dir == TF_DIR_RX) ? "RX" : "TX", 1745 sparms.idx, 1746 rc); 1747 goto error; 1748 } 1749 } 1750 1751 /* Link the resource to the flow in the flow db */ 1752 memset(&fid_parms, 0, sizeof(fid_parms)); 1753 fid_parms.direction = tbl->direction; 1754 fid_parms.resource_func = tbl->resource_func; 1755 fid_parms.resource_type = tbl->resource_type; 1756 fid_parms.resource_sub_type = tbl->resource_sub_type; 1757 fid_parms.resource_hndl = aparms.idx; 1758 fid_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 1759 1760 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1761 parms->tbl_idx, 1762 parms->fid, 1763 &fid_parms); 1764 if (rc) { 1765 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 1766 rc); 1767 goto error; 1768 } 1769 1770 /* Perform the VF rep action */ 1771 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 1772 if (rc) { 1773 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 1774 goto error; 1775 } 1776 return rc; 1777 error: 1778 /* 1779 * Free the allocated resource since we failed to either 1780 * write to the entry or link the flow 1781 */ 1782 free_parms.dir = tbl->direction; 1783 free_parms.type = tbl->resource_type; 1784 free_parms.idx = aparms.idx; 1785 free_parms.tbl_scope_id = tbl_scope_id; 1786 1787 trc = tf_free_tbl_entry(tfp, &free_parms); 1788 if (trc) 1789 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n"); 1790 1791 return rc; 1792 } 1793 1794 static int32_t 1795 ulp_mapper_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1796 struct bnxt_ulp_mapper_tbl_info *tbl) 1797 { 1798 struct bnxt_ulp_mapper_class_key_field_info *kflds; 1799 struct bnxt_ulp_mapper_cache_entry *cache_entry; 1800 struct bnxt_ulp_mapper_ident_info *idents; 1801 uint32_t i, num_kflds = 0, num_idents = 0; 1802 struct ulp_flow_db_res_params fid_parms; 1803 struct tf_free_identifier_parms fparms; 1804 uint16_t tmplen, tmp_ident; 1805 struct ulp_blob key; 1806 uint8_t *cache_key; 1807 uint64_t regval; 1808 uint16_t *ckey; 1809 int32_t rc; 1810 1811 /* Get the key fields list and build the key. */ 1812 kflds = ulp_mapper_key_fields_get(tbl, &num_kflds); 1813 if (!kflds || !num_kflds) { 1814 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1815 return -EINVAL; 1816 } 1817 if (!ulp_blob_init(&key, tbl->key_bit_size, 1818 parms->device_params->byte_order)) { 1819 BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); 1820 return -EINVAL; 1821 } 1822 for (i = 0; i < num_kflds; i++) { 1823 /* Setup the key */ 1824 rc = ulp_mapper_keymask_field_process(parms, tbl->direction, 1825 &kflds[i], 1826 &key, 1, "Cache Key"); 1827 if (rc) { 1828 BNXT_TF_DBG(ERR, 1829 "Failed to create key for Cache rc=%d\n", 1830 rc); 1831 return -EINVAL; 1832 } 1833 } 1834 1835 /* 1836 * Perform the lookup in the cache table with constructed key. The 1837 * cache_key is a byte array of tmplen, it needs to be converted to a 1838 * index for the cache table. 1839 */ 1840 cache_key = ulp_blob_data_get(&key, &tmplen); 1841 ckey = (uint16_t *)cache_key; 1842 1843 /* 1844 * The id computed based on resource sub type and direction where 1845 * dir is the bit0 and rest of the bits come from resource 1846 * sub type. 1847 */ 1848 cache_entry = ulp_mapper_cache_entry_get(parms->ulp_ctx, 1849 (tbl->resource_sub_type << 1 | 1850 (tbl->direction & 0x1)), 1851 *ckey); 1852 1853 /* 1854 * Get the identifier list for processing by both the hit and miss 1855 * processing. 1856 */ 1857 idents = ulp_mapper_ident_fields_get(tbl, &num_idents); 1858 1859 if (!cache_entry->ref_count) { 1860 /* Initialize the cache entry */ 1861 cache_entry->tcam_idx = 0; 1862 cache_entry->ref_count = 0; 1863 for (i = 0; i < BNXT_ULP_CACHE_TBL_IDENT_MAX_NUM; i++) 1864 cache_entry->idents[i] = ULP_IDENTS_INVALID; 1865 1866 /* Need to allocate identifiers for storing in the cache. */ 1867 for (i = 0; i < num_idents; i++) { 1868 /* 1869 * Since we are using the cache, the identifier does not 1870 * get added to the flow db. Pass in the pointer to the 1871 * tmp_ident. 1872 */ 1873 rc = ulp_mapper_ident_process(parms, tbl, 1874 &idents[i], &tmp_ident); 1875 if (rc) 1876 goto error; 1877 1878 cache_entry->ident_types[i] = idents[i].ident_type; 1879 cache_entry->idents[i] = tmp_ident; 1880 } 1881 1882 /* Tell the TCAM processor to alloc an entry */ 1883 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_ALLOC; 1884 /* Store the cache key for use by the tcam process code */ 1885 parms->cache_ptr = cache_entry; 1886 } else { 1887 /* Cache hit, get values from result. */ 1888 for (i = 0; i < num_idents; i++) { 1889 regval = (uint64_t)cache_entry->idents[i]; 1890 if (!ulp_regfile_write(parms->regfile, 1891 idents[i].regfile_idx, 1892 tfp_cpu_to_be_64(regval))) { 1893 BNXT_TF_DBG(ERR, 1894 "Failed to write to regfile\n"); 1895 return -EINVAL; 1896 } 1897 } 1898 /* 1899 * The cached entry is being used, so let the tcam processing 1900 * know not to process this table. 1901 */ 1902 parms->tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_CACHE_SKIP; 1903 } 1904 1905 /* Made through the cache processing, increment the reference count. */ 1906 cache_entry->ref_count++; 1907 1908 /* Link the cache to the flow db. */ 1909 memset(&fid_parms, 0, sizeof(fid_parms)); 1910 fid_parms.direction = tbl->direction; 1911 fid_parms.resource_func = tbl->resource_func; 1912 1913 /* 1914 * Cache resource type is composed of table_type, resource 1915 * sub type and direction, it needs to set appropriately via setter. 1916 */ 1917 ulp_mapper_cache_res_type_set(&fid_parms, 1918 tbl->resource_type, 1919 (tbl->resource_sub_type << 1 | 1920 (tbl->direction & 0x1))); 1921 fid_parms.resource_hndl = (uint64_t)*ckey; 1922 fid_parms.critical_resource = tbl->critical_resource; 1923 rc = ulp_flow_db_resource_add(parms->ulp_ctx, 1924 parms->tbl_idx, 1925 parms->fid, 1926 &fid_parms); 1927 if (rc) 1928 BNXT_TF_DBG(ERR, "Failed to add cache to flow db.\n"); 1929 1930 return rc; 1931 error: 1932 /* 1933 * This error handling only gets called when the idents are being 1934 * allocated for the cache on misses. Using the num_idents that was 1935 * previously set. 1936 */ 1937 for (i = 0; i < num_idents; i++) { 1938 if (cache_entry->idents[i] == ULP_IDENTS_INVALID) 1939 continue; 1940 1941 fparms.dir = tbl->direction; 1942 fparms.ident_type = idents[i].ident_type; 1943 fparms.id = cache_entry->idents[i]; 1944 tf_free_identifier(parms->tfp, &fparms); 1945 } 1946 1947 return rc; 1948 } 1949 1950 static int32_t 1951 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1952 struct bnxt_ulp_mapper_tbl_info *tbl) 1953 { 1954 struct bnxt_ulp_mapper_result_field_info *flds; 1955 struct ulp_blob data; 1956 uint64_t idx; 1957 uint16_t tmplen; 1958 uint32_t i, num_flds; 1959 int32_t rc = 0; 1960 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; 1961 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1962 uint32_t encap_flds; 1963 1964 /* Initialize the blob data */ 1965 if (!ulp_blob_init(&data, tbl->result_bit_size, 1966 parms->device_params->byte_order)) { 1967 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 1968 return -EINVAL; 1969 } 1970 1971 /* Get the result fields list */ 1972 flds = ulp_mapper_result_fields_get(tbl, &num_flds, &encap_flds); 1973 1974 if (!flds || !num_flds || encap_flds) { 1975 BNXT_TF_DBG(ERR, "template undefined for the IF table\n"); 1976 return -EINVAL; 1977 } 1978 1979 /* process the result fields, loop through them */ 1980 for (i = 0; i < num_flds; i++) { 1981 /* Process the result fields */ 1982 rc = ulp_mapper_result_field_process(parms, 1983 tbl->direction, 1984 &flds[i], 1985 &data, 1986 "IFtable Result"); 1987 if (rc) { 1988 BNXT_TF_DBG(ERR, "data field failed\n"); 1989 return rc; 1990 } 1991 } 1992 1993 /* Get the index details from computed field */ 1994 if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_COMP_FIELD) { 1995 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->index_operand); 1996 } else if (tbl->index_opcode == BNXT_ULP_INDEX_OPCODE_CONSTANT) { 1997 idx = tbl->index_operand; 1998 } else { 1999 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); 2000 return -EINVAL; 2001 } 2002 2003 /* Perform the tf table set by filling the set params */ 2004 iftbl_params.dir = tbl->direction; 2005 iftbl_params.type = tbl->resource_type; 2006 iftbl_params.data = ulp_blob_data_get(&data, &tmplen); 2007 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2008 iftbl_params.idx = idx; 2009 2010 rc = tf_set_if_tbl_entry(tfp, &iftbl_params); 2011 if (rc) { 2012 BNXT_TF_DBG(ERR, "Set table[%d][%s][%d] failed rc=%d\n", 2013 iftbl_params.type, 2014 (iftbl_params.dir == TF_DIR_RX) ? "RX" : "TX", 2015 iftbl_params.idx, 2016 rc); 2017 return rc; 2018 } 2019 2020 /* 2021 * TBD: Need to look at the need to store idx in flow db for restore 2022 * the table to its original state on deletion of this entry. 2023 */ 2024 return rc; 2025 } 2026 2027 static int32_t 2028 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 2029 struct bnxt_ulp_mapper_data *mapper_data) 2030 { 2031 struct bnxt_ulp_glb_resource_info *glb_res; 2032 uint32_t num_glb_res_ids, idx; 2033 int32_t rc = 0; 2034 2035 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); 2036 if (!glb_res || !num_glb_res_ids) { 2037 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 2038 return -EINVAL; 2039 } 2040 2041 /* Iterate the global resources and process each one */ 2042 for (idx = 0; idx < num_glb_res_ids; idx++) { 2043 switch (glb_res[idx].resource_func) { 2044 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2045 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 2046 mapper_data, 2047 &glb_res[idx]); 2048 break; 2049 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2050 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 2051 mapper_data, 2052 &glb_res[idx]); 2053 break; 2054 default: 2055 BNXT_TF_DBG(ERR, "Global resource %x not supported\n", 2056 glb_res[idx].resource_func); 2057 rc = -EINVAL; 2058 break; 2059 } 2060 if (rc) 2061 return rc; 2062 } 2063 return rc; 2064 } 2065 2066 /* 2067 * Function to process the conditional opcode of the mapper table. 2068 * returns 1 to skip the table. 2069 * return 0 to continue processing the table. 2070 */ 2071 static int32_t 2072 ulp_mapper_tbl_cond_opcode_process(struct bnxt_ulp_mapper_parms *parms, 2073 struct bnxt_ulp_mapper_tbl_info *tbl) 2074 { 2075 int32_t rc = 1; 2076 2077 switch (tbl->cond_opcode) { 2078 case BNXT_ULP_COND_OPCODE_NOP: 2079 rc = 0; 2080 break; 2081 case BNXT_ULP_COND_OPCODE_COMP_FIELD_IS_SET: 2082 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && 2083 ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) 2084 rc = 0; 2085 break; 2086 case BNXT_ULP_COND_OPCODE_ACTION_BIT_IS_SET: 2087 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2088 tbl->cond_operand)) 2089 rc = 0; 2090 break; 2091 case BNXT_ULP_COND_OPCODE_HDR_BIT_IS_SET: 2092 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2093 tbl->cond_operand)) 2094 rc = 0; 2095 break; 2096 case BNXT_ULP_COND_OPCODE_COMP_FIELD_NOT_SET: 2097 if (tbl->cond_operand < BNXT_ULP_CF_IDX_LAST && 2098 !ULP_COMP_FLD_IDX_RD(parms, tbl->cond_operand)) 2099 rc = 0; 2100 break; 2101 case BNXT_ULP_COND_OPCODE_ACTION_BIT_NOT_SET: 2102 if (!ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2103 tbl->cond_operand)) 2104 rc = 0; 2105 break; 2106 case BNXT_ULP_COND_OPCODE_HDR_BIT_NOT_SET: 2107 if (!ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2108 tbl->cond_operand)) 2109 rc = 0; 2110 break; 2111 default: 2112 BNXT_TF_DBG(ERR, 2113 "Invalid arg in mapper tbl for cond opcode\n"); 2114 break; 2115 } 2116 return rc; 2117 } 2118 2119 /* 2120 * Function to process the action template. Iterate through the list 2121 * action info templates and process it. 2122 */ 2123 static int32_t 2124 ulp_mapper_action_tbls_process(struct bnxt_ulp_mapper_parms *parms) 2125 { 2126 uint32_t i; 2127 int32_t rc = 0; 2128 struct bnxt_ulp_mapper_tbl_info *tbl; 2129 2130 if (!parms->atbls || !parms->num_atbls) { 2131 BNXT_TF_DBG(ERR, "No action tables for template[%d][%d].\n", 2132 parms->dev_id, parms->act_tid); 2133 return -EINVAL; 2134 } 2135 2136 for (i = 0; i < parms->num_atbls; i++) { 2137 tbl = &parms->atbls[i]; 2138 if (ulp_mapper_tbl_cond_opcode_process(parms, tbl)) 2139 continue; 2140 2141 switch (tbl->resource_func) { 2142 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2143 rc = ulp_mapper_index_tbl_process(parms, tbl, false); 2144 if (rc) { 2145 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 2146 tbl->resource_func); 2147 return rc; 2148 } 2149 break; 2150 default: 2151 BNXT_TF_DBG(ERR, "Unexpected action resource %d\n", 2152 tbl->resource_func); 2153 return -EINVAL; 2154 } 2155 } 2156 2157 return rc; 2158 } 2159 2160 /* Create the classifier table entries for a flow. */ 2161 static int32_t 2162 ulp_mapper_class_tbls_process(struct bnxt_ulp_mapper_parms *parms) 2163 { 2164 uint32_t i; 2165 int32_t rc = 0; 2166 2167 if (!parms) 2168 return -EINVAL; 2169 2170 if (!parms->ctbls || !parms->num_ctbls) { 2171 BNXT_TF_DBG(ERR, "No class tables for template[%d][%d].\n", 2172 parms->dev_id, parms->class_tid); 2173 return -EINVAL; 2174 } 2175 2176 for (i = 0; i < parms->num_ctbls; i++) { 2177 struct bnxt_ulp_mapper_tbl_info *tbl = &parms->ctbls[i]; 2178 2179 if (ulp_mapper_tbl_cond_opcode_process(parms, tbl)) 2180 continue; 2181 2182 switch (tbl->resource_func) { 2183 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2184 rc = ulp_mapper_tcam_tbl_process(parms, tbl); 2185 break; 2186 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2187 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2188 rc = ulp_mapper_em_tbl_process(parms, tbl); 2189 break; 2190 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2191 rc = ulp_mapper_index_tbl_process(parms, tbl, true); 2192 break; 2193 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: 2194 rc = ulp_mapper_cache_tbl_process(parms, tbl); 2195 break; 2196 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: 2197 rc = ulp_mapper_if_tbl_process(parms, tbl); 2198 break; 2199 default: 2200 BNXT_TF_DBG(ERR, "Unexpected class resource %d\n", 2201 tbl->resource_func); 2202 return -EINVAL; 2203 } 2204 2205 if (rc) { 2206 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 2207 tbl->resource_func); 2208 return rc; 2209 } 2210 } 2211 2212 return rc; 2213 } 2214 2215 static int32_t 2216 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 2217 struct ulp_flow_db_res_params *res) 2218 { 2219 struct tf *tfp; 2220 int32_t rc = 0; 2221 2222 if (!res || !ulp) { 2223 BNXT_TF_DBG(ERR, "Unable to free resource\n "); 2224 return -EINVAL; 2225 } 2226 2227 tfp = bnxt_ulp_cntxt_tfp_get(ulp); 2228 if (!tfp) { 2229 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n"); 2230 return -EINVAL; 2231 } 2232 2233 switch (res->resource_func) { 2234 case BNXT_ULP_RESOURCE_FUNC_CACHE_TABLE: 2235 rc = ulp_mapper_cache_entry_free(ulp, tfp, res); 2236 break; 2237 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2238 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res); 2239 break; 2240 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2241 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2242 rc = ulp_mapper_em_entry_free(ulp, tfp, res); 2243 break; 2244 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2245 rc = ulp_mapper_index_entry_free(ulp, tfp, res); 2246 break; 2247 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2248 rc = ulp_mapper_ident_free(ulp, tfp, res); 2249 break; 2250 case BNXT_ULP_RESOURCE_FUNC_HW_FID: 2251 rc = ulp_mapper_mark_free(ulp, res); 2252 break; 2253 default: 2254 break; 2255 } 2256 2257 return rc; 2258 } 2259 2260 int32_t 2261 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, 2262 uint32_t fid, 2263 enum bnxt_ulp_flow_db_tables tbl_type) 2264 { 2265 struct ulp_flow_db_res_params res_parms = { 0 }; 2266 int32_t rc, trc; 2267 2268 if (!ulp_ctx) { 2269 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 2270 return -EINVAL; 2271 } 2272 2273 /* 2274 * Set the critical resource on the first resource del, then iterate 2275 * while status is good 2276 */ 2277 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; 2278 rc = ulp_flow_db_resource_del(ulp_ctx, tbl_type, fid, &res_parms); 2279 2280 if (rc) { 2281 /* 2282 * This is unexpected on the first call to resource del. 2283 * It likely means that the flow did not exist in the flow db. 2284 */ 2285 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", 2286 tbl_type, fid, rc); 2287 return rc; 2288 } 2289 2290 while (!rc) { 2291 trc = ulp_mapper_resource_free(ulp_ctx, &res_parms); 2292 if (trc) 2293 /* 2294 * On fail, we still need to attempt to free the 2295 * remaining resources. Don't return 2296 */ 2297 BNXT_TF_DBG(ERR, 2298 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64 2299 "] failed rc=%d.\n", 2300 tbl_type, fid, res_parms.resource_func, 2301 res_parms.resource_hndl, trc); 2302 2303 /* All subsequent call require the non-critical_resource */ 2304 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 2305 2306 rc = ulp_flow_db_resource_del(ulp_ctx, 2307 tbl_type, 2308 fid, 2309 &res_parms); 2310 } 2311 2312 /* Free the Flow ID since we've removed all resources */ 2313 rc = ulp_flow_db_fid_free(ulp_ctx, tbl_type, fid); 2314 2315 return rc; 2316 } 2317 2318 static void 2319 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, 2320 struct bnxt_ulp_mapper_data *mapper_data) 2321 { 2322 struct bnxt_ulp_mapper_glb_resource_entry *ent; 2323 struct ulp_flow_db_res_params res; 2324 uint32_t dir, idx; 2325 2326 /* Iterate the global resources and process each one */ 2327 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { 2328 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 2329 idx++) { 2330 ent = &mapper_data->glb_res_tbl[dir][idx]; 2331 if (ent->resource_func == 2332 BNXT_ULP_RESOURCE_FUNC_INVALID) 2333 continue; 2334 memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); 2335 res.resource_func = ent->resource_func; 2336 res.direction = dir; 2337 res.resource_type = ent->resource_type; 2338 /*convert it from BE to cpu */ 2339 res.resource_hndl = 2340 tfp_be_to_cpu_64(ent->resource_hndl); 2341 ulp_mapper_resource_free(ulp_ctx, &res); 2342 } 2343 } 2344 } 2345 2346 int32_t 2347 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, uint32_t fid, 2348 enum bnxt_ulp_flow_db_tables flow_tbl_type) 2349 { 2350 if (!ulp_ctx) { 2351 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 2352 return -EINVAL; 2353 } 2354 2355 return ulp_mapper_resources_free(ulp_ctx, fid, flow_tbl_type); 2356 } 2357 2358 /* Function to handle the default global templates that are allocated during 2359 * the startup and reused later. 2360 */ 2361 static int32_t 2362 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx) 2363 { 2364 uint32_t *glbl_tmpl_list; 2365 uint32_t num_glb_tmpls, idx, dev_id; 2366 struct bnxt_ulp_mapper_parms parms; 2367 struct bnxt_ulp_mapper_data *mapper_data; 2368 int32_t rc = 0; 2369 2370 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls); 2371 if (!glbl_tmpl_list || !num_glb_tmpls) 2372 return rc; /* No global templates to process */ 2373 2374 /* Get the device id from the ulp context */ 2375 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 2376 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 2377 return -EINVAL; 2378 } 2379 2380 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2381 if (!mapper_data) { 2382 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 2383 return -EINVAL; 2384 } 2385 2386 /* Iterate the global resources and process each one */ 2387 for (idx = 0; idx < num_glb_tmpls; idx++) { 2388 /* Initialize the parms structure */ 2389 memset(&parms, 0, sizeof(parms)); 2390 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2391 parms.ulp_ctx = ulp_ctx; 2392 parms.dev_id = dev_id; 2393 parms.mapper_data = mapper_data; 2394 2395 /* Get the class table entry from dev id and class id */ 2396 parms.class_tid = glbl_tmpl_list[idx]; 2397 parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id, 2398 parms.class_tid, 2399 &parms.num_ctbls, 2400 &parms.tbl_idx); 2401 if (!parms.ctbls || !parms.num_ctbls) { 2402 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2403 parms.dev_id, parms.class_tid); 2404 return -EINVAL; 2405 } 2406 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 2407 if (!parms.device_params) { 2408 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2409 parms.dev_id, parms.class_tid); 2410 return -EINVAL; 2411 } 2412 rc = ulp_mapper_class_tbls_process(&parms); 2413 if (rc) { 2414 BNXT_TF_DBG(ERR, 2415 "class tables failed creation for %d:%d\n", 2416 parms.dev_id, parms.class_tid); 2417 return rc; 2418 } 2419 } 2420 return rc; 2421 } 2422 2423 /* Function to handle the mapping of the Flow to be compatible 2424 * with the underlying hardware. 2425 */ 2426 int32_t 2427 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 2428 struct bnxt_ulp_mapper_create_parms *cparms, 2429 uint32_t *flowid) 2430 { 2431 struct bnxt_ulp_mapper_parms parms; 2432 struct ulp_regfile regfile; 2433 int32_t rc, trc; 2434 2435 if (!ulp_ctx || !cparms) 2436 return -EINVAL; 2437 2438 /* Initialize the parms structure */ 2439 memset(&parms, 0, sizeof(parms)); 2440 parms.act_prop = cparms->act_prop; 2441 parms.act_bitmap = cparms->act; 2442 parms.hdr_bitmap = cparms->hdr_bitmap; 2443 parms.regfile = ®file; 2444 parms.hdr_field = cparms->hdr_field; 2445 parms.comp_fld = cparms->comp_fld; 2446 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2447 parms.ulp_ctx = ulp_ctx; 2448 parms.tcam_tbl_opc = BNXT_ULP_MAPPER_TCAM_TBL_OPC_NORMAL; 2449 2450 /* Get the device id from the ulp context */ 2451 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { 2452 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 2453 return -EINVAL; 2454 } 2455 2456 /* 2457 * Get the mapper data for dynamic mapper data such as default 2458 * ids. 2459 */ 2460 parms.mapper_data = (struct bnxt_ulp_mapper_data *) 2461 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2462 if (!parms.mapper_data) { 2463 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 2464 return -EINVAL; 2465 } 2466 2467 /* Get the action table entry from device id and act context id */ 2468 parms.act_tid = cparms->act_tid; 2469 2470 /* 2471 * Perform the action table get only if act template is not zero 2472 * for act template zero like for default rules ignore the action 2473 * table processing. 2474 */ 2475 if (parms.act_tid) { 2476 parms.atbls = ulp_mapper_action_tbl_list_get(parms.dev_id, 2477 parms.act_tid, 2478 &parms.num_atbls); 2479 if (!parms.atbls || !parms.num_atbls) { 2480 BNXT_TF_DBG(ERR, "No action tables for %d:%d\n", 2481 parms.dev_id, parms.act_tid); 2482 return -EINVAL; 2483 } 2484 } 2485 2486 /* Get the class table entry from device id and act context id */ 2487 parms.class_tid = cparms->class_tid; 2488 parms.ctbls = ulp_mapper_class_tbl_list_get(parms.dev_id, 2489 parms.class_tid, 2490 &parms.num_ctbls, 2491 &parms.tbl_idx); 2492 if (!parms.ctbls || !parms.num_ctbls) { 2493 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2494 parms.dev_id, parms.class_tid); 2495 return -EINVAL; 2496 } 2497 2498 /* Get the device params, it will be used in later processing */ 2499 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 2500 if (!parms.device_params) { 2501 BNXT_TF_DBG(ERR, "No class tables for %d:%d\n", 2502 parms.dev_id, parms.class_tid); 2503 return -EINVAL; 2504 } 2505 2506 /* initialize the registry file for further processing */ 2507 if (!ulp_regfile_init(parms.regfile)) { 2508 BNXT_TF_DBG(ERR, "regfile initialization failed.\n"); 2509 return -EINVAL; 2510 } 2511 2512 rc = ulp_regfile_write(parms.regfile, 2513 BNXT_ULP_REGFILE_INDEX_CLASS_TID, 2514 tfp_cpu_to_be_64((uint64_t)parms.class_tid)); 2515 if (!rc) { 2516 BNXT_TF_DBG(ERR, "Unable to write template ID to regfile\n"); 2517 return -EINVAL; 2518 } 2519 2520 /* Allocate a Flow ID for attaching all resources for the flow to. 2521 * Once allocated, all errors have to walk the list of resources and 2522 * free each of them. 2523 */ 2524 rc = ulp_flow_db_fid_alloc(ulp_ctx, 2525 parms.tbl_idx, 2526 cparms->func_id, 2527 &parms.fid); 2528 if (rc) { 2529 BNXT_TF_DBG(ERR, "Unable to allocate flow table entry\n"); 2530 return rc; 2531 } 2532 2533 /* Process the action template list from the selected action table*/ 2534 if (parms.act_tid) { 2535 rc = ulp_mapper_action_tbls_process(&parms); 2536 if (rc) { 2537 BNXT_TF_DBG(ERR, 2538 "action tables failed creation for %d:%d\n", 2539 parms.dev_id, parms.act_tid); 2540 goto flow_error; 2541 } 2542 } 2543 2544 /* All good. Now process the class template */ 2545 rc = ulp_mapper_class_tbls_process(&parms); 2546 if (rc) { 2547 BNXT_TF_DBG(ERR, "class tables failed creation for %d:%d\n", 2548 parms.dev_id, parms.class_tid); 2549 goto flow_error; 2550 } 2551 2552 *flowid = parms.fid; 2553 2554 return rc; 2555 2556 flow_error: 2557 /* Free all resources that were allocated during flow creation */ 2558 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.fid, 2559 BNXT_ULP_REGULAR_FLOW_TABLE); 2560 if (trc) 2561 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); 2562 2563 return rc; 2564 } 2565 2566 int32_t 2567 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) 2568 { 2569 struct bnxt_ulp_cache_tbl_params *tbl; 2570 struct bnxt_ulp_mapper_data *data; 2571 uint32_t i; 2572 struct tf *tfp; 2573 int32_t rc, csize; 2574 2575 if (!ulp_ctx) 2576 return -EINVAL; 2577 2578 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2579 if (!tfp) 2580 return -EINVAL; 2581 2582 data = rte_zmalloc("ulp_mapper_data", 2583 sizeof(struct bnxt_ulp_mapper_data), 0); 2584 if (!data) { 2585 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n"); 2586 return -ENOMEM; 2587 } 2588 2589 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) { 2590 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n"); 2591 /* Don't call deinit since the prof_func wasn't allocated. */ 2592 rte_free(data); 2593 return -ENOMEM; 2594 } 2595 2596 /* Allocate the global resource ids */ 2597 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); 2598 if (rc) { 2599 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n"); 2600 goto error; 2601 } 2602 2603 /* Allocate the ulp cache tables. */ 2604 for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { 2605 tbl = ulp_mapper_cache_tbl_params_get(i); 2606 if (!tbl) { 2607 BNXT_TF_DBG(ERR, "Failed to get cache table parms (%d)", 2608 i); 2609 goto error; 2610 } 2611 if (tbl->num_entries != 0) { 2612 csize = sizeof(struct bnxt_ulp_mapper_cache_entry) * 2613 tbl->num_entries; 2614 data->cache_tbl[i] = rte_zmalloc("ulp mapper cache tbl", 2615 csize, 0); 2616 if (!data->cache_tbl[i]) { 2617 BNXT_TF_DBG(ERR, "Failed to allocate Cache " 2618 "table %d.\n", i); 2619 rc = -ENOMEM; 2620 goto error; 2621 } 2622 } 2623 } 2624 2625 rc = ulp_mapper_glb_template_table_init(ulp_ctx); 2626 if (rc) { 2627 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n"); 2628 goto error; 2629 } 2630 2631 return 0; 2632 error: 2633 /* Ignore the return code in favor of returning the original error. */ 2634 ulp_mapper_deinit(ulp_ctx); 2635 return rc; 2636 } 2637 2638 void 2639 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) 2640 { 2641 struct bnxt_ulp_mapper_data *data; 2642 uint32_t i; 2643 struct tf *tfp; 2644 2645 if (!ulp_ctx) { 2646 BNXT_TF_DBG(ERR, 2647 "Failed to acquire ulp context, so data may " 2648 "not be released.\n"); 2649 return; 2650 } 2651 2652 data = (struct bnxt_ulp_mapper_data *) 2653 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 2654 if (!data) { 2655 /* Go ahead and return since there is no allocated data. */ 2656 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n"); 2657 return; 2658 } 2659 2660 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 2661 if (!tfp) { 2662 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); 2663 /* Free the mapper data regardless of errors. */ 2664 goto free_mapper_data; 2665 } 2666 2667 /* Free the global resource info table entries */ 2668 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); 2669 2670 free_mapper_data: 2671 /* Free the ulp cache tables */ 2672 for (i = 0; i < BNXT_ULP_CACHE_TBL_MAX_SZ; i++) { 2673 rte_free(data->cache_tbl[i]); 2674 data->cache_tbl[i] = NULL; 2675 } 2676 2677 rte_free(data); 2678 /* Reset the data pointer within the ulp_ctx. */ 2679 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); 2680 } 2681