1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_log.h> 7 #include <rte_malloc.h> 8 #include "bnxt.h" 9 #include "ulp_template_db_enum.h" 10 #include "ulp_template_struct.h" 11 #include "bnxt_tf_common.h" 12 #include "ulp_utils.h" 13 #include "bnxt_ulp.h" 14 #include "tfp.h" 15 #include "tf_ext_flow_handle.h" 16 #include "ulp_mark_mgr.h" 17 #include "ulp_mapper.h" 18 #include "ulp_flow_db.h" 19 #include "tf_util.h" 20 #include "ulp_template_db_tbl.h" 21 22 static const char * 23 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type) 24 { 25 switch (tmpl_type) { 26 case BNXT_ULP_TEMPLATE_TYPE_CLASS: 27 return "class"; 28 case BNXT_ULP_TEMPLATE_TYPE_ACTION: 29 return "action"; 30 default: 31 return "invalid template type"; 32 } 33 } 34 35 36 static struct bnxt_ulp_glb_resource_info * 37 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries) 38 { 39 if (!num_entries) 40 return NULL; 41 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 42 return ulp_glb_resource_tbl; 43 } 44 45 /* 46 * Read the global resource from the mapper global resource list 47 * 48 * The regval is always returned in big-endian. 49 * 50 * returns 0 on success 51 */ 52 static int32_t 53 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data, 54 enum tf_dir dir, 55 uint16_t idx, 56 uint64_t *regval) 57 { 58 if (!mapper_data || !regval || 59 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST) 60 return -EINVAL; 61 62 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl; 63 return 0; 64 } 65 66 /* 67 * Write a global resource to the mapper global resource list 68 * 69 * The regval value must be in big-endian. 70 * 71 * return 0 on success. 72 */ 73 static int32_t 74 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, 75 struct bnxt_ulp_glb_resource_info *res, 76 uint64_t regval) 77 { 78 struct bnxt_ulp_mapper_glb_resource_entry *ent; 79 80 /* validate the arguments */ 81 if (!data || res->direction >= TF_DIR_MAX || 82 res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST) 83 return -EINVAL; 84 85 /* write to the mapper data */ 86 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index]; 87 ent->resource_func = res->resource_func; 88 ent->resource_type = res->resource_type; 89 ent->resource_hndl = regval; 90 return 0; 91 } 92 93 /* 94 * Internal function to allocate identity resource and store it in mapper data. 95 * 96 * returns 0 on success 97 */ 98 static int32_t 99 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx, 100 struct bnxt_ulp_mapper_data *mapper_data, 101 struct bnxt_ulp_glb_resource_info *glb_res) 102 { 103 struct tf_alloc_identifier_parms iparms = { 0 }; 104 struct tf_free_identifier_parms fparms; 105 uint64_t regval; 106 struct tf *tfp; 107 int32_t rc = 0; 108 109 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 110 if (!tfp) 111 return -EINVAL; 112 113 iparms.ident_type = glb_res->resource_type; 114 iparms.dir = glb_res->direction; 115 116 /* Allocate the Identifier using tf api */ 117 rc = tf_alloc_identifier(tfp, &iparms); 118 if (rc) { 119 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", 120 tf_dir_2_str(iparms.dir), 121 iparms.ident_type); 122 return rc; 123 } 124 125 /* entries are stored as big-endian format */ 126 regval = tfp_cpu_to_be_64((uint64_t)iparms.id); 127 /* write to the mapper global resource */ 128 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval); 129 if (rc) { 130 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 131 /* Free the identifier when update failed */ 132 fparms.dir = iparms.dir; 133 fparms.ident_type = iparms.ident_type; 134 fparms.id = iparms.id; 135 tf_free_identifier(tfp, &fparms); 136 return rc; 137 } 138 return rc; 139 } 140 141 /* 142 * Internal function to allocate index tbl resource and store it in mapper data. 143 * 144 * returns 0 on success 145 */ 146 static int32_t 147 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx, 148 struct bnxt_ulp_mapper_data *mapper_data, 149 struct bnxt_ulp_glb_resource_info *glb_res) 150 { 151 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 152 struct tf_free_tbl_entry_parms free_parms = { 0 }; 153 uint64_t regval; 154 struct tf *tfp; 155 uint32_t tbl_scope_id; 156 int32_t rc = 0; 157 158 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 159 if (!tfp) 160 return -EINVAL; 161 162 /* Get the scope id */ 163 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id); 164 if (rc) { 165 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 166 return rc; 167 } 168 169 aparms.type = glb_res->resource_type; 170 aparms.dir = glb_res->direction; 171 aparms.search_enable = 0; 172 aparms.tbl_scope_id = tbl_scope_id; 173 174 /* Allocate the index tbl using tf api */ 175 rc = tf_alloc_tbl_entry(tfp, &aparms); 176 if (rc) { 177 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", 178 tf_dir_2_str(aparms.dir), aparms.type); 179 return rc; 180 } 181 182 /* entries are stored as big-endian format */ 183 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx); 184 /* write to the mapper global resource */ 185 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval); 186 if (rc) { 187 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 188 /* Free the identifier when update failed */ 189 free_parms.dir = aparms.dir; 190 free_parms.type = aparms.type; 191 free_parms.idx = aparms.idx; 192 tf_free_tbl_entry(tfp, &free_parms); 193 return rc; 194 } 195 return rc; 196 } 197 198 /* Retrieve the global template table */ 199 static uint32_t * 200 ulp_mapper_glb_template_table_get(uint32_t *num_entries) 201 { 202 if (!num_entries) 203 return NULL; 204 *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ; 205 return ulp_glb_template_tbl; 206 } 207 208 static int32_t 209 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms, 210 uint32_t operand, 211 uint8_t *val) 212 { 213 uint32_t t_idx; 214 215 t_idx = parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT + 216 BNXT_ULP_GLB_FIELD_TBL_SHIFT); 217 t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) << 218 BNXT_ULP_GLB_FIELD_TBL_SHIFT; 219 t_idx += operand; 220 221 if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) { 222 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n", 223 parms->class_tid, t_idx, operand); 224 *val = 0; 225 return -EINVAL; /* error */ 226 } 227 *val = ulp_glb_field_tbl[t_idx]; 228 return 0; 229 } 230 231 /* 232 * Get the size of the action property for a given index. 233 * 234 * idx [in] The index for the action property 235 * 236 * returns the size of the action property. 237 */ 238 static uint32_t 239 ulp_mapper_act_prop_size_get(uint32_t idx) 240 { 241 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) 242 return 0; 243 return ulp_act_prop_map_table[idx]; 244 } 245 246 static struct bnxt_ulp_mapper_cond_info * 247 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms, 248 uint32_t tid, 249 uint32_t *num_tbls, 250 enum bnxt_ulp_cond_list_opc *opc) 251 { 252 uint32_t idx; 253 const struct bnxt_ulp_template_device_tbls *dev_tbls; 254 255 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 256 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums; 257 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode; 258 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx; 259 260 return &dev_tbls->cond_list[idx]; 261 } 262 263 static struct bnxt_ulp_mapper_cond_info * 264 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms, 265 struct bnxt_ulp_mapper_tbl_info *tbl, 266 uint32_t *num_tbls, 267 enum bnxt_ulp_cond_list_opc *opc) 268 { 269 uint32_t idx; 270 const struct bnxt_ulp_template_device_tbls *dev_tbls; 271 272 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 273 *num_tbls = tbl->execute_info.cond_nums; 274 *opc = tbl->execute_info.cond_list_opcode; 275 idx = tbl->execute_info.cond_start_idx; 276 277 return &dev_tbls->cond_list[idx]; 278 } 279 280 /* 281 * Get a list of classifier tables that implement the flow 282 * Gets a device dependent list of tables that implement the class template id 283 * 284 * mparms [in] The mappers parms with data related to the flow. 285 * 286 * tid [in] The template id that matches the flow 287 * 288 * num_tbls [out] The number of classifier tables in the returned array 289 * 290 * returns An array of classifier tables to implement the flow, or NULL on 291 * error 292 */ 293 static struct bnxt_ulp_mapper_tbl_info * 294 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms, 295 uint32_t tid, 296 uint32_t *num_tbls) 297 { 298 uint32_t idx; 299 const struct bnxt_ulp_template_device_tbls *dev_tbls; 300 301 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 302 303 idx = dev_tbls->tmpl_list[tid].start_tbl_idx; 304 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls; 305 306 return &dev_tbls->tbl_list[idx]; 307 } 308 309 /* 310 * Get the list of key fields that implement the flow. 311 * 312 * mparms [in] The mapper parms with information about the flow 313 * 314 * tbl [in] A single table instance to get the key fields from 315 * 316 * num_flds [out] The number of key fields in the returned array 317 * 318 * Returns array of Key fields, or NULL on error. 319 */ 320 static struct bnxt_ulp_mapper_key_info * 321 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms, 322 struct bnxt_ulp_mapper_tbl_info *tbl, 323 uint32_t *num_flds) 324 { 325 uint32_t idx; 326 const struct bnxt_ulp_template_device_tbls *dev_tbls; 327 328 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 329 if (!dev_tbls->key_info_list) { 330 *num_flds = 0; 331 return NULL; 332 } 333 334 idx = tbl->key_start_idx; 335 *num_flds = tbl->key_num_fields; 336 337 return &dev_tbls->key_info_list[idx]; 338 } 339 340 /* 341 * Get the list of data fields that implement the flow. 342 * 343 * mparms [in] The mapper parms with information about the flow 344 * 345 * tbl [in] A single table instance to get the data fields from 346 * 347 * num_flds [out] The number of data fields in the returned array. 348 * 349 * num_encap_flds [out] The number of encap fields in the returned array. 350 * 351 * Returns array of data fields, or NULL on error. 352 */ 353 static struct bnxt_ulp_mapper_field_info * 354 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms, 355 struct bnxt_ulp_mapper_tbl_info *tbl, 356 uint32_t *num_flds, 357 uint32_t *num_encap_flds) 358 { 359 uint32_t idx; 360 const struct bnxt_ulp_template_device_tbls *dev_tbls; 361 362 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 363 if (!dev_tbls->result_field_list) { 364 *num_flds = 0; 365 *num_encap_flds = 0; 366 return NULL; 367 } 368 369 idx = tbl->result_start_idx; 370 *num_flds = tbl->result_num_fields; 371 *num_encap_flds = tbl->encap_num_fields; 372 373 return &dev_tbls->result_field_list[idx]; 374 } 375 376 /* 377 * Get the list of ident fields that implement the flow 378 * 379 * tbl [in] A single table instance to get the ident fields from 380 * 381 * num_flds [out] The number of ident fields in the returned array 382 * 383 * returns array of ident fields, or NULL on error 384 */ 385 static struct bnxt_ulp_mapper_ident_info * 386 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms, 387 struct bnxt_ulp_mapper_tbl_info *tbl, 388 uint32_t *num_flds) 389 { 390 uint32_t idx; 391 const struct bnxt_ulp_template_device_tbls *dev_tbls; 392 393 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 394 if (!dev_tbls->ident_list) { 395 *num_flds = 0; 396 return NULL; 397 } 398 399 idx = tbl->ident_start_idx; 400 *num_flds = tbl->ident_nums; 401 402 return &dev_tbls->ident_list[idx]; 403 } 404 405 static inline int32_t 406 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused, 407 struct tf *tfp, 408 struct ulp_flow_db_res_params *res) 409 { 410 struct tf_free_tcam_entry_parms fparms = { 411 .dir = res->direction, 412 .tcam_tbl_type = res->resource_type, 413 .idx = (uint16_t)res->resource_hndl 414 }; 415 416 return tf_free_tcam_entry(tfp, &fparms); 417 } 418 419 static inline int32_t 420 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp, 421 struct tf *tfp, 422 struct ulp_flow_db_res_params *res) 423 { 424 struct tf_free_tbl_entry_parms fparms = { 425 .dir = res->direction, 426 .type = res->resource_type, 427 .idx = (uint32_t)res->resource_hndl 428 }; 429 430 /* 431 * Just get the table scope, it will be ignored if not necessary 432 * by the tf_free_tbl_entry 433 */ 434 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 435 436 return tf_free_tbl_entry(tfp, &fparms); 437 } 438 439 static inline int32_t 440 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp, 441 struct tf *tfp, 442 struct ulp_flow_db_res_params *res) 443 { 444 struct tf_delete_em_entry_parms fparms = { 0 }; 445 int32_t rc; 446 447 fparms.dir = res->direction; 448 if (res->resource_func == BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE) 449 fparms.mem = TF_MEM_EXTERNAL; 450 else 451 fparms.mem = TF_MEM_INTERNAL; 452 fparms.flow_handle = res->resource_hndl; 453 454 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 455 if (rc) { 456 BNXT_TF_DBG(ERR, "Failed to get table scope\n"); 457 return -EINVAL; 458 } 459 460 return tf_delete_em_entry(tfp, &fparms); 461 } 462 463 static inline int32_t 464 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused, 465 struct tf *tfp, 466 struct ulp_flow_db_res_params *res) 467 { 468 struct tf_free_identifier_parms fparms = { 469 .dir = res->direction, 470 .ident_type = res->resource_type, 471 .id = (uint16_t)res->resource_hndl 472 }; 473 474 return tf_free_identifier(tfp, &fparms); 475 } 476 477 static inline int32_t 478 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, 479 struct ulp_flow_db_res_params *res) 480 { 481 return ulp_mark_db_mark_del(ulp, 482 res->resource_type, 483 res->resource_hndl); 484 } 485 486 static inline int32_t 487 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp, 488 uint32_t parent_fid, 489 struct ulp_flow_db_res_params *res) 490 { 491 uint32_t idx, child_fid = 0, parent_idx; 492 struct bnxt_ulp_flow_db *flow_db; 493 494 parent_idx = (uint32_t)res->resource_hndl; 495 496 /* check the validity of the parent fid */ 497 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) || 498 idx != parent_idx) { 499 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid); 500 return -EINVAL; 501 } 502 503 /* Clear all the child flows parent index */ 504 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp); 505 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx, 506 &child_fid)) { 507 /* update the child flows resource handle */ 508 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR, 509 child_fid)) { 510 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n", 511 child_fid); 512 return -EINVAL; 513 } 514 } 515 516 /* free the parent entry in the parent table flow */ 517 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) { 518 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid); 519 return -EINVAL; 520 } 521 return 0; 522 } 523 524 static inline int32_t 525 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp, 526 uint32_t child_fid, 527 struct ulp_flow_db_res_params *res) 528 { 529 uint32_t parent_fid; 530 531 parent_fid = (uint32_t)res->resource_hndl; 532 if (!parent_fid) 533 return 0; /* Already freed - orphan child*/ 534 535 /* reset the child flow bitset*/ 536 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) { 537 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n", 538 parent_fid, child_fid); 539 return -EINVAL; 540 } 541 return 0; 542 } 543 544 /* 545 * Process the flow database opcode alloc action. 546 * returns 0 on success 547 */ 548 static int32_t 549 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms, 550 struct bnxt_ulp_mapper_tbl_info *tbl) 551 { 552 uint32_t rid = 0; 553 uint64_t val64; 554 int32_t rc = 0; 555 556 /* allocate a new fid */ 557 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx, 558 BNXT_ULP_FDB_TYPE_RID, 559 0, &rid); 560 if (rc) { 561 BNXT_TF_DBG(ERR, 562 "Unable to allocate flow table entry\n"); 563 return -EINVAL; 564 } 565 /* Store the allocated fid in regfile*/ 566 val64 = rid; 567 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand, 568 tfp_cpu_to_be_64(val64)); 569 if (rc) { 570 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 571 tbl->fdb_operand); 572 ulp_flow_db_fid_free(parms->ulp_ctx, 573 BNXT_ULP_FDB_TYPE_RID, rid); 574 return -EINVAL; 575 } 576 return 0; 577 } 578 579 /* 580 * Process the flow database opcode action. 581 * returns 0 on success. 582 */ 583 static int32_t 584 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms, 585 struct bnxt_ulp_mapper_tbl_info *tbl, 586 struct ulp_flow_db_res_params *fid_parms) 587 { 588 uint32_t push_fid; 589 uint64_t val64; 590 enum bnxt_ulp_fdb_type flow_type; 591 int32_t rc = 0; 592 593 switch (tbl->fdb_opcode) { 594 case BNXT_ULP_FDB_OPC_PUSH: 595 push_fid = parms->fid; 596 flow_type = parms->flow_type; 597 break; 598 case BNXT_ULP_FDB_OPC_ALLOC_PUSH_REGFILE: 599 case BNXT_ULP_FDB_OPC_PUSH_REGFILE: 600 /* get the fid from the regfile */ 601 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand, 602 &val64); 603 if (!rc) { 604 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 605 tbl->fdb_operand); 606 return -EINVAL; 607 } 608 /* Use the extracted fid to update the flow resource */ 609 push_fid = (uint32_t)tfp_be_to_cpu_64(val64); 610 flow_type = BNXT_ULP_FDB_TYPE_RID; 611 break; 612 default: 613 return rc; /* Nothing to be done */ 614 } 615 616 /* Add the resource to the flow database */ 617 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type, 618 push_fid, fid_parms); 619 if (rc) 620 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n", 621 push_fid, rc); 622 return rc; 623 } 624 625 /* 626 * Process the flow database opcode action. 627 * returns 0 on success. 628 */ 629 static int32_t 630 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms, 631 struct bnxt_ulp_mapper_tbl_info *tbl, 632 uint32_t *priority) 633 { 634 int32_t rc = 0; 635 636 switch (tbl->pri_opcode) { 637 case BNXT_ULP_PRI_OPC_NOT_USED: 638 *priority = 0; 639 break; 640 case BNXT_ULP_PRI_OPC_CONST: 641 *priority = tbl->pri_operand; 642 break; 643 case BNXT_ULP_PRI_OPC_APP_PRI: 644 *priority = parms->app_priority; 645 break; 646 default: 647 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n", 648 tbl->pri_opcode); 649 rc = -EINVAL; 650 break; 651 } 652 return rc; 653 } 654 655 /* 656 * Process the identifier list in the given table. 657 * Extract the ident from the table entry and 658 * write it to the reg file. 659 * returns 0 on success. 660 */ 661 static int32_t 662 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms, 663 struct bnxt_ulp_mapper_tbl_info *tbl, 664 uint8_t *byte_data, 665 uint32_t byte_data_size, 666 enum bnxt_ulp_byte_order byte_order) 667 { 668 struct bnxt_ulp_mapper_ident_info *idents; 669 uint32_t i, num_idents = 0; 670 uint64_t val64; 671 672 /* validate the null arguments */ 673 if (!byte_data) { 674 BNXT_TF_DBG(ERR, "invalid argument\n"); 675 return -EINVAL; 676 } 677 678 /* Get the ident list and process each one */ 679 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 680 681 for (i = 0; i < num_idents; i++) { 682 /* check the size of the buffer for validation */ 683 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) > 684 ULP_BYTE_2_BITS(byte_data_size) || 685 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) { 686 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n", 687 idents[i].ident_bit_pos, 688 idents[i].ident_bit_size, 689 byte_data_size); 690 return -EINVAL; 691 } 692 val64 = 0; 693 if (byte_order == BNXT_ULP_BYTE_ORDER_LE) 694 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64, 695 sizeof(val64), 696 idents[i].ident_bit_pos, 697 idents[i].ident_bit_size); 698 else 699 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64, 700 idents[i].ident_bit_pos, 701 idents[i].ident_bit_size); 702 703 /* Write it to the regfile, val64 is already in big-endian*/ 704 if (ulp_regfile_write(parms->regfile, 705 idents[i].regfile_idx, val64)) { 706 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", 707 idents[i].regfile_idx); 708 return -EINVAL; 709 } 710 } 711 return 0; 712 } 713 714 /* 715 * Process the identifier instruction and either store it in the flow database 716 * or return it in the val (if not NULL) on success. If val is NULL, the 717 * identifier is to be stored in the flow database. 718 */ 719 static int32_t 720 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, 721 struct bnxt_ulp_mapper_tbl_info *tbl, 722 struct bnxt_ulp_mapper_ident_info *ident, 723 uint16_t *val) 724 { 725 struct ulp_flow_db_res_params fid_parms; 726 uint64_t id = 0; 727 int32_t idx; 728 struct tf_alloc_identifier_parms iparms = { 0 }; 729 struct tf_free_identifier_parms free_parms = { 0 }; 730 struct tf *tfp; 731 int rc; 732 733 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 734 if (!tfp) { 735 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 736 return -EINVAL; 737 } 738 739 idx = ident->regfile_idx; 740 741 iparms.ident_type = ident->ident_type; 742 iparms.dir = tbl->direction; 743 744 rc = tf_alloc_identifier(tfp, &iparms); 745 if (rc) { 746 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n", 747 tf_dir_2_str(iparms.dir), 748 tf_ident_2_str(iparms.ident_type)); 749 return rc; 750 } 751 752 id = (uint64_t)tfp_cpu_to_be_64(iparms.id); 753 if (ulp_regfile_write(parms->regfile, idx, id)) { 754 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 755 rc = -EINVAL; 756 /* Need to free the identifier, so goto error */ 757 goto error; 758 } 759 760 /* Link the resource to the flow in the flow db */ 761 if (!val) { 762 memset(&fid_parms, 0, sizeof(fid_parms)); 763 fid_parms.direction = tbl->direction; 764 fid_parms.resource_func = ident->resource_func; 765 fid_parms.resource_type = ident->ident_type; 766 fid_parms.resource_hndl = iparms.id; 767 fid_parms.critical_resource = tbl->critical_resource; 768 769 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 770 if (rc) { 771 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 772 rc); 773 /* Need to free the identifier, so goto error */ 774 goto error; 775 } 776 } else { 777 *val = iparms.id; 778 } 779 return 0; 780 781 error: 782 /* Need to free the identifier */ 783 free_parms.dir = tbl->direction; 784 free_parms.ident_type = ident->ident_type; 785 free_parms.id = iparms.id; 786 787 (void)tf_free_identifier(tfp, &free_parms); 788 789 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n", 790 ident->description, 791 tf_dir_2_str(tbl->direction)); 792 return rc; 793 } 794 795 /* 796 * Process the identifier instruction and extract it from result blob. 797 * Increment the identifier reference count and store it in the flow database. 798 */ 799 static int32_t 800 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms, 801 struct bnxt_ulp_mapper_tbl_info *tbl, 802 struct bnxt_ulp_mapper_ident_info *ident, 803 struct ulp_blob *res_blob) 804 { 805 struct ulp_flow_db_res_params fid_parms; 806 uint64_t id = 0; 807 uint32_t idx = 0; 808 struct tf_search_identifier_parms sparms = { 0 }; 809 struct tf_free_identifier_parms free_parms = { 0 }; 810 struct tf *tfp; 811 int rc; 812 813 /* Get the tfp from ulp context */ 814 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 815 if (!tfp) { 816 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 817 return -EINVAL; 818 } 819 820 /* Extract the index from the result blob */ 821 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx), 822 ident->ident_bit_pos, ident->ident_bit_size); 823 if (rc) { 824 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n"); 825 return -EIO; 826 } 827 828 /* populate the search params and search identifier shadow table */ 829 sparms.ident_type = ident->ident_type; 830 sparms.dir = tbl->direction; 831 /* convert the idx into cpu format */ 832 sparms.search_id = tfp_be_to_cpu_32(idx); 833 834 /* Search identifier also increase the reference count */ 835 rc = tf_search_identifier(tfp, &sparms); 836 if (rc) { 837 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n", 838 tf_dir_2_str(sparms.dir), 839 tf_ident_2_str(sparms.ident_type), 840 sparms.search_id); 841 return rc; 842 } 843 844 /* Write it to the regfile */ 845 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id); 846 if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) { 847 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 848 rc = -EINVAL; 849 /* Need to free the identifier, so goto error */ 850 goto error; 851 } 852 853 /* Link the resource to the flow in the flow db */ 854 memset(&fid_parms, 0, sizeof(fid_parms)); 855 fid_parms.direction = tbl->direction; 856 fid_parms.resource_func = ident->resource_func; 857 fid_parms.resource_type = ident->ident_type; 858 fid_parms.resource_hndl = sparms.search_id; 859 fid_parms.critical_resource = tbl->critical_resource; 860 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 861 if (rc) { 862 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 863 rc); 864 /* Need to free the identifier, so goto error */ 865 goto error; 866 } 867 868 return 0; 869 870 error: 871 /* Need to free the identifier */ 872 free_parms.dir = tbl->direction; 873 free_parms.ident_type = ident->ident_type; 874 free_parms.id = sparms.search_id; 875 (void)tf_free_identifier(tfp, &free_parms); 876 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n", 877 ident->description, 878 tf_dir_2_str(tbl->direction), sparms.search_id); 879 return rc; 880 } 881 882 static int32_t 883 ulp_mapper_field_process(struct bnxt_ulp_mapper_parms *parms, 884 enum tf_dir dir, 885 struct bnxt_ulp_mapper_field_info *fld, 886 struct ulp_blob *blob, 887 uint8_t is_key, 888 const char *name) 889 { 890 uint32_t val_size = 0, field_size = 0; 891 uint64_t hdr_bit, act_bit, regval; 892 uint16_t write_idx = blob->write_idx; 893 uint16_t idx, size_idx, bitlen; 894 uint8_t *val = NULL; 895 uint8_t act_val[16]; 896 uint8_t bit; 897 898 bitlen = fld->field_bit_size; 899 switch (fld->field_opcode) { 900 case BNXT_ULP_FIELD_OPC_SET_TO_CONSTANT: 901 val = fld->field_operand; 902 if (!ulp_blob_push(blob, val, bitlen)) { 903 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 904 return -EINVAL; 905 } 906 break; 907 case BNXT_ULP_FIELD_OPC_SET_TO_ZERO: 908 if (ulp_blob_pad_push(blob, bitlen) < 0) { 909 BNXT_TF_DBG(ERR, "%s too large for blob\n", name); 910 return -EINVAL; 911 } 912 break; 913 case BNXT_ULP_FIELD_OPC_SET_TO_REGFILE: 914 if (!ulp_operand_read(fld->field_operand, 915 (uint8_t *)&idx, sizeof(uint16_t))) { 916 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 917 return -EINVAL; 918 } 919 920 idx = tfp_be_to_cpu_16(idx); 921 /* Uninitialized regfile entries return 0 */ 922 if (!ulp_regfile_read(parms->regfile, idx, ®val)) { 923 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n", 924 name, idx); 925 return -EINVAL; 926 } 927 928 val = ulp_blob_push_64(blob, ®val, bitlen); 929 if (!val) { 930 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 931 return -EINVAL; 932 } 933 break; 934 case BNXT_ULP_FIELD_OPC_SET_TO_GLB_REGFILE: 935 if (!ulp_operand_read(fld->field_operand, 936 (uint8_t *)&idx, 937 sizeof(uint16_t))) { 938 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name); 939 return -EINVAL; 940 } 941 idx = tfp_be_to_cpu_16(idx); 942 if (ulp_mapper_glb_resource_read(parms->mapper_data, 943 dir, 944 idx, ®val)) { 945 BNXT_TF_DBG(ERR, "%s global regfile[%d] read failed.\n", 946 name, idx); 947 return -EINVAL; 948 } 949 val = ulp_blob_push_64(blob, ®val, bitlen); 950 if (!val) { 951 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 952 return -EINVAL; 953 } 954 break; 955 case BNXT_ULP_FIELD_OPC_SET_TO_COMP_FIELD: 956 if (!ulp_operand_read(fld->field_operand, 957 (uint8_t *)&idx, 958 sizeof(uint16_t))) { 959 BNXT_TF_DBG(ERR, "%s operand read failed.\n", 960 name); 961 return -EINVAL; 962 } 963 idx = tfp_be_to_cpu_16(idx); 964 if (idx < BNXT_ULP_CF_IDX_LAST) 965 val = ulp_blob_push_32(blob, &parms->comp_fld[idx], 966 bitlen); 967 if (!val) { 968 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 969 return -EINVAL; 970 } 971 break; 972 case BNXT_ULP_FIELD_OPC_IF_ACT_BIT_THEN_ACT_PROP_ELSE_CONST: 973 if (!ulp_operand_read(fld->field_operand, 974 (uint8_t *)&act_bit, sizeof(uint64_t))) { 975 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 976 return -EINVAL; 977 } 978 act_bit = tfp_be_to_cpu_64(act_bit); 979 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { 980 /* Action bit is set so consider operand_true */ 981 if (!ulp_operand_read(fld->field_operand_true, 982 (uint8_t *)&idx, 983 sizeof(uint16_t))) { 984 BNXT_TF_DBG(ERR, 985 "%s true operand read failed\n", 986 name); 987 return -EINVAL; 988 } 989 idx = tfp_be_to_cpu_16(idx); 990 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 991 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", 992 name, idx); 993 return -EINVAL; 994 } 995 val = &parms->act_prop->act_details[idx]; 996 field_size = ulp_mapper_act_prop_size_get(idx); 997 if (bitlen < ULP_BYTE_2_BITS(field_size)) { 998 field_size = field_size - ((bitlen + 7) / 8); 999 val += field_size; 1000 } 1001 if (!ulp_blob_push(blob, val, bitlen)) { 1002 BNXT_TF_DBG(ERR, "%s push to blob failed\n", 1003 name); 1004 return -EINVAL; 1005 } 1006 } else { 1007 /* action bit is not set, use the operand false */ 1008 val = fld->field_operand_false; 1009 if (!ulp_blob_push(blob, val, bitlen)) { 1010 BNXT_TF_DBG(ERR, "%s push to blob failed\n", 1011 name); 1012 return -EINVAL; 1013 } 1014 } 1015 break; 1016 case BNXT_ULP_FIELD_OPC_IF_ACT_BIT_THEN_CONST_ELSE_CONST: 1017 if (!ulp_operand_read(fld->field_operand, 1018 (uint8_t *)&act_bit, sizeof(uint64_t))) { 1019 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 1020 return -EINVAL; 1021 } 1022 act_bit = tfp_be_to_cpu_64(act_bit); 1023 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) { 1024 /* Action bit is set so consider operand_true */ 1025 val = fld->field_operand_true; 1026 } else { 1027 /* action bit is not set, use the operand false */ 1028 val = fld->field_operand_false; 1029 } 1030 if (!ulp_blob_push(blob, val, bitlen)) { 1031 BNXT_TF_DBG(ERR, "%s push to blob failed\n", 1032 name); 1033 return -EINVAL; 1034 } 1035 break; 1036 case BNXT_ULP_FIELD_OPC_IF_COMP_FIELD_THEN_CF_ELSE_CF: 1037 if (!ulp_operand_read(fld->field_operand, 1038 (uint8_t *)&idx, 1039 sizeof(uint16_t))) { 1040 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name); 1041 return -EINVAL; 1042 } 1043 idx = tfp_be_to_cpu_16(idx); 1044 if (idx >= BNXT_ULP_CF_IDX_LAST) { 1045 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx); 1046 return -EINVAL; 1047 } 1048 /* check if the computed field is set */ 1049 if (ULP_COMP_FLD_IDX_RD(parms, idx)) 1050 val = fld->field_operand_true; 1051 else 1052 val = fld->field_operand_false; 1053 1054 /* read the appropriate computed field */ 1055 if (!ulp_operand_read(val, (uint8_t *)&idx, sizeof(uint16_t))) { 1056 BNXT_TF_DBG(ERR, "%s val operand read failed\n", name); 1057 return -EINVAL; 1058 } 1059 idx = tfp_be_to_cpu_16(idx); 1060 if (idx >= BNXT_ULP_CF_IDX_LAST) { 1061 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx); 1062 return -EINVAL; 1063 } 1064 val = ulp_blob_push_32(blob, &parms->comp_fld[idx], bitlen); 1065 if (!val) { 1066 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 1067 return -EINVAL; 1068 } 1069 break; 1070 case BNXT_ULP_FIELD_OPC_IF_HDR_BIT_THEN_CONST_ELSE_CONST: 1071 if (!ulp_operand_read(fld->field_operand, 1072 (uint8_t *)&hdr_bit, sizeof(uint64_t))) { 1073 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 1074 return -EINVAL; 1075 } 1076 hdr_bit = tfp_be_to_cpu_64(hdr_bit); 1077 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit)) { 1078 /* Header bit is set so consider operand_true */ 1079 val = fld->field_operand_true; 1080 } else { 1081 /* Header bit is not set, use the operand false */ 1082 val = fld->field_operand_false; 1083 } 1084 if (!ulp_blob_push(blob, val, bitlen)) { 1085 BNXT_TF_DBG(ERR, "%s push to blob failed\n", 1086 name); 1087 return -EINVAL; 1088 } 1089 break; 1090 case BNXT_ULP_FIELD_OPC_SET_TO_ACT_PROP: 1091 if (!ulp_operand_read(fld->field_operand, 1092 (uint8_t *)&idx, sizeof(uint16_t))) { 1093 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 1094 return -EINVAL; 1095 } 1096 idx = tfp_be_to_cpu_16(idx); 1097 1098 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1099 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx); 1100 return -EINVAL; 1101 } 1102 val = &parms->act_prop->act_details[idx]; 1103 field_size = ulp_mapper_act_prop_size_get(idx); 1104 if (bitlen < ULP_BYTE_2_BITS(field_size)) { 1105 field_size = field_size - ((bitlen + 7) / 8); 1106 val += field_size; 1107 } 1108 if (!ulp_blob_push(blob, val, bitlen)) { 1109 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 1110 return -EINVAL; 1111 } 1112 break; 1113 case BNXT_ULP_FIELD_OPC_SET_TO_ACT_BIT: 1114 if (!ulp_operand_read(fld->field_operand, 1115 (uint8_t *)&act_bit, sizeof(uint64_t))) { 1116 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 1117 return -EINVAL; 1118 } 1119 act_bit = tfp_be_to_cpu_64(act_bit); 1120 memset(act_val, 0, sizeof(act_val)); 1121 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit)) 1122 act_val[0] = 1; 1123 if (bitlen > ULP_BYTE_2_BITS(sizeof(act_val))) { 1124 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name); 1125 return -EINVAL; 1126 } 1127 if (!ulp_blob_push(blob, act_val, bitlen)) { 1128 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 1129 return -EINVAL; 1130 } 1131 val = act_val; 1132 break; 1133 case BNXT_ULP_FIELD_OPC_SET_TO_ENCAP_ACT_PROP_SZ: 1134 if (!ulp_operand_read(fld->field_operand, 1135 (uint8_t *)&idx, sizeof(uint16_t))) { 1136 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 1137 return -EINVAL; 1138 } 1139 idx = tfp_be_to_cpu_16(idx); 1140 1141 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1142 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx); 1143 return -EINVAL; 1144 } 1145 val = &parms->act_prop->act_details[idx]; 1146 1147 /* get the size index next */ 1148 if (!ulp_operand_read(&fld->field_operand[sizeof(uint16_t)], 1149 (uint8_t *)&size_idx, sizeof(uint16_t))) { 1150 BNXT_TF_DBG(ERR, "%s operand read failed\n", name); 1151 return -EINVAL; 1152 } 1153 size_idx = tfp_be_to_cpu_16(size_idx); 1154 1155 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1156 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx); 1157 return -EINVAL; 1158 } 1159 memcpy(&val_size, &parms->act_prop->act_details[size_idx], 1160 sizeof(uint32_t)); 1161 val_size = tfp_be_to_cpu_32(val_size); 1162 val_size = ULP_BYTE_2_BITS(val_size); 1163 ulp_blob_push_encap(blob, val, val_size); 1164 break; 1165 case BNXT_ULP_FIELD_OPC_SET_TO_HDR_FIELD: 1166 if (!ulp_operand_read(fld->field_operand, (uint8_t *)&idx, 1167 sizeof(uint16_t))) { 1168 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name); 1169 return -EINVAL; 1170 } 1171 idx = tfp_be_to_cpu_16(idx); 1172 /* get the index from the global field list */ 1173 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) { 1174 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 1175 idx); 1176 return -EINVAL; 1177 } 1178 if (is_key) 1179 val = parms->hdr_field[bit].spec; 1180 else 1181 val = parms->hdr_field[bit].mask; 1182 1183 /* 1184 * Need to account for how much data was pushed to the header 1185 * field vs how much is to be inserted in the key/mask. 1186 */ 1187 field_size = parms->hdr_field[bit].size; 1188 if (bitlen < ULP_BYTE_2_BITS(field_size)) { 1189 field_size = field_size - ((bitlen + 7) / 8); 1190 val += field_size; 1191 } 1192 1193 if (!ulp_blob_push(blob, val, bitlen)) { 1194 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name); 1195 return -EINVAL; 1196 } 1197 break; 1198 default: 1199 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n", 1200 name, fld->field_opcode, write_idx); 1201 return -EINVAL; 1202 } 1203 return 0; 1204 } 1205 1206 /* 1207 * Result table process and fill the result blob. 1208 * data [out] - the result blob data 1209 */ 1210 static int32_t 1211 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms, 1212 struct bnxt_ulp_mapper_tbl_info *tbl, 1213 struct ulp_blob *data, 1214 const char *name) 1215 { 1216 struct bnxt_ulp_mapper_field_info *dflds; 1217 uint32_t i, num_flds = 0, encap_flds = 0; 1218 int32_t rc = 0; 1219 1220 /* Get the result field list */ 1221 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, 1222 &encap_flds); 1223 1224 /* validate the result field list counts */ 1225 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && 1226 (!num_flds && !encap_flds)) || !dflds || 1227 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && 1228 (!num_flds || encap_flds))) { 1229 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n", 1230 num_flds, encap_flds); 1231 return -EINVAL; 1232 } 1233 1234 /* process the result fields, loop through them */ 1235 for (i = 0; i < (num_flds + encap_flds); i++) { 1236 /* set the swap index if encap swap bit is enabled */ 1237 if (parms->device_params->encap_byte_swap && encap_flds && 1238 i == num_flds) 1239 ulp_blob_encap_swap_idx_set(data); 1240 1241 /* Process the result fields */ 1242 rc = ulp_mapper_field_process(parms, tbl->direction, 1243 &dflds[i], data, 0, name); 1244 if (rc) { 1245 BNXT_TF_DBG(ERR, "data field failed\n"); 1246 return rc; 1247 } 1248 } 1249 1250 /* if encap bit swap is enabled perform the bit swap */ 1251 if (parms->device_params->encap_byte_swap && encap_flds) 1252 ulp_blob_perform_encap_swap(data); 1253 1254 return rc; 1255 } 1256 1257 static int32_t 1258 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, 1259 struct bnxt_ulp_mapper_tbl_info *tbl, 1260 uint64_t flow_id) 1261 { 1262 struct ulp_flow_db_res_params fid_parms; 1263 uint32_t mark, gfid, mark_flag; 1264 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1265 int32_t rc = 0; 1266 1267 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1268 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 1269 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1270 BNXT_ULP_ACTION_BIT_MARK))) 1271 return rc; /* no need to perform gfid process */ 1272 1273 /* Get the mark id details from action property */ 1274 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1275 sizeof(mark)); 1276 mark = tfp_be_to_cpu_32(mark); 1277 1278 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid); 1279 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID; 1280 1281 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1282 gfid, mark); 1283 if (rc) { 1284 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1285 return rc; 1286 } 1287 fid_parms.direction = tbl->direction; 1288 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1289 fid_parms.critical_resource = tbl->critical_resource; 1290 fid_parms.resource_type = mark_flag; 1291 fid_parms.resource_hndl = gfid; 1292 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1293 if (rc) 1294 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1295 return rc; 1296 } 1297 1298 static int32_t 1299 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, 1300 struct bnxt_ulp_mapper_tbl_info *tbl) 1301 { 1302 struct ulp_flow_db_res_params fid_parms; 1303 uint32_t act_idx, mark, mark_flag; 1304 uint64_t val64; 1305 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1306 int32_t rc = 0; 1307 1308 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1309 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 1310 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1311 BNXT_ULP_ACTION_BIT_MARK))) 1312 return rc; /* no need to perform mark action process */ 1313 1314 /* Get the mark id details from action property */ 1315 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1316 sizeof(mark)); 1317 mark = tfp_be_to_cpu_32(mark); 1318 1319 if (!ulp_regfile_read(parms->regfile, 1320 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 1321 &val64)) { 1322 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1323 return -EINVAL; 1324 } 1325 act_idx = tfp_be_to_cpu_64(val64); 1326 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID; 1327 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1328 act_idx, mark); 1329 if (rc) { 1330 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1331 return rc; 1332 } 1333 fid_parms.direction = tbl->direction; 1334 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1335 fid_parms.critical_resource = tbl->critical_resource; 1336 fid_parms.resource_type = mark_flag; 1337 fid_parms.resource_hndl = act_idx; 1338 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1339 if (rc) 1340 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1341 return rc; 1342 } 1343 1344 static int32_t 1345 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms, 1346 struct bnxt_ulp_mapper_tbl_info *tbl) 1347 { 1348 struct ulp_flow_db_res_params fid_parms; 1349 uint32_t act_idx, mark, mark_flag; 1350 uint64_t val64; 1351 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1352 int32_t rc = 0; 1353 1354 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1355 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION) 1356 return rc; /* no need to perform mark action process */ 1357 1358 /* Get the mark id details from the computed field of dev port id */ 1359 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID); 1360 1361 /* Get the main action pointer */ 1362 if (!ulp_regfile_read(parms->regfile, 1363 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 1364 &val64)) { 1365 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1366 return -EINVAL; 1367 } 1368 act_idx = tfp_be_to_cpu_64(val64); 1369 1370 /* Set the mark flag to local fid and vfr flag */ 1371 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; 1372 1373 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1374 act_idx, mark); 1375 if (rc) { 1376 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1377 return rc; 1378 } 1379 fid_parms.direction = tbl->direction; 1380 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1381 fid_parms.critical_resource = tbl->critical_resource; 1382 fid_parms.resource_type = mark_flag; 1383 fid_parms.resource_hndl = act_idx; 1384 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1385 if (rc) 1386 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1387 return rc; 1388 } 1389 1390 /* Tcam table scan the identifier list and allocate each identifier */ 1391 static int32_t 1392 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms, 1393 struct bnxt_ulp_mapper_tbl_info *tbl) 1394 { 1395 struct bnxt_ulp_mapper_ident_info *idents; 1396 uint32_t num_idents; 1397 uint32_t i; 1398 1399 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 1400 for (i = 0; i < num_idents; i++) { 1401 if (ulp_mapper_ident_process(parms, tbl, 1402 &idents[i], NULL)) 1403 return -EINVAL; 1404 } 1405 return 0; 1406 } 1407 1408 /* 1409 * Tcam table scan the identifier list and extract the identifier from 1410 * the result blob. 1411 */ 1412 static int32_t 1413 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms, 1414 struct bnxt_ulp_mapper_tbl_info *tbl, 1415 struct ulp_blob *data) 1416 { 1417 struct bnxt_ulp_mapper_ident_info *idents; 1418 uint32_t num_idents = 0, i; 1419 int32_t rc = 0; 1420 1421 /* 1422 * Extract the listed identifiers from the result field, 1423 * no need to allocate them. 1424 */ 1425 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 1426 for (i = 0; i < num_idents; i++) { 1427 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data); 1428 if (rc) { 1429 BNXT_TF_DBG(ERR, "Error in identifier extraction\n"); 1430 return rc; 1431 } 1432 } 1433 return rc; 1434 } 1435 1436 /* Internal function to write the tcam entry */ 1437 static int32_t 1438 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms, 1439 struct bnxt_ulp_mapper_tbl_info *tbl, 1440 struct ulp_blob *key, 1441 struct ulp_blob *mask, 1442 struct ulp_blob *data, 1443 uint16_t idx) 1444 { 1445 struct tf_set_tcam_entry_parms sparms = { 0 }; 1446 struct tf *tfp; 1447 uint16_t tmplen; 1448 int32_t rc; 1449 1450 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1451 if (!tfp) { 1452 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1453 return -EINVAL; 1454 } 1455 1456 sparms.dir = tbl->direction; 1457 sparms.tcam_tbl_type = tbl->resource_type; 1458 sparms.idx = idx; 1459 /* Already verified the key/mask lengths */ 1460 sparms.key = ulp_blob_data_get(key, &tmplen); 1461 sparms.mask = ulp_blob_data_get(mask, &tmplen); 1462 sparms.key_sz_in_bits = tbl->key_bit_size; 1463 sparms.result = ulp_blob_data_get(data, &tmplen); 1464 1465 if (tbl->result_bit_size != tmplen) { 1466 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n", 1467 tmplen, tbl->result_bit_size); 1468 return -EINVAL; 1469 } 1470 sparms.result_sz_in_bits = tbl->result_bit_size; 1471 if (tf_set_tcam_entry(tfp, &sparms)) { 1472 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n", 1473 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 1474 tf_dir_2_str(sparms.dir), sparms.idx); 1475 return -EIO; 1476 } 1477 1478 /* Mark action */ 1479 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1480 if (rc) { 1481 BNXT_TF_DBG(ERR, "failed mark action processing\n"); 1482 return rc; 1483 } 1484 1485 return rc; 1486 } 1487 1488 #define BNXT_ULP_WC_TCAM_SLICE_SIZE 80 1489 /* internal function to post process the key/mask blobs for wildcard tcam tbl */ 1490 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob, 1491 uint32_t len) 1492 { 1493 uint8_t mode[2] = {0x0, 0x0}; 1494 uint32_t mode_len = len / BNXT_ULP_WC_TCAM_SLICE_SIZE; 1495 uint32_t size, idx; 1496 1497 /* Add the mode bits to the key and mask*/ 1498 if (mode_len == 2) 1499 mode[1] = 2; 1500 else if (mode_len > 2) 1501 mode[1] = 3; 1502 1503 size = BNXT_ULP_WC_TCAM_SLICE_SIZE + ULP_BYTE_2_BITS(sizeof(mode)); 1504 for (idx = 0; idx < mode_len; idx++) 1505 ulp_blob_insert(blob, (size * idx), mode, 1506 ULP_BYTE_2_BITS(sizeof(mode))); 1507 ulp_blob_perform_64B_word_swap(blob); 1508 ulp_blob_perform_64B_byte_swap(blob); 1509 } 1510 1511 static int32_t 1512 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1513 struct bnxt_ulp_mapper_tbl_info *tbl) 1514 { 1515 struct bnxt_ulp_mapper_key_info *kflds; 1516 struct ulp_blob key, mask, data, update_data; 1517 uint32_t i, num_kflds; 1518 struct tf *tfp; 1519 int32_t rc, trc; 1520 struct tf_alloc_tcam_entry_parms aparms = { 0 }; 1521 struct tf_search_tcam_entry_parms searchparms = { 0 }; 1522 struct ulp_flow_db_res_params fid_parms = { 0 }; 1523 struct tf_free_tcam_entry_parms free_parms = { 0 }; 1524 uint32_t hit = 0; 1525 uint16_t tmplen = 0; 1526 uint16_t idx; 1527 1528 /* Skip this if table opcode is NOP */ 1529 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED || 1530 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) { 1531 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n", 1532 tbl->tbl_opcode); 1533 return 0; 1534 } 1535 1536 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1537 if (!tfp) { 1538 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1539 return -EINVAL; 1540 } 1541 1542 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 1543 if (!kflds || !num_kflds) { 1544 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1545 return -EINVAL; 1546 } 1547 1548 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, 1549 parms->device_params->byte_order) || 1550 !ulp_blob_init(&mask, tbl->blob_key_bit_size, 1551 parms->device_params->byte_order) || 1552 !ulp_blob_init(&data, tbl->result_bit_size, 1553 parms->device_params->byte_order) || 1554 !ulp_blob_init(&update_data, tbl->result_bit_size, 1555 parms->device_params->byte_order)) { 1556 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1557 return -EINVAL; 1558 } 1559 1560 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) { 1561 key.byte_order = BNXT_ULP_BYTE_ORDER_BE; 1562 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE; 1563 } 1564 1565 /* create the key/mask */ 1566 /* 1567 * NOTE: The WC table will require some kind of flag to handle the 1568 * mode bits within the key/mask 1569 */ 1570 for (i = 0; i < num_kflds; i++) { 1571 /* Setup the key */ 1572 rc = ulp_mapper_field_process(parms, tbl->direction, 1573 &kflds[i].field_info_spec, 1574 &key, 1, "TCAM Key"); 1575 if (rc) { 1576 BNXT_TF_DBG(ERR, "Key field set failed %s\n", 1577 kflds[i].field_info_spec.description); 1578 return rc; 1579 } 1580 1581 /* Setup the mask */ 1582 rc = ulp_mapper_field_process(parms, tbl->direction, 1583 &kflds[i].field_info_mask, 1584 &mask, 0, "TCAM Mask"); 1585 if (rc) { 1586 BNXT_TF_DBG(ERR, "Mask field set failed %s\n", 1587 kflds[i].field_info_mask.description); 1588 return rc; 1589 } 1590 } 1591 1592 /* For wild card tcam perform the post process to swap the blob */ 1593 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) { 1594 ulp_mapper_wc_tcam_tbl_post_process(&key, tbl->key_bit_size); 1595 ulp_mapper_wc_tcam_tbl_post_process(&mask, tbl->key_bit_size); 1596 } 1597 1598 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 1599 /* allocate the tcam index */ 1600 aparms.dir = tbl->direction; 1601 aparms.tcam_tbl_type = tbl->resource_type; 1602 aparms.key = ulp_blob_data_get(&key, &tmplen); 1603 aparms.key_sz_in_bits = tmplen; 1604 if (tbl->blob_key_bit_size != tmplen) { 1605 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n", 1606 tmplen, tbl->blob_key_bit_size); 1607 return -EINVAL; 1608 } 1609 1610 aparms.mask = ulp_blob_data_get(&mask, &tmplen); 1611 if (tbl->blob_key_bit_size != tmplen) { 1612 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n", 1613 tmplen, tbl->blob_key_bit_size); 1614 return -EINVAL; 1615 } 1616 1617 /* calculate the entry priority */ 1618 rc = ulp_mapper_priority_opc_process(parms, tbl, 1619 &aparms.priority); 1620 if (rc) { 1621 BNXT_TF_DBG(ERR, "entry priority process failed\n"); 1622 return rc; 1623 } 1624 1625 rc = tf_alloc_tcam_entry(tfp, &aparms); 1626 if (rc) { 1627 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); 1628 return rc; 1629 } 1630 idx = aparms.idx; 1631 hit = aparms.hit; 1632 } else { 1633 /* 1634 * Searching before allocation to see if we already have an 1635 * entry. This allows re-use of a constrained resource. 1636 */ 1637 searchparms.dir = tbl->direction; 1638 searchparms.tcam_tbl_type = tbl->resource_type; 1639 searchparms.key = ulp_blob_data_get(&key, &tmplen); 1640 searchparms.key_sz_in_bits = tbl->key_bit_size; 1641 searchparms.mask = ulp_blob_data_get(&mask, &tmplen); 1642 searchparms.alloc = 1; 1643 searchparms.result = ulp_blob_data_get(&data, &tmplen); 1644 searchparms.result_sz_in_bits = tbl->result_bit_size; 1645 1646 /* calculate the entry priority */ 1647 rc = ulp_mapper_priority_opc_process(parms, tbl, 1648 &searchparms.priority); 1649 if (rc) { 1650 BNXT_TF_DBG(ERR, "entry priority process failed\n"); 1651 return rc; 1652 } 1653 1654 rc = tf_search_tcam_entry(tfp, &searchparms); 1655 if (rc) { 1656 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc); 1657 return rc; 1658 } 1659 1660 /* Successful search, check the result */ 1661 if (searchparms.search_status == REJECT) { 1662 BNXT_TF_DBG(ERR, "tcam alloc rejected\n"); 1663 return -ENOMEM; 1664 } 1665 idx = searchparms.idx; 1666 hit = searchparms.hit; 1667 } 1668 1669 /* Write the tcam index into the regfile*/ 1670 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand, 1671 (uint64_t)tfp_cpu_to_be_64(idx))) { 1672 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", 1673 tbl->tbl_operand); 1674 rc = -EINVAL; 1675 /* Need to free the tcam idx, so goto error */ 1676 goto error; 1677 } 1678 1679 /* if it is miss then it is same as no search before alloc */ 1680 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 1681 /*Scan identifier list, allocate identifier and update regfile*/ 1682 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); 1683 /* Create the result blob */ 1684 if (!rc) 1685 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 1686 "TCAM Result"); 1687 /* write the tcam entry */ 1688 if (!rc) 1689 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key, 1690 &mask, &data, idx); 1691 } else { 1692 /*Scan identifier list, extract identifier and update regfile*/ 1693 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); 1694 } 1695 if (rc) 1696 goto error; 1697 1698 /* Add the tcam index to the flow database */ 1699 fid_parms.direction = tbl->direction; 1700 fid_parms.resource_func = tbl->resource_func; 1701 fid_parms.resource_type = tbl->resource_type; 1702 fid_parms.critical_resource = tbl->critical_resource; 1703 fid_parms.resource_hndl = idx; 1704 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1705 if (rc) { 1706 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 1707 rc); 1708 /* Need to free the identifier, so goto error */ 1709 goto error; 1710 } 1711 1712 return 0; 1713 error: 1714 free_parms.dir = tbl->direction; 1715 free_parms.tcam_tbl_type = tbl->resource_type; 1716 free_parms.idx = idx; 1717 trc = tf_free_tcam_entry(tfp, &free_parms); 1718 if (trc) 1719 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", 1720 tbl->resource_type, tbl->direction, idx); 1721 return rc; 1722 } 1723 1724 static int32_t 1725 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1726 struct bnxt_ulp_mapper_tbl_info *tbl) 1727 { 1728 struct bnxt_ulp_mapper_key_info *kflds; 1729 struct ulp_blob key, data; 1730 uint32_t i, num_kflds; 1731 uint16_t tmplen; 1732 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1733 struct ulp_flow_db_res_params fid_parms = { 0 }; 1734 struct tf_insert_em_entry_parms iparms = { 0 }; 1735 struct tf_delete_em_entry_parms free_parms = { 0 }; 1736 enum bnxt_ulp_flow_mem_type mtype; 1737 int32_t trc; 1738 int32_t rc = 0; 1739 1740 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); 1741 if (rc) { 1742 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n"); 1743 return -EINVAL; 1744 } 1745 1746 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 1747 if (!kflds || !num_kflds) { 1748 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1749 return -EINVAL; 1750 } 1751 1752 /* Initialize the key/result blobs */ 1753 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, 1754 parms->device_params->byte_order) || 1755 !ulp_blob_init(&data, tbl->result_bit_size, 1756 parms->device_params->byte_order)) { 1757 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1758 return -EINVAL; 1759 } 1760 1761 /* create the key */ 1762 for (i = 0; i < num_kflds; i++) { 1763 /* Setup the key */ 1764 rc = ulp_mapper_field_process(parms, tbl->direction, 1765 &kflds[i].field_info_spec, 1766 &key, 1, "EM Key"); 1767 if (rc) { 1768 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 1769 return rc; 1770 } 1771 } 1772 1773 /* 1774 * TBD: Normally should process identifiers in case of using recycle or 1775 * loopback. Not supporting recycle for now. 1776 */ 1777 1778 /* Create the result data blob */ 1779 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result"); 1780 if (rc) { 1781 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 1782 return rc; 1783 } 1784 /* do the transpose for the internal EM keys */ 1785 if (tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE) 1786 ulp_blob_perform_byte_reverse(&key); 1787 1788 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, 1789 &iparms.tbl_scope_id); 1790 if (rc) { 1791 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1792 return rc; 1793 } 1794 1795 /* 1796 * NOTE: the actual blob size will differ from the size in the tbl 1797 * entry due to the padding. 1798 */ 1799 iparms.dup_check = 0; 1800 iparms.dir = tbl->direction; 1801 iparms.mem = tbl->resource_type; 1802 iparms.key = ulp_blob_data_get(&key, &tmplen); 1803 iparms.key_sz_in_bits = tbl->key_bit_size; 1804 iparms.em_record = ulp_blob_data_get(&data, &tmplen); 1805 iparms.em_record_sz_in_bits = tbl->result_bit_size; 1806 1807 rc = tf_insert_em_entry(tfp, &iparms); 1808 if (rc) { 1809 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc); 1810 return rc; 1811 } 1812 1813 /* Mark action process */ 1814 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && 1815 tbl->resource_type == TF_MEM_EXTERNAL) 1816 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); 1817 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && 1818 tbl->resource_type == TF_MEM_INTERNAL) 1819 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1820 if (rc) { 1821 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1822 goto error; 1823 } 1824 1825 /* Link the EM resource to the flow in the flow db */ 1826 memset(&fid_parms, 0, sizeof(fid_parms)); 1827 fid_parms.direction = tbl->direction; 1828 fid_parms.resource_func = tbl->resource_func; 1829 fid_parms.resource_type = tbl->resource_type; 1830 fid_parms.critical_resource = tbl->critical_resource; 1831 fid_parms.resource_hndl = iparms.flow_handle; 1832 1833 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1834 if (rc) { 1835 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", 1836 rc); 1837 /* Need to free the identifier, so goto error */ 1838 goto error; 1839 } 1840 1841 return 0; 1842 error: 1843 free_parms.dir = iparms.dir; 1844 free_parms.mem = iparms.mem; 1845 free_parms.tbl_scope_id = iparms.tbl_scope_id; 1846 free_parms.flow_handle = iparms.flow_handle; 1847 1848 trc = tf_delete_em_entry(tfp, &free_parms); 1849 if (trc) 1850 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n"); 1851 1852 return rc; 1853 } 1854 1855 static int32_t 1856 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1857 struct bnxt_ulp_mapper_tbl_info *tbl) 1858 { 1859 struct ulp_flow_db_res_params fid_parms; 1860 struct ulp_blob data; 1861 uint64_t regval = 0; 1862 uint16_t tmplen; 1863 uint32_t index, hit; 1864 int32_t rc = 0, trc = 0; 1865 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 1866 struct tf_search_tbl_entry_parms srchparms = { 0 }; 1867 struct tf_set_tbl_entry_parms sparms = { 0 }; 1868 struct tf_get_tbl_entry_parms gparms = { 0 }; 1869 struct tf_free_tbl_entry_parms free_parms = { 0 }; 1870 uint32_t tbl_scope_id; 1871 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 1872 uint16_t bit_size; 1873 bool alloc = false; 1874 bool write = false; 1875 bool search = false; 1876 1877 /* use the max size if encap is enabled */ 1878 if (tbl->encap_num_fields) 1879 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 1880 else 1881 bit_size = tbl->result_bit_size; 1882 1883 /* Initialize the blob data */ 1884 if (!ulp_blob_init(&data, bit_size, 1885 parms->device_params->byte_order)) { 1886 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n"); 1887 return -EINVAL; 1888 } 1889 1890 /* Get the scope id first */ 1891 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); 1892 if (rc) { 1893 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 1894 return rc; 1895 } 1896 1897 switch (tbl->tbl_opcode) { 1898 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE: 1899 alloc = true; 1900 break; 1901 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE: 1902 /* 1903 * Build the entry, alloc an index, write the table, and store 1904 * the data in the regfile. 1905 */ 1906 alloc = true; 1907 write = true; 1908 break; 1909 case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE: 1910 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 1911 /* Not currently supporting with EXT */ 1912 BNXT_TF_DBG(ERR, 1913 "Ext Table Search Opcode not supported.\n"); 1914 return -EINVAL; 1915 } 1916 /* 1917 * Search for the entry in the tf core. If it is hit, save the 1918 * index in the regfile. If it is a miss, Build the entry, 1919 * alloc an index, write the table, and store the data in the 1920 * regfile (same as ALLOC_WR). 1921 */ 1922 search = true; 1923 break; 1924 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE: 1925 /* 1926 * get the index to write to from the regfile and then write 1927 * the table entry. 1928 */ 1929 if (!ulp_regfile_read(parms->regfile, 1930 tbl->tbl_operand, 1931 ®val)) { 1932 BNXT_TF_DBG(ERR, 1933 "Failed to get tbl idx from regfile[%d].\n", 1934 tbl->tbl_operand); 1935 return -EINVAL; 1936 } 1937 index = tfp_be_to_cpu_64(regval); 1938 /* For external, we need to reverse shift */ 1939 if (tbl->resource_type == TF_TBL_TYPE_EXT) 1940 index = TF_ACT_REC_PTR_2_OFFSET(index); 1941 1942 write = true; 1943 break; 1944 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE: 1945 /* 1946 * get the index to write to from the global regfile and then 1947 * write the table. 1948 */ 1949 if (ulp_mapper_glb_resource_read(parms->mapper_data, 1950 tbl->direction, 1951 tbl->tbl_operand, 1952 ®val)) { 1953 BNXT_TF_DBG(ERR, 1954 "Failed to get tbl idx from Global " 1955 "regfile[%d].\n", 1956 tbl->tbl_operand); 1957 return -EINVAL; 1958 } 1959 index = tfp_be_to_cpu_64(regval); 1960 /* For external, we need to reverse shift */ 1961 if (tbl->resource_type == TF_TBL_TYPE_EXT) 1962 index = TF_ACT_REC_PTR_2_OFFSET(index); 1963 write = true; 1964 break; 1965 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE: 1966 /* 1967 * The read is different from the rest and can be handled here 1968 * instead of trying to use common code. Simply read the table 1969 * with the index from the regfile, scan and store the 1970 * identifiers, and return. 1971 */ 1972 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 1973 /* Not currently supporting with EXT */ 1974 BNXT_TF_DBG(ERR, 1975 "Ext Table Read Opcode not supported.\n"); 1976 return -EINVAL; 1977 } 1978 if (!ulp_regfile_read(parms->regfile, 1979 tbl->tbl_operand, ®val)) { 1980 BNXT_TF_DBG(ERR, 1981 "Failed to get tbl idx from regfile[%d]\n", 1982 tbl->tbl_operand); 1983 return -EINVAL; 1984 } 1985 index = tfp_be_to_cpu_64(regval); 1986 gparms.dir = tbl->direction; 1987 gparms.type = tbl->resource_type; 1988 gparms.data = ulp_blob_data_get(&data, &tmplen); 1989 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size); 1990 gparms.idx = index; 1991 rc = tf_get_tbl_entry(tfp, &gparms); 1992 if (rc) { 1993 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n", 1994 tbl->resource_type, index); 1995 return rc; 1996 } 1997 /* 1998 * Scan the fields in the entry and push them into the regfile. 1999 */ 2000 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2001 gparms.data, 2002 gparms.data_sz_in_bytes, 2003 data.byte_order); 2004 if (rc) { 2005 BNXT_TF_DBG(ERR, "Failed to read fields on tbl read " 2006 "rc=%d\n", rc); 2007 return rc; 2008 } 2009 return 0; 2010 default: 2011 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n", 2012 tbl->tbl_opcode); 2013 return -EINVAL; 2014 } 2015 2016 if (write || search) { 2017 /* Get the result fields list */ 2018 rc = ulp_mapper_tbl_result_build(parms, 2019 tbl, 2020 &data, 2021 "Indexed Result"); 2022 if (rc) { 2023 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2024 return rc; 2025 } 2026 } 2027 2028 if (search) { 2029 /* Use the result blob to perform a search */ 2030 memset(&srchparms, 0, sizeof(srchparms)); 2031 srchparms.dir = tbl->direction; 2032 srchparms.type = tbl->resource_type; 2033 srchparms.alloc = 1; 2034 srchparms.result = ulp_blob_data_get(&data, &tmplen); 2035 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2036 srchparms.tbl_scope_id = tbl_scope_id; 2037 rc = tf_search_tbl_entry(tfp, &srchparms); 2038 if (rc) { 2039 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2040 tf_tbl_type_2_str(tbl->resource_type), 2041 tf_dir_2_str(tbl->direction), rc); 2042 return rc; 2043 } 2044 if (srchparms.search_status == REJECT) { 2045 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n", 2046 tf_tbl_type_2_str(tbl->resource_type), 2047 tf_dir_2_str(tbl->direction)); 2048 return -ENOMEM; 2049 } 2050 index = srchparms.idx; 2051 hit = srchparms.hit; 2052 if (hit) 2053 write = false; 2054 else 2055 write = true; 2056 } 2057 2058 if (alloc) { 2059 aparms.dir = tbl->direction; 2060 aparms.type = tbl->resource_type; 2061 aparms.tbl_scope_id = tbl_scope_id; 2062 2063 /* All failures after the alloc succeeds require a free */ 2064 rc = tf_alloc_tbl_entry(tfp, &aparms); 2065 if (rc) { 2066 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2067 tf_tbl_type_2_str(tbl->resource_type), 2068 tf_dir_2_str(tbl->direction), rc); 2069 return rc; 2070 } 2071 index = aparms.idx; 2072 } 2073 2074 if (search || alloc) { 2075 /* 2076 * Store the index in the regfile since we either allocated it 2077 * or it was a hit. 2078 * 2079 * Calculate the idx for the result record, for external EM the 2080 * offset needs to be shifted accordingly. 2081 * If external non-inline table types are used then need to 2082 * revisit this logic. 2083 */ 2084 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2085 regval = TF_ACT_REC_OFFSET_2_PTR(index); 2086 else 2087 regval = index; 2088 2089 rc = ulp_regfile_write(parms->regfile, 2090 tbl->tbl_operand, 2091 tfp_cpu_to_be_64(regval)); 2092 if (rc) { 2093 BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n", 2094 tbl->tbl_operand, rc); 2095 goto error; 2096 } 2097 } 2098 2099 if (write) { 2100 sparms.dir = tbl->direction; 2101 sparms.type = tbl->resource_type; 2102 sparms.data = ulp_blob_data_get(&data, &tmplen); 2103 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2104 sparms.idx = index; 2105 sparms.tbl_scope_id = tbl_scope_id; 2106 rc = tf_set_tbl_entry(tfp, &sparms); 2107 if (rc) { 2108 BNXT_TF_DBG(ERR, 2109 "Index table[%s][%s][%x] write failed " 2110 "rc=%d\n", 2111 tf_tbl_type_2_str(sparms.type), 2112 tf_dir_2_str(sparms.dir), 2113 sparms.idx, rc); 2114 goto error; 2115 } 2116 } 2117 2118 /* Link the resource to the flow in the flow db */ 2119 memset(&fid_parms, 0, sizeof(fid_parms)); 2120 fid_parms.direction = tbl->direction; 2121 fid_parms.resource_func = tbl->resource_func; 2122 fid_parms.resource_type = tbl->resource_type; 2123 fid_parms.resource_sub_type = tbl->resource_sub_type; 2124 fid_parms.resource_hndl = index; 2125 fid_parms.critical_resource = tbl->critical_resource; 2126 2127 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2128 if (rc) { 2129 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2130 rc); 2131 goto error; 2132 } 2133 2134 /* Perform the VF rep action */ 2135 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 2136 if (rc) { 2137 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 2138 goto error; 2139 } 2140 return rc; 2141 error: 2142 /* 2143 * Free the allocated resource since we failed to either 2144 * write to the entry or link the flow 2145 */ 2146 free_parms.dir = tbl->direction; 2147 free_parms.type = tbl->resource_type; 2148 free_parms.idx = index; 2149 free_parms.tbl_scope_id = tbl_scope_id; 2150 2151 trc = tf_free_tbl_entry(tfp, &free_parms); 2152 if (trc) 2153 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n"); 2154 2155 return rc; 2156 } 2157 2158 static int32_t 2159 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2160 struct bnxt_ulp_mapper_tbl_info *tbl) 2161 { 2162 struct ulp_blob data, res_blob; 2163 uint64_t idx; 2164 uint16_t tmplen; 2165 int32_t rc = 0; 2166 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; 2167 struct tf_get_if_tbl_entry_parms get_parms = { 0 }; 2168 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx); 2169 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode; 2170 uint32_t res_size; 2171 2172 /* Initialize the blob data */ 2173 if (!ulp_blob_init(&data, tbl->result_bit_size, 2174 parms->device_params->byte_order)) { 2175 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 2176 return -EINVAL; 2177 } 2178 2179 /* create the result blob */ 2180 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result"); 2181 if (rc) { 2182 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2183 return rc; 2184 } 2185 2186 /* Get the index details */ 2187 switch (if_opc) { 2188 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD: 2189 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 2190 break; 2191 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE: 2192 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) { 2193 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 2194 tbl->tbl_operand); 2195 return -EINVAL; 2196 } 2197 idx = tfp_be_to_cpu_64(idx); 2198 break; 2199 case BNXT_ULP_IF_TBL_OPC_WR_CONST: 2200 idx = tbl->tbl_operand; 2201 break; 2202 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD: 2203 /* Initialize the result blob */ 2204 if (!ulp_blob_init(&res_blob, tbl->result_bit_size, 2205 parms->device_params->byte_order)) { 2206 BNXT_TF_DBG(ERR, "Failed initial result blob\n"); 2207 return -EINVAL; 2208 } 2209 2210 /* read the interface table */ 2211 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 2212 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size); 2213 get_parms.dir = tbl->direction; 2214 get_parms.type = tbl->resource_type; 2215 get_parms.idx = idx; 2216 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen); 2217 get_parms.data_sz_in_bytes = res_size; 2218 2219 rc = tf_get_if_tbl_entry(tfp, &get_parms); 2220 if (rc) { 2221 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n", 2222 get_parms.type, 2223 tf_dir_2_str(get_parms.dir), 2224 get_parms.idx, rc); 2225 return rc; 2226 } 2227 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2228 res_blob.data, 2229 res_size, 2230 res_blob.byte_order); 2231 if (rc) 2232 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc); 2233 return rc; 2234 case BNXT_ULP_IF_TBL_OPC_NOT_USED: 2235 return rc; /* skip it */ 2236 default: 2237 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); 2238 return -EINVAL; 2239 } 2240 2241 /* Perform the tf table set by filling the set params */ 2242 iftbl_params.dir = tbl->direction; 2243 iftbl_params.type = tbl->resource_type; 2244 iftbl_params.data = ulp_blob_data_get(&data, &tmplen); 2245 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2246 iftbl_params.idx = idx; 2247 2248 rc = tf_set_if_tbl_entry(tfp, &iftbl_params); 2249 if (rc) { 2250 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n", 2251 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */ 2252 tf_dir_2_str(iftbl_params.dir), 2253 iftbl_params.idx, rc); 2254 return rc; 2255 } 2256 2257 /* 2258 * TBD: Need to look at the need to store idx in flow db for restore 2259 * the table to its original state on deletion of this entry. 2260 */ 2261 return rc; 2262 } 2263 2264 static int32_t 2265 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2266 struct bnxt_ulp_mapper_tbl_info *tbl) 2267 { 2268 struct bnxt_ulp_mapper_key_info *kflds; 2269 struct ulp_flow_db_res_params fid_parms; 2270 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g; 2271 uint16_t tmplen; 2272 struct ulp_blob key, data; 2273 uint8_t *cache_key; 2274 int32_t tbl_idx; 2275 uint32_t i, ckey, num_kflds = 0; 2276 uint32_t gen_tbl_hit = 0, fdb_write = 0; 2277 uint8_t *byte_data; 2278 int32_t rc = 0; 2279 2280 /* Get the key fields list and build the key. */ 2281 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2282 if (!kflds || !num_kflds) { 2283 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2284 return -EINVAL; 2285 } 2286 if (!ulp_blob_init(&key, tbl->key_bit_size, 2287 parms->device_params->byte_order)) { 2288 BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); 2289 return -EINVAL; 2290 } 2291 for (i = 0; i < num_kflds; i++) { 2292 /* Setup the key */ 2293 rc = ulp_mapper_field_process(parms, tbl->direction, 2294 &kflds[i].field_info_spec, 2295 &key, 1, "Gen Tbl Key"); 2296 if (rc) { 2297 BNXT_TF_DBG(ERR, 2298 "Failed to create key for Gen tbl rc=%d\n", 2299 rc); 2300 return -EINVAL; 2301 } 2302 } 2303 2304 /* Calculate the table index for the generic table*/ 2305 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type, 2306 tbl->direction); 2307 if (tbl_idx < 0) { 2308 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n", 2309 tbl->resource_sub_type, tbl->direction); 2310 return -EINVAL; 2311 } 2312 2313 /* The_key is a byte array convert it to a search index */ 2314 cache_key = ulp_blob_data_get(&key, &tmplen); 2315 memcpy(&ckey, cache_key, sizeof(ckey)); 2316 /* Get the generic table entry */ 2317 rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx, 2318 tbl_idx, ckey, &gen_tbl_ent); 2319 if (rc) { 2320 BNXT_TF_DBG(ERR, 2321 "Failed to create key for Gen tbl rc=%d\n", rc); 2322 return -EINVAL; 2323 } 2324 switch (tbl->tbl_opcode) { 2325 case BNXT_ULP_GENERIC_TBL_OPC_READ: 2326 /* check the reference count */ 2327 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { 2328 g = &gen_tbl_ent; 2329 /* Scan ident list and create the result blob*/ 2330 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2331 g->byte_data, 2332 g->byte_data_size, 2333 g->byte_order); 2334 if (rc) { 2335 BNXT_TF_DBG(ERR, 2336 "Failed to scan ident list\n"); 2337 return -EINVAL; 2338 } 2339 /* increment the reference count */ 2340 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); 2341 2342 /* it is a hit */ 2343 gen_tbl_hit = 1; 2344 fdb_write = 1; 2345 } 2346 break; 2347 case BNXT_ULP_GENERIC_TBL_OPC_WRITE: 2348 /* check the reference count */ 2349 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { 2350 /* a hit then error */ 2351 BNXT_TF_DBG(ERR, "generic entry already present %x\n", 2352 ckey); 2353 return -EINVAL; /* success */ 2354 } 2355 2356 /* Initialize the blob data */ 2357 if (!ulp_blob_init(&data, tbl->result_bit_size, 2358 gen_tbl_ent.byte_order)) { 2359 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 2360 return -EINVAL; 2361 } 2362 2363 /* Get the result fields list */ 2364 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 2365 "Gen tbl Result"); 2366 if (rc) { 2367 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2368 return rc; 2369 } 2370 byte_data = ulp_blob_data_get(&data, &tmplen); 2371 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent, 2372 tmplen, byte_data, 2373 ULP_BITS_2_BYTE(tmplen)); 2374 if (rc) { 2375 BNXT_TF_DBG(ERR, "Failed to write generic table\n"); 2376 return -EINVAL; 2377 } 2378 2379 /* increment the reference count */ 2380 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); 2381 fdb_write = 1; 2382 break; 2383 default: 2384 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode); 2385 return -EINVAL; 2386 } 2387 2388 /* Set the generic entry hit */ 2389 rc = ulp_regfile_write(parms->regfile, 2390 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT, 2391 tfp_cpu_to_be_64(gen_tbl_hit)); 2392 if (rc) { 2393 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 2394 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT); 2395 return -EIO; 2396 } 2397 2398 /* add the entry to the flow database */ 2399 if (fdb_write) { 2400 memset(&fid_parms, 0, sizeof(fid_parms)); 2401 fid_parms.direction = tbl->direction; 2402 fid_parms.resource_func = tbl->resource_func; 2403 fid_parms.resource_sub_type = tbl->resource_sub_type; 2404 fid_parms.resource_hndl = ckey; 2405 fid_parms.critical_resource = tbl->critical_resource; 2406 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2407 if (rc) 2408 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc); 2409 } 2410 return rc; 2411 } 2412 2413 static int32_t 2414 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 2415 struct bnxt_ulp_mapper_data *mapper_data) 2416 { 2417 struct bnxt_ulp_glb_resource_info *glb_res; 2418 uint32_t num_glb_res_ids, idx; 2419 int32_t rc = 0; 2420 2421 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); 2422 if (!glb_res || !num_glb_res_ids) { 2423 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 2424 return -EINVAL; 2425 } 2426 2427 /* Iterate the global resources and process each one */ 2428 for (idx = 0; idx < num_glb_res_ids; idx++) { 2429 switch (glb_res[idx].resource_func) { 2430 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2431 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 2432 mapper_data, 2433 &glb_res[idx]); 2434 break; 2435 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2436 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 2437 mapper_data, 2438 &glb_res[idx]); 2439 break; 2440 default: 2441 BNXT_TF_DBG(ERR, "Global resource %x not supported\n", 2442 glb_res[idx].resource_func); 2443 rc = -EINVAL; 2444 break; 2445 } 2446 if (rc) 2447 return rc; 2448 } 2449 return rc; 2450 } 2451 2452 /* 2453 * Function to process the memtype opcode of the mapper table. 2454 * returns 1 to skip the table. 2455 * return 0 to continue processing the table. 2456 * 2457 * defaults to skip 2458 */ 2459 static int32_t 2460 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms, 2461 struct bnxt_ulp_mapper_tbl_info *tbl) 2462 { 2463 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT; 2464 int32_t rc = 1; 2465 2466 bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); 2467 2468 switch (tbl->mem_type_opcode) { 2469 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT: 2470 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) 2471 rc = 0; 2472 break; 2473 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT: 2474 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT) 2475 rc = 0; 2476 break; 2477 case BNXT_ULP_MEM_TYPE_OPC_NOP: 2478 rc = 0; 2479 break; 2480 default: 2481 BNXT_TF_DBG(ERR, 2482 "Invalid arg in mapper in memtype opcode\n"); 2483 break; 2484 } 2485 return rc; 2486 } 2487 2488 /* 2489 * Common conditional opcode process routine that is used for both the template 2490 * rejection and table conditional execution. 2491 */ 2492 static int32_t 2493 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms, 2494 enum bnxt_ulp_cond_opc opc, 2495 uint32_t operand, 2496 int32_t *res) 2497 { 2498 int32_t rc = 0; 2499 uint8_t bit; 2500 uint64_t regval; 2501 2502 switch (opc) { 2503 case BNXT_ULP_COND_OPC_COMP_FIELD_IS_SET: 2504 if (operand < BNXT_ULP_CF_IDX_LAST) { 2505 *res = ULP_COMP_FLD_IDX_RD(parms, operand); 2506 } else { 2507 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", 2508 operand); 2509 rc = -EINVAL; 2510 } 2511 break; 2512 case BNXT_ULP_COND_OPC_COMP_FIELD_NOT_SET: 2513 if (operand < BNXT_ULP_CF_IDX_LAST) { 2514 *res = !ULP_COMP_FLD_IDX_RD(parms, operand); 2515 } else { 2516 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", 2517 operand); 2518 rc = -EINVAL; 2519 } 2520 break; 2521 case BNXT_ULP_COND_OPC_ACTION_BIT_IS_SET: 2522 if (operand < BNXT_ULP_ACTION_BIT_LAST) { 2523 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2524 operand); 2525 } else { 2526 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", 2527 operand); 2528 rc = -EINVAL; 2529 } 2530 break; 2531 case BNXT_ULP_COND_OPC_ACTION_BIT_NOT_SET: 2532 if (operand < BNXT_ULP_ACTION_BIT_LAST) { 2533 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2534 operand); 2535 } else { 2536 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", 2537 operand); 2538 rc = -EINVAL; 2539 } 2540 break; 2541 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET: 2542 if (operand < BNXT_ULP_HDR_BIT_LAST) { 2543 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2544 operand); 2545 } else { 2546 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 2547 operand); 2548 rc = -EINVAL; 2549 } 2550 break; 2551 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET: 2552 if (operand < BNXT_ULP_HDR_BIT_LAST) { 2553 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 2554 operand); 2555 } else { 2556 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 2557 operand); 2558 rc = -EINVAL; 2559 } 2560 break; 2561 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET: 2562 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 2563 if (rc) { 2564 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 2565 operand); 2566 return -EINVAL; 2567 } 2568 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 2569 break; 2570 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET: 2571 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 2572 if (rc) { 2573 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 2574 operand); 2575 return -EINVAL; 2576 } 2577 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 2578 break; 2579 case BNXT_ULP_COND_OPC_REGFILE_IS_SET: 2580 if (!ulp_regfile_read(parms->regfile, operand, ®val)) { 2581 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); 2582 return -EINVAL; 2583 } 2584 *res = regval != 0; 2585 break; 2586 case BNXT_ULP_COND_OPC_REGFILE_NOT_SET: 2587 if (!ulp_regfile_read(parms->regfile, operand, ®val)) { 2588 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); 2589 return -EINVAL; 2590 } 2591 *res = regval == 0; 2592 break; 2593 default: 2594 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc); 2595 rc = -EINVAL; 2596 break; 2597 } 2598 return (rc); 2599 } 2600 2601 /* 2602 * Processes a list of conditions and returns both a status and result of the 2603 * list. The status must be checked prior to verifying the result. 2604 * 2605 * returns 0 for success, negative on failure 2606 * returns res = 1 for true, res = 0 for false. 2607 */ 2608 static int32_t 2609 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms, 2610 enum bnxt_ulp_cond_list_opc list_opc, 2611 struct bnxt_ulp_mapper_cond_info *list, 2612 uint32_t num, 2613 int32_t *res) 2614 { 2615 uint32_t i; 2616 int32_t rc = 0, trc; 2617 2618 switch (list_opc) { 2619 case BNXT_ULP_COND_LIST_OPC_AND: 2620 /* AND Defaults to true. */ 2621 *res = 1; 2622 break; 2623 case BNXT_ULP_COND_LIST_OPC_OR: 2624 /* OR Defaults to false. */ 2625 *res = 0; 2626 break; 2627 case BNXT_ULP_COND_LIST_OPC_TRUE: 2628 *res = 1; 2629 return rc; 2630 case BNXT_ULP_COND_LIST_OPC_FALSE: 2631 *res = 0; 2632 return rc; 2633 default: 2634 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n", 2635 list_opc); 2636 return -EINVAL; 2637 } 2638 2639 for (i = 0; i < num; i++) { 2640 rc = ulp_mapper_cond_opc_process(parms, 2641 list[i].cond_opcode, 2642 list[i].cond_operand, 2643 &trc); 2644 if (rc) 2645 return rc; 2646 2647 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) { 2648 /* early return if result is ever zero */ 2649 if (!trc) { 2650 *res = trc; 2651 return rc; 2652 } 2653 } else { 2654 /* early return if result is ever non-zero */ 2655 if (trc) { 2656 *res = trc; 2657 return rc; 2658 } 2659 } 2660 } 2661 2662 return rc; 2663 } 2664 2665 /* 2666 * Processes conflict resolution and returns both a status and result. 2667 * The status must be checked prior to verifying the result. 2668 * 2669 * returns 0 for success, negative on failure 2670 * returns res = 1 for true, res = 0 for false. 2671 */ 2672 static int32_t 2673 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms, 2674 struct bnxt_ulp_mapper_tbl_info *tbl, 2675 int32_t *res) 2676 { 2677 int32_t rc = 0; 2678 uint64_t regval; 2679 uint64_t comp_sig_id; 2680 2681 *res = 0; 2682 switch (tbl->accept_opcode) { 2683 case BNXT_ULP_ACCEPT_OPC_ALWAYS: 2684 *res = 1; 2685 break; 2686 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH: 2687 /* perform the signature validation*/ 2688 if (tbl->resource_func == 2689 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) { 2690 /* Perform the check that generic table is hit or not */ 2691 if (!ulp_regfile_read(parms->regfile, 2692 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT, 2693 ®val)) { 2694 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 2695 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT); 2696 return -EINVAL; 2697 } 2698 if (!regval) { 2699 /* not a hit so no need to check flow sign*/ 2700 *res = 1; 2701 return rc; 2702 } 2703 } 2704 /* compare the new flow signature against stored one */ 2705 if (!ulp_regfile_read(parms->regfile, 2706 BNXT_ULP_RF_IDX_FLOW_SIG_ID, 2707 ®val)) { 2708 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 2709 BNXT_ULP_RF_IDX_FLOW_SIG_ID); 2710 return -EINVAL; 2711 } 2712 comp_sig_id = ULP_COMP_FLD_IDX_RD(parms, 2713 BNXT_ULP_CF_IDX_FLOW_SIG_ID); 2714 regval = tfp_be_to_cpu_64(regval); 2715 if (comp_sig_id == regval) 2716 *res = 1; 2717 else 2718 BNXT_TF_DBG(ERR, "failed signature match %x:%x\n", 2719 (uint32_t)comp_sig_id, (uint32_t)regval); 2720 break; 2721 default: 2722 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n", 2723 tbl->accept_opcode); 2724 return -EINVAL; 2725 } 2726 return rc; 2727 } 2728 2729 static int32_t 2730 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid) 2731 { 2732 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL; 2733 enum bnxt_ulp_cond_list_opc cond_opc; 2734 struct bnxt_ulp_mapper_tbl_info *tbls; 2735 struct bnxt_ulp_mapper_tbl_info *tbl; 2736 uint32_t num_tbls, i, num_cond_tbls; 2737 int32_t rc = -EINVAL, cond_rc = 0; 2738 2739 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid, 2740 &num_cond_tbls, 2741 &cond_opc); 2742 /* 2743 * Process the reject list if exists, otherwise assume that the 2744 * template is allowed. 2745 */ 2746 if (cond_tbls && num_cond_tbls) { 2747 rc = ulp_mapper_cond_opc_list_process(parms, 2748 cond_opc, 2749 cond_tbls, 2750 num_cond_tbls, 2751 &cond_rc); 2752 if (rc) 2753 return rc; 2754 2755 /* Reject the template if True */ 2756 if (cond_rc) { 2757 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n", 2758 ulp_mapper_tmpl_name_str(parms->tmpl_type), 2759 tid); 2760 return -EINVAL; 2761 } 2762 } 2763 2764 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls); 2765 if (!tbls || !num_tbls) { 2766 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n", 2767 ulp_mapper_tmpl_name_str(parms->tmpl_type), 2768 parms->dev_id, tid); 2769 return -EINVAL; 2770 } 2771 2772 for (i = 0; i < num_tbls; i++) { 2773 tbl = &tbls[i]; 2774 2775 /* Handle the table level opcodes to determine if required. */ 2776 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl)) 2777 continue; 2778 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl, 2779 &num_cond_tbls, 2780 &cond_opc); 2781 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc, 2782 cond_tbls, num_cond_tbls, 2783 &cond_rc); 2784 if (rc) { 2785 BNXT_TF_DBG(ERR, "Failed to process cond opc list " 2786 "(%d)\n", rc); 2787 return rc; 2788 } 2789 /* Skip the table if False */ 2790 if (!cond_rc) 2791 continue; 2792 2793 /* process the fdb opcode for alloc push */ 2794 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_PUSH_REGFILE) { 2795 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl); 2796 if (rc) { 2797 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n"); 2798 return rc; 2799 } 2800 } 2801 2802 switch (tbl->resource_func) { 2803 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2804 rc = ulp_mapper_tcam_tbl_process(parms, tbl); 2805 break; 2806 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2807 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2808 rc = ulp_mapper_em_tbl_process(parms, tbl); 2809 break; 2810 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2811 rc = ulp_mapper_index_tbl_process(parms, tbl); 2812 break; 2813 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: 2814 rc = ulp_mapper_if_tbl_process(parms, tbl); 2815 break; 2816 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 2817 rc = ulp_mapper_gen_tbl_process(parms, tbl); 2818 break; 2819 case BNXT_ULP_RESOURCE_FUNC_INVALID: 2820 rc = 0; 2821 break; 2822 default: 2823 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n", 2824 tbl->resource_func); 2825 rc = -EINVAL; 2826 goto error; 2827 } 2828 2829 if (rc) { 2830 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 2831 tbl->resource_func); 2832 goto error; 2833 } 2834 2835 /* perform the post table process */ 2836 rc = ulp_mapper_conflict_resolution_process(parms, tbl, 2837 &cond_rc); 2838 if (rc || !cond_rc) { 2839 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n"); 2840 rc = -EINVAL; 2841 goto error; 2842 } 2843 } 2844 2845 return rc; 2846 error: 2847 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n", 2848 ulp_mapper_tmpl_name_str(parms->tmpl_type), 2849 parms->dev_id, tid); 2850 return rc; 2851 } 2852 2853 static int32_t 2854 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 2855 uint32_t fid, 2856 struct ulp_flow_db_res_params *res) 2857 { 2858 struct tf *tfp; 2859 int32_t rc = 0; 2860 2861 if (!res || !ulp) { 2862 BNXT_TF_DBG(ERR, "Unable to free resource\n "); 2863 return -EINVAL; 2864 } 2865 2866 tfp = bnxt_ulp_cntxt_tfp_get(ulp); 2867 if (!tfp) { 2868 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n"); 2869 return -EINVAL; 2870 } 2871 2872 switch (res->resource_func) { 2873 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 2874 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res); 2875 break; 2876 case BNXT_ULP_RESOURCE_FUNC_EXT_EM_TABLE: 2877 case BNXT_ULP_RESOURCE_FUNC_INT_EM_TABLE: 2878 rc = ulp_mapper_em_entry_free(ulp, tfp, res); 2879 break; 2880 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2881 rc = ulp_mapper_index_entry_free(ulp, tfp, res); 2882 break; 2883 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2884 rc = ulp_mapper_ident_free(ulp, tfp, res); 2885 break; 2886 case BNXT_ULP_RESOURCE_FUNC_HW_FID: 2887 rc = ulp_mapper_mark_free(ulp, res); 2888 break; 2889 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW: 2890 rc = ulp_mapper_parent_flow_free(ulp, fid, res); 2891 break; 2892 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW: 2893 rc = ulp_mapper_child_flow_free(ulp, fid, res); 2894 break; 2895 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 2896 rc = ulp_mapper_gen_tbl_res_free(ulp, res); 2897 break; 2898 default: 2899 break; 2900 } 2901 2902 return rc; 2903 } 2904 2905 int32_t 2906 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, 2907 enum bnxt_ulp_fdb_type flow_type, 2908 uint32_t fid) 2909 { 2910 struct ulp_flow_db_res_params res_parms = { 0 }; 2911 int32_t rc, trc; 2912 2913 if (!ulp_ctx) { 2914 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 2915 return -EINVAL; 2916 } 2917 2918 /* 2919 * Set the critical resource on the first resource del, then iterate 2920 * while status is good 2921 */ 2922 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; 2923 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms); 2924 2925 if (rc) { 2926 /* 2927 * This is unexpected on the first call to resource del. 2928 * It likely means that the flow did not exist in the flow db. 2929 */ 2930 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", 2931 flow_type, fid, rc); 2932 return rc; 2933 } 2934 2935 while (!rc) { 2936 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms); 2937 if (trc) 2938 /* 2939 * On fail, we still need to attempt to free the 2940 * remaining resources. Don't return 2941 */ 2942 BNXT_TF_DBG(ERR, 2943 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64 2944 "] failed rc=%d.\n", 2945 flow_type, fid, res_parms.resource_func, 2946 res_parms.resource_hndl, trc); 2947 2948 /* All subsequent call require the non-critical_resource */ 2949 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 2950 2951 rc = ulp_flow_db_resource_del(ulp_ctx, 2952 flow_type, 2953 fid, 2954 &res_parms); 2955 } 2956 2957 /* Free the Flow ID since we've removed all resources */ 2958 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid); 2959 2960 return rc; 2961 } 2962 2963 static void 2964 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, 2965 struct bnxt_ulp_mapper_data *mapper_data) 2966 { 2967 struct bnxt_ulp_mapper_glb_resource_entry *ent; 2968 struct ulp_flow_db_res_params res; 2969 uint32_t dir, idx; 2970 2971 /* Iterate the global resources and process each one */ 2972 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { 2973 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 2974 idx++) { 2975 ent = &mapper_data->glb_res_tbl[dir][idx]; 2976 if (ent->resource_func == 2977 BNXT_ULP_RESOURCE_FUNC_INVALID) 2978 continue; 2979 memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); 2980 res.resource_func = ent->resource_func; 2981 res.direction = dir; 2982 res.resource_type = ent->resource_type; 2983 /*convert it from BE to cpu */ 2984 res.resource_hndl = 2985 tfp_be_to_cpu_64(ent->resource_hndl); 2986 ulp_mapper_resource_free(ulp_ctx, 0, &res); 2987 } 2988 } 2989 } 2990 2991 int32_t 2992 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, 2993 enum bnxt_ulp_fdb_type flow_type, 2994 uint32_t fid) 2995 { 2996 int32_t rc; 2997 2998 if (!ulp_ctx) { 2999 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 3000 return -EINVAL; 3001 } 3002 3003 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid); 3004 return rc; 3005 } 3006 3007 /* Function to handle the default global templates that are allocated during 3008 * the startup and reused later. 3009 */ 3010 static int32_t 3011 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx) 3012 { 3013 uint32_t *glbl_tmpl_list; 3014 uint32_t num_glb_tmpls, idx, dev_id; 3015 struct bnxt_ulp_mapper_parms parms; 3016 struct bnxt_ulp_mapper_data *mapper_data; 3017 int32_t rc = 0; 3018 3019 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls); 3020 if (!glbl_tmpl_list || !num_glb_tmpls) 3021 return rc; /* No global templates to process */ 3022 3023 /* Get the device id from the ulp context */ 3024 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 3025 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 3026 return -EINVAL; 3027 } 3028 3029 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 3030 if (!mapper_data) { 3031 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 3032 return -EINVAL; 3033 } 3034 3035 /* Iterate the global resources and process each one */ 3036 for (idx = 0; idx < num_glb_tmpls; idx++) { 3037 /* Initialize the parms structure */ 3038 memset(&parms, 0, sizeof(parms)); 3039 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 3040 parms.ulp_ctx = ulp_ctx; 3041 parms.dev_id = dev_id; 3042 parms.mapper_data = mapper_data; 3043 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT; 3044 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; 3045 3046 /* Get the class table entry from dev id and class id */ 3047 parms.class_tid = glbl_tmpl_list[idx]; 3048 3049 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 3050 if (!parms.device_params) { 3051 BNXT_TF_DBG(ERR, "No device for device id %d\n", 3052 parms.dev_id); 3053 return -EINVAL; 3054 } 3055 3056 rc = ulp_mapper_tbls_process(&parms, parms.class_tid); 3057 if (rc) 3058 return rc; 3059 } 3060 return rc; 3061 } 3062 3063 /* Function to handle the mapping of the Flow to be compatible 3064 * with the underlying hardware. 3065 */ 3066 int32_t 3067 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 3068 struct bnxt_ulp_mapper_create_parms *cparms) 3069 { 3070 struct bnxt_ulp_mapper_parms parms; 3071 struct ulp_regfile regfile; 3072 int32_t rc = 0, trc; 3073 3074 if (!ulp_ctx || !cparms) 3075 return -EINVAL; 3076 3077 /* Initialize the parms structure */ 3078 memset(&parms, 0, sizeof(parms)); 3079 parms.act_prop = cparms->act_prop; 3080 parms.act_bitmap = cparms->act; 3081 parms.hdr_bitmap = cparms->hdr_bitmap; 3082 parms.regfile = ®file; 3083 parms.hdr_field = cparms->hdr_field; 3084 parms.comp_fld = cparms->comp_fld; 3085 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 3086 parms.ulp_ctx = ulp_ctx; 3087 parms.act_tid = cparms->act_tid; 3088 parms.class_tid = cparms->class_tid; 3089 parms.flow_type = cparms->flow_type; 3090 parms.parent_flow = cparms->parent_flow; 3091 parms.parent_fid = cparms->parent_fid; 3092 parms.fid = cparms->flow_id; 3093 parms.tun_idx = cparms->tun_idx; 3094 parms.app_priority = cparms->app_priority; 3095 3096 /* Get the device id from the ulp context */ 3097 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { 3098 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 3099 return -EINVAL; 3100 } 3101 3102 /* Get the device params, it will be used in later processing */ 3103 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 3104 if (!parms.device_params) { 3105 BNXT_TF_DBG(ERR, "No device parms for device id %d\n", 3106 parms.dev_id); 3107 return -EINVAL; 3108 } 3109 3110 /* 3111 * Get the mapper data for dynamic mapper data such as default 3112 * ids. 3113 */ 3114 parms.mapper_data = (struct bnxt_ulp_mapper_data *) 3115 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 3116 if (!parms.mapper_data) { 3117 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 3118 return -EINVAL; 3119 } 3120 3121 /* initialize the registry file for further processing */ 3122 if (!ulp_regfile_init(parms.regfile)) { 3123 BNXT_TF_DBG(ERR, "regfile initialization failed.\n"); 3124 return -EINVAL; 3125 } 3126 3127 /* Process the action template list from the selected action table*/ 3128 if (parms.act_tid) { 3129 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION; 3130 /* Process the action template tables */ 3131 rc = ulp_mapper_tbls_process(&parms, parms.act_tid); 3132 if (rc) 3133 goto flow_error; 3134 } 3135 3136 if (parms.class_tid) { 3137 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; 3138 3139 /* Process the class template tables.*/ 3140 rc = ulp_mapper_tbls_process(&parms, parms.class_tid); 3141 if (rc) 3142 goto flow_error; 3143 } 3144 3145 /* setup the parent-child details */ 3146 if (parms.parent_flow) { 3147 /* create a parent flow details */ 3148 rc = ulp_flow_db_parent_flow_create(&parms); 3149 if (rc) 3150 goto flow_error; 3151 } else if (parms.parent_fid) { 3152 /* create a child flow details */ 3153 rc = ulp_flow_db_child_flow_create(&parms); 3154 if (rc) 3155 goto flow_error; 3156 } 3157 3158 return rc; 3159 3160 flow_error: 3161 /* Free all resources that were allocated during flow creation */ 3162 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type, 3163 parms.fid); 3164 if (trc) 3165 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); 3166 3167 return rc; 3168 } 3169 3170 int32_t 3171 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) 3172 { 3173 struct bnxt_ulp_mapper_data *data; 3174 struct tf *tfp; 3175 int32_t rc; 3176 3177 if (!ulp_ctx) 3178 return -EINVAL; 3179 3180 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 3181 if (!tfp) 3182 return -EINVAL; 3183 3184 data = rte_zmalloc("ulp_mapper_data", 3185 sizeof(struct bnxt_ulp_mapper_data), 0); 3186 if (!data) { 3187 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n"); 3188 return -ENOMEM; 3189 } 3190 3191 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) { 3192 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n"); 3193 /* Don't call deinit since the prof_func wasn't allocated. */ 3194 rte_free(data); 3195 return -ENOMEM; 3196 } 3197 3198 /* Allocate the global resource ids */ 3199 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); 3200 if (rc) { 3201 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n"); 3202 goto error; 3203 } 3204 3205 /* Allocate the generic table list */ 3206 rc = ulp_mapper_generic_tbl_list_init(data); 3207 if (rc) { 3208 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n"); 3209 goto error; 3210 } 3211 3212 /* Allocate global template table entries */ 3213 rc = ulp_mapper_glb_template_table_init(ulp_ctx); 3214 if (rc) { 3215 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n"); 3216 goto error; 3217 } 3218 3219 return 0; 3220 error: 3221 /* Ignore the return code in favor of returning the original error. */ 3222 ulp_mapper_deinit(ulp_ctx); 3223 return rc; 3224 } 3225 3226 void 3227 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) 3228 { 3229 struct bnxt_ulp_mapper_data *data; 3230 struct tf *tfp; 3231 3232 if (!ulp_ctx) { 3233 BNXT_TF_DBG(ERR, 3234 "Failed to acquire ulp context, so data may " 3235 "not be released.\n"); 3236 return; 3237 } 3238 3239 data = (struct bnxt_ulp_mapper_data *) 3240 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 3241 if (!data) { 3242 /* Go ahead and return since there is no allocated data. */ 3243 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n"); 3244 return; 3245 } 3246 3247 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 3248 if (!tfp) { 3249 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); 3250 /* Free the mapper data regardless of errors. */ 3251 goto free_mapper_data; 3252 } 3253 3254 /* Free the global resource info table entries */ 3255 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); 3256 3257 free_mapper_data: 3258 /* Free the generic table */ 3259 (void)ulp_mapper_generic_tbl_list_deinit(data); 3260 3261 rte_free(data); 3262 /* Reset the data pointer within the ulp_ctx. */ 3263 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); 3264 } 3265