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