1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2023 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 13 #include "bnxt.h" 14 #include "bnxt_ulp.h" 15 #include "bnxt_tf_common.h" 16 #include "hsi_struct_def_dpdk.h" 17 #include "tf_core.h" 18 #include "tf_ext_flow_handle.h" 19 20 #include "ulp_template_db_enum.h" 21 #include "ulp_template_struct.h" 22 #include "ulp_mark_mgr.h" 23 #include "ulp_fc_mgr.h" 24 #include "ulp_flow_db.h" 25 #include "ulp_mapper.h" 26 #include "ulp_port_db.h" 27 #include "ulp_tun.h" 28 #include "ulp_ha_mgr.h" 29 #include "bnxt_tf_pmd_shim.h" 30 #include "ulp_template_db_tbl.h" 31 32 /* Linked list of all TF sessions. */ 33 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list = 34 STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list); 35 36 /* Mutex to synchronize bnxt_ulp_session_list operations. */ 37 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER; 38 39 /* Spin lock to protect context global list */ 40 uint32_t bnxt_ulp_ctxt_lock_created; 41 rte_spinlock_t bnxt_ulp_ctxt_lock; 42 TAILQ_HEAD(cntx_list_entry_list, ulp_context_list_entry); 43 static struct cntx_list_entry_list ulp_cntx_list = 44 TAILQ_HEAD_INITIALIZER(ulp_cntx_list); 45 46 /* Static function declarations */ 47 static int32_t bnxt_ulp_cntxt_list_init(void); 48 static int32_t bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx); 49 static void bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx); 50 51 /* 52 * Allow the deletion of context only for the bnxt device that 53 * created the session. 54 */ 55 bool 56 ulp_ctx_deinit_allowed(struct bnxt_ulp_context *ulp_ctx) 57 { 58 if (!ulp_ctx || !ulp_ctx->cfg_data) 59 return false; 60 61 if (!ulp_ctx->cfg_data->ref_cnt) { 62 BNXT_TF_DBG(DEBUG, "ulp ctx shall initiate deinit\n"); 63 return true; 64 } 65 66 return false; 67 } 68 69 static int32_t 70 bnxt_ulp_devid_get(struct bnxt *bp, 71 enum bnxt_ulp_device_id *ulp_dev_id) 72 { 73 if (BNXT_CHIP_P5(bp)) { 74 *ulp_dev_id = BNXT_ULP_DEVICE_ID_THOR; 75 return 0; 76 } 77 78 if (BNXT_STINGRAY(bp)) 79 *ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY; 80 else 81 /* Assuming P4 */ 82 *ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS; 83 84 return 0; 85 } 86 87 struct bnxt_ulp_app_capabilities_info * 88 bnxt_ulp_app_cap_list_get(uint32_t *num_entries) 89 { 90 if (!num_entries) 91 return NULL; 92 *num_entries = BNXT_ULP_APP_CAP_TBL_MAX_SZ; 93 return ulp_app_cap_info_list; 94 } 95 96 struct bnxt_ulp_shared_act_info * 97 bnxt_ulp_shared_act_info_get(uint32_t *num_entries) 98 { 99 if (!num_entries) 100 return NULL; 101 102 *num_entries = BNXT_ULP_GEN_TBL_MAX_SZ; 103 104 return ulp_shared_act_info; 105 } 106 107 static struct bnxt_ulp_resource_resv_info * 108 bnxt_ulp_app_resource_resv_list_get(uint32_t *num_entries) 109 { 110 if (num_entries == NULL) 111 return NULL; 112 *num_entries = BNXT_ULP_APP_RESOURCE_RESV_LIST_MAX_SZ; 113 return ulp_app_resource_resv_list; 114 } 115 116 struct bnxt_ulp_resource_resv_info * 117 bnxt_ulp_resource_resv_list_get(uint32_t *num_entries) 118 { 119 if (!num_entries) 120 return NULL; 121 *num_entries = BNXT_ULP_RESOURCE_RESV_LIST_MAX_SZ; 122 return ulp_resource_resv_list; 123 } 124 125 struct bnxt_ulp_glb_resource_info * 126 bnxt_ulp_app_glb_resource_info_list_get(uint32_t *num_entries) 127 { 128 if (!num_entries) 129 return NULL; 130 *num_entries = BNXT_ULP_APP_GLB_RESOURCE_TBL_MAX_SZ; 131 return ulp_app_glb_resource_tbl; 132 } 133 134 static int32_t 135 bnxt_ulp_named_resources_calc(struct bnxt_ulp_context *ulp_ctx, 136 struct bnxt_ulp_glb_resource_info *info, 137 uint32_t num, 138 enum bnxt_ulp_session_type stype, 139 struct tf_session_resources *res) 140 { 141 uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST, res_type, i; 142 enum tf_dir dir; 143 uint8_t app_id; 144 int32_t rc = 0; 145 146 if (ulp_ctx == NULL || info == NULL || res == NULL || num == 0) { 147 BNXT_TF_DBG(ERR, "Invalid parms to named resources calc.\n"); 148 return -EINVAL; 149 } 150 151 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 152 if (rc) { 153 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 154 return -EINVAL; 155 } 156 157 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 158 if (rc) { 159 BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n"); 160 return -EINVAL; 161 } 162 163 for (i = 0; i < num; i++) { 164 if (dev_id != info[i].device_id || app_id != info[i].app_id) 165 continue; 166 /* check to see if the session type matches only then include */ 167 if ((stype || info[i].session_type) && 168 !(info[i].session_type & stype)) 169 continue; 170 171 dir = info[i].direction; 172 res_type = info[i].resource_type; 173 174 switch (info[i].resource_func) { 175 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 176 res->ident_cnt[dir].cnt[res_type]++; 177 break; 178 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 179 res->tbl_cnt[dir].cnt[res_type]++; 180 break; 181 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 182 res->tcam_cnt[dir].cnt[res_type]++; 183 break; 184 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 185 res->em_cnt[dir].cnt[res_type]++; 186 break; 187 default: 188 BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n,", 189 info[i].resource_func); 190 continue; 191 } 192 } 193 194 return 0; 195 } 196 197 static int32_t 198 bnxt_ulp_unnamed_resources_calc(struct bnxt_ulp_context *ulp_ctx, 199 struct bnxt_ulp_resource_resv_info *info, 200 uint32_t num, 201 enum bnxt_ulp_session_type stype, 202 struct tf_session_resources *res) 203 { 204 uint32_t dev_id, res_type, i; 205 enum tf_dir dir; 206 uint8_t app_id; 207 int32_t rc = 0; 208 209 if (ulp_ctx == NULL || res == NULL || info == NULL || num == 0) { 210 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n"); 211 return -EINVAL; 212 } 213 214 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 215 if (rc) { 216 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 217 return -EINVAL; 218 } 219 220 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 221 if (rc) { 222 BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n"); 223 return -EINVAL; 224 } 225 226 for (i = 0; i < num; i++) { 227 if (app_id != info[i].app_id || dev_id != info[i].device_id) 228 continue; 229 230 /* check to see if the session type matches only then include */ 231 if ((stype || info[i].session_type) && 232 !(info[i].session_type & stype)) 233 continue; 234 235 dir = info[i].direction; 236 res_type = info[i].resource_type; 237 238 switch (info[i].resource_func) { 239 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 240 res->ident_cnt[dir].cnt[res_type] = info[i].count; 241 break; 242 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 243 res->tbl_cnt[dir].cnt[res_type] = info[i].count; 244 break; 245 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 246 res->tcam_cnt[dir].cnt[res_type] = info[i].count; 247 break; 248 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 249 res->em_cnt[dir].cnt[res_type] = info[i].count; 250 break; 251 default: 252 break; 253 } 254 } 255 return 0; 256 } 257 258 static int32_t 259 bnxt_ulp_tf_resources_get(struct bnxt_ulp_context *ulp_ctx, 260 enum bnxt_ulp_session_type stype, 261 struct tf_session_resources *res) 262 { 263 struct bnxt_ulp_resource_resv_info *unnamed = NULL; 264 uint32_t unum; 265 int32_t rc = 0; 266 267 if (ulp_ctx == NULL || res == NULL) { 268 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n"); 269 return -EINVAL; 270 } 271 272 /* use DEFAULT_NON_HA instead of DEFAULT resources if HA is disabled */ 273 if (ULP_APP_HA_IS_DYNAMIC(ulp_ctx)) 274 stype = ulp_ctx->cfg_data->def_session_type; 275 276 unnamed = bnxt_ulp_resource_resv_list_get(&unum); 277 if (unnamed == NULL) { 278 BNXT_TF_DBG(ERR, "Unable to get resource resv list.\n"); 279 return -EINVAL; 280 } 281 282 rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, stype, 283 res); 284 if (rc) 285 BNXT_TF_DBG(ERR, "Unable to calc resources for session.\n"); 286 287 return rc; 288 } 289 290 static int32_t 291 bnxt_ulp_tf_shared_session_resources_get(struct bnxt_ulp_context *ulp_ctx, 292 enum bnxt_ulp_session_type stype, 293 struct tf_session_resources *res) 294 { 295 struct bnxt_ulp_resource_resv_info *unnamed; 296 struct bnxt_ulp_glb_resource_info *named; 297 uint32_t unum, nnum; 298 int32_t rc; 299 300 if (ulp_ctx == NULL || res == NULL) { 301 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n"); 302 return -EINVAL; 303 } 304 305 /* Make sure the resources are zero before accumulating. */ 306 memset(res, 0, sizeof(struct tf_session_resources)); 307 308 if (bnxt_ulp_cntxt_ha_enabled(ulp_ctx) && 309 stype == BNXT_ULP_SESSION_TYPE_SHARED) 310 stype = ulp_ctx->cfg_data->hu_session_type; 311 312 /* 313 * Shared resources are comprised of both named and unnamed resources. 314 * First get the unnamed counts, and then add the named to the result. 315 */ 316 /* Get the baseline counts */ 317 unnamed = bnxt_ulp_app_resource_resv_list_get(&unum); 318 if (unnamed == NULL) { 319 BNXT_TF_DBG(ERR, "Unable to get shared resource resv list.\n"); 320 return -EINVAL; 321 } 322 rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, stype, 323 res); 324 if (rc) { 325 BNXT_TF_DBG(ERR, 326 "Unable to calc resources for shared session.\n"); 327 return -EINVAL; 328 } 329 330 /* Get the named list and add the totals */ 331 named = bnxt_ulp_app_glb_resource_info_list_get(&nnum); 332 if (named == NULL) { 333 BNXT_TF_DBG(ERR, "Unable to get app global resource list\n"); 334 return -EINVAL; 335 } 336 rc = bnxt_ulp_named_resources_calc(ulp_ctx, named, nnum, stype, res); 337 if (rc) 338 BNXT_TF_DBG(ERR, "Unable to calc named resources\n"); 339 340 return rc; 341 } 342 343 /* Function to set the hot upgrade support into the context */ 344 static int 345 bnxt_ulp_multi_shared_session_support_set(struct bnxt *bp, 346 enum bnxt_ulp_device_id devid, 347 uint32_t fw_hu_update) 348 { 349 struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx; 350 struct tf_get_version_parms v_params = { 0 }; 351 struct tf *tfp; 352 int32_t rc = 0; 353 int32_t new_fw = 0; 354 355 v_params.device_type = bnxt_ulp_cntxt_convert_dev_id(devid); 356 v_params.bp = bp; 357 358 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 359 rc = tf_get_version(tfp, &v_params); 360 if (rc) { 361 BNXT_TF_DBG(ERR, "Unable to get tf version.\n"); 362 return rc; 363 } 364 365 if (v_params.major == 1 && v_params.minor == 0 && 366 v_params.update == 1) { 367 new_fw = 1; 368 } 369 /* if the version update is greater than 0 then set support for 370 * multiple version 371 */ 372 if (new_fw) { 373 ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_MULTI_SHARED_SUPPORT; 374 ulp_ctx->cfg_data->hu_session_type = 375 BNXT_ULP_SESSION_TYPE_SHARED; 376 } 377 if (!new_fw && fw_hu_update) { 378 ulp_ctx->cfg_data->ulp_flags &= ~BNXT_ULP_HIGH_AVAIL_ENABLED; 379 ulp_ctx->cfg_data->hu_session_type = 380 BNXT_ULP_SESSION_TYPE_SHARED | 381 BNXT_ULP_SESSION_TYPE_SHARED_OWC; 382 } 383 384 if (!new_fw && !fw_hu_update) { 385 ulp_ctx->cfg_data->hu_session_type = 386 BNXT_ULP_SESSION_TYPE_SHARED | 387 BNXT_ULP_SESSION_TYPE_SHARED_OWC; 388 } 389 390 return rc; 391 } 392 393 int32_t 394 bnxt_ulp_cntxt_app_caps_init(struct bnxt *bp, 395 uint8_t app_id, uint32_t dev_id) 396 { 397 struct bnxt_ulp_app_capabilities_info *info; 398 uint32_t num = 0, fw = 0; 399 uint16_t i; 400 bool found = false; 401 struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx; 402 403 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(ulp_ctx->cfg_data->ulp_flags)) { 404 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 405 app_id, dev_id); 406 return -EINVAL; 407 } 408 409 info = bnxt_ulp_app_cap_list_get(&num); 410 if (!info || !num) { 411 BNXT_TF_DBG(ERR, "Failed to get app capabilities.\n"); 412 return -EINVAL; 413 } 414 415 for (i = 0; i < num; i++) { 416 if (info[i].app_id != app_id || info[i].device_id != dev_id) 417 continue; 418 found = true; 419 if (info[i].flags & BNXT_ULP_APP_CAP_SHARED_EN) 420 ulp_ctx->cfg_data->ulp_flags |= 421 BNXT_ULP_SHARED_SESSION_ENABLED; 422 if (info[i].flags & BNXT_ULP_APP_CAP_HOT_UPGRADE_EN) 423 ulp_ctx->cfg_data->ulp_flags |= 424 BNXT_ULP_HIGH_AVAIL_ENABLED; 425 if (info[i].flags & BNXT_ULP_APP_CAP_UNICAST_ONLY) 426 ulp_ctx->cfg_data->ulp_flags |= 427 BNXT_ULP_APP_UNICAST_ONLY; 428 if (info[i].flags & BNXT_ULP_APP_CAP_IP_TOS_PROTO_SUPPORT) 429 ulp_ctx->cfg_data->ulp_flags |= 430 BNXT_ULP_APP_TOS_PROTO_SUPPORT; 431 if (info[i].flags & BNXT_ULP_APP_CAP_BC_MC_SUPPORT) 432 ulp_ctx->cfg_data->ulp_flags |= 433 BNXT_ULP_APP_BC_MC_SUPPORT; 434 if (info[i].flags & BNXT_ULP_APP_CAP_SOCKET_DIRECT) { 435 /* Enable socket direction only if MR is enabled in fw*/ 436 if (BNXT_MULTIROOT_EN(bp)) { 437 ulp_ctx->cfg_data->ulp_flags |= 438 BNXT_ULP_APP_SOCKET_DIRECT; 439 BNXT_TF_DBG(INFO, 440 "Socket Direct feature is enabled\n"); 441 } 442 } 443 if (info[i].flags & BNXT_ULP_APP_CAP_HA_DYNAMIC) { 444 /* Read the environment variable to determine hot up */ 445 if (!bnxt_pmd_get_hot_upgrade_env()) { 446 ulp_ctx->cfg_data->ulp_flags |= 447 BNXT_ULP_APP_HA_DYNAMIC; 448 /* reset Hot upgrade, dynamically disabled */ 449 ulp_ctx->cfg_data->ulp_flags &= 450 ~BNXT_ULP_HIGH_AVAIL_ENABLED; 451 ulp_ctx->cfg_data->def_session_type = 452 BNXT_ULP_SESSION_TYPE_DEFAULT_NON_HA; 453 BNXT_TF_DBG(INFO, "Hot upgrade disabled.\n"); 454 } 455 } 456 457 bnxt_ulp_vxlan_ip_port_set(ulp_ctx, info[i].vxlan_ip_port); 458 bnxt_ulp_vxlan_port_set(ulp_ctx, info[i].vxlan_port); 459 bnxt_ulp_ecpri_udp_port_set(ulp_ctx, info[i].ecpri_udp_port); 460 461 /* set the shared session support from firmware */ 462 fw = info[i].upgrade_fw_update; 463 if (ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags) && 464 bnxt_ulp_multi_shared_session_support_set(bp, dev_id, fw)) { 465 BNXT_TF_DBG(ERR, 466 "Unable to get shared session support\n"); 467 return -EINVAL; 468 } 469 bnxt_ulp_ha_reg_set(ulp_ctx, info[i].ha_reg_state, 470 info[i].ha_reg_cnt); 471 ulp_ctx->cfg_data->ha_pool_id = info[i].ha_pool_id; 472 } 473 if (!found) { 474 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 475 app_id, dev_id); 476 ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_APP_DEV_UNSUPPORTED; 477 return -EINVAL; 478 } 479 480 return 0; 481 } 482 483 /* Function to retrieve the vxlan_ip (ecpri) port from the context. */ 484 int 485 bnxt_ulp_ecpri_udp_port_set(struct bnxt_ulp_context *ulp_ctx, 486 uint32_t ecpri_udp_port) 487 { 488 if (!ulp_ctx || !ulp_ctx->cfg_data) 489 return -EINVAL; 490 491 ulp_ctx->cfg_data->ecpri_udp_port = ecpri_udp_port; 492 493 return 0; 494 } 495 496 /* Function to retrieve the vxlan_ip (ecpri) port from the context. */ 497 unsigned int 498 bnxt_ulp_ecpri_udp_port_get(struct bnxt_ulp_context *ulp_ctx) 499 { 500 if (!ulp_ctx || !ulp_ctx->cfg_data) 501 return 0; 502 503 return (unsigned int)ulp_ctx->cfg_data->ecpri_udp_port; 504 } 505 506 /* Function to set the number for vxlan_ip (custom vxlan) port into the context */ 507 int 508 bnxt_ulp_vxlan_ip_port_set(struct bnxt_ulp_context *ulp_ctx, 509 uint32_t vxlan_ip_port) 510 { 511 if (!ulp_ctx || !ulp_ctx->cfg_data) 512 return -EINVAL; 513 514 ulp_ctx->cfg_data->vxlan_ip_port = vxlan_ip_port; 515 516 return 0; 517 } 518 519 /* Function to retrieve the vxlan_ip (custom vxlan) port from the context. */ 520 unsigned int 521 bnxt_ulp_vxlan_ip_port_get(struct bnxt_ulp_context *ulp_ctx) 522 { 523 if (!ulp_ctx || !ulp_ctx->cfg_data) 524 return 0; 525 526 return (unsigned int)ulp_ctx->cfg_data->vxlan_ip_port; 527 } 528 529 /* Function to set the number for vxlan port into the context */ 530 int 531 bnxt_ulp_vxlan_port_set(struct bnxt_ulp_context *ulp_ctx, 532 uint32_t vxlan_port) 533 { 534 if (!ulp_ctx || !ulp_ctx->cfg_data) 535 return -EINVAL; 536 537 ulp_ctx->cfg_data->vxlan_port = vxlan_port; 538 539 return 0; 540 } 541 542 /* Function to retrieve the vxlan port from the context. */ 543 unsigned int 544 bnxt_ulp_vxlan_port_get(struct bnxt_ulp_context *ulp_ctx) 545 { 546 if (!ulp_ctx || !ulp_ctx->cfg_data) 547 return 0; 548 549 return (unsigned int)ulp_ctx->cfg_data->vxlan_port; 550 } 551 552 static inline uint32_t 553 bnxt_ulp_session_idx_get(enum bnxt_ulp_session_type session_type) { 554 if (session_type & BNXT_ULP_SESSION_TYPE_SHARED) 555 return 1; 556 else if (session_type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 557 return 2; 558 return 0; 559 } 560 561 /* Function to set the tfp session details in session */ 562 static int32_t 563 bnxt_ulp_session_tfp_set(struct bnxt_ulp_session_state *session, 564 enum bnxt_ulp_session_type session_type, 565 struct tf *tfp) 566 { 567 uint32_t idx = bnxt_ulp_session_idx_get(session_type); 568 int32_t rc = 0; 569 570 if (!session->session_opened[idx]) { 571 session->g_tfp[idx] = rte_zmalloc("bnxt_ulp_session_tfp", 572 sizeof(struct tf), 0); 573 if (!session->g_tfp[idx]) { 574 BNXT_TF_DBG(DEBUG, "Failed to alloc session tfp\n"); 575 return -ENOMEM; 576 } 577 session->g_tfp[idx]->session = tfp->session; 578 session->session_opened[idx] = 1; 579 } 580 return rc; 581 } 582 583 /* Function to get the tfp session details in session */ 584 static struct tf_session_info * 585 bnxt_ulp_session_tfp_get(struct bnxt_ulp_session_state *session, 586 enum bnxt_ulp_session_type session_type) 587 { 588 uint32_t idx = bnxt_ulp_session_idx_get(session_type); 589 590 if (session->session_opened[idx]) 591 return session->g_tfp[idx]->session; 592 return NULL; 593 } 594 595 static uint32_t 596 bnxt_ulp_session_is_open(struct bnxt_ulp_session_state *session, 597 enum bnxt_ulp_session_type session_type) 598 { 599 uint32_t idx = bnxt_ulp_session_idx_get(session_type); 600 601 return session->session_opened[idx]; 602 } 603 604 /* Function to reset the tfp session details in session */ 605 static void 606 bnxt_ulp_session_tfp_reset(struct bnxt_ulp_session_state *session, 607 enum bnxt_ulp_session_type session_type) 608 { 609 uint32_t idx = bnxt_ulp_session_idx_get(session_type); 610 611 if (session->session_opened[idx]) { 612 session->session_opened[idx] = 0; 613 rte_free(session->g_tfp[idx]); 614 session->g_tfp[idx] = NULL; 615 } 616 } 617 618 static void 619 ulp_ctx_shared_session_close(struct bnxt *bp, 620 enum bnxt_ulp_session_type session_type, 621 struct bnxt_ulp_session_state *session) 622 { 623 struct tf *tfp; 624 int32_t rc; 625 626 tfp = bnxt_ulp_cntxt_tfp_get(bp->ulp_ctx, session_type); 627 if (!tfp) { 628 /* 629 * Log it under debug since this is likely a case of the 630 * shared session not being created. For example, a failed 631 * initialization. 632 */ 633 BNXT_TF_DBG(DEBUG, "Failed to get shared tfp on close.\n"); 634 return; 635 } 636 rc = tf_close_session(tfp); 637 if (rc) 638 BNXT_TF_DBG(ERR, "Failed to close the shared session rc=%d.\n", 639 rc); 640 (void)bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session_type, NULL); 641 bnxt_ulp_session_tfp_reset(session, session_type); 642 } 643 644 static int32_t 645 ulp_ctx_mh_get_session_name(struct bnxt *bp, 646 struct tf_open_session_parms *parms) 647 { 648 int32_t rc = 0; 649 unsigned int domain = 0, bus = 0, slot = 0, device = 0; 650 rc = sscanf(parms->ctrl_chan_name, 651 "%x:%x:%x.%u", 652 &domain, 653 &bus, 654 &slot, 655 &device); 656 if (rc != 4) { 657 /* PCI Domain not provided (optional in DPDK), thus we 658 * force domain to 0 and recheck. 659 */ 660 domain = 0; 661 /* Check parsing of bus/slot/device */ 662 rc = sscanf(parms->ctrl_chan_name, 663 "%x:%x.%u", 664 &bus, 665 &slot, 666 &device); 667 if (rc != 3) { 668 BNXT_TF_DBG(DEBUG, 669 "Failed to scan device ctrl_chan_name\n"); 670 return -EINVAL; 671 } 672 } 673 674 /* change domain name for multi-host system */ 675 domain = domain + (0xf & bp->multi_host_pf_pci_id); 676 sprintf(parms->ctrl_chan_name, 677 "%x:%x:%x.%u", 678 domain, 679 bus, 680 slot, 681 device); 682 BNXT_TF_DBG(DEBUG, 683 "Session name for Multi-Host: ctrl_chan_name:%s\n", parms->ctrl_chan_name); 684 return 0; 685 } 686 687 static int32_t 688 ulp_ctx_shared_session_open(struct bnxt *bp, 689 enum bnxt_ulp_session_type session_type, 690 struct bnxt_ulp_session_state *session) 691 { 692 struct rte_eth_dev *ethdev = bp->eth_dev; 693 struct tf_session_resources *resources; 694 struct tf_open_session_parms parms; 695 size_t nb; 696 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 697 int32_t rc = 0; 698 uint8_t app_id; 699 struct tf *tfp; 700 uint8_t pool_id; 701 702 memset(&parms, 0, sizeof(parms)); 703 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 704 parms.ctrl_chan_name); 705 if (rc) { 706 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n", 707 ethdev->data->port_id, rc); 708 return rc; 709 } 710 711 /* On multi-host system, adjust ctrl_chan_name to avoid confliction */ 712 if (BNXT_MH(bp)) { 713 rc = ulp_ctx_mh_get_session_name(bp, &parms); 714 if (rc) 715 return rc; 716 } 717 718 resources = &parms.resources; 719 720 /* 721 * Need to account for size of ctrl_chan_name and 1 extra for Null 722 * terminator 723 */ 724 nb = sizeof(parms.ctrl_chan_name) - strlen(parms.ctrl_chan_name) - 1; 725 726 /* 727 * Build the ctrl_chan_name with shared token. 728 * When HA is enabled, the WC TCAM needs extra management by the core, 729 * so add the wc_tcam string to the control channel. 730 */ 731 pool_id = bp->ulp_ctx->cfg_data->ha_pool_id; 732 if (!bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 733 if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) 734 strncat(parms.ctrl_chan_name, "-tf_shared-wc_tcam", nb); 735 else 736 strncat(parms.ctrl_chan_name, "-tf_shared", nb); 737 } else if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 738 if (session_type == BNXT_ULP_SESSION_TYPE_SHARED) { 739 strncat(parms.ctrl_chan_name, "-tf_shared", nb); 740 } else if (session_type == BNXT_ULP_SESSION_TYPE_SHARED_WC) { 741 char session_pool_name[64]; 742 743 sprintf(session_pool_name, "-tf_shared-pool%d", 744 pool_id); 745 746 if (nb >= strlen(session_pool_name)) { 747 strncat(parms.ctrl_chan_name, session_pool_name, nb); 748 } else { 749 BNXT_TF_DBG(ERR, "No space left for session_name\n"); 750 return -EINVAL; 751 } 752 } 753 } 754 755 rc = bnxt_ulp_tf_shared_session_resources_get(bp->ulp_ctx, session_type, 756 resources); 757 if (rc) 758 return rc; 759 760 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 761 if (rc) { 762 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 763 return -EINVAL; 764 } 765 766 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 767 if (rc) { 768 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n"); 769 return rc; 770 } 771 772 tfp = bnxt_ulp_bp_tfp_get(bp, session_type); 773 parms.device_type = bnxt_ulp_cntxt_convert_dev_id(ulp_dev_id); 774 parms.bp = bp; 775 776 /* 777 * Open the session here, but the collect the resources during the 778 * mapper initialization. 779 */ 780 rc = tf_open_session(tfp, &parms); 781 if (rc) 782 return rc; 783 784 if (parms.shared_session_creator) 785 BNXT_TF_DBG(DEBUG, "Shared session creator.\n"); 786 else 787 BNXT_TF_DBG(DEBUG, "Shared session attached.\n"); 788 789 /* Save the shared session in global data */ 790 rc = bnxt_ulp_session_tfp_set(session, session_type, tfp); 791 if (rc) { 792 BNXT_TF_DBG(ERR, "Failed to add shared tfp to session\n"); 793 return rc; 794 } 795 796 rc = bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session_type, tfp); 797 if (rc) { 798 BNXT_TF_DBG(ERR, "Failed to add shared tfp to ulp (%d)\n", rc); 799 return rc; 800 } 801 802 return rc; 803 } 804 805 static int32_t 806 ulp_ctx_shared_session_attach(struct bnxt *bp, 807 struct bnxt_ulp_session_state *ses) 808 { 809 enum bnxt_ulp_session_type type; 810 struct tf *tfp; 811 int32_t rc = 0; 812 813 /* Simply return success if shared session not enabled */ 814 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 815 type = BNXT_ULP_SESSION_TYPE_SHARED; 816 tfp = bnxt_ulp_bp_tfp_get(bp, type); 817 tfp->session = bnxt_ulp_session_tfp_get(ses, type); 818 rc = ulp_ctx_shared_session_open(bp, type, ses); 819 } 820 821 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 822 type = BNXT_ULP_SESSION_TYPE_SHARED_WC; 823 tfp = bnxt_ulp_bp_tfp_get(bp, type); 824 tfp->session = bnxt_ulp_session_tfp_get(ses, type); 825 rc = ulp_ctx_shared_session_open(bp, type, ses); 826 } 827 828 if (!rc) 829 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, true); 830 831 return rc; 832 } 833 834 static void 835 ulp_ctx_shared_session_detach(struct bnxt *bp) 836 { 837 struct tf *tfp; 838 839 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 840 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_SHARED); 841 if (tfp->session) { 842 tf_close_session(tfp); 843 tfp->session = NULL; 844 } 845 } 846 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 847 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_SHARED_WC); 848 if (tfp->session) { 849 tf_close_session(tfp); 850 tfp->session = NULL; 851 } 852 } 853 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, false); 854 } 855 856 /* 857 * Initialize an ULP session. 858 * An ULP session will contain all the resources needed to support rte flow 859 * offloads. A session is initialized as part of rte_eth_device start. 860 * A single vswitch instance can have multiple uplinks which means 861 * rte_eth_device start will be called for each of these devices. 862 * ULP session manager will make sure that a single ULP session is only 863 * initialized once. Apart from this, it also initializes MARK database, 864 * EEM table & flow database. ULP session manager also manages a list of 865 * all opened ULP sessions. 866 */ 867 static int32_t 868 ulp_ctx_session_open(struct bnxt *bp, 869 struct bnxt_ulp_session_state *session) 870 { 871 struct rte_eth_dev *ethdev = bp->eth_dev; 872 int32_t rc = 0; 873 struct tf_open_session_parms params; 874 struct tf_session_resources *resources; 875 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 876 uint8_t app_id; 877 struct tf *tfp; 878 879 memset(¶ms, 0, sizeof(params)); 880 881 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 882 params.ctrl_chan_name); 883 if (rc) { 884 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n", 885 ethdev->data->port_id, rc); 886 return rc; 887 } 888 889 /* On multi-host system, adjust ctrl_chan_name to avoid confliction */ 890 if (BNXT_MH(bp)) { 891 rc = ulp_ctx_mh_get_session_name(bp, ¶ms); 892 if (rc) 893 return rc; 894 } 895 896 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 897 if (rc) { 898 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 899 return -EINVAL; 900 } 901 902 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 903 if (rc) { 904 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n"); 905 return rc; 906 } 907 908 params.device_type = bnxt_ulp_cntxt_convert_dev_id(ulp_dev_id); 909 resources = ¶ms.resources; 910 rc = bnxt_ulp_tf_resources_get(bp->ulp_ctx, 911 BNXT_ULP_SESSION_TYPE_DEFAULT, 912 resources); 913 if (rc) 914 return rc; 915 916 params.bp = bp; 917 918 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 919 rc = tf_open_session(tfp, ¶ms); 920 if (rc) { 921 BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n", 922 params.ctrl_chan_name, rc); 923 return -EINVAL; 924 } 925 rc = bnxt_ulp_session_tfp_set(session, 926 BNXT_ULP_SESSION_TYPE_DEFAULT, tfp); 927 if (rc) { 928 BNXT_TF_DBG(ERR, "Failed to set TF session - %s, rc = %d\n", 929 params.ctrl_chan_name, rc); 930 return -EINVAL; 931 } 932 return rc; 933 } 934 935 /* 936 * Close the ULP session. 937 * It takes the ulp context pointer. 938 */ 939 static void 940 ulp_ctx_session_close(struct bnxt *bp, 941 struct bnxt_ulp_session_state *session) 942 { 943 struct tf *tfp; 944 945 /* close the session in the hardware */ 946 if (bnxt_ulp_session_is_open(session, BNXT_ULP_SESSION_TYPE_DEFAULT)) { 947 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 948 tf_close_session(tfp); 949 } 950 bnxt_ulp_session_tfp_reset(session, BNXT_ULP_SESSION_TYPE_DEFAULT); 951 } 952 953 static void 954 bnxt_init_tbl_scope_parms(struct bnxt *bp, 955 struct tf_alloc_tbl_scope_parms *params) 956 { 957 struct bnxt_ulp_device_params *dparms; 958 uint32_t dev_id; 959 int rc; 960 961 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 962 if (rc) 963 /* TBD: For now, just use default. */ 964 dparms = 0; 965 else 966 dparms = bnxt_ulp_device_params_get(dev_id); 967 968 /* 969 * Set the flush timer for EEM entries. The value is in 100ms intervals, 970 * so 100 is 10s. 971 */ 972 params->hw_flow_cache_flush_timer = 100; 973 974 if (!dparms) { 975 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 976 params->rx_max_action_entry_sz_in_bits = 977 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 978 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 979 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS; 980 981 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 982 params->tx_max_action_entry_sz_in_bits = 983 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 984 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 985 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS; 986 } else { 987 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 988 params->rx_max_action_entry_sz_in_bits = 989 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 990 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 991 params->rx_num_flows_in_k = 992 dparms->ext_flow_db_num_entries / 1024; 993 994 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 995 params->tx_max_action_entry_sz_in_bits = 996 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 997 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 998 params->tx_num_flows_in_k = 999 dparms->ext_flow_db_num_entries / 1024; 1000 } 1001 BNXT_TF_DBG(INFO, "Table Scope initialized with %uK flows.\n", 1002 params->rx_num_flows_in_k); 1003 } 1004 1005 /* Initialize Extended Exact Match host memory. */ 1006 static int32_t 1007 ulp_eem_tbl_scope_init(struct bnxt *bp) 1008 { 1009 struct tf_alloc_tbl_scope_parms params = {0}; 1010 struct bnxt_ulp_device_params *dparms; 1011 enum bnxt_ulp_flow_mem_type mtype; 1012 uint32_t dev_id; 1013 struct tf *tfp; 1014 int rc; 1015 1016 /* Get the dev specific number of flows that needed to be supported. */ 1017 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 1018 BNXT_TF_DBG(ERR, "Invalid device id\n"); 1019 return -EINVAL; 1020 } 1021 1022 dparms = bnxt_ulp_device_params_get(dev_id); 1023 if (!dparms) { 1024 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 1025 return -ENODEV; 1026 } 1027 1028 if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype)) 1029 return -EINVAL; 1030 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 1031 BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n"); 1032 return 0; 1033 } 1034 1035 bnxt_init_tbl_scope_parms(bp, ¶ms); 1036 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1037 rc = tf_alloc_tbl_scope(tfp, ¶ms); 1038 if (rc) { 1039 BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n", 1040 rc); 1041 return rc; 1042 } 1043 1044 rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id); 1045 if (rc) { 1046 BNXT_TF_DBG(ERR, "Unable to set table scope id\n"); 1047 return rc; 1048 } 1049 1050 return 0; 1051 } 1052 1053 /* Free Extended Exact Match host memory */ 1054 static int32_t 1055 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 1056 { 1057 struct tf_free_tbl_scope_parms params = {0}; 1058 struct tf *tfp; 1059 int32_t rc = 0; 1060 struct bnxt_ulp_device_params *dparms; 1061 enum bnxt_ulp_flow_mem_type mtype; 1062 uint32_t dev_id; 1063 1064 if (!ulp_ctx || !ulp_ctx->cfg_data) 1065 return -EINVAL; 1066 1067 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT); 1068 if (!tfp) { 1069 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n"); 1070 return -EINVAL; 1071 } 1072 1073 /* Get the dev specific number of flows that needed to be supported. */ 1074 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 1075 BNXT_TF_DBG(ERR, "Invalid device id\n"); 1076 return -EINVAL; 1077 } 1078 1079 dparms = bnxt_ulp_device_params_get(dev_id); 1080 if (!dparms) { 1081 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 1082 return -ENODEV; 1083 } 1084 1085 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype)) 1086 return -EINVAL; 1087 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 1088 BNXT_TF_DBG(INFO, "Table Scope free is not required\n"); 1089 return 0; 1090 } 1091 1092 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, ¶ms.tbl_scope_id); 1093 if (rc) { 1094 BNXT_TF_DBG(ERR, "Failed to get the table scope id\n"); 1095 return -EINVAL; 1096 } 1097 1098 rc = tf_free_tbl_scope(tfp, ¶ms); 1099 if (rc) { 1100 BNXT_TF_DBG(ERR, "Unable to free table scope\n"); 1101 return -EINVAL; 1102 } 1103 return rc; 1104 } 1105 1106 /* The function to free and deinit the ulp context data. */ 1107 static int32_t 1108 ulp_ctx_deinit(struct bnxt *bp, 1109 struct bnxt_ulp_session_state *session) 1110 { 1111 /* close the tf session */ 1112 ulp_ctx_session_close(bp, session); 1113 1114 /* The shared session must be closed last. */ 1115 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) 1116 ulp_ctx_shared_session_close(bp, BNXT_ULP_SESSION_TYPE_SHARED, 1117 session); 1118 1119 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) 1120 ulp_ctx_shared_session_close(bp, 1121 BNXT_ULP_SESSION_TYPE_SHARED_WC, 1122 session); 1123 1124 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, false); 1125 1126 /* Free the contents */ 1127 if (session->cfg_data) { 1128 rte_free(session->cfg_data); 1129 bp->ulp_ctx->cfg_data = NULL; 1130 session->cfg_data = NULL; 1131 } 1132 return 0; 1133 } 1134 1135 /* The function to allocate and initialize the ulp context data. */ 1136 static int32_t 1137 ulp_ctx_init(struct bnxt *bp, 1138 struct bnxt_ulp_session_state *session) 1139 { 1140 struct bnxt_ulp_data *ulp_data; 1141 int32_t rc = 0; 1142 enum bnxt_ulp_device_id devid; 1143 enum bnxt_ulp_session_type stype; 1144 struct tf *tfp; 1145 1146 /* Initialize the context entries list */ 1147 bnxt_ulp_cntxt_list_init(); 1148 1149 /* Add the context to the context entries list */ 1150 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 1151 if (rc) { 1152 BNXT_TF_DBG(ERR, "Failed to add the context list entry\n"); 1153 return -ENOMEM; 1154 } 1155 1156 /* Allocate memory to hold ulp context data. */ 1157 ulp_data = rte_zmalloc("bnxt_ulp_data", 1158 sizeof(struct bnxt_ulp_data), 0); 1159 if (!ulp_data) { 1160 BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n"); 1161 return -ENOMEM; 1162 } 1163 1164 /* Increment the ulp context data reference count usage. */ 1165 bp->ulp_ctx->cfg_data = ulp_data; 1166 session->cfg_data = ulp_data; 1167 ulp_data->ref_cnt++; 1168 ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED; 1169 1170 rc = bnxt_ulp_devid_get(bp, &devid); 1171 if (rc) { 1172 BNXT_TF_DBG(ERR, "Unable to determine device for ULP init.\n"); 1173 goto error_deinit; 1174 } 1175 1176 rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid); 1177 if (rc) { 1178 BNXT_TF_DBG(ERR, "Unable to set device for ULP init.\n"); 1179 goto error_deinit; 1180 } 1181 1182 rc = bnxt_ulp_cntxt_app_id_set(bp->ulp_ctx, bp->app_id); 1183 if (rc) { 1184 BNXT_TF_DBG(ERR, "Unable to set app_id for ULP init.\n"); 1185 goto error_deinit; 1186 } 1187 BNXT_TF_DBG(DEBUG, "Ulp initialized with app id %d\n", bp->app_id); 1188 1189 rc = bnxt_ulp_cntxt_app_caps_init(bp, bp->app_id, devid); 1190 if (rc) { 1191 BNXT_TF_DBG(ERR, "Unable to set caps for app(%x)/dev(%x)\n", 1192 bp->app_id, devid); 1193 goto error_deinit; 1194 } 1195 1196 if (BNXT_TESTPMD_EN(bp)) { 1197 ulp_data->ulp_flags &= ~BNXT_ULP_VF_REP_ENABLED; 1198 BNXT_TF_DBG(ERR, "Enabled Testpmd forward mode\n"); 1199 } 1200 1201 /* 1202 * Shared session must be created before first regular session but after 1203 * the ulp_ctx is valid. 1204 */ 1205 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 1206 rc = ulp_ctx_shared_session_open(bp, 1207 BNXT_ULP_SESSION_TYPE_SHARED, 1208 session); 1209 if (rc) { 1210 BNXT_TF_DBG(ERR, "Unable to open shared session (%d)\n", 1211 rc); 1212 goto error_deinit; 1213 } 1214 } 1215 1216 /* Multiple session support */ 1217 if (bnxt_ulp_cntxt_multi_shared_session_enabled(bp->ulp_ctx)) { 1218 stype = BNXT_ULP_SESSION_TYPE_SHARED_WC; 1219 rc = ulp_ctx_shared_session_open(bp, stype, session); 1220 if (rc) { 1221 BNXT_TF_DBG(ERR, 1222 "Unable to open shared wc session (%d)\n", 1223 rc); 1224 goto error_deinit; 1225 } 1226 } 1227 bnxt_ulp_cntxt_num_shared_clients_set(bp->ulp_ctx, true); 1228 1229 /* Open the ulp session. */ 1230 rc = ulp_ctx_session_open(bp, session); 1231 if (rc) 1232 goto error_deinit; 1233 1234 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1235 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT, tfp); 1236 return rc; 1237 1238 error_deinit: 1239 session->session_opened[BNXT_ULP_SESSION_TYPE_DEFAULT] = 1; 1240 (void)ulp_ctx_deinit(bp, session); 1241 return rc; 1242 } 1243 1244 /* The function to initialize ulp dparms with devargs */ 1245 static int32_t 1246 ulp_dparms_init(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 1247 { 1248 struct bnxt_ulp_device_params *dparms; 1249 uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST; 1250 1251 if (!bp->max_num_kflows) { 1252 /* Defaults to Internal */ 1253 bnxt_ulp_cntxt_mem_type_set(ulp_ctx, 1254 BNXT_ULP_FLOW_MEM_TYPE_INT); 1255 return 0; 1256 } 1257 1258 /* The max_num_kflows were set, so move to external */ 1259 if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT)) 1260 return -EINVAL; 1261 1262 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 1263 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 1264 return -EINVAL; 1265 } 1266 1267 dparms = bnxt_ulp_device_params_get(dev_id); 1268 if (!dparms) { 1269 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n"); 1270 return -EINVAL; 1271 } 1272 1273 /* num_flows = max_num_kflows * 1024 */ 1274 dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024; 1275 /* GFID = 2 * num_flows */ 1276 dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2; 1277 BNXT_TF_DBG(DEBUG, "Set the number of flows = %" PRIu64 "\n", 1278 dparms->ext_flow_db_num_entries); 1279 1280 return 0; 1281 } 1282 1283 /* The function to initialize bp flags with truflow features */ 1284 static int32_t 1285 ulp_dparms_dev_port_intf_update(struct bnxt *bp, 1286 struct bnxt_ulp_context *ulp_ctx) 1287 { 1288 enum bnxt_ulp_flow_mem_type mtype; 1289 1290 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype)) 1291 return -EINVAL; 1292 /* Update the bp flag with gfid flag */ 1293 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT) 1294 bp->flags |= BNXT_FLAG_GFID_ENABLE; 1295 1296 return 0; 1297 } 1298 1299 static int32_t 1300 ulp_ctx_attach(struct bnxt *bp, 1301 struct bnxt_ulp_session_state *session) 1302 { 1303 int32_t rc = 0; 1304 uint32_t flags, dev_id = BNXT_ULP_DEVICE_ID_LAST; 1305 struct tf *tfp; 1306 uint8_t app_id; 1307 1308 /* Increment the ulp context data reference count usage. */ 1309 bp->ulp_ctx->cfg_data = session->cfg_data; 1310 bp->ulp_ctx->cfg_data->ref_cnt++; 1311 1312 /* update the session details in bnxt tfp */ 1313 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1314 tfp->session = bnxt_ulp_session_tfp_get(session, 1315 BNXT_ULP_SESSION_TYPE_DEFAULT); 1316 1317 /* Add the context to the context entries list */ 1318 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 1319 if (rc) { 1320 BNXT_TF_DBG(ERR, "Failed to add the context list entry\n"); 1321 return -EINVAL; 1322 } 1323 1324 /* 1325 * The supported flag will be set during the init. Use it now to 1326 * know if we should go through the attach. 1327 */ 1328 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 1329 if (rc) { 1330 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 1331 return -EINVAL; 1332 } 1333 1334 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 1335 if (rc) { 1336 BNXT_TF_DBG(ERR, "Unable do get the dev_id.\n"); 1337 return -EINVAL; 1338 } 1339 1340 flags = bp->ulp_ctx->cfg_data->ulp_flags; 1341 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(flags)) { 1342 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 1343 app_id, dev_id); 1344 return -EINVAL; 1345 } 1346 1347 /* Create a TF Client */ 1348 rc = ulp_ctx_session_open(bp, session); 1349 if (rc) { 1350 PMD_DRV_LOG_LINE(ERR, "Failed to open ctxt session, rc:%d", rc); 1351 tfp->session = NULL; 1352 return rc; 1353 } 1354 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1355 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, BNXT_ULP_SESSION_TYPE_DEFAULT, tfp); 1356 return rc; 1357 } 1358 1359 static void 1360 ulp_ctx_detach(struct bnxt *bp) 1361 { 1362 struct tf *tfp; 1363 1364 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1365 if (tfp->session) { 1366 tf_close_session(tfp); 1367 tfp->session = NULL; 1368 } 1369 } 1370 1371 /* 1372 * Initialize the state of an ULP session. 1373 * If the state of an ULP session is not initialized, set it's state to 1374 * initialized. If the state is already initialized, do nothing. 1375 */ 1376 static void 1377 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init) 1378 { 1379 pthread_mutex_lock(&session->bnxt_ulp_mutex); 1380 1381 if (!session->bnxt_ulp_init) { 1382 session->bnxt_ulp_init = true; 1383 *init = false; 1384 } else { 1385 *init = true; 1386 } 1387 1388 pthread_mutex_unlock(&session->bnxt_ulp_mutex); 1389 } 1390 1391 /* 1392 * Check if an ULP session is already allocated for a specific PCI 1393 * domain & bus. If it is already allocated simply return the session 1394 * pointer, otherwise allocate a new session. 1395 */ 1396 static struct bnxt_ulp_session_state * 1397 ulp_get_session(struct bnxt *bp, struct rte_pci_addr *pci_addr) 1398 { 1399 struct bnxt_ulp_session_state *session; 1400 1401 /* if multi root capability is enabled, then ignore the pci bus id */ 1402 STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) { 1403 if (BNXT_MULTIROOT_EN(bp)) { 1404 if (!memcmp(bp->dsn, session->dsn, 1405 sizeof(session->dsn))) { 1406 return session; 1407 } 1408 } else if (session->pci_info.domain == pci_addr->domain && 1409 session->pci_info.bus == pci_addr->bus) { 1410 return session; 1411 } 1412 } 1413 return NULL; 1414 } 1415 1416 /* 1417 * Allocate and Initialize an ULP session and set it's state to INITIALIZED. 1418 * If it's already initialized simply return the already existing session. 1419 */ 1420 static struct bnxt_ulp_session_state * 1421 ulp_session_init(struct bnxt *bp, 1422 bool *init) 1423 { 1424 struct rte_pci_device *pci_dev; 1425 struct rte_pci_addr *pci_addr; 1426 struct bnxt_ulp_session_state *session; 1427 int rc = 0; 1428 1429 if (!bp) 1430 return NULL; 1431 1432 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 1433 pci_addr = &pci_dev->addr; 1434 1435 pthread_mutex_lock(&bnxt_ulp_global_mutex); 1436 1437 session = ulp_get_session(bp, pci_addr); 1438 if (!session) { 1439 /* Not Found the session Allocate a new one */ 1440 session = rte_zmalloc("bnxt_ulp_session", 1441 sizeof(struct bnxt_ulp_session_state), 1442 0); 1443 if (!session) { 1444 BNXT_TF_DBG(ERR, 1445 "Allocation failed for bnxt_ulp_session\n"); 1446 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1447 return NULL; 1448 1449 } else { 1450 /* Add it to the queue */ 1451 session->pci_info.domain = pci_addr->domain; 1452 session->pci_info.bus = pci_addr->bus; 1453 memcpy(session->dsn, bp->dsn, sizeof(session->dsn)); 1454 rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL); 1455 if (rc) { 1456 BNXT_TF_DBG(ERR, "mutex create failed\n"); 1457 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1458 return NULL; 1459 } 1460 STAILQ_INSERT_TAIL(&bnxt_ulp_session_list, 1461 session, next); 1462 } 1463 } 1464 ulp_context_initialized(session, init); 1465 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1466 return session; 1467 } 1468 1469 /* 1470 * When a device is closed, remove it's associated session from the global 1471 * session list. 1472 */ 1473 static void 1474 ulp_session_deinit(struct bnxt_ulp_session_state *session) 1475 { 1476 if (!session) 1477 return; 1478 1479 if (!session->cfg_data) { 1480 pthread_mutex_lock(&bnxt_ulp_global_mutex); 1481 STAILQ_REMOVE(&bnxt_ulp_session_list, session, 1482 bnxt_ulp_session_state, next); 1483 pthread_mutex_destroy(&session->bnxt_ulp_mutex); 1484 rte_free(session); 1485 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1486 } 1487 } 1488 1489 /* 1490 * Internal api to enable NAT feature. 1491 * Set set_flag to 1 to set the value or zero to reset the value. 1492 * returns 0 on success. 1493 */ 1494 static int32_t 1495 bnxt_ulp_global_cfg_update(struct bnxt *bp, 1496 enum tf_dir dir, 1497 enum tf_global_config_type type, 1498 uint32_t offset, 1499 uint32_t value, 1500 uint32_t set_flag) 1501 { 1502 uint32_t global_cfg = 0; 1503 int rc; 1504 struct tf_global_cfg_parms parms = { 0 }; 1505 struct tf *tfp; 1506 1507 /* Initialize the params */ 1508 parms.dir = dir, 1509 parms.type = type, 1510 parms.offset = offset, 1511 parms.config = (uint8_t *)&global_cfg, 1512 parms.config_sz_in_bytes = sizeof(global_cfg); 1513 1514 tfp = bnxt_ulp_bp_tfp_get(bp, BNXT_ULP_SESSION_TYPE_DEFAULT); 1515 rc = tf_get_global_cfg(tfp, &parms); 1516 if (rc) { 1517 BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n", 1518 type, rc); 1519 return rc; 1520 } 1521 1522 if (set_flag) 1523 global_cfg |= value; 1524 else 1525 global_cfg &= ~value; 1526 1527 /* SET the register RE_CFA_REG_ACT_TECT */ 1528 rc = tf_set_global_cfg(tfp, &parms); 1529 if (rc) { 1530 BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n", 1531 type, rc); 1532 return rc; 1533 } 1534 return rc; 1535 } 1536 1537 /* Internal function to delete all the flows belonging to the given port */ 1538 static void 1539 bnxt_ulp_flush_port_flows(struct bnxt *bp) 1540 { 1541 uint16_t func_id; 1542 1543 /* it is assumed that port is either TVF or PF */ 1544 if (ulp_port_db_port_func_id_get(bp->ulp_ctx, 1545 bp->eth_dev->data->port_id, 1546 &func_id)) { 1547 BNXT_TF_DBG(ERR, "Invalid argument\n"); 1548 return; 1549 } 1550 (void)ulp_flow_db_function_flow_flush(bp->ulp_ctx, func_id); 1551 } 1552 1553 /* Internal function to delete the VFR default flows */ 1554 static void 1555 bnxt_ulp_destroy_vfr_default_rules(struct bnxt *bp, bool global) 1556 { 1557 struct bnxt_ulp_vfr_rule_info *info; 1558 uint16_t port_id; 1559 struct rte_eth_dev *vfr_eth_dev; 1560 struct bnxt_representor *vfr_bp; 1561 1562 if (!BNXT_TRUFLOW_EN(bp) || rte_eth_dev_is_repr(bp->eth_dev)) 1563 return; 1564 1565 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 1566 return; 1567 1568 /* Delete default rules for all ports */ 1569 for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { 1570 info = &bp->ulp_ctx->cfg_data->vfr_rule_info[port_id]; 1571 if (!info->valid) 1572 continue; 1573 1574 if (!global && info->parent_port_id != 1575 bp->eth_dev->data->port_id) 1576 continue; 1577 1578 /* Destroy the flows */ 1579 ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id); 1580 /* Clean up the tx action pointer */ 1581 vfr_eth_dev = &rte_eth_devices[port_id]; 1582 if (vfr_eth_dev) { 1583 vfr_bp = vfr_eth_dev->data->dev_private; 1584 vfr_bp->vfr_tx_cfa_action = 0; 1585 } 1586 memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info)); 1587 } 1588 } 1589 1590 /* 1591 * When a port is deinit'ed by dpdk. This function is called 1592 * and this function clears the ULP context and rest of the 1593 * infrastructure associated with it. 1594 */ 1595 static void 1596 bnxt_ulp_deinit(struct bnxt *bp, 1597 struct bnxt_ulp_session_state *session) 1598 { 1599 bool ha_enabled; 1600 1601 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 1602 return; 1603 1604 ha_enabled = bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx); 1605 if (ha_enabled && 1606 bnxt_ulp_session_is_open(session, BNXT_ULP_SESSION_TYPE_DEFAULT)) { 1607 int32_t rc = ulp_ha_mgr_close(bp->ulp_ctx); 1608 if (rc) 1609 BNXT_TF_DBG(ERR, "Failed to close HA (%d)\n", rc); 1610 } 1611 1612 /* clean up default flows */ 1613 bnxt_ulp_destroy_df_rules(bp, true); 1614 1615 /* clean up default VFR flows */ 1616 bnxt_ulp_destroy_vfr_default_rules(bp, true); 1617 1618 /* clean up regular flows */ 1619 ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR); 1620 1621 /* cleanup the eem table scope */ 1622 ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx); 1623 1624 /* cleanup the flow database */ 1625 ulp_flow_db_deinit(bp->ulp_ctx); 1626 1627 /* Delete the Mark database */ 1628 ulp_mark_db_deinit(bp->ulp_ctx); 1629 1630 /* cleanup the ulp mapper */ 1631 ulp_mapper_deinit(bp->ulp_ctx); 1632 1633 /* Delete the Flow Counter Manager */ 1634 ulp_fc_mgr_deinit(bp->ulp_ctx); 1635 1636 /* Delete the Port database */ 1637 ulp_port_db_deinit(bp->ulp_ctx); 1638 1639 /* Disable NAT feature */ 1640 (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 1641 TF_TUNNEL_ENCAP_NAT, 1642 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 1643 1644 (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 1645 TF_TUNNEL_ENCAP_NAT, 1646 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 1647 1648 /* free the flow db lock */ 1649 pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock); 1650 1651 if (ha_enabled) 1652 ulp_ha_mgr_deinit(bp->ulp_ctx); 1653 1654 /* Delete the ulp context and tf session and free the ulp context */ 1655 ulp_ctx_deinit(bp, session); 1656 BNXT_TF_DBG(DEBUG, "ulp ctx has been deinitialized\n"); 1657 } 1658 1659 /* 1660 * When a port is initialized by dpdk. This functions is called 1661 * and this function initializes the ULP context and rest of the 1662 * infrastructure associated with it. 1663 */ 1664 static int32_t 1665 bnxt_ulp_init(struct bnxt *bp, 1666 struct bnxt_ulp_session_state *session) 1667 { 1668 int rc; 1669 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 1670 1671 /* Allocate and Initialize the ulp context. */ 1672 rc = ulp_ctx_init(bp, session); 1673 if (rc) { 1674 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n"); 1675 goto jump_to_error; 1676 } 1677 1678 rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL); 1679 if (rc) { 1680 BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n"); 1681 goto jump_to_error; 1682 } 1683 1684 /* Initialize ulp dparms with values devargs passed */ 1685 rc = ulp_dparms_init(bp, bp->ulp_ctx); 1686 if (rc) { 1687 BNXT_TF_DBG(ERR, "Failed to initialize the dparms\n"); 1688 goto jump_to_error; 1689 } 1690 1691 /* create the port database */ 1692 rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt); 1693 if (rc) { 1694 BNXT_TF_DBG(ERR, "Failed to create the port database\n"); 1695 goto jump_to_error; 1696 } 1697 1698 /* Create the Mark database. */ 1699 rc = ulp_mark_db_init(bp->ulp_ctx); 1700 if (rc) { 1701 BNXT_TF_DBG(ERR, "Failed to create the mark database\n"); 1702 goto jump_to_error; 1703 } 1704 1705 /* Create the flow database. */ 1706 rc = ulp_flow_db_init(bp->ulp_ctx); 1707 if (rc) { 1708 BNXT_TF_DBG(ERR, "Failed to create the flow database\n"); 1709 goto jump_to_error; 1710 } 1711 1712 /* Create the eem table scope. */ 1713 rc = ulp_eem_tbl_scope_init(bp); 1714 if (rc) { 1715 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n"); 1716 goto jump_to_error; 1717 } 1718 1719 rc = ulp_mapper_init(bp->ulp_ctx); 1720 if (rc) { 1721 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n"); 1722 goto jump_to_error; 1723 } 1724 1725 rc = ulp_fc_mgr_init(bp->ulp_ctx); 1726 if (rc) { 1727 BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n"); 1728 goto jump_to_error; 1729 } 1730 1731 /* 1732 * Enable NAT feature. Set the global configuration register 1733 * Tunnel encap to enable NAT with the reuse of existing inner 1734 * L2 header smac and dmac 1735 */ 1736 rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 1737 TF_TUNNEL_ENCAP_NAT, 1738 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 1739 if (rc) { 1740 BNXT_TF_DBG(ERR, "Failed to set rx global configuration\n"); 1741 goto jump_to_error; 1742 } 1743 1744 rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 1745 TF_TUNNEL_ENCAP_NAT, 1746 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 1747 if (rc) { 1748 BNXT_TF_DBG(ERR, "Failed to set tx global configuration\n"); 1749 goto jump_to_error; 1750 } 1751 1752 if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) { 1753 rc = ulp_ha_mgr_init(bp->ulp_ctx); 1754 if (rc) { 1755 BNXT_TF_DBG(ERR, "Failed to initialize HA %d\n", rc); 1756 goto jump_to_error; 1757 } 1758 rc = ulp_ha_mgr_open(bp->ulp_ctx); 1759 if (rc) { 1760 BNXT_TF_DBG(ERR, "Failed to Process HA Open %d\n", rc); 1761 goto jump_to_error; 1762 } 1763 } 1764 1765 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 1766 if (rc) { 1767 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n"); 1768 return rc; 1769 } 1770 1771 if (ulp_dev_id == BNXT_ULP_DEVICE_ID_THOR) { 1772 rc = bnxt_flow_meter_init(bp); 1773 if (rc) { 1774 BNXT_TF_DBG(ERR, "Failed to config meter\n"); 1775 goto jump_to_error; 1776 } 1777 } 1778 1779 BNXT_TF_DBG(DEBUG, "ulp ctx has been initialized\n"); 1780 return rc; 1781 1782 jump_to_error: 1783 bnxt_ulp_deinit(bp, session); 1784 return rc; 1785 } 1786 1787 static int 1788 ulp_cust_vxlan_alloc(struct bnxt *bp) 1789 { 1790 int rc = 0; 1791 1792 if (ULP_APP_CUST_VXLAN_SUPPORT(bp->ulp_ctx)) { 1793 rc = bnxt_tunnel_dst_port_alloc(bp, 1794 bp->ulp_ctx->cfg_data->vxlan_port, 1795 HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN); 1796 if (rc) 1797 BNXT_TF_DBG(ERR, "Failed to set global vxlan port\n"); 1798 } 1799 1800 if (ULP_APP_CUST_VXLAN_IP_SUPPORT(bp->ulp_ctx)) { 1801 rc = bnxt_tunnel_dst_port_alloc(bp, 1802 bp->ulp_ctx->cfg_data->vxlan_ip_port, 1803 HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_V4); 1804 if (rc) 1805 BNXT_TF_DBG(ERR, "Failed to set global custom vxlan_ip port\n"); 1806 } 1807 1808 return rc; 1809 } 1810 1811 /* 1812 * When a port is initialized by dpdk. This functions sets up 1813 * the port specific details. 1814 */ 1815 int32_t 1816 bnxt_ulp_port_init(struct bnxt *bp) 1817 { 1818 struct bnxt_ulp_session_state *session; 1819 bool initialized; 1820 enum bnxt_ulp_device_id devid = BNXT_ULP_DEVICE_ID_LAST; 1821 uint32_t ulp_flags; 1822 int32_t rc = 0; 1823 1824 if (!BNXT_TRUFLOW_EN(bp)) { 1825 BNXT_TF_DBG(DEBUG, 1826 "Skip ulp init for port: %d, TF is not enabled\n", 1827 bp->eth_dev->data->port_id); 1828 return rc; 1829 } 1830 1831 if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) { 1832 BNXT_TF_DBG(DEBUG, 1833 "Skip ulp init for port: %d, not a TVF or PF\n", 1834 bp->eth_dev->data->port_id); 1835 return rc; 1836 } 1837 1838 if (bp->ulp_ctx) { 1839 BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n"); 1840 return rc; 1841 } 1842 1843 bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx", 1844 sizeof(struct bnxt_ulp_context), 0); 1845 if (!bp->ulp_ctx) { 1846 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n"); 1847 return -ENOMEM; 1848 } 1849 1850 /* 1851 * Multiple uplink ports can be associated with a single vswitch. 1852 * Make sure only the port that is started first will initialize 1853 * the TF session. 1854 */ 1855 session = ulp_session_init(bp, &initialized); 1856 if (!session) { 1857 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n"); 1858 rc = -EIO; 1859 goto jump_to_error; 1860 } 1861 1862 if (initialized) { 1863 /* 1864 * If ULP is already initialized for a specific domain then 1865 * simply assign the ulp context to this rte_eth_dev. 1866 */ 1867 rc = ulp_ctx_attach(bp, session); 1868 if (rc) { 1869 BNXT_TF_DBG(ERR, "Failed to attach the ulp context\n"); 1870 goto jump_to_error; 1871 } 1872 1873 /* 1874 * Attach to the shared session, must be called after the 1875 * ulp_ctx_attach in order to ensure that ulp data is available 1876 * for attaching. 1877 */ 1878 rc = ulp_ctx_shared_session_attach(bp, session); 1879 if (rc) { 1880 BNXT_TF_DBG(ERR, 1881 "Failed attach to shared session (%d)", rc); 1882 goto jump_to_error; 1883 } 1884 } else { 1885 rc = bnxt_ulp_init(bp, session); 1886 if (rc) { 1887 BNXT_TF_DBG(ERR, "Failed to initialize the ulp init\n"); 1888 goto jump_to_error; 1889 } 1890 } 1891 1892 /* Update bnxt driver flags */ 1893 rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx); 1894 if (rc) { 1895 BNXT_TF_DBG(ERR, "Failed to update driver flags\n"); 1896 goto jump_to_error; 1897 } 1898 1899 /* update the port database for the given interface */ 1900 rc = ulp_port_db_port_update(bp->ulp_ctx, bp->eth_dev); 1901 if (rc) { 1902 BNXT_TF_DBG(ERR, "Failed to update port database\n"); 1903 goto jump_to_error; 1904 } 1905 1906 /* create the default rules */ 1907 rc = bnxt_ulp_create_df_rules(bp); 1908 if (rc) { 1909 BNXT_TF_DBG(ERR, "Failed to create default flow\n"); 1910 goto jump_to_error; 1911 } 1912 1913 rc = bnxt_ulp_devid_get(bp, &devid); 1914 if (rc) { 1915 BNXT_TF_DBG(ERR, "Unable to determine device for ULP port init.\n"); 1916 goto jump_to_error; 1917 } 1918 1919 /* set the unicast mode */ 1920 if (bnxt_ulp_cntxt_ptr2_ulp_flags_get(bp->ulp_ctx, &ulp_flags)) { 1921 BNXT_TF_DBG(ERR, "Error in getting ULP context flags\n"); 1922 goto jump_to_error; 1923 } 1924 if (ulp_flags & BNXT_ULP_APP_UNICAST_ONLY) { 1925 if (bnxt_pmd_set_unicast_rxmask(bp->eth_dev)) { 1926 BNXT_TF_DBG(ERR, "Error in setting unicast rxmode\n"); 1927 goto jump_to_error; 1928 } 1929 } 1930 1931 rc = ulp_cust_vxlan_alloc(bp); 1932 if (rc) 1933 goto jump_to_error; 1934 1935 return rc; 1936 1937 jump_to_error: 1938 bnxt_ulp_port_deinit(bp); 1939 return rc; 1940 } 1941 1942 static void 1943 ulp_cust_vxlan_free(struct bnxt *bp) 1944 { 1945 int rc; 1946 1947 if (ULP_APP_CUST_VXLAN_SUPPORT(bp->ulp_ctx)) { 1948 rc = bnxt_tunnel_dst_port_free(bp, 1949 bp->ulp_ctx->cfg_data->vxlan_port, 1950 HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN); 1951 if (rc) 1952 BNXT_TF_DBG(ERR, "Failed to clear global vxlan port\n"); 1953 } 1954 1955 if (ULP_APP_CUST_VXLAN_IP_SUPPORT(bp->ulp_ctx)) { 1956 rc = bnxt_tunnel_dst_port_free(bp, 1957 bp->ulp_ctx->cfg_data->vxlan_ip_port, 1958 HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_V4); 1959 if (rc) 1960 BNXT_TF_DBG(ERR, "Failed to clear global custom vxlan port\n"); 1961 } 1962 } 1963 1964 /* 1965 * When a port is de-initialized by dpdk. This functions clears up 1966 * the port specific details. 1967 */ 1968 void 1969 bnxt_ulp_port_deinit(struct bnxt *bp) 1970 { 1971 struct bnxt_ulp_session_state *session; 1972 struct rte_pci_device *pci_dev; 1973 struct rte_pci_addr *pci_addr; 1974 1975 if (!BNXT_TRUFLOW_EN(bp)) { 1976 BNXT_TF_DBG(DEBUG, 1977 "Skip ULP deinit for port:%d, TF is not enabled\n", 1978 bp->eth_dev->data->port_id); 1979 return; 1980 } 1981 1982 if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) { 1983 BNXT_TF_DBG(DEBUG, 1984 "Skip ULP deinit port:%d, not a TVF or PF\n", 1985 bp->eth_dev->data->port_id); 1986 return; 1987 } 1988 1989 if (!bp->ulp_ctx) { 1990 BNXT_TF_DBG(DEBUG, "ulp ctx already de-allocated\n"); 1991 return; 1992 } 1993 1994 BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n", 1995 bp->eth_dev->data->port_id); 1996 1997 /* Get the session details */ 1998 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 1999 pci_addr = &pci_dev->addr; 2000 pthread_mutex_lock(&bnxt_ulp_global_mutex); 2001 session = ulp_get_session(bp, pci_addr); 2002 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 2003 2004 /* session not found then just exit */ 2005 if (!session) { 2006 /* Free the ulp context */ 2007 rte_free(bp->ulp_ctx); 2008 bp->ulp_ctx = NULL; 2009 return; 2010 } 2011 2012 /* Check the reference count to deinit or deattach*/ 2013 if (bp->ulp_ctx->cfg_data && bp->ulp_ctx->cfg_data->ref_cnt) { 2014 bp->ulp_ctx->cfg_data->ref_cnt--; 2015 if (bp->ulp_ctx->cfg_data->ref_cnt) { 2016 /* Free tunnel configurations */ 2017 ulp_cust_vxlan_free(bp); 2018 2019 /* free the port details */ 2020 /* Free the default flow rule associated to this port */ 2021 bnxt_ulp_destroy_df_rules(bp, false); 2022 bnxt_ulp_destroy_vfr_default_rules(bp, false); 2023 2024 /* free flows associated with this port */ 2025 bnxt_ulp_flush_port_flows(bp); 2026 2027 /* close the session associated with this port */ 2028 ulp_ctx_detach(bp); 2029 2030 /* always detach/close shared after the session. */ 2031 ulp_ctx_shared_session_detach(bp); 2032 } else { 2033 /* Perform ulp ctx deinit */ 2034 bnxt_ulp_deinit(bp, session); 2035 } 2036 } 2037 2038 /* Free the ulp context in the context entry list */ 2039 bnxt_ulp_cntxt_list_del(bp->ulp_ctx); 2040 2041 /* clean up the session */ 2042 ulp_session_deinit(session); 2043 2044 /* Free the ulp context */ 2045 rte_free(bp->ulp_ctx); 2046 bp->ulp_ctx = NULL; 2047 } 2048 2049 /* Below are the access functions to access internal data of ulp context. */ 2050 /* Function to set the Mark DB into the context */ 2051 int32_t 2052 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx, 2053 struct bnxt_ulp_mark_tbl *mark_tbl) 2054 { 2055 if (!ulp_ctx || !ulp_ctx->cfg_data) { 2056 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 2057 return -EINVAL; 2058 } 2059 2060 ulp_ctx->cfg_data->mark_tbl = mark_tbl; 2061 2062 return 0; 2063 } 2064 2065 /* Function to retrieve the Mark DB from the context. */ 2066 struct bnxt_ulp_mark_tbl * 2067 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx) 2068 { 2069 if (!ulp_ctx || !ulp_ctx->cfg_data) 2070 return NULL; 2071 2072 return ulp_ctx->cfg_data->mark_tbl; 2073 } 2074 2075 bool 2076 bnxt_ulp_cntxt_shared_session_enabled(struct bnxt_ulp_context *ulp_ctx) 2077 { 2078 return ULP_SHARED_SESSION_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags); 2079 } 2080 2081 bool 2082 bnxt_ulp_cntxt_multi_shared_session_enabled(struct bnxt_ulp_context *ulp_ctx) 2083 { 2084 return ULP_MULTI_SHARED_IS_SUPPORTED(ulp_ctx); 2085 } 2086 2087 int32_t 2088 bnxt_ulp_cntxt_app_id_set(struct bnxt_ulp_context *ulp_ctx, uint8_t app_id) 2089 { 2090 if (!ulp_ctx) 2091 return -EINVAL; 2092 ulp_ctx->cfg_data->app_id = app_id; 2093 return 0; 2094 } 2095 2096 int32_t 2097 bnxt_ulp_cntxt_app_id_get(struct bnxt_ulp_context *ulp_ctx, uint8_t *app_id) 2098 { 2099 /* Default APP id is zero */ 2100 if (!ulp_ctx || !app_id) 2101 return -EINVAL; 2102 *app_id = ulp_ctx->cfg_data->app_id; 2103 return 0; 2104 } 2105 2106 /* Function to set the device id of the hardware. */ 2107 int32_t 2108 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx, 2109 uint32_t dev_id) 2110 { 2111 if (ulp_ctx && ulp_ctx->cfg_data) { 2112 ulp_ctx->cfg_data->dev_id = dev_id; 2113 return 0; 2114 } 2115 2116 return -EINVAL; 2117 } 2118 2119 /* Function to get the device id of the hardware. */ 2120 int32_t 2121 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx, 2122 uint32_t *dev_id) 2123 { 2124 if (ulp_ctx && ulp_ctx->cfg_data) { 2125 *dev_id = ulp_ctx->cfg_data->dev_id; 2126 return 0; 2127 } 2128 *dev_id = BNXT_ULP_DEVICE_ID_LAST; 2129 BNXT_TF_DBG(ERR, "Failed to read dev_id from ulp ctxt\n"); 2130 return -EINVAL; 2131 } 2132 2133 int32_t 2134 bnxt_ulp_cntxt_mem_type_set(struct bnxt_ulp_context *ulp_ctx, 2135 enum bnxt_ulp_flow_mem_type mem_type) 2136 { 2137 if (ulp_ctx && ulp_ctx->cfg_data) { 2138 ulp_ctx->cfg_data->mem_type = mem_type; 2139 return 0; 2140 } 2141 BNXT_TF_DBG(ERR, "Failed to write mem_type in ulp ctxt\n"); 2142 return -EINVAL; 2143 } 2144 2145 int32_t 2146 bnxt_ulp_cntxt_mem_type_get(struct bnxt_ulp_context *ulp_ctx, 2147 enum bnxt_ulp_flow_mem_type *mem_type) 2148 { 2149 if (ulp_ctx && ulp_ctx->cfg_data) { 2150 *mem_type = ulp_ctx->cfg_data->mem_type; 2151 return 0; 2152 } 2153 *mem_type = BNXT_ULP_FLOW_MEM_TYPE_LAST; 2154 BNXT_TF_DBG(ERR, "Failed to read mem_type in ulp ctxt\n"); 2155 return -EINVAL; 2156 } 2157 2158 /* Function to get the table scope id of the EEM table. */ 2159 int32_t 2160 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx, 2161 uint32_t *tbl_scope_id) 2162 { 2163 if (ulp_ctx && ulp_ctx->cfg_data) { 2164 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id; 2165 return 0; 2166 } 2167 2168 return -EINVAL; 2169 } 2170 2171 /* Function to set the table scope id of the EEM table. */ 2172 int32_t 2173 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx, 2174 uint32_t tbl_scope_id) 2175 { 2176 if (ulp_ctx && ulp_ctx->cfg_data) { 2177 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id; 2178 return 0; 2179 } 2180 2181 return -EINVAL; 2182 } 2183 2184 /* Function to get the number of shared clients attached */ 2185 uint8_t 2186 bnxt_ulp_cntxt_num_shared_clients_get(struct bnxt_ulp_context *ulp) 2187 { 2188 if (ulp == NULL || ulp->cfg_data == NULL) { 2189 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 2190 return 0; 2191 } 2192 return ulp->cfg_data->num_shared_clients; 2193 } 2194 2195 /* Function to set the number of shared clients */ 2196 int 2197 bnxt_ulp_cntxt_num_shared_clients_set(struct bnxt_ulp_context *ulp, bool incr) 2198 { 2199 if (ulp == NULL || ulp->cfg_data == NULL) { 2200 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 2201 return 0; 2202 } 2203 if (incr) 2204 ulp->cfg_data->num_shared_clients++; 2205 else if (ulp->cfg_data->num_shared_clients) 2206 ulp->cfg_data->num_shared_clients--; 2207 2208 BNXT_TF_DBG(DEBUG, "%d:clients(%d)\n", incr, 2209 ulp->cfg_data->num_shared_clients); 2210 2211 return 0; 2212 } 2213 2214 /* Function to set the tfp session details from the ulp context. */ 2215 int32_t 2216 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, 2217 enum bnxt_ulp_session_type s_type, 2218 struct tf *tfp) 2219 { 2220 uint32_t idx = 0; 2221 2222 if (!ulp) { 2223 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 2224 return -EINVAL; 2225 } 2226 if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp)) { 2227 if (s_type & BNXT_ULP_SESSION_TYPE_SHARED) 2228 idx = 1; 2229 else if (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 2230 idx = 2; 2231 2232 } else { 2233 if ((s_type & BNXT_ULP_SESSION_TYPE_SHARED) || 2234 (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)) 2235 idx = 1; 2236 } 2237 2238 ulp->g_tfp[idx] = tfp; 2239 return 0; 2240 } 2241 2242 /* Function to get the tfp session details from the ulp context. */ 2243 struct tf * 2244 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp, 2245 enum bnxt_ulp_session_type s_type) 2246 { 2247 uint32_t idx = 0; 2248 2249 if (!ulp) { 2250 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 2251 return NULL; 2252 } 2253 if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp)) { 2254 if (s_type & BNXT_ULP_SESSION_TYPE_SHARED) 2255 idx = 1; 2256 else if (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 2257 idx = 2; 2258 } else { 2259 if ((s_type & BNXT_ULP_SESSION_TYPE_SHARED) || 2260 (s_type & BNXT_ULP_SESSION_TYPE_SHARED_WC)) 2261 idx = 1; 2262 } 2263 return ulp->g_tfp[idx]; 2264 } 2265 2266 /* 2267 * Get the device table entry based on the device id. 2268 * 2269 * dev_id [in] The device id of the hardware 2270 * 2271 * Returns the pointer to the device parameters. 2272 */ 2273 struct bnxt_ulp_device_params * 2274 bnxt_ulp_device_params_get(uint32_t dev_id) 2275 { 2276 if (dev_id < BNXT_ULP_MAX_NUM_DEVICES) 2277 return &ulp_device_params[dev_id]; 2278 return NULL; 2279 } 2280 2281 /* Function to set the flow database to the ulp context. */ 2282 int32_t 2283 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx, 2284 struct bnxt_ulp_flow_db *flow_db) 2285 { 2286 if (!ulp_ctx || !ulp_ctx->cfg_data) 2287 return -EINVAL; 2288 2289 ulp_ctx->cfg_data->flow_db = flow_db; 2290 return 0; 2291 } 2292 2293 /* Function to get the flow database from the ulp context. */ 2294 struct bnxt_ulp_flow_db * 2295 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx) 2296 { 2297 if (!ulp_ctx || !ulp_ctx->cfg_data) 2298 return NULL; 2299 2300 return ulp_ctx->cfg_data->flow_db; 2301 } 2302 2303 /* Function to get the tunnel cache table info from the ulp context. */ 2304 struct bnxt_tun_cache_entry * 2305 bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx) 2306 { 2307 if (!ulp_ctx || !ulp_ctx->cfg_data) 2308 return NULL; 2309 2310 return ulp_ctx->cfg_data->tun_tbl; 2311 } 2312 2313 /* Function to get the ulp context from eth device. */ 2314 struct bnxt_ulp_context * 2315 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev) 2316 { 2317 struct bnxt *bp = (struct bnxt *)dev->data->dev_private; 2318 2319 if (rte_eth_dev_is_repr(dev)) { 2320 struct bnxt_representor *vfr = dev->data->dev_private; 2321 2322 bp = vfr->parent_dev->data->dev_private; 2323 } 2324 2325 if (!bp) { 2326 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n"); 2327 return NULL; 2328 } 2329 return bp->ulp_ctx; 2330 } 2331 2332 int32_t 2333 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx, 2334 void *mapper_data) 2335 { 2336 if (!ulp_ctx || !ulp_ctx->cfg_data) { 2337 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 2338 return -EINVAL; 2339 } 2340 2341 ulp_ctx->cfg_data->mapper_data = mapper_data; 2342 return 0; 2343 } 2344 2345 void * 2346 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx) 2347 { 2348 if (!ulp_ctx || !ulp_ctx->cfg_data) { 2349 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 2350 return NULL; 2351 } 2352 2353 return ulp_ctx->cfg_data->mapper_data; 2354 } 2355 2356 /* Function to set the port database to the ulp context. */ 2357 int32_t 2358 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx, 2359 struct bnxt_ulp_port_db *port_db) 2360 { 2361 if (!ulp_ctx || !ulp_ctx->cfg_data) 2362 return -EINVAL; 2363 2364 ulp_ctx->cfg_data->port_db = port_db; 2365 return 0; 2366 } 2367 2368 /* Function to get the port database from the ulp context. */ 2369 struct bnxt_ulp_port_db * 2370 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx) 2371 { 2372 if (!ulp_ctx || !ulp_ctx->cfg_data) 2373 return NULL; 2374 2375 return ulp_ctx->cfg_data->port_db; 2376 } 2377 2378 /* Function to set the flow counter info into the context */ 2379 int32_t 2380 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx, 2381 struct bnxt_ulp_fc_info *ulp_fc_info) 2382 { 2383 if (!ulp_ctx || !ulp_ctx->cfg_data) { 2384 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 2385 return -EINVAL; 2386 } 2387 2388 ulp_ctx->cfg_data->fc_info = ulp_fc_info; 2389 2390 return 0; 2391 } 2392 2393 /* Function to retrieve the flow counter info from the context. */ 2394 struct bnxt_ulp_fc_info * 2395 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx) 2396 { 2397 if (!ulp_ctx || !ulp_ctx->cfg_data) 2398 return NULL; 2399 2400 return ulp_ctx->cfg_data->fc_info; 2401 } 2402 2403 /* Function to get the ulp flags from the ulp context. */ 2404 int32_t 2405 bnxt_ulp_cntxt_ptr2_ulp_flags_get(struct bnxt_ulp_context *ulp_ctx, 2406 uint32_t *flags) 2407 { 2408 if (!ulp_ctx || !ulp_ctx->cfg_data) 2409 return -1; 2410 2411 *flags = ulp_ctx->cfg_data->ulp_flags; 2412 return 0; 2413 } 2414 2415 /* Function to get the ulp vfr info from the ulp context. */ 2416 struct bnxt_ulp_vfr_rule_info* 2417 bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(struct bnxt_ulp_context *ulp_ctx, 2418 uint32_t port_id) 2419 { 2420 if (!ulp_ctx || !ulp_ctx->cfg_data || port_id >= RTE_MAX_ETHPORTS) 2421 return NULL; 2422 2423 return &ulp_ctx->cfg_data->vfr_rule_info[port_id]; 2424 } 2425 2426 /* Function to acquire the flow database lock from the ulp context. */ 2427 int32_t 2428 bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context *ulp_ctx) 2429 { 2430 if (!ulp_ctx || !ulp_ctx->cfg_data) 2431 return -1; 2432 2433 if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) { 2434 BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n"); 2435 return -1; 2436 } 2437 return 0; 2438 } 2439 2440 /* Function to release the flow database lock from the ulp context. */ 2441 void 2442 bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context *ulp_ctx) 2443 { 2444 if (!ulp_ctx || !ulp_ctx->cfg_data) 2445 return; 2446 2447 pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock); 2448 } 2449 2450 /* Function to extract the action type from the shared action handle. */ 2451 int32_t 2452 bnxt_get_action_handle_type(const struct rte_flow_action_handle *handle, 2453 uint32_t *action_handle_type) 2454 { 2455 if (!action_handle_type) 2456 return -EINVAL; 2457 2458 *action_handle_type = (uint32_t)(((uint64_t)handle >> 32) & 0xffffffff); 2459 if (*action_handle_type >= BNXT_ULP_GEN_TBL_MAX_SZ) 2460 return -EINVAL; 2461 2462 return 0; 2463 } 2464 2465 /* Function to extract the direction from the shared action handle. */ 2466 int32_t 2467 bnxt_get_action_handle_direction(const struct rte_flow_action_handle *handle, 2468 uint32_t *dir) 2469 { 2470 uint32_t shared_type; 2471 int32_t ret = 0; 2472 2473 ret = bnxt_get_action_handle_type(handle, &shared_type); 2474 if (ret) 2475 return ret; 2476 2477 *dir = shared_type & 0x1 ? BNXT_ULP_DIR_EGRESS : BNXT_ULP_DIR_INGRESS; 2478 2479 return ret; 2480 } 2481 2482 /* Function to extract the action index from the shared action handle. */ 2483 uint32_t 2484 bnxt_get_action_handle_index(const struct rte_flow_action_handle *handle) 2485 { 2486 return (uint32_t)((uint64_t)handle & 0xffffffff); 2487 } 2488 2489 /* Function to set the ha info into the context */ 2490 int32_t 2491 bnxt_ulp_cntxt_ptr2_ha_info_set(struct bnxt_ulp_context *ulp_ctx, 2492 struct bnxt_ulp_ha_mgr_info *ulp_ha_info) 2493 { 2494 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) { 2495 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 2496 return -EINVAL; 2497 } 2498 ulp_ctx->cfg_data->ha_info = ulp_ha_info; 2499 return 0; 2500 } 2501 2502 /* Function to retrieve the ha info from the context. */ 2503 struct bnxt_ulp_ha_mgr_info * 2504 bnxt_ulp_cntxt_ptr2_ha_info_get(struct bnxt_ulp_context *ulp_ctx) 2505 { 2506 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 2507 return NULL; 2508 return ulp_ctx->cfg_data->ha_info; 2509 } 2510 2511 bool 2512 bnxt_ulp_cntxt_ha_enabled(struct bnxt_ulp_context *ulp_ctx) 2513 { 2514 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 2515 return false; 2516 return !!ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags); 2517 } 2518 2519 static int32_t 2520 bnxt_ulp_cntxt_list_init(void) 2521 { 2522 /* Create the cntxt spin lock only once*/ 2523 if (!bnxt_ulp_ctxt_lock_created) 2524 rte_spinlock_init(&bnxt_ulp_ctxt_lock); 2525 bnxt_ulp_ctxt_lock_created = 1; 2526 return 0; 2527 } 2528 2529 static int32_t 2530 bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx) 2531 { 2532 struct ulp_context_list_entry *entry; 2533 2534 entry = rte_zmalloc(NULL, sizeof(struct ulp_context_list_entry), 0); 2535 if (entry == NULL) { 2536 BNXT_TF_DBG(ERR, "unable to allocate memory\n"); 2537 return -ENOMEM; 2538 } 2539 2540 rte_spinlock_lock(&bnxt_ulp_ctxt_lock); 2541 entry->ulp_ctx = ulp_ctx; 2542 TAILQ_INSERT_TAIL(&ulp_cntx_list, entry, next); 2543 rte_spinlock_unlock(&bnxt_ulp_ctxt_lock); 2544 return 0; 2545 } 2546 2547 static void 2548 bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx) 2549 { 2550 struct ulp_context_list_entry *entry, *temp; 2551 2552 rte_spinlock_lock(&bnxt_ulp_ctxt_lock); 2553 RTE_TAILQ_FOREACH_SAFE(entry, &ulp_cntx_list, next, temp) { 2554 if (entry->ulp_ctx == ulp_ctx) { 2555 TAILQ_REMOVE(&ulp_cntx_list, entry, next); 2556 rte_free(entry); 2557 break; 2558 } 2559 } 2560 rte_spinlock_unlock(&bnxt_ulp_ctxt_lock); 2561 } 2562 2563 struct bnxt_ulp_context * 2564 bnxt_ulp_cntxt_entry_acquire(void *arg) 2565 { 2566 struct ulp_context_list_entry *entry; 2567 2568 /* take a lock and get the first ulp context available */ 2569 if (rte_spinlock_trylock(&bnxt_ulp_ctxt_lock)) { 2570 TAILQ_FOREACH(entry, &ulp_cntx_list, next) 2571 if (entry->ulp_ctx->cfg_data == arg) 2572 return entry->ulp_ctx; 2573 rte_spinlock_unlock(&bnxt_ulp_ctxt_lock); 2574 } 2575 return NULL; 2576 } 2577 2578 void 2579 bnxt_ulp_cntxt_entry_release(void) 2580 { 2581 rte_spinlock_unlock(&bnxt_ulp_ctxt_lock); 2582 } 2583 2584 /* Function to get the app tunnel details from the ulp context. */ 2585 struct bnxt_flow_app_tun_ent * 2586 bnxt_ulp_cntxt_ptr2_app_tun_list_get(struct bnxt_ulp_context *ulp) 2587 { 2588 if (!ulp || !ulp->cfg_data) 2589 return NULL; 2590 2591 return ulp->cfg_data->app_tun; 2592 } 2593 2594 /* Function to get the truflow app id. This defined in the build file */ 2595 uint32_t 2596 bnxt_ulp_default_app_id_get(void) 2597 { 2598 return BNXT_TF_APP_ID; 2599 } 2600 2601 /* Function to convert ulp dev id to regular dev id. */ 2602 uint32_t 2603 bnxt_ulp_cntxt_convert_dev_id(uint32_t ulp_dev_id) 2604 { 2605 enum tf_device_type type = 0; 2606 2607 switch (ulp_dev_id) { 2608 case BNXT_ULP_DEVICE_ID_WH_PLUS: 2609 type = TF_DEVICE_TYPE_P4; 2610 break; 2611 case BNXT_ULP_DEVICE_ID_STINGRAY: 2612 type = TF_DEVICE_TYPE_SR; 2613 break; 2614 case BNXT_ULP_DEVICE_ID_THOR: 2615 type = TF_DEVICE_TYPE_P5; 2616 break; 2617 default: 2618 BNXT_TF_DBG(ERR, "Invalid device id\n"); 2619 break; 2620 } 2621 return type; 2622 } 2623 2624 /* This function sets the IF table index for the 2625 * Application to poll to get the hot upgrade state and count details from 2626 * the firmware. 2627 */ 2628 int32_t 2629 bnxt_ulp_ha_reg_set(struct bnxt_ulp_context *ulp_ctx, 2630 uint8_t state, uint8_t cnt) 2631 { 2632 if (!ulp_ctx || !ulp_ctx->cfg_data) 2633 return -EINVAL; 2634 2635 if (ULP_MULTI_SHARED_IS_SUPPORTED(ulp_ctx)) { 2636 ulp_ctx->cfg_data->hu_reg_state = state; 2637 ulp_ctx->cfg_data->hu_reg_cnt = cnt; 2638 } else { 2639 ulp_ctx->cfg_data->hu_reg_state = ULP_HA_IF_TBL_IDX; 2640 ulp_ctx->cfg_data->hu_reg_cnt = ULP_HA_CLIENT_CNT_IF_TBL_IDX; 2641 } 2642 return 0; 2643 } 2644 2645 /* This function gets the IF table index for the 2646 * application to poll to get the application hot upgrade state from 2647 * the firmware. 2648 */ 2649 uint32_t 2650 bnxt_ulp_ha_reg_state_get(struct bnxt_ulp_context *ulp_ctx) 2651 { 2652 if (!ulp_ctx || !ulp_ctx->cfg_data) 2653 return 0; 2654 2655 return (uint32_t)ulp_ctx->cfg_data->hu_reg_state; 2656 } 2657 2658 /* This function gets the IF table index for the 2659 * Application to poll to get the application count from 2660 * the firmware. 2661 */ 2662 uint32_t 2663 bnxt_ulp_ha_reg_cnt_get(struct bnxt_ulp_context *ulp_ctx) 2664 { 2665 if (!ulp_ctx || !ulp_ctx->cfg_data) 2666 return 0; 2667 2668 return (uint32_t)ulp_ctx->cfg_data->hu_reg_cnt; 2669 } 2670 2671 struct tf* 2672 bnxt_ulp_bp_tfp_get(struct bnxt *bp, enum bnxt_ulp_session_type type) 2673 { 2674 enum bnxt_session_type btype; 2675 2676 if (type & BNXT_ULP_SESSION_TYPE_SHARED) 2677 btype = BNXT_SESSION_TYPE_SHARED_COMMON; 2678 else if (type & BNXT_ULP_SESSION_TYPE_SHARED_WC) 2679 btype = BNXT_SESSION_TYPE_SHARED_WC; 2680 else 2681 btype = BNXT_SESSION_TYPE_REGULAR; 2682 2683 return bnxt_get_tfp_session(bp, btype); 2684 } 2685