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 #include "ulp_port_db.h" 22 #include "ulp_ha_mgr.h" 23 #include "bnxt_tf_pmd_shim.h" 24 25 static uint8_t mapper_fld_zeros[16] = { 0 }; 26 27 static uint8_t mapper_fld_ones[16] = { 28 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 29 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 30 }; 31 32 static uint8_t mapper_fld_one[16] = { 33 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 34 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 35 }; 36 37 static const char * 38 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type) 39 { 40 switch (tmpl_type) { 41 case BNXT_ULP_TEMPLATE_TYPE_CLASS: 42 return "class"; 43 case BNXT_ULP_TEMPLATE_TYPE_ACTION: 44 return "action"; 45 default: 46 return "invalid template type"; 47 } 48 } 49 50 static struct bnxt_ulp_glb_resource_info * 51 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries) 52 { 53 if (!num_entries) 54 return NULL; 55 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 56 return ulp_glb_resource_tbl; 57 } 58 59 /* 60 * Read the global resource from the mapper global resource list 61 * 62 * The regval is always returned in big-endian. 63 * 64 * returns 0 on success 65 */ 66 static int32_t 67 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data, 68 enum tf_dir dir, 69 uint16_t idx, 70 uint64_t *regval, 71 bool *shared) 72 { 73 if (!mapper_data || !regval || !shared || 74 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST) 75 return -EINVAL; 76 77 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl; 78 *shared = mapper_data->glb_res_tbl[dir][idx].shared; 79 return 0; 80 } 81 82 /* 83 * Write a global resource to the mapper global resource list 84 * 85 * The regval value must be in big-endian. 86 * 87 * return 0 on success. 88 */ 89 static int32_t 90 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, 91 struct bnxt_ulp_glb_resource_info *res, 92 uint64_t regval, bool shared) 93 { 94 struct bnxt_ulp_mapper_glb_resource_entry *ent; 95 96 /* validate the arguments */ 97 if (!data || res->direction >= TF_DIR_MAX || 98 res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST) 99 return -EINVAL; 100 101 /* write to the mapper data */ 102 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index]; 103 ent->resource_func = res->resource_func; 104 ent->resource_type = res->resource_type; 105 ent->resource_hndl = regval; 106 ent->shared = shared; 107 return 0; 108 } 109 110 /* 111 * Internal function to allocate identity resource and store it in mapper data. 112 * 113 * returns 0 on success 114 */ 115 static int32_t 116 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx, 117 struct bnxt_ulp_mapper_data *mapper_data, 118 struct bnxt_ulp_glb_resource_info *glb_res) 119 { 120 struct tf_alloc_identifier_parms iparms = { 0 }; 121 struct tf_free_identifier_parms fparms; 122 uint64_t regval; 123 struct tf *tfp; 124 int32_t rc = 0; 125 126 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 127 if (!tfp) 128 return -EINVAL; 129 130 iparms.ident_type = glb_res->resource_type; 131 iparms.dir = glb_res->direction; 132 133 /* Allocate the Identifier using tf api */ 134 rc = tf_alloc_identifier(tfp, &iparms); 135 if (rc) { 136 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", 137 tf_dir_2_str(iparms.dir), 138 iparms.ident_type); 139 return rc; 140 } 141 142 /* entries are stored as big-endian format */ 143 regval = tfp_cpu_to_be_64((uint64_t)iparms.id); 144 /* 145 * write to the mapper global resource 146 * Shared resources are never allocated through this method, so the 147 * shared flag is always false. 148 */ 149 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false); 150 if (rc) { 151 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 152 /* Free the identifier when update failed */ 153 fparms.dir = iparms.dir; 154 fparms.ident_type = iparms.ident_type; 155 fparms.id = iparms.id; 156 tf_free_identifier(tfp, &fparms); 157 return rc; 158 } 159 return rc; 160 } 161 162 /* 163 * Internal function to allocate index tbl resource and store it in mapper data. 164 * 165 * returns 0 on success 166 */ 167 static int32_t 168 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx, 169 struct bnxt_ulp_mapper_data *mapper_data, 170 struct bnxt_ulp_glb_resource_info *glb_res) 171 { 172 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 173 struct tf_free_tbl_entry_parms free_parms = { 0 }; 174 uint64_t regval; 175 struct tf *tfp; 176 uint32_t tbl_scope_id; 177 int32_t rc = 0; 178 179 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 180 if (!tfp) 181 return -EINVAL; 182 183 /* Get the scope id */ 184 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id); 185 if (rc) { 186 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 187 return rc; 188 } 189 190 aparms.type = glb_res->resource_type; 191 aparms.dir = glb_res->direction; 192 aparms.search_enable = 0; 193 aparms.tbl_scope_id = tbl_scope_id; 194 195 /* Allocate the index tbl using tf api */ 196 rc = tf_alloc_tbl_entry(tfp, &aparms); 197 if (rc) { 198 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n", 199 tf_dir_2_str(aparms.dir), aparms.type); 200 return rc; 201 } 202 203 /* entries are stored as big-endian format */ 204 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx); 205 /* 206 * write to the mapper global resource 207 * Shared resources are never allocated through this method, so the 208 * shared flag is always false. 209 */ 210 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false); 211 if (rc) { 212 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n"); 213 /* Free the identifier when update failed */ 214 free_parms.dir = aparms.dir; 215 free_parms.type = aparms.type; 216 free_parms.idx = aparms.idx; 217 tf_free_tbl_entry(tfp, &free_parms); 218 return rc; 219 } 220 return rc; 221 } 222 223 static int32_t 224 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms, 225 uint32_t operand, 226 uint8_t *val) 227 { 228 uint32_t t_idx; 229 230 t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT + 231 BNXT_ULP_HDR_SIG_ID_SHIFT + 232 BNXT_ULP_GLB_FIELD_TBL_SHIFT); 233 t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT + 234 BNXT_ULP_GLB_FIELD_TBL_SHIFT); 235 t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) << 236 BNXT_ULP_GLB_FIELD_TBL_SHIFT; 237 t_idx += operand; 238 239 if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) { 240 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n", 241 parms->class_tid, t_idx, operand); 242 *val = 0; 243 return -EINVAL; /* error */ 244 } 245 *val = ulp_glb_field_tbl[t_idx]; 246 return 0; 247 } 248 249 /* 250 * Get the size of the action property for a given index. 251 * 252 * idx [in] The index for the action property 253 * 254 * returns the size of the action property. 255 */ 256 static uint32_t 257 ulp_mapper_act_prop_size_get(uint32_t idx) 258 { 259 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) 260 return 0; 261 return ulp_act_prop_map_table[idx]; 262 } 263 264 static struct bnxt_ulp_mapper_cond_info * 265 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms, 266 uint32_t tid, 267 uint32_t *num_tbls, 268 enum bnxt_ulp_cond_list_opc *opc) 269 { 270 uint32_t idx; 271 const struct bnxt_ulp_template_device_tbls *dev_tbls; 272 273 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 274 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums; 275 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode; 276 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx; 277 278 return &dev_tbls->cond_list[idx]; 279 } 280 281 static struct bnxt_ulp_mapper_cond_info * 282 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms, 283 struct bnxt_ulp_mapper_tbl_info *tbl, 284 uint32_t *num_tbls, 285 enum bnxt_ulp_cond_list_opc *opc) 286 { 287 uint32_t idx; 288 const struct bnxt_ulp_template_device_tbls *dev_tbls; 289 290 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 291 *num_tbls = tbl->execute_info.cond_nums; 292 *opc = tbl->execute_info.cond_list_opcode; 293 idx = tbl->execute_info.cond_start_idx; 294 295 return &dev_tbls->cond_list[idx]; 296 } 297 298 /* 299 * Get a list of classifier tables that implement the flow 300 * Gets a device dependent list of tables that implement the class template id 301 * 302 * mparms [in] The mappers parms with data related to the flow. 303 * 304 * tid [in] The template id that matches the flow 305 * 306 * num_tbls [out] The number of classifier tables in the returned array 307 * 308 * returns An array of classifier tables to implement the flow, or NULL on 309 * error 310 */ 311 static struct bnxt_ulp_mapper_tbl_info * 312 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms, 313 uint32_t tid, 314 uint32_t *num_tbls) 315 { 316 uint32_t idx; 317 const struct bnxt_ulp_template_device_tbls *dev_tbls; 318 319 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 320 321 idx = dev_tbls->tmpl_list[tid].start_tbl_idx; 322 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls; 323 324 return &dev_tbls->tbl_list[idx]; 325 } 326 327 /* 328 * Get the list of key fields that implement the flow. 329 * 330 * mparms [in] The mapper parms with information about the flow 331 * 332 * tbl [in] A single table instance to get the key fields from 333 * 334 * num_flds [out] The number of key fields in the returned array 335 * 336 * Returns array of Key fields, or NULL on error. 337 */ 338 static struct bnxt_ulp_mapper_key_info * 339 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms, 340 struct bnxt_ulp_mapper_tbl_info *tbl, 341 uint32_t *num_flds) 342 { 343 uint32_t idx; 344 const struct bnxt_ulp_template_device_tbls *dev_tbls; 345 346 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 347 if (!dev_tbls->key_info_list) { 348 *num_flds = 0; 349 return NULL; 350 } 351 352 idx = tbl->key_start_idx; 353 *num_flds = tbl->key_num_fields; 354 355 return &dev_tbls->key_info_list[idx]; 356 } 357 358 /* 359 * Get the list of data fields that implement the flow. 360 * 361 * mparms [in] The mapper parms with information about the flow 362 * 363 * tbl [in] A single table instance to get the data fields from 364 * 365 * num_flds [out] The number of data fields in the returned array. 366 * 367 * num_encap_flds [out] The number of encap fields in the returned array. 368 * 369 * Returns array of data fields, or NULL on error. 370 */ 371 static struct bnxt_ulp_mapper_field_info * 372 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms, 373 struct bnxt_ulp_mapper_tbl_info *tbl, 374 uint32_t *num_flds, 375 uint32_t *num_encap_flds) 376 { 377 uint32_t idx; 378 const struct bnxt_ulp_template_device_tbls *dev_tbls; 379 380 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 381 if (!dev_tbls->result_field_list) { 382 *num_flds = 0; 383 *num_encap_flds = 0; 384 return NULL; 385 } 386 387 idx = tbl->result_start_idx; 388 *num_flds = tbl->result_num_fields; 389 *num_encap_flds = tbl->encap_num_fields; 390 391 return &dev_tbls->result_field_list[idx]; 392 } 393 394 /* 395 * Get the list of ident fields that implement the flow 396 * 397 * tbl [in] A single table instance to get the ident fields from 398 * 399 * num_flds [out] The number of ident fields in the returned array 400 * 401 * returns array of ident fields, or NULL on error 402 */ 403 static struct bnxt_ulp_mapper_ident_info * 404 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms, 405 struct bnxt_ulp_mapper_tbl_info *tbl, 406 uint32_t *num_flds) 407 { 408 uint32_t idx; 409 const struct bnxt_ulp_template_device_tbls *dev_tbls; 410 411 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 412 if (!dev_tbls->ident_list) { 413 *num_flds = 0; 414 return NULL; 415 } 416 417 idx = tbl->ident_start_idx; 418 *num_flds = tbl->ident_nums; 419 420 return &dev_tbls->ident_list[idx]; 421 } 422 423 static inline int32_t 424 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp, 425 struct tf *tfp, 426 struct ulp_flow_db_res_params *res) 427 { 428 struct tf_free_tcam_entry_parms fparms = { 429 .dir = res->direction, 430 .tcam_tbl_type = res->resource_type, 431 .idx = (uint16_t)res->resource_hndl 432 }; 433 434 /* If HA is enabled, we may have to remap the TF Type */ 435 if (bnxt_ulp_cntxt_ha_enabled(ulp)) { 436 enum ulp_ha_mgr_region region; 437 int32_t rc; 438 439 switch (res->resource_type) { 440 case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH: 441 case TF_TCAM_TBL_TYPE_WC_TCAM_LOW: 442 rc = ulp_ha_mgr_region_get(ulp, ®ion); 443 if (rc) 444 /* Log this, but assume region is correct */ 445 BNXT_TF_DBG(ERR, 446 "Unable to get HA region (%d)\n", 447 rc); 448 else 449 fparms.tcam_tbl_type = 450 (region == ULP_HA_REGION_LOW) ? 451 TF_TCAM_TBL_TYPE_WC_TCAM_LOW : 452 TF_TCAM_TBL_TYPE_WC_TCAM_HIGH; 453 break; 454 default: 455 break; 456 } 457 } 458 return tf_free_tcam_entry(tfp, &fparms); 459 } 460 461 static inline int32_t 462 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp, 463 struct tf *tfp, 464 struct ulp_flow_db_res_params *res) 465 { 466 struct tf_free_tbl_entry_parms fparms = { 467 .dir = res->direction, 468 .type = res->resource_type, 469 .idx = (uint32_t)res->resource_hndl 470 }; 471 472 /* 473 * Just get the table scope, it will be ignored if not necessary 474 * by the tf_free_tbl_entry 475 */ 476 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 477 478 return tf_free_tbl_entry(tfp, &fparms); 479 } 480 481 static inline int32_t 482 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp, 483 struct tf *tfp, 484 struct ulp_flow_db_res_params *res) 485 { 486 struct tf_delete_em_entry_parms fparms = { 0 }; 487 int32_t rc; 488 489 fparms.dir = res->direction; 490 fparms.flow_handle = res->resource_hndl; 491 492 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id); 493 if (rc) { 494 BNXT_TF_DBG(ERR, "Failed to get table scope\n"); 495 return -EINVAL; 496 } 497 498 return tf_delete_em_entry(tfp, &fparms); 499 } 500 501 static inline int32_t 502 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused, 503 struct tf *tfp, 504 struct ulp_flow_db_res_params *res) 505 { 506 struct tf_free_identifier_parms fparms = { 507 .dir = res->direction, 508 .ident_type = res->resource_type, 509 .id = (uint16_t)res->resource_hndl 510 }; 511 512 return tf_free_identifier(tfp, &fparms); 513 } 514 515 static inline int32_t 516 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, 517 struct ulp_flow_db_res_params *res) 518 { 519 return ulp_mark_db_mark_del(ulp, 520 res->resource_type, 521 res->resource_hndl); 522 } 523 524 static inline int32_t 525 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp, 526 uint32_t parent_fid, 527 struct ulp_flow_db_res_params *res) 528 { 529 uint32_t idx, child_fid = 0, parent_idx; 530 struct bnxt_ulp_flow_db *flow_db; 531 532 parent_idx = (uint32_t)res->resource_hndl; 533 534 /* check the validity of the parent fid */ 535 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) || 536 idx != parent_idx) { 537 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid); 538 return -EINVAL; 539 } 540 541 /* Clear all the child flows parent index */ 542 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp); 543 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx, 544 &child_fid)) { 545 /* update the child flows resource handle */ 546 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR, 547 child_fid)) { 548 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n", 549 child_fid); 550 return -EINVAL; 551 } 552 } 553 554 /* free the parent entry in the parent table flow */ 555 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) { 556 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid); 557 return -EINVAL; 558 } 559 return 0; 560 } 561 562 static inline int32_t 563 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp, 564 uint32_t child_fid, 565 struct ulp_flow_db_res_params *res) 566 { 567 uint32_t parent_fid; 568 569 parent_fid = (uint32_t)res->resource_hndl; 570 if (!parent_fid) 571 return 0; /* Already freed - orphan child*/ 572 573 /* reset the child flow bitset*/ 574 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) { 575 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n", 576 parent_fid, child_fid); 577 return -EINVAL; 578 } 579 return 0; 580 } 581 582 /* 583 * Process the flow database opcode alloc action. 584 * returns 0 on success 585 */ 586 static int32_t 587 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms, 588 struct bnxt_ulp_mapper_tbl_info *tbl) 589 { 590 uint32_t rid = 0; 591 uint64_t val64; 592 int32_t rc = 0; 593 594 /* allocate a new fid */ 595 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx, 596 BNXT_ULP_FDB_TYPE_RID, 597 0, &rid); 598 if (rc) { 599 BNXT_TF_DBG(ERR, 600 "Unable to allocate flow table entry\n"); 601 return -EINVAL; 602 } 603 /* Store the allocated fid in regfile*/ 604 val64 = rid; 605 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand, 606 tfp_cpu_to_be_64(val64)); 607 if (rc) { 608 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 609 tbl->fdb_operand); 610 ulp_flow_db_fid_free(parms->ulp_ctx, 611 BNXT_ULP_FDB_TYPE_RID, rid); 612 return -EINVAL; 613 } 614 return 0; 615 } 616 617 /* 618 * Process the flow database opcode action. 619 * returns 0 on success. 620 */ 621 static int32_t 622 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms, 623 struct bnxt_ulp_mapper_tbl_info *tbl, 624 struct ulp_flow_db_res_params *fid_parms) 625 { 626 uint32_t push_fid; 627 uint64_t val64; 628 enum bnxt_ulp_fdb_type flow_type; 629 int32_t rc = 0; 630 631 switch (tbl->fdb_opcode) { 632 case BNXT_ULP_FDB_OPC_PUSH_FID: 633 push_fid = parms->fid; 634 flow_type = parms->flow_type; 635 break; 636 case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE: 637 /* get the fid from the regfile */ 638 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand, 639 &val64); 640 if (!rc) { 641 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 642 tbl->fdb_operand); 643 return -EINVAL; 644 } 645 /* Use the extracted fid to update the flow resource */ 646 push_fid = (uint32_t)tfp_be_to_cpu_64(val64); 647 flow_type = BNXT_ULP_FDB_TYPE_RID; 648 break; 649 default: 650 return rc; /* Nothing to be done */ 651 } 652 653 /* Add the resource to the flow database */ 654 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type, 655 push_fid, fid_parms); 656 if (rc) 657 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n", 658 push_fid, rc); 659 return rc; 660 } 661 662 /* 663 * Process the flow database opcode action. 664 * returns 0 on success. 665 */ 666 static int32_t 667 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms, 668 struct bnxt_ulp_mapper_tbl_info *tbl, 669 uint32_t *priority) 670 { 671 int32_t rc = 0; 672 673 switch (tbl->pri_opcode) { 674 case BNXT_ULP_PRI_OPC_NOT_USED: 675 *priority = 0; 676 break; 677 case BNXT_ULP_PRI_OPC_CONST: 678 *priority = tbl->pri_operand; 679 break; 680 case BNXT_ULP_PRI_OPC_APP_PRI: 681 *priority = parms->app_priority; 682 break; 683 default: 684 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n", 685 tbl->pri_opcode); 686 rc = -EINVAL; 687 break; 688 } 689 return rc; 690 } 691 692 /* 693 * Process the identifier list in the given table. 694 * Extract the ident from the table entry and 695 * write it to the reg file. 696 * returns 0 on success. 697 */ 698 static int32_t 699 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms, 700 struct bnxt_ulp_mapper_tbl_info *tbl, 701 uint8_t *byte_data, 702 uint32_t byte_data_size, 703 enum bnxt_ulp_byte_order byte_order) 704 { 705 struct bnxt_ulp_mapper_ident_info *idents; 706 uint32_t i, num_idents = 0; 707 uint64_t val64; 708 709 /* validate the null arguments */ 710 if (!byte_data) { 711 BNXT_TF_DBG(ERR, "invalid argument\n"); 712 return -EINVAL; 713 } 714 715 /* Get the ident list and process each one */ 716 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 717 718 for (i = 0; i < num_idents; i++) { 719 /* check the size of the buffer for validation */ 720 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) > 721 ULP_BYTE_2_BITS(byte_data_size) || 722 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) { 723 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n", 724 idents[i].ident_bit_pos, 725 idents[i].ident_bit_size, 726 byte_data_size); 727 return -EINVAL; 728 } 729 val64 = 0; 730 if (byte_order == BNXT_ULP_BYTE_ORDER_LE) 731 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64, 732 sizeof(val64), 733 idents[i].ident_bit_pos, 734 idents[i].ident_bit_size); 735 else 736 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64, 737 idents[i].ident_bit_pos, 738 idents[i].ident_bit_size); 739 740 /* Write it to the regfile, val64 is already in big-endian*/ 741 if (ulp_regfile_write(parms->regfile, 742 idents[i].regfile_idx, val64)) { 743 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", 744 idents[i].regfile_idx); 745 return -EINVAL; 746 } 747 } 748 return 0; 749 } 750 751 /* 752 * Process the identifier instruction and either store it in the flow database 753 * or return it in the val (if not NULL) on success. If val is NULL, the 754 * identifier is to be stored in the flow database. 755 */ 756 static int32_t 757 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, 758 struct bnxt_ulp_mapper_tbl_info *tbl, 759 struct bnxt_ulp_mapper_ident_info *ident, 760 uint16_t *val) 761 { 762 struct ulp_flow_db_res_params fid_parms; 763 uint64_t id = 0; 764 int32_t idx; 765 struct tf_alloc_identifier_parms iparms = { 0 }; 766 struct tf_free_identifier_parms free_parms = { 0 }; 767 struct tf *tfp; 768 int rc; 769 770 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 771 if (!tfp) { 772 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 773 return -EINVAL; 774 } 775 776 idx = ident->regfile_idx; 777 778 iparms.ident_type = ident->ident_type; 779 iparms.dir = tbl->direction; 780 781 rc = tf_alloc_identifier(tfp, &iparms); 782 if (rc) { 783 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n", 784 tf_dir_2_str(iparms.dir), 785 tf_ident_2_str(iparms.ident_type)); 786 return rc; 787 } 788 789 id = (uint64_t)tfp_cpu_to_be_64(iparms.id); 790 if (ulp_regfile_write(parms->regfile, idx, id)) { 791 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 792 rc = -EINVAL; 793 /* Need to free the identifier, so goto error */ 794 goto error; 795 } 796 797 /* Link the resource to the flow in the flow db */ 798 if (!val) { 799 memset(&fid_parms, 0, sizeof(fid_parms)); 800 fid_parms.direction = tbl->direction; 801 fid_parms.resource_func = ident->resource_func; 802 fid_parms.resource_type = ident->ident_type; 803 fid_parms.resource_hndl = iparms.id; 804 fid_parms.critical_resource = tbl->critical_resource; 805 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 806 807 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 808 if (rc) { 809 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 810 rc); 811 /* Need to free the identifier, so goto error */ 812 goto error; 813 } 814 } else { 815 *val = iparms.id; 816 } 817 return 0; 818 819 error: 820 /* Need to free the identifier */ 821 free_parms.dir = tbl->direction; 822 free_parms.ident_type = ident->ident_type; 823 free_parms.id = iparms.id; 824 825 (void)tf_free_identifier(tfp, &free_parms); 826 827 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n", 828 ident->description, 829 tf_dir_2_str(tbl->direction)); 830 return rc; 831 } 832 833 /* 834 * Process the identifier instruction and extract it from result blob. 835 * Increment the identifier reference count and store it in the flow database. 836 */ 837 static int32_t 838 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms, 839 struct bnxt_ulp_mapper_tbl_info *tbl, 840 struct bnxt_ulp_mapper_ident_info *ident, 841 struct ulp_blob *res_blob) 842 { 843 struct ulp_flow_db_res_params fid_parms; 844 uint64_t id = 0; 845 uint32_t idx = 0; 846 struct tf_search_identifier_parms sparms = { 0 }; 847 struct tf_free_identifier_parms free_parms = { 0 }; 848 struct tf *tfp; 849 int rc; 850 851 /* Get the tfp from ulp context */ 852 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 853 if (!tfp) { 854 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n"); 855 return -EINVAL; 856 } 857 858 /* Extract the index from the result blob */ 859 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx), 860 ident->ident_bit_pos, ident->ident_bit_size); 861 if (rc) { 862 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n"); 863 return -EIO; 864 } 865 866 /* populate the search params and search identifier shadow table */ 867 sparms.ident_type = ident->ident_type; 868 sparms.dir = tbl->direction; 869 /* convert the idx into cpu format */ 870 sparms.search_id = tfp_be_to_cpu_32(idx); 871 872 /* Search identifier also increase the reference count */ 873 rc = tf_search_identifier(tfp, &sparms); 874 if (rc) { 875 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n", 876 tf_dir_2_str(sparms.dir), 877 tf_ident_2_str(sparms.ident_type), 878 sparms.search_id); 879 return rc; 880 } 881 882 /* Write it to the regfile */ 883 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id); 884 if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) { 885 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx); 886 rc = -EINVAL; 887 /* Need to free the identifier, so goto error */ 888 goto error; 889 } 890 891 /* Link the resource to the flow in the flow db */ 892 memset(&fid_parms, 0, sizeof(fid_parms)); 893 fid_parms.direction = tbl->direction; 894 fid_parms.resource_func = ident->resource_func; 895 fid_parms.resource_type = ident->ident_type; 896 fid_parms.resource_hndl = sparms.search_id; 897 fid_parms.critical_resource = tbl->critical_resource; 898 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 899 900 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 901 if (rc) { 902 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n", 903 rc); 904 /* Need to free the identifier, so goto error */ 905 goto error; 906 } 907 908 return 0; 909 910 error: 911 /* Need to free the identifier */ 912 free_parms.dir = tbl->direction; 913 free_parms.ident_type = ident->ident_type; 914 free_parms.id = sparms.search_id; 915 (void)tf_free_identifier(tfp, &free_parms); 916 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n", 917 ident->description, 918 tf_dir_2_str(tbl->direction), sparms.search_id); 919 return rc; 920 } 921 922 static int32_t 923 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms, 924 uint32_t port_id, 925 uint16_t val16, 926 uint8_t **val) 927 { 928 enum bnxt_ulp_port_table port_data = val16; 929 930 switch (port_data) { 931 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC: 932 if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id, 933 val)) { 934 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); 935 return -EINVAL; 936 } 937 break; 938 case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC: 939 if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id, 940 val)) { 941 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); 942 return -EINVAL; 943 } 944 break; 945 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC: 946 if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id, 947 val)) { 948 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id); 949 return -EINVAL; 950 } 951 break; 952 default: 953 BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data); 954 return -EINVAL; 955 } 956 return 0; 957 } 958 959 static int32_t 960 ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms, 961 enum bnxt_ulp_field_src field_src, 962 uint8_t *field_opr, 963 enum tf_dir dir, 964 uint8_t is_key, 965 uint32_t bitlen, 966 uint8_t **val, 967 uint32_t *val_len, 968 uint64_t *value) 969 { 970 struct bnxt_ulp_mapper_data *m; 971 uint8_t bit; 972 uint32_t port_id, val_size, field_size; 973 uint16_t idx, size_idx, offset; 974 uint32_t bytelen = ULP_BITS_2_BYTE(bitlen); 975 uint8_t *buffer; 976 uint64_t lregval; 977 bool shared; 978 979 *val_len = bitlen; 980 *value = 0; 981 /* Perform the action */ 982 switch (field_src) { 983 case BNXT_ULP_FIELD_SRC_ZERO: 984 *val = mapper_fld_zeros; 985 break; 986 case BNXT_ULP_FIELD_SRC_CONST: 987 *val = field_opr; 988 break; 989 case BNXT_ULP_FIELD_SRC_ONES: 990 *val = mapper_fld_ones; 991 *value = 1; 992 break; 993 case BNXT_ULP_FIELD_SRC_CF: 994 if (!ulp_operand_read(field_opr, 995 (uint8_t *)&idx, sizeof(uint16_t))) { 996 BNXT_TF_DBG(ERR, "CF operand read failed\n"); 997 return -EINVAL; 998 } 999 idx = tfp_be_to_cpu_16(idx); 1000 if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) { 1001 BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx, 1002 bytelen); 1003 return -EINVAL; 1004 } 1005 buffer = (uint8_t *)&parms->comp_fld[idx]; 1006 *val = &buffer[sizeof(uint64_t) - bytelen]; 1007 *value = ULP_COMP_FLD_IDX_RD(parms, idx); 1008 break; 1009 case BNXT_ULP_FIELD_SRC_RF: 1010 if (!ulp_operand_read(field_opr, 1011 (uint8_t *)&idx, sizeof(uint16_t))) { 1012 BNXT_TF_DBG(ERR, "RF operand read failed\n"); 1013 return -EINVAL; 1014 } 1015 1016 idx = tfp_be_to_cpu_16(idx); 1017 /* Uninitialized regfile entries return 0 */ 1018 if (!ulp_regfile_read(parms->regfile, idx, &lregval) || 1019 sizeof(uint64_t) < bytelen) { 1020 BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx, 1021 bytelen); 1022 return -EINVAL; 1023 } 1024 buffer = (uint8_t *)&parms->regfile->entry[idx].data; 1025 *val = &buffer[sizeof(uint64_t) - bytelen]; 1026 *value = tfp_be_to_cpu_64(lregval); 1027 break; 1028 case BNXT_ULP_FIELD_SRC_ACT_PROP: 1029 if (!ulp_operand_read(field_opr, 1030 (uint8_t *)&idx, sizeof(uint16_t))) { 1031 BNXT_TF_DBG(ERR, "Action operand read failed\n"); 1032 return -EINVAL; 1033 } 1034 idx = tfp_be_to_cpu_16(idx); 1035 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1036 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx); 1037 return -EINVAL; 1038 } 1039 buffer = &parms->act_prop->act_details[idx]; 1040 field_size = ulp_mapper_act_prop_size_get(idx); 1041 if (bytelen > field_size) { 1042 BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n", 1043 idx, field_size); 1044 return -EINVAL; 1045 } 1046 *val = &buffer[field_size - bytelen]; 1047 break; 1048 case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ: 1049 if (!ulp_operand_read(field_opr, 1050 (uint8_t *)&idx, sizeof(uint16_t))) { 1051 BNXT_TF_DBG(ERR, "Action sz operand read failed\n"); 1052 return -EINVAL; 1053 } 1054 idx = tfp_be_to_cpu_16(idx); 1055 1056 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1057 BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx); 1058 return -EINVAL; 1059 } 1060 *val = &parms->act_prop->act_details[idx]; 1061 1062 /* get the size index next */ 1063 if (!ulp_operand_read(&field_opr[sizeof(uint16_t)], 1064 (uint8_t *)&size_idx, sizeof(uint16_t))) { 1065 BNXT_TF_DBG(ERR, "Action sz operand read failed\n"); 1066 return -EINVAL; 1067 } 1068 size_idx = tfp_be_to_cpu_16(size_idx); 1069 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) { 1070 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx); 1071 return -EINVAL; 1072 } 1073 memcpy(&val_size, &parms->act_prop->act_details[size_idx], 1074 sizeof(uint32_t)); 1075 val_size = tfp_be_to_cpu_32(val_size); 1076 *val_len = ULP_BYTE_2_BITS(val_size); 1077 break; 1078 case BNXT_ULP_FIELD_SRC_GLB_RF: 1079 if (!ulp_operand_read(field_opr, 1080 (uint8_t *)&idx, sizeof(uint16_t))) { 1081 BNXT_TF_DBG(ERR, "Global regfile read failed\n"); 1082 return -EINVAL; 1083 } 1084 idx = tfp_be_to_cpu_16(idx); 1085 if (ulp_mapper_glb_resource_read(parms->mapper_data, 1086 dir, idx, &lregval, &shared) || 1087 sizeof(uint64_t) < bytelen) { 1088 BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n", 1089 idx, bytelen); 1090 return -EINVAL; 1091 } 1092 m = parms->mapper_data; 1093 buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl; 1094 *val = &buffer[sizeof(uint64_t) - bytelen]; 1095 *value = tfp_be_to_cpu_64(lregval); 1096 break; 1097 case BNXT_ULP_FIELD_SRC_HF: 1098 case BNXT_ULP_FIELD_SRC_SUB_HF: 1099 if (!ulp_operand_read(field_opr, 1100 (uint8_t *)&idx, sizeof(uint16_t))) { 1101 BNXT_TF_DBG(ERR, "Header field read failed\n"); 1102 return -EINVAL; 1103 } 1104 idx = tfp_be_to_cpu_16(idx); 1105 /* get the index from the global field list */ 1106 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) { 1107 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 1108 idx); 1109 return -EINVAL; 1110 } 1111 if (is_key) 1112 buffer = parms->hdr_field[bit].spec; 1113 else 1114 buffer = parms->hdr_field[bit].mask; 1115 1116 field_size = parms->hdr_field[bit].size; 1117 if (bytelen > field_size) { 1118 BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n", 1119 bit, field_size); 1120 return -EINVAL; 1121 } 1122 if (field_src == BNXT_ULP_FIELD_SRC_HF) { 1123 *val = &buffer[field_size - bytelen]; 1124 } else { 1125 /* get the offset next */ 1126 if (!ulp_operand_read(&field_opr[sizeof(uint16_t)], 1127 (uint8_t *)&offset, 1128 sizeof(uint16_t))) { 1129 BNXT_TF_DBG(ERR, "Hdr fld size read failed\n"); 1130 return -EINVAL; 1131 } 1132 offset = tfp_be_to_cpu_16(offset); 1133 offset = ULP_BITS_2_BYTE_NR(offset); 1134 if ((offset + bytelen) > field_size) { 1135 BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit); 1136 return -EINVAL; 1137 } 1138 *val = &buffer[offset]; 1139 } 1140 break; 1141 case BNXT_ULP_FIELD_SRC_HDR_BIT: 1142 if (!ulp_operand_read(field_opr, 1143 (uint8_t *)&lregval, sizeof(uint64_t))) { 1144 BNXT_TF_DBG(ERR, "Header bit read failed\n"); 1145 return -EINVAL; 1146 } 1147 lregval = tfp_be_to_cpu_64(lregval); 1148 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) { 1149 *val = mapper_fld_one; 1150 *value = 1; 1151 } else { 1152 *val = mapper_fld_zeros; 1153 } 1154 break; 1155 case BNXT_ULP_FIELD_SRC_ACT_BIT: 1156 if (!ulp_operand_read(field_opr, 1157 (uint8_t *)&lregval, sizeof(uint64_t))) { 1158 BNXT_TF_DBG(ERR, "Action bit read failed\n"); 1159 return -EINVAL; 1160 } 1161 lregval = tfp_be_to_cpu_64(lregval); 1162 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) { 1163 *val = mapper_fld_one; 1164 *value = 1; 1165 } else { 1166 *val = mapper_fld_zeros; 1167 } 1168 break; 1169 case BNXT_ULP_FIELD_SRC_FIELD_BIT: 1170 if (!ulp_operand_read(field_opr, 1171 (uint8_t *)&idx, sizeof(uint16_t))) { 1172 BNXT_TF_DBG(ERR, "Field bit read failed\n"); 1173 return -EINVAL; 1174 } 1175 idx = tfp_be_to_cpu_16(idx); 1176 /* get the index from the global field list */ 1177 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) { 1178 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 1179 idx); 1180 return -EINVAL; 1181 } 1182 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) { 1183 *val = mapper_fld_one; 1184 *value = 1; 1185 } else { 1186 *val = mapper_fld_zeros; 1187 } 1188 break; 1189 case BNXT_ULP_FIELD_SRC_PORT_TABLE: 1190 /* The port id is present in the comp field list */ 1191 port_id = ULP_COMP_FLD_IDX_RD(parms, 1192 BNXT_ULP_CF_IDX_DEV_PORT_ID); 1193 /* get the port table enum */ 1194 if (!ulp_operand_read(field_opr, 1195 (uint8_t *)&idx, sizeof(uint16_t))) { 1196 BNXT_TF_DBG(ERR, "Port table enum read failed\n"); 1197 return -EINVAL; 1198 } 1199 idx = tfp_be_to_cpu_16(idx); 1200 if (ulp_mapper_field_port_db_process(parms, port_id, idx, 1201 val)) { 1202 BNXT_TF_DBG(ERR, "field port table failed\n"); 1203 return -EINVAL; 1204 } 1205 case BNXT_ULP_FIELD_SRC_SKIP: 1206 /* do nothing */ 1207 break; 1208 case BNXT_ULP_FIELD_SRC_REJECT: 1209 return -EINVAL; 1210 default: 1211 BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src); 1212 return -EINVAL; 1213 } 1214 return 0; 1215 } 1216 1217 static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen, 1218 uint64_t *output) 1219 { 1220 uint16_t val_16; 1221 uint32_t val_32; 1222 uint64_t val_64; 1223 uint32_t bytelen; 1224 1225 bytelen = ULP_BITS_2_BYTE(bitlen); 1226 if (bytelen == sizeof(uint8_t)) { 1227 *output = *((uint8_t *)buffer); 1228 } else if (bytelen == sizeof(uint16_t)) { 1229 val_16 = *((uint16_t *)buffer); 1230 *output = tfp_be_to_cpu_16(val_16); 1231 } else if (bytelen == sizeof(uint32_t)) { 1232 val_32 = *((uint32_t *)buffer); 1233 *output = tfp_be_to_cpu_32(val_32); 1234 } else if (bytelen == sizeof(val_64)) { 1235 val_64 = *((uint64_t *)buffer); 1236 *output = tfp_be_to_cpu_64(val_64); 1237 } else { 1238 *output = 0; 1239 return -EINVAL; 1240 } 1241 return 0; 1242 } 1243 1244 static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src, 1245 struct ulp_blob *blob, 1246 uint8_t *val, 1247 uint32_t val_len, 1248 uint8_t **out_val) 1249 { 1250 if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) { 1251 if (ulp_blob_pad_push(blob, val_len) < 0) { 1252 BNXT_TF_DBG(ERR, "too large for blob\n"); 1253 return -EINVAL; 1254 } 1255 } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) { 1256 if (ulp_blob_push_encap(blob, val, val_len) < 0) { 1257 BNXT_TF_DBG(ERR, "encap blob push failed\n"); 1258 return -EINVAL; 1259 } 1260 } else { 1261 if (!ulp_blob_push(blob, val, val_len)) { 1262 BNXT_TF_DBG(ERR, "push of val1 failed\n"); 1263 return -EINVAL; 1264 } 1265 } 1266 *out_val = val; 1267 return 0; 1268 } 1269 1270 static int32_t 1271 ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms, 1272 enum tf_dir dir, 1273 struct bnxt_ulp_mapper_field_info *fld, 1274 struct ulp_blob *blob, 1275 uint8_t is_key, 1276 const char *name) 1277 { 1278 uint16_t write_idx = blob->write_idx; 1279 uint8_t *val = NULL, *val1, *val2, *val3; 1280 uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0; 1281 uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0; 1282 uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0; 1283 uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0; 1284 uint64_t value1 = 0, value2 = 0, value3 = 0; 1285 int32_t rc = 0; 1286 1287 /* prepare the field source and values */ 1288 switch (fld->field_opc) { 1289 case BNXT_ULP_FIELD_OPC_SRC1: 1290 process_src1 = 1; 1291 break; 1292 case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: 1293 process_src1 = 1; 1294 break; 1295 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: 1296 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: 1297 process_src3 = 1; 1298 eval_src3 = 1; 1299 process_src1 = 1; 1300 process_src2 = 1; 1301 eval_src1 = 1; 1302 eval_src2 = 1; 1303 break; 1304 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: 1305 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: 1306 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: 1307 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: 1308 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: 1309 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: 1310 process_src1 = 1; 1311 process_src2 = 1; 1312 eval_src1 = 1; 1313 eval_src2 = 1; 1314 break; 1315 default: 1316 break; 1317 } 1318 1319 /* process the src1 opcode */ 1320 if (process_src1) { 1321 if (ulp_mapper_field_src_process(parms, fld->field_src1, 1322 fld->field_opr1, dir, is_key, 1323 fld->field_bit_size, &val1, 1324 &val1_len, &value1)) { 1325 BNXT_TF_DBG(ERR, "fld src1 process failed\n"); 1326 goto error; 1327 } 1328 if (eval_src1) { 1329 if (ulp_mapper_field_buffer_eval(val1, val1_len, 1330 &val1_int)) { 1331 BNXT_TF_DBG(ERR, "fld src1 eval failed\n"); 1332 goto error; 1333 } 1334 } 1335 } 1336 1337 /* for "if then clause" set the correct process */ 1338 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) { 1339 if (value1) 1340 process_src2 = 1; 1341 else 1342 process_src3 = 1; 1343 } 1344 1345 /* process src2 opcode */ 1346 if (process_src2) { 1347 if (ulp_mapper_field_src_process(parms, fld->field_src2, 1348 fld->field_opr2, dir, is_key, 1349 fld->field_bit_size, &val2, 1350 &val2_len, &value2)) { 1351 BNXT_TF_DBG(ERR, "fld src2 process failed\n"); 1352 goto error; 1353 } 1354 if (eval_src2) { 1355 if (ulp_mapper_field_buffer_eval(val2, val2_len, 1356 &val2_int)) { 1357 BNXT_TF_DBG(ERR, "fld src2 eval failed\n"); 1358 goto error; 1359 } 1360 } 1361 } 1362 1363 /* process src3 opcode */ 1364 if (process_src3) { 1365 if (ulp_mapper_field_src_process(parms, fld->field_src3, 1366 fld->field_opr3, dir, is_key, 1367 fld->field_bit_size, &val3, 1368 &val3_len, &value3)) { 1369 BNXT_TF_DBG(ERR, "fld src3 process failed\n"); 1370 goto error; 1371 } 1372 if (eval_src3) { 1373 if (ulp_mapper_field_buffer_eval(val3, val3_len, 1374 &val3_int)) { 1375 BNXT_TF_DBG(ERR, "fld src3 eval failed\n"); 1376 goto error; 1377 } 1378 } 1379 } 1380 1381 val_len = fld->field_bit_size; 1382 /* process the field opcodes */ 1383 switch (fld->field_opc) { 1384 case BNXT_ULP_FIELD_OPC_SRC1: 1385 rc = ulp_mapper_field_blob_write(fld->field_src1, 1386 blob, val1, val1_len, &val); 1387 val_len = val1_len; 1388 break; 1389 case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: 1390 if (value1) { 1391 rc = ulp_mapper_field_blob_write(fld->field_src2, blob, 1392 val2, val2_len, &val); 1393 val_len = val2_len; 1394 } else { 1395 rc = ulp_mapper_field_blob_write(fld->field_src3, blob, 1396 val3, val3_len, &val); 1397 val_len = val3_len; 1398 } 1399 break; 1400 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: 1401 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: 1402 val_int = val1_int + val2_int; 1403 val_int = tfp_cpu_to_be_64(val_int); 1404 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1405 if (!val) 1406 rc = -EINVAL; 1407 break; 1408 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: 1409 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: 1410 val_int = val1_int - val2_int; 1411 val_int = tfp_cpu_to_be_64(val_int); 1412 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1413 if (!val) 1414 rc = -EINVAL; 1415 break; 1416 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: 1417 val_int = val1_int | val2_int; 1418 val_int = tfp_cpu_to_be_64(val_int); 1419 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1420 if (!val) 1421 rc = -EINVAL; 1422 break; 1423 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: 1424 val_int = val1_int | val2_int | val3_int; 1425 val_int = tfp_cpu_to_be_64(val_int); 1426 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1427 if (!val) 1428 rc = -EINVAL; 1429 break; 1430 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: 1431 val_int = val1_int & val2_int; 1432 val_int = tfp_cpu_to_be_64(val_int); 1433 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1434 if (!val) 1435 rc = -EINVAL; 1436 break; 1437 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: 1438 val_int = val1_int & (val2_int | val3_int); 1439 val_int = tfp_cpu_to_be_64(val_int); 1440 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 1441 if (!val) 1442 rc = -EINVAL; 1443 break; 1444 case BNXT_ULP_FIELD_OPC_SKIP: 1445 break; 1446 default: 1447 BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc); 1448 rc = -EINVAL; 1449 break; 1450 } 1451 1452 return rc; 1453 error: 1454 BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name, 1455 fld->description, (val) ? write_idx : 0, val_len); 1456 return -EINVAL; 1457 } 1458 1459 /* 1460 * Result table process and fill the result blob. 1461 * data [out] - the result blob data 1462 */ 1463 static int32_t 1464 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms, 1465 struct bnxt_ulp_mapper_tbl_info *tbl, 1466 struct ulp_blob *data, 1467 const char *name) 1468 { 1469 struct bnxt_ulp_mapper_field_info *dflds; 1470 uint32_t i, num_flds = 0, encap_flds = 0; 1471 int32_t rc = 0; 1472 1473 /* Get the result field list */ 1474 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, 1475 &encap_flds); 1476 1477 /* validate the result field list counts */ 1478 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && 1479 (!num_flds && !encap_flds)) || !dflds || 1480 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE && 1481 (!num_flds || encap_flds))) { 1482 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n", 1483 num_flds, encap_flds); 1484 return -EINVAL; 1485 } 1486 1487 /* process the result fields, loop through them */ 1488 for (i = 0; i < (num_flds + encap_flds); i++) { 1489 /* set the swap index if encap swap bit is enabled */ 1490 if (parms->device_params->encap_byte_swap && encap_flds && 1491 i == num_flds) 1492 ulp_blob_encap_swap_idx_set(data); 1493 1494 /* Process the result fields */ 1495 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 1496 &dflds[i], data, 0, name); 1497 if (rc) { 1498 BNXT_TF_DBG(ERR, "data field failed\n"); 1499 return rc; 1500 } 1501 } 1502 1503 /* if encap bit swap is enabled perform the bit swap */ 1504 if (parms->device_params->encap_byte_swap && encap_flds) 1505 ulp_blob_perform_encap_swap(data); 1506 1507 return rc; 1508 } 1509 1510 static int32_t 1511 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, 1512 struct bnxt_ulp_mapper_tbl_info *tbl, 1513 uint64_t flow_id) 1514 { 1515 struct ulp_flow_db_res_params fid_parms; 1516 uint32_t mark, gfid, mark_flag; 1517 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1518 int32_t rc = 0; 1519 1520 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1521 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 1522 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1523 BNXT_ULP_ACT_BIT_MARK))) 1524 return rc; /* no need to perform gfid process */ 1525 1526 /* Get the mark id details from action property */ 1527 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1528 sizeof(mark)); 1529 mark = tfp_be_to_cpu_32(mark); 1530 1531 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid); 1532 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID; 1533 1534 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1535 gfid, mark); 1536 if (rc) { 1537 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1538 return rc; 1539 } 1540 fid_parms.direction = tbl->direction; 1541 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1542 fid_parms.critical_resource = tbl->critical_resource; 1543 fid_parms.resource_type = mark_flag; 1544 fid_parms.resource_hndl = gfid; 1545 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 1546 1547 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1548 if (rc) 1549 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1550 return rc; 1551 } 1552 1553 static int32_t 1554 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, 1555 struct bnxt_ulp_mapper_tbl_info *tbl) 1556 { 1557 struct ulp_flow_db_res_params fid_parms; 1558 uint32_t act_idx, mark, mark_flag; 1559 uint64_t val64; 1560 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1561 int32_t rc = 0; 1562 1563 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1564 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 1565 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 1566 BNXT_ULP_ACT_BIT_MARK))) 1567 return rc; /* no need to perform mark action process */ 1568 1569 /* Get the mark id details from action property */ 1570 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 1571 sizeof(mark)); 1572 mark = tfp_be_to_cpu_32(mark); 1573 1574 if (!ulp_regfile_read(parms->regfile, 1575 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 1576 &val64)) { 1577 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1578 return -EINVAL; 1579 } 1580 act_idx = tfp_be_to_cpu_64(val64); 1581 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID; 1582 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1583 act_idx, mark); 1584 if (rc) { 1585 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1586 return rc; 1587 } 1588 fid_parms.direction = tbl->direction; 1589 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1590 fid_parms.critical_resource = tbl->critical_resource; 1591 fid_parms.resource_type = mark_flag; 1592 fid_parms.resource_hndl = act_idx; 1593 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 1594 1595 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1596 if (rc) 1597 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1598 return rc; 1599 } 1600 1601 static int32_t 1602 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms, 1603 struct bnxt_ulp_mapper_tbl_info *tbl) 1604 { 1605 struct ulp_flow_db_res_params fid_parms; 1606 uint32_t act_idx, mark, mark_flag; 1607 uint64_t val64; 1608 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 1609 int32_t rc = 0; 1610 1611 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 1612 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION) 1613 return rc; /* no need to perform mark action process */ 1614 1615 /* Get the mark id details from the computed field of dev port id */ 1616 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID); 1617 1618 /* Get the main action pointer */ 1619 if (!ulp_regfile_read(parms->regfile, 1620 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 1621 &val64)) { 1622 BNXT_TF_DBG(ERR, "read action ptr main failed\n"); 1623 return -EINVAL; 1624 } 1625 act_idx = tfp_be_to_cpu_64(val64); 1626 1627 /* Set the mark flag to local fid and vfr flag */ 1628 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; 1629 1630 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 1631 act_idx, mark); 1632 if (rc) { 1633 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 1634 return rc; 1635 } 1636 fid_parms.direction = tbl->direction; 1637 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 1638 fid_parms.critical_resource = tbl->critical_resource; 1639 fid_parms.resource_type = mark_flag; 1640 fid_parms.resource_hndl = act_idx; 1641 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 1642 1643 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1644 if (rc) 1645 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 1646 return rc; 1647 } 1648 1649 /* Tcam table scan the identifier list and allocate each identifier */ 1650 static int32_t 1651 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms, 1652 struct bnxt_ulp_mapper_tbl_info *tbl) 1653 { 1654 struct bnxt_ulp_mapper_ident_info *idents; 1655 uint32_t num_idents; 1656 uint32_t i; 1657 1658 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 1659 for (i = 0; i < num_idents; i++) { 1660 if (ulp_mapper_ident_process(parms, tbl, 1661 &idents[i], NULL)) 1662 return -EINVAL; 1663 } 1664 return 0; 1665 } 1666 1667 /* 1668 * Tcam table scan the identifier list and extract the identifier from 1669 * the result blob. 1670 */ 1671 static int32_t 1672 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms, 1673 struct bnxt_ulp_mapper_tbl_info *tbl, 1674 struct ulp_blob *data) 1675 { 1676 struct bnxt_ulp_mapper_ident_info *idents; 1677 uint32_t num_idents = 0, i; 1678 int32_t rc = 0; 1679 1680 /* 1681 * Extract the listed identifiers from the result field, 1682 * no need to allocate them. 1683 */ 1684 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 1685 for (i = 0; i < num_idents; i++) { 1686 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data); 1687 if (rc) { 1688 BNXT_TF_DBG(ERR, "Error in identifier extraction\n"); 1689 return rc; 1690 } 1691 } 1692 return rc; 1693 } 1694 1695 /* Internal function to write the tcam entry */ 1696 static int32_t 1697 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms, 1698 struct bnxt_ulp_mapper_tbl_info *tbl, 1699 struct ulp_blob *key, 1700 struct ulp_blob *mask, 1701 struct ulp_blob *data, 1702 uint16_t idx) 1703 { 1704 struct tf_set_tcam_entry_parms sparms = { 0 }; 1705 struct tf *tfp; 1706 uint16_t tmplen; 1707 int32_t rc; 1708 1709 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 1710 if (!tfp) { 1711 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1712 return -EINVAL; 1713 } 1714 1715 sparms.dir = tbl->direction; 1716 sparms.tcam_tbl_type = tbl->resource_type; 1717 sparms.idx = idx; 1718 sparms.key = ulp_blob_data_get(key, &tmplen); 1719 sparms.key_sz_in_bits = tmplen; 1720 sparms.mask = ulp_blob_data_get(mask, &tmplen); 1721 sparms.result = ulp_blob_data_get(data, &tmplen); 1722 sparms.result_sz_in_bits = tmplen; 1723 if (tf_set_tcam_entry(tfp, &sparms)) { 1724 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n", 1725 tf_tcam_tbl_2_str(sparms.tcam_tbl_type), 1726 tf_dir_2_str(sparms.dir), sparms.idx); 1727 return -EIO; 1728 } 1729 1730 /* Mark action */ 1731 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 1732 if (rc) { 1733 BNXT_TF_DBG(ERR, "failed mark action processing\n"); 1734 return rc; 1735 } 1736 1737 return rc; 1738 } 1739 1740 /* 1741 * internal function to post process key/mask blobs for dynamic pad WC tcam tbl 1742 * 1743 * parms [in] The mappers parms with data related to the flow. 1744 * 1745 * key [in] The original key to be transformed 1746 * 1747 * mask [in] The original mask to be transformed 1748 * 1749 * tkey [in/out] The transformed key 1750 * 1751 * tmask [in/out] The transformed mask 1752 * 1753 * returns zero on success, non-zero on failure 1754 */ 1755 static uint32_t 1756 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms, 1757 struct ulp_blob *key, 1758 struct ulp_blob *mask, 1759 struct ulp_blob *tkey, 1760 struct ulp_blob *tmask) 1761 { 1762 uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset; 1763 uint32_t cword, i, rc; 1764 int32_t pad; 1765 uint8_t *val; 1766 1767 slice_width = dparms->wc_slice_width; 1768 clen = dparms->wc_ctl_size_bits; 1769 max_slices = dparms->wc_max_slices; 1770 blen = ulp_blob_data_len_get(key); 1771 1772 /* Get the length of the key based on number of slices and width */ 1773 num_slices = 1; 1774 tlen = slice_width; 1775 while (tlen < blen && 1776 num_slices <= max_slices) { 1777 num_slices = num_slices << 1; 1778 tlen = tlen << 1; 1779 } 1780 1781 if (num_slices > max_slices) { 1782 BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen); 1783 return -EINVAL; 1784 } 1785 1786 /* The key/mask may not be on a natural slice boundary, pad it */ 1787 pad = tlen - blen; 1788 if (ulp_blob_pad_push(key, pad) < 0 || 1789 ulp_blob_pad_push(mask, pad) < 0) { 1790 BNXT_TF_DBG(ERR, "Unable to pad key/mask\n"); 1791 return -EINVAL; 1792 } 1793 1794 /* The new length accounts for the ctrl word length and num slices */ 1795 tlen = tlen + clen * num_slices; 1796 if (!ulp_blob_init(tkey, tlen, key->byte_order) || 1797 !ulp_blob_init(tmask, tlen, mask->byte_order)) { 1798 BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n"); 1799 return -EINVAL; 1800 } 1801 1802 /* Build the transformed key/mask */ 1803 cword = dparms->wc_mode_list[num_slices - 1]; 1804 cword = tfp_cpu_to_be_32(cword); 1805 offset = 0; 1806 for (i = 0; i < num_slices; i++) { 1807 val = ulp_blob_push_32(tkey, &cword, clen); 1808 if (!val) { 1809 BNXT_TF_DBG(ERR, "Key ctrl word push failed\n"); 1810 return -EINVAL; 1811 } 1812 val = ulp_blob_push_32(tmask, &cword, clen); 1813 if (!val) { 1814 BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n"); 1815 return -EINVAL; 1816 } 1817 rc = ulp_blob_append(tkey, key, offset, slice_width); 1818 if (rc) { 1819 BNXT_TF_DBG(ERR, "Key blob append failed\n"); 1820 return rc; 1821 } 1822 rc = ulp_blob_append(tmask, mask, offset, slice_width); 1823 if (rc) { 1824 BNXT_TF_DBG(ERR, "Mask blob append failed\n"); 1825 return rc; 1826 } 1827 offset += slice_width; 1828 } 1829 1830 /* The key/mask are byte reversed on every 4 byte chunk */ 1831 ulp_blob_perform_byte_reverse(tkey, 4); 1832 ulp_blob_perform_byte_reverse(tmask, 4); 1833 1834 return 0; 1835 } 1836 1837 /* internal function to post process the key/mask blobs for wildcard tcam tbl */ 1838 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob) 1839 { 1840 ulp_blob_perform_64B_word_swap(blob); 1841 ulp_blob_perform_64B_byte_swap(blob); 1842 } 1843 1844 static int32_t 1845 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1846 struct bnxt_ulp_mapper_tbl_info *tbl) 1847 { 1848 struct bnxt_ulp_mapper_key_info *kflds; 1849 struct ulp_blob okey, omask, data, update_data; 1850 struct ulp_blob tkey, tmask; /* transform key and mask */ 1851 struct ulp_blob *key, *mask; 1852 uint32_t i, num_kflds; 1853 struct tf *tfp; 1854 int32_t rc, trc; 1855 struct bnxt_ulp_device_params *dparms = parms->device_params; 1856 struct tf_alloc_tcam_entry_parms aparms = { 0 }; 1857 struct tf_search_tcam_entry_parms searchparms = { 0 }; 1858 struct ulp_flow_db_res_params fid_parms = { 0 }; 1859 struct tf_free_tcam_entry_parms free_parms = { 0 }; 1860 uint32_t hit = 0; 1861 uint16_t tmplen = 0; 1862 uint16_t idx; 1863 1864 /* Set the key and mask to the original key and mask. */ 1865 key = &okey; 1866 mask = &omask; 1867 1868 /* Skip this if table opcode is NOP */ 1869 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED || 1870 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) { 1871 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n", 1872 tbl->tbl_opcode); 1873 return 0; 1874 } 1875 1876 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 1877 if (!tfp) { 1878 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n"); 1879 return -EINVAL; 1880 } 1881 1882 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 1883 if (!kflds || !num_kflds) { 1884 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 1885 return -EINVAL; 1886 } 1887 1888 if (!ulp_blob_init(key, tbl->blob_key_bit_size, tbl->byte_order) || 1889 !ulp_blob_init(mask, tbl->blob_key_bit_size, tbl->byte_order) || 1890 !ulp_blob_init(&data, tbl->result_bit_size, dparms->byte_order) || 1891 !ulp_blob_init(&update_data, tbl->result_bit_size, 1892 dparms->byte_order)) { 1893 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 1894 return -EINVAL; 1895 } 1896 1897 /* create the key/mask */ 1898 /* 1899 * NOTE: The WC table will require some kind of flag to handle the 1900 * mode bits within the key/mask 1901 */ 1902 for (i = 0; i < num_kflds; i++) { 1903 /* Setup the key */ 1904 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 1905 &kflds[i].field_info_spec, 1906 key, 1, "TCAM Key"); 1907 if (rc) { 1908 BNXT_TF_DBG(ERR, "Key field set failed %s\n", 1909 kflds[i].field_info_spec.description); 1910 return rc; 1911 } 1912 1913 /* Setup the mask */ 1914 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 1915 &kflds[i].field_info_mask, 1916 mask, 0, "TCAM Mask"); 1917 if (rc) { 1918 BNXT_TF_DBG(ERR, "Mask field set failed %s\n", 1919 kflds[i].field_info_mask.description); 1920 return rc; 1921 } 1922 } 1923 1924 /* For wild card tcam perform the post process to swap the blob */ 1925 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM || 1926 tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH || 1927 tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW) { 1928 if (dparms->dynamic_pad_en) { 1929 /* Sets up the slices for writing to the WC TCAM */ 1930 rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms, 1931 key, mask, 1932 &tkey, 1933 &tmask); 1934 if (rc) { 1935 BNXT_TF_DBG(ERR, 1936 "Failed to post proc WC entry.\n"); 1937 return rc; 1938 } 1939 /* Now need to use the transform Key/Mask */ 1940 key = &tkey; 1941 mask = &tmask; 1942 } else { 1943 ulp_mapper_wc_tcam_tbl_post_process(key); 1944 ulp_mapper_wc_tcam_tbl_post_process(mask); 1945 } 1946 1947 } 1948 1949 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 1950 /* allocate the tcam index */ 1951 aparms.dir = tbl->direction; 1952 aparms.tcam_tbl_type = tbl->resource_type; 1953 aparms.key = ulp_blob_data_get(key, &tmplen); 1954 aparms.key_sz_in_bits = tmplen; 1955 aparms.mask = ulp_blob_data_get(mask, &tmplen); 1956 1957 /* calculate the entry priority */ 1958 rc = ulp_mapper_priority_opc_process(parms, tbl, 1959 &aparms.priority); 1960 if (rc) { 1961 BNXT_TF_DBG(ERR, "entry priority process failed\n"); 1962 return rc; 1963 } 1964 1965 rc = tf_alloc_tcam_entry(tfp, &aparms); 1966 if (rc) { 1967 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc); 1968 return rc; 1969 } 1970 idx = aparms.idx; 1971 hit = aparms.hit; 1972 } else { 1973 /* 1974 * Searching before allocation to see if we already have an 1975 * entry. This allows re-use of a constrained resource. 1976 */ 1977 searchparms.dir = tbl->direction; 1978 searchparms.tcam_tbl_type = tbl->resource_type; 1979 searchparms.key = ulp_blob_data_get(key, &tmplen); 1980 searchparms.key_sz_in_bits = tbl->key_bit_size; 1981 searchparms.mask = ulp_blob_data_get(mask, &tmplen); 1982 searchparms.alloc = 1; 1983 searchparms.result = ulp_blob_data_get(&data, &tmplen); 1984 searchparms.result_sz_in_bits = tbl->result_bit_size; 1985 1986 /* calculate the entry priority */ 1987 rc = ulp_mapper_priority_opc_process(parms, tbl, 1988 &searchparms.priority); 1989 if (rc) { 1990 BNXT_TF_DBG(ERR, "entry priority process failed\n"); 1991 return rc; 1992 } 1993 1994 rc = tf_search_tcam_entry(tfp, &searchparms); 1995 if (rc) { 1996 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc); 1997 return rc; 1998 } 1999 2000 /* Successful search, check the result */ 2001 if (searchparms.search_status == REJECT) { 2002 BNXT_TF_DBG(ERR, "tcam alloc rejected\n"); 2003 return -ENOMEM; 2004 } 2005 idx = searchparms.idx; 2006 hit = searchparms.hit; 2007 } 2008 2009 /* Write the tcam index into the regfile*/ 2010 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand, 2011 (uint64_t)tfp_cpu_to_be_64(idx))) { 2012 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", 2013 tbl->tbl_operand); 2014 rc = -EINVAL; 2015 /* Need to free the tcam idx, so goto error */ 2016 goto error; 2017 } 2018 2019 /* if it is miss then it is same as no search before alloc */ 2020 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) { 2021 /*Scan identifier list, allocate identifier and update regfile*/ 2022 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl); 2023 /* Create the result blob */ 2024 if (!rc) 2025 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 2026 "TCAM Result"); 2027 /* write the tcam entry */ 2028 if (!rc) 2029 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key, 2030 mask, &data, idx); 2031 } else { 2032 /*Scan identifier list, extract identifier and update regfile*/ 2033 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data); 2034 } 2035 if (rc) 2036 goto error; 2037 2038 /* Add the tcam index to the flow database */ 2039 fid_parms.direction = tbl->direction; 2040 fid_parms.resource_func = tbl->resource_func; 2041 fid_parms.resource_type = tbl->resource_type; 2042 fid_parms.critical_resource = tbl->critical_resource; 2043 fid_parms.resource_hndl = idx; 2044 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 2045 2046 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2047 if (rc) { 2048 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2049 rc); 2050 /* Need to free the identifier, so goto error */ 2051 goto error; 2052 } 2053 2054 return 0; 2055 error: 2056 free_parms.dir = tbl->direction; 2057 free_parms.tcam_tbl_type = tbl->resource_type; 2058 free_parms.idx = idx; 2059 trc = tf_free_tcam_entry(tfp, &free_parms); 2060 if (trc) 2061 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n", 2062 tbl->resource_type, tbl->direction, idx); 2063 return rc; 2064 } 2065 2066 static int32_t 2067 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2068 struct bnxt_ulp_mapper_tbl_info *tbl) 2069 { 2070 struct bnxt_ulp_mapper_key_info *kflds; 2071 struct ulp_blob key, data; 2072 uint32_t i, num_kflds; 2073 uint16_t tmplen; 2074 struct tf *tfp; 2075 struct ulp_flow_db_res_params fid_parms = { 0 }; 2076 struct tf_insert_em_entry_parms iparms = { 0 }; 2077 struct tf_delete_em_entry_parms free_parms = { 0 }; 2078 enum bnxt_ulp_flow_mem_type mtype; 2079 struct bnxt_ulp_device_params *dparms = parms->device_params; 2080 int32_t trc; 2081 int32_t rc = 0; 2082 int32_t pad = 0; 2083 2084 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 2085 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype); 2086 if (rc) { 2087 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n"); 2088 return -EINVAL; 2089 } 2090 2091 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2092 if (!kflds || !num_kflds) { 2093 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2094 return -EINVAL; 2095 } 2096 2097 /* Initialize the key/result blobs */ 2098 if (!ulp_blob_init(&key, tbl->blob_key_bit_size, 2099 tbl->byte_order) || 2100 !ulp_blob_init(&data, tbl->result_bit_size, 2101 tbl->byte_order)) { 2102 BNXT_TF_DBG(ERR, "blob inits failed.\n"); 2103 return -EINVAL; 2104 } 2105 2106 /* create the key */ 2107 for (i = 0; i < num_kflds; i++) { 2108 /* Setup the key */ 2109 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2110 &kflds[i].field_info_spec, 2111 &key, 1, "EM Key"); 2112 if (rc) { 2113 BNXT_TF_DBG(ERR, "Key field set failed.\n"); 2114 return rc; 2115 } 2116 } 2117 2118 /* if dynamic padding is enabled then add padding to result data */ 2119 if (dparms->dynamic_pad_en) { 2120 /* add padding to make sure key is at byte boundary */ 2121 ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS); 2122 2123 /* add the pad */ 2124 pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits; 2125 if (pad < 0) { 2126 BNXT_TF_DBG(ERR, "Invalid em blk size and align\n"); 2127 return -EINVAL; 2128 } 2129 ulp_blob_pad_push(&data, (uint32_t)pad); 2130 } 2131 2132 /* Create the result data blob */ 2133 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result"); 2134 if (rc) { 2135 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2136 return rc; 2137 } 2138 if (dparms->dynamic_pad_en) { 2139 uint32_t abits = dparms->em_blk_align_bits; 2140 2141 /* when dynamic padding is enabled merge result + key */ 2142 rc = ulp_blob_block_merge(&data, &key, abits, pad); 2143 if (rc) { 2144 BNXT_TF_DBG(ERR, "Failed to merge the result blob\n"); 2145 return rc; 2146 } 2147 2148 /* add padding to make sure merged result is at slice boundary*/ 2149 ulp_blob_pad_align(&data, abits); 2150 2151 ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits)); 2152 } 2153 2154 /* do the transpose for the internal EM keys */ 2155 if (tbl->resource_type == TF_MEM_INTERNAL) { 2156 if (dparms->em_key_align_bytes) { 2157 int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes); 2158 2159 tmplen = ulp_blob_data_len_get(&key); 2160 ulp_blob_pad_push(&key, b - tmplen); 2161 } 2162 tmplen = ulp_blob_data_len_get(&key); 2163 ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen)); 2164 } 2165 2166 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, 2167 &iparms.tbl_scope_id); 2168 if (rc) { 2169 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 2170 return rc; 2171 } 2172 2173 /* 2174 * NOTE: the actual blob size will differ from the size in the tbl 2175 * entry due to the padding. 2176 */ 2177 iparms.dup_check = 0; 2178 iparms.dir = tbl->direction; 2179 iparms.mem = tbl->resource_type; 2180 iparms.key = ulp_blob_data_get(&key, &tmplen); 2181 iparms.key_sz_in_bits = tbl->key_bit_size; 2182 iparms.em_record = ulp_blob_data_get(&data, &tmplen); 2183 if (tbl->result_bit_size) 2184 iparms.em_record_sz_in_bits = tbl->result_bit_size; 2185 else 2186 iparms.em_record_sz_in_bits = tmplen; 2187 2188 rc = tf_insert_em_entry(tfp, &iparms); 2189 if (rc) { 2190 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc); 2191 return rc; 2192 } 2193 2194 /* Mark action process */ 2195 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT && 2196 tbl->resource_type == TF_MEM_EXTERNAL) 2197 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id); 2198 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT && 2199 tbl->resource_type == TF_MEM_INTERNAL) 2200 rc = ulp_mapper_mark_act_ptr_process(parms, tbl); 2201 if (rc) { 2202 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n"); 2203 goto error; 2204 } 2205 2206 /* Link the EM resource to the flow in the flow db */ 2207 memset(&fid_parms, 0, sizeof(fid_parms)); 2208 fid_parms.direction = tbl->direction; 2209 fid_parms.resource_func = tbl->resource_func; 2210 fid_parms.resource_type = tbl->resource_type; 2211 fid_parms.critical_resource = tbl->critical_resource; 2212 fid_parms.resource_hndl = iparms.flow_handle; 2213 2214 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2215 if (rc) { 2216 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", 2217 rc); 2218 /* Need to free the identifier, so goto error */ 2219 goto error; 2220 } 2221 2222 return 0; 2223 error: 2224 free_parms.dir = iparms.dir; 2225 free_parms.mem = iparms.mem; 2226 free_parms.tbl_scope_id = iparms.tbl_scope_id; 2227 free_parms.flow_handle = iparms.flow_handle; 2228 2229 trc = tf_delete_em_entry(tfp, &free_parms); 2230 if (trc) 2231 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n"); 2232 2233 return rc; 2234 } 2235 2236 static int32_t 2237 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2238 struct bnxt_ulp_mapper_tbl_info *tbl) 2239 { 2240 struct ulp_flow_db_res_params fid_parms; 2241 struct ulp_blob data; 2242 uint64_t regval = 0; 2243 uint16_t tmplen; 2244 uint32_t index; 2245 int32_t rc = 0, trc = 0; 2246 struct tf_alloc_tbl_entry_parms aparms = { 0 }; 2247 struct tf_set_tbl_entry_parms sparms = { 0 }; 2248 struct tf_get_tbl_entry_parms gparms = { 0 }; 2249 struct tf_free_tbl_entry_parms free_parms = { 0 }; 2250 uint32_t tbl_scope_id; 2251 struct tf *tfp; 2252 struct bnxt_ulp_glb_resource_info glb_res = { 0 }; 2253 uint16_t bit_size; 2254 bool alloc = false; 2255 bool write = false; 2256 bool global = false; 2257 uint64_t act_rec_size; 2258 bool shared = false; 2259 2260 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 2261 /* use the max size if encap is enabled */ 2262 if (tbl->encap_num_fields) 2263 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS; 2264 else 2265 bit_size = tbl->result_bit_size; 2266 2267 /* Initialize the blob data */ 2268 if (!ulp_blob_init(&data, bit_size, 2269 parms->device_params->byte_order)) { 2270 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n"); 2271 return -EINVAL; 2272 } 2273 2274 /* Get the scope id first */ 2275 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id); 2276 if (rc) { 2277 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc); 2278 return rc; 2279 } 2280 2281 switch (tbl->tbl_opcode) { 2282 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE: 2283 alloc = true; 2284 break; 2285 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE: 2286 /* 2287 * Build the entry, alloc an index, write the table, and store 2288 * the data in the regfile. 2289 */ 2290 alloc = true; 2291 write = true; 2292 break; 2293 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE: 2294 /* 2295 * get the index to write to from the regfile and then write 2296 * the table entry. 2297 */ 2298 if (!ulp_regfile_read(parms->regfile, 2299 tbl->tbl_operand, 2300 ®val)) { 2301 BNXT_TF_DBG(ERR, 2302 "Failed to get tbl idx from regfile[%d].\n", 2303 tbl->tbl_operand); 2304 return -EINVAL; 2305 } 2306 index = tfp_be_to_cpu_64(regval); 2307 /* For external, we need to reverse shift */ 2308 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2309 index = TF_ACT_REC_PTR_2_OFFSET(index); 2310 2311 write = true; 2312 break; 2313 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE: 2314 /* 2315 * Build the entry, alloc an index, write the table, and store 2316 * the data in the global regfile. 2317 */ 2318 alloc = true; 2319 global = true; 2320 write = true; 2321 glb_res.direction = tbl->direction; 2322 glb_res.resource_func = tbl->resource_func; 2323 glb_res.resource_type = tbl->resource_type; 2324 glb_res.glb_regfile_index = tbl->tbl_operand; 2325 break; 2326 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE: 2327 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) { 2328 BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n"); 2329 return -EINVAL; 2330 } 2331 /* 2332 * get the index to write to from the global regfile and then 2333 * write the table. 2334 */ 2335 if (ulp_mapper_glb_resource_read(parms->mapper_data, 2336 tbl->direction, 2337 tbl->tbl_operand, 2338 ®val, &shared)) { 2339 BNXT_TF_DBG(ERR, 2340 "Failed to get tbl idx from Glb RF[%d].\n", 2341 tbl->tbl_operand); 2342 return -EINVAL; 2343 } 2344 index = tfp_be_to_cpu_64(regval); 2345 /* For external, we need to reverse shift */ 2346 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2347 index = TF_ACT_REC_PTR_2_OFFSET(index); 2348 write = true; 2349 break; 2350 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE: 2351 /* 2352 * The read is different from the rest and can be handled here 2353 * instead of trying to use common code. Simply read the table 2354 * with the index from the regfile, scan and store the 2355 * identifiers, and return. 2356 */ 2357 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 2358 /* Not currently supporting with EXT */ 2359 BNXT_TF_DBG(ERR, 2360 "Ext Table Read Opcode not supported.\n"); 2361 return -EINVAL; 2362 } 2363 if (!ulp_regfile_read(parms->regfile, 2364 tbl->tbl_operand, ®val)) { 2365 BNXT_TF_DBG(ERR, 2366 "Failed to get tbl idx from regfile[%d]\n", 2367 tbl->tbl_operand); 2368 return -EINVAL; 2369 } 2370 index = tfp_be_to_cpu_64(regval); 2371 gparms.dir = tbl->direction; 2372 gparms.type = tbl->resource_type; 2373 gparms.data = ulp_blob_data_get(&data, &tmplen); 2374 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size); 2375 gparms.idx = index; 2376 rc = tf_get_tbl_entry(tfp, &gparms); 2377 if (rc) { 2378 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n", 2379 tbl->resource_type, index); 2380 return rc; 2381 } 2382 /* 2383 * Scan the fields in the entry and push them into the regfile. 2384 */ 2385 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2386 gparms.data, 2387 gparms.data_sz_in_bytes, 2388 data.byte_order); 2389 if (rc) { 2390 BNXT_TF_DBG(ERR, 2391 "Failed to get flds on tbl read rc=%d\n", 2392 rc); 2393 return rc; 2394 } 2395 return 0; 2396 default: 2397 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n", 2398 tbl->tbl_opcode); 2399 return -EINVAL; 2400 } 2401 2402 if (write) { 2403 /* Get the result fields list */ 2404 rc = ulp_mapper_tbl_result_build(parms, 2405 tbl, 2406 &data, 2407 "Indexed Result"); 2408 if (rc) { 2409 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2410 return rc; 2411 } 2412 } 2413 2414 if (alloc) { 2415 aparms.dir = tbl->direction; 2416 aparms.type = tbl->resource_type; 2417 aparms.tbl_scope_id = tbl_scope_id; 2418 2419 /* All failures after the alloc succeeds require a free */ 2420 rc = tf_alloc_tbl_entry(tfp, &aparms); 2421 if (rc) { 2422 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n", 2423 tf_tbl_type_2_str(tbl->resource_type), 2424 tf_dir_2_str(tbl->direction), rc); 2425 return rc; 2426 } 2427 index = aparms.idx; 2428 2429 /* 2430 * Store the index in the regfile since we either allocated it 2431 * or it was a hit. 2432 * 2433 * Calculate the idx for the result record, for external EM the 2434 * offset needs to be shifted accordingly. 2435 * If external non-inline table types are used then need to 2436 * revisit this logic. 2437 */ 2438 if (tbl->resource_type == TF_TBL_TYPE_EXT) 2439 regval = TF_ACT_REC_OFFSET_2_PTR(index); 2440 else 2441 regval = index; 2442 regval = tfp_cpu_to_be_64(regval); 2443 2444 if (global) { 2445 /* 2446 * Shared resources are never allocated through this 2447 * method, so the shared flag is always false. 2448 */ 2449 rc = ulp_mapper_glb_resource_write(parms->mapper_data, 2450 &glb_res, regval, 2451 false); 2452 } else { 2453 rc = ulp_regfile_write(parms->regfile, 2454 tbl->tbl_operand, regval); 2455 } 2456 if (rc) { 2457 BNXT_TF_DBG(ERR, 2458 "Failed to write %s regfile[%d] rc=%d\n", 2459 (global) ? "global" : "reg", 2460 tbl->tbl_operand, rc); 2461 goto error; 2462 } 2463 } 2464 2465 if (write) { 2466 sparms.dir = tbl->direction; 2467 sparms.type = tbl->resource_type; 2468 sparms.data = ulp_blob_data_get(&data, &tmplen); 2469 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2470 sparms.idx = index; 2471 sparms.tbl_scope_id = tbl_scope_id; 2472 if (shared) 2473 tfp = bnxt_ulp_cntxt_shared_tfp_get(parms->ulp_ctx); 2474 rc = tf_set_tbl_entry(tfp, &sparms); 2475 if (rc) { 2476 BNXT_TF_DBG(ERR, 2477 "Index table[%s][%s][%x] write fail rc=%d\n", 2478 tf_tbl_type_2_str(sparms.type), 2479 tf_dir_2_str(sparms.dir), 2480 sparms.idx, rc); 2481 goto error; 2482 } 2483 2484 /* Calculate action record size */ 2485 if (tbl->resource_type == TF_TBL_TYPE_EXT) { 2486 act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16; 2487 act_rec_size--; 2488 if (ulp_regfile_write(parms->regfile, 2489 BNXT_ULP_RF_IDX_ACTION_REC_SIZE, 2490 tfp_cpu_to_be_64(act_rec_size))) 2491 BNXT_TF_DBG(ERR, 2492 "Failed write the act rec size\n"); 2493 } 2494 } 2495 2496 /* Link the resource to the flow in the flow db */ 2497 memset(&fid_parms, 0, sizeof(fid_parms)); 2498 fid_parms.direction = tbl->direction; 2499 fid_parms.resource_func = tbl->resource_func; 2500 fid_parms.resource_type = tbl->resource_type; 2501 fid_parms.resource_sub_type = tbl->resource_sub_type; 2502 fid_parms.resource_hndl = index; 2503 fid_parms.critical_resource = tbl->critical_resource; 2504 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 2505 2506 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2507 if (rc) { 2508 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2509 rc); 2510 goto error; 2511 } 2512 2513 /* Perform the VF rep action */ 2514 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl); 2515 if (rc) { 2516 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc); 2517 goto error; 2518 } 2519 return rc; 2520 error: 2521 /* Shared resources are not freed */ 2522 if (shared) 2523 return rc; 2524 /* 2525 * Free the allocated resource since we failed to either 2526 * write to the entry or link the flow 2527 */ 2528 free_parms.dir = tbl->direction; 2529 free_parms.type = tbl->resource_type; 2530 free_parms.idx = index; 2531 free_parms.tbl_scope_id = tbl_scope_id; 2532 2533 trc = tf_free_tbl_entry(tfp, &free_parms); 2534 if (trc) 2535 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n"); 2536 2537 return rc; 2538 } 2539 2540 static int32_t 2541 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2542 struct bnxt_ulp_mapper_tbl_info *tbl) 2543 { 2544 struct ulp_blob data, res_blob; 2545 uint64_t idx; 2546 uint16_t tmplen; 2547 int32_t rc = 0; 2548 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 }; 2549 struct tf_get_if_tbl_entry_parms get_parms = { 0 }; 2550 struct tf *tfp; 2551 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode; 2552 uint32_t res_size; 2553 2554 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session); 2555 /* Initialize the blob data */ 2556 if (!ulp_blob_init(&data, tbl->result_bit_size, 2557 parms->device_params->byte_order)) { 2558 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 2559 return -EINVAL; 2560 } 2561 2562 /* create the result blob */ 2563 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result"); 2564 if (rc) { 2565 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2566 return rc; 2567 } 2568 2569 /* Get the index details */ 2570 switch (if_opc) { 2571 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD: 2572 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 2573 break; 2574 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE: 2575 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) { 2576 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 2577 tbl->tbl_operand); 2578 return -EINVAL; 2579 } 2580 idx = tfp_be_to_cpu_64(idx); 2581 break; 2582 case BNXT_ULP_IF_TBL_OPC_WR_CONST: 2583 idx = tbl->tbl_operand; 2584 break; 2585 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD: 2586 /* Initialize the result blob */ 2587 if (!ulp_blob_init(&res_blob, tbl->result_bit_size, 2588 parms->device_params->byte_order)) { 2589 BNXT_TF_DBG(ERR, "Failed initial result blob\n"); 2590 return -EINVAL; 2591 } 2592 2593 /* read the interface table */ 2594 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand); 2595 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size); 2596 get_parms.dir = tbl->direction; 2597 get_parms.type = tbl->resource_type; 2598 get_parms.idx = idx; 2599 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen); 2600 get_parms.data_sz_in_bytes = res_size; 2601 2602 rc = tf_get_if_tbl_entry(tfp, &get_parms); 2603 if (rc) { 2604 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n", 2605 get_parms.type, 2606 tf_dir_2_str(get_parms.dir), 2607 get_parms.idx, rc); 2608 return rc; 2609 } 2610 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2611 res_blob.data, 2612 res_size, 2613 res_blob.byte_order); 2614 if (rc) 2615 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc); 2616 return rc; 2617 case BNXT_ULP_IF_TBL_OPC_NOT_USED: 2618 return rc; /* skip it */ 2619 default: 2620 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n"); 2621 return -EINVAL; 2622 } 2623 2624 /* Perform the tf table set by filling the set params */ 2625 iftbl_params.dir = tbl->direction; 2626 iftbl_params.type = tbl->resource_type; 2627 iftbl_params.data = ulp_blob_data_get(&data, &tmplen); 2628 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen); 2629 iftbl_params.idx = idx; 2630 2631 rc = tf_set_if_tbl_entry(tfp, &iftbl_params); 2632 if (rc) { 2633 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n", 2634 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */ 2635 tf_dir_2_str(iftbl_params.dir), 2636 iftbl_params.idx, rc); 2637 return rc; 2638 } 2639 2640 /* 2641 * TBD: Need to look at the need to store idx in flow db for restore 2642 * the table to its original state on deletion of this entry. 2643 */ 2644 return rc; 2645 } 2646 2647 static int32_t 2648 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2649 struct bnxt_ulp_mapper_tbl_info *tbl) 2650 { 2651 struct ulp_mapper_gen_tbl_list *gen_tbl_list; 2652 struct bnxt_ulp_mapper_key_info *kflds; 2653 struct ulp_flow_db_res_params fid_parms; 2654 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g; 2655 struct ulp_gen_hash_entry_params hash_entry; 2656 uint16_t tmplen = 0; 2657 struct ulp_blob key, data; 2658 uint8_t *cache_key; 2659 int32_t tbl_idx; 2660 uint32_t i, num_kflds = 0, key_index = 0; 2661 uint32_t gen_tbl_miss = 1, fdb_write = 0; 2662 uint8_t *byte_data; 2663 int32_t rc = 0; 2664 2665 /* Get the key fields list and build the key. */ 2666 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2667 if (!kflds || !num_kflds) { 2668 BNXT_TF_DBG(ERR, "Failed to get key fields\n"); 2669 return -EINVAL; 2670 } 2671 2672 if (!ulp_blob_init(&key, tbl->key_bit_size, 2673 parms->device_params->byte_order)) { 2674 BNXT_TF_DBG(ERR, "Failed to alloc blob\n"); 2675 return -EINVAL; 2676 } 2677 for (i = 0; i < num_kflds; i++) { 2678 /* Setup the key */ 2679 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2680 &kflds[i].field_info_spec, 2681 &key, 1, "Gen Tbl Key"); 2682 if (rc) { 2683 BNXT_TF_DBG(ERR, 2684 "Failed to create key for Gen tbl rc=%d\n", 2685 rc); 2686 return -EINVAL; 2687 } 2688 } 2689 2690 /* Calculate the table index for the generic table*/ 2691 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type, 2692 tbl->direction); 2693 if (tbl_idx < 0) { 2694 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n", 2695 tbl->resource_sub_type, tbl->direction); 2696 return -EINVAL; 2697 } 2698 2699 /* The_key is a byte array convert it to a search index */ 2700 cache_key = ulp_blob_data_get(&key, &tmplen); 2701 /* get the generic table */ 2702 gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx]; 2703 2704 /* Check if generic hash table */ 2705 if (gen_tbl_list->hash_tbl) { 2706 if (tbl->gen_tbl_lkup_type != 2707 BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) { 2708 BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n", 2709 gen_tbl_list->gen_tbl_name); 2710 return -EINVAL; 2711 } 2712 hash_entry.key_data = cache_key; 2713 hash_entry.key_length = ULP_BITS_2_BYTE(tmplen); 2714 rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl, 2715 &hash_entry); 2716 if (rc) { 2717 BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n", 2718 gen_tbl_list->gen_tbl_name); 2719 return rc; 2720 } 2721 if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) { 2722 key_index = hash_entry.key_idx; 2723 /* Get the generic table entry */ 2724 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, 2725 key_index, 2726 &gen_tbl_ent)) 2727 return -EINVAL; 2728 /* store the hash index in the fdb */ 2729 key_index = hash_entry.hash_index; 2730 } 2731 } else { 2732 /* convert key to index directly */ 2733 if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) { 2734 BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n", 2735 gen_tbl_list->gen_tbl_name); 2736 return -EINVAL; 2737 } 2738 memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen)); 2739 /* Get the generic table entry */ 2740 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index, 2741 &gen_tbl_ent)) 2742 return -EINVAL; 2743 } 2744 switch (tbl->tbl_opcode) { 2745 case BNXT_ULP_GENERIC_TBL_OPC_READ: 2746 if (gen_tbl_list->hash_tbl) { 2747 if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND) 2748 break; /* nothing to be done , no entry */ 2749 } 2750 2751 /* check the reference count */ 2752 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { 2753 g = &gen_tbl_ent; 2754 /* Scan ident list and create the result blob*/ 2755 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2756 g->byte_data, 2757 g->byte_data_size, 2758 g->byte_order); 2759 if (rc) { 2760 BNXT_TF_DBG(ERR, 2761 "Failed to scan ident list\n"); 2762 return -EINVAL; 2763 } 2764 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) { 2765 /* increment the reference count */ 2766 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); 2767 } 2768 2769 /* it is a hit */ 2770 gen_tbl_miss = 0; 2771 fdb_write = 1; 2772 } 2773 break; 2774 case BNXT_ULP_GENERIC_TBL_OPC_WRITE: 2775 if (gen_tbl_list->hash_tbl) { 2776 rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list, 2777 &hash_entry, 2778 &gen_tbl_ent); 2779 if (rc) 2780 return rc; 2781 /* store the hash index in the fdb */ 2782 key_index = hash_entry.hash_index; 2783 } 2784 /* check the reference count */ 2785 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { 2786 /* a hit then error */ 2787 BNXT_TF_DBG(ERR, "generic entry already present\n"); 2788 return -EINVAL; /* success */ 2789 } 2790 2791 /* Initialize the blob data */ 2792 if (!ulp_blob_init(&data, tbl->result_bit_size, 2793 gen_tbl_ent.byte_order)) { 2794 BNXT_TF_DBG(ERR, "Failed initial index table blob\n"); 2795 return -EINVAL; 2796 } 2797 2798 /* Get the result fields list */ 2799 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 2800 "Gen tbl Result"); 2801 if (rc) { 2802 BNXT_TF_DBG(ERR, "Failed to build the result blob\n"); 2803 return rc; 2804 } 2805 byte_data = ulp_blob_data_get(&data, &tmplen); 2806 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent, 2807 tmplen, byte_data, 2808 ULP_BITS_2_BYTE(tmplen)); 2809 if (rc) { 2810 BNXT_TF_DBG(ERR, "Failed to write generic table\n"); 2811 return -EINVAL; 2812 } 2813 2814 /* increment the reference count */ 2815 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent); 2816 fdb_write = 1; 2817 parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index; 2818 break; 2819 default: 2820 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode); 2821 return -EINVAL; 2822 } 2823 2824 /* Set the generic entry hit */ 2825 rc = ulp_regfile_write(parms->regfile, 2826 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, 2827 tfp_cpu_to_be_64(gen_tbl_miss)); 2828 if (rc) { 2829 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n", 2830 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); 2831 return -EIO; 2832 } 2833 2834 /* add the entry to the flow database */ 2835 if (fdb_write) { 2836 memset(&fid_parms, 0, sizeof(fid_parms)); 2837 fid_parms.direction = tbl->direction; 2838 fid_parms.resource_func = tbl->resource_func; 2839 fid_parms.resource_sub_type = tbl->resource_sub_type; 2840 fid_parms.resource_hndl = key_index; 2841 fid_parms.critical_resource = tbl->critical_resource; 2842 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session); 2843 2844 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2845 if (rc) 2846 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc); 2847 } 2848 return rc; 2849 } 2850 2851 static int32_t 2852 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2853 struct bnxt_ulp_mapper_tbl_info *tbl) 2854 { 2855 int32_t rc = 0; 2856 2857 /* process the fdb opcode for alloc push */ 2858 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) { 2859 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl); 2860 if (rc) { 2861 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n"); 2862 return rc; 2863 } 2864 } 2865 return rc; 2866 } 2867 2868 static int32_t 2869 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 2870 struct bnxt_ulp_mapper_data *mapper_data) 2871 { 2872 struct bnxt_ulp_glb_resource_info *glb_res; 2873 uint32_t num_glb_res_ids, idx, dev_id; 2874 uint8_t app_id; 2875 int32_t rc = 0; 2876 2877 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids); 2878 if (!glb_res || !num_glb_res_ids) { 2879 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 2880 return -EINVAL; 2881 } 2882 2883 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 2884 if (rc) { 2885 BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n", 2886 rc); 2887 return rc; 2888 } 2889 2890 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 2891 if (rc) { 2892 BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n", 2893 rc); 2894 return rc; 2895 } 2896 2897 /* Iterate the global resources and process each one */ 2898 for (idx = 0; idx < num_glb_res_ids; idx++) { 2899 if (dev_id != glb_res[idx].device_id || 2900 glb_res[idx].app_id != app_id) 2901 continue; 2902 switch (glb_res[idx].resource_func) { 2903 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2904 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 2905 mapper_data, 2906 &glb_res[idx]); 2907 break; 2908 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2909 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 2910 mapper_data, 2911 &glb_res[idx]); 2912 break; 2913 default: 2914 BNXT_TF_DBG(ERR, "Global resource %x not supported\n", 2915 glb_res[idx].resource_func); 2916 rc = -EINVAL; 2917 break; 2918 } 2919 if (rc) 2920 return rc; 2921 } 2922 return rc; 2923 } 2924 2925 /* 2926 * Iterate over the shared resources assigned during tf_open_session and store 2927 * them in the global regfile with the shared flag. 2928 */ 2929 static int32_t 2930 ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 2931 struct bnxt_ulp_mapper_data *mapper_data) 2932 { 2933 struct tf_get_shared_tbl_increment_parms iparms; 2934 struct bnxt_ulp_glb_resource_info *glb_res; 2935 struct tf_get_session_info_parms sparms; 2936 uint32_t num_entries, i, dev_id, res; 2937 struct tf_resource_info *res_info; 2938 uint32_t addend; 2939 uint64_t regval; 2940 enum tf_dir dir; 2941 int32_t rc = 0; 2942 struct tf *tfp; 2943 uint8_t app_id; 2944 2945 memset(&sparms, 0, sizeof(sparms)); 2946 glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries); 2947 if (!glb_res || !num_entries) { 2948 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 2949 return -EINVAL; 2950 } 2951 tfp = bnxt_ulp_cntxt_shared_tfp_get(ulp_ctx); 2952 if (!tfp) { 2953 BNXT_TF_DBG(ERR, "Failed to get tfp for app global init"); 2954 return -EINVAL; 2955 } 2956 /* 2957 * Retrieve the resources that were assigned during the shared session 2958 * creation. 2959 */ 2960 rc = tf_get_session_info(tfp, &sparms); 2961 if (rc) { 2962 BNXT_TF_DBG(ERR, "Failed to get session info (%d)\n", rc); 2963 return rc; 2964 } 2965 2966 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 2967 if (rc) { 2968 BNXT_TF_DBG(ERR, "Failed to get the app id in glb init (%d).\n", 2969 rc); 2970 return rc; 2971 } 2972 2973 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 2974 if (rc) { 2975 BNXT_TF_DBG(ERR, "Failed to get dev id for app glb init (%d)\n", 2976 rc); 2977 return rc; 2978 } 2979 2980 /* Store all the app global resources */ 2981 for (i = 0; i < num_entries; i++) { 2982 if (dev_id != glb_res[i].device_id || 2983 app_id != glb_res[i].app_id) 2984 continue; 2985 dir = glb_res[i].direction; 2986 res = glb_res[i].resource_type; 2987 addend = 1; 2988 2989 switch (glb_res[i].resource_func) { 2990 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 2991 res_info = &sparms.session_info.ident[dir].info[res]; 2992 break; 2993 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 2994 /* 2995 * Tables may have various strides for the allocations. 2996 * Need to account. 2997 */ 2998 memset(&iparms, 0, sizeof(iparms)); 2999 iparms.dir = dir; 3000 iparms.type = res; 3001 rc = tf_get_shared_tbl_increment(tfp, &iparms); 3002 if (rc) { 3003 BNXT_TF_DBG(ERR, 3004 "Failed to get addend for %s[%s] rc=(%d)\n", 3005 tf_tbl_type_2_str(res), 3006 tf_dir_2_str(dir), rc); 3007 return rc; 3008 } 3009 addend = iparms.increment_cnt; 3010 res_info = &sparms.session_info.tbl[dir].info[res]; 3011 break; 3012 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 3013 res_info = &sparms.session_info.tcam[dir].info[res]; 3014 break; 3015 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 3016 res_info = &sparms.session_info.em[dir].info[res]; 3017 break; 3018 default: 3019 BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n", 3020 glb_res[i].resource_func); 3021 continue; 3022 } 3023 regval = tfp_cpu_to_be_64((uint64_t)res_info->start); 3024 res_info->start += addend; 3025 /* 3026 * All resources written to the global regfile are shared for 3027 * this function. 3028 */ 3029 rc = ulp_mapper_glb_resource_write(mapper_data, &glb_res[i], 3030 regval, true); 3031 if (rc) 3032 return rc; 3033 } 3034 3035 return rc; 3036 } 3037 3038 /* 3039 * Common conditional opcode process routine that is used for both the template 3040 * rejection and table conditional execution. 3041 */ 3042 static int32_t 3043 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms, 3044 enum bnxt_ulp_cond_opc opc, 3045 uint32_t operand, 3046 int32_t *res) 3047 { 3048 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT; 3049 int32_t rc = 0; 3050 uint8_t bit; 3051 uint64_t regval; 3052 3053 switch (opc) { 3054 case BNXT_ULP_COND_OPC_CF_IS_SET: 3055 if (operand < BNXT_ULP_CF_IDX_LAST) { 3056 *res = ULP_COMP_FLD_IDX_RD(parms, operand); 3057 } else { 3058 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", 3059 operand); 3060 rc = -EINVAL; 3061 } 3062 break; 3063 case BNXT_ULP_COND_OPC_CF_NOT_SET: 3064 if (operand < BNXT_ULP_CF_IDX_LAST) { 3065 *res = !ULP_COMP_FLD_IDX_RD(parms, operand); 3066 } else { 3067 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n", 3068 operand); 3069 rc = -EINVAL; 3070 } 3071 break; 3072 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET: 3073 if (operand < BNXT_ULP_ACT_BIT_LAST) { 3074 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits, 3075 operand); 3076 } else { 3077 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", 3078 operand); 3079 rc = -EINVAL; 3080 } 3081 break; 3082 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET: 3083 if (operand < BNXT_ULP_ACT_BIT_LAST) { 3084 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits, 3085 operand); 3086 } else { 3087 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n", 3088 operand); 3089 rc = -EINVAL; 3090 } 3091 break; 3092 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET: 3093 if (operand < BNXT_ULP_HDR_BIT_LAST) { 3094 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 3095 operand); 3096 } else { 3097 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 3098 operand); 3099 rc = -EINVAL; 3100 } 3101 break; 3102 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET: 3103 if (operand < BNXT_ULP_HDR_BIT_LAST) { 3104 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 3105 operand); 3106 } else { 3107 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n", 3108 operand); 3109 rc = -EINVAL; 3110 } 3111 break; 3112 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET: 3113 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3114 if (rc) { 3115 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 3116 operand); 3117 return -EINVAL; 3118 } 3119 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 3120 break; 3121 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET: 3122 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3123 if (rc) { 3124 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 3125 operand); 3126 return -EINVAL; 3127 } 3128 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 3129 break; 3130 case BNXT_ULP_COND_OPC_RF_IS_SET: 3131 if (!ulp_regfile_read(parms->regfile, operand, ®val)) { 3132 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); 3133 return -EINVAL; 3134 } 3135 *res = regval != 0; 3136 break; 3137 case BNXT_ULP_COND_OPC_RF_NOT_SET: 3138 if (!ulp_regfile_read(parms->regfile, operand, ®val)) { 3139 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand); 3140 return -EINVAL; 3141 } 3142 *res = regval == 0; 3143 break; 3144 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH: 3145 if (parms->flow_pattern_id == operand) { 3146 BNXT_TF_DBG(ERR, "field pattern match failed %x\n", 3147 parms->flow_pattern_id); 3148 return -EINVAL; 3149 } 3150 break; 3151 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH: 3152 if (parms->act_pattern_id == operand) { 3153 BNXT_TF_DBG(ERR, "act pattern match failed %x\n", 3154 parms->act_pattern_id); 3155 return -EINVAL; 3156 } 3157 break; 3158 case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET: 3159 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) { 3160 BNXT_TF_DBG(ERR, "Failed to get the mem type\n"); 3161 return -EINVAL; 3162 } 3163 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1; 3164 break; 3165 case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET: 3166 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) { 3167 BNXT_TF_DBG(ERR, "Failed to get the mem type\n"); 3168 return -EINVAL; 3169 } 3170 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0; 3171 break; 3172 default: 3173 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc); 3174 rc = -EINVAL; 3175 break; 3176 } 3177 return (rc); 3178 } 3179 3180 static int32_t 3181 ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms, 3182 enum tf_dir dir, 3183 enum bnxt_ulp_func_src func_src, 3184 uint16_t func_opr, 3185 uint64_t *result) 3186 { 3187 uint64_t regval; 3188 bool shared; 3189 3190 *result = false; 3191 switch (func_src) { 3192 case BNXT_ULP_FUNC_SRC_COMP_FIELD: 3193 if (func_opr >= BNXT_ULP_CF_IDX_LAST) { 3194 BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr); 3195 return -EINVAL; 3196 } 3197 *result = ULP_COMP_FLD_IDX_RD(parms, func_opr); 3198 break; 3199 case BNXT_ULP_FUNC_SRC_REGFILE: 3200 if (!ulp_regfile_read(parms->regfile, func_opr, ®val)) { 3201 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr); 3202 return -EINVAL; 3203 } 3204 *result = tfp_be_to_cpu_64(regval); 3205 break; 3206 case BNXT_ULP_FUNC_SRC_GLB_REGFILE: 3207 if (ulp_mapper_glb_resource_read(parms->mapper_data, dir, 3208 func_opr, ®val, &shared)) { 3209 BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n", 3210 func_opr); 3211 return -EINVAL; 3212 } 3213 *result = tfp_be_to_cpu_64(regval); 3214 break; 3215 case BNXT_ULP_FUNC_SRC_CONST: 3216 *result = func_opr; 3217 break; 3218 default: 3219 BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src); 3220 return -EINVAL; 3221 } 3222 return 0; 3223 } 3224 3225 static int32_t 3226 ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms, 3227 struct bnxt_ulp_mapper_tbl_info *tbl) 3228 { 3229 struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info; 3230 uint64_t res = 0, res1 = 0, res2 = 0; 3231 int32_t rc = 0; 3232 uint32_t process_src1 = 0, process_src2 = 0; 3233 3234 /* determine which functional operands to compute */ 3235 switch (func_info->func_opc) { 3236 case BNXT_ULP_FUNC_OPC_NOP: 3237 return rc; 3238 case BNXT_ULP_FUNC_OPC_EQ: 3239 case BNXT_ULP_FUNC_OPC_NE: 3240 case BNXT_ULP_FUNC_OPC_GE: 3241 case BNXT_ULP_FUNC_OPC_GT: 3242 case BNXT_ULP_FUNC_OPC_LE: 3243 case BNXT_ULP_FUNC_OPC_LT: 3244 process_src1 = 1; 3245 process_src2 = 1; 3246 break; 3247 case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: 3248 process_src1 = 1; 3249 break; 3250 default: 3251 break; 3252 } 3253 3254 if (process_src1) { 3255 rc = ulp_mapper_func_opr_compute(parms, tbl->direction, 3256 func_info->func_src1, 3257 func_info->func_opr1, &res1); 3258 if (rc) 3259 return rc; 3260 } 3261 3262 if (process_src2) { 3263 rc = ulp_mapper_func_opr_compute(parms, tbl->direction, 3264 func_info->func_src2, 3265 func_info->func_opr2, &res2); 3266 if (rc) 3267 return rc; 3268 } 3269 3270 /* perform the functional opcode operations */ 3271 switch (func_info->func_opc) { 3272 case BNXT_ULP_FUNC_OPC_EQ: 3273 if (res1 == res2) 3274 res = 1; 3275 break; 3276 case BNXT_ULP_FUNC_OPC_NE: 3277 if (res1 != res2) 3278 res = 1; 3279 break; 3280 case BNXT_ULP_FUNC_OPC_GE: 3281 if (res1 >= res2) 3282 res = 1; 3283 break; 3284 case BNXT_ULP_FUNC_OPC_GT: 3285 if (res1 > res2) 3286 res = 1; 3287 break; 3288 case BNXT_ULP_FUNC_OPC_LE: 3289 if (res1 <= res2) 3290 res = 1; 3291 break; 3292 case BNXT_ULP_FUNC_OPC_LT: 3293 if (res1 < res2) 3294 res = 1; 3295 break; 3296 case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: 3297 res = res1; 3298 break; 3299 case BNXT_ULP_FUNC_OPC_RSS_CONFIG: 3300 /* apply the rss config using pmd method */ 3301 return bnxt_rss_config_action_apply(parms); 3302 case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR: 3303 rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res); 3304 if (rc) 3305 return -EINVAL; 3306 res = tfp_be_to_cpu_64(res); 3307 break; 3308 default: 3309 BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc); 3310 return -EINVAL; 3311 } 3312 if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr, 3313 tfp_cpu_to_be_64(res))) { 3314 BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n", 3315 func_info->func_dst_opr); 3316 return -EINVAL; 3317 } 3318 3319 return rc; 3320 } 3321 3322 3323 /* 3324 * Processes a list of conditions and returns both a status and result of the 3325 * list. The status must be checked prior to verifying the result. 3326 * 3327 * returns 0 for success, negative on failure 3328 * returns res = 1 for true, res = 0 for false. 3329 */ 3330 static int32_t 3331 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms, 3332 enum bnxt_ulp_cond_list_opc list_opc, 3333 struct bnxt_ulp_mapper_cond_info *list, 3334 uint32_t num, 3335 int32_t *res) 3336 { 3337 uint32_t i; 3338 int32_t rc = 0, trc = 0; 3339 3340 switch (list_opc) { 3341 case BNXT_ULP_COND_LIST_OPC_AND: 3342 /* AND Defaults to true. */ 3343 *res = 1; 3344 break; 3345 case BNXT_ULP_COND_LIST_OPC_OR: 3346 /* OR Defaults to false. */ 3347 *res = 0; 3348 break; 3349 case BNXT_ULP_COND_LIST_OPC_TRUE: 3350 *res = 1; 3351 return rc; 3352 case BNXT_ULP_COND_LIST_OPC_FALSE: 3353 *res = 0; 3354 return rc; 3355 default: 3356 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n", 3357 list_opc); 3358 *res = 0; 3359 return -EINVAL; 3360 } 3361 3362 for (i = 0; i < num; i++) { 3363 rc = ulp_mapper_cond_opc_process(parms, 3364 list[i].cond_opcode, 3365 list[i].cond_operand, 3366 &trc); 3367 if (rc) 3368 return rc; 3369 3370 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) { 3371 /* early return if result is ever zero */ 3372 if (!trc) { 3373 *res = trc; 3374 return rc; 3375 } 3376 } else { 3377 /* early return if result is ever non-zero */ 3378 if (trc) { 3379 *res = trc; 3380 return rc; 3381 } 3382 } 3383 } 3384 3385 return rc; 3386 } 3387 3388 /* 3389 * Processes conflict resolution and returns both a status and result. 3390 * The status must be checked prior to verifying the result. 3391 * 3392 * returns 0 for success, negative on failure 3393 * returns res = 1 for true, res = 0 for false. 3394 */ 3395 static int32_t 3396 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms, 3397 struct bnxt_ulp_mapper_tbl_info *tbl, 3398 int32_t *res) 3399 { 3400 int32_t rc = 0; 3401 uint64_t regval; 3402 uint64_t comp_sig; 3403 3404 *res = 0; 3405 switch (tbl->accept_opcode) { 3406 case BNXT_ULP_ACCEPT_OPC_ALWAYS: 3407 *res = 1; 3408 break; 3409 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH: 3410 /* perform the signature validation*/ 3411 if (tbl->resource_func == 3412 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) { 3413 /* Perform the check that generic table is hit or not */ 3414 if (!ulp_regfile_read(parms->regfile, 3415 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, 3416 ®val)) { 3417 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 3418 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); 3419 return -EINVAL; 3420 } 3421 if (regval) { 3422 /* not a hit so no need to check flow sign*/ 3423 *res = 1; 3424 return rc; 3425 } 3426 } 3427 /* compare the new flow signature against stored one */ 3428 if (!ulp_regfile_read(parms->regfile, 3429 BNXT_ULP_RF_IDX_FLOW_SIG_ID, 3430 ®val)) { 3431 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 3432 BNXT_ULP_RF_IDX_FLOW_SIG_ID); 3433 return -EINVAL; 3434 } 3435 comp_sig = ULP_COMP_FLD_IDX_RD(parms, 3436 BNXT_ULP_CF_IDX_FLOW_SIG_ID); 3437 regval = tfp_be_to_cpu_64(regval); 3438 if (comp_sig == regval) 3439 *res = 1; 3440 else 3441 BNXT_TF_DBG(ERR, "failed signature match 0x%016" 3442 PRIX64 ":%x\n", comp_sig, (uint32_t)regval); 3443 break; 3444 default: 3445 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n", 3446 tbl->accept_opcode); 3447 return -EINVAL; 3448 } 3449 return rc; 3450 } 3451 3452 static int32_t 3453 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid) 3454 { 3455 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL; 3456 enum bnxt_ulp_cond_list_opc cond_opc; 3457 struct bnxt_ulp_mapper_tbl_info *tbls; 3458 struct bnxt_ulp_mapper_tbl_info *tbl; 3459 uint32_t num_tbls, tbl_idx, num_cond_tbls; 3460 int32_t rc = -EINVAL, cond_rc = 0; 3461 int32_t cond_goto = 1; 3462 3463 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid, 3464 &num_cond_tbls, 3465 &cond_opc); 3466 /* 3467 * Process the reject list if exists, otherwise assume that the 3468 * template is allowed. 3469 */ 3470 if (cond_tbls && num_cond_tbls) { 3471 rc = ulp_mapper_cond_opc_list_process(parms, 3472 cond_opc, 3473 cond_tbls, 3474 num_cond_tbls, 3475 &cond_rc); 3476 if (rc) 3477 return rc; 3478 3479 /* Reject the template if True */ 3480 if (cond_rc) { 3481 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n", 3482 ulp_mapper_tmpl_name_str(parms->tmpl_type), 3483 tid); 3484 return -EINVAL; 3485 } 3486 } 3487 3488 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls); 3489 if (!tbls || !num_tbls) { 3490 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n", 3491 ulp_mapper_tmpl_name_str(parms->tmpl_type), 3492 parms->dev_id, tid); 3493 return -EINVAL; 3494 } 3495 3496 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) { 3497 tbl = &tbls[tbl_idx]; 3498 cond_goto = tbl->execute_info.cond_true_goto; 3499 /* Process the conditional func code opcodes */ 3500 if (ulp_mapper_func_info_process(parms, tbl)) { 3501 BNXT_TF_DBG(ERR, "Failed to process cond update\n"); 3502 rc = -EINVAL; 3503 goto error; 3504 } 3505 3506 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl, 3507 &num_cond_tbls, 3508 &cond_opc); 3509 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc, 3510 cond_tbls, num_cond_tbls, 3511 &cond_rc); 3512 if (rc) { 3513 BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n", 3514 rc); 3515 goto error; 3516 } 3517 /* Skip the table if False */ 3518 if (!cond_rc) { 3519 cond_goto = tbl->execute_info.cond_false_goto; 3520 goto next_iteration; 3521 } 3522 3523 switch (tbl->resource_func) { 3524 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 3525 rc = ulp_mapper_tcam_tbl_process(parms, tbl); 3526 break; 3527 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 3528 rc = ulp_mapper_em_tbl_process(parms, tbl); 3529 break; 3530 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 3531 rc = ulp_mapper_index_tbl_process(parms, tbl); 3532 break; 3533 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: 3534 rc = ulp_mapper_if_tbl_process(parms, tbl); 3535 break; 3536 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 3537 rc = ulp_mapper_gen_tbl_process(parms, tbl); 3538 break; 3539 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE: 3540 rc = ulp_mapper_ctrl_tbl_process(parms, tbl); 3541 break; 3542 case BNXT_ULP_RESOURCE_FUNC_INVALID: 3543 rc = 0; 3544 break; 3545 default: 3546 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n", 3547 tbl->resource_func); 3548 rc = -EINVAL; 3549 goto error; 3550 } 3551 3552 if (rc) { 3553 BNXT_TF_DBG(ERR, "Resource type %d failed\n", 3554 tbl->resource_func); 3555 goto error; 3556 } 3557 3558 /* perform the post table process */ 3559 rc = ulp_mapper_conflict_resolution_process(parms, tbl, 3560 &cond_rc); 3561 if (rc || !cond_rc) { 3562 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n"); 3563 rc = -EINVAL; 3564 goto error; 3565 } 3566 next_iteration: 3567 if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) { 3568 BNXT_TF_DBG(ERR, "reject the flow\n"); 3569 rc = -EINVAL; 3570 goto error; 3571 } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) { 3572 uint32_t rf_idx; 3573 uint64_t regval; 3574 3575 /* least significant 16 bits from reg_file index */ 3576 rf_idx = (uint32_t)(cond_goto & 0xFFFF); 3577 if (!ulp_regfile_read(parms->regfile, rf_idx, 3578 ®val)) { 3579 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", 3580 rf_idx); 3581 rc = -EINVAL; 3582 goto error; 3583 } 3584 cond_goto = (int32_t)regval; 3585 } 3586 3587 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) { 3588 BNXT_TF_DBG(ERR, "invalid conditional goto %d\n", 3589 cond_goto); 3590 goto error; 3591 } 3592 tbl_idx += cond_goto; 3593 } 3594 3595 return rc; 3596 error: 3597 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n", 3598 ulp_mapper_tmpl_name_str(parms->tmpl_type), 3599 parms->dev_id, tid); 3600 return rc; 3601 } 3602 3603 static int32_t 3604 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 3605 uint32_t fid, 3606 struct ulp_flow_db_res_params *res) 3607 { 3608 struct tf *tfp; 3609 int32_t rc = 0; 3610 3611 if (!res || !ulp) { 3612 BNXT_TF_DBG(ERR, "Unable to free resource\n "); 3613 return -EINVAL; 3614 } 3615 if (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION) 3616 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_YES); 3617 else 3618 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_NO); 3619 if (!tfp) { 3620 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n"); 3621 return -EINVAL; 3622 } 3623 3624 switch (res->resource_func) { 3625 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 3626 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res); 3627 break; 3628 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 3629 rc = ulp_mapper_em_entry_free(ulp, tfp, res); 3630 break; 3631 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 3632 rc = ulp_mapper_index_entry_free(ulp, tfp, res); 3633 break; 3634 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 3635 rc = ulp_mapper_ident_free(ulp, tfp, res); 3636 break; 3637 case BNXT_ULP_RESOURCE_FUNC_HW_FID: 3638 rc = ulp_mapper_mark_free(ulp, res); 3639 break; 3640 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW: 3641 rc = ulp_mapper_parent_flow_free(ulp, fid, res); 3642 break; 3643 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW: 3644 rc = ulp_mapper_child_flow_free(ulp, fid, res); 3645 break; 3646 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 3647 rc = ulp_mapper_gen_tbl_res_free(ulp, res); 3648 break; 3649 default: 3650 break; 3651 } 3652 3653 return rc; 3654 } 3655 3656 int32_t 3657 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, 3658 enum bnxt_ulp_fdb_type flow_type, 3659 uint32_t fid) 3660 { 3661 struct ulp_flow_db_res_params res_parms = { 0 }; 3662 int32_t rc, trc; 3663 3664 if (!ulp_ctx) { 3665 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 3666 return -EINVAL; 3667 } 3668 3669 /* 3670 * Set the critical resource on the first resource del, then iterate 3671 * while status is good 3672 */ 3673 if (flow_type != BNXT_ULP_FDB_TYPE_RID) 3674 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; 3675 3676 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms); 3677 3678 if (rc) { 3679 /* 3680 * This is unexpected on the first call to resource del. 3681 * It likely means that the flow did not exist in the flow db. 3682 */ 3683 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", 3684 flow_type, fid, rc); 3685 return rc; 3686 } 3687 3688 while (!rc) { 3689 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms); 3690 if (trc) 3691 /* 3692 * On fail, we still need to attempt to free the 3693 * remaining resources. Don't return 3694 */ 3695 BNXT_TF_DBG(ERR, 3696 "Flow[%d][0x%x] Res[%d][0x%016" PRIX64 3697 "] failed rc=%d.\n", 3698 flow_type, fid, res_parms.resource_func, 3699 res_parms.resource_hndl, trc); 3700 3701 /* All subsequent call require the non-critical_resource */ 3702 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 3703 3704 rc = ulp_flow_db_resource_del(ulp_ctx, 3705 flow_type, 3706 fid, 3707 &res_parms); 3708 } 3709 3710 /* Free the Flow ID since we've removed all resources */ 3711 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid); 3712 3713 return rc; 3714 } 3715 3716 static void 3717 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, 3718 struct bnxt_ulp_mapper_data *mapper_data) 3719 { 3720 struct bnxt_ulp_mapper_glb_resource_entry *ent; 3721 struct ulp_flow_db_res_params res; 3722 uint32_t dir, idx; 3723 3724 /* Iterate the global resources and process each one */ 3725 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { 3726 for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) { 3727 ent = &mapper_data->glb_res_tbl[dir][idx]; 3728 if (ent->resource_func == 3729 BNXT_ULP_RESOURCE_FUNC_INVALID || 3730 ent->shared) 3731 continue; 3732 memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); 3733 res.resource_func = ent->resource_func; 3734 res.direction = dir; 3735 res.resource_type = ent->resource_type; 3736 /*convert it from BE to cpu */ 3737 res.resource_hndl = 3738 tfp_be_to_cpu_64(ent->resource_hndl); 3739 ulp_mapper_resource_free(ulp_ctx, 0, &res); 3740 } 3741 } 3742 } 3743 3744 int32_t 3745 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, 3746 enum bnxt_ulp_fdb_type flow_type, 3747 uint32_t fid) 3748 { 3749 int32_t rc; 3750 3751 if (!ulp_ctx) { 3752 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n"); 3753 return -EINVAL; 3754 } 3755 3756 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid); 3757 return rc; 3758 } 3759 3760 /* Function to handle the mapping of the Flow to be compatible 3761 * with the underlying hardware. 3762 */ 3763 int32_t 3764 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 3765 struct bnxt_ulp_mapper_create_parms *cparms) 3766 { 3767 struct bnxt_ulp_mapper_parms parms; 3768 struct ulp_regfile regfile; 3769 int32_t rc = 0, trc; 3770 3771 if (!ulp_ctx || !cparms) 3772 return -EINVAL; 3773 3774 /* Initialize the parms structure */ 3775 memset(&parms, 0, sizeof(parms)); 3776 parms.act_prop = cparms->act_prop; 3777 parms.act_bitmap = cparms->act; 3778 parms.hdr_bitmap = cparms->hdr_bitmap; 3779 parms.regfile = ®file; 3780 parms.hdr_field = cparms->hdr_field; 3781 parms.fld_bitmap = cparms->fld_bitmap; 3782 parms.comp_fld = cparms->comp_fld; 3783 parms.ulp_ctx = ulp_ctx; 3784 parms.act_tid = cparms->act_tid; 3785 parms.class_tid = cparms->class_tid; 3786 parms.flow_type = cparms->flow_type; 3787 parms.parent_flow = cparms->parent_flow; 3788 parms.parent_fid = cparms->parent_fid; 3789 parms.fid = cparms->flow_id; 3790 parms.tun_idx = cparms->tun_idx; 3791 parms.app_priority = cparms->app_priority; 3792 parms.flow_pattern_id = cparms->flow_pattern_id; 3793 parms.act_pattern_id = cparms->act_pattern_id; 3794 parms.app_id = cparms->app_id; 3795 parms.port_id = cparms->port_id; 3796 3797 /* Get the device id from the ulp context */ 3798 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) { 3799 BNXT_TF_DBG(ERR, "Invalid ulp context\n"); 3800 return -EINVAL; 3801 } 3802 3803 /* Get the device params, it will be used in later processing */ 3804 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id); 3805 if (!parms.device_params) { 3806 BNXT_TF_DBG(ERR, "No device parms for device id %d\n", 3807 parms.dev_id); 3808 return -EINVAL; 3809 } 3810 3811 /* 3812 * Get the mapper data for dynamic mapper data such as default 3813 * ids. 3814 */ 3815 parms.mapper_data = (struct bnxt_ulp_mapper_data *) 3816 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 3817 if (!parms.mapper_data) { 3818 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n"); 3819 return -EINVAL; 3820 } 3821 3822 /* initialize the registry file for further processing */ 3823 if (!ulp_regfile_init(parms.regfile)) { 3824 BNXT_TF_DBG(ERR, "regfile initialization failed.\n"); 3825 return -EINVAL; 3826 } 3827 3828 /* Process the action template list from the selected action table*/ 3829 if (parms.act_tid) { 3830 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION; 3831 /* Process the action template tables */ 3832 rc = ulp_mapper_tbls_process(&parms, parms.act_tid); 3833 if (rc) 3834 goto flow_error; 3835 cparms->shared_hndl = parms.shared_hndl; 3836 } 3837 3838 if (parms.class_tid) { 3839 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; 3840 3841 /* Process the class template tables.*/ 3842 rc = ulp_mapper_tbls_process(&parms, parms.class_tid); 3843 if (rc) 3844 goto flow_error; 3845 } 3846 3847 /* setup the parent-child details */ 3848 if (parms.parent_flow) { 3849 /* create a parent flow details */ 3850 rc = ulp_flow_db_parent_flow_create(&parms); 3851 if (rc) 3852 goto flow_error; 3853 } else if (parms.parent_fid) { 3854 /* create a child flow details */ 3855 rc = ulp_flow_db_child_flow_create(&parms); 3856 if (rc) 3857 goto flow_error; 3858 } 3859 3860 return rc; 3861 3862 flow_error: 3863 /* Free all resources that were allocated during flow creation */ 3864 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type, 3865 parms.fid); 3866 if (trc) 3867 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc); 3868 3869 return rc; 3870 } 3871 3872 int32_t 3873 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) 3874 { 3875 struct bnxt_ulp_mapper_data *data; 3876 struct tf *tfp; 3877 int32_t rc; 3878 3879 if (!ulp_ctx) 3880 return -EINVAL; 3881 3882 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 3883 if (!tfp) 3884 return -EINVAL; 3885 3886 data = rte_zmalloc("ulp_mapper_data", 3887 sizeof(struct bnxt_ulp_mapper_data), 0); 3888 if (!data) { 3889 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n"); 3890 return -ENOMEM; 3891 } 3892 3893 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) { 3894 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n"); 3895 /* Don't call deinit since the prof_func wasn't allocated. */ 3896 rte_free(data); 3897 return -ENOMEM; 3898 } 3899 3900 /* Allocate the global resource ids */ 3901 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); 3902 if (rc) { 3903 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n"); 3904 goto error; 3905 } 3906 3907 /* 3908 * Only initialize the app global resources if a shared session was 3909 * created. 3910 */ 3911 if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) { 3912 rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data); 3913 if (rc) { 3914 BNXT_TF_DBG(ERR, "Failed to init app glb resources\n"); 3915 goto error; 3916 } 3917 } 3918 3919 /* Allocate the generic table list */ 3920 rc = ulp_mapper_generic_tbl_list_init(data); 3921 if (rc) { 3922 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n"); 3923 goto error; 3924 } 3925 3926 return 0; 3927 error: 3928 /* Ignore the return code in favor of returning the original error. */ 3929 ulp_mapper_deinit(ulp_ctx); 3930 return rc; 3931 } 3932 3933 void 3934 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) 3935 { 3936 struct bnxt_ulp_mapper_data *data; 3937 struct tf *tfp; 3938 3939 if (!ulp_ctx) { 3940 BNXT_TF_DBG(ERR, 3941 "Failed to acquire ulp context, so data may not be released.\n"); 3942 return; 3943 } 3944 3945 data = (struct bnxt_ulp_mapper_data *) 3946 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 3947 if (!data) { 3948 /* Go ahead and return since there is no allocated data. */ 3949 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n"); 3950 return; 3951 } 3952 3953 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 3954 if (!tfp) { 3955 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n"); 3956 /* Free the mapper data regardless of errors. */ 3957 goto free_mapper_data; 3958 } 3959 3960 /* Free the global resource info table entries */ 3961 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); 3962 3963 free_mapper_data: 3964 /* Free the generic table */ 3965 (void)ulp_mapper_generic_tbl_list_deinit(data); 3966 3967 rte_free(data); 3968 /* Reset the data pointer within the ulp_ctx. */ 3969 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); 3970 } 3971