1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2023 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 "bnxt_ulp_utils.h" 15 #include "tfp.h" 16 #include "tf_ext_flow_handle.h" 17 #include "ulp_mark_mgr.h" 18 #include "ulp_mapper.h" 19 #include "ulp_flow_db.h" 20 #include "tf_util.h" 21 #include "ulp_template_db_tbl.h" 22 #include "ulp_port_db.h" 23 #include "ulp_ha_mgr.h" 24 #include "bnxt_tf_pmd_shim.h" 25 #ifdef TF_FLOW_SCALE_QUERY 26 #include "tf_resources.h" 27 #include "tfc_resources.h" 28 #endif /* TF_FLOW_SCALE_QUERY */ 29 30 static uint8_t mapper_fld_zeros[16] = { 0 }; 31 32 static uint8_t mapper_fld_ones[16] = { 33 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 34 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 35 }; 36 37 static uint8_t mapper_fld_one[16] = { 38 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 39 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 40 }; 41 42 static int32_t 43 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms, 44 struct bnxt_ulp_mapper_cond_list_info *info, 45 int32_t *res); 46 47 static const struct ulp_mapper_core_ops * 48 bnxt_ulp_mapper_ops_get(struct bnxt *bp) 49 { 50 int32_t rc; 51 enum bnxt_ulp_device_id dev_id; 52 const struct ulp_mapper_core_ops *func_ops; 53 54 rc = bnxt_ulp_devid_get(bp, &dev_id); 55 if (unlikely(rc)) 56 return NULL; 57 58 switch (dev_id) { 59 case BNXT_ULP_DEVICE_ID_THOR2: 60 func_ops = &ulp_mapper_tfc_core_ops; 61 break; 62 case BNXT_ULP_DEVICE_ID_THOR: 63 case BNXT_ULP_DEVICE_ID_STINGRAY: 64 case BNXT_ULP_DEVICE_ID_WH_PLUS: 65 func_ops = &ulp_mapper_tf_core_ops; 66 break; 67 default: 68 func_ops = NULL; 69 break; 70 } 71 return func_ops; 72 } 73 74 static const struct ulp_mapper_core_ops * 75 ulp_mapper_data_oper_get(struct bnxt_ulp_context *ulp_ctx) 76 { 77 struct bnxt_ulp_mapper_data *m_data; 78 79 m_data = (struct bnxt_ulp_mapper_data *)ulp_ctx->cfg_data->mapper_data; 80 return m_data->mapper_oper; 81 } 82 83 static const char * 84 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type) 85 { 86 switch (tmpl_type) { 87 case BNXT_ULP_TEMPLATE_TYPE_CLASS: 88 return "class"; 89 case BNXT_ULP_TEMPLATE_TYPE_ACTION: 90 return "action"; 91 default: 92 return "invalid template type"; 93 } 94 } 95 96 static struct bnxt_ulp_glb_resource_info * 97 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries) 98 { 99 if (unlikely(!num_entries)) 100 return NULL; 101 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ; 102 return ulp_glb_resource_tbl; 103 } 104 105 /* 106 * Read the global resource from the mapper global resource list 107 * 108 * The regval is always returned in big-endian. 109 * 110 * returns 0 on success 111 */ 112 int32_t 113 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data, 114 enum tf_dir dir, 115 uint16_t idx, 116 uint64_t *regval, 117 bool *shared) 118 { 119 if (unlikely(!mapper_data || !regval || !shared || 120 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)) 121 return -EINVAL; 122 123 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl; 124 *shared = mapper_data->glb_res_tbl[dir][idx].shared; 125 return 0; 126 } 127 128 /* 129 * Write a global resource to the mapper global resource list 130 * 131 * The regval value must be in big-endian. 132 * 133 * return 0 on success. 134 */ 135 int32_t 136 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data, 137 struct bnxt_ulp_glb_resource_info *res, 138 uint64_t regval, bool shared) 139 { 140 struct bnxt_ulp_mapper_glb_resource_entry *ent; 141 142 /* validate the arguments */ 143 if (unlikely(!data || res->direction >= TF_DIR_MAX || 144 res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)) 145 return -EINVAL; 146 147 /* write to the mapper data */ 148 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index]; 149 ent->resource_func = res->resource_func; 150 ent->resource_type = res->resource_type; 151 ent->resource_hndl = regval; 152 ent->shared = shared; 153 return 0; 154 } 155 156 /* 157 * Internal function to allocate identity resource and store it in mapper data. 158 * 159 * returns 0 on success 160 */ 161 int32_t 162 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx, 163 struct bnxt_ulp_mapper_data *mapper_data, 164 struct bnxt_ulp_glb_resource_info *glb_res, 165 bool shared) 166 { 167 const struct ulp_mapper_core_ops *op = mapper_data->mapper_oper; 168 uint32_t session_type = BNXT_ULP_SESSION_TYPE_DEFAULT; 169 struct ulp_flow_db_res_params res = { 0 }; 170 uint64_t regval, id = 0; 171 int32_t rc = 0; 172 173 session_type = shared ? BNXT_ULP_SESSION_TYPE_SHARED : 174 BNXT_ULP_SESSION_TYPE_DEFAULT; 175 176 /* Global identifiers are tracked by session */ 177 rc = op->ulp_mapper_core_ident_alloc_process(ulp_ctx, 178 session_type, 179 glb_res->resource_type, 180 glb_res->direction, 181 CFA_TRACK_TYPE_SID, 182 &id); 183 if (unlikely(rc)) 184 return rc; 185 186 /* entries are stored as big-endian format */ 187 regval = tfp_cpu_to_be_64(id); 188 /* 189 * write to the mapper global resource 190 * Shared resources are never allocated through this method, so the 191 * shared flag is always false. 192 */ 193 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, shared); 194 if (unlikely(rc)) { 195 BNXT_DRV_DBG(ERR, "Failed to write to global resource id\n"); 196 /* Free the identifier when update failed */ 197 res.direction = glb_res->direction; 198 res.resource_type = glb_res->resource_type; 199 res.resource_hndl = id; 200 op->ulp_mapper_core_ident_free(ulp_ctx, &res); 201 return rc; 202 } 203 return rc; 204 } 205 206 /* 207 * Internal function to allocate index tbl resource and store it in mapper data. 208 * 209 * returns 0 on success 210 */ 211 int32_t 212 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx, 213 struct bnxt_ulp_mapper_data *mapper_data, 214 struct bnxt_ulp_glb_resource_info *glb_res, 215 bool shared) 216 { 217 const struct ulp_mapper_core_ops *op = mapper_data->mapper_oper; 218 uint32_t session_type = BNXT_ULP_SESSION_TYPE_DEFAULT; 219 struct ulp_flow_db_res_params res = { 0 }; 220 uint64_t regval, index = 0; 221 int32_t rc = 0; 222 223 session_type = shared ? BNXT_ULP_SESSION_TYPE_SHARED : 224 BNXT_ULP_SESSION_TYPE_DEFAULT; 225 226 op->ulp_mapper_core_index_tbl_alloc_process(ulp_ctx, session_type, 227 glb_res->resource_type, 228 glb_res->direction, &index); 229 230 /* entries are stored as big-endian format */ 231 regval = tfp_cpu_to_be_64((uint64_t)index); 232 /* 233 * write to the mapper global resource 234 * Shared resources are never allocated through this method, so the 235 * shared flag is always false. 236 */ 237 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, shared); 238 if (unlikely(rc)) { 239 BNXT_DRV_DBG(ERR, "Failed to write to global resource id\n"); 240 /* Free the index when update failed */ 241 res.direction = glb_res->direction; 242 res.resource_type = glb_res->resource_type; 243 res.resource_hndl = index; 244 rc = op->ulp_mapper_core_cmm_entry_free(ulp_ctx, &res, NULL); 245 return rc; 246 } 247 return rc; 248 } 249 250 static int32_t 251 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms, 252 uint32_t operand, 253 uint8_t *val) 254 { 255 uint32_t t_idx; 256 257 if (unlikely(operand >= BNXT_ULP_GLB_FIELD_TBL_SIZE)) { 258 BNXT_DRV_DBG(ERR, "Invalid hdr field index %x:%x\n", 259 parms->class_tid, operand); 260 *val = 0; 261 return -EINVAL; /* error */ 262 } 263 264 t_idx = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID); 265 *val = ulp_class_match_list[t_idx].field_list[operand]; 266 return 0; 267 } 268 269 /* 270 * Get the size of the action property for a given index. 271 * 272 * idx [in] The index for the action property 273 * 274 * returns the size of the action property. 275 */ 276 static uint32_t 277 ulp_mapper_act_prop_size_get(uint32_t idx) 278 { 279 if (unlikely(idx >= BNXT_ULP_ACT_PROP_IDX_LAST)) 280 return 0; 281 return ulp_act_prop_map_table[idx]; 282 } 283 284 static struct bnxt_ulp_mapper_cond_list_info * 285 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms, 286 uint32_t tid) 287 { 288 const struct bnxt_ulp_template_device_tbls *dev_tbls; 289 290 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 291 return &dev_tbls->tmpl_list[tid].reject_info; 292 } 293 294 static struct bnxt_ulp_mapper_cond_list_info * 295 ulp_mapper_cond_oper_list_get(struct bnxt_ulp_mapper_parms *mparms, 296 uint32_t idx) 297 { 298 const struct bnxt_ulp_template_device_tbls *dev_tbls; 299 300 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 301 if (unlikely(idx >= dev_tbls->cond_oper_list_size)) 302 return NULL; 303 return &dev_tbls->cond_oper_list[idx]; 304 } 305 306 static struct bnxt_ulp_mapper_cond_info * 307 ulp_mapper_tmpl_cond_list_get(struct bnxt_ulp_mapper_parms *mparms, 308 uint32_t idx) 309 { 310 const struct bnxt_ulp_template_device_tbls *dev_tbls; 311 312 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 313 if (unlikely(idx >= dev_tbls->cond_list_size)) 314 return NULL; 315 return &dev_tbls->cond_list[idx]; 316 } 317 318 /* 319 * Get a list of classifier tables that implement the flow 320 * Gets a device dependent list of tables that implement the class template id 321 * 322 * mparms [in] The mappers parms with data related to the flow. 323 * 324 * tid [in] The template id that matches the flow 325 * 326 * num_tbls [out] The number of classifier tables in the returned array 327 * 328 * returns An array of classifier tables to implement the flow, or NULL on 329 * error 330 */ 331 static struct bnxt_ulp_mapper_tbl_info * 332 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms, 333 uint32_t tid, 334 uint32_t *num_tbls) 335 { 336 uint32_t idx; 337 const struct bnxt_ulp_template_device_tbls *dev_tbls; 338 339 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 340 341 idx = dev_tbls->tmpl_list[tid].start_tbl_idx; 342 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls; 343 344 return &dev_tbls->tbl_list[idx]; 345 } 346 347 /* 348 * Get the list of key fields that implement the flow. 349 * 350 * mparms [in] The mapper parms with information about the flow 351 * 352 * tbl [in] A single table instance to get the key fields from 353 * 354 * num_flds [out] The number of key fields in the returned array 355 * 356 * Returns array of Key fields, or NULL on error. 357 */ 358 struct bnxt_ulp_mapper_key_info * 359 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms, 360 struct bnxt_ulp_mapper_tbl_info *tbl, 361 uint32_t *num_flds) 362 { 363 uint32_t idx; 364 const struct bnxt_ulp_template_device_tbls *dev_tbls; 365 366 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 367 if (unlikely(!dev_tbls->key_info_list)) { 368 *num_flds = 0; 369 return NULL; 370 } 371 372 idx = tbl->key_start_idx; 373 *num_flds = tbl->key_num_fields; 374 375 return &dev_tbls->key_info_list[idx]; 376 } 377 378 /* 379 * Get the list of partial key fields that implement the flow. 380 * 381 * mparms [in] The mapper parms with information about the flow 382 * 383 * tbl [in] A single table instance to get the key fields from 384 * 385 * Return number of partial fields.return 0 if no partial fields 386 */ 387 uint32_t 388 ulp_mapper_partial_key_fields_get(struct bnxt_ulp_mapper_parms *mparms, 389 struct bnxt_ulp_mapper_tbl_info *tbl) 390 { 391 const struct bnxt_ulp_template_device_tbls *dev_tbls; 392 393 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 394 if (!dev_tbls->key_info_list) 395 return 0; 396 return tbl->partial_key_num_fields; 397 } 398 399 /* 400 * Get the list of data fields that implement the flow. 401 * 402 * mparms [in] The mapper parms with information about the flow 403 * 404 * tbl [in] A single table instance to get the data fields from 405 * 406 * num_flds [out] The number of data fields in the returned array. 407 * 408 * num_encap_flds [out] The number of encap fields in the returned array. 409 * 410 * Returns array of data fields, or NULL on error. 411 */ 412 static struct bnxt_ulp_mapper_field_info * 413 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms, 414 struct bnxt_ulp_mapper_tbl_info *tbl, 415 uint32_t *num_flds, 416 uint32_t *num_encap_flds) 417 { 418 uint32_t idx; 419 const struct bnxt_ulp_template_device_tbls *dev_tbls; 420 421 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 422 if (unlikely(!dev_tbls->result_field_list)) { 423 *num_flds = 0; 424 *num_encap_flds = 0; 425 return NULL; 426 } 427 428 idx = tbl->result_start_idx; 429 *num_flds = tbl->result_num_fields; 430 *num_encap_flds = tbl->encap_num_fields; 431 432 return &dev_tbls->result_field_list[idx]; 433 } 434 435 /* 436 * Get the list of ident fields that implement the flow 437 * 438 * tbl [in] A single table instance to get the ident fields from 439 * 440 * num_flds [out] The number of ident fields in the returned array 441 * 442 * returns array of ident fields, or NULL on error 443 */ 444 static struct bnxt_ulp_mapper_ident_info * 445 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms, 446 struct bnxt_ulp_mapper_tbl_info *tbl, 447 uint32_t *num_flds) 448 { 449 uint32_t idx; 450 const struct bnxt_ulp_template_device_tbls *dev_tbls; 451 452 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 453 if (unlikely(!dev_tbls->ident_list)) { 454 *num_flds = 0; 455 return NULL; 456 } 457 458 idx = tbl->ident_start_idx; 459 *num_flds = tbl->ident_nums; 460 461 return &dev_tbls->ident_list[idx]; 462 } 463 464 static struct bnxt_ulp_mapper_field_info * 465 ulp_mapper_tmpl_key_ext_list_get(struct bnxt_ulp_mapper_parms *mparms, 466 uint32_t idx) 467 { 468 const struct bnxt_ulp_template_device_tbls *dev_tbls; 469 470 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type]; 471 if (unlikely(idx >= dev_tbls->key_ext_list_size)) 472 return NULL; 473 return &dev_tbls->key_ext_list[idx]; 474 } 475 476 static inline int32_t 477 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp, 478 struct ulp_flow_db_res_params *res) 479 { 480 return ulp_mark_db_mark_del(ulp, 481 res->resource_type, 482 res->resource_hndl); 483 } 484 485 static inline int32_t 486 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp, 487 uint32_t parent_fid, 488 struct ulp_flow_db_res_params *res) 489 { 490 uint32_t pc_idx; 491 492 pc_idx = (uint32_t)res->resource_hndl; 493 494 /* reset the child flow bitset*/ 495 if (unlikely(ulp_flow_db_pc_db_parent_flow_set(ulp, pc_idx, parent_fid, 0))) { 496 BNXT_DRV_DBG(ERR, "error in reset parent flow bitset %x:%x\n", 497 pc_idx, parent_fid); 498 return -EINVAL; 499 } 500 return 0; 501 } 502 503 static inline int32_t 504 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp, 505 uint32_t child_fid, 506 struct ulp_flow_db_res_params *res) 507 { 508 uint32_t pc_idx; 509 510 pc_idx = (uint32_t)res->resource_hndl; 511 512 /* reset the child flow bitset*/ 513 if (unlikely(ulp_flow_db_pc_db_child_flow_set(ulp, pc_idx, child_fid, 0))) { 514 BNXT_DRV_DBG(ERR, 515 "error in resetting child flow bitset %x:%x\n", 516 pc_idx, child_fid); 517 return -EINVAL; 518 } 519 return 0; 520 } 521 522 /* 523 * Process the flow database opcode alloc action. 524 * returns 0 on success 525 */ 526 static int32_t 527 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms, 528 struct bnxt_ulp_mapper_tbl_info *tbl) 529 { 530 uint32_t rid = 0; 531 uint64_t val64; 532 int32_t rc = 0; 533 534 /* allocate a new fid */ 535 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx, 536 BNXT_ULP_FDB_TYPE_RID, 537 0, &rid); 538 if (unlikely(rc)) { 539 BNXT_DRV_DBG(ERR, 540 "Unable to allocate flow table entry\n"); 541 return -EINVAL; 542 } 543 /* Store the allocated fid in regfile*/ 544 val64 = rid; 545 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand, 546 tfp_cpu_to_be_64(val64)); 547 if (unlikely(rc)) { 548 BNXT_DRV_DBG(ERR, "Write regfile[%d] failed\n", 549 tbl->fdb_operand); 550 ulp_flow_db_fid_free(parms->ulp_ctx, 551 BNXT_ULP_FDB_TYPE_RID, rid); 552 return -EINVAL; 553 } 554 /* save the rid into the parms in case a flow fails before pushing the 555 * rid into the fid 556 */ 557 parms->rid = rid; 558 return 0; 559 } 560 561 /* 562 * Process the flow database opcode action. 563 * returns 0 on success. 564 */ 565 int32_t 566 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms, 567 struct bnxt_ulp_mapper_tbl_info *tbl, 568 struct ulp_flow_db_res_params *fid_parms) 569 { 570 uint32_t push_fid; 571 uint64_t val64 = 0; 572 enum bnxt_ulp_fdb_type flow_type; 573 int32_t rc = 0; 574 575 switch (tbl->fdb_opcode) { 576 case BNXT_ULP_FDB_OPC_PUSH_FID: 577 push_fid = parms->flow_id; 578 flow_type = parms->flow_type; 579 break; 580 case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE: 581 /* get the fid from the regfile */ 582 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand, 583 &val64); 584 if (unlikely(rc)) { 585 BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n", 586 tbl->fdb_operand); 587 return -EINVAL; 588 } 589 /* Use the extracted fid to update the flow resource */ 590 push_fid = (uint32_t)tfp_be_to_cpu_64(val64); 591 flow_type = BNXT_ULP_FDB_TYPE_RID; 592 break; 593 case BNXT_ULP_FDB_OPC_PUSH_FID_SW_ONLY: 594 push_fid = parms->flow_id; 595 flow_type = parms->flow_type; 596 fid_parms->fdb_flags = ULP_FDB_FLAG_SW_ONLY; 597 break; 598 default: 599 return rc; /* Nothing to be done */ 600 } 601 602 /* Add the resource to the flow database */ 603 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type, 604 push_fid, fid_parms); 605 if (unlikely(rc)) 606 BNXT_DRV_DBG(ERR, "Failed to add res to flow %x rc = %d\n", 607 push_fid, rc); 608 609 return rc; 610 } 611 612 /* 613 * Process the flow database opcode action. 614 * returns 0 on success. 615 */ 616 int32_t 617 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms, 618 struct bnxt_ulp_mapper_tbl_info *tbl, 619 uint32_t *priority) 620 { 621 uint64_t regval = 0; 622 int32_t rc = 0; 623 624 switch (tbl->pri_opcode) { 625 case BNXT_ULP_PRI_OPC_NOT_USED: 626 *priority = bnxt_ulp_default_app_priority_get(parms->ulp_ctx); 627 break; 628 case BNXT_ULP_PRI_OPC_CONST: 629 *priority = tbl->pri_operand; 630 break; 631 case BNXT_ULP_PRI_OPC_APP_PRI: 632 *priority = parms->app_priority; 633 break; 634 case BNXT_ULP_PRI_OPC_APP_PRI_OR_CONST: 635 if (parms->app_priority) 636 *priority = parms->app_priority; 637 else 638 *priority = tbl->pri_operand; 639 break; 640 case BNXT_ULP_PRI_OPC_REGFILE: 641 if (unlikely(ulp_regfile_read(parms->regfile, tbl->pri_operand, 642 ®val))) { 643 BNXT_DRV_DBG(ERR, "regfile[%u] read oob\n", 644 tbl->pri_operand); 645 rc = -EINVAL; 646 } 647 *priority = (uint32_t)tfp_be_to_cpu_64(regval); 648 break; 649 case BNXT_ULP_PRI_OPC_COMP_FIELD: 650 if (likely(tbl->pri_operand < BNXT_ULP_CF_IDX_LAST)) { 651 regval = ULP_COMP_FLD_IDX_RD(parms, tbl->pri_operand); 652 *priority = regval; 653 } else { 654 BNXT_DRV_DBG(ERR, "comp field out of bounds %u\n", 655 tbl->pri_operand); 656 rc = -EINVAL; 657 } 658 break; 659 default: 660 BNXT_DRV_DBG(ERR, "Priority opcode not supported %d\n", 661 tbl->pri_opcode); 662 rc = -EINVAL; 663 break; 664 } 665 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 666 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 667 if (!rc) 668 BNXT_DRV_DBG(DEBUG, "Tcam priority = 0x%x\n", *priority); 669 #endif 670 #endif 671 return rc; 672 } 673 674 /* 675 * Process the identifier list in the given table. 676 * Extract the ident from the table entry and 677 * write it to the reg file. 678 * returns 0 on success. 679 */ 680 int32_t 681 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms, 682 struct bnxt_ulp_mapper_tbl_info *tbl, 683 uint8_t *byte_data, 684 uint32_t byte_data_size, 685 enum bnxt_ulp_byte_order byte_order) 686 { 687 struct bnxt_ulp_mapper_ident_info *idents; 688 uint32_t i, num_idents = 0; 689 uint64_t val64; 690 691 /* validate the null arguments */ 692 if (unlikely(!byte_data)) { 693 BNXT_DRV_DBG(ERR, "invalid argument\n"); 694 return -EINVAL; 695 } 696 697 /* Get the ident list and process each one */ 698 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 699 700 for (i = 0; i < num_idents; i++) { 701 /* check the size of the buffer for validation */ 702 if (unlikely((idents[i].ident_bit_pos + idents[i].ident_bit_size) > 703 ULP_BYTE_2_BITS(byte_data_size) || 704 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64)))) { 705 BNXT_DRV_DBG(ERR, "invalid offset or length %x:%x:%x\n", 706 idents[i].ident_bit_pos, 707 idents[i].ident_bit_size, 708 byte_data_size); 709 return -EINVAL; 710 } 711 val64 = 0; 712 if (byte_order == BNXT_ULP_BYTE_ORDER_LE) 713 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64, 714 sizeof(val64), 715 idents[i].ident_bit_pos, 716 idents[i].ident_bit_size); 717 else 718 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64, 719 idents[i].ident_bit_pos, 720 idents[i].ident_bit_size); 721 722 /* Write it to the regfile, val64 is already in big-endian*/ 723 if (unlikely(ulp_regfile_write(parms->regfile, 724 idents[i].regfile_idx, val64))) { 725 BNXT_DRV_DBG(ERR, "Regfile[%d] write failed.\n", 726 idents[i].regfile_idx); 727 return -EINVAL; 728 } 729 } 730 return 0; 731 } 732 733 /* 734 * Process the identifier instruction and either store it in the flow database 735 * or return it in the val (if not NULL) on success. If val is NULL, the 736 * identifier is to be stored in the flow database. 737 */ 738 static int32_t 739 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms, 740 struct bnxt_ulp_mapper_tbl_info *tbl, 741 struct bnxt_ulp_mapper_ident_info *ident, 742 uint16_t *val) 743 { 744 const struct ulp_mapper_core_ops *op = parms->mapper_data->mapper_oper; 745 struct ulp_flow_db_res_params fid_parms = { 0 }; 746 uint64_t id = 0; 747 int32_t idx; 748 int rc; 749 750 fid_parms.direction = tbl->direction; 751 fid_parms.resource_func = ident->resource_func; 752 fid_parms.resource_type = ident->ident_type; 753 fid_parms.critical_resource = tbl->critical_resource; 754 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 755 756 rc = op->ulp_mapper_core_ident_alloc_process(parms->ulp_ctx, 757 tbl->session_type, 758 ident->ident_type, 759 tbl->direction, 760 tbl->track_type, 761 &id); 762 if (unlikely(rc)) { 763 BNXT_DRV_DBG(ERR, "identifier process failed\n"); 764 return rc; 765 } 766 767 fid_parms.resource_hndl = id; 768 idx = ident->regfile_idx; 769 if (unlikely(ulp_regfile_write(parms->regfile, idx, tfp_cpu_to_be_64(id)))) { 770 BNXT_DRV_DBG(ERR, "Regfile[%d] write failed.\n", idx); 771 rc = -EINVAL; 772 /* Need to free the identifier, so goto error */ 773 goto error; 774 } 775 776 /* Link the resource to the flow in the flow db */ 777 if (!val) { 778 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 779 if (unlikely(rc)) { 780 BNXT_DRV_DBG(ERR, 781 "Failed to link res to flow rc = %d\n", 782 rc); 783 /* Need to free the identifier, so goto error */ 784 goto error; 785 } 786 } else { 787 *val = id; 788 } 789 return 0; 790 791 error: 792 /* Need to free the identifier */ 793 op->ulp_mapper_core_ident_free(parms->ulp_ctx, &fid_parms); 794 return rc; 795 } 796 797 static int32_t 798 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms, 799 uint32_t port_id, 800 uint16_t val16, 801 uint8_t **val) 802 { 803 enum bnxt_ulp_port_table port_data = val16; 804 805 switch (port_data) { 806 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC: 807 if (unlikely(ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id, 808 val))) { 809 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 810 return -EINVAL; 811 } 812 break; 813 case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC: 814 if (unlikely(ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id, 815 val))) { 816 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 817 return -EINVAL; 818 } 819 break; 820 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC: 821 if (unlikely(ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id, 822 val))) { 823 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 824 return -EINVAL; 825 } 826 break; 827 case BNXT_ULP_PORT_TABLE_PORT_IS_PF: 828 if (unlikely(ulp_port_db_port_is_pf_get(parms->ulp_ctx, port_id, 829 val))) { 830 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 831 return -EINVAL; 832 } 833 break; 834 case BNXT_ULP_PORT_TABLE_VF_FUNC_METADATA: 835 if (unlikely(ulp_port_db_port_meta_data_get(parms->ulp_ctx, port_id, 836 val))) { 837 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 838 return -EINVAL; 839 } 840 break; 841 case BNXT_ULP_PORT_TABLE_TABLE_SCOPE: 842 if (unlikely(ulp_port_db_port_table_scope_get(parms->ulp_ctx, 843 port_id, val))) { 844 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 845 return -EINVAL; 846 } 847 break; 848 case BNXT_ULP_PORT_TABLE_VF_FUNC_FID: 849 if (unlikely(ulp_port_db_port_vf_fid_get(parms->ulp_ctx, port_id, val))) { 850 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 851 return -EINVAL; 852 } 853 break; 854 default: 855 BNXT_DRV_DBG(ERR, "Invalid port_data %d\n", port_data); 856 return -EINVAL; 857 } 858 return 0; 859 } 860 861 static int32_t 862 ulp_mapper_field_port_db_write(struct bnxt_ulp_mapper_parms *parms, 863 uint32_t port_id, 864 uint16_t idx, 865 uint8_t *val, 866 uint32_t length) 867 { 868 enum bnxt_ulp_port_table port_data = idx; 869 uint32_t val32; 870 871 switch (port_data) { 872 case BNXT_ULP_PORT_TABLE_PHY_PORT_MIRROR_ID: 873 if (ULP_BITS_2_BYTE(length) > sizeof(val32)) { 874 BNXT_DRV_DBG(ERR, "Invalid data length %u\n", length); 875 return -EINVAL; 876 } 877 memcpy(&val32, val, ULP_BITS_2_BYTE(length)); 878 if (unlikely(ulp_port_db_port_table_mirror_set(parms->ulp_ctx, 879 port_id, 880 val32))) { 881 BNXT_DRV_DBG(ERR, "Invalid port id %u\n", port_id); 882 return -EINVAL; 883 } 884 break; 885 default: 886 BNXT_DRV_DBG(ERR, "Invalid port_data %d\n", port_data); 887 return -EINVAL; 888 } 889 return 0; 890 } 891 892 static int32_t 893 ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms, 894 enum bnxt_ulp_field_src field_src, 895 uint8_t *field_opr, 896 enum tf_dir dir, 897 uint8_t is_key, 898 uint32_t bitlen, 899 uint8_t **val, 900 uint32_t *val_len, 901 uint64_t *value) 902 { 903 struct bnxt_ulp_mapper_cond_list_info info = { 0 }; 904 struct bnxt_ulp_mapper_data *m; 905 uint8_t bit; 906 uint32_t port_id, val_size, field_size; 907 uint16_t idx = 0, size_idx = 0, offset = 0; 908 uint32_t bytelen = ULP_BITS_2_BYTE(bitlen); 909 uint8_t *buffer; 910 uint64_t lregval; 911 int32_t cond_res; 912 bool shared; 913 uint8_t i = 0; 914 915 *val_len = bitlen; 916 *value = 0; 917 /* Perform the action */ 918 switch (field_src) { 919 case BNXT_ULP_FIELD_SRC_ZERO: 920 *val = mapper_fld_zeros; 921 break; 922 case BNXT_ULP_FIELD_SRC_CONST: 923 *val = field_opr; 924 break; 925 case BNXT_ULP_FIELD_SRC_ONES: 926 *val = mapper_fld_ones; 927 *value = 1; 928 break; 929 case BNXT_ULP_FIELD_SRC_CF: 930 if (unlikely(ulp_operand_read(field_opr, 931 (uint8_t *)&idx, sizeof(uint16_t)))) { 932 BNXT_DRV_DBG(ERR, "CF operand read failed\n"); 933 return -EINVAL; 934 } 935 idx = tfp_be_to_cpu_16(idx); 936 if (unlikely(idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t))) { 937 BNXT_DRV_DBG(ERR, "comp field [%d] read oob %d\n", idx, 938 bytelen); 939 return -EINVAL; 940 } 941 buffer = (uint8_t *)&parms->comp_fld[idx]; 942 *val = &buffer[sizeof(uint64_t) - bytelen]; 943 *value = ULP_COMP_FLD_IDX_RD(parms, idx); 944 break; 945 case BNXT_ULP_FIELD_SRC_RF: 946 if (unlikely(ulp_operand_read(field_opr, 947 (uint8_t *)&idx, sizeof(uint16_t)))) { 948 BNXT_DRV_DBG(ERR, "RF operand read failed\n"); 949 return -EINVAL; 950 } 951 952 idx = tfp_be_to_cpu_16(idx); 953 /* Uninitialized regfile entries return 0 */ 954 if (unlikely(ulp_regfile_read(parms->regfile, idx, &lregval)) || 955 sizeof(uint64_t) < bytelen) { 956 BNXT_DRV_DBG(ERR, "regfile[%d] read oob %u\n", idx, 957 bytelen); 958 return -EINVAL; 959 } 960 buffer = (uint8_t *)&parms->regfile->entry[idx].data; 961 *val = &buffer[sizeof(uint64_t) - bytelen]; 962 *value = tfp_be_to_cpu_64(lregval); 963 break; 964 case BNXT_ULP_FIELD_SRC_ACT_PROP: 965 if (unlikely(ulp_operand_read(field_opr, 966 (uint8_t *)&idx, sizeof(uint16_t)))) { 967 BNXT_DRV_DBG(ERR, "Action operand read failed\n"); 968 return -EINVAL; 969 } 970 idx = tfp_be_to_cpu_16(idx); 971 if (unlikely(idx >= BNXT_ULP_ACT_PROP_IDX_LAST)) { 972 BNXT_DRV_DBG(ERR, "act_prop[%d] oob\n", idx); 973 return -EINVAL; 974 } 975 buffer = &parms->act_prop->act_details[idx]; 976 field_size = ulp_mapper_act_prop_size_get(idx); 977 if (unlikely(bytelen > field_size)) { 978 BNXT_DRV_DBG(ERR, "act_prop[%d] field size small %u\n", 979 idx, field_size); 980 return -EINVAL; 981 } 982 *val = &buffer[field_size - bytelen]; 983 if (sizeof(*value) >= field_size) { 984 *value = buffer[0]; 985 for (i = 1; i < field_size; i++) 986 *value = (*value << 8) | buffer[i]; 987 } 988 break; 989 case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ: 990 if (unlikely(ulp_operand_read(field_opr, 991 (uint8_t *)&idx, sizeof(uint16_t)))) { 992 BNXT_DRV_DBG(ERR, "Action sz operand read failed\n"); 993 return -EINVAL; 994 } 995 idx = tfp_be_to_cpu_16(idx); 996 997 if (unlikely(idx >= BNXT_ULP_ACT_PROP_IDX_LAST)) { 998 BNXT_DRV_DBG(ERR, "act_prop_sz[%d] oob\n", idx); 999 return -EINVAL; 1000 } 1001 *val = &parms->act_prop->act_details[idx]; 1002 1003 /* get the size index next */ 1004 if (unlikely(ulp_operand_read(&field_opr[sizeof(uint16_t)], 1005 (uint8_t *)&size_idx, sizeof(uint16_t)))) { 1006 BNXT_DRV_DBG(ERR, "Action sz operand read failed\n"); 1007 return -EINVAL; 1008 } 1009 size_idx = tfp_be_to_cpu_16(size_idx); 1010 if (unlikely(size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST)) { 1011 BNXT_DRV_DBG(ERR, "act_prop[%d] oob\n", size_idx); 1012 return -EINVAL; 1013 } 1014 memcpy(&val_size, &parms->act_prop->act_details[size_idx], 1015 sizeof(uint32_t)); 1016 val_size = tfp_be_to_cpu_32(val_size); 1017 *val_len = ULP_BYTE_2_BITS(val_size); 1018 break; 1019 case BNXT_ULP_FIELD_SRC_GLB_RF: 1020 if (unlikely(ulp_operand_read(field_opr, 1021 (uint8_t *)&idx, sizeof(uint16_t)))) { 1022 BNXT_DRV_DBG(ERR, "Global regfile read failed\n"); 1023 return -EINVAL; 1024 } 1025 idx = tfp_be_to_cpu_16(idx); 1026 if (unlikely(ulp_mapper_glb_resource_read(parms->mapper_data, 1027 dir, idx, &lregval, &shared) || 1028 sizeof(uint64_t) < bytelen)) { 1029 BNXT_DRV_DBG(ERR, "Global regfile[%d] read failed %u\n", 1030 idx, bytelen); 1031 return -EINVAL; 1032 } 1033 m = parms->mapper_data; 1034 buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl; 1035 *val = &buffer[sizeof(uint64_t) - bytelen]; 1036 *value = tfp_be_to_cpu_64(lregval); 1037 break; 1038 case BNXT_ULP_FIELD_SRC_HF: 1039 case BNXT_ULP_FIELD_SRC_SUB_HF: 1040 if (unlikely(ulp_operand_read(field_opr, 1041 (uint8_t *)&idx, sizeof(uint16_t)))) { 1042 BNXT_DRV_DBG(ERR, "Header field read failed\n"); 1043 return -EINVAL; 1044 } 1045 idx = tfp_be_to_cpu_16(idx); 1046 /* get the index from the global field list */ 1047 if (unlikely(ulp_mapper_glb_field_tbl_get(parms, idx, &bit))) { 1048 BNXT_DRV_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 1049 idx); 1050 return -EINVAL; 1051 } 1052 if (is_key) 1053 buffer = parms->hdr_field[bit].spec; 1054 else 1055 buffer = parms->hdr_field[bit].mask; 1056 1057 field_size = parms->hdr_field[bit].size; 1058 if (!field_size) { 1059 /* To support field processing of undefined fields */ 1060 *val = mapper_fld_zeros; 1061 break; 1062 } else if (unlikely(bytelen > field_size)) { 1063 BNXT_DRV_DBG(ERR, "Hdr field[%d] size small %u\n", 1064 bit, field_size); 1065 return -EINVAL; 1066 } 1067 if (field_src == BNXT_ULP_FIELD_SRC_HF) { 1068 *val = &buffer[field_size - bytelen]; 1069 } else { 1070 /* get the offset next */ 1071 if (unlikely(ulp_operand_read(&field_opr[sizeof(uint16_t)], 1072 (uint8_t *)&offset, 1073 sizeof(uint16_t)))) { 1074 BNXT_DRV_DBG(ERR, "Hdr fld size read failed\n"); 1075 return -EINVAL; 1076 } 1077 offset = tfp_be_to_cpu_16(offset); 1078 offset = ULP_BITS_2_BYTE_NR(offset); 1079 if (unlikely((offset + bytelen) > field_size)) { 1080 BNXT_DRV_DBG(ERR, "Hdr field[%d] oob\n", bit); 1081 return -EINVAL; 1082 } 1083 *val = &buffer[offset]; 1084 } 1085 break; 1086 case BNXT_ULP_FIELD_SRC_HDR_BIT: 1087 if (unlikely(ulp_operand_read(field_opr, 1088 (uint8_t *)&lregval, sizeof(uint64_t)))) { 1089 BNXT_DRV_DBG(ERR, "Header bit read failed\n"); 1090 return -EINVAL; 1091 } 1092 lregval = tfp_be_to_cpu_64(lregval); 1093 if (unlikely(ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval))) { 1094 *val = mapper_fld_one; 1095 *value = 1; 1096 } else { 1097 *val = mapper_fld_zeros; 1098 } 1099 break; 1100 case BNXT_ULP_FIELD_SRC_ACT_BIT: 1101 if (unlikely(ulp_operand_read(field_opr, 1102 (uint8_t *)&lregval, sizeof(uint64_t)))) { 1103 BNXT_DRV_DBG(ERR, "Action bit read failed\n"); 1104 return -EINVAL; 1105 } 1106 lregval = tfp_be_to_cpu_64(lregval); 1107 if (unlikely(ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval))) { 1108 *val = mapper_fld_one; 1109 *value = 1; 1110 } else { 1111 *val = mapper_fld_zeros; 1112 } 1113 break; 1114 case BNXT_ULP_FIELD_SRC_FIELD_BIT: 1115 if (unlikely(ulp_operand_read(field_opr, 1116 (uint8_t *)&idx, sizeof(uint16_t)))) { 1117 BNXT_DRV_DBG(ERR, "Field bit read failed\n"); 1118 return -EINVAL; 1119 } 1120 idx = tfp_be_to_cpu_16(idx); 1121 /* get the index from the global field list */ 1122 if (unlikely(ulp_mapper_glb_field_tbl_get(parms, idx, &bit))) { 1123 BNXT_DRV_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n", 1124 idx); 1125 return -EINVAL; 1126 } 1127 if (unlikely(ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit))) { 1128 *val = mapper_fld_one; 1129 *value = 1; 1130 } else { 1131 *val = mapper_fld_zeros; 1132 } 1133 break; 1134 case BNXT_ULP_FIELD_SRC_PORT_TABLE: 1135 if (unlikely(ulp_operand_read(field_opr, 1136 (uint8_t *)&idx, sizeof(uint16_t)))) { 1137 BNXT_DRV_DBG(ERR, "CF operand read failed\n"); 1138 return -EINVAL; 1139 } 1140 idx = tfp_be_to_cpu_16(idx); 1141 if (unlikely(idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t))) { 1142 BNXT_DRV_DBG(ERR, "comp field [%d] read oob %d\n", idx, 1143 bytelen); 1144 return -EINVAL; 1145 } 1146 1147 /* The port id is present in the comp field list */ 1148 port_id = ULP_COMP_FLD_IDX_RD(parms, idx); 1149 /* get the port table enum */ 1150 if (unlikely(ulp_operand_read(field_opr + sizeof(uint16_t), 1151 (uint8_t *)&idx, sizeof(uint16_t)))) { 1152 BNXT_DRV_DBG(ERR, "Port table enum read failed\n"); 1153 return -EINVAL; 1154 } 1155 idx = tfp_be_to_cpu_16(idx); 1156 if (unlikely(ulp_mapper_field_port_db_process(parms, port_id, idx, 1157 val))) { 1158 BNXT_DRV_DBG(ERR, "field port table failed\n"); 1159 return -EINVAL; 1160 } 1161 break; 1162 case BNXT_ULP_FIELD_SRC_ENC_HDR_BIT: 1163 if (unlikely(ulp_operand_read(field_opr, 1164 (uint8_t *)&lregval, sizeof(uint64_t)))) { 1165 BNXT_DRV_DBG(ERR, "Header bit read failed\n"); 1166 return -EINVAL; 1167 } 1168 lregval = tfp_be_to_cpu_64(lregval); 1169 if (ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, lregval)) { 1170 *val = mapper_fld_one; 1171 *value = 1; 1172 } else { 1173 *val = mapper_fld_zeros; 1174 } 1175 break; 1176 case BNXT_ULP_FIELD_SRC_ENC_FIELD: 1177 if (unlikely(ulp_operand_read(field_opr, 1178 (uint8_t *)&idx, sizeof(uint16_t)))) { 1179 BNXT_DRV_DBG(ERR, "Header field read failed\n"); 1180 return -EINVAL; 1181 } 1182 idx = tfp_be_to_cpu_16(idx); 1183 /* get the index from the global field list */ 1184 if (unlikely(idx >= BNXT_ULP_ENC_FIELD_LAST)) { 1185 BNXT_DRV_DBG(ERR, "invalid encap field tbl idx %d\n", 1186 idx); 1187 return -EINVAL; 1188 } 1189 buffer = parms->enc_field[idx].spec; 1190 field_size = parms->enc_field[idx].size; 1191 if (unlikely(bytelen > field_size)) { 1192 BNXT_DRV_DBG(ERR, "Encap field[%d] size small %u\n", 1193 idx, field_size); 1194 return -EINVAL; 1195 } 1196 *val = &buffer[field_size - bytelen]; 1197 break; 1198 case BNXT_ULP_FIELD_SRC_SKIP: 1199 /* do nothing */ 1200 *val = mapper_fld_zeros; 1201 *val_len = 0; 1202 break; 1203 case BNXT_ULP_FIELD_SRC_REJECT: 1204 return -EINVAL; 1205 case BNXT_ULP_FIELD_SRC_LIST_AND: 1206 case BNXT_ULP_FIELD_SRC_LIST_OR: 1207 /* read the cond table index and count */ 1208 if (unlikely(ulp_operand_read(field_opr, 1209 (uint8_t *)&idx, sizeof(uint16_t)))) { 1210 BNXT_DRV_DBG(ERR, "Cond idx operand read failed\n"); 1211 return -EINVAL; 1212 } 1213 idx = tfp_be_to_cpu_16(idx); 1214 1215 if (unlikely(ulp_operand_read(field_opr + sizeof(uint16_t), 1216 (uint8_t *)&size_idx, sizeof(uint16_t)))) { 1217 BNXT_DRV_DBG(ERR, "Cond count operand read failed\n"); 1218 return -EINVAL; 1219 } 1220 size_idx = tfp_be_to_cpu_16(size_idx); 1221 1222 /* populate the extracted vales to create a temp cond list */ 1223 if (field_src == BNXT_ULP_FIELD_SRC_LIST_AND) 1224 info.cond_list_opcode = BNXT_ULP_COND_LIST_OPC_AND; 1225 else 1226 info.cond_list_opcode = BNXT_ULP_COND_LIST_OPC_OR; 1227 info.cond_start_idx = idx; 1228 info.cond_nums = size_idx; 1229 if (unlikely(ulp_mapper_cond_opc_list_process(parms, &info, &cond_res))) { 1230 BNXT_DRV_DBG(ERR, "Cond evaluation failed\n"); 1231 return -EINVAL; 1232 } 1233 if (cond_res) { 1234 *val = mapper_fld_one; 1235 *value = 1; 1236 } else { 1237 *val = mapper_fld_zeros; 1238 *value = 0; 1239 } 1240 break; 1241 case BNXT_ULP_FIELD_SRC_CF_BIT: 1242 if (unlikely(ulp_operand_read(field_opr, 1243 (uint8_t *)&lregval, sizeof(uint64_t)))) { 1244 BNXT_DRV_DBG(ERR, "CF operand read failed\n"); 1245 return -EINVAL; 1246 } 1247 lregval = tfp_be_to_cpu_64(lregval); 1248 if (unlikely(ULP_BITMAP_ISSET(parms->cf_bitmap, lregval))) { 1249 *val = mapper_fld_one; 1250 *value = 1; 1251 } else { 1252 *val = mapper_fld_zeros; 1253 } 1254 break; 1255 default: 1256 BNXT_DRV_DBG(ERR, "invalid field opcode 0x%x\n", field_src); 1257 return -EINVAL; 1258 } 1259 return 0; 1260 } 1261 1262 static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen, 1263 uint64_t *output) 1264 { 1265 uint16_t val_16; 1266 uint32_t val_32; 1267 uint64_t val_64; 1268 uint32_t bytelen; 1269 1270 bytelen = ULP_BITS_2_BYTE(bitlen); 1271 if (bytelen == sizeof(uint8_t)) { 1272 *output = *((uint8_t *)buffer); 1273 } else if (bytelen == sizeof(uint16_t)) { 1274 val_16 = *((uint16_t *)buffer); 1275 *output = tfp_be_to_cpu_16(val_16); 1276 } else if (bytelen == sizeof(uint32_t)) { 1277 val_32 = *((uint32_t *)buffer); 1278 *output = tfp_be_to_cpu_32(val_32); 1279 } else if (bytelen == sizeof(val_64)) { 1280 val_64 = *((uint64_t *)buffer); 1281 *output = tfp_be_to_cpu_64(val_64); 1282 } else { 1283 *output = 0; 1284 return -EINVAL; 1285 } 1286 return 0; 1287 } 1288 1289 static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src, 1290 struct ulp_blob *blob, 1291 uint8_t *val, 1292 uint32_t val_len, 1293 uint8_t **out_val) 1294 { 1295 if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) { 1296 if (unlikely(ulp_blob_pad_push(blob, val_len) < 0)) { 1297 BNXT_DRV_DBG(ERR, "too large for blob\n"); 1298 return -EINVAL; 1299 } 1300 } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) { 1301 if (unlikely(ulp_blob_push_encap(blob, val, val_len) < 0)) { 1302 BNXT_DRV_DBG(ERR, "encap blob push failed\n"); 1303 return -EINVAL; 1304 } 1305 } else if (fld_src == BNXT_ULP_FIELD_SRC_SKIP) { 1306 /* do nothing */ 1307 } else { 1308 if (unlikely(ulp_blob_push(blob, val, val_len))) { 1309 BNXT_DRV_DBG(ERR, "push of val1 failed\n"); 1310 return -EINVAL; 1311 } 1312 } 1313 *out_val = val; 1314 return 0; 1315 } 1316 1317 static int32_t 1318 ulp_mapper_field_opc_next(struct bnxt_ulp_mapper_parms *parms, 1319 enum tf_dir dir, 1320 uint8_t *field_opr, 1321 struct ulp_blob *blob, 1322 uint8_t is_key, 1323 const char *name) 1324 { 1325 struct bnxt_ulp_mapper_field_info *field_info; 1326 uint16_t idx = 0; 1327 1328 /* read the cond table index and count */ 1329 if (unlikely(ulp_operand_read(field_opr, 1330 (uint8_t *)&idx, sizeof(uint16_t)))) { 1331 BNXT_DRV_DBG(ERR, "field idx operand read failed\n"); 1332 return -EINVAL; 1333 } 1334 idx = tfp_be_to_cpu_16(idx); 1335 1336 field_info = ulp_mapper_tmpl_key_ext_list_get(parms, idx); 1337 if (unlikely(field_info == NULL)) { 1338 BNXT_DRV_DBG(ERR, "Invalid field idx %d\n", idx); 1339 return -EINVAL; 1340 } 1341 1342 return ulp_mapper_field_opc_process(parms, dir, field_info, 1343 blob, is_key, name); 1344 } 1345 1346 static void 1347 ulp_mapper_key_recipe_tbl_deinit(struct bnxt_ulp_mapper_data *mdata) 1348 { 1349 struct bnxt_ulp_key_recipe_entry **recipes; 1350 enum bnxt_ulp_direction dir; 1351 uint32_t idx, ftype; 1352 1353 /* If recipe table is not initialized then exit */ 1354 if (!mdata->key_recipe_info.num_recipes) 1355 return; 1356 1357 for (dir = 0; dir < BNXT_ULP_DIRECTION_LAST; dir++) { 1358 for (ftype = 0; ftype < ULP_RECIPE_TYPE_MAX; ftype++) { 1359 recipes = mdata->key_recipe_info.recipes[dir][ftype]; 1360 for (idx = 0; idx < mdata->key_recipe_info.num_recipes; 1361 idx++) { 1362 if (recipes[idx]) 1363 rte_free(recipes[idx]); 1364 } 1365 rte_free(mdata->key_recipe_info.recipes[dir][ftype]); 1366 mdata->key_recipe_info.recipes[dir][ftype] = NULL; 1367 rte_free(mdata->key_recipe_info.recipe_ba[dir][ftype]); 1368 mdata->key_recipe_info.recipe_ba[dir][ftype] = NULL; 1369 } 1370 } 1371 mdata->key_recipe_info.num_recipes = 0; 1372 } 1373 1374 static int32_t 1375 ulp_mapper_key_recipe_tbl_init(struct bnxt_ulp_context *ulp_ctx, 1376 struct bnxt_ulp_mapper_data *mdata) 1377 { 1378 struct bnxt_ulp_key_recipe_entry **recipes; 1379 enum bnxt_ulp_direction dir; 1380 uint32_t dev_id = 0, size_val; 1381 uint32_t num_recipes, ftype, pool_size; 1382 int32_t rc = 0; 1383 struct bitalloc *recipe_ba; 1384 1385 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 1386 if (unlikely(rc)) { 1387 BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n"); 1388 return -EINVAL; 1389 } 1390 num_recipes = bnxt_ulp_num_key_recipes_get(ulp_ctx); 1391 if (!num_recipes) 1392 return rc; 1393 1394 /* Need to write these values so that a failure will result in freeing 1395 * the memory in the deinit 1396 */ 1397 mdata->key_recipe_info.num_recipes = num_recipes; 1398 mdata->key_recipe_info.max_fields = BNXT_ULP_KEY_RECIPE_MAX_FLDS; 1399 1400 size_val = sizeof(struct bnxt_ulp_key_recipe_entry *); 1401 pool_size = BITALLOC_SIZEOF(num_recipes); 1402 1403 /* The caller will deinit if failures occur, so just return fail instead 1404 * of attempting to free allocated memory 1405 **/ 1406 for (dir = 0; dir < BNXT_ULP_DIRECTION_LAST; dir++) { 1407 for (ftype = 0; ftype < ULP_RECIPE_TYPE_MAX; ftype++) { 1408 recipes = rte_zmalloc("key_recipe_list", 1409 size_val * num_recipes, 0); 1410 if (unlikely(!recipes)) { 1411 BNXT_DRV_DBG(ERR, "Unable to alloc memory\n"); 1412 return -ENOMEM; 1413 } 1414 mdata->key_recipe_info.recipes[dir][ftype] = recipes; 1415 1416 recipe_ba = rte_malloc("key_recipe_ba", pool_size, 0); 1417 if (unlikely(!recipe_ba)) { 1418 BNXT_DRV_DBG(ERR, "Unable to alloc memory\n"); 1419 return -ENOMEM; 1420 } 1421 mdata->key_recipe_info.recipe_ba[dir][ftype] = 1422 recipe_ba; 1423 rc = ba_init(recipe_ba, num_recipes, true); 1424 if (unlikely(rc)) { 1425 BNXT_DRV_DBG(ERR, 1426 "Unable to alloc recipe ba\n"); 1427 return -ENOMEM; 1428 } 1429 } 1430 } 1431 return rc; 1432 } 1433 1434 static struct bnxt_ulp_mapper_data * 1435 ulp_mapper_key_recipe_args_validate(struct bnxt_ulp_context *ulp_ctx, 1436 enum bnxt_ulp_direction dir, 1437 enum bnxt_ulp_resource_sub_type stype, 1438 uint32_t recipe_id) 1439 { 1440 struct bnxt_ulp_mapper_data *mdata; 1441 1442 mdata = (struct bnxt_ulp_mapper_data *) 1443 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 1444 if (unlikely(!mdata)) { 1445 BNXT_DRV_DBG(ERR, "Unable to get mapper data.\n"); 1446 return NULL; 1447 } 1448 if (unlikely(dir >= BNXT_ULP_DIRECTION_LAST)) { 1449 BNXT_DRV_DBG(ERR, "Invalid dir (%d) in key recipe\n", dir); 1450 return NULL; 1451 } 1452 if (unlikely(mdata->key_recipe_info.num_recipes == 0)) { 1453 BNXT_DRV_DBG(ERR, "Recipes are not supported\n"); 1454 return NULL; 1455 } 1456 if (unlikely(stype != BNXT_ULP_RESOURCE_SUB_TYPE_KEY_RECIPE_TABLE_WM && 1457 stype != BNXT_ULP_RESOURCE_SUB_TYPE_KEY_RECIPE_TABLE_EM)) { 1458 BNXT_DRV_DBG(ERR, "Invalid type (%d) in key recipe\n", stype); 1459 return NULL; 1460 } 1461 if (unlikely(recipe_id >= mdata->key_recipe_info.num_recipes || 1462 !mdata->key_recipe_info.num_recipes)) { 1463 BNXT_DRV_DBG(ERR, "Key recipe id out of range(%u >= %u)\n", 1464 recipe_id, mdata->key_recipe_info.num_recipes); 1465 return NULL; 1466 } 1467 return mdata; 1468 } 1469 1470 static struct bnxt_ulp_key_recipe_entry * 1471 ulp_mapper_key_recipe_alloc(struct bnxt_ulp_context *ulp_ctx, 1472 enum bnxt_ulp_direction dir, 1473 enum bnxt_ulp_resource_sub_type stype, 1474 uint32_t recipe_id, bool alloc_only, 1475 uint8_t *max_fields) 1476 { 1477 struct bnxt_ulp_key_recipe_entry **recipes; 1478 struct bnxt_ulp_mapper_data *mdata = NULL; 1479 uint32_t size_s = sizeof(struct bnxt_ulp_key_recipe_entry); 1480 1481 mdata = ulp_mapper_key_recipe_args_validate(ulp_ctx, dir, 1482 stype, recipe_id); 1483 if (unlikely(mdata == NULL)) 1484 return NULL; 1485 1486 recipes = mdata->key_recipe_info.recipes[dir][stype]; 1487 if (alloc_only && recipes[recipe_id] == NULL) { 1488 recipes[recipe_id] = rte_zmalloc("key_recipe_entry", size_s, 0); 1489 if (recipes[recipe_id] == NULL) { 1490 BNXT_DRV_DBG(ERR, "Unable to alloc key recipe\n"); 1491 return NULL; 1492 } 1493 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1494 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1495 BNXT_DRV_INF("Alloc key recipe [%s]:[%s] = 0x%X\n", 1496 (dir == BNXT_ULP_DIRECTION_INGRESS) ? "rx" : "tx", 1497 ulp_mapper_key_recipe_type_to_str(stype), recipe_id); 1498 #endif 1499 #endif 1500 } else if (alloc_only) { 1501 BNXT_DRV_DBG(ERR, "Recipe ID (%d) already allocated\n", 1502 recipe_id); 1503 } 1504 *max_fields = mdata->key_recipe_info.max_fields; 1505 return recipes[recipe_id]; 1506 } 1507 1508 /* The free just marks the entry as not in use and resets the number of entries 1509 * to zero. 1510 */ 1511 static int32_t 1512 ulp_mapper_key_recipe_free(struct bnxt_ulp_context *ulp_ctx, 1513 uint8_t dir, 1514 enum bnxt_ulp_resource_sub_type stype, 1515 uint32_t index) 1516 { 1517 struct bnxt_ulp_key_recipe_entry **recipes; 1518 struct bnxt_ulp_mapper_data *mdata = NULL; 1519 struct bitalloc *recipe_ba = NULL; 1520 int32_t rc; 1521 1522 mdata = ulp_mapper_key_recipe_args_validate(ulp_ctx, dir, 1523 stype, index); 1524 if (unlikely(mdata == NULL)) 1525 return -EINVAL; 1526 1527 recipe_ba = mdata->key_recipe_info.recipe_ba[dir][stype]; 1528 rc = ba_free(recipe_ba, index); 1529 if (unlikely(rc < 0)) 1530 BNXT_DRV_DBG(DEBUG, "Unable to free recipe id[%s][%u] = (%d)\n", 1531 (dir == BNXT_ULP_DIRECTION_INGRESS) ? "rx" : "tx", 1532 stype, index); 1533 1534 recipes = mdata->key_recipe_info.recipes[dir][stype]; 1535 if (unlikely(recipes[index] == NULL)) { 1536 BNXT_DRV_DBG(DEBUG, "recipe id[%s][%u] = (%d) already freed\n", 1537 (dir == BNXT_ULP_DIRECTION_INGRESS) ? "rx" : "tx", 1538 stype, index); 1539 return 0; 1540 } 1541 rte_free(recipes[index]); 1542 recipes[index] = NULL; 1543 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1544 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1545 BNXT_DRV_INF("Free key recipe [%s]:[%s] = 0x%X\n", 1546 (dir == BNXT_ULP_DIRECTION_INGRESS) ? "rx" : "tx", 1547 ulp_mapper_key_recipe_type_to_str(stype), index); 1548 #endif 1549 #endif 1550 return 0; 1551 } 1552 1553 static void 1554 ulp_mapper_key_recipe_copy_to_src1(struct bnxt_ulp_mapper_field_info *dst, 1555 enum bnxt_ulp_field_src field_src, 1556 uint8_t *field_opr, 1557 struct bnxt_ulp_mapper_field_info *src, 1558 bool *written) 1559 { 1560 if (field_src != BNXT_ULP_FIELD_SRC_SKIP) { 1561 dst->field_opc = BNXT_ULP_FIELD_OPC_SRC1; 1562 dst->field_src1 = field_src; 1563 memcpy(dst->field_opr1, field_opr, 16); 1564 memcpy(dst->description, src->description, 64); 1565 dst->field_bit_size = src->field_bit_size; 1566 *written = true; 1567 } 1568 } 1569 1570 struct bnxt_ulp_mapper_key_info * 1571 ulp_mapper_key_recipe_fields_get(struct bnxt_ulp_mapper_parms *parms, 1572 struct bnxt_ulp_mapper_tbl_info *tbl, 1573 uint32_t *num_flds) 1574 { 1575 struct bnxt_ulp_key_recipe_entry **recipes; 1576 enum bnxt_ulp_resource_sub_type stype; 1577 struct bnxt_ulp_mapper_data *mdata = NULL; 1578 uint64_t regval = 0; 1579 uint32_t recipe_id = 0; 1580 1581 /* Don't like this, but need to convert from a tbl resource func to the 1582 * subtype for key_recipes. 1583 */ 1584 switch (tbl->resource_func) { 1585 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 1586 stype = BNXT_ULP_RESOURCE_SUB_TYPE_KEY_RECIPE_TABLE_EM; 1587 break; 1588 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 1589 stype = BNXT_ULP_RESOURCE_SUB_TYPE_KEY_RECIPE_TABLE_WM; 1590 break; 1591 default: 1592 BNXT_DRV_DBG(ERR, "Invalid res func(%d) for recipe fields\n", 1593 tbl->resource_func); 1594 return NULL; 1595 }; 1596 1597 /* Get the recipe index from the registry file */ 1598 if (ulp_regfile_read(parms->regfile, tbl->key_recipe_operand, 1599 ®val)) { 1600 BNXT_DRV_DBG(ERR, "Failed to get tbl idx from regfile[%d].\n", 1601 tbl->tbl_operand); 1602 return NULL; 1603 } 1604 recipe_id = (uint32_t)tfp_be_to_cpu_64(regval); 1605 mdata = ulp_mapper_key_recipe_args_validate(parms->ulp_ctx, 1606 tbl->direction, 1607 stype, recipe_id); 1608 if (mdata == NULL) 1609 return NULL; 1610 1611 recipes = mdata->key_recipe_info.recipes[tbl->direction][stype]; 1612 if (recipes[recipe_id] == NULL) 1613 return NULL; 1614 1615 *num_flds = recipes[recipe_id]->cnt; 1616 return &recipes[recipe_id]->flds[0]; 1617 } 1618 1619 static int32_t 1620 ulp_mapper_key_recipe_field_opc_next(struct bnxt_ulp_mapper_parms *parms, 1621 enum bnxt_ulp_direction dir, 1622 uint8_t *field_opr, 1623 uint8_t is_key, 1624 const char *name, 1625 bool *written, 1626 struct bnxt_ulp_mapper_field_info *ofld) 1627 { 1628 struct bnxt_ulp_mapper_field_info *field_info; 1629 uint16_t idx = 0; 1630 1631 /* read the cond table index and count */ 1632 if (unlikely(ulp_operand_read(field_opr, 1633 (uint8_t *)&idx, sizeof(uint16_t)))) { 1634 BNXT_DRV_DBG(ERR, "field idx operand read failed\n"); 1635 return -EINVAL; 1636 } 1637 idx = tfp_be_to_cpu_16(idx); 1638 1639 field_info = ulp_mapper_tmpl_key_ext_list_get(parms, idx); 1640 if (unlikely(field_info == NULL)) { 1641 BNXT_DRV_DBG(ERR, "Invalid field idx %d\n", idx); 1642 return -EINVAL; 1643 } 1644 1645 return ulp_mapper_key_recipe_field_opc_process(parms, dir, field_info, 1646 is_key, name, 1647 written, ofld); 1648 } 1649 1650 int32_t 1651 ulp_mapper_key_recipe_field_opc_process(struct bnxt_ulp_mapper_parms *parms, 1652 uint8_t dir, 1653 struct bnxt_ulp_mapper_field_info *fld, 1654 uint8_t is_key, 1655 const char *name, 1656 bool *written, 1657 struct bnxt_ulp_mapper_field_info *ofld) 1658 { 1659 uint8_t process_src1 = 0; 1660 uint32_t val1_len = 0; 1661 uint64_t value1 = 0; 1662 int32_t rc = 0; 1663 uint8_t *val1; 1664 1665 /* prepare the field source and values */ 1666 switch (fld->field_opc) { 1667 case BNXT_ULP_FIELD_OPC_SRC1: 1668 /* No logic, just take SRC1 and return */ 1669 ulp_mapper_key_recipe_copy_to_src1(ofld, fld->field_src1, 1670 fld->field_opr1, fld, 1671 written); 1672 return rc; 1673 case BNXT_ULP_FIELD_OPC_SKIP: 1674 *written = false; 1675 return rc; 1676 case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: 1677 case BNXT_ULP_FIELD_OPC_TERNARY_LIST: 1678 process_src1 = 1; 1679 break; 1680 default: 1681 BNXT_DRV_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc); 1682 rc = -EINVAL; 1683 return rc; 1684 } 1685 1686 /* process the src1 opcode */ 1687 if (process_src1) { 1688 if (unlikely(ulp_mapper_field_src_process(parms, fld->field_src1, 1689 fld->field_opr1, dir, is_key, 1690 fld->field_bit_size, &val1, 1691 &val1_len, &value1))) { 1692 BNXT_DRV_DBG(ERR, "fld src1 process failed\n"); 1693 return -EINVAL; 1694 } 1695 } 1696 1697 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) { 1698 if (value1) 1699 ulp_mapper_key_recipe_copy_to_src1(ofld, 1700 fld->field_src2, 1701 fld->field_opr2, 1702 fld, written); 1703 else 1704 ulp_mapper_key_recipe_copy_to_src1(ofld, 1705 fld->field_src3, 1706 fld->field_opr3, 1707 fld, written); 1708 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_TERNARY_LIST) { 1709 if (value1) { 1710 /* check if src2 is next */ 1711 if (fld->field_src2 == BNXT_ULP_FIELD_SRC_NEXT) { 1712 /* get the next field info */ 1713 if (unlikely(ulp_mapper_key_recipe_field_opc_next(parms, 1714 dir, 1715 fld->field_opr2, 1716 is_key, 1717 name, 1718 written, 1719 ofld))) { 1720 BNXT_DRV_DBG(ERR, 1721 "recipe fld next process fail\n"); 1722 return -EINVAL; 1723 } else { 1724 return rc; 1725 } 1726 } else { 1727 ulp_mapper_key_recipe_copy_to_src1(ofld, 1728 fld->field_src2, 1729 fld->field_opr2, 1730 fld, written); 1731 } 1732 } else { 1733 /* check if src3 is next */ 1734 if (fld->field_src3 == BNXT_ULP_FIELD_SRC_NEXT) { 1735 /* get the next field info */ 1736 if (unlikely(ulp_mapper_key_recipe_field_opc_next(parms, 1737 dir, 1738 fld->field_opr3, 1739 is_key, 1740 name, 1741 written, 1742 ofld))) { 1743 BNXT_DRV_DBG(ERR, 1744 "recipt fld next process fail\n"); 1745 return -EINVAL; 1746 } else { 1747 return rc; 1748 } 1749 } else { 1750 ulp_mapper_key_recipe_copy_to_src1(ofld, 1751 fld->field_src3, 1752 fld->field_opr3, 1753 fld, written); 1754 } 1755 } 1756 } 1757 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 1758 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 1759 if (*written && is_key) 1760 BNXT_DRV_DBG(DEBUG, "%-20s bits = %-3d\n", fld->description, 1761 fld->field_bit_size); 1762 #endif 1763 #endif 1764 return rc; 1765 } 1766 1767 static int32_t 1768 ulp_mapper_key_recipe_tbl_process(struct bnxt_ulp_mapper_parms *parms, 1769 struct bnxt_ulp_mapper_tbl_info *tbl) 1770 { 1771 bool alloc = false, write = false, regfile = false; 1772 struct bnxt_ulp_mapper_key_info *kflds, *rflds; 1773 struct bnxt_ulp_mapper_field_info *kfld, *rfld; 1774 struct bnxt_ulp_mapper_data *mdata = NULL; 1775 struct bnxt_ulp_key_recipe_entry *recipe; 1776 struct ulp_flow_db_res_params fid_parms; 1777 int32_t rc = 0, free_rc, tmp_recipe_id; 1778 enum bnxt_ulp_resource_sub_type stype; 1779 uint8_t max_rflds = 0, rnum_flds = 0; 1780 enum bnxt_ulp_direction dir; 1781 struct bitalloc *recipe_ba = NULL; 1782 uint32_t recipe_id = 0; 1783 uint32_t i, num_kflds; 1784 bool written = false; 1785 uint64_t regval = 0; 1786 1787 dir = tbl->direction; 1788 stype = tbl->resource_sub_type; 1789 1790 switch (tbl->tbl_opcode) { 1791 case BNXT_ULP_KEY_RECIPE_TBL_OPC_ALLOC_WR_REGFILE: 1792 alloc = true; 1793 write = true; 1794 regfile = true; 1795 break; 1796 case BNXT_ULP_KEY_RECIPE_TBL_OPC_ALLOC_REGFILE: 1797 alloc = true; 1798 regfile = true; 1799 break; 1800 case BNXT_ULP_KEY_RECIPE_TBL_OPC_WR_REGFILE: 1801 alloc = false; 1802 regfile = true; 1803 write = true; 1804 break; 1805 default: 1806 BNXT_DRV_DBG(ERR, "Invalid recipe table opcode %d\n", 1807 tbl->tbl_opcode); 1808 return -EINVAL; 1809 }; 1810 1811 /* Get the recipe_id from the regfile */ 1812 if (!alloc && regfile) { 1813 if (unlikely(ulp_regfile_read(parms->regfile, 1814 tbl->tbl_operand, 1815 ®val))) { 1816 BNXT_DRV_DBG(ERR, 1817 "Fail to get tbl idx from regfile[%d].\n", 1818 tbl->tbl_operand); 1819 return -EINVAL; 1820 } 1821 recipe_id = rte_be_to_cpu_64(regval); 1822 } 1823 1824 if (alloc) { 1825 /* Allocate a recipe id based on the direction and type 1826 * only supported types are EM and WC for now. 1827 */ 1828 mdata = ulp_mapper_key_recipe_args_validate(parms->ulp_ctx, dir, 1829 stype, 0); 1830 if (unlikely(mdata == NULL)) 1831 return -EINVAL; 1832 1833 recipe_ba = mdata->key_recipe_info.recipe_ba[dir][stype]; 1834 tmp_recipe_id = ba_alloc(recipe_ba); 1835 if (unlikely(tmp_recipe_id < 0)) { 1836 BNXT_DRV_DBG(ERR, "Failed to allocate a recipe id\n"); 1837 return -EINVAL; 1838 } else if (unlikely((uint32_t)tmp_recipe_id >= 1839 mdata->key_recipe_info.num_recipes)) { 1840 /* Shouldn't get here, but could be an issue with the 1841 * allocator, so free the recipe_id 1842 */ 1843 BNXT_DRV_DBG(ERR, 1844 "Allocated recipe id(%d) >= max(%d)\n", 1845 tmp_recipe_id, 1846 mdata->key_recipe_info.num_recipes); 1847 (void)ba_free(recipe_ba, tmp_recipe_id); 1848 return -EINVAL; 1849 } 1850 /* any error after this must goto error in order to free 1851 * the recipe_id 1852 */ 1853 recipe_id = tmp_recipe_id; 1854 } 1855 1856 if (alloc && regfile) { 1857 regval = rte_cpu_to_be_64(recipe_id); 1858 rc = ulp_regfile_write(parms->regfile, tbl->tbl_operand, 1859 regval); 1860 if (unlikely(rc)) { 1861 BNXT_DRV_DBG(ERR, "Failed to write regfile[%d] rc=%d\n", 1862 tbl->tbl_operand, rc); 1863 if (recipe_ba) 1864 (void)ba_free(recipe_ba, recipe_id); 1865 return -EINVAL; 1866 } 1867 } 1868 1869 /* allocate or Get the recipe entry based on alloc */ 1870 recipe = ulp_mapper_key_recipe_alloc(parms->ulp_ctx, dir, stype, 1871 recipe_id, alloc, &max_rflds); 1872 if (unlikely(!recipe || !max_rflds)) { 1873 BNXT_DRV_DBG(ERR, "Failed to get the recipe slot\n"); 1874 if (recipe_ba) 1875 (void)ba_free(recipe_ba, recipe_id); 1876 return -EINVAL; 1877 } 1878 1879 /* We have a recipe_id by now, write the data */ 1880 if (write) { 1881 /* Get the key fields to process */ 1882 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 1883 if (unlikely(!kflds || !num_kflds)) { 1884 BNXT_DRV_DBG(ERR, "Failed to get the key fields\n"); 1885 rc = -EINVAL; 1886 goto error; 1887 } 1888 1889 rflds = &recipe->flds[0]; 1890 /* iterate over the key fields and write the recipe */ 1891 for (i = 0; i < num_kflds; i++) { 1892 if (unlikely(rnum_flds >= max_rflds)) { 1893 BNXT_DRV_DBG(ERR, 1894 "Max recipe fields exceeded (%d)\n", 1895 rnum_flds); 1896 goto error; 1897 } 1898 written = false; 1899 kfld = &kflds[i].field_info_spec; 1900 rfld = &rflds[rnum_flds].field_info_spec; 1901 1902 rc = ulp_mapper_key_recipe_field_opc_process(parms, 1903 dir, 1904 kfld, 1, 1905 "KEY", 1906 &written, 1907 rfld); 1908 if (unlikely(rc)) 1909 goto error; 1910 1911 if (stype == 1912 BNXT_ULP_RESOURCE_SUB_TYPE_KEY_RECIPE_TABLE_WM) { 1913 kfld = &kflds[i].field_info_mask; 1914 rfld = &rflds[rnum_flds].field_info_mask; 1915 rc = ulp_mapper_key_recipe_field_opc_process(parms, 1916 dir, 1917 kfld, 1918 0, 1919 "MASK", 1920 &written, 1921 rfld); 1922 if (unlikely(rc)) 1923 goto error; 1924 } 1925 if (written) 1926 rnum_flds++; 1927 } 1928 recipe->cnt = rnum_flds; 1929 } 1930 1931 memset(&fid_parms, 0, sizeof(fid_parms)); 1932 fid_parms.direction = tbl->direction; 1933 fid_parms.resource_func = tbl->resource_func; 1934 fid_parms.resource_type = tbl->resource_type; 1935 fid_parms.resource_sub_type = tbl->resource_sub_type; 1936 fid_parms.resource_hndl = recipe_id; 1937 fid_parms.critical_resource = tbl->critical_resource; 1938 1939 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 1940 if (unlikely(rc)) { 1941 BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 1942 rc); 1943 goto error; 1944 } 1945 1946 return rc; 1947 error: 1948 /* Free the actual recipe */ 1949 free_rc = ulp_mapper_key_recipe_free(parms->ulp_ctx, tbl->direction, 1950 tbl->resource_sub_type, recipe_id); 1951 if (free_rc) 1952 BNXT_DRV_DBG(ERR, "Failed to free recipe on error: %d\n", 1953 free_rc); 1954 return rc; 1955 } 1956 1957 int32_t 1958 ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms, 1959 enum tf_dir dir, 1960 struct bnxt_ulp_mapper_field_info *fld, 1961 struct ulp_blob *blob, 1962 uint8_t is_key, 1963 const char *name) 1964 { 1965 uint16_t write_idx = blob->write_idx; 1966 uint8_t *val = NULL, *val1, *val2, *val3; 1967 uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0; 1968 uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0; 1969 uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0; 1970 uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0; 1971 uint64_t value1 = 0, value2 = 0, value3 = 0; 1972 int32_t rc = 0; 1973 1974 /* prepare the field source and values */ 1975 switch (fld->field_opc) { 1976 case BNXT_ULP_FIELD_OPC_SRC1: 1977 process_src1 = 1; 1978 break; 1979 case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: 1980 case BNXT_ULP_FIELD_OPC_TERNARY_LIST: 1981 process_src1 = 1; 1982 break; 1983 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: 1984 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: 1985 process_src3 = 1; 1986 eval_src3 = 1; 1987 process_src1 = 1; 1988 process_src2 = 1; 1989 eval_src1 = 1; 1990 eval_src2 = 1; 1991 break; 1992 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: 1993 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: 1994 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: 1995 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: 1996 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: 1997 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: 1998 process_src1 = 1; 1999 process_src2 = 1; 2000 eval_src1 = 1; 2001 eval_src2 = 1; 2002 break; 2003 default: 2004 break; 2005 } 2006 2007 /* process the src1 opcode */ 2008 if (process_src1) { 2009 if (unlikely(ulp_mapper_field_src_process(parms, fld->field_src1, 2010 fld->field_opr1, dir, is_key, 2011 fld->field_bit_size, &val1, 2012 &val1_len, &value1))) { 2013 BNXT_DRV_DBG(ERR, "fld src1 process failed\n"); 2014 goto error; 2015 } 2016 if (eval_src1) { 2017 if (unlikely(ulp_mapper_field_buffer_eval(val1, val1_len, 2018 &val1_int))) { 2019 BNXT_DRV_DBG(ERR, "fld src1 eval failed\n"); 2020 goto error; 2021 } 2022 } 2023 } 2024 2025 /* for "if then clause" set the correct process */ 2026 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) { 2027 if (value1) 2028 process_src2 = 1; 2029 else 2030 process_src3 = 1; 2031 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_TERNARY_LIST) { 2032 if (value1) { 2033 /* check if src2 is next */ 2034 if (fld->field_src2 == BNXT_ULP_FIELD_SRC_NEXT) { 2035 /* get the next field info */ 2036 if (unlikely(ulp_mapper_field_opc_next(parms, dir, 2037 fld->field_opr2, 2038 blob, is_key, 2039 name))) { 2040 BNXT_DRV_DBG(ERR, 2041 "fld next process fail\n"); 2042 goto error; 2043 } else { 2044 return rc; 2045 } 2046 } else { 2047 process_src2 = 1; 2048 } 2049 } else { 2050 /* check if src2 is next */ 2051 if (fld->field_src3 == BNXT_ULP_FIELD_SRC_NEXT) { 2052 /* get the next field info */ 2053 if (unlikely(ulp_mapper_field_opc_next(parms, dir, 2054 fld->field_opr3, 2055 blob, is_key, 2056 name))) { 2057 BNXT_DRV_DBG(ERR, 2058 "fld next process fail\n"); 2059 goto error; 2060 } else { 2061 return rc; 2062 } 2063 } else { 2064 process_src3 = 1; 2065 } 2066 } 2067 } 2068 2069 /* process src2 opcode */ 2070 if (process_src2) { 2071 if (unlikely(ulp_mapper_field_src_process(parms, fld->field_src2, 2072 fld->field_opr2, dir, is_key, 2073 fld->field_bit_size, &val2, 2074 &val2_len, &value2))) { 2075 BNXT_DRV_DBG(ERR, "fld src2 process failed\n"); 2076 goto error; 2077 } 2078 if (eval_src2) { 2079 if (unlikely(ulp_mapper_field_buffer_eval(val2, val2_len, 2080 &val2_int))) { 2081 BNXT_DRV_DBG(ERR, "fld src2 eval failed\n"); 2082 goto error; 2083 } 2084 } 2085 } 2086 2087 /* process src3 opcode */ 2088 if (process_src3) { 2089 if (unlikely(ulp_mapper_field_src_process(parms, fld->field_src3, 2090 fld->field_opr3, dir, is_key, 2091 fld->field_bit_size, &val3, 2092 &val3_len, &value3))) { 2093 BNXT_DRV_DBG(ERR, "fld src3 process failed\n"); 2094 goto error; 2095 } 2096 if (eval_src3) { 2097 if (unlikely(ulp_mapper_field_buffer_eval(val3, val3_len, 2098 &val3_int))) { 2099 BNXT_DRV_DBG(ERR, "fld src3 eval failed\n"); 2100 goto error; 2101 } 2102 } 2103 } 2104 2105 val_len = fld->field_bit_size; 2106 /* process the field opcodes */ 2107 switch (fld->field_opc) { 2108 case BNXT_ULP_FIELD_OPC_SRC1: 2109 rc = ulp_mapper_field_blob_write(fld->field_src1, 2110 blob, val1, val1_len, &val); 2111 val_len = val1_len; 2112 break; 2113 case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3: 2114 case BNXT_ULP_FIELD_OPC_TERNARY_LIST: 2115 if (value1) { 2116 rc = ulp_mapper_field_blob_write(fld->field_src2, blob, 2117 val2, val2_len, &val); 2118 val_len = val2_len; 2119 } else { 2120 rc = ulp_mapper_field_blob_write(fld->field_src3, blob, 2121 val3, val3_len, &val); 2122 val_len = val3_len; 2123 } 2124 break; 2125 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2: 2126 case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST: 2127 val_int = val1_int + val2_int; 2128 val_int = tfp_cpu_to_be_64(val_int); 2129 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 2130 if (unlikely(!val)) 2131 rc = -EINVAL; 2132 break; 2133 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2: 2134 case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST: 2135 val_int = val1_int - val2_int; 2136 val_int = tfp_cpu_to_be_64(val_int); 2137 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 2138 if (unlikely(!val)) 2139 rc = -EINVAL; 2140 break; 2141 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2: 2142 val_int = val1_int | val2_int; 2143 val_int = tfp_cpu_to_be_64(val_int); 2144 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 2145 if (unlikely(!val)) 2146 rc = -EINVAL; 2147 break; 2148 case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3: 2149 val_int = val1_int | val2_int | val3_int; 2150 val_int = tfp_cpu_to_be_64(val_int); 2151 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 2152 if (unlikely(!val)) 2153 rc = -EINVAL; 2154 break; 2155 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2: 2156 val_int = val1_int & val2_int; 2157 val_int = tfp_cpu_to_be_64(val_int); 2158 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 2159 if (unlikely(!val)) 2160 rc = -EINVAL; 2161 break; 2162 case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3: 2163 val_int = val1_int & (val2_int | val3_int); 2164 val_int = tfp_cpu_to_be_64(val_int); 2165 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size); 2166 if (unlikely(!val)) 2167 rc = -EINVAL; 2168 break; 2169 case BNXT_ULP_FIELD_OPC_SKIP: 2170 break; 2171 default: 2172 BNXT_DRV_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc); 2173 rc = -EINVAL; 2174 break; 2175 } 2176 2177 if (!rc) 2178 return rc; 2179 error: 2180 BNXT_DRV_DBG(ERR, "Error in %s:%s process %u:%u\n", name, 2181 fld->description, (val) ? write_idx : 0, val_len); 2182 return -EINVAL; 2183 } 2184 2185 /* 2186 * Result table process and fill the result blob. 2187 * data [out] - the result blob data 2188 */ 2189 int32_t 2190 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms, 2191 struct bnxt_ulp_mapper_tbl_info *tbl, 2192 struct ulp_blob *data, 2193 const char *name) 2194 { 2195 struct bnxt_ulp_mapper_field_info *dflds; 2196 uint32_t i = 0, num_flds = 0, encap_flds = 0; 2197 const struct ulp_mapper_core_ops *oper; 2198 struct ulp_blob encap_blob; 2199 int32_t rc = 0; 2200 2201 /* Get the result field list */ 2202 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds, 2203 &encap_flds); 2204 2205 /* validate the result field list counts */ 2206 if (unlikely(!dflds || (!num_flds && !encap_flds))) { 2207 BNXT_DRV_DBG(ERR, "Failed to get data fields %x:%x\n", 2208 num_flds, encap_flds); 2209 return -EINVAL; 2210 } 2211 2212 /* process the result fields */ 2213 for (i = 0; i < num_flds; i++) { 2214 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2215 &dflds[i], data, 0, name); 2216 if (unlikely(rc)) { 2217 BNXT_DRV_DBG(ERR, "result field processing failed\n"); 2218 return rc; 2219 } 2220 } 2221 2222 /* process encap fields if any */ 2223 if (encap_flds) { 2224 uint32_t pad = 0; 2225 /* Initialize the encap blob */ 2226 if (unlikely(ulp_blob_init(&encap_blob, 2227 ULP_BYTE_2_BITS(tbl->record_size), 2228 parms->device_params->encap_byte_order))) { 2229 BNXT_DRV_DBG(ERR, "blob inits failed.\n"); 2230 return -EINVAL; 2231 } 2232 for (; i < encap_flds; i++) { 2233 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2234 &dflds[i], 2235 &encap_blob, 0, name); 2236 if (unlikely(rc)) { 2237 BNXT_DRV_DBG(ERR, 2238 "encap field processing failed\n"); 2239 return rc; 2240 } 2241 } 2242 /* add the dynamic pad push */ 2243 if (parms->device_params->dynamic_sram_en) { 2244 uint16_t rec_s = ULP_BYTE_2_BITS(tbl->record_size); 2245 uint16_t blob_len; 2246 2247 oper = parms->mapper_data->mapper_oper; 2248 blob_len = ulp_blob_data_len_get(&encap_blob); 2249 2250 /* Get the padding size */ 2251 oper->ulp_mapper_core_dyn_tbl_type_get(parms, tbl, 2252 blob_len, 2253 &rec_s); 2254 pad = rec_s - blob_len; 2255 } else { 2256 pad = ULP_BYTE_2_BITS(tbl->record_size) - 2257 ulp_blob_data_len_get(&encap_blob); 2258 } 2259 if (unlikely(ulp_blob_pad_push(&encap_blob, pad) < 0)) { 2260 BNXT_DRV_DBG(ERR, "encap buffer padding failed\n"); 2261 return -EINVAL; 2262 } 2263 2264 /* perform the 64 bit byte swap */ 2265 ulp_blob_perform_64B_byte_swap(&encap_blob); 2266 /* Append encap blob to the result blob */ 2267 rc = ulp_blob_buffer_copy(data, &encap_blob); 2268 if (unlikely(rc)) { 2269 BNXT_DRV_DBG(ERR, "encap buffer copy failed\n"); 2270 return rc; 2271 } 2272 } 2273 return rc; 2274 } 2275 2276 int32_t 2277 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms, 2278 struct bnxt_ulp_mapper_tbl_info *tbl, 2279 uint64_t flow_id) 2280 { 2281 struct ulp_flow_db_res_params fid_parms; 2282 uint32_t mark, gfid, mark_flag; 2283 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 2284 int32_t rc = 0; 2285 2286 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 2287 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 2288 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2289 BNXT_ULP_ACT_BIT_MARK))) 2290 return rc; /* no need to perform gfid process */ 2291 2292 /* Get the mark id details from action property */ 2293 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 2294 sizeof(mark)); 2295 mark = tfp_be_to_cpu_32(mark); 2296 2297 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid); 2298 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID; 2299 2300 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 2301 gfid, mark); 2302 if (unlikely(rc)) { 2303 BNXT_DRV_DBG(ERR, "Failed to add mark to flow\n"); 2304 return rc; 2305 } 2306 fid_parms.direction = tbl->direction; 2307 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 2308 fid_parms.critical_resource = tbl->critical_resource; 2309 fid_parms.resource_type = mark_flag; 2310 fid_parms.resource_hndl = gfid; 2311 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 2312 2313 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2314 if (unlikely(rc)) 2315 BNXT_DRV_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 2316 return rc; 2317 } 2318 2319 int32_t 2320 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms, 2321 struct bnxt_ulp_mapper_tbl_info *tbl) 2322 { 2323 struct ulp_flow_db_res_params fid_parms; 2324 uint32_t act_idx, mark, mark_flag; 2325 uint64_t val64 = 0; 2326 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 2327 int32_t rc = 0; 2328 2329 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 2330 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION && 2331 ULP_BITMAP_ISSET(parms->act_bitmap->bits, 2332 BNXT_ULP_ACT_BIT_MARK))) 2333 return rc; /* no need to perform mark action process */ 2334 2335 /* Get the mark id details from action property */ 2336 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK], 2337 sizeof(mark)); 2338 mark = tfp_be_to_cpu_32(mark); 2339 2340 if (unlikely(ulp_regfile_read(parms->regfile, 2341 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 2342 &val64))) { 2343 BNXT_DRV_DBG(ERR, "read action ptr main failed\n"); 2344 return -EINVAL; 2345 } 2346 act_idx = tfp_be_to_cpu_64(val64); 2347 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID; 2348 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 2349 act_idx, mark); 2350 if (unlikely(rc)) { 2351 BNXT_DRV_DBG(ERR, "Failed to add mark to flow\n"); 2352 return rc; 2353 } 2354 fid_parms.direction = tbl->direction; 2355 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 2356 fid_parms.critical_resource = tbl->critical_resource; 2357 fid_parms.resource_type = mark_flag; 2358 fid_parms.resource_hndl = act_idx; 2359 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 2360 2361 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2362 if (unlikely(rc)) 2363 BNXT_DRV_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 2364 return rc; 2365 } 2366 2367 int32_t 2368 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms, 2369 struct bnxt_ulp_mapper_tbl_info *tbl) 2370 { 2371 struct ulp_flow_db_res_params fid_parms; 2372 uint32_t act_idx, mark, mark_flag; 2373 uint64_t val64 = 0; 2374 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode; 2375 int32_t rc = 0; 2376 2377 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP || 2378 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION) 2379 return rc; /* no need to perform mark action process */ 2380 2381 /* Get the mark id details from the computed field of dev port id */ 2382 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID); 2383 2384 /* Get the main action pointer */ 2385 if (unlikely(ulp_regfile_read(parms->regfile, 2386 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR, 2387 &val64))) { 2388 BNXT_DRV_DBG(ERR, "read action ptr main failed\n"); 2389 return -EINVAL; 2390 } 2391 act_idx = tfp_be_to_cpu_64(val64); 2392 2393 /* Set the mark flag to local fid and vfr flag */ 2394 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; 2395 2396 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 2397 act_idx, mark); 2398 if (unlikely(rc)) { 2399 BNXT_DRV_DBG(ERR, "Failed to add mark to flow\n"); 2400 return rc; 2401 } 2402 fid_parms.direction = tbl->direction; 2403 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 2404 fid_parms.critical_resource = tbl->critical_resource; 2405 fid_parms.resource_type = mark_flag; 2406 fid_parms.resource_hndl = act_idx; 2407 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 2408 2409 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2410 if (unlikely(rc)) 2411 BNXT_DRV_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 2412 return rc; 2413 } 2414 2415 /* Tcam table scan the identifier list and allocate each identifier */ 2416 int32_t 2417 ulp_mapper_tcam_tbl_ident_alloc(struct bnxt_ulp_mapper_parms *parms, 2418 struct bnxt_ulp_mapper_tbl_info *tbl) 2419 { 2420 struct bnxt_ulp_mapper_ident_info *idents; 2421 uint32_t num_idents; 2422 uint32_t i; 2423 2424 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents); 2425 for (i = 0; i < num_idents; i++) { 2426 if (unlikely(ulp_mapper_ident_process(parms, tbl, 2427 &idents[i], NULL))) 2428 return -EINVAL; 2429 } 2430 return 0; 2431 } 2432 2433 /* 2434 * internal function to post process key/mask blobs for dynamic pad WC tcam tbl 2435 * 2436 * parms [in] The mappers parms with data related to the flow. 2437 * 2438 * key [in] The original key to be transformed 2439 * 2440 * mask [in] The original mask to be transformed 2441 * 2442 * tkey [in/out] The transformed key 2443 * 2444 * tmask [in/out] The transformed mask 2445 * 2446 * returns zero on success, non-zero on failure 2447 */ 2448 uint32_t 2449 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms, 2450 struct ulp_blob *key, 2451 struct ulp_blob *mask, 2452 struct ulp_blob *tkey, 2453 struct ulp_blob *tmask) 2454 { 2455 uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset; 2456 uint32_t cword, i, rc; 2457 int32_t pad; 2458 uint8_t *val; 2459 2460 slice_width = dparms->wc_slice_width; 2461 clen = dparms->wc_ctl_size_bits; 2462 max_slices = dparms->wc_max_slices; 2463 blen = ulp_blob_data_len_get(key); 2464 2465 /* Get the length of the key based on number of slices and width */ 2466 num_slices = 1; 2467 tlen = slice_width; 2468 while (tlen < blen && 2469 num_slices <= max_slices) { 2470 num_slices = num_slices << 1; 2471 tlen = tlen << 1; 2472 } 2473 2474 if (unlikely(num_slices > max_slices)) { 2475 BNXT_DRV_DBG(ERR, "Key size (%d) too large for WC\n", blen); 2476 return -EINVAL; 2477 } 2478 2479 /* The key/mask may not be on a natural slice boundary, pad it */ 2480 pad = tlen - blen; 2481 if (unlikely(ulp_blob_pad_push(key, pad) < 0 || 2482 ulp_blob_pad_push(mask, pad) < 0)) { 2483 BNXT_DRV_DBG(ERR, "Unable to pad key/mask\n"); 2484 return -EINVAL; 2485 } 2486 2487 /* The new length accounts for the ctrl word length and num slices */ 2488 tlen = tlen + clen * num_slices; 2489 if (unlikely(ulp_blob_init(tkey, tlen, key->byte_order) || 2490 ulp_blob_init(tmask, tlen, mask->byte_order))) { 2491 BNXT_DRV_DBG(ERR, "Unable to post process wc tcam entry\n"); 2492 return -EINVAL; 2493 } 2494 2495 /* Build the transformed key/mask */ 2496 cword = dparms->wc_mode_list[num_slices - 1]; 2497 cword = tfp_cpu_to_be_32(cword); 2498 offset = 0; 2499 for (i = 0; i < num_slices; i++) { 2500 val = ulp_blob_push_32(tkey, &cword, clen); 2501 if (unlikely(!val)) { 2502 BNXT_DRV_DBG(ERR, "Key ctrl word push failed\n"); 2503 return -EINVAL; 2504 } 2505 val = ulp_blob_push_32(tmask, &cword, clen); 2506 if (unlikely(!val)) { 2507 BNXT_DRV_DBG(ERR, "Mask ctrl word push failed\n"); 2508 return -EINVAL; 2509 } 2510 rc = ulp_blob_append(tkey, key, offset, slice_width); 2511 if (unlikely(rc)) { 2512 BNXT_DRV_DBG(ERR, "Key blob append failed\n"); 2513 return rc; 2514 } 2515 rc = ulp_blob_append(tmask, mask, offset, slice_width); 2516 if (unlikely(rc)) { 2517 BNXT_DRV_DBG(ERR, "Mask blob append failed\n"); 2518 return rc; 2519 } 2520 offset += slice_width; 2521 } 2522 2523 /* The key/mask are byte reversed on every 4 byte chunk */ 2524 ulp_blob_perform_byte_reverse(tkey, 4); 2525 ulp_blob_perform_byte_reverse(tmask, 4); 2526 2527 return 0; 2528 } 2529 2530 /* Post process the key/mask blobs for wildcard tcam tbl */ 2531 void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob) 2532 { 2533 ulp_blob_perform_64B_word_swap(blob); 2534 ulp_blob_perform_64B_byte_swap(blob); 2535 } 2536 2537 static int32_t 2538 ulp_mapper_gen_tbl_ref_cnt_process(struct bnxt_ulp_mapper_parms *parms, 2539 struct bnxt_ulp_mapper_tbl_info *tbl, 2540 struct ulp_mapper_gen_tbl_entry *entry) 2541 { 2542 int32_t rc = 0; 2543 uint64_t val64; 2544 2545 /* Allow the template to manage the reference count */ 2546 switch (tbl->ref_cnt_opcode) { 2547 case BNXT_ULP_REF_CNT_OPC_INC: 2548 ULP_GEN_TBL_REF_CNT_INC(entry); 2549 break; 2550 case BNXT_ULP_REF_CNT_OPC_DEC: 2551 /* writes never decrement the ref count */ 2552 if (tbl->tbl_opcode == BNXT_ULP_GENERIC_TBL_OPC_WRITE) 2553 return -EINVAL; 2554 2555 ULP_GEN_TBL_REF_CNT_DEC(entry); 2556 break; 2557 case BNXT_ULP_REF_CNT_OPC_NOP: 2558 /* Nothing to be done, generally used when 2559 * template gets the ref_cnt to make a decision 2560 */ 2561 break; 2562 case BNXT_ULP_REF_CNT_OPC_DEFAULT: 2563 /* This is the default case and is backward 2564 * compatible with older templates 2565 */ 2566 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) 2567 ULP_GEN_TBL_REF_CNT_INC(entry); 2568 break; 2569 default: 2570 BNXT_DRV_DBG(ERR, "Invalid REF_CNT_OPC %d\n", 2571 tbl->ref_cnt_opcode); 2572 return -EINVAL; 2573 } 2574 2575 if (tbl->tbl_opcode == BNXT_ULP_GENERIC_TBL_OPC_READ) { 2576 /* Add ref_cnt to the regfile for template to use. */ 2577 val64 = (uint32_t)ULP_GEN_TBL_REF_CNT(entry); 2578 val64 = tfp_cpu_to_be_64(val64); 2579 rc = ulp_regfile_write(parms->regfile, 2580 BNXT_ULP_RF_IDX_REF_CNT, 2581 val64); 2582 if (unlikely(rc)) { 2583 BNXT_DRV_DBG(ERR, "Failed to write regfile[ref_cnt]\n"); 2584 return rc; 2585 } 2586 } 2587 2588 return rc; 2589 } 2590 2591 static int32_t 2592 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2593 struct bnxt_ulp_mapper_tbl_info *tbl) 2594 { 2595 struct ulp_mapper_gen_tbl_list *gen_tbl_list; 2596 struct bnxt_ulp_mapper_key_info *kflds; 2597 struct ulp_flow_db_res_params fid_parms; 2598 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g; 2599 struct ulp_gen_hash_entry_params hash_entry; 2600 enum ulp_gen_list_search_flag list_srch = ULP_GEN_LIST_SEARCH_MISSED; 2601 uint16_t keylen, datalen = 0; 2602 struct ulp_blob key, data; 2603 uint8_t *cache_key; 2604 int32_t tbl_idx; 2605 uint32_t i, num_kflds = 0, key_index = 0, num_par_kflds = 0, pad = 0; 2606 uint32_t gen_tbl_miss = 1, fdb_write = 0; 2607 uint8_t *byte_data; 2608 int32_t rc = 0; 2609 2610 /* Get the key fields list and build the key. */ 2611 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds); 2612 if (unlikely(!kflds || !num_kflds)) { 2613 BNXT_DRV_DBG(ERR, "Failed to get key fields\n"); 2614 return -EINVAL; 2615 } 2616 2617 /* Get the partial key list number*/ 2618 num_par_kflds = ulp_mapper_partial_key_fields_get(parms, tbl); 2619 2620 if (num_par_kflds) 2621 pad = ULP_BYTE_2_BITS(sizeof(uint8_t)) - 2622 ULP_BITS_IS_BYTE_NOT_ALIGNED(tbl->key_bit_size); 2623 2624 if (unlikely(ulp_blob_init(&key, tbl->key_bit_size + pad + 2625 tbl->partial_key_bit_size, 2626 parms->device_params->key_byte_order))) { 2627 BNXT_DRV_DBG(ERR, "Failed to alloc blob\n"); 2628 return -EINVAL; 2629 } 2630 for (i = 0; i < num_kflds + num_par_kflds; i++) { 2631 /* Setup the key */ 2632 rc = ulp_mapper_field_opc_process(parms, tbl->direction, 2633 &kflds[i].field_info_spec, 2634 &key, 1, "Gen Tbl Key"); 2635 if (unlikely(rc)) { 2636 BNXT_DRV_DBG(ERR, 2637 "Failed to create key for Gen tbl rc=%d\n", 2638 rc); 2639 return -EINVAL; 2640 } 2641 /* pad for the alignment between exact key and partial key */ 2642 if (num_par_kflds && i == num_kflds - 1) { 2643 if (unlikely(ulp_blob_pad_push(&key, pad) < 0)) { 2644 BNXT_DRV_DBG(ERR, "key padding failed\n"); 2645 return -EINVAL; 2646 } 2647 } 2648 } 2649 2650 /* Calculate the table index for the generic table*/ 2651 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type, 2652 tbl->direction); 2653 if (unlikely(tbl_idx < 0)) { 2654 BNXT_DRV_DBG(ERR, "Invalid table index %x:%x\n", 2655 tbl->resource_sub_type, tbl->direction); 2656 return -EINVAL; 2657 } 2658 2659 /* The_key is a byte array convert it to a search index */ 2660 cache_key = ulp_blob_data_get(&key, &keylen); 2661 2662 /* get the generic table */ 2663 gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx]; 2664 2665 /* perform basic validation of generic table */ 2666 if (unlikely((gen_tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_HASH_LIST && 2667 gen_tbl_list->hash_tbl == NULL) || 2668 gen_tbl_list->mem_data == NULL)) { 2669 BNXT_DRV_DBG(ERR, "Uninitialized gen table index %x:%x\n", 2670 tbl->resource_sub_type, tbl->direction); 2671 return -EINVAL; 2672 } 2673 2674 /* Check if generic hash table */ 2675 if (gen_tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_HASH_LIST) { 2676 if (unlikely(tbl->gen_tbl_lkup_type != 2677 BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH)) { 2678 BNXT_DRV_DBG(ERR, "%s: Invalid template lkup type\n", 2679 gen_tbl_list->gen_tbl_name); 2680 return -EINVAL; 2681 } 2682 hash_entry.key_data = cache_key; 2683 hash_entry.key_length = ULP_BITS_2_BYTE(keylen); 2684 rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl, 2685 &hash_entry); 2686 if (unlikely(rc)) { 2687 BNXT_DRV_DBG(ERR, "%s: hash tbl search failed\n", 2688 gen_tbl_list->gen_tbl_name); 2689 return rc; 2690 } 2691 if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) { 2692 key_index = hash_entry.key_idx; 2693 /* Get the generic table entry */ 2694 if (unlikely(ulp_mapper_gen_tbl_entry_get(gen_tbl_list, 2695 key_index, 2696 &gen_tbl_ent))) 2697 return -EINVAL; 2698 /* store the hash index in the fdb */ 2699 key_index = hash_entry.hash_index; 2700 } 2701 } else if (gen_tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_KEY_LIST) { 2702 /* convert key to index directly */ 2703 if (unlikely(ULP_BITS_2_BYTE(keylen) > (int32_t)sizeof(key_index))) { 2704 BNXT_DRV_DBG(ERR, "%s: keysize is bigger then 4 bytes\n", 2705 gen_tbl_list->gen_tbl_name); 2706 return -EINVAL; 2707 } 2708 memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(keylen)); 2709 /* Get the generic table entry */ 2710 if (unlikely(ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index, 2711 &gen_tbl_ent))) 2712 return -EINVAL; 2713 } else if (gen_tbl_list->tbl_type == 2714 BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST) { 2715 list_srch = ulp_gen_tbl_simple_list_search(gen_tbl_list, 2716 cache_key, 2717 &key_index); 2718 /* Get the generic table entry */ 2719 if (unlikely(ulp_mapper_gen_tbl_entry_get(gen_tbl_list, 2720 key_index, 2721 &gen_tbl_ent))) 2722 return -EINVAL; 2723 } 2724 2725 switch (tbl->tbl_opcode) { 2726 case BNXT_ULP_GENERIC_TBL_OPC_READ: 2727 if (gen_tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_HASH_LIST && 2728 gen_tbl_list->hash_tbl) { 2729 if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND) 2730 break; /* nothing to be done , no entry */ 2731 } else if (gen_tbl_list->tbl_type == 2732 BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST) { 2733 if (list_srch == ULP_GEN_LIST_SEARCH_MISSED || 2734 list_srch == ULP_GEN_LIST_SEARCH_FULL) 2735 break; 2736 } 2737 2738 /* check the reference count */ 2739 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) { 2740 g = &gen_tbl_ent; 2741 /* Scan ident list and create the result blob*/ 2742 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl, 2743 g->byte_data, 2744 g->byte_data_size, 2745 g->byte_order); 2746 if (unlikely(rc)) { 2747 BNXT_DRV_DBG(ERR, 2748 "Failed to scan ident list\n"); 2749 return -EINVAL; 2750 } 2751 2752 /* it is a hit */ 2753 gen_tbl_miss = 0; 2754 fdb_write = 1; 2755 } 2756 break; 2757 case BNXT_ULP_GENERIC_TBL_OPC_WRITE: 2758 if (gen_tbl_list->tbl_type == BNXT_ULP_GEN_TBL_TYPE_HASH_LIST && 2759 gen_tbl_list->hash_tbl) { 2760 rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list, 2761 &hash_entry, 2762 &gen_tbl_ent); 2763 if (unlikely(rc)) 2764 return rc; 2765 /* store the hash index in the fdb */ 2766 key_index = hash_entry.hash_index; 2767 } else if (gen_tbl_list->tbl_type == 2768 BNXT_ULP_GEN_TBL_TYPE_SIMPLE_LIST) { 2769 if (unlikely(list_srch == ULP_GEN_LIST_SEARCH_FULL)) { 2770 BNXT_DRV_DBG(ERR, "failed to add gen entry\n"); 2771 return -ENOMEM; 2772 } 2773 } 2774 2775 /* check the reference count and ignore ref_cnt if NOP. 2776 * NOP allows a write as an update. 2777 */ 2778 if (unlikely(tbl->ref_cnt_opcode != BNXT_ULP_REF_CNT_OPC_NOP && 2779 ULP_GEN_TBL_REF_CNT(&gen_tbl_ent))) { 2780 /* a hit then error */ 2781 BNXT_DRV_DBG(ERR, "generic entry already present\n"); 2782 return -EINVAL; /* success */ 2783 } 2784 2785 /* Initialize the blob data */ 2786 if (unlikely(ulp_blob_init(&data, tbl->result_bit_size, 2787 gen_tbl_ent.byte_order))) { 2788 BNXT_DRV_DBG(ERR, "Failed initial index table blob\n"); 2789 return -EINVAL; 2790 } 2791 2792 /* Get the result fields list */ 2793 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 2794 "Gen tbl Result"); 2795 if (unlikely(rc)) { 2796 BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 2797 return rc; 2798 } 2799 byte_data = ulp_blob_data_get(&data, &datalen); 2800 rc = ulp_mapper_gen_tbl_entry_data_set(gen_tbl_list, 2801 &gen_tbl_ent, 2802 cache_key, 2803 ULP_BITS_2_BYTE(keylen), 2804 byte_data, 2805 ULP_BITS_2_BYTE(datalen) 2806 ); 2807 if (unlikely(rc)) { 2808 BNXT_DRV_DBG(ERR, "Failed to write generic table\n"); 2809 return -EINVAL; 2810 } 2811 2812 fdb_write = 1; 2813 parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index; 2814 break; 2815 default: 2816 BNXT_DRV_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode); 2817 return -EINVAL; 2818 } 2819 2820 /* Set the generic entry hit */ 2821 rc = ulp_regfile_write(parms->regfile, 2822 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, 2823 tfp_cpu_to_be_64(gen_tbl_miss)); 2824 if (unlikely(rc)) { 2825 BNXT_DRV_DBG(ERR, "Write regfile[%d] failed\n", 2826 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); 2827 return -EIO; 2828 } 2829 2830 /* add the entry to the flow database */ 2831 if (fdb_write) { 2832 memset(&fid_parms, 0, sizeof(fid_parms)); 2833 fid_parms.direction = tbl->direction; 2834 fid_parms.resource_func = tbl->resource_func; 2835 fid_parms.resource_sub_type = tbl->resource_sub_type; 2836 fid_parms.resource_hndl = key_index; 2837 fid_parms.critical_resource = tbl->critical_resource; 2838 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 2839 2840 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2841 if (unlikely(rc)) { 2842 BNXT_DRV_DBG(ERR, "Fail to add gen ent flowdb %d\n", 2843 rc); 2844 return rc; 2845 } 2846 2847 /* Reset the in-flight RID when generic table is written and the 2848 * rid has been pushed into a handle (rid or fid). Once it has 2849 * been written, we have persistent accounting of the resources. 2850 */ 2851 if (tbl->tbl_opcode == BNXT_ULP_GENERIC_TBL_OPC_WRITE && 2852 (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE || 2853 tbl->fdb_opcode == BNXT_ULP_FDB_OPC_PUSH_FID)) 2854 parms->rid = 0; 2855 2856 rc = ulp_mapper_gen_tbl_ref_cnt_process(parms, tbl, 2857 &gen_tbl_ent); 2858 } 2859 2860 return rc; 2861 } 2862 2863 static int32_t 2864 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2865 struct bnxt_ulp_mapper_tbl_info *tbl) 2866 { 2867 int32_t rc = 0; 2868 uint64_t val64 = 0; 2869 uint32_t rid; 2870 2871 /* process the fdb opcode for alloc push */ 2872 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) { 2873 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl); 2874 if (unlikely(rc)) { 2875 BNXT_DRV_DBG(ERR, "Failed to do fdb alloc\n"); 2876 return rc; 2877 } 2878 } else if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_DELETE_RID_REGFILE) { 2879 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand, &val64); 2880 if (unlikely(rc)) { 2881 BNXT_DRV_DBG(ERR, "Failed to get RID from regfile\n"); 2882 return rc; 2883 } 2884 rid = (uint32_t)tfp_be_to_cpu_64(val64); 2885 rc = ulp_mapper_resources_free(parms->ulp_ctx, 2886 BNXT_ULP_FDB_TYPE_RID, 2887 rid, 2888 NULL); 2889 } 2890 2891 return rc; 2892 } 2893 2894 static int32_t 2895 ulp_mapper_vnic_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2896 struct bnxt_ulp_mapper_tbl_info *tbl) 2897 { 2898 struct ulp_flow_db_res_params fid_parms; 2899 uint16_t vnic_idx = 0, vnic_id = 0; 2900 int32_t rc = 0; 2901 2902 switch (tbl->resource_sub_type) { 2903 case BNXT_ULP_RESOURCE_SUB_TYPE_VNIC_TABLE_RSS: 2904 if (unlikely(tbl->tbl_opcode != BNXT_ULP_VNIC_TBL_OPC_ALLOC_WR_REGFILE)) { 2905 BNXT_DRV_DBG(ERR, "Invalid vnic table opcode\n"); 2906 return -EINVAL; 2907 } 2908 rc = bnxt_pmd_rss_action_create(parms, &vnic_idx, &vnic_id); 2909 if (unlikely(rc)) { 2910 BNXT_DRV_DBG(ERR, "Failed create rss action\n"); 2911 return rc; 2912 } 2913 break; 2914 case BNXT_ULP_RESOURCE_SUB_TYPE_VNIC_TABLE_QUEUE: 2915 if (unlikely(tbl->tbl_opcode != BNXT_ULP_VNIC_TBL_OPC_ALLOC_WR_REGFILE)) { 2916 BNXT_DRV_DBG(ERR, "Invalid vnic table opcode\n"); 2917 return -EINVAL; 2918 } 2919 rc = bnxt_pmd_queue_action_create(parms, &vnic_idx, &vnic_id); 2920 if (unlikely(rc)) { 2921 BNXT_DRV_DBG(ERR, "Failed create queue action\n"); 2922 return rc; 2923 } 2924 break; 2925 default: 2926 BNXT_DRV_DBG(ERR, "Invalid vnic table sub type\n"); 2927 return -EINVAL; 2928 } 2929 2930 /* Link the created vnic to the flow in the flow db */ 2931 memset(&fid_parms, 0, sizeof(fid_parms)); 2932 fid_parms.direction = tbl->direction; 2933 fid_parms.resource_func = tbl->resource_func; 2934 fid_parms.resource_type = tbl->resource_type; 2935 fid_parms.resource_sub_type = tbl->resource_sub_type; 2936 fid_parms.resource_hndl = vnic_idx; 2937 fid_parms.critical_resource = tbl->critical_resource; 2938 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2939 if (unlikely(rc)) { 2940 BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2941 rc); 2942 return rc; 2943 } 2944 rc = ulp_regfile_write(parms->regfile, tbl->tbl_operand, 2945 (uint64_t)tfp_cpu_to_be_64(vnic_id)); 2946 if (unlikely(rc)) 2947 BNXT_DRV_DBG(ERR, "Failed to write regfile[%d] rc=%d\n", 2948 tbl->tbl_operand, rc); 2949 2950 return rc; 2951 } 2952 2953 static int32_t 2954 ulp_mapper_stats_cache_tbl_process(struct bnxt_ulp_mapper_parms *parms, 2955 struct bnxt_ulp_mapper_tbl_info *tbl) 2956 { 2957 struct ulp_flow_db_res_params fid_parms; 2958 uint64_t counter_handle; 2959 struct ulp_blob data; 2960 uint16_t data_len = 0; 2961 uint8_t *tmp_data; 2962 int32_t rc = 0; 2963 2964 /* Initialize the blob data */ 2965 if (unlikely(ulp_blob_init(&data, tbl->result_bit_size, 2966 BNXT_ULP_BYTE_ORDER_BE))) { 2967 BNXT_DRV_DBG(ERR, "Failed initial ulp_global table blob\n"); 2968 return -EINVAL; 2969 } 2970 2971 /* read the arguments from the result table */ 2972 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 2973 "ULP Global Result"); 2974 if (unlikely(rc)) { 2975 BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 2976 return rc; 2977 } 2978 2979 tmp_data = ulp_blob_data_get(&data, &data_len); 2980 counter_handle = *(uint64_t *)tmp_data; 2981 counter_handle = tfp_be_to_cpu_64(counter_handle); 2982 2983 memset(&fid_parms, 0, sizeof(fid_parms)); 2984 fid_parms.direction = tbl->direction; 2985 fid_parms.resource_func = tbl->resource_func; 2986 fid_parms.resource_type = tbl->resource_type; 2987 fid_parms.resource_sub_type = tbl->resource_sub_type; 2988 fid_parms.resource_hndl = counter_handle; 2989 fid_parms.critical_resource = tbl->critical_resource; 2990 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 2991 if (unlikely(rc)) { 2992 BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 2993 rc); 2994 return rc; 2995 } 2996 2997 rc = ulp_sc_mgr_entry_alloc(parms, counter_handle, tbl); 2998 if (unlikely(rc)) { 2999 BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 3000 rc); 3001 return rc; 3002 } 3003 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 3004 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 3005 BNXT_DRV_DBG(DEBUG, "flow id =0x%x\n", parms->flow_id); 3006 #endif 3007 #endif 3008 return rc; 3009 } 3010 3011 static int32_t 3012 ulp_mapper_stats_cache_tbl_res_free(struct bnxt_ulp_context *ulp, 3013 uint32_t fid) 3014 { 3015 ulp_sc_mgr_entry_free(ulp, fid); 3016 return 0; 3017 } 3018 3019 /* Free the vnic resource */ 3020 static int32_t 3021 ulp_mapper_vnic_tbl_res_free(struct bnxt_ulp_context *ulp __rte_unused, 3022 struct bnxt *bp, 3023 struct ulp_flow_db_res_params *res) 3024 { 3025 uint16_t vnic_idx = res->resource_hndl; 3026 3027 if (res->resource_sub_type == 3028 BNXT_ULP_RESOURCE_SUB_TYPE_VNIC_TABLE_QUEUE) 3029 return bnxt_pmd_queue_action_delete(bp, vnic_idx); 3030 else 3031 return bnxt_pmd_rss_action_delete(bp, vnic_idx); 3032 } 3033 3034 static int32_t 3035 ulp_mapper_global_res_free(struct bnxt_ulp_context *ulp, 3036 struct bnxt *bp __rte_unused, 3037 struct ulp_flow_db_res_params *res) 3038 { 3039 uint64_t handle = res->resource_hndl; 3040 3041 return bnxt_pmd_global_tunnel_set(ulp, 0, res->resource_sub_type, 3042 0, &handle); 3043 } 3044 3045 static int32_t 3046 ulp_mapper_global_register_tbl_process(struct bnxt_ulp_mapper_parms *parms, 3047 struct bnxt_ulp_mapper_tbl_info *tbl) 3048 { 3049 struct ulp_flow_db_res_params fid_parms = { 0 }; 3050 struct ulp_blob data; 3051 uint16_t data_len = 0; 3052 uint8_t *tmp_data; 3053 uint16_t udp_port; 3054 uint64_t handle; 3055 int32_t rc = 0, write_reg = 0; 3056 3057 /* Initialize the blob data */ 3058 if (unlikely(ulp_blob_init(&data, tbl->result_bit_size, 3059 BNXT_ULP_BYTE_ORDER_BE))) { 3060 BNXT_DRV_DBG(ERR, "Failed initial ulp_global table blob\n"); 3061 return -EINVAL; 3062 } 3063 3064 /* read the arguments from the result table */ 3065 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, 3066 "ULP Global Result"); 3067 if (unlikely(rc)) { 3068 BNXT_DRV_DBG(ERR, "Failed to build the result blob\n"); 3069 return rc; 3070 } 3071 3072 switch (tbl->tbl_opcode) { 3073 case BNXT_ULP_GLOBAL_REGISTER_TBL_OPC_WR_REGFILE: 3074 write_reg = 1; 3075 break; 3076 case BNXT_ULP_GLOBAL_REGISTER_TBL_OPC_NOT_USED: 3077 break; 3078 default: 3079 BNXT_DRV_DBG(ERR, "Invalid global table opcode %d\n", 3080 tbl->tbl_opcode); 3081 return -EINVAL; 3082 } 3083 3084 tmp_data = ulp_blob_data_get(&data, &data_len); 3085 udp_port = *((uint16_t *)tmp_data); 3086 udp_port = tfp_be_to_cpu_16(udp_port); 3087 3088 rc = bnxt_pmd_global_tunnel_set(parms->ulp_ctx, 3089 parms->port_id, tbl->resource_sub_type, 3090 udp_port, &handle); 3091 if (unlikely(rc)) { 3092 BNXT_DRV_DBG(ERR, "Unable to set Type %d port\n", 3093 tbl->resource_sub_type); 3094 return rc; 3095 } 3096 3097 /* Set the common pieces of fid parms */ 3098 fid_parms.direction = tbl->direction; 3099 fid_parms.resource_func = tbl->resource_func; 3100 fid_parms.resource_sub_type = tbl->resource_sub_type; 3101 fid_parms.critical_resource = tbl->critical_resource; 3102 fid_parms.resource_hndl = handle; 3103 3104 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 3105 3106 if (unlikely(rc)) 3107 return rc; 3108 3109 /* write to the regfile if opcode is set */ 3110 if (write_reg) { 3111 rc = ulp_regfile_write(parms->regfile, 3112 tbl->tbl_operand, 3113 tfp_cpu_to_be_64(handle)); 3114 if (rc) 3115 BNXT_DRV_DBG(ERR, "Regfile[%d] write failed.\n", 3116 tbl->tbl_operand); 3117 } 3118 3119 return rc; 3120 } 3121 3122 static int32_t 3123 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 3124 struct bnxt_ulp_mapper_data *mapper_data) 3125 { 3126 struct bnxt_ulp_glb_resource_info *glb_res; 3127 uint32_t num_entries = 0, idx, dev_id; 3128 uint8_t app_id; 3129 int32_t rc = 0; 3130 3131 glb_res = ulp_mapper_glb_resource_info_list_get(&num_entries); 3132 /* Check if there are no resources */ 3133 if (!num_entries) 3134 return 0; 3135 3136 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 3137 if (unlikely(rc)) { 3138 BNXT_DRV_DBG(ERR, "Failed to get device id for glb init (%d)\n", 3139 rc); 3140 return rc; 3141 } 3142 3143 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 3144 if (unlikely(rc)) { 3145 BNXT_DRV_DBG(ERR, "Failed to get app id for glb init (%d)\n", 3146 rc); 3147 return rc; 3148 } 3149 3150 /* Iterate the global resources and process each one */ 3151 for (idx = 0; idx < num_entries; idx++) { 3152 if (dev_id != glb_res[idx].device_id || 3153 glb_res[idx].app_id != app_id) 3154 continue; 3155 switch (glb_res[idx].resource_func) { 3156 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 3157 rc = ulp_mapper_resource_ident_allocate(ulp_ctx, 3158 mapper_data, 3159 &glb_res[idx], 3160 false); 3161 break; 3162 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 3163 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx, 3164 mapper_data, 3165 &glb_res[idx], 3166 false); 3167 break; 3168 default: 3169 BNXT_DRV_DBG(ERR, "Global resource %x not supported\n", 3170 glb_res[idx].resource_func); 3171 rc = -EINVAL; 3172 break; 3173 } 3174 if (rc) 3175 return rc; 3176 } 3177 return rc; 3178 } 3179 3180 /* 3181 * Iterate over the shared resources assigned during tf_open_session and store 3182 * them in the global regfile with the shared flag. 3183 */ 3184 static int32_t 3185 ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx, 3186 struct bnxt_ulp_mapper_data *mapper_data) 3187 { 3188 const struct ulp_mapper_core_ops *op = mapper_data->mapper_oper; 3189 3190 return op->ulp_mapper_core_app_glb_res_info_init(ulp_ctx, mapper_data); 3191 } 3192 3193 /* 3194 * Common conditional opcode process routine that is used for both the template 3195 * rejection and table conditional execution. 3196 */ 3197 static int32_t 3198 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms, 3199 enum bnxt_ulp_cond_opc opc, 3200 uint64_t operand, 3201 int32_t *res) 3202 { 3203 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT; 3204 uint32_t field_size = 0; 3205 int32_t rc = 0; 3206 uint8_t bit, tmp; 3207 uint64_t regval = 0, result = 0; 3208 3209 switch (opc) { 3210 case BNXT_ULP_COND_OPC_CF_IS_SET: 3211 if (operand < BNXT_ULP_CF_IDX_LAST) { 3212 result = ULP_COMP_FLD_IDX_RD(parms, operand); 3213 } else { 3214 BNXT_DRV_DBG(ERR, 3215 "comp field out of bounds %" PRIu64 "\n", 3216 operand); 3217 rc = -EINVAL; 3218 } 3219 break; 3220 case BNXT_ULP_COND_OPC_CF_NOT_SET: 3221 if (likely(operand < BNXT_ULP_CF_IDX_LAST)) { 3222 result = !ULP_COMP_FLD_IDX_RD(parms, operand); 3223 } else { 3224 BNXT_DRV_DBG(ERR, 3225 "comp field out of bounds %" PRIu64 "\n", 3226 operand); 3227 rc = -EINVAL; 3228 } 3229 break; 3230 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET: 3231 if (likely(operand < BNXT_ULP_ACT_BIT_LAST)) { 3232 result = ULP_BITMAP_ISSET(parms->act_bitmap->bits, 3233 operand); 3234 } else { 3235 BNXT_DRV_DBG(ERR, 3236 "action bit out of bounds %" PRIu64 "\n", 3237 operand); 3238 rc = -EINVAL; 3239 } 3240 break; 3241 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET: 3242 if (likely(operand < BNXT_ULP_ACT_BIT_LAST)) { 3243 result = !ULP_BITMAP_ISSET(parms->act_bitmap->bits, 3244 operand); 3245 } else { 3246 BNXT_DRV_DBG(ERR, 3247 "action bit out of bounds %" PRIu64 "\n", 3248 operand); 3249 rc = -EINVAL; 3250 } 3251 break; 3252 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET: 3253 if (likely(operand < BNXT_ULP_HDR_BIT_LAST)) { 3254 result = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 3255 operand); 3256 } else { 3257 BNXT_DRV_DBG(ERR, 3258 "header bit out of bounds %" PRIu64 "\n", 3259 operand); 3260 rc = -EINVAL; 3261 } 3262 break; 3263 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET: 3264 if (likely(operand < BNXT_ULP_HDR_BIT_LAST)) { 3265 result = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, 3266 operand); 3267 } else { 3268 BNXT_DRV_DBG(ERR, 3269 "header bit out of bounds %" PRIu64 "\n", 3270 operand); 3271 rc = -EINVAL; 3272 } 3273 break; 3274 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET: 3275 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3276 if (unlikely(rc)) { 3277 BNXT_DRV_DBG(ERR, 3278 "invalid ulp_glb_field_tbl idx %" PRIu64 "\n", 3279 operand); 3280 return -EINVAL; 3281 } 3282 result = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 3283 break; 3284 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET: 3285 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3286 if (unlikely(rc)) { 3287 BNXT_DRV_DBG(ERR, 3288 "invalid ulp_glb_field_tbl idx %" PRIu64 "\n", 3289 operand); 3290 return -EINVAL; 3291 } 3292 result = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit); 3293 break; 3294 case BNXT_ULP_COND_OPC_RF_IS_SET: 3295 if (ulp_regfile_read(parms->regfile, operand, ®val)) { 3296 BNXT_DRV_DBG(ERR, 3297 "regfile[%" PRIu64 "] read oob\n", 3298 operand); 3299 return -EINVAL; 3300 } 3301 result = regval != 0; 3302 break; 3303 case BNXT_ULP_COND_OPC_RF_NOT_SET: 3304 if (unlikely(ulp_regfile_read(parms->regfile, operand, ®val))) { 3305 BNXT_DRV_DBG(ERR, 3306 "regfile[%" PRIu64 "] read oob\n", operand); 3307 return -EINVAL; 3308 } 3309 result = regval == 0; 3310 break; 3311 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH: 3312 result = parms->flow_pattern_id == operand; 3313 break; 3314 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH: 3315 result = parms->act_pattern_id == operand; 3316 break; 3317 case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET: 3318 if (unlikely(bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype))) { 3319 BNXT_DRV_DBG(ERR, "Failed to get the mem type\n"); 3320 return -EINVAL; 3321 } 3322 result = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1; 3323 break; 3324 case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET: 3325 if (unlikely(bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype))) { 3326 BNXT_DRV_DBG(ERR, "Failed to get the mem type\n"); 3327 return -EINVAL; 3328 } 3329 result = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0; 3330 break; 3331 case BNXT_ULP_COND_OPC_ENC_HDR_BIT_IS_SET: 3332 if (likely(operand < BNXT_ULP_HDR_BIT_LAST)) { 3333 result = ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, 3334 operand); 3335 } else { 3336 BNXT_DRV_DBG(ERR, 3337 "header bit out of bounds %" PRIu64 "\n", 3338 operand); 3339 rc = -EINVAL; 3340 } 3341 break; 3342 case BNXT_ULP_COND_OPC_ENC_HDR_BIT_NOT_SET: 3343 if (likely(operand < BNXT_ULP_HDR_BIT_LAST)) { 3344 result = !ULP_BITMAP_ISSET(parms->enc_hdr_bitmap->bits, 3345 operand); 3346 } else { 3347 BNXT_DRV_DBG(ERR, 3348 "header bit out of bounds %" PRIu64 "\n", 3349 operand); 3350 rc = -EINVAL; 3351 } 3352 break; 3353 case BNXT_ULP_COND_OPC_ACT_PROP_IS_SET: 3354 case BNXT_ULP_COND_OPC_ACT_PROP_NOT_SET: 3355 /* only supporting 1-byte action properties for now */ 3356 if (unlikely(operand >= BNXT_ULP_ACT_PROP_IDX_LAST)) { 3357 BNXT_DRV_DBG(ERR, 3358 "act_prop[%" PRIu64 "] oob\n", operand); 3359 return -EINVAL; 3360 } 3361 field_size = ulp_mapper_act_prop_size_get(operand); 3362 if (unlikely(sizeof(tmp) != field_size)) { 3363 BNXT_DRV_DBG(ERR, 3364 "act_prop[%" PRIu64 "] field mismatch %u\n", 3365 operand, field_size); 3366 return -EINVAL; 3367 } 3368 tmp = parms->act_prop->act_details[operand]; 3369 if (opc == BNXT_ULP_COND_OPC_ACT_PROP_IS_SET) 3370 result = (int32_t)(tmp); 3371 else 3372 result = (int32_t)(!tmp); 3373 break; 3374 case BNXT_ULP_COND_OPC_CF_BIT_IS_SET: 3375 case BNXT_ULP_COND_OPC_CF_BIT_NOT_SET: 3376 if (likely(operand < BNXT_ULP_CF_BIT_LAST)) { 3377 result = ULP_BITMAP_ISSET(parms->cf_bitmap, operand); 3378 } else { 3379 BNXT_DRV_DBG(ERR, 3380 "CF bit out of bounds %" PRIx64 "\n", 3381 operand); 3382 rc = -EINVAL; 3383 } 3384 if (opc == BNXT_ULP_COND_OPC_CF_BIT_NOT_SET) 3385 result = !result; 3386 break; 3387 case BNXT_ULP_COND_OPC_WC_FIELD_BIT_IS_SET: 3388 case BNXT_ULP_COND_OPC_WC_FIELD_BIT_NOT_SET: 3389 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3390 if (unlikely(rc)) { 3391 BNXT_DRV_DBG(ERR, 3392 "invalid ulp_glb_field idx %" PRIu64 "\n", 3393 operand); 3394 return -EINVAL; 3395 } 3396 result = ULP_INDEX_BITMAP_GET(parms->wc_field_bitmap, bit); 3397 if (opc == BNXT_ULP_COND_OPC_WC_FIELD_BIT_NOT_SET) 3398 result = !result; 3399 break; 3400 case BNXT_ULP_COND_OPC_EXCLUDE_FIELD_BIT_IS_SET: 3401 case BNXT_ULP_COND_OPC_EXCLUDE_FIELD_BIT_NOT_SET: 3402 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit); 3403 if (unlikely(rc)) { 3404 BNXT_DRV_DBG(ERR, 3405 "invalid ulp_glb_field idx %" PRIu64 "\n", 3406 operand); 3407 return -EINVAL; 3408 } 3409 result = ULP_INDEX_BITMAP_GET(parms->exclude_field_bitmap, bit); 3410 if (opc == BNXT_ULP_COND_OPC_EXCLUDE_FIELD_BIT_NOT_SET) 3411 result = !result; 3412 break; 3413 case BNXT_ULP_COND_OPC_FEATURE_BIT_IS_SET: 3414 case BNXT_ULP_COND_OPC_FEATURE_BIT_NOT_SET: 3415 regval = bnxt_ulp_feature_bits_get(parms->ulp_ctx); 3416 result = ULP_BITMAP_ISSET(regval, operand); 3417 if (opc == BNXT_ULP_COND_OPC_FEATURE_BIT_NOT_SET) 3418 result = !ULP_BITMAP_ISSET(regval, operand); 3419 break; 3420 default: 3421 BNXT_DRV_DBG(ERR, "Invalid conditional opcode %d\n", opc); 3422 rc = -EINVAL; 3423 break; 3424 } 3425 3426 *res = !!result; 3427 return (rc); 3428 } 3429 3430 static int32_t 3431 ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms, 3432 enum tf_dir dir, 3433 enum bnxt_ulp_func_src func_src, 3434 uint64_t func_opr, 3435 uint64_t *result) 3436 { 3437 uint64_t regval; 3438 bool shared; 3439 3440 *result = false; 3441 switch (func_src) { 3442 case BNXT_ULP_FUNC_SRC_COMP_FIELD: 3443 if (unlikely(func_opr >= BNXT_ULP_CF_IDX_LAST)) { 3444 BNXT_DRV_DBG(ERR, "invalid index %u\n", 3445 (uint32_t)func_opr); 3446 return -EINVAL; 3447 } 3448 *result = ULP_COMP_FLD_IDX_RD(parms, func_opr); 3449 break; 3450 case BNXT_ULP_FUNC_SRC_REGFILE: 3451 if (unlikely(ulp_regfile_read(parms->regfile, func_opr, ®val))) { 3452 BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n", 3453 (uint32_t)func_opr); 3454 return -EINVAL; 3455 } 3456 *result = tfp_be_to_cpu_64(regval); 3457 break; 3458 case BNXT_ULP_FUNC_SRC_GLB_REGFILE: 3459 if (unlikely(ulp_mapper_glb_resource_read(parms->mapper_data, dir, 3460 func_opr, ®val, &shared))) { 3461 BNXT_DRV_DBG(ERR, "global regfile[%d] read failed.\n", 3462 (uint32_t)func_opr); 3463 return -EINVAL; 3464 } 3465 *result = tfp_be_to_cpu_64(regval); 3466 break; 3467 case BNXT_ULP_FUNC_SRC_CONST: 3468 *result = func_opr; 3469 break; 3470 case BNXT_ULP_FUNC_SRC_ACTION_BITMAP: 3471 *result = parms->act_bitmap->bits; 3472 break; 3473 case BNXT_ULP_FUNC_SRC_HEADER_BITMAP: 3474 *result = parms->hdr_bitmap->bits; 3475 break; 3476 default: 3477 BNXT_DRV_DBG(ERR, "invalid src code %u\n", func_src); 3478 return -EINVAL; 3479 } 3480 return 0; 3481 } 3482 3483 static int32_t 3484 ulp_mapper_vfr_mark_set(struct bnxt_ulp_mapper_parms *parms, 3485 uint32_t key, uint16_t port_id, 3486 struct bnxt_ulp_mapper_tbl_info *tbl) 3487 { 3488 struct ulp_flow_db_res_params fid_parms; 3489 uint32_t mark_flag; 3490 int32_t rc; 3491 3492 /* Set the mark flag to local fid and vfr flag */ 3493 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID; 3494 3495 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag, 3496 key, port_id); 3497 if (unlikely(rc)) { 3498 BNXT_DRV_DBG(ERR, "Failed to add mark to flow\n"); 3499 return rc; 3500 } 3501 fid_parms.direction = tbl->direction; 3502 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID; 3503 fid_parms.critical_resource = tbl->critical_resource; 3504 fid_parms.resource_type = mark_flag; 3505 fid_parms.resource_hndl = key; 3506 fid_parms.resource_sub_type = 0; 3507 ulp_flow_db_shared_session_set(&fid_parms, tbl->session_type); 3508 3509 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 3510 if (rc) { 3511 int32_t trc = 0; 3512 BNXT_DRV_DBG(ERR, "Fail to link res to flow rc = %d\n", rc); 3513 trc = ulp_mark_db_mark_del(parms->ulp_ctx, mark_flag, key); 3514 if (trc) 3515 BNXT_DRV_DBG(ERR, 3516 "Failed to cleanup mark rc = %d\n", rc); 3517 } 3518 return rc; 3519 } 3520 3521 static int32_t 3522 ulp_mapper_bd_act_set(struct bnxt_ulp_mapper_parms *parms __rte_unused, 3523 uint16_t port_id, uint32_t action) 3524 { 3525 return bnxt_pmd_bd_act_set(port_id, action); 3526 } 3527 3528 /* oper size is in bits and res size are in bytes */ 3529 static int32_t 3530 ulp_mapper_func_cond_list_process(struct bnxt_ulp_mapper_parms *parms, 3531 uint32_t idx, uint8_t dir, 3532 uint32_t oper_size, uint64_t *res, 3533 uint32_t res_size) 3534 { 3535 struct bnxt_ulp_mapper_field_info *fld; 3536 uint8_t *val = NULL; 3537 uint32_t val_len = 0; 3538 uint64_t value = 0; 3539 uint16_t ext_idx = 0; 3540 uint8_t *res_local = (uint8_t *)res; 3541 3542 /* Get the field info from the key ext list */ 3543 fld = ulp_mapper_tmpl_key_ext_list_get(parms, idx); 3544 if (unlikely(fld == NULL || fld->field_opc != 3545 BNXT_ULP_FIELD_OPC_TERNARY_LIST)) { 3546 BNXT_DRV_DBG(ERR, "Invalid field idx %d\n", idx); 3547 return -EINVAL; 3548 } 3549 3550 /* process the condition list */ 3551 if (unlikely(ulp_mapper_field_src_process(parms, fld->field_src1, 3552 fld->field_opr1, dir, 3553 1, oper_size, &val, 3554 &val_len, &value))) { 3555 BNXT_DRV_DBG(ERR, "error processing func opcode %u\n", 3556 idx); 3557 return -EINVAL; 3558 } 3559 if (value) { 3560 if (fld->field_src2 == BNXT_ULP_FIELD_SRC_NEXT) { 3561 /* read the next key ext table index */ 3562 if (unlikely(ulp_operand_read(fld->field_opr2, 3563 (uint8_t *)&ext_idx, 3564 sizeof(uint16_t)))) { 3565 BNXT_DRV_DBG(ERR, 3566 "field idx operand read failed\n"); 3567 return -EINVAL; 3568 } 3569 ext_idx = tfp_be_to_cpu_16(ext_idx); 3570 return ulp_mapper_func_cond_list_process(parms, ext_idx, 3571 dir, oper_size, 3572 res, res_size); 3573 } else { 3574 /* get the value from then part */ 3575 if (unlikely(ulp_mapper_field_src_process(parms, fld->field_src2, 3576 fld->field_opr2, dir, 3577 1, oper_size, 3578 &val, &val_len, 3579 &value))) { 3580 BNXT_DRV_DBG(ERR, 3581 "error processing func oper %u\n", 3582 ext_idx); 3583 return -EINVAL; 3584 } 3585 } 3586 } else { 3587 if (fld->field_src3 == BNXT_ULP_FIELD_SRC_NEXT) { 3588 /* read the next key ext table index */ 3589 if (unlikely(ulp_operand_read(fld->field_opr3, 3590 (uint8_t *)&ext_idx, 3591 sizeof(uint16_t)))) { 3592 BNXT_DRV_DBG(ERR, 3593 "field idx operand read failed\n"); 3594 return -EINVAL; 3595 } 3596 ext_idx = tfp_be_to_cpu_16(ext_idx); 3597 return ulp_mapper_func_cond_list_process(parms, ext_idx, 3598 dir, oper_size, 3599 res, res_size); 3600 } else { 3601 /* get the value from else part */ 3602 if (unlikely(ulp_mapper_field_src_process(parms, fld->field_src3, 3603 fld->field_opr3, dir, 3604 1, oper_size, 3605 &val, &val_len, 3606 &value))) { 3607 BNXT_DRV_DBG(ERR, 3608 "error processing func oper %u\n", 3609 ext_idx); 3610 return -EINVAL; 3611 } 3612 } 3613 } 3614 /* write the value into result */ 3615 ulp_operand_read(val, res_local + res_size - 3616 ULP_BITS_2_BYTE_NR(oper_size), 3617 ULP_BITS_2_BYTE_NR(val_len)); 3618 3619 /* convert the data to cpu format */ 3620 *res = tfp_be_to_cpu_64(*res); 3621 return 0; 3622 } 3623 3624 static int32_t 3625 ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms, 3626 struct bnxt_ulp_mapper_tbl_info *tbl) 3627 { 3628 const struct ulp_mapper_core_ops *op = parms->mapper_data->mapper_oper; 3629 struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info; 3630 uint64_t res = 0, res1 = 0, res2 = 0; 3631 int32_t rc = 0; 3632 uint32_t process_src1 = 0, process_src2 = 0; 3633 3634 /* determine which functional operands to compute */ 3635 switch (func_info->func_opc) { 3636 case BNXT_ULP_FUNC_OPC_NOP: 3637 return rc; 3638 case BNXT_ULP_FUNC_OPC_EQ: 3639 case BNXT_ULP_FUNC_OPC_NE: 3640 case BNXT_ULP_FUNC_OPC_GE: 3641 case BNXT_ULP_FUNC_OPC_GT: 3642 case BNXT_ULP_FUNC_OPC_LE: 3643 case BNXT_ULP_FUNC_OPC_LT: 3644 case BNXT_ULP_FUNC_OPC_LEFT_SHIFT: 3645 case BNXT_ULP_FUNC_OPC_RIGHT_SHIFT: 3646 case BNXT_ULP_FUNC_OPC_BIT_OR: 3647 case BNXT_ULP_FUNC_OPC_BIT_AND: 3648 case BNXT_ULP_FUNC_OPC_BIT_XOR: 3649 case BNXT_ULP_FUNC_OPC_LOG_OR: 3650 case BNXT_ULP_FUNC_OPC_LOG_AND: 3651 case BNXT_ULP_FUNC_OPC_ADD: 3652 case BNXT_ULP_FUNC_OPC_SUB: 3653 process_src1 = 1; 3654 process_src2 = 1; 3655 break; 3656 case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: 3657 process_src1 = 1; 3658 break; 3659 case BNXT_ULP_FUNC_OPC_HANDLE_TO_OFFSET: 3660 case BNXT_ULP_FUNC_OPC_VFR_MARK_SET: 3661 case BNXT_ULP_FUNC_OPC_BD_ACT_SET: 3662 process_src1 = 1; 3663 process_src2 = 1; 3664 break; 3665 case BNXT_ULP_FUNC_OPC_NOT_NOT: 3666 process_src1 = 1; 3667 case BNXT_ULP_FUNC_OPC_COND_LIST: 3668 break; 3669 case BNXT_ULP_FUNC_OPC_PORT_TABLE: 3670 process_src1 = 1; 3671 process_src2 = 1; 3672 break; 3673 default: 3674 break; 3675 } 3676 3677 if (process_src1) { 3678 rc = ulp_mapper_func_opr_compute(parms, tbl->direction, 3679 func_info->func_src1, 3680 func_info->func_opr1, &res1); 3681 if (rc) 3682 return rc; 3683 } 3684 3685 if (process_src2) { 3686 rc = ulp_mapper_func_opr_compute(parms, tbl->direction, 3687 func_info->func_src2, 3688 func_info->func_opr2, &res2); 3689 if (rc) 3690 return rc; 3691 } 3692 3693 /* perform the functional opcode operations */ 3694 switch (func_info->func_opc) { 3695 case BNXT_ULP_FUNC_OPC_EQ: 3696 if (res1 == res2) 3697 res = 1; 3698 break; 3699 case BNXT_ULP_FUNC_OPC_NE: 3700 if (res1 != res2) 3701 res = 1; 3702 break; 3703 case BNXT_ULP_FUNC_OPC_GE: 3704 if (res1 >= res2) 3705 res = 1; 3706 break; 3707 case BNXT_ULP_FUNC_OPC_GT: 3708 if (res1 > res2) 3709 res = 1; 3710 break; 3711 case BNXT_ULP_FUNC_OPC_LE: 3712 if (res1 <= res2) 3713 res = 1; 3714 break; 3715 case BNXT_ULP_FUNC_OPC_LT: 3716 if (res1 < res2) 3717 res = 1; 3718 break; 3719 case BNXT_ULP_FUNC_OPC_LEFT_SHIFT: 3720 res = res1 << res2; 3721 break; 3722 case BNXT_ULP_FUNC_OPC_RIGHT_SHIFT: 3723 res = res1 >> res2; 3724 break; 3725 case BNXT_ULP_FUNC_OPC_ADD: 3726 res = res1 + res2; 3727 break; 3728 case BNXT_ULP_FUNC_OPC_SUB: 3729 res = res1 - res2; 3730 break; 3731 case BNXT_ULP_FUNC_OPC_NOT_NOT: 3732 res = !!res1; 3733 break; 3734 case BNXT_ULP_FUNC_OPC_BIT_AND: 3735 res = res1 & res2; 3736 break; 3737 case BNXT_ULP_FUNC_OPC_BIT_OR: 3738 res = res1 | res2; 3739 break; 3740 case BNXT_ULP_FUNC_OPC_BIT_XOR: 3741 res = res1 ^ res2; 3742 break; 3743 case BNXT_ULP_FUNC_OPC_LOG_AND: 3744 res = res1 && res2; 3745 break; 3746 case BNXT_ULP_FUNC_OPC_LOG_OR: 3747 res = res1 || res2; 3748 break; 3749 case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF: 3750 res = res1; 3751 break; 3752 case BNXT_ULP_FUNC_OPC_RSS_CONFIG: 3753 /* apply the rss config using pmd method */ 3754 return bnxt_rss_config_action_apply(parms); 3755 case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR: 3756 rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res); 3757 if (unlikely(rc)) 3758 return -EINVAL; 3759 res = tfp_be_to_cpu_64(res); 3760 break; 3761 case BNXT_ULP_FUNC_OPC_HANDLE_TO_OFFSET: 3762 rc = op->ulp_mapper_core_handle_to_offset(parms, res1, 3763 res2, &res); 3764 break; 3765 case BNXT_ULP_FUNC_OPC_VFR_MARK_SET: 3766 /* res1 is key, res2 is portid */ 3767 return ulp_mapper_vfr_mark_set(parms, res1, res2, tbl); 3768 case BNXT_ULP_FUNC_OPC_BD_ACT_SET: 3769 /* res1 is port_id, res2 is action */ 3770 return ulp_mapper_bd_act_set(parms, res1, res2); 3771 case BNXT_ULP_FUNC_OPC_COND_LIST: 3772 if (unlikely(func_info->func_src1 != BNXT_ULP_FUNC_SRC_KEY_EXT_LIST)) { 3773 BNXT_DRV_DBG(ERR, "invalid func source %u\n", 3774 func_info->func_opc); 3775 return -EINVAL; 3776 } 3777 if (ulp_mapper_func_cond_list_process(parms, 3778 func_info->func_opr1, 3779 tbl->direction, 3780 func_info->func_oper_size, 3781 &res, sizeof(res))) 3782 return -EINVAL; 3783 break; 3784 case BNXT_ULP_FUNC_OPC_PORT_TABLE: 3785 rc = ulp_mapper_field_port_db_write(parms, res1, 3786 func_info->func_dst_opr, 3787 (uint8_t *)&res2, 3788 func_info->func_oper_size); 3789 return rc; 3790 default: 3791 BNXT_DRV_DBG(ERR, "invalid func code %u\n", 3792 func_info->func_opc); 3793 return -EINVAL; 3794 } 3795 if (unlikely(ulp_regfile_write(parms->regfile, func_info->func_dst_opr, 3796 tfp_cpu_to_be_64(res)))) { 3797 BNXT_DRV_DBG(ERR, "Failed write the func_opc %u\n", 3798 func_info->func_dst_opr); 3799 return -EINVAL; 3800 } 3801 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 3802 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_MAPPER 3803 BNXT_DRV_DBG(DEBUG, "write the %" PRIX64 " into func_opc %u\n", res, 3804 func_info->func_dst_opr); 3805 #endif 3806 #endif 3807 3808 return rc; 3809 } 3810 3811 /* 3812 * Processes a list of conditions and returns both a status and result of the 3813 * list. The status must be checked prior to verifying the result. 3814 * 3815 * returns 0 for success, negative on failure 3816 * returns res = 1 for true, res = 0 for false. 3817 */ 3818 static int32_t 3819 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms, 3820 struct bnxt_ulp_mapper_cond_list_info *info, 3821 int32_t *res) 3822 { 3823 struct bnxt_ulp_mapper_cond_info *cond_list; 3824 int32_t rc = 0, trc = 0; 3825 uint32_t i; 3826 3827 switch (info->cond_list_opcode) { 3828 case BNXT_ULP_COND_LIST_OPC_AND: 3829 /* AND Defaults to true. */ 3830 *res = 1; 3831 break; 3832 case BNXT_ULP_COND_LIST_OPC_OR: 3833 /* OR Defaults to false. */ 3834 *res = 0; 3835 break; 3836 case BNXT_ULP_COND_LIST_OPC_TRUE: 3837 *res = 1; 3838 return rc; 3839 case BNXT_ULP_COND_LIST_OPC_FALSE: 3840 *res = 0; 3841 return rc; 3842 default: 3843 BNXT_DRV_DBG(ERR, "Invalid conditional list opcode %d\n", 3844 info->cond_list_opcode); 3845 *res = 0; 3846 return -EINVAL; 3847 } 3848 3849 cond_list = ulp_mapper_tmpl_cond_list_get(parms, info->cond_start_idx); 3850 for (i = 0; i < info->cond_nums; i++) { 3851 rc = ulp_mapper_cond_opc_process(parms, 3852 cond_list[i].cond_opcode, 3853 cond_list[i].cond_operand, 3854 &trc); 3855 if (unlikely(rc)) 3856 return rc; 3857 3858 if (info->cond_list_opcode == BNXT_ULP_COND_LIST_OPC_AND) { 3859 /* early return if result is ever zero */ 3860 if (!trc) { 3861 *res = trc; 3862 return rc; 3863 } 3864 } else { 3865 /* early return if result is ever non-zero */ 3866 if (trc) { 3867 *res = trc; 3868 return rc; 3869 } 3870 } 3871 } 3872 3873 return rc; 3874 } 3875 3876 static int32_t 3877 ulp_mapper_cond_reject_list_process(struct bnxt_ulp_mapper_parms *parms, 3878 uint32_t tid, int32_t *res) 3879 { 3880 struct bnxt_ulp_mapper_cond_list_info *reject_info; 3881 struct bnxt_ulp_mapper_cond_list_info *oper; 3882 int32_t cond_list_res = 0, cond_res = 0, rc = 0; 3883 uint32_t idx; 3884 3885 /* set the rejection result to accept */ 3886 *res = 0; 3887 3888 /* get the reject condition list */ 3889 reject_info = ulp_mapper_tmpl_reject_list_get(parms, tid); 3890 3891 if (reject_info->cond_list_opcode == BNXT_ULP_COND_LIST_OPC_TRUE) { 3892 cond_list_res = 1; 3893 goto jump_exit; 3894 } 3895 3896 /* If there are no reject conditions then skip */ 3897 if (!reject_info->cond_nums) 3898 return rc; 3899 3900 /* Iterate the list to process the conditions */ 3901 if (reject_info->cond_list_opcode == BNXT_ULP_COND_LIST_OPC_LIST_AND || 3902 reject_info->cond_list_opcode == BNXT_ULP_COND_LIST_OPC_LIST_OR) { 3903 /* Initialize the cond result */ 3904 if (reject_info->cond_list_opcode == 3905 BNXT_ULP_COND_LIST_OPC_LIST_AND) 3906 cond_res = 1; 3907 3908 for (idx = reject_info->cond_start_idx; 3909 idx < reject_info->cond_start_idx + 3910 reject_info->cond_nums; idx++) { 3911 oper = ulp_mapper_cond_oper_list_get(parms, idx); 3912 if (unlikely(!oper)) { 3913 BNXT_DRV_DBG(ERR, 3914 "Invalid cond oper idx %d\n", 3915 idx); 3916 return -EINVAL; 3917 } 3918 rc = ulp_mapper_cond_opc_list_process(parms, oper, 3919 &cond_list_res); 3920 /* if any error, then return */ 3921 if (rc) 3922 goto jump_exit; 3923 3924 /* early return if result is ever zero */ 3925 if (cond_res /*and */ && !cond_list_res /*false*/) 3926 goto jump_exit; 3927 3928 /* early return if result is ever non-zero */ 3929 if (!cond_res /*or */ && cond_list_res /*true*/) 3930 goto jump_exit; 3931 } 3932 } else { 3933 rc = ulp_mapper_cond_opc_list_process(parms, reject_info, 3934 &cond_list_res); 3935 } 3936 jump_exit: 3937 *res = cond_list_res; 3938 /* Reject the template if True */ 3939 if (cond_list_res) 3940 BNXT_DRV_DBG(ERR, "%s Template %d rejected.\n", 3941 ulp_mapper_tmpl_name_str(parms->tmpl_type), tid); 3942 return rc; 3943 } 3944 3945 static int32_t 3946 ulp_mapper_cond_execute_list_process(struct bnxt_ulp_mapper_parms *parms, 3947 struct bnxt_ulp_mapper_tbl_info *tbl, 3948 int32_t *res) 3949 { 3950 struct bnxt_ulp_mapper_cond_list_info *execute_info; 3951 struct bnxt_ulp_mapper_cond_list_info *oper; 3952 int32_t cond_list_res = 0, cond_res = 0, rc = 0; 3953 uint32_t idx; 3954 3955 /* set the execute result to true */ 3956 *res = 1; 3957 execute_info = &tbl->execute_info; 3958 3959 /* If there are no execute conditions then skip */ 3960 if (!execute_info->cond_nums) 3961 return rc; 3962 3963 /* Iterate the list to process the conditions */ 3964 if (execute_info->cond_list_opcode == BNXT_ULP_COND_LIST_OPC_LIST_AND || 3965 execute_info->cond_list_opcode == BNXT_ULP_COND_LIST_OPC_LIST_OR) { 3966 /* Initialize the cond result */ 3967 if (execute_info->cond_list_opcode == 3968 BNXT_ULP_COND_LIST_OPC_LIST_AND) 3969 cond_res = 1; 3970 3971 for (idx = execute_info->cond_start_idx; 3972 idx < execute_info->cond_start_idx + 3973 execute_info->cond_nums; idx++) { 3974 oper = ulp_mapper_cond_oper_list_get(parms, idx); 3975 if (unlikely(!oper)) { 3976 BNXT_DRV_DBG(ERR, 3977 "Invalid cond oper idx %d\n", 3978 idx); 3979 return -EINVAL; 3980 } 3981 rc = ulp_mapper_cond_opc_list_process(parms, oper, 3982 &cond_list_res); 3983 /* if any error, then return */ 3984 if (rc) 3985 goto jump_exit; 3986 3987 /* early return if result is ever zero */ 3988 if (cond_res /*and */ && !cond_list_res /*false*/) 3989 goto jump_exit; 3990 3991 /* early return if result is ever non-zero */ 3992 if (!cond_res /*or */ && cond_list_res /*true*/) 3993 goto jump_exit; 3994 } 3995 } else { 3996 rc = ulp_mapper_cond_opc_list_process(parms, execute_info, 3997 &cond_list_res); 3998 } 3999 jump_exit: 4000 *res = cond_list_res; 4001 return rc; 4002 } 4003 4004 /* 4005 * Processes conflict resolution and returns both a status and result. 4006 * The status must be checked prior to verifying the result. 4007 * 4008 * returns 0 for success, negative on failure 4009 * returns res = 1 for true, res = 0 for false. 4010 */ 4011 static int32_t 4012 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms, 4013 struct bnxt_ulp_mapper_tbl_info *tbl, 4014 int32_t *res) 4015 { 4016 int32_t rc = 0; 4017 uint64_t regval = 0; 4018 uint64_t comp_sig; 4019 4020 *res = 0; 4021 switch (tbl->accept_opcode) { 4022 case BNXT_ULP_ACCEPT_OPC_ALWAYS: 4023 *res = 1; 4024 break; 4025 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH: 4026 /* perform the signature validation*/ 4027 if (tbl->resource_func == 4028 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) { 4029 /* Perform the check that generic table is hit or not */ 4030 if (unlikely(ulp_regfile_read(parms->regfile, 4031 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS, 4032 ®val))) { 4033 BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n", 4034 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS); 4035 return -EINVAL; 4036 } 4037 if (regval) { 4038 /* not a hit so no need to check flow sign*/ 4039 *res = 1; 4040 return rc; 4041 } 4042 } 4043 /* compare the new flow signature against stored one */ 4044 if (unlikely(ulp_regfile_read(parms->regfile, 4045 BNXT_ULP_RF_IDX_FLOW_SIG_ID, 4046 ®val))) { 4047 BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n", 4048 BNXT_ULP_RF_IDX_FLOW_SIG_ID); 4049 return -EINVAL; 4050 } 4051 comp_sig = ULP_COMP_FLD_IDX_RD(parms, 4052 BNXT_ULP_CF_IDX_FLOW_SIG_ID); 4053 regval = tfp_be_to_cpu_64(regval); 4054 if (likely(comp_sig == regval)) 4055 *res = 1; 4056 else 4057 BNXT_DRV_DBG(ERR, "failed signature match 0x%016" 4058 PRIX64 ":%x\n", comp_sig, (uint32_t)regval); 4059 break; 4060 default: 4061 BNXT_DRV_DBG(ERR, "Invalid accept opcode %d\n", 4062 tbl->accept_opcode); 4063 return -EINVAL; 4064 } 4065 return rc; 4066 } 4067 4068 static int32_t 4069 ulp_mapper_allocator_tbl_process(struct bnxt_ulp_mapper_parms *parms, 4070 struct bnxt_ulp_mapper_tbl_info *tbl) 4071 { 4072 struct ulp_flow_db_res_params fid_parms; 4073 int32_t alloc_index, rc = 0; 4074 uint64_t regval = 0; 4075 4076 /* Only Alloc opcode is supported for now */ 4077 if (tbl->tbl_opcode != BNXT_ULP_ALLOC_TBL_OPC_ALLOC) 4078 return 0; /* nothing to done */ 4079 4080 /* allocate the index from the allocator */ 4081 rc = ulp_allocator_tbl_list_alloc(parms->mapper_data, 4082 tbl->resource_sub_type, 4083 tbl->direction, &alloc_index); 4084 if (unlikely(rc)) { 4085 BNXT_DRV_DBG(ERR, "unable to alloc index %x:%x\n", 4086 tbl->resource_sub_type, tbl->direction); 4087 return -EINVAL; 4088 } 4089 4090 /* Write to the regfile */ 4091 regval = rte_cpu_to_be_64(alloc_index); 4092 rc = ulp_regfile_write(parms->regfile, tbl->tbl_operand, regval); 4093 if (unlikely(rc)) { 4094 BNXT_DRV_DBG(ERR, "Failed to write regfile[%d] rc=%d\n", 4095 tbl->tbl_operand, rc); 4096 return -EINVAL; 4097 } 4098 4099 /* update the flow database */ 4100 memset(&fid_parms, 0, sizeof(fid_parms)); 4101 fid_parms.direction = tbl->direction; 4102 fid_parms.resource_func = tbl->resource_func; 4103 fid_parms.resource_type = tbl->resource_type; 4104 fid_parms.resource_sub_type = tbl->resource_sub_type; 4105 fid_parms.resource_hndl = alloc_index; 4106 fid_parms.critical_resource = tbl->critical_resource; 4107 4108 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms); 4109 if (unlikely(rc)) { 4110 BNXT_DRV_DBG(ERR, "Failed to link resource to flow rc = %d\n", 4111 rc); 4112 goto error; 4113 } 4114 return rc; 4115 error: 4116 /* Free the allocated index */ 4117 (void)ulp_allocator_tbl_list_free(parms->mapper_data, 4118 tbl->resource_sub_type, 4119 tbl->direction, alloc_index); 4120 return rc; 4121 } 4122 4123 static int32_t 4124 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, void *error) 4125 { 4126 struct bnxt_ulp_mapper_tbl_info *tbls; 4127 struct bnxt_ulp_mapper_tbl_info *tbl; 4128 uint32_t num_tbls, tbl_idx; 4129 const struct ulp_mapper_core_ops *oper; 4130 int32_t rc = -EINVAL, cond_rc = 0; 4131 int32_t cond_goto = 1; 4132 uint32_t tid; 4133 4134 oper = parms->mapper_data->mapper_oper; 4135 4136 /* assign the template id based on template type */ 4137 tid = (parms->tmpl_type == BNXT_ULP_TEMPLATE_TYPE_ACTION) ? 4138 parms->act_tid : parms->class_tid; 4139 4140 rc = ulp_mapper_cond_reject_list_process(parms, tid, &cond_rc); 4141 /* if rc is failure or cond_rc is a reject then exit tbl processing */ 4142 if (unlikely(rc || cond_rc)) 4143 return -EINVAL; 4144 4145 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls); 4146 if (unlikely(!tbls || !num_tbls)) { 4147 BNXT_DRV_DBG(ERR, "No %s tables for %d:%d\n", 4148 ulp_mapper_tmpl_name_str(parms->tmpl_type), 4149 parms->dev_id, tid); 4150 return -EINVAL; 4151 } 4152 4153 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) { 4154 tbl = &tbls[tbl_idx]; 4155 cond_goto = tbl->execute_info.cond_true_goto; 4156 /* Process the conditional func code opcodes */ 4157 if (unlikely(ulp_mapper_func_info_process(parms, tbl))) { 4158 BNXT_DRV_DBG(ERR, "Failed to process cond update\n"); 4159 rc = -EINVAL; 4160 goto error; 4161 } 4162 4163 /* process the execute info of the table */ 4164 rc = ulp_mapper_cond_execute_list_process(parms, tbl, &cond_rc); 4165 if (unlikely(rc)) { 4166 BNXT_DRV_DBG(ERR, "Failed to proc cond opc list (%d)\n", 4167 rc); 4168 goto error; 4169 } 4170 /* Skip the table if False */ 4171 if (!cond_rc) { 4172 cond_goto = tbl->execute_info.cond_false_goto; 4173 goto next_iteration; 4174 } 4175 4176 switch (tbl->resource_func) { 4177 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 4178 rc = oper->ulp_mapper_core_tcam_tbl_process(parms, tbl); 4179 break; 4180 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 4181 rc = oper->ulp_mapper_core_em_tbl_process(parms, tbl, 4182 error); 4183 break; 4184 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 4185 rc = oper->ulp_mapper_core_index_tbl_process(parms, 4186 tbl); 4187 break; 4188 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE: 4189 rc = oper->ulp_mapper_core_if_tbl_process(parms, tbl); 4190 break; 4191 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 4192 rc = ulp_mapper_gen_tbl_process(parms, tbl); 4193 break; 4194 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE: 4195 rc = ulp_mapper_ctrl_tbl_process(parms, tbl); 4196 break; 4197 case BNXT_ULP_RESOURCE_FUNC_VNIC_TABLE: 4198 rc = ulp_mapper_vnic_tbl_process(parms, tbl); 4199 break; 4200 case BNXT_ULP_RESOURCE_FUNC_GLOBAL_REGISTER_TABLE: 4201 rc = ulp_mapper_global_register_tbl_process(parms, tbl); 4202 break; 4203 case BNXT_ULP_RESOURCE_FUNC_CMM_TABLE: 4204 case BNXT_ULP_RESOURCE_FUNC_CMM_STAT: 4205 rc = oper->ulp_mapper_core_cmm_tbl_process(parms, tbl, 4206 error); 4207 break; 4208 case BNXT_ULP_RESOURCE_FUNC_INVALID: 4209 rc = 0; 4210 break; 4211 case BNXT_ULP_RESOURCE_FUNC_KEY_RECIPE_TABLE: 4212 rc = ulp_mapper_key_recipe_tbl_process(parms, tbl); 4213 break; 4214 case BNXT_ULP_RESOURCE_FUNC_ALLOCATOR_TABLE: 4215 rc = ulp_mapper_allocator_tbl_process(parms, tbl); 4216 break; 4217 case BNXT_ULP_RESOURCE_FUNC_STATS_CACHE: 4218 rc = ulp_mapper_stats_cache_tbl_process(parms, tbl); 4219 break; 4220 default: 4221 BNXT_DRV_DBG(ERR, "Unexpected mapper resource %d\n", 4222 tbl->resource_func); 4223 rc = -EINVAL; 4224 goto error; 4225 } 4226 4227 if (rc) { 4228 BNXT_DRV_DBG(ERR, "Resource type %d failed\n", 4229 tbl->resource_func); 4230 goto error; 4231 } 4232 4233 /* perform the post table process */ 4234 rc = ulp_mapper_conflict_resolution_process(parms, tbl, 4235 &cond_rc); 4236 if (unlikely(rc || !cond_rc)) { 4237 BNXT_DRV_DBG(ERR, "Failed due to conflict resolution\n"); 4238 rc = -EINVAL; 4239 goto error; 4240 } 4241 next_iteration: 4242 if (cond_goto < 0) { 4243 if (unlikely(((int32_t)tbl_idx + cond_goto) < 0)) { 4244 BNXT_DRV_DBG(ERR, 4245 "invalid conditional goto %d\n", 4246 cond_goto); 4247 goto error; 4248 } 4249 } else if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) { 4250 if (tbl->false_message || tbl->true_message) { 4251 const char *msg = (tbl->false_message) ? 4252 tbl->false_message : 4253 tbl->true_message; 4254 4255 BNXT_DRV_DBG(DEBUG, "%s\n", msg); 4256 if (unlikely(error)) 4257 rte_flow_error_set(error, EINVAL, 4258 RTE_FLOW_ERROR_TYPE_ITEM, 4259 NULL, msg); 4260 return -EINVAL; 4261 } 4262 BNXT_DRV_DBG(ERR, "reject the flow\n"); 4263 rc = -EINVAL; 4264 goto error; 4265 } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) { 4266 int32_t rf_idx; 4267 uint64_t regval = 0; 4268 4269 /* least significant 16 bits from reg_file index */ 4270 rf_idx = (int32_t)(cond_goto & 0xFFFF); 4271 if (unlikely(ulp_regfile_read(parms->regfile, rf_idx, 4272 ®val))) { 4273 BNXT_DRV_DBG(ERR, "regfile[%d] read oob\n", 4274 rf_idx); 4275 rc = -EINVAL; 4276 goto error; 4277 } 4278 cond_goto = (int32_t)regval; 4279 } 4280 tbl_idx += cond_goto; 4281 } 4282 4283 return rc; 4284 error: 4285 BNXT_DRV_DBG(ERR, "%s tables failed operation for %d:%d\n", 4286 ulp_mapper_tmpl_name_str(parms->tmpl_type), 4287 parms->dev_id, tid); 4288 return rc; 4289 } 4290 4291 static int32_t 4292 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp, 4293 uint32_t fid, 4294 struct ulp_flow_db_res_params *res, 4295 void *error) 4296 { 4297 const struct ulp_mapper_core_ops *mapper_op; 4298 struct bnxt_ulp_mapper_data *mdata; 4299 int32_t rc = 0; 4300 4301 if (unlikely(!res || !ulp)) { 4302 BNXT_DRV_DBG(ERR, "Unable to free resource\n "); 4303 return -EINVAL; 4304 } 4305 4306 mapper_op = ulp_mapper_data_oper_get(ulp); 4307 switch (res->resource_func) { 4308 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 4309 rc = mapper_op->ulp_mapper_core_tcam_entry_free(ulp, res); 4310 break; 4311 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 4312 rc = mapper_op->ulp_mapper_core_em_entry_free(ulp, res, error); 4313 break; 4314 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 4315 rc = mapper_op->ulp_mapper_core_index_entry_free(ulp, res); 4316 break; 4317 case BNXT_ULP_RESOURCE_FUNC_CMM_TABLE: 4318 case BNXT_ULP_RESOURCE_FUNC_CMM_STAT: 4319 rc = mapper_op->ulp_mapper_core_cmm_entry_free(ulp, res, error); 4320 break; 4321 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 4322 rc = mapper_op->ulp_mapper_core_ident_free(ulp, res); 4323 break; 4324 case BNXT_ULP_RESOURCE_FUNC_HW_FID: 4325 rc = ulp_mapper_mark_free(ulp, res); 4326 break; 4327 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW: 4328 rc = ulp_mapper_parent_flow_free(ulp, fid, res); 4329 break; 4330 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW: 4331 rc = ulp_mapper_child_flow_free(ulp, fid, res); 4332 break; 4333 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE: 4334 rc = ulp_mapper_gen_tbl_res_free(ulp, fid, res); 4335 break; 4336 case BNXT_ULP_RESOURCE_FUNC_VNIC_TABLE: 4337 rc = ulp_mapper_vnic_tbl_res_free(ulp, ulp->bp, res); 4338 break; 4339 case BNXT_ULP_RESOURCE_FUNC_GLOBAL_REGISTER_TABLE: 4340 rc = ulp_mapper_global_res_free(ulp, ulp->bp, res); 4341 break; 4342 case BNXT_ULP_RESOURCE_FUNC_KEY_RECIPE_TABLE: 4343 rc = ulp_mapper_key_recipe_free(ulp, res->direction, 4344 res->resource_sub_type, 4345 res->resource_hndl); 4346 break; 4347 case BNXT_ULP_RESOURCE_FUNC_ALLOCATOR_TABLE: 4348 mdata = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp); 4349 if (unlikely(!mdata)) { 4350 BNXT_DRV_DBG(ERR, "Unable to get mapper data\n"); 4351 return -EINVAL; 4352 } 4353 rc = ulp_allocator_tbl_list_free(mdata, 4354 res->resource_sub_type, 4355 res->direction, 4356 res->resource_hndl); 4357 break; 4358 case BNXT_ULP_RESOURCE_FUNC_STATS_CACHE: 4359 rc = ulp_mapper_stats_cache_tbl_res_free(ulp, 4360 fid); 4361 break; 4362 default: 4363 break; 4364 } 4365 4366 return rc; 4367 } 4368 4369 int32_t 4370 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx, 4371 enum bnxt_ulp_fdb_type flow_type, 4372 uint32_t fid, 4373 void *error) 4374 { 4375 struct ulp_flow_db_res_params res_parms = { 0 }; 4376 int32_t rc, trc, frc = 0; 4377 4378 if (unlikely(!ulp_ctx)) { 4379 BNXT_DRV_DBG(ERR, "Invalid parms, unable to free flow\n"); 4380 return -EINVAL; 4381 } 4382 4383 /* 4384 * Set the critical resource on the first resource del, then iterate 4385 * while status is good 4386 */ 4387 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES; 4388 4389 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms); 4390 4391 if (rc) { 4392 /* 4393 * This is unexpected on the first call to resource del. 4394 * It likely means that the flow did not exist in the flow db. 4395 */ 4396 BNXT_DRV_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n", 4397 flow_type, fid, rc); 4398 return rc; 4399 } 4400 4401 while (!rc) { 4402 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms, error); 4403 if (trc) { 4404 /* 4405 * On fail, we still need to attempt to free the 4406 * remaining resources. Don't return 4407 */ 4408 BNXT_DRV_DBG(ERR, 4409 "Flow[%d][0x%x] Res[%d][0x%016" PRIX64 4410 "] failed rc=%d.\n", 4411 flow_type, fid, res_parms.resource_func, 4412 res_parms.resource_hndl, trc); 4413 4414 /* Capture error in final rc */ 4415 frc = trc; 4416 } 4417 /* All subsequent call require the non-critical_resource */ 4418 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO; 4419 4420 rc = ulp_flow_db_resource_del(ulp_ctx, 4421 flow_type, 4422 fid, 4423 &res_parms); 4424 } 4425 4426 /* Expected that flow_db should return no entry */ 4427 if (rc != -ENOENT) 4428 frc = rc; 4429 4430 /* Free the Flow ID since we've removed all resources */ 4431 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid); 4432 4433 /* Ensure that any error will be reported */ 4434 if (rc) 4435 frc = rc; 4436 4437 #ifdef TF_FLOW_SCALE_QUERY 4438 /* update for regular flows only */ 4439 if (flow_type == BNXT_ULP_FDB_TYPE_REGULAR) 4440 ulp_resc_usage_sync(ulp_ctx); 4441 #endif /* TF_FLOW_SCALE_QUERY */ 4442 4443 return frc; 4444 } 4445 4446 static void 4447 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx, 4448 struct bnxt_ulp_mapper_data *mapper_data) 4449 { 4450 struct bnxt_ulp_mapper_glb_resource_entry *ent; 4451 struct ulp_flow_db_res_params res; 4452 uint32_t dir, idx; 4453 4454 /* Iterate the global resources and process each one */ 4455 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) { 4456 for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) { 4457 ent = &mapper_data->glb_res_tbl[dir][idx]; 4458 if (ent->resource_func == 4459 BNXT_ULP_RESOURCE_FUNC_INVALID || 4460 ent->shared) 4461 continue; 4462 memset(&res, 0, sizeof(struct ulp_flow_db_res_params)); 4463 res.resource_func = ent->resource_func; 4464 res.direction = dir; 4465 res.resource_type = ent->resource_type; 4466 /*convert it from BE to cpu */ 4467 res.resource_hndl = 4468 tfp_be_to_cpu_64(ent->resource_hndl); 4469 ulp_mapper_resource_free(ulp_ctx, 0, &res, NULL); 4470 } 4471 } 4472 } 4473 4474 int32_t 4475 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx, 4476 enum bnxt_ulp_fdb_type flow_type, 4477 uint32_t fid, 4478 void *error) 4479 { 4480 int32_t rc; 4481 4482 if (unlikely(!ulp_ctx)) { 4483 BNXT_DRV_DBG(ERR, "Invalid parms, unable to free flow\n"); 4484 return -EINVAL; 4485 } 4486 4487 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid, error); 4488 return rc; 4489 } 4490 4491 /* Function to handle the mapping of the Flow to be compatible 4492 * with the underlying hardware. 4493 */ 4494 int32_t 4495 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx, 4496 struct bnxt_ulp_mapper_parms *parms, void *error) 4497 { 4498 const struct ulp_mapper_core_ops *oper; 4499 struct ulp_regfile regfile; 4500 int32_t rc = 0, trc; 4501 4502 if (unlikely(!ulp_ctx || !parms)) 4503 return -EINVAL; 4504 4505 parms->regfile = ®file; 4506 parms->ulp_ctx = ulp_ctx; 4507 4508 oper = ulp_mapper_data_oper_get(ulp_ctx); 4509 4510 /* Get the device id from the ulp context */ 4511 if (unlikely(bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms->dev_id))) { 4512 BNXT_DRV_DBG(ERR, "Invalid ulp context\n"); 4513 return -EINVAL; 4514 } 4515 if (unlikely(bnxt_ulp_cntxt_fid_get(ulp_ctx, &parms->fw_fid))) { 4516 BNXT_DRV_DBG(ERR, "Unable to get the func_id\n"); 4517 return -EINVAL; 4518 } 4519 4520 /* Get the device params, it will be used in later processing */ 4521 parms->device_params = bnxt_ulp_device_params_get(parms->dev_id); 4522 if (unlikely(!parms->device_params)) { 4523 BNXT_DRV_DBG(ERR, "No device parms for device id %d\n", 4524 parms->dev_id); 4525 return -EINVAL; 4526 } 4527 4528 /* 4529 * Get the mapper data for dynamic mapper data such as default 4530 * ids. 4531 */ 4532 parms->mapper_data = (struct bnxt_ulp_mapper_data *) 4533 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 4534 if (unlikely(!parms->mapper_data)) { 4535 BNXT_DRV_DBG(ERR, "Failed to get the ulp mapper data\n"); 4536 return -EINVAL; 4537 } 4538 4539 /* initialize the registry file for further processing */ 4540 if (unlikely(ulp_regfile_init(parms->regfile))) { 4541 BNXT_DRV_DBG(ERR, "regfile initialization failed.\n"); 4542 return -EINVAL; 4543 } 4544 4545 /* Start batching */ 4546 rc = oper->ulp_mapper_mpc_batch_start(&parms->batch_info); 4547 if (unlikely(rc)) { 4548 BNXT_DRV_DBG(ERR, "MPC Batch start failed\n"); 4549 return -EINVAL; 4550 } 4551 4552 /* Process the action template list from the selected action table*/ 4553 if (parms->act_tid) { 4554 parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION; 4555 /* Process the action template tables */ 4556 rc = ulp_mapper_tbls_process(parms, error); 4557 if (unlikely(rc)) 4558 goto batch_error; 4559 } 4560 4561 if (parms->class_tid) { 4562 parms->tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS; 4563 /* Process the class template tables.*/ 4564 rc = ulp_mapper_tbls_process(parms, error); 4565 if (unlikely(rc)) 4566 goto batch_error; 4567 } 4568 4569 if (oper->ulp_mapper_mpc_batch_started(&parms->batch_info)) { 4570 /* Should only get here is there were no EM inserts */ 4571 rc = oper->ulp_mapper_mpc_batch_end(&ulp_ctx->bp->tfcp, 4572 &parms->batch_info); 4573 if (unlikely(rc)) { 4574 BNXT_DRV_DBG(ERR, "MPC Batch end failed\n"); 4575 goto flow_error; 4576 } 4577 } 4578 4579 /* setup the parent-child details */ 4580 if (parms->parent_flow) { 4581 /* create a parent flow details */ 4582 rc = ulp_flow_db_parent_flow_create(parms); 4583 if (unlikely(rc)) 4584 goto flow_error; 4585 } else if (parms->child_flow) { 4586 /* create a child flow details */ 4587 rc = ulp_flow_db_child_flow_create(parms); 4588 if (unlikely(rc)) 4589 goto flow_error; 4590 } 4591 4592 #ifdef TF_FLOW_SCALE_QUERY 4593 ulp_resc_usage_sync(ulp_ctx); 4594 #endif /* TF_FLOW_SCALE_QUERY */ 4595 4596 return rc; 4597 4598 batch_error: 4599 /* 4600 * An error occurred after batching had started but before it 4601 * ended. Call batch end and ignore any errors. 4602 */ 4603 if (oper->ulp_mapper_mpc_batch_started(&parms->batch_info)) 4604 oper->ulp_mapper_mpc_batch_end(&ulp_ctx->bp->tfcp, 4605 &parms->batch_info); 4606 4607 flow_error: 4608 if (parms->rid) { 4609 /* An RID was in-flight but not pushed, free the resources */ 4610 trc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_RID, 4611 parms->rid, NULL); 4612 if (trc) 4613 BNXT_DRV_DBG(ERR, 4614 "Failed to free resources rid=0x%08x rc=%d\n", 4615 parms->rid, trc); 4616 parms->rid = 0; 4617 } 4618 4619 /* Free all resources that were allocated during flow creation */ 4620 if (parms->flow_id) { 4621 trc = ulp_mapper_flow_destroy(ulp_ctx, parms->flow_type, 4622 parms->flow_id, NULL); 4623 if (trc) 4624 BNXT_DRV_DBG(ERR, 4625 "Failed to free resources fid=0x%08x rc=%d\n", 4626 parms->flow_id, trc); 4627 } 4628 4629 return rc; 4630 } 4631 4632 #ifdef TF_FLOW_SCALE_QUERY 4633 /* Sync resource usage state with firmware */ 4634 int ulp_resc_usage_sync(struct bnxt_ulp_context *ulp_ctx) 4635 { 4636 uint32_t dev_id; 4637 if (unlikely(bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id))) { 4638 BNXT_DRV_DBG(ERR, "Invalid ulp context\n"); 4639 return -EINVAL; 4640 } 4641 4642 if (dev_id == BNXT_ULP_DEVICE_ID_THOR) { 4643 tf_resc_resume_usage_update(); 4644 tf_resc_usage_update_all(ulp_ctx->bp); 4645 } else if (dev_id == BNXT_ULP_DEVICE_ID_THOR2) { 4646 tfc_resc_usage_query_all(ulp_ctx->bp); 4647 } 4648 4649 return 0; 4650 } 4651 #endif /* TF_FLOW_SCALE_QUERY */ 4652 4653 int32_t 4654 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx) 4655 { 4656 struct bnxt_ulp_mapper_data *data; 4657 int32_t rc; 4658 4659 if (!ulp_ctx) 4660 return -EINVAL; 4661 4662 data = rte_zmalloc("ulp_mapper_data", 4663 sizeof(struct bnxt_ulp_mapper_data), 0); 4664 if (unlikely(!data)) { 4665 BNXT_DRV_DBG(ERR, "Failed to allocate the mapper data\n"); 4666 return -ENOMEM; 4667 } 4668 4669 /* set the mapper operations for the current platform */ 4670 data->mapper_oper = bnxt_ulp_mapper_ops_get(ulp_ctx->bp); 4671 if (unlikely(data->mapper_oper == NULL)) { 4672 rte_free(data); 4673 BNXT_DRV_DBG(ERR, "Failed to get mapper ops\n"); 4674 return -ENOMEM; 4675 } 4676 4677 if (unlikely(bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data))) { 4678 BNXT_DRV_DBG(ERR, "Failed to set mapper data in context\n"); 4679 /* Don't call deinit since the prof_func wasn't allocated. */ 4680 rte_free(data); 4681 return -ENOMEM; 4682 } 4683 4684 /* Allocate the global resource ids */ 4685 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data); 4686 if (unlikely(rc)) { 4687 BNXT_DRV_DBG(ERR, "Failed to initialize global resource ids\n"); 4688 goto error; 4689 } 4690 4691 /* 4692 * Only initialize the app global resources if a shared session was 4693 * created. 4694 */ 4695 if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) { 4696 rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data); 4697 if (unlikely(rc)) { 4698 BNXT_DRV_DBG(ERR, "Failed to init app glb resources\n"); 4699 goto error; 4700 } 4701 } 4702 4703 /* Allocate the generic table list */ 4704 rc = ulp_mapper_generic_tbl_list_init(ulp_ctx, data); 4705 if (unlikely(rc)) { 4706 BNXT_DRV_DBG(ERR, "Failed to initialize generic tbl list\n"); 4707 goto error; 4708 } 4709 4710 rc = ulp_mapper_key_recipe_tbl_init(ulp_ctx, data); 4711 if (unlikely(rc)) { 4712 BNXT_DRV_DBG(ERR, "Failed to initialize key_recipe tbl\n"); 4713 goto error; 4714 } 4715 4716 rc = ulp_allocator_tbl_list_init(ulp_ctx, data); 4717 if (unlikely(rc)) { 4718 BNXT_DRV_DBG(ERR, "Failed to initialize allocator tbl\n"); 4719 goto error; 4720 } 4721 4722 return 0; 4723 error: 4724 /* Ignore the return code in favor of returning the original error. */ 4725 ulp_mapper_deinit(ulp_ctx); 4726 return rc; 4727 } 4728 4729 void 4730 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx) 4731 { 4732 struct bnxt_ulp_mapper_data *data; 4733 4734 if (unlikely(!ulp_ctx)) { 4735 BNXT_DRV_DBG(ERR, 4736 "Failed to acquire ulp context, so data may not be released.\n"); 4737 return; 4738 } 4739 4740 data = (struct bnxt_ulp_mapper_data *) 4741 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx); 4742 if (unlikely(!data)) { 4743 /* Go ahead and return since there is no allocated data. */ 4744 BNXT_DRV_DBG(ERR, "No data appears to have been allocated.\n"); 4745 return; 4746 } 4747 4748 /* Free the global resource info table entries */ 4749 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data); 4750 4751 /* Free the generic table */ 4752 (void)ulp_mapper_generic_tbl_list_deinit(data); 4753 4754 /* Free the key recipe table */ 4755 (void)ulp_mapper_key_recipe_tbl_deinit(data); 4756 4757 /* Free the allocator table */ 4758 (void)ulp_allocator_tbl_list_deinit(data); 4759 4760 rte_free(data); 4761 /* Reset the data pointer within the ulp_ctx. */ 4762 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL); 4763 } 4764