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_tf.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_flow_db.h" 30 #include "ulp_mapper.h" 31 #include "ulp_matcher.h" 32 #include "ulp_port_db.h" 33 #include "ulp_tun.h" 34 #include "ulp_ha_mgr.h" 35 #include "bnxt_tf_pmd_shim.h" 36 #include "ulp_template_db_tbl.h" 37 38 /* Function to set the tfp session details from the ulp context. */ 39 int32_t 40 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, 41 enum bnxt_ulp_session_type s_type, 42 struct tf *tfp) 43 { 44 uint32_t idx = 0; 45 enum bnxt_ulp_tfo_type tfo_type = BNXT_ULP_TFO_TYPE_TF; 46 47 if (ulp == NULL) 48 return -EINVAL; 49 50 if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp)) { 51 if (s_type & BNXT_ULP_SESSION_TYPE_SHARED) 52 idx = 1; 53 else if (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 54 idx = 2; 55 56 } else { 57 if ((s_type & BNXT_ULP_SESSION_TYPE_SHARED) || 58 (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)) 59 idx = 1; 60 } 61 62 ulp->g_tfp[idx] = tfp; 63 64 if (tfp == NULL) { 65 uint32_t i = 0; 66 while (i < BNXT_ULP_SESSION_MAX && ulp->g_tfp[i] == NULL) 67 i++; 68 if (i == BNXT_ULP_SESSION_MAX) 69 ulp->tfo_type = BNXT_ULP_TFO_TYPE_INVALID; 70 } else { 71 ulp->tfo_type = tfo_type; 72 } 73 return 0; 74 } 75 76 /* Function to get the tfp session details from the ulp context. */ 77 struct tf * 78 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp, 79 enum bnxt_ulp_session_type s_type) 80 { 81 uint32_t idx = 0; 82 83 if (ulp == NULL) 84 return NULL; 85 86 if (ulp->tfo_type != BNXT_ULP_TFO_TYPE_TF) { 87 BNXT_DRV_DBG(ERR, "Wrong tf type %d != %d\n", 88 ulp->tfo_type, BNXT_ULP_TFO_TYPE_TF); 89 return NULL; 90 } 91 92 if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp)) { 93 if (s_type & BNXT_ULP_SESSION_TYPE_SHARED) 94 idx = 1; 95 else if (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 96 idx = 2; 97 } else { 98 if ((s_type & BNXT_ULP_SESSION_TYPE_SHARED) || 99 (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)) 100 idx = 1; 101 } 102 return (struct tf *)ulp->g_tfp[idx]; 103 } 104 105 struct tf *bnxt_get_tfp_session(struct bnxt *bp, enum bnxt_session_type type) 106 { 107 return (type >= BNXT_SESSION_TYPE_LAST) ? 108 &bp->tfp[BNXT_SESSION_TYPE_REGULAR] : &bp->tfp[type]; 109 } 110 111 struct tf * 112 bnxt_ulp_bp_tfp_get(struct bnxt *bp, enum bnxt_ulp_session_type type) 113 { 114 enum bnxt_session_type btype; 115 116 if (type & BNXT_ULP_SESSION_TYPE_SHARED) 117 btype = BNXT_SESSION_TYPE_SHARED_COMMON; 118 else if (type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 119 btype = BNXT_SESSION_TYPE_SHARED_WC; 120 else 121 btype = BNXT_SESSION_TYPE_REGULAR; 122 123 return bnxt_get_tfp_session(bp, btype); 124 } 125 126 static int32_t 127 ulp_tf_named_resources_calc(struct bnxt_ulp_context *ulp_ctx, 128 struct bnxt_ulp_glb_resource_info *info, 129 uint32_t num, 130 enum bnxt_ulp_session_type stype, 131 struct tf_session_resources *res) 132 { 133 uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST, res_type, i; 134 enum tf_dir dir; 135 uint8_t app_id; 136 int32_t rc = 0; 137 138 if (ulp_ctx == NULL || info == NULL || res == NULL || num == 0) { 139 BNXT_DRV_DBG(ERR, "Invalid parms to named resources calc.\n"); 140 return -EINVAL; 141 } 142 143 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 144 if (rc) { 145 BNXT_DRV_DBG(ERR, "Unable to get the app id from ulp.\n"); 146 return -EINVAL; 147 } 148 149 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 150 if (rc) { 151 BNXT_DRV_DBG(ERR, "Unable to get the dev id from ulp.\n"); 152 return -EINVAL; 153 } 154 155 for (i = 0; i < num; i++) { 156 if (dev_id != info[i].device_id || app_id != info[i].app_id) 157 continue; 158 /* check to see if the session type matches only then include */ 159 if ((stype || info[i].session_type) && 160 !(info[i].session_type & stype)) 161 continue; 162 163 dir = info[i].direction; 164 res_type = info[i].resource_type; 165 166 switch (info[i].resource_func) { 167 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 168 res->ident_cnt[dir].cnt[res_type]++; 169 break; 170 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 171 res->tbl_cnt[dir].cnt[res_type]++; 172 break; 173 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 174 res->tcam_cnt[dir].cnt[res_type]++; 175 break; 176 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 177 res->em_cnt[dir].cnt[res_type]++; 178 break; 179 default: 180 BNXT_DRV_DBG(ERR, "Unknown resource func (0x%x)\n,", 181 info[i].resource_func); 182 continue; 183 } 184 } 185 186 return 0; 187 } 188 189 static int32_t 190 ulp_tf_unnamed_resources_calc(struct bnxt_ulp_context *ulp_ctx, 191 struct bnxt_ulp_resource_resv_info *info, 192 uint32_t num, 193 enum bnxt_ulp_session_type stype, 194 struct tf_session_resources *res) 195 { 196 uint32_t dev_id, res_type, i; 197 enum tf_dir dir; 198 uint8_t app_id; 199 int32_t rc = 0; 200 201 if (ulp_ctx == NULL || res == NULL || info == NULL || num == 0) { 202 BNXT_DRV_DBG(ERR, "Invalid arguments to get resources.\n"); 203 return -EINVAL; 204 } 205 206 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 207 if (rc) { 208 BNXT_DRV_DBG(ERR, "Unable to get the app id from ulp.\n"); 209 return -EINVAL; 210 } 211 212 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 213 if (rc) { 214 BNXT_DRV_DBG(ERR, "Unable to get the dev id from ulp.\n"); 215 return -EINVAL; 216 } 217 218 for (i = 0; i < num; i++) { 219 if (app_id != info[i].app_id || dev_id != info[i].device_id) 220 continue; 221 222 /* check to see if the session type matches only then include */ 223 if ((stype || info[i].session_type) && 224 !(info[i].session_type & stype)) 225 continue; 226 227 dir = info[i].direction; 228 res_type = info[i].resource_type; 229 230 switch (info[i].resource_func) { 231 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 232 res->ident_cnt[dir].cnt[res_type] = info[i].count; 233 break; 234 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 235 res->tbl_cnt[dir].cnt[res_type] = info[i].count; 236 break; 237 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 238 res->tcam_cnt[dir].cnt[res_type] = info[i].count; 239 break; 240 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 241 res->em_cnt[dir].cnt[res_type] = info[i].count; 242 break; 243 default: 244 break; 245 } 246 } 247 return 0; 248 } 249 250 static int32_t 251 ulp_tf_resources_get(struct bnxt_ulp_context *ulp_ctx, 252 enum bnxt_ulp_session_type stype, 253 struct tf_session_resources *res) 254 { 255 struct bnxt_ulp_resource_resv_info *unnamed = NULL; 256 uint32_t unum; 257 int32_t rc = 0; 258 259 if (ulp_ctx == NULL || res == NULL) { 260 BNXT_DRV_DBG(ERR, "Invalid arguments to get resources.\n"); 261 return -EINVAL; 262 } 263 264 /* use DEFAULT_NON_HA instead of DEFAULT resources if HA is disabled */ 265 if (ULP_APP_HA_IS_DYNAMIC(ulp_ctx)) 266 stype = ulp_ctx->cfg_data->def_session_type; 267 268 unnamed = bnxt_ulp_resource_resv_list_get(&unum); 269 if (unnamed == NULL) { 270 BNXT_DRV_DBG(ERR, "Unable to get resource resv list.\n"); 271 return -EINVAL; 272 } 273 274 rc = ulp_tf_unnamed_resources_calc(ulp_ctx, unnamed, unum, stype, res); 275 if (rc) 276 BNXT_DRV_DBG(ERR, "Unable to calc resources for session.\n"); 277 278 return rc; 279 } 280 281 static int32_t 282 ulp_tf_shared_session_resources_get(struct bnxt_ulp_context *ulp_ctx, 283 enum bnxt_ulp_session_type stype, 284 struct tf_session_resources *res) 285 { 286 struct bnxt_ulp_resource_resv_info *unnamed; 287 struct bnxt_ulp_glb_resource_info *named; 288 uint32_t unum = 0, nnum = 0; 289 int32_t rc; 290 291 if (ulp_ctx == NULL || res == NULL) { 292 BNXT_DRV_DBG(ERR, "Invalid arguments to get resources.\n"); 293 return -EINVAL; 294 } 295 296 /* Make sure the resources are zero before accumulating. */ 297 memset(res, 0, sizeof(struct tf_session_resources)); 298 299 if (bnxt_ulp_cntxt_ha_enabled(ulp_ctx) && 300 stype == BNXT_ULP_SESSION_TYPE_SHARED) 301 stype = ulp_ctx->cfg_data->hu_session_type; 302 303 /* 304 * Shared resources are comprised of both named and unnamed resources. 305 * First get the unnamed counts, and then add the named to the result. 306 */ 307 /* Get the baseline counts */ 308 unnamed = bnxt_ulp_app_resource_resv_list_get(&unum); 309 if (unum) { 310 rc = ulp_tf_unnamed_resources_calc(ulp_ctx, unnamed, 311 unum, stype, res); 312 if (rc) { 313 BNXT_DRV_DBG(ERR, 314 "Unable to calc resources for shared session.\n"); 315 return -EINVAL; 316 } 317 } 318 319 /* Get the named list and add the totals */ 320 named = bnxt_ulp_app_glb_resource_info_list_get(&nnum); 321 /* No need to calc resources, none to calculate */ 322 if (!nnum) 323 return 0; 324 325 rc = ulp_tf_named_resources_calc(ulp_ctx, named, nnum, stype, res); 326 if (rc) 327 BNXT_DRV_DBG(ERR, "Unable to calc named resources\n"); 328 329 return rc; 330 } 331 332 /* Function to set the hot upgrade support into the context */ 333 static int 334 ulp_tf_multi_shared_session_support_set(struct bnxt *bp, 335 enum bnxt_ulp_device_id devid, 336 uint32_t fw_hu_update) 337 { 338 struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx; 339 struct tf_get_version_parms v_params = { 0 }; 340 struct tf *tfp; 341 int32_t rc = 0; 342 int32_t new_fw = 0; 343 344 v_params.device_type = bnxt_ulp_cntxt_convert_dev_id(devid); 345 v_params.bp = bp; 346 347 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 348 rc = tf_get_version(tfp, &v_params); 349 if (rc) { 350 BNXT_DRV_DBG(ERR, "Unable to get tf version.\n"); 351 return rc; 352 } 353 354 if (v_params.major == 1 && v_params.minor == 0 && 355 v_params.update == 1) { 356 new_fw = 1; 357 } 358 /* if the version update is greater than 0 then set support for 359 * multiple version 360 */ 361 if (new_fw) { 362 ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_MULTI_SHARED_SUPPORT; 363 ulp_ctx->cfg_data->hu_session_type = 364 BNXT_ULP_SESSION_TYPE_SHARED; 365 } 366 if (!new_fw && fw_hu_update) { 367 ulp_ctx->cfg_data->ulp_flags &= ~BNXT_ULP_HIGH_AVAIL_ENABLED; 368 ulp_ctx->cfg_data->hu_session_type = 369 BNXT_ULP_SESSION_TYPE_SHARED | 370 BNXT_ULP_SESSION_TYPE_SHARED_OWC; 371 } 372 373 if (!new_fw && !fw_hu_update) { 374 ulp_ctx->cfg_data->hu_session_type = 375 BNXT_ULP_SESSION_TYPE_SHARED | 376 BNXT_ULP_SESSION_TYPE_SHARED_OWC; 377 } 378 379 return rc; 380 } 381 382 static int32_t 383 ulp_tf_cntxt_app_caps_init(struct bnxt *bp, 384 uint8_t app_id, uint32_t dev_id) 385 { 386 struct bnxt_ulp_app_capabilities_info *info; 387 uint32_t num = 0, fw = 0; 388 uint16_t i; 389 bool found = false; 390 struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx; 391 392 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(ulp_ctx->cfg_data->ulp_flags)) { 393 BNXT_DRV_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 394 app_id, dev_id); 395 return -EINVAL; 396 } 397 398 info = bnxt_ulp_app_cap_list_get(&num); 399 if (!info || !num) { 400 BNXT_DRV_DBG(ERR, "Failed to get app capabilities.\n"); 401 return -EINVAL; 402 } 403 404 for (i = 0; i < num; i++) { 405 if (info[i].app_id != app_id || info[i].device_id != dev_id) 406 continue; 407 found = true; 408 if (info[i].flags & BNXT_ULP_APP_CAP_SHARED_EN) 409 ulp_ctx->cfg_data->ulp_flags |= 410 BNXT_ULP_SHARED_SESSION_ENABLED; 411 if (info[i].flags & BNXT_ULP_APP_CAP_HOT_UPGRADE_EN) 412 ulp_ctx->cfg_data->ulp_flags |= 413 BNXT_ULP_HIGH_AVAIL_ENABLED; 414 if (info[i].flags & BNXT_ULP_APP_CAP_UNICAST_ONLY) 415 ulp_ctx->cfg_data->ulp_flags |= 416 BNXT_ULP_APP_UNICAST_ONLY; 417 if (info[i].flags & BNXT_ULP_APP_CAP_IP_TOS_PROTO_SUPPORT) 418 ulp_ctx->cfg_data->ulp_flags |= 419 BNXT_ULP_APP_TOS_PROTO_SUPPORT; 420 if (info[i].flags & BNXT_ULP_APP_CAP_BC_MC_SUPPORT) 421 ulp_ctx->cfg_data->ulp_flags |= 422 BNXT_ULP_APP_BC_MC_SUPPORT; 423 if (info[i].flags & BNXT_ULP_APP_CAP_SOCKET_DIRECT) { 424 /* Enable socket direction only if MR is enabled in fw*/ 425 if (BNXT_MULTIROOT_EN(bp)) { 426 ulp_ctx->cfg_data->ulp_flags |= 427 BNXT_ULP_APP_SOCKET_DIRECT; 428 BNXT_DRV_DBG(INFO, 429 "Socket Direct feature is enabled\n"); 430 } 431 } 432 if (info[i].flags & BNXT_ULP_APP_CAP_HA_DYNAMIC) { 433 /* Read the environment variable to determine hot up */ 434 if (!bnxt_pmd_get_hot_up_config()) { 435 ulp_ctx->cfg_data->ulp_flags |= 436 BNXT_ULP_APP_HA_DYNAMIC; 437 /* reset Hot upgrade, dynamically disabled */ 438 ulp_ctx->cfg_data->ulp_flags &= 439 ~BNXT_ULP_HIGH_AVAIL_ENABLED; 440 ulp_ctx->cfg_data->def_session_type = 441 BNXT_ULP_SESSION_TYPE_DEFAULT_NON_HA; 442 BNXT_DRV_DBG(INFO, "Hot upgrade disabled.\n"); 443 } 444 } 445 if (info[i].flags & BNXT_ULP_APP_CAP_SRV6) 446 ulp_ctx->cfg_data->ulp_flags |= 447 BNXT_ULP_APP_SRV6; 448 449 if (info[i].flags & BNXT_ULP_APP_CAP_L2_ETYPE) 450 ulp_ctx->cfg_data->ulp_flags |= 451 BNXT_ULP_APP_L2_ETYPE; 452 453 bnxt_ulp_cntxt_vxlan_ip_port_set(ulp_ctx, info[i].vxlan_ip_port); 454 bnxt_ulp_cntxt_vxlan_port_set(ulp_ctx, info[i].vxlan_port); 455 bnxt_ulp_cntxt_ecpri_udp_port_set(ulp_ctx, info[i].ecpri_udp_port); 456 bnxt_ulp_vxlan_gpe_next_proto_set(ulp_ctx, info[i].tunnel_next_proto); 457 bnxt_ulp_num_key_recipes_set(ulp_ctx, 458 info[i].num_key_recipes_per_dir); 459 460 /* set the shared session support from firmware */ 461 fw = info[i].upgrade_fw_update; 462 if (ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags) && 463 ulp_tf_multi_shared_session_support_set(bp, dev_id, fw)) { 464 BNXT_DRV_DBG(ERR, 465 "Unable to get shared session support\n"); 466 return -EINVAL; 467 } 468 bnxt_ulp_cntxt_ha_reg_set(ulp_ctx, info[i].ha_reg_state, 469 info[i].ha_reg_cnt); 470 ulp_ctx->cfg_data->ha_pool_id = info[i].ha_pool_id; 471 bnxt_ulp_default_app_priority_set(ulp_ctx, 472 info[i].default_priority); 473 bnxt_ulp_max_def_priority_set(ulp_ctx, 474 info[i].max_def_priority); 475 bnxt_ulp_min_flow_priority_set(ulp_ctx, 476 info[i].min_flow_priority); 477 bnxt_ulp_max_flow_priority_set(ulp_ctx, 478 info[i].max_flow_priority); 479 /* Update the capability feature bits*/ 480 if (bnxt_ulp_cap_feat_process(info[i].feature_bits, 481 &ulp_ctx->cfg_data->feature_bits)) 482 return -EINVAL; 483 484 bnxt_ulp_cntxt_ptr2_default_class_bits_set(ulp_ctx, 485 info[i].default_class_bits); 486 bnxt_ulp_cntxt_ptr2_default_act_bits_set(ulp_ctx, 487 info[i].default_act_bits); 488 } 489 if (!found) { 490 BNXT_DRV_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 491 app_id, dev_id); 492 ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_APP_DEV_UNSUPPORTED; 493 return -EINVAL; 494 } 495 496 return 0; 497 } 498 499 static inline uint32_t 500 ulp_tf_session_idx_get(enum bnxt_ulp_session_type session_type) { 501 if (session_type & BNXT_ULP_SESSION_TYPE_SHARED) 502 return 1; 503 else if (session_type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 504 return 2; 505 return 0; 506 } 507 508 /* Function to set the tfp session details in session */ 509 static int32_t 510 ulp_tf_session_tfp_set(struct bnxt_ulp_session_state *session, 511 enum bnxt_ulp_session_type session_type, 512 struct tf *tfp) 513 { 514 uint32_t idx = ulp_tf_session_idx_get(session_type); 515 struct tf *local_tfp; 516 int32_t rc = 0; 517 518 if (!session->session_opened[idx]) { 519 local_tfp = rte_zmalloc("bnxt_ulp_session_tfp", 520 sizeof(struct tf), 0); 521 522 if (local_tfp == NULL) { 523 BNXT_DRV_DBG(DEBUG, "Failed to alloc session tfp\n"); 524 return -ENOMEM; 525 } 526 local_tfp->session = tfp->session; 527 session->g_tfp[idx] = local_tfp; 528 session->session_opened[idx] = 1; 529 } 530 return rc; 531 } 532 533 /* Function to get the tfp session details in session */ 534 static struct tf_session_info * 535 ulp_tf_session_tfp_get(struct bnxt_ulp_session_state *session, 536 enum bnxt_ulp_session_type session_type) 537 { 538 uint32_t idx = ulp_tf_session_idx_get(session_type); 539 struct tf *local_tfp = session->g_tfp[idx]; 540 541 if (session->session_opened[idx]) 542 return local_tfp->session; 543 return NULL; 544 } 545 546 static uint32_t 547 ulp_tf_session_is_open(struct bnxt_ulp_session_state *session, 548 enum bnxt_ulp_session_type session_type) 549 { 550 uint32_t idx = ulp_tf_session_idx_get(session_type); 551 552 return session->session_opened[idx]; 553 } 554 555 /* Function to reset the tfp session details in session */ 556 static void 557 ulp_tf_session_tfp_reset(struct bnxt_ulp_session_state *session, 558 enum bnxt_ulp_session_type session_type) 559 { 560 uint32_t idx = ulp_tf_session_idx_get(session_type); 561 562 if (session->session_opened[idx]) { 563 session->session_opened[idx] = 0; 564 rte_free(session->g_tfp[idx]); 565 session->g_tfp[idx] = NULL; 566 } 567 } 568 569 static void 570 ulp_tf_ctx_shared_session_close(struct bnxt *bp, 571 enum bnxt_ulp_session_type session_type, 572 struct bnxt_ulp_session_state *session) 573 { 574 struct tf *tfp; 575 int32_t rc; 576 577 tfp = bnxt_ulp_cntxt_tfp_get(bp->ulp_ctx, session_type); 578 if (!tfp) { 579 /* 580 * Log it under debug since this is likely a case of the 581 * shared session not being created. For example, a failed 582 * initialization. 583 */ 584 BNXT_DRV_DBG(DEBUG, "Failed to get shared tfp on close.\n"); 585 return; 586 } 587 rc = tf_close_session(tfp); 588 if (rc) 589 BNXT_DRV_DBG(ERR, "Failed to close the shared session rc=%d.\n", 590 rc); 591 (void)bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session_type, NULL); 592 ulp_tf_session_tfp_reset(session, session_type); 593 } 594 595 static int32_t 596 ulp_tf_ctx_shared_session_open(struct bnxt *bp, 597 enum bnxt_ulp_session_type session_type, 598 struct bnxt_ulp_session_state *session) 599 { 600 struct rte_eth_dev *ethdev = bp->eth_dev; 601 struct tf_session_resources *resources; 602 struct tf_open_session_parms parms; 603 size_t nb; 604 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 605 int32_t rc = 0; 606 uint8_t app_id; 607 struct tf *tfp; 608 uint8_t pool_id; 609 610 memset(&parms, 0, sizeof(parms)); 611 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 612 parms.ctrl_chan_name); 613 if (rc) { 614 BNXT_DRV_DBG(ERR, "Invalid port %d, rc = %d\n", 615 ethdev->data->port_id, rc); 616 return rc; 617 } 618 619 /* On multi-host system, adjust ctrl_chan_name to avoid confliction */ 620 if (BNXT_MH(bp)) { 621 rc = ulp_ctx_mh_get_session_name(bp, &parms); 622 if (rc) 623 return rc; 624 } 625 626 resources = &parms.resources; 627 628 /* 629 * Need to account for size of ctrl_chan_name and 1 extra for Null 630 * terminator 631 */ 632 nb = sizeof(parms.ctrl_chan_name) - strlen(parms.ctrl_chan_name) - 1; 633 634 /* 635 * Build the ctrl_chan_name with shared token. 636 * When HA is enabled, the WC TCAM needs extra management by the core, 637 * so add the wc_tcam string to the control channel. 638 */ 639 pool_id = bp->ulp_ctx->cfg_data->ha_pool_id; 640 if (!bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 641 if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) 642 strncat(parms.ctrl_chan_name, "-tf_shared-wc_tcam", nb); 643 else 644 strncat(parms.ctrl_chan_name, "-tf_shared", nb); 645 } else if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 646 if (session_type == BNXT_ULP_SESSION_TYPE_SHARED) { 647 strncat(parms.ctrl_chan_name, "-tf_shared", nb); 648 } else if (session_type == BNXT_ULP_SESSION_TYPE_SHARED_WC) { 649 char session_pool_name[64]; 650 651 sprintf(session_pool_name, "-tf_shared-pool%d", 652 pool_id); 653 654 if (nb >= strlen(session_pool_name)) { 655 strncat(parms.ctrl_chan_name, session_pool_name, nb); 656 } else { 657 BNXT_DRV_DBG(ERR, "No space left for session_name\n"); 658 return -EINVAL; 659 } 660 } 661 } 662 663 rc = ulp_tf_shared_session_resources_get(bp->ulp_ctx, session_type, 664 resources); 665 if (rc) 666 return rc; 667 668 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 669 if (rc) { 670 BNXT_DRV_DBG(ERR, "Unable to get the app id from ulp.\n"); 671 return -EINVAL; 672 } 673 674 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 675 if (rc) { 676 BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n"); 677 return rc; 678 } 679 680 tfp = bnxt_ulp_bp_tfp_get(bp, session_type); 681 parms.device_type = bnxt_ulp_cntxt_convert_dev_id(ulp_dev_id); 682 parms.bp = bp; 683 684 /* 685 * Open the session here, but the collect the resources during the 686 * mapper initialization. 687 */ 688 rc = tf_open_session(tfp, &parms); 689 if (rc) 690 return rc; 691 692 if (parms.shared_session_creator) 693 BNXT_DRV_DBG(DEBUG, "Shared session creator.\n"); 694 else 695 BNXT_DRV_DBG(DEBUG, "Shared session attached.\n"); 696 697 /* Save the shared session in global data */ 698 rc = ulp_tf_session_tfp_set(session, session_type, tfp); 699 if (rc) { 700 BNXT_DRV_DBG(ERR, "Failed to add shared tfp to session\n"); 701 return rc; 702 } 703 704 rc = bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session_type, tfp); 705 if (rc) { 706 BNXT_DRV_DBG(ERR, "Failed to add shared tfp to ulp (%d)\n", rc); 707 return rc; 708 } 709 710 return rc; 711 } 712 713 static int32_t 714 ulp_tf_ctx_shared_session_attach(struct bnxt *bp, 715 struct bnxt_ulp_session_state *ses) 716 { 717 enum bnxt_ulp_session_type type; 718 struct tf *tfp; 719 int32_t rc = 0; 720 721 /* Simply return success if shared session not enabled */ 722 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 723 type = BNXT_ULP_SESSION_TYPE_SHARED; 724 tfp = bnxt_ulp_bp_tfp_get(bp, type); 725 tfp->session = ulp_tf_session_tfp_get(ses, type); 726 rc = ulp_tf_ctx_shared_session_open(bp, type, ses); 727 } 728 729 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 730 type = BNXT_ULP_SESSION_TYPE_SHARED_WC; 731 tfp = bnxt_ulp_bp_tfp_get(bp, type); 732 tfp->session = ulp_tf_session_tfp_get(ses, type); 733 rc = ulp_tf_ctx_shared_session_open(bp, type, ses); 734 } 735 736 if (!rc) 737 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, true); 738 739 return rc; 740 } 741 742 static void 743 ulp_tf_ctx_shared_session_detach(struct bnxt *bp) 744 { 745 struct tf *tfp; 746 747 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 748 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_SHARED); 749 if (tfp->session) { 750 tf_close_session(tfp); 751 tfp->session = NULL; 752 } 753 } 754 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 755 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_SHARED_WC); 756 if (tfp->session) { 757 tf_close_session(tfp); 758 tfp->session = NULL; 759 } 760 } 761 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, false); 762 } 763 764 /* 765 * Initialize an ULP session. 766 * An ULP session will contain all the resources needed to support rte flow 767 * offloads. A session is initialized as part of rte_eth_device start. 768 * A single vswitch instance can have multiple uplinks which means 769 * rte_eth_device start will be called for each of these devices. 770 * ULP session manager will make sure that a single ULP session is only 771 * initialized once. Apart from this, it also initializes MARK database, 772 * EEM table & flow database. ULP session manager also manages a list of 773 * all opened ULP sessions. 774 */ 775 static int32_t 776 ulp_tf_ctx_session_open(struct bnxt *bp, 777 struct bnxt_ulp_session_state *session) 778 { 779 struct rte_eth_dev *ethdev = bp->eth_dev; 780 int32_t rc = 0; 781 struct tf_open_session_parms params; 782 struct tf_session_resources *resources; 783 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 784 uint8_t app_id; 785 struct tf *tfp; 786 787 memset(¶ms, 0, sizeof(params)); 788 789 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 790 params.ctrl_chan_name); 791 if (rc) { 792 BNXT_DRV_DBG(ERR, "Invalid port %d, rc = %d\n", 793 ethdev->data->port_id, rc); 794 return rc; 795 } 796 797 /* On multi-host system, adjust ctrl_chan_name to avoid confliction */ 798 if (BNXT_MH(bp)) { 799 rc = ulp_ctx_mh_get_session_name(bp, ¶ms); 800 if (rc) 801 return rc; 802 } 803 804 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 805 if (rc) { 806 BNXT_DRV_DBG(ERR, "Unable to get the app id from ulp.\n"); 807 return -EINVAL; 808 } 809 810 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 811 if (rc) { 812 BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n"); 813 return rc; 814 } 815 816 params.device_type = bnxt_ulp_cntxt_convert_dev_id(ulp_dev_id); 817 resources = ¶ms.resources; 818 rc = ulp_tf_resources_get(bp->ulp_ctx, 819 BNXT_ULP_SESSION_TYPE_DEFAULT, 820 resources); 821 if (rc) 822 return rc; 823 824 params.bp = bp; 825 826 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 827 rc = tf_open_session(tfp, ¶ms); 828 if (rc) { 829 BNXT_DRV_DBG(ERR, "Failed to open TF session - %s, rc = %d\n", 830 params.ctrl_chan_name, rc); 831 return -EINVAL; 832 } 833 rc = ulp_tf_session_tfp_set(session, BNXT_ULP_SESSION_TYPE_DEFAULT, tfp); 834 if (rc) { 835 BNXT_DRV_DBG(ERR, "Failed to set TF session - %s, rc = %d\n", 836 params.ctrl_chan_name, rc); 837 return -EINVAL; 838 } 839 return rc; 840 } 841 842 /* 843 * Close the ULP session. 844 * It takes the ulp context pointer. 845 */ 846 static void 847 ulp_tf_ctx_session_close(struct bnxt *bp, 848 struct bnxt_ulp_session_state *session) 849 { 850 struct tf *tfp; 851 852 /* close the session in the hardware */ 853 if (ulp_tf_session_is_open(session, BNXT_ULP_SESSION_TYPE_DEFAULT)) { 854 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 855 tf_close_session(tfp); 856 } 857 ulp_tf_session_tfp_reset(session, BNXT_ULP_SESSION_TYPE_DEFAULT); 858 } 859 860 static void 861 ulp_tf_init_tbl_scope_parms(struct bnxt *bp, 862 struct tf_alloc_tbl_scope_parms *params) 863 { 864 struct bnxt_ulp_device_params *dparms; 865 uint32_t dev_id; 866 int rc; 867 868 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 869 if (rc) 870 /* TBD: For now, just use default. */ 871 dparms = 0; 872 else 873 dparms = bnxt_ulp_device_params_get(dev_id); 874 875 /* 876 * Set the flush timer for EEM entries. The value is in 100ms intervals, 877 * so 100 is 10s. 878 */ 879 params->hw_flow_cache_flush_timer = 100; 880 881 if (!dparms) { 882 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 883 params->rx_max_action_entry_sz_in_bits = 884 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 885 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 886 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS; 887 888 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 889 params->tx_max_action_entry_sz_in_bits = 890 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 891 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 892 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS; 893 } else { 894 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 895 params->rx_max_action_entry_sz_in_bits = 896 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 897 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 898 params->rx_num_flows_in_k = 899 dparms->ext_flow_db_num_entries / 1024; 900 901 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 902 params->tx_max_action_entry_sz_in_bits = 903 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 904 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 905 params->tx_num_flows_in_k = 906 dparms->ext_flow_db_num_entries / 1024; 907 } 908 BNXT_DRV_DBG(INFO, "Table Scope initialized with %uK flows.\n", 909 params->rx_num_flows_in_k); 910 } 911 912 /* Initialize Extended Exact Match host memory. */ 913 static int32_t 914 ulp_tf_eem_tbl_scope_init(struct bnxt *bp) 915 { 916 struct tf_alloc_tbl_scope_parms params = {0}; 917 struct bnxt_ulp_device_params *dparms; 918 enum bnxt_ulp_flow_mem_type mtype; 919 uint32_t dev_id; 920 struct tf *tfp; 921 int rc; 922 923 /* Get the dev specific number of flows that needed to be supported. */ 924 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 925 BNXT_DRV_DBG(ERR, "Invalid device id\n"); 926 return -EINVAL; 927 } 928 929 dparms = bnxt_ulp_device_params_get(dev_id); 930 if (!dparms) { 931 BNXT_DRV_DBG(ERR, "could not fetch the device params\n"); 932 return -ENODEV; 933 } 934 935 if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype)) 936 return -EINVAL; 937 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 938 BNXT_DRV_DBG(INFO, "Table Scope alloc is not required\n"); 939 return 0; 940 } 941 942 ulp_tf_init_tbl_scope_parms(bp, ¶ms); 943 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 944 rc = tf_alloc_tbl_scope(tfp, ¶ms); 945 if (rc) { 946 BNXT_DRV_DBG(ERR, 947 "Unable to allocate eem table scope rc = %d\n", 948 rc); 949 return rc; 950 } 951 952 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 953 BNXT_DRV_DBG(DEBUG, "TableScope=0x%0x %d\n", 954 params.tbl_scope_id, 955 params.tbl_scope_id); 956 #endif 957 958 rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id); 959 if (rc) { 960 BNXT_DRV_DBG(ERR, "Unable to set table scope id\n"); 961 return rc; 962 } 963 964 return 0; 965 } 966 967 /* Free Extended Exact Match host memory */ 968 static int32_t 969 ulp_tf_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 970 { 971 struct tf_free_tbl_scope_parms params = {0}; 972 struct tf *tfp; 973 int32_t rc = 0; 974 struct bnxt_ulp_device_params *dparms; 975 enum bnxt_ulp_flow_mem_type mtype; 976 uint32_t dev_id; 977 978 if (!ulp_ctx || !ulp_ctx->cfg_data) 979 return -EINVAL; 980 981 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT); 982 if (!tfp) { 983 BNXT_DRV_DBG(ERR, "Failed to get the truflow pointer\n"); 984 return -EINVAL; 985 } 986 987 /* Get the dev specific number of flows that needed to be supported. */ 988 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 989 BNXT_DRV_DBG(ERR, "Invalid device id\n"); 990 return -EINVAL; 991 } 992 993 dparms = bnxt_ulp_device_params_get(dev_id); 994 if (!dparms) { 995 BNXT_DRV_DBG(ERR, "could not fetch the device params\n"); 996 return -ENODEV; 997 } 998 999 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype)) 1000 return -EINVAL; 1001 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 1002 BNXT_DRV_DBG(INFO, "Table Scope free is not required\n"); 1003 return 0; 1004 } 1005 1006 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, ¶ms.tbl_scope_id); 1007 if (rc) { 1008 BNXT_DRV_DBG(ERR, "Failed to get the table scope id\n"); 1009 return -EINVAL; 1010 } 1011 1012 rc = tf_free_tbl_scope(tfp, ¶ms); 1013 if (rc) { 1014 BNXT_DRV_DBG(ERR, "Unable to free table scope\n"); 1015 return -EINVAL; 1016 } 1017 return rc; 1018 } 1019 1020 /* The function to free and deinit the ulp context data. */ 1021 static int32_t 1022 ulp_tf_ctx_deinit(struct bnxt *bp, 1023 struct bnxt_ulp_session_state *session) 1024 { 1025 /* close the tf session */ 1026 ulp_tf_ctx_session_close(bp, session); 1027 1028 /* The shared session must be closed last. */ 1029 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) 1030 ulp_tf_ctx_shared_session_close(bp, BNXT_ULP_SESSION_TYPE_SHARED, 1031 session); 1032 1033 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) 1034 ulp_tf_ctx_shared_session_close(bp, 1035 BNXT_ULP_SESSION_TYPE_SHARED_WC, 1036 session); 1037 1038 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, false); 1039 1040 /* Free the contents */ 1041 if (session->cfg_data) { 1042 rte_free(session->cfg_data); 1043 bp->ulp_ctx->cfg_data = NULL; 1044 session->cfg_data = NULL; 1045 } 1046 return 0; 1047 } 1048 1049 /* The function to allocate and initialize the ulp context data. */ 1050 static int32_t 1051 ulp_tf_ctx_init(struct bnxt *bp, 1052 struct bnxt_ulp_session_state *session) 1053 { 1054 struct bnxt_ulp_data *ulp_data; 1055 int32_t rc = 0; 1056 enum bnxt_ulp_device_id devid; 1057 enum bnxt_ulp_session_type stype; 1058 struct tf *tfp; 1059 1060 /* Initialize the context entries list */ 1061 bnxt_ulp_cntxt_list_init(); 1062 1063 /* Allocate memory to hold ulp context data. */ 1064 ulp_data = rte_zmalloc("bnxt_ulp_data", 1065 sizeof(struct bnxt_ulp_data), 0); 1066 if (!ulp_data) { 1067 BNXT_DRV_DBG(ERR, "Failed to allocate memory for ulp data\n"); 1068 return -ENOMEM; 1069 } 1070 1071 /* Increment the ulp context data reference count usage. */ 1072 bp->ulp_ctx->cfg_data = ulp_data; 1073 session->cfg_data = ulp_data; 1074 ulp_data->ref_cnt++; 1075 ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED; 1076 1077 /* Add the context to the context entries list */ 1078 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 1079 if (rc) { 1080 BNXT_DRV_DBG(ERR, "Failed to add the context list entry\n"); 1081 goto error_deinit; 1082 } 1083 1084 rc = bnxt_ulp_devid_get(bp, &devid); 1085 if (rc) { 1086 BNXT_DRV_DBG(ERR, "Unable to determine device for ULP init.\n"); 1087 goto error_deinit; 1088 } 1089 1090 rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid); 1091 if (rc) { 1092 BNXT_DRV_DBG(ERR, "Unable to set device for ULP init.\n"); 1093 goto error_deinit; 1094 } 1095 1096 rc = bnxt_ulp_cntxt_app_id_set(bp->ulp_ctx, bp->app_id); 1097 if (rc) { 1098 BNXT_DRV_DBG(ERR, "Unable to set app_id for ULP init.\n"); 1099 goto error_deinit; 1100 } 1101 BNXT_DRV_DBG(DEBUG, "Ulp initialized with app id %d\n", bp->app_id); 1102 1103 rc = ulp_tf_cntxt_app_caps_init(bp, bp->app_id, devid); 1104 if (rc) { 1105 BNXT_DRV_DBG(ERR, "Unable to set caps for app(%x)/dev(%x)\n", 1106 bp->app_id, devid); 1107 goto error_deinit; 1108 } 1109 1110 if (BNXT_TESTPMD_EN(bp)) { 1111 ulp_data->ulp_flags &= ~BNXT_ULP_VF_REP_ENABLED; 1112 BNXT_DRV_DBG(ERR, "Enabled Testpmd forward mode\n"); 1113 } 1114 1115 /* 1116 * Shared session must be created before first regular session but after 1117 * the ulp_ctx is valid. 1118 */ 1119 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 1120 rc = ulp_tf_ctx_shared_session_open(bp, 1121 BNXT_ULP_SESSION_TYPE_SHARED, 1122 session); 1123 if (rc) { 1124 BNXT_DRV_DBG(ERR, "Unable to open shared session (%d)\n", 1125 rc); 1126 goto error_deinit; 1127 } 1128 } 1129 1130 /* Multiple session support */ 1131 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 1132 stype = BNXT_ULP_SESSION_TYPE_SHARED_WC; 1133 rc = ulp_tf_ctx_shared_session_open(bp, stype, session); 1134 if (rc) { 1135 BNXT_DRV_DBG(ERR, 1136 "Unable to open shared wc session (%d)\n", 1137 rc); 1138 goto error_deinit; 1139 } 1140 } 1141 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, true); 1142 1143 /* Open the ulp session. */ 1144 rc = ulp_tf_ctx_session_open(bp, session); 1145 if (rc) 1146 goto error_deinit; 1147 1148 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1149 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT, tfp); 1150 return rc; 1151 1152 error_deinit: 1153 session->session_opened[BNXT_ULP_SESSION_TYPE_DEFAULT] = 1; 1154 (void)ulp_tf_ctx_deinit(bp, session); 1155 return rc; 1156 } 1157 1158 /* The function to initialize ulp dparms with devargs */ 1159 static int32_t 1160 ulp_tf_dparms_init(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 1161 { 1162 struct bnxt_ulp_device_params *dparms; 1163 uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST; 1164 1165 if (!bp->max_num_kflows) { 1166 /* Defaults to Internal */ 1167 bnxt_ulp_cntxt_mem_type_set(ulp_ctx, 1168 BNXT_ULP_FLOW_MEM_TYPE_INT); 1169 return 0; 1170 } 1171 1172 /* The max_num_kflows were set, so move to external */ 1173 if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT)) 1174 return -EINVAL; 1175 1176 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 1177 BNXT_DRV_DBG(DEBUG, "Failed to get device id\n"); 1178 return -EINVAL; 1179 } 1180 1181 dparms = bnxt_ulp_device_params_get(dev_id); 1182 if (!dparms) { 1183 BNXT_DRV_DBG(DEBUG, "Failed to get device parms\n"); 1184 return -EINVAL; 1185 } 1186 1187 /* num_flows = max_num_kflows * 1024 */ 1188 dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024; 1189 /* GFID = 2 * num_flows */ 1190 dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2; 1191 BNXT_DRV_DBG(DEBUG, "Set the number of flows = %" PRIu64 "\n", 1192 dparms->ext_flow_db_num_entries); 1193 1194 return 0; 1195 } 1196 1197 static int32_t 1198 ulp_tf_ctx_attach(struct bnxt *bp, 1199 struct bnxt_ulp_session_state *session) 1200 { 1201 int32_t rc = 0; 1202 uint32_t flags, dev_id = BNXT_ULP_DEVICE_ID_LAST; 1203 struct tf *tfp; 1204 uint8_t app_id; 1205 1206 /* Increment the ulp context data reference count usage. */ 1207 bp->ulp_ctx->cfg_data = session->cfg_data; 1208 bp->ulp_ctx->cfg_data->ref_cnt++; 1209 1210 /* update the session details in bnxt tfp */ 1211 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1212 tfp->session = ulp_tf_session_tfp_get(session, 1213 BNXT_ULP_SESSION_TYPE_DEFAULT); 1214 1215 /* Add the context to the context entries list */ 1216 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 1217 if (rc) { 1218 BNXT_DRV_DBG(ERR, "Failed to add the context list entry\n"); 1219 return -EINVAL; 1220 } 1221 1222 /* 1223 * The supported flag will be set during the init. Use it now to 1224 * know if we should go through the attach. 1225 */ 1226 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 1227 if (rc) { 1228 BNXT_DRV_DBG(ERR, "Unable to get the app id from ulp.\n"); 1229 return -EINVAL; 1230 } 1231 1232 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 1233 if (rc) { 1234 BNXT_DRV_DBG(ERR, "Unable do get the dev_id.\n"); 1235 return -EINVAL; 1236 } 1237 1238 flags = bp->ulp_ctx->cfg_data->ulp_flags; 1239 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(flags)) { 1240 BNXT_DRV_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 1241 app_id, dev_id); 1242 return -EINVAL; 1243 } 1244 1245 /* Create a TF Client */ 1246 rc = ulp_tf_ctx_session_open(bp, session); 1247 if (rc) { 1248 BNXT_DRV_DBG(ERR, "Failed to open ctxt session, rc:%d\n", rc); 1249 tfp->session = NULL; 1250 return rc; 1251 } 1252 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1253 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT, tfp); 1254 1255 /* 1256 * Attach to the shared session, must be called after the 1257 * ulp_ctx_attach in order to ensure that ulp data is available 1258 * for attaching. 1259 */ 1260 rc = ulp_tf_ctx_shared_session_attach(bp, session); 1261 if (rc) 1262 BNXT_DRV_DBG(ERR, "Failed attach to shared session (%d)", rc); 1263 1264 return rc; 1265 } 1266 1267 static void 1268 ulp_tf_ctx_detach(struct bnxt *bp, 1269 struct bnxt_ulp_session_state *session __rte_unused) 1270 { 1271 struct tf *tfp; 1272 1273 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1274 if (tfp->session) { 1275 tf_close_session(tfp); 1276 tfp->session = NULL; 1277 } 1278 1279 /* always detach/close shared after the session. */ 1280 ulp_tf_ctx_shared_session_detach(bp); 1281 } 1282 1283 /* 1284 * Internal api to enable NAT feature. 1285 * Set set_flag to 1 to set the value or zero to reset the value. 1286 * returns 0 on success. 1287 */ 1288 static int32_t 1289 ulp_tf_global_cfg_update(struct bnxt *bp, 1290 enum tf_dir dir, 1291 enum tf_global_config_type type, 1292 uint32_t offset, 1293 uint32_t value, 1294 uint32_t set_flag) 1295 { 1296 uint32_t global_cfg = 0; 1297 int rc; 1298 struct tf_global_cfg_parms parms = { 0 }; 1299 struct tf *tfp; 1300 1301 /* Initialize the params */ 1302 parms.dir = dir, 1303 parms.type = type, 1304 parms.offset = offset, 1305 parms.config = (uint8_t *)&global_cfg, 1306 parms.config_sz_in_bytes = sizeof(global_cfg); 1307 1308 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1309 rc = tf_get_global_cfg(tfp, &parms); 1310 if (rc) { 1311 BNXT_DRV_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n", 1312 type, rc); 1313 return rc; 1314 } 1315 1316 if (set_flag) 1317 global_cfg |= value; 1318 else 1319 global_cfg &= ~value; 1320 1321 /* SET the register RE_CFA_REG_ACT_TECT */ 1322 rc = tf_set_global_cfg(tfp, &parms); 1323 if (rc) { 1324 BNXT_DRV_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n", 1325 type, rc); 1326 return rc; 1327 } 1328 return rc; 1329 } 1330 1331 /** 1332 * When a port is initialized by dpdk. This functions is called 1333 * to enable the meter and initializes the meter global configurations. 1334 */ 1335 #define BNXT_THOR_FMTCR_NUM_MET_MET_1K (0x7UL << 20) 1336 #define BNXT_THOR_FMTCR_CNTRS_ENABLE (0x1UL << 25) 1337 #define BNXT_THOR_FMTCR_INTERVAL_1K (1024) 1338 static int32_t 1339 ulp_tf_flow_mtr_init(struct bnxt *bp) 1340 { 1341 int rc = 0; 1342 1343 /* 1344 * Enable metering. Set the meter global configuration register. 1345 * Set number of meter to 1K. Disable the drop counter for now. 1346 */ 1347 rc = ulp_tf_global_cfg_update(bp, TF_DIR_RX, TF_METER_CFG, 1348 0, 1349 BNXT_THOR_FMTCR_NUM_MET_MET_1K, 1350 1); 1351 if (rc) { 1352 BNXT_DRV_DBG(ERR, "Failed to set rx meter configuration\n"); 1353 goto jump_to_error; 1354 } 1355 1356 rc = ulp_tf_global_cfg_update(bp, TF_DIR_TX, TF_METER_CFG, 1357 0, 1358 BNXT_THOR_FMTCR_NUM_MET_MET_1K, 1359 1); 1360 if (rc) { 1361 BNXT_DRV_DBG(ERR, "Failed to set tx meter configuration\n"); 1362 goto jump_to_error; 1363 } 1364 1365 /* 1366 * Set meter refresh rate to 1024 clock cycle. This value works for 1367 * most bit rates especially for high rates. 1368 */ 1369 rc = ulp_tf_global_cfg_update(bp, TF_DIR_RX, TF_METER_INTERVAL_CFG, 1370 0, 1371 BNXT_THOR_FMTCR_INTERVAL_1K, 1372 1); 1373 if (rc) { 1374 BNXT_DRV_DBG(ERR, "Failed to set rx meter interval\n"); 1375 goto jump_to_error; 1376 } 1377 1378 rc = bnxt_flow_mtr_init(bp); 1379 if (rc) { 1380 BNXT_DRV_DBG(ERR, "Failed to config meter\n"); 1381 goto jump_to_error; 1382 } 1383 1384 return rc; 1385 1386 jump_to_error: 1387 return rc; 1388 } 1389 1390 /* 1391 * When a port is deinit'ed by dpdk. This function is called 1392 * and this function clears the ULP context and rest of the 1393 * infrastructure associated with it. 1394 */ 1395 static void 1396 ulp_tf_deinit(struct bnxt *bp, 1397 struct bnxt_ulp_session_state *session) 1398 { 1399 bool ha_enabled; 1400 1401 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 1402 return; 1403 1404 ha_enabled = bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx); 1405 if (ha_enabled && 1406 ulp_tf_session_is_open(session, BNXT_ULP_SESSION_TYPE_DEFAULT)) { 1407 int32_t rc = ulp_ha_mgr_close(bp->ulp_ctx); 1408 if (rc) 1409 BNXT_DRV_DBG(ERR, "Failed to close HA (%d)\n", rc); 1410 } 1411 1412 /* cleanup the eem table scope */ 1413 ulp_tf_eem_tbl_scope_deinit(bp, bp->ulp_ctx); 1414 1415 /* cleanup the flow database */ 1416 ulp_flow_db_deinit(bp->ulp_ctx); 1417 1418 /* Delete the Mark database */ 1419 ulp_mark_db_deinit(bp->ulp_ctx); 1420 1421 /* cleanup the ulp mapper */ 1422 ulp_mapper_deinit(bp->ulp_ctx); 1423 1424 /* cleanup the ulp matcher */ 1425 ulp_matcher_deinit(bp->ulp_ctx); 1426 1427 /* Delete the Flow Counter Manager */ 1428 ulp_fc_mgr_deinit(bp->ulp_ctx); 1429 1430 /* Delete the Port database */ 1431 ulp_port_db_deinit(bp->ulp_ctx); 1432 1433 /* Disable NAT feature */ 1434 (void)ulp_tf_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 1435 TF_TUNNEL_ENCAP_NAT, 1436 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 1437 1438 (void)ulp_tf_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 1439 TF_TUNNEL_ENCAP_NAT, 1440 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 1441 1442 /* free the flow db lock */ 1443 pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock); 1444 1445 if (ha_enabled) 1446 ulp_ha_mgr_deinit(bp->ulp_ctx); 1447 1448 /* Delete the ulp context and tf session and free the ulp context */ 1449 ulp_tf_ctx_deinit(bp, session); 1450 BNXT_DRV_DBG(DEBUG, "ulp ctx has been deinitialized\n"); 1451 } 1452 1453 /* 1454 * When a port is initialized by dpdk. This functions is called 1455 * and this function initializes the ULP context and rest of the 1456 * infrastructure associated with it. 1457 */ 1458 static int32_t 1459 ulp_tf_init(struct bnxt *bp, 1460 struct bnxt_ulp_session_state *session) 1461 { 1462 int rc; 1463 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 1464 1465 /* Select 64bit SSE4.2 intrinsic if available */ 1466 rte_hash_crc_set_alg(CRC32_SSE42_x64); 1467 1468 /* Allocate and Initialize the ulp context. */ 1469 rc = ulp_tf_ctx_init(bp, session); 1470 if (rc) { 1471 BNXT_DRV_DBG(ERR, "Failed to create the ulp context\n"); 1472 goto jump_to_error; 1473 } 1474 1475 pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL); 1476 1477 /* Initialize ulp dparms with values devargs passed */ 1478 rc = ulp_tf_dparms_init(bp, bp->ulp_ctx); 1479 if (rc) { 1480 BNXT_DRV_DBG(ERR, "Failed to initialize the dparms\n"); 1481 goto jump_to_error; 1482 } 1483 1484 /* create the port database */ 1485 rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt); 1486 if (rc) { 1487 BNXT_DRV_DBG(ERR, "Failed to create the port database\n"); 1488 goto jump_to_error; 1489 } 1490 1491 /* Create the Mark database. */ 1492 rc = ulp_mark_db_init(bp->ulp_ctx); 1493 if (rc) { 1494 BNXT_DRV_DBG(ERR, "Failed to create the mark database\n"); 1495 goto jump_to_error; 1496 } 1497 1498 /* Create the flow database. */ 1499 rc = ulp_flow_db_init(bp->ulp_ctx); 1500 if (rc) { 1501 BNXT_DRV_DBG(ERR, "Failed to create the flow database\n"); 1502 goto jump_to_error; 1503 } 1504 1505 /* Create the eem table scope. */ 1506 rc = ulp_tf_eem_tbl_scope_init(bp); 1507 if (rc) { 1508 BNXT_DRV_DBG(ERR, "Failed to create the eem scope table\n"); 1509 goto jump_to_error; 1510 } 1511 1512 rc = ulp_matcher_init(bp->ulp_ctx); 1513 if (rc) { 1514 BNXT_DRV_DBG(ERR, "Failed to initialize ulp matcher\n"); 1515 goto jump_to_error; 1516 } 1517 1518 rc = ulp_mapper_init(bp->ulp_ctx); 1519 if (rc) { 1520 BNXT_DRV_DBG(ERR, "Failed to initialize ulp mapper\n"); 1521 goto jump_to_error; 1522 } 1523 1524 rc = ulp_fc_mgr_init(bp->ulp_ctx); 1525 if (rc) { 1526 BNXT_DRV_DBG(ERR, "Failed to initialize ulp flow counter mgr\n"); 1527 goto jump_to_error; 1528 } 1529 1530 /* 1531 * Enable NAT feature. Set the global configuration register 1532 * Tunnel encap to enable NAT with the reuse of existing inner 1533 * L2 header smac and dmac 1534 */ 1535 rc = ulp_tf_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 1536 TF_TUNNEL_ENCAP_NAT, 1537 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 1538 if (rc) { 1539 BNXT_DRV_DBG(ERR, "Failed to set rx global configuration\n"); 1540 goto jump_to_error; 1541 } 1542 1543 rc = ulp_tf_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 1544 TF_TUNNEL_ENCAP_NAT, 1545 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 1546 if (rc) { 1547 BNXT_DRV_DBG(ERR, "Failed to set tx global configuration\n"); 1548 goto jump_to_error; 1549 } 1550 1551 if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) { 1552 rc = ulp_ha_mgr_init(bp->ulp_ctx); 1553 if (rc) { 1554 BNXT_DRV_DBG(ERR, "Failed to initialize HA %d\n", rc); 1555 goto jump_to_error; 1556 } 1557 rc = ulp_ha_mgr_open(bp->ulp_ctx); 1558 if (rc) { 1559 BNXT_DRV_DBG(ERR, "Failed to Process HA Open %d\n", rc); 1560 goto jump_to_error; 1561 } 1562 } 1563 1564 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 1565 if (rc) { 1566 BNXT_DRV_DBG(ERR, "Unable to get device id from ulp.\n"); 1567 return rc; 1568 } 1569 1570 if (ulp_dev_id == BNXT_ULP_DEVICE_ID_THOR) { 1571 rc = ulp_tf_flow_mtr_init(bp); 1572 if (rc) { 1573 BNXT_DRV_DBG(ERR, "Failed to config meter\n"); 1574 goto jump_to_error; 1575 } 1576 } 1577 1578 BNXT_DRV_DBG(DEBUG, "ulp ctx has been initialized\n"); 1579 return rc; 1580 1581 jump_to_error: 1582 bp->ulp_ctx->ops->ulp_deinit(bp, session); 1583 return rc; 1584 } 1585 1586 /** 1587 * Get meter capabilities. 1588 */ 1589 #define MAX_FLOW_PER_METER 1024 1590 #define MAX_METER_RATE_100GBPS ((1ULL << 30) * 100 / 8) 1591 static int 1592 ulp_tf_mtr_cap_get(struct bnxt *bp, 1593 struct rte_mtr_capabilities *cap) 1594 { 1595 struct tf_get_session_info_parms iparms; 1596 struct tf *tfp; 1597 int32_t rc = 0; 1598 1599 /* Get number of meter reserved for this session */ 1600 memset(&iparms, 0, sizeof(iparms)); 1601 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1602 rc = tf_get_session_info(tfp, &iparms); 1603 if (rc != 0) { 1604 BNXT_DRV_DBG(ERR, "Failed to get session resource info\n"); 1605 return rc; 1606 } 1607 1608 memset(cap, 0, sizeof(struct rte_mtr_capabilities)); 1609 1610 cap->n_max = iparms.session_info.tbl[TF_DIR_RX].info[TF_TBL_TYPE_METER_INST].stride; 1611 if (!cap->n_max) { 1612 BNXT_DRV_DBG(ERR, "Meter is not supported\n"); 1613 return -EINVAL; 1614 } 1615 1616 #if (RTE_VERSION_NUM(21, 05, 0, 0) <= RTE_VERSION) 1617 cap->srtcm_rfc2697_byte_mode_supported = 1; 1618 #endif 1619 cap->n_shared_max = cap->n_max; 1620 /* No meter is identical */ 1621 cap->identical = 1; 1622 cap->shared_identical = 1; 1623 cap->shared_n_flows_per_mtr_max = MAX_FLOW_PER_METER; 1624 cap->chaining_n_mtrs_per_flow_max = 1; /* Chaining is not supported. */ 1625 cap->meter_srtcm_rfc2697_n_max = cap->n_max; 1626 cap->meter_rate_max = MAX_METER_RATE_100GBPS; 1627 /* No stats supported now */ 1628 cap->stats_mask = 0; 1629 1630 return 0; 1631 } 1632 1633 const struct bnxt_ulp_core_ops bnxt_ulp_tf_core_ops = { 1634 .ulp_ctx_attach = ulp_tf_ctx_attach, 1635 .ulp_ctx_detach = ulp_tf_ctx_detach, 1636 .ulp_deinit = ulp_tf_deinit, 1637 .ulp_init = ulp_tf_init, 1638 .ulp_vfr_session_fid_add = NULL, 1639 .ulp_vfr_session_fid_rem = NULL, 1640 .ulp_mtr_cap_get = ulp_tf_mtr_cap_get 1641 }; 1642