1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_log.h> 7 #include <rte_malloc.h> 8 #include <rte_flow.h> 9 #include <rte_flow_driver.h> 10 #include <rte_tailq.h> 11 #include <rte_spinlock.h> 12 #include <rte_mtr.h> 13 #include <rte_version.h> 14 #include <rte_hash_crc.h> 15 16 #include "bnxt.h" 17 #include "bnxt_ulp.h" 18 #include "bnxt_ulp_utils.h" 19 #include "bnxt_ulp_tfc.h" 20 #include "bnxt_tf_common.h" 21 #include "hsi_struct_def_dpdk.h" 22 #include "tf_core.h" 23 #include "tf_ext_flow_handle.h" 24 25 #include "ulp_template_db_enum.h" 26 #include "ulp_template_struct.h" 27 #include "ulp_mark_mgr.h" 28 #include "ulp_fc_mgr.h" 29 #include "ulp_sc_mgr.h" 30 #include "ulp_flow_db.h" 31 #include "ulp_mapper.h" 32 #include "ulp_matcher.h" 33 #include "ulp_port_db.h" 34 #include "ulp_tun.h" 35 #include "ulp_ha_mgr.h" 36 #include "bnxt_tf_pmd_shim.h" 37 #include "ulp_template_db_tbl.h" 38 #include "tfc_resources.h" 39 40 /* define to enable shared table scope */ 41 #define TFC_SHARED_TBL_SCOPE_ENABLE 0 42 43 bool 44 bnxt_ulp_cntxt_shared_tbl_scope_enabled(struct bnxt_ulp_context *ulp_ctx) 45 { 46 uint32_t flags = 0; 47 int rc; 48 49 rc = bnxt_ulp_cntxt_ptr2_ulp_flags_get(ulp_ctx, &flags); 50 if (rc) 51 return false; 52 return !!(flags & BNXT_ULP_SHARED_TBL_SCOPE_ENABLED); 53 } 54 55 int32_t 56 bnxt_ulp_cntxt_tfcp_set(struct bnxt_ulp_context *ulp, struct tfc *tfcp) 57 { 58 enum bnxt_ulp_tfo_type tfo_type = BNXT_ULP_TFO_TYPE_TFC; 59 60 if (ulp == NULL) 61 return -EINVAL; 62 63 /* If NULL, this is invalidating an entry */ 64 if (tfcp == NULL) 65 tfo_type = BNXT_ULP_TFO_TYPE_INVALID; 66 ulp->tfo_type = tfo_type; 67 ulp->tfcp = tfcp; 68 69 return 0; 70 } 71 72 struct tfc * 73 bnxt_ulp_cntxt_tfcp_get(struct bnxt_ulp_context *ulp) 74 { 75 if (ulp == NULL) 76 return NULL; 77 78 if (ulp->tfo_type != BNXT_ULP_TFO_TYPE_TFC) { 79 BNXT_DRV_DBG(ERR, "Wrong tf type %d != %d\n", 80 ulp->tfo_type, BNXT_ULP_TFO_TYPE_TFC); 81 return NULL; 82 } 83 84 return (struct tfc *)ulp->tfcp; 85 } 86 87 uint32_t 88 bnxt_ulp_cntxt_tbl_scope_max_pools_get(struct bnxt_ulp_context *ulp_ctx) 89 { 90 /* Max pools can be 1 or greater, always return workable value */ 91 if (ulp_ctx != NULL && 92 ulp_ctx->cfg_data != NULL && 93 ulp_ctx->cfg_data->max_pools) 94 return ulp_ctx->cfg_data->max_pools; 95 return 1; 96 } 97 98 int32_t 99 bnxt_ulp_cntxt_tbl_scope_max_pools_set(struct bnxt_ulp_context *ulp_ctx, 100 uint32_t max) 101 { 102 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 103 return -EINVAL; 104 105 /* make sure that max is at least 1 */ 106 if (max == 0) 107 max = 1; 108 109 ulp_ctx->cfg_data->max_pools = max; 110 return 0; 111 } 112 113 enum tfc_tbl_scope_bucket_factor 114 bnxt_ulp_cntxt_em_mulitplier_get(struct bnxt_ulp_context *ulp_ctx) 115 { 116 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 117 return TFC_TBL_SCOPE_BUCKET_FACTOR_1; 118 119 return ulp_ctx->cfg_data->em_multiplier; 120 } 121 122 int32_t 123 bnxt_ulp_cntxt_em_mulitplier_set(struct bnxt_ulp_context *ulp_ctx, 124 enum tfc_tbl_scope_bucket_factor factor) 125 { 126 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 127 return -EINVAL; 128 ulp_ctx->cfg_data->em_multiplier = factor; 129 return 0; 130 } 131 132 uint32_t 133 bnxt_ulp_cntxt_num_rx_flows_get(struct bnxt_ulp_context *ulp_ctx) 134 { 135 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 136 return 0; 137 return ulp_ctx->cfg_data->num_rx_flows; 138 } 139 140 int32_t 141 bnxt_ulp_cntxt_num_rx_flows_set(struct bnxt_ulp_context *ulp_ctx, uint32_t num) 142 { 143 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 144 return -EINVAL; 145 ulp_ctx->cfg_data->num_rx_flows = num; 146 return 0; 147 } 148 149 uint32_t 150 bnxt_ulp_cntxt_num_tx_flows_get(struct bnxt_ulp_context *ulp_ctx) 151 { 152 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 153 return 0; 154 return ulp_ctx->cfg_data->num_tx_flows; 155 } 156 157 int32_t 158 bnxt_ulp_cntxt_num_tx_flows_set(struct bnxt_ulp_context *ulp_ctx, uint32_t num) 159 { 160 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 161 return -EINVAL; 162 ulp_ctx->cfg_data->num_tx_flows = num; 163 return 0; 164 } 165 166 uint16_t 167 bnxt_ulp_cntxt_em_rx_key_max_sz_get(struct bnxt_ulp_context *ulp_ctx) 168 { 169 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 170 return 0; 171 return ulp_ctx->cfg_data->em_rx_key_max_sz; 172 } 173 174 int32_t 175 bnxt_ulp_cntxt_em_rx_key_max_sz_set(struct bnxt_ulp_context *ulp_ctx, 176 uint16_t max) 177 { 178 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 179 return -EINVAL; 180 181 ulp_ctx->cfg_data->em_rx_key_max_sz = max; 182 return 0; 183 } 184 185 uint16_t 186 bnxt_ulp_cntxt_em_tx_key_max_sz_get(struct bnxt_ulp_context *ulp_ctx) 187 { 188 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 189 return 0; 190 return ulp_ctx->cfg_data->em_tx_key_max_sz; 191 } 192 193 int32_t 194 bnxt_ulp_cntxt_em_tx_key_max_sz_set(struct bnxt_ulp_context *ulp_ctx, 195 uint16_t max) 196 { 197 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 198 return -EINVAL; 199 200 ulp_ctx->cfg_data->em_tx_key_max_sz = max; 201 return 0; 202 } 203 204 uint16_t 205 bnxt_ulp_cntxt_act_rec_rx_max_sz_get(struct bnxt_ulp_context *ulp_ctx) 206 { 207 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 208 return 0; 209 return ulp_ctx->cfg_data->act_rx_max_sz; 210 } 211 212 int32_t 213 bnxt_ulp_cntxt_act_rec_rx_max_sz_set(struct bnxt_ulp_context *ulp_ctx, 214 int16_t max) 215 { 216 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 217 return -EINVAL; 218 219 ulp_ctx->cfg_data->act_rx_max_sz = max; 220 return 0; 221 } 222 223 uint16_t 224 bnxt_ulp_cntxt_act_rec_tx_max_sz_get(struct bnxt_ulp_context *ulp_ctx) 225 { 226 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 227 return 0; 228 return ulp_ctx->cfg_data->act_tx_max_sz; 229 } 230 231 int32_t 232 bnxt_ulp_cntxt_act_rec_tx_max_sz_set(struct bnxt_ulp_context *ulp_ctx, 233 int16_t max) 234 { 235 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 236 return -EINVAL; 237 238 ulp_ctx->cfg_data->act_tx_max_sz = max; 239 return 0; 240 } 241 242 uint32_t 243 bnxt_ulp_cntxt_page_sz_get(struct bnxt_ulp_context *ulp_ctx) 244 { 245 if (ulp_ctx == NULL) 246 return 0; 247 248 return ulp_ctx->cfg_data->page_sz; 249 } 250 251 int32_t 252 bnxt_ulp_cntxt_page_sz_set(struct bnxt_ulp_context *ulp_ctx, 253 uint32_t page_sz) 254 { 255 if (ulp_ctx == NULL) 256 return -EINVAL; 257 ulp_ctx->cfg_data->page_sz = page_sz; 258 return 0; 259 } 260 261 static int32_t 262 ulp_tfc_dparms_init(struct bnxt *bp, 263 struct bnxt_ulp_context *ulp_ctx, 264 uint32_t dev_id) 265 { 266 struct bnxt_ulp_device_params *dparms; 267 uint32_t num_flows = 0, num_rx_flows = 0, num_tx_flows = 0; 268 269 /* The max_num_kflows were set, so move to external */ 270 if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT)) 271 return -EINVAL; 272 273 dparms = bnxt_ulp_device_params_get(dev_id); 274 if (!dparms) { 275 BNXT_DRV_DBG(DEBUG, "Failed to get device parms\n"); 276 return -EINVAL; 277 } 278 279 if (bp->max_num_kflows) { 280 num_flows = bp->max_num_kflows * 1024; 281 dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024; 282 } else { 283 num_rx_flows = bnxt_ulp_cntxt_num_rx_flows_get(ulp_ctx); 284 num_tx_flows = bnxt_ulp_cntxt_num_tx_flows_get(ulp_ctx); 285 num_flows = num_rx_flows + num_tx_flows; 286 } 287 288 dparms->ext_flow_db_num_entries = num_flows; 289 290 /* GFID = 2 * num_flows */ 291 dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2; 292 BNXT_DRV_DBG(DEBUG, "Set the number of flows = %" PRIu64 "\n", 293 dparms->ext_flow_db_num_entries); 294 295 return 0; 296 } 297 298 static void 299 ulp_tfc_tbl_scope_deinit(struct bnxt *bp) 300 { 301 uint16_t fid = 0, fid_cnt = 0; 302 struct tfc *tfcp; 303 uint8_t tsid = 0; 304 int32_t rc; 305 306 tfcp = bnxt_ulp_cntxt_tfcp_get(bp->ulp_ctx); 307 if (tfcp == NULL) 308 return; 309 310 rc = bnxt_ulp_cntxt_tsid_get(bp->ulp_ctx, &tsid); 311 312 rc = bnxt_ulp_cntxt_fid_get(bp->ulp_ctx, &fid); 313 if (rc) 314 return; 315 316 rc = tfc_tbl_scope_cpm_free(tfcp, tsid); 317 if (rc) 318 BNXT_DRV_DBG(ERR, "Failed Freeing CPM TSID:%d FID:%d\n", 319 tsid, fid); 320 else 321 BNXT_DRV_DBG(DEBUG, "Freed CPM TSID:%d FID: %d\n", tsid, fid); 322 323 rc = tfc_tbl_scope_mem_free(tfcp, fid, tsid); 324 if (rc) 325 BNXT_DRV_DBG(ERR, "Failed freeing tscope mem TSID:%d FID:%d\n", 326 tsid, fid); 327 else 328 BNXT_DRV_DBG(DEBUG, "Freed tscope mem TSID:%d FID:%d\n", 329 tsid, fid); 330 331 rc = tfc_tbl_scope_fid_rem(tfcp, fid, tsid, &fid_cnt); 332 if (rc) 333 BNXT_DRV_DBG(ERR, "Failed removing FID from TSID:%d FID:%d\n", 334 tsid, fid); 335 else 336 BNXT_DRV_DBG(DEBUG, "Removed FID from TSID:%d FID:%d\n", 337 tsid, fid); 338 } 339 340 static int32_t 341 ulp_tfc_tbl_scope_init(struct bnxt *bp) 342 { 343 struct tfc_tbl_scope_mem_alloc_parms mem_parms; 344 struct tfc_tbl_scope_size_query_parms qparms = { 0 }; 345 uint16_t max_lkup_sz[CFA_DIR_MAX], max_act_sz[CFA_DIR_MAX]; 346 struct tfc_tbl_scope_cpm_alloc_parms cparms; 347 uint16_t fid, max_pools; 348 bool first = true, shared = false; 349 uint8_t tsid = 0; 350 struct tfc *tfcp; 351 int32_t rc = 0; 352 353 tfcp = bnxt_ulp_cntxt_tfcp_get(bp->ulp_ctx); 354 if (tfcp == NULL) 355 return -EINVAL; 356 357 fid = bp->fw_fid; 358 359 max_pools = bnxt_ulp_cntxt_tbl_scope_max_pools_get(bp->ulp_ctx); 360 max_lkup_sz[CFA_DIR_RX] = 361 bnxt_ulp_cntxt_em_rx_key_max_sz_get(bp->ulp_ctx); 362 max_lkup_sz[CFA_DIR_TX] = 363 bnxt_ulp_cntxt_em_tx_key_max_sz_get(bp->ulp_ctx); 364 max_act_sz[CFA_DIR_RX] = 365 bnxt_ulp_cntxt_act_rec_rx_max_sz_get(bp->ulp_ctx); 366 max_act_sz[CFA_DIR_TX] = 367 bnxt_ulp_cntxt_act_rec_tx_max_sz_get(bp->ulp_ctx); 368 369 shared = bnxt_ulp_cntxt_shared_tbl_scope_enabled(bp->ulp_ctx); 370 371 #if (TFC_SHARED_TBL_SCOPE_ENABLE == 1) 372 /* Temporary code for testing shared table scopes until ULP 373 * usage defined. 374 */ 375 if (!BNXT_PF(bp)) { 376 shared = true; 377 max_pools = 8; 378 } 379 #endif 380 /* Calculate the sizes for setting up memory */ 381 qparms.shared = shared; 382 qparms.max_pools = max_pools; 383 qparms.factor = bnxt_ulp_cntxt_em_mulitplier_get(bp->ulp_ctx); 384 qparms.flow_cnt[CFA_DIR_RX] = 385 bnxt_ulp_cntxt_num_rx_flows_get(bp->ulp_ctx); 386 qparms.flow_cnt[CFA_DIR_TX] = 387 bnxt_ulp_cntxt_num_tx_flows_get(bp->ulp_ctx); 388 qparms.key_sz_in_bytes[CFA_DIR_RX] = max_lkup_sz[CFA_DIR_RX]; 389 qparms.key_sz_in_bytes[CFA_DIR_TX] = max_lkup_sz[CFA_DIR_TX]; 390 qparms.act_rec_sz_in_bytes[CFA_DIR_RX] = max_act_sz[CFA_DIR_RX]; 391 qparms.act_rec_sz_in_bytes[CFA_DIR_TX] = max_act_sz[CFA_DIR_TX]; 392 rc = tfc_tbl_scope_size_query(tfcp, &qparms); 393 if (rc) 394 return rc; 395 396 397 398 rc = tfc_tbl_scope_id_alloc(tfcp, shared, CFA_APP_TYPE_TF, &tsid, 399 &first); 400 if (rc) { 401 BNXT_DRV_DBG(ERR, "Failed to allocate tscope\n"); 402 return rc; 403 } 404 BNXT_DRV_DBG(DEBUG, "Allocated tscope TSID:%d\n", tsid); 405 406 rc = bnxt_ulp_cntxt_tsid_set(bp->ulp_ctx, tsid); 407 if (rc) 408 return rc; 409 410 /* If we are shared and not the first table scope creator 411 */ 412 if (shared && !first) { 413 bool configured; 414 #define ULP_SHARED_TSID_WAIT_TIMEOUT 5000 415 #define ULP_SHARED_TSID_WAIT_TIME 50 416 int32_t timeout = ULP_SHARED_TSID_WAIT_TIMEOUT; 417 do { 418 rte_delay_ms(ULP_SHARED_TSID_WAIT_TIME); 419 rc = tfc_tbl_scope_config_state_get(tfcp, tsid, &configured); 420 if (rc) { 421 BNXT_DRV_DBG(ERR, 422 "Failed get tsid(%d) config state\n", 423 rc); 424 return rc; 425 } 426 timeout -= ULP_SHARED_TSID_WAIT_TIME; 427 BNXT_DRV_DBG(INFO, 428 "Waiting %d ms for shared tsid(%d)\n", 429 timeout, tsid); 430 } while (!configured && timeout > 0); 431 if (timeout <= 0) { 432 BNXT_DRV_DBG(ERR, "Timed out on shared tsid(%d)\n", 433 tsid); 434 return -ETIMEDOUT; 435 } 436 } 437 mem_parms.first = first; 438 mem_parms.static_bucket_cnt_exp[CFA_DIR_RX] = 439 qparms.static_bucket_cnt_exp[CFA_DIR_RX]; 440 mem_parms.static_bucket_cnt_exp[CFA_DIR_TX] = 441 qparms.static_bucket_cnt_exp[CFA_DIR_TX]; 442 mem_parms.lkup_rec_cnt[CFA_DIR_RX] = qparms.lkup_rec_cnt[CFA_DIR_RX]; 443 mem_parms.lkup_rec_cnt[CFA_DIR_TX] = qparms.lkup_rec_cnt[CFA_DIR_TX]; 444 mem_parms.act_rec_cnt[CFA_DIR_RX] = qparms.act_rec_cnt[CFA_DIR_RX]; 445 mem_parms.act_rec_cnt[CFA_DIR_TX] = qparms.act_rec_cnt[CFA_DIR_TX]; 446 mem_parms.pbl_page_sz_in_bytes = 447 bnxt_ulp_cntxt_page_sz_get(bp->ulp_ctx); 448 mem_parms.max_pools = max_pools; 449 450 mem_parms.lkup_pool_sz_exp[CFA_DIR_RX] = 451 qparms.lkup_pool_sz_exp[CFA_DIR_RX]; 452 mem_parms.lkup_pool_sz_exp[CFA_DIR_TX] = 453 qparms.lkup_pool_sz_exp[CFA_DIR_TX]; 454 455 mem_parms.act_pool_sz_exp[CFA_DIR_RX] = 456 qparms.act_pool_sz_exp[CFA_DIR_RX]; 457 mem_parms.act_pool_sz_exp[CFA_DIR_TX] = 458 qparms.act_pool_sz_exp[CFA_DIR_TX]; 459 mem_parms.local = true; 460 rc = tfc_tbl_scope_mem_alloc(tfcp, fid, tsid, &mem_parms); 461 if (rc) { 462 BNXT_DRV_DBG(ERR, 463 "Failed to allocate tscope mem TSID:%d on FID:%d\n", 464 tsid, fid); 465 return rc; 466 } 467 468 BNXT_DRV_DBG(DEBUG, "Allocated or set tscope mem TSID:%d on FID:%d\n", 469 tsid, fid); 470 471 472 /* The max contiguous is in 32 Bytes records, so convert Bytes to 32 473 * Byte records. 474 */ 475 cparms.lkup_max_contig_rec[CFA_DIR_RX] = (max_lkup_sz[CFA_DIR_RX] + 31) / 32; 476 cparms.lkup_max_contig_rec[CFA_DIR_TX] = (max_lkup_sz[CFA_DIR_TX] + 31) / 32; 477 cparms.act_max_contig_rec[CFA_DIR_RX] = (max_act_sz[CFA_DIR_RX] + 31) / 32; 478 cparms.act_max_contig_rec[CFA_DIR_TX] = (max_act_sz[CFA_DIR_TX] + 31) / 32; 479 cparms.max_pools = max_pools; 480 481 rc = tfc_tbl_scope_cpm_alloc(tfcp, tsid, &cparms); 482 if (rc) 483 BNXT_DRV_DBG(ERR, "Failed to allocate CPM TSID:%d FID:%d\n", 484 tsid, fid); 485 else 486 BNXT_DRV_DBG(DEBUG, "Allocated CPM TSID:%d FID:%d\n", tsid, fid); 487 488 return rc; 489 } 490 491 static int32_t 492 ulp_tfc_cntxt_app_caps_init(struct bnxt *bp, uint8_t app_id, uint32_t dev_id) 493 { 494 struct bnxt_ulp_app_capabilities_info *info; 495 struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx; 496 uint32_t num = 0, rc; 497 bool found = false; 498 uint16_t i; 499 500 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(ulp_ctx->cfg_data->ulp_flags)) { 501 BNXT_DRV_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 502 app_id, dev_id); 503 return -EINVAL; 504 } 505 506 info = bnxt_ulp_app_cap_list_get(&num); 507 if (!info || !num) { 508 BNXT_DRV_DBG(ERR, "Failed to get app capabilities.\n"); 509 return -EINVAL; 510 } 511 512 for (i = 0; i < num && !found; i++) { 513 if (info[i].app_id != app_id || info[i].device_id != dev_id) 514 continue; 515 found = true; 516 if (info[i].flags & BNXT_ULP_APP_CAP_SHARED_EN) 517 ulp_ctx->cfg_data->ulp_flags |= 518 BNXT_ULP_SHARED_SESSION_ENABLED; 519 if (info[i].flags & BNXT_ULP_APP_CAP_HOT_UPGRADE_EN) 520 ulp_ctx->cfg_data->ulp_flags |= 521 BNXT_ULP_HIGH_AVAIL_ENABLED; 522 if (info[i].flags & BNXT_ULP_APP_CAP_UNICAST_ONLY) 523 ulp_ctx->cfg_data->ulp_flags |= 524 BNXT_ULP_APP_UNICAST_ONLY; 525 if (info[i].flags & BNXT_ULP_APP_CAP_IP_TOS_PROTO_SUPPORT) 526 ulp_ctx->cfg_data->ulp_flags |= 527 BNXT_ULP_APP_TOS_PROTO_SUPPORT; 528 if (info[i].flags & BNXT_ULP_APP_CAP_BC_MC_SUPPORT) 529 ulp_ctx->cfg_data->ulp_flags |= 530 BNXT_ULP_APP_BC_MC_SUPPORT; 531 if (info[i].flags & BNXT_ULP_APP_CAP_SOCKET_DIRECT) { 532 /* Enable socket direction only if MR is enabled in fw*/ 533 if (BNXT_MULTIROOT_EN(bp)) { 534 ulp_ctx->cfg_data->ulp_flags |= 535 BNXT_ULP_APP_SOCKET_DIRECT; 536 BNXT_DRV_DBG(DEBUG, 537 "Socket Direct feature is enabled\n"); 538 } 539 } 540 /* Update the capability feature bits*/ 541 if (bnxt_ulp_cap_feat_process(info[i].feature_bits, 542 &ulp_ctx->cfg_data->feature_bits)) 543 return -EINVAL; 544 545 bnxt_ulp_default_app_priority_set(ulp_ctx, 546 info[i].default_priority); 547 bnxt_ulp_max_def_priority_set(ulp_ctx, 548 info[i].max_def_priority); 549 bnxt_ulp_min_flow_priority_set(ulp_ctx, 550 info[i].min_flow_priority); 551 bnxt_ulp_max_flow_priority_set(ulp_ctx, 552 info[i].max_flow_priority); 553 554 bnxt_ulp_cntxt_ptr2_default_class_bits_set(ulp_ctx, 555 info[i].default_class_bits); 556 bnxt_ulp_cntxt_ptr2_default_act_bits_set(ulp_ctx, 557 info[i].default_act_bits); 558 559 rc = bnxt_ulp_cntxt_tbl_scope_max_pools_set(ulp_ctx, 560 info[i].max_pools); 561 if (rc) 562 return rc; 563 rc = bnxt_ulp_cntxt_em_mulitplier_set(ulp_ctx, 564 info[i].em_multiplier); 565 if (rc) 566 return rc; 567 568 rc = bnxt_ulp_cntxt_num_rx_flows_set(ulp_ctx, 569 info[i].num_rx_flows); 570 if (rc) 571 return rc; 572 573 rc = bnxt_ulp_cntxt_num_tx_flows_set(ulp_ctx, 574 info[i].num_tx_flows); 575 if (rc) 576 return rc; 577 578 rc = bnxt_ulp_cntxt_em_rx_key_max_sz_set(ulp_ctx, 579 info[i].em_rx_key_max_sz); 580 if (rc) 581 return rc; 582 583 rc = bnxt_ulp_cntxt_em_tx_key_max_sz_set(ulp_ctx, 584 info[i].em_tx_key_max_sz); 585 if (rc) 586 return rc; 587 588 rc = bnxt_ulp_cntxt_act_rec_rx_max_sz_set(ulp_ctx, 589 info[i].act_rx_max_sz); 590 if (rc) 591 return rc; 592 593 rc = bnxt_ulp_cntxt_act_rec_tx_max_sz_set(ulp_ctx, 594 info[i].act_tx_max_sz); 595 if (rc) 596 return rc; 597 598 rc = bnxt_ulp_cntxt_page_sz_set(ulp_ctx, 599 info[i].pbl_page_sz_in_bytes); 600 if (rc) 601 return rc; 602 bnxt_ulp_num_key_recipes_set(ulp_ctx, 603 info[i].num_key_recipes_per_dir); 604 } 605 if (!found) { 606 BNXT_DRV_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 607 app_id, dev_id); 608 ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_APP_DEV_UNSUPPORTED; 609 return -EINVAL; 610 } 611 612 return 0; 613 } 614 615 /* The function to free and deinit the ulp context data. */ 616 static int32_t 617 ulp_tfc_ctx_deinit(struct bnxt *bp, 618 struct bnxt_ulp_session_state *session) 619 { 620 /* Free the contents */ 621 if (session->cfg_data) { 622 rte_free(session->cfg_data); 623 bp->ulp_ctx->cfg_data = NULL; 624 session->cfg_data = NULL; 625 } 626 return 0; 627 } 628 629 /* The function to allocate and initialize the ulp context data. */ 630 static int32_t 631 ulp_tfc_ctx_init(struct bnxt *bp, 632 struct bnxt_ulp_session_state *session) 633 { 634 struct bnxt_ulp_data *ulp_data; 635 enum bnxt_ulp_device_id devid; 636 int32_t rc = 0; 637 638 /* Initialize the context entries list */ 639 bnxt_ulp_cntxt_list_init(); 640 641 /* Allocate memory to hold ulp context data. */ 642 ulp_data = rte_zmalloc("bnxt_ulp_data", 643 sizeof(struct bnxt_ulp_data), 0); 644 if (!ulp_data) { 645 BNXT_DRV_DBG(ERR, "Failed to allocate memory for ulp data\n"); 646 return -ENOMEM; 647 } 648 649 /* Increment the ulp context data reference count usage. */ 650 bp->ulp_ctx->cfg_data = ulp_data; 651 session->cfg_data = ulp_data; 652 ulp_data->ref_cnt++; 653 ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED; 654 655 /* Add the context to the context entries list */ 656 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 657 if (rc) { 658 BNXT_DRV_DBG(ERR, "Failed to add the context list entry\n"); 659 goto error_deinit; 660 } 661 662 rc = bnxt_ulp_devid_get(bp, &devid); 663 if (rc) { 664 BNXT_DRV_DBG(ERR, "Unable to determine device for ULP init.\n"); 665 goto error_deinit; 666 } 667 668 rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid); 669 if (rc) { 670 BNXT_DRV_DBG(ERR, "Unable to set device for ULP init.\n"); 671 goto error_deinit; 672 } 673 674 rc = bnxt_ulp_cntxt_app_id_set(bp->ulp_ctx, bp->app_id); 675 if (rc) { 676 BNXT_DRV_DBG(ERR, "Unable to set app_id for ULP init.\n"); 677 goto error_deinit; 678 } 679 BNXT_DRV_DBG(DEBUG, "Ulp initialized with app id %d\n", bp->app_id); 680 681 rc = ulp_tfc_dparms_init(bp, bp->ulp_ctx, devid); 682 if (rc) { 683 BNXT_DRV_DBG(ERR, "Unable to init dparms for app(%x)/dev(%x)\n", 684 bp->app_id, devid); 685 goto error_deinit; 686 } 687 688 rc = ulp_tfc_cntxt_app_caps_init(bp, bp->app_id, devid); 689 if (rc) { 690 BNXT_DRV_DBG(ERR, "Unable to set caps for app(%x)/dev(%x)\n", 691 bp->app_id, devid); 692 goto error_deinit; 693 } 694 695 if (BNXT_TESTPMD_EN(bp)) { 696 ulp_data->ulp_flags &= ~BNXT_ULP_VF_REP_ENABLED; 697 BNXT_DRV_DBG(ERR, "Enabled Testpmd forward mode\n"); 698 } 699 700 return rc; 701 702 error_deinit: 703 session->session_opened[BNXT_ULP_SESSION_TYPE_DEFAULT] = 1; 704 (void)ulp_tfc_ctx_deinit(bp, session); 705 return rc; 706 } 707 708 static int32_t 709 ulp_tfc_vfr_session_fid_add(struct bnxt_ulp_context *ulp_ctx, uint16_t rep_fid) 710 { 711 uint16_t fid_cnt = 0, sid = 0; 712 struct tfc *tfcp = NULL; 713 int rc; 714 715 tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx); 716 if (!tfcp) { 717 PMD_DRV_LOG_LINE(ERR, "Unable to get tfcp from ulp_ctx"); 718 return -EINVAL; 719 } 720 721 /* Get the session id */ 722 rc = bnxt_ulp_cntxt_sid_get(ulp_ctx, &sid); 723 if (rc) { 724 PMD_DRV_LOG_LINE(ERR, "Unable to get SID for VFR FID=%d", rep_fid); 725 return rc; 726 } 727 728 rc = tfc_session_fid_add(tfcp, rep_fid, sid, &fid_cnt); 729 if (!rc) 730 PMD_DRV_LOG_LINE(DEBUG, 731 "EFID=%d added to SID=%d, %d total", 732 rep_fid, sid, fid_cnt); 733 else 734 PMD_DRV_LOG_LINE(ERR, 735 "Failed to add EFID=%d to SID=%d", 736 rep_fid, sid); 737 return rc; 738 } 739 740 static int32_t 741 ulp_tfc_vfr_session_fid_rem(struct bnxt_ulp_context *ulp_ctx, uint16_t rep_fid) 742 { 743 uint16_t fid_cnt = 0, sid = 0; 744 struct tfc *tfcp = NULL; 745 int rc; 746 747 tfcp = bnxt_ulp_cntxt_tfcp_get(ulp_ctx); 748 if (!tfcp) { 749 PMD_DRV_LOG_LINE(ERR, "Unable tfcp from ulp_ctx"); 750 return -EINVAL; 751 } 752 753 /* Get the session id */ 754 rc = bnxt_ulp_cntxt_sid_get(ulp_ctx, &sid); 755 if (rc) { 756 PMD_DRV_LOG_LINE(ERR, "Unable to get SID for VFR FID=%d", rep_fid); 757 return rc; 758 } 759 760 rc = tfc_session_fid_rem(tfcp, rep_fid, &fid_cnt); 761 if (!rc) 762 PMD_DRV_LOG_LINE(DEBUG, 763 "Removed EFID=%d from SID=%d, %d remain", 764 rep_fid, sid, fid_cnt); 765 else 766 PMD_DRV_LOG_LINE(ERR, 767 "Failed to remove EFID=%d from SID=%d", 768 rep_fid, sid); 769 770 return rc; 771 } 772 773 static int32_t 774 ulp_tfc_ctx_attach(struct bnxt *bp, 775 struct bnxt_ulp_session_state *session) 776 { 777 uint32_t flags, dev_id = BNXT_ULP_DEVICE_ID_LAST; 778 uint16_t fid_cnt = 0; 779 int32_t rc = 0; 780 uint8_t app_id; 781 782 bp->tfcp.bp = bp; 783 rc = tfc_open(&bp->tfcp); 784 if (rc) { 785 BNXT_DRV_DBG(ERR, "Failed to initialize the tfc object\n"); 786 return rc; 787 } 788 789 rc = bnxt_ulp_cntxt_tfcp_set(bp->ulp_ctx, &bp->tfcp); 790 if (rc) { 791 BNXT_DRV_DBG(ERR, "Failed to add tfcp to ulp ctxt\n"); 792 return rc; 793 } 794 795 rc = bnxt_ulp_devid_get(bp, &dev_id); 796 if (rc) { 797 BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n"); 798 return rc; 799 } 800 801 /* Increment the ulp context data reference count usage. */ 802 bp->ulp_ctx->cfg_data = session->cfg_data; 803 bp->ulp_ctx->cfg_data->ref_cnt++; 804 805 rc = tfc_session_fid_add(&bp->tfcp, bp->fw_fid, 806 session->session_id, &fid_cnt); 807 if (rc) { 808 BNXT_DRV_DBG(ERR, "Failed to add RFID:%d to SID:%d.\n", 809 bp->fw_fid, session->session_id); 810 return rc; 811 } 812 BNXT_DRV_DBG(DEBUG, "RFID:%d added to SID:%d\n", 813 bp->fw_fid, session->session_id); 814 815 rc = bnxt_ulp_cntxt_sid_set(bp->ulp_ctx, session->session_id); 816 if (rc) { 817 BNXT_DRV_DBG(ERR, "Failed to add fid to session.\n"); 818 return rc; 819 } 820 821 /* Add the context to the context entries list */ 822 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 823 if (rc) { 824 BNXT_DRV_DBG(ERR, "Failed to add the context list entry\n"); 825 return -EINVAL; 826 } 827 828 /* 829 * The supported flag will be set during the init. Use it now to 830 * know if we should go through the attach. 831 */ 832 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 833 if (rc) { 834 BNXT_DRV_DBG(ERR, "Unable to get the app id from ulp.\n"); 835 return -EINVAL; 836 } 837 flags = bp->ulp_ctx->cfg_data->ulp_flags; 838 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(flags)) { 839 BNXT_DRV_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 840 app_id, dev_id); 841 return -EINVAL; 842 } 843 844 rc = ulp_tfc_tbl_scope_init(bp); 845 846 return rc; 847 } 848 849 static void 850 ulp_tfc_ctx_detach(struct bnxt *bp, 851 struct bnxt_ulp_session_state *session) 852 { 853 uint16_t fid_cnt = 0; 854 int32_t rc; 855 856 ulp_tfc_tbl_scope_deinit(bp); 857 858 rc = tfc_session_fid_rem(&bp->tfcp, bp->fw_fid, &fid_cnt); 859 if (rc) 860 BNXT_DRV_DBG(ERR, "Failed to remove RFID:%d from SID:%d\n", 861 bp->fw_fid, session->session_id); 862 else 863 BNXT_DRV_DBG(DEBUG, "Removed RFID:%d from SID:%d CNT:%d\n", 864 bp->fw_fid, session->session_id, fid_cnt); 865 bnxt_ulp_cntxt_sid_reset(bp->ulp_ctx); 866 (void)tfc_close(&bp->tfcp); 867 } 868 869 /* 870 * When a port is deinit'ed by dpdk. This function is called 871 * and this function clears the ULP context and rest of the 872 * infrastructure associated with it. 873 */ 874 static void 875 ulp_tfc_deinit(struct bnxt *bp, 876 struct bnxt_ulp_session_state *session) 877 { 878 bool ha_enabled; 879 uint16_t fid_cnt = 0; 880 int32_t rc; 881 882 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 883 return; 884 885 ha_enabled = bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx); 886 if (ha_enabled) { 887 rc = ulp_ha_mgr_close(bp->ulp_ctx); 888 if (rc) 889 BNXT_DRV_DBG(ERR, "Failed to close HA (%d)\n", rc); 890 } 891 892 /* Delete the Stats Counter Manager */ 893 ulp_sc_mgr_deinit(bp->ulp_ctx); 894 895 /* cleanup the flow database */ 896 ulp_flow_db_deinit(bp->ulp_ctx); 897 898 /* Delete the Mark database */ 899 ulp_mark_db_deinit(bp->ulp_ctx); 900 901 /* cleanup the ulp mapper */ 902 ulp_mapper_deinit(bp->ulp_ctx); 903 904 /* cleanup the ulp matcher */ 905 ulp_matcher_deinit(bp->ulp_ctx); 906 907 /* Delete the Flow Counter Manager */ 908 ulp_fc_mgr_deinit(bp->ulp_ctx); 909 910 /* Delete the Port database */ 911 ulp_port_db_deinit(bp->ulp_ctx); 912 913 /* free the flow db lock */ 914 pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock); 915 916 ulp_tfc_tbl_scope_deinit(bp); 917 918 rc = tfc_session_fid_rem(&bp->tfcp, bp->fw_fid, &fid_cnt); 919 if (rc) 920 BNXT_DRV_DBG(ERR, "Failed to remove RFID:%d from SID:%d\n", 921 bp->fw_fid, session->session_id); 922 else 923 BNXT_DRV_DBG(DEBUG, "Removed RFID:%d from SID:%d CNT:%d\n", 924 bp->fw_fid, session->session_id, fid_cnt); 925 bnxt_ulp_cntxt_sid_reset(bp->ulp_ctx); 926 (void)tfc_close(&bp->tfcp); 927 928 /* Delete the ulp context and tf session and free the ulp context */ 929 ulp_tfc_ctx_deinit(bp, session); 930 931 BNXT_DRV_DBG(DEBUG, "ulp ctx has been deinitialized\n"); 932 } 933 934 /* 935 * When a port is initialized by dpdk. This functions is called 936 * and this function initializes the ULP context and rest of the 937 * infrastructure associated with it. 938 */ 939 static int32_t 940 ulp_tfc_init(struct bnxt *bp, 941 struct bnxt_ulp_session_state *session) 942 { 943 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 944 uint16_t sid; 945 int rc; 946 947 /* Select 64bit SSE4.2 intrinsic if available */ 948 rte_hash_crc_set_alg(CRC32_SSE42_x64); 949 950 rc = bnxt_ulp_devid_get(bp, &ulp_dev_id); 951 if (rc) { 952 BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n"); 953 return rc; 954 } 955 956 bp->tfcp.bp = bp; 957 rc = tfc_open(&bp->tfcp); 958 if (rc) { 959 BNXT_DRV_DBG(ERR, "Failed to initialize the tfc object\n"); 960 return rc; 961 } 962 963 rc = bnxt_ulp_cntxt_tfcp_set(bp->ulp_ctx, &bp->tfcp); 964 if (rc) { 965 BNXT_DRV_DBG(ERR, "Failed to add tfcp to ulp cntxt\n"); 966 return rc; 967 } 968 969 /* First time, so allocate a session and save it. */ 970 rc = tfc_session_id_alloc(&bp->tfcp, bp->fw_fid, &sid); 971 if (rc) { 972 BNXT_DRV_DBG(ERR, "Failed to allocate a session id\n"); 973 return rc; 974 } 975 BNXT_DRV_DBG(DEBUG, "SID:%d allocated with RFID:%d\n", sid, bp->fw_fid); 976 session->session_id = sid; 977 rc = bnxt_ulp_cntxt_sid_set(bp->ulp_ctx, sid); 978 if (rc) { 979 BNXT_DRV_DBG(ERR, "Failed to sid to ulp cntxt\n"); 980 return rc; 981 } 982 983 /* Allocate and Initialize the ulp context. */ 984 rc = ulp_tfc_ctx_init(bp, session); 985 if (rc) { 986 BNXT_DRV_DBG(ERR, "Failed to create the ulp context\n"); 987 goto jump_to_error; 988 } 989 990 rc = ulp_tfc_tbl_scope_init(bp); 991 if (rc) { 992 BNXT_DRV_DBG(ERR, "Failed to create the ulp context\n"); 993 goto jump_to_error; 994 } 995 996 pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL); 997 998 rc = ulp_tfc_dparms_init(bp, bp->ulp_ctx, ulp_dev_id); 999 if (rc) { 1000 BNXT_DRV_DBG(ERR, "Failed to initialize the dparms\n"); 1001 goto jump_to_error; 1002 } 1003 1004 /* create the port database */ 1005 rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt); 1006 if (rc) { 1007 BNXT_DRV_DBG(ERR, "Failed to create the port database\n"); 1008 goto jump_to_error; 1009 } 1010 1011 /* BAUCOM TODO: Mark database assumes LFID/GFID Parms, need to look at 1012 * alternatives. 1013 */ 1014 /* Create the Mark database. */ 1015 rc = ulp_mark_db_init(bp->ulp_ctx); 1016 if (rc) { 1017 BNXT_DRV_DBG(ERR, "Failed to create the mark database\n"); 1018 goto jump_to_error; 1019 } 1020 1021 /* Create the flow database. */ 1022 rc = ulp_flow_db_init(bp->ulp_ctx); 1023 if (rc) { 1024 BNXT_DRV_DBG(ERR, "Failed to create the flow database\n"); 1025 goto jump_to_error; 1026 } 1027 1028 rc = ulp_matcher_init(bp->ulp_ctx); 1029 if (rc) { 1030 BNXT_DRV_DBG(ERR, "Failed to initialize ulp matcher\n"); 1031 goto jump_to_error; 1032 } 1033 1034 rc = ulp_mapper_init(bp->ulp_ctx); 1035 if (rc) { 1036 BNXT_DRV_DBG(ERR, "Failed to initialize ulp mapper\n"); 1037 goto jump_to_error; 1038 } 1039 1040 /* BAUCOM TODO: need to make FC Mgr not start the thread. */ 1041 rc = ulp_fc_mgr_init(bp->ulp_ctx); 1042 if (rc) { 1043 BNXT_DRV_DBG(ERR, "Failed to initialize ulp flow counter mgr\n"); 1044 goto jump_to_error; 1045 } 1046 1047 rc = ulp_sc_mgr_init(bp->ulp_ctx); 1048 if (rc) { 1049 BNXT_DRV_DBG(ERR, "Failed to initialize ulp stats cache mgr\n"); 1050 goto jump_to_error; 1051 } 1052 1053 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 1054 if (rc) { 1055 BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n"); 1056 return rc; 1057 } 1058 1059 if (ulp_dev_id == BNXT_ULP_DEVICE_ID_THOR2) { 1060 rc = bnxt_flow_mtr_init(bp); 1061 if (rc) { 1062 BNXT_DRV_DBG(ERR, "Failed to config meter\n"); 1063 goto jump_to_error; 1064 } 1065 } 1066 1067 #ifdef TF_FLOW_SCALE_QUERY 1068 /* Query resource statstics from firmware */ 1069 tfc_resc_usage_query_all(bp); 1070 #endif /* TF_FLOW_SCALE_QUERY */ 1071 1072 BNXT_DRV_DBG(DEBUG, "ulp ctx has been initialized\n"); 1073 return rc; 1074 1075 jump_to_error: 1076 bp->ulp_ctx->ops->ulp_deinit(bp, session); 1077 return rc; 1078 } 1079 1080 /** 1081 * Get meter capabilities. 1082 */ 1083 #define MAX_FLOW_PER_METER 1024 1084 #define MAX_NUM_METER 1024 1085 #define MAX_METER_RATE_200GBPS ((1ULL << 31) * 100 / 8) 1086 static int 1087 ulp_tfc_mtr_cap_get(struct bnxt *bp __rte_unused, 1088 struct rte_mtr_capabilities *cap) 1089 { 1090 #if (RTE_VERSION_NUM(21, 05, 0, 0) <= RTE_VERSION) 1091 cap->srtcm_rfc2697_byte_mode_supported = 1; 1092 #endif 1093 cap->n_max = MAX_NUM_METER; 1094 cap->n_shared_max = cap->n_max; 1095 /* No meter is identical */ 1096 cap->identical = 1; 1097 cap->shared_identical = 1; 1098 cap->shared_n_flows_per_mtr_max = MAX_FLOW_PER_METER; 1099 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */ 1100 cap->meter_srtcm_rfc2697_n_max = cap->n_max; 1101 cap->meter_rate_max = MAX_METER_RATE_200GBPS; 1102 /* No stats supported now */ 1103 cap->stats_mask = 0; 1104 1105 return 0; 1106 } 1107 1108 const struct bnxt_ulp_core_ops bnxt_ulp_tfc_core_ops = { 1109 .ulp_ctx_attach = ulp_tfc_ctx_attach, 1110 .ulp_ctx_detach = ulp_tfc_ctx_detach, 1111 .ulp_deinit = ulp_tfc_deinit, 1112 .ulp_init = ulp_tfc_init, 1113 .ulp_vfr_session_fid_add = ulp_tfc_vfr_session_fid_add, 1114 .ulp_vfr_session_fid_rem = ulp_tfc_vfr_session_fid_rem, 1115 .ulp_mtr_cap_get = ulp_tfc_mtr_cap_get 1116 }; 1117