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 13 #include "bnxt.h" 14 #include "bnxt_ulp.h" 15 #include "bnxt_tf_common.h" 16 #include "tf_core.h" 17 #include "tf_ext_flow_handle.h" 18 19 #include "ulp_template_db_enum.h" 20 #include "ulp_template_struct.h" 21 #include "ulp_mark_mgr.h" 22 #include "ulp_fc_mgr.h" 23 #include "ulp_flow_db.h" 24 #include "ulp_mapper.h" 25 #include "ulp_port_db.h" 26 #include "ulp_tun.h" 27 #include "ulp_ha_mgr.h" 28 #include "bnxt_tf_pmd_shim.h" 29 30 /* Linked list of all TF sessions. */ 31 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list = 32 STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list); 33 34 /* Mutex to synchronize bnxt_ulp_session_list operations. */ 35 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER; 36 37 /* Spin lock to protect context global list */ 38 rte_spinlock_t bnxt_ulp_ctxt_lock; 39 TAILQ_HEAD(cntx_list_entry_list, ulp_context_list_entry); 40 static struct cntx_list_entry_list ulp_cntx_list = 41 TAILQ_HEAD_INITIALIZER(ulp_cntx_list); 42 43 /* Static function declarations */ 44 static int32_t bnxt_ulp_cntxt_list_init(void); 45 static int32_t bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx); 46 static void bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx); 47 48 /* 49 * Allow the deletion of context only for the bnxt device that 50 * created the session. 51 */ 52 bool 53 ulp_ctx_deinit_allowed(struct bnxt_ulp_context *ulp_ctx) 54 { 55 if (!ulp_ctx || !ulp_ctx->cfg_data) 56 return false; 57 58 if (!ulp_ctx->cfg_data->ref_cnt) { 59 BNXT_TF_DBG(DEBUG, "ulp ctx shall initiate deinit\n"); 60 return true; 61 } 62 63 return false; 64 } 65 66 static int32_t 67 bnxt_ulp_devid_get(struct bnxt *bp, 68 enum bnxt_ulp_device_id *ulp_dev_id) 69 { 70 if (BNXT_CHIP_P5(bp)) { 71 *ulp_dev_id = BNXT_ULP_DEVICE_ID_THOR; 72 return 0; 73 } 74 75 if (BNXT_STINGRAY(bp)) 76 *ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY; 77 else 78 /* Assuming Whitney */ 79 *ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS; 80 81 return 0; 82 } 83 84 struct bnxt_ulp_app_capabilities_info * 85 bnxt_ulp_app_cap_list_get(uint32_t *num_entries) 86 { 87 if (!num_entries) 88 return NULL; 89 *num_entries = BNXT_ULP_APP_CAP_TBL_MAX_SZ; 90 return ulp_app_cap_info_list; 91 } 92 93 static struct bnxt_ulp_resource_resv_info * 94 bnxt_ulp_app_resource_resv_list_get(uint32_t *num_entries) 95 { 96 if (num_entries == NULL) 97 return NULL; 98 *num_entries = BNXT_ULP_APP_RESOURCE_RESV_LIST_MAX_SZ; 99 return ulp_app_resource_resv_list; 100 } 101 102 struct bnxt_ulp_resource_resv_info * 103 bnxt_ulp_resource_resv_list_get(uint32_t *num_entries) 104 { 105 if (!num_entries) 106 return NULL; 107 *num_entries = BNXT_ULP_RESOURCE_RESV_LIST_MAX_SZ; 108 return ulp_resource_resv_list; 109 } 110 111 struct bnxt_ulp_glb_resource_info * 112 bnxt_ulp_app_glb_resource_info_list_get(uint32_t *num_entries) 113 { 114 if (!num_entries) 115 return NULL; 116 *num_entries = BNXT_ULP_APP_GLB_RESOURCE_TBL_MAX_SZ; 117 return ulp_app_glb_resource_tbl; 118 } 119 120 static int32_t 121 bnxt_ulp_named_resources_calc(struct bnxt_ulp_context *ulp_ctx, 122 struct bnxt_ulp_glb_resource_info *info, 123 uint32_t num, 124 struct tf_session_resources *res) 125 { 126 uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST, res_type, i; 127 enum tf_dir dir; 128 uint8_t app_id; 129 int32_t rc = 0; 130 131 if (ulp_ctx == NULL || info == NULL || res == NULL || num == 0) { 132 BNXT_TF_DBG(ERR, "Invalid parms to named resources calc.\n"); 133 return -EINVAL; 134 } 135 136 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 137 if (rc) { 138 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 139 return -EINVAL; 140 } 141 142 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 143 if (rc) { 144 BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n"); 145 return -EINVAL; 146 } 147 148 for (i = 0; i < num; i++) { 149 if (dev_id != info[i].device_id || app_id != info[i].app_id) 150 continue; 151 dir = info[i].direction; 152 res_type = info[i].resource_type; 153 154 switch (info[i].resource_func) { 155 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 156 res->ident_cnt[dir].cnt[res_type]++; 157 break; 158 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 159 res->tbl_cnt[dir].cnt[res_type]++; 160 break; 161 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 162 res->tcam_cnt[dir].cnt[res_type]++; 163 break; 164 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 165 res->em_cnt[dir].cnt[res_type]++; 166 break; 167 default: 168 BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n,", 169 info[i].resource_func); 170 continue; 171 } 172 } 173 174 return 0; 175 } 176 177 static int32_t 178 bnxt_ulp_unnamed_resources_calc(struct bnxt_ulp_context *ulp_ctx, 179 struct bnxt_ulp_resource_resv_info *info, 180 uint32_t num, 181 struct tf_session_resources *res) 182 { 183 uint32_t dev_id, res_type, i; 184 enum tf_dir dir; 185 uint8_t app_id; 186 int32_t rc = 0; 187 188 if (ulp_ctx == NULL || res == NULL || info == NULL || num == 0) { 189 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n"); 190 return -EINVAL; 191 } 192 193 rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id); 194 if (rc) { 195 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 196 return -EINVAL; 197 } 198 199 rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id); 200 if (rc) { 201 BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n"); 202 return -EINVAL; 203 } 204 205 for (i = 0; i < num; i++) { 206 if (app_id != info[i].app_id || dev_id != info[i].device_id) 207 continue; 208 dir = info[i].direction; 209 res_type = info[i].resource_type; 210 211 switch (info[i].resource_func) { 212 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER: 213 res->ident_cnt[dir].cnt[res_type] = info[i].count; 214 break; 215 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE: 216 res->tbl_cnt[dir].cnt[res_type] = info[i].count; 217 break; 218 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE: 219 res->tcam_cnt[dir].cnt[res_type] = info[i].count; 220 break; 221 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE: 222 res->em_cnt[dir].cnt[res_type] = info[i].count; 223 break; 224 default: 225 break; 226 } 227 } 228 return 0; 229 } 230 231 static int32_t 232 bnxt_ulp_tf_resources_get(struct bnxt_ulp_context *ulp_ctx, 233 struct tf_session_resources *res) 234 { 235 struct bnxt_ulp_resource_resv_info *unnamed = NULL; 236 uint32_t unum; 237 int32_t rc = 0; 238 239 if (ulp_ctx == NULL || res == NULL) { 240 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n"); 241 return -EINVAL; 242 } 243 244 unnamed = bnxt_ulp_resource_resv_list_get(&unum); 245 if (unnamed == NULL) { 246 BNXT_TF_DBG(ERR, "Unable to get resource resv list.\n"); 247 return -EINVAL; 248 } 249 250 rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, res); 251 if (rc) 252 BNXT_TF_DBG(ERR, "Unable to calc resources for session.\n"); 253 254 return rc; 255 } 256 257 static int32_t 258 bnxt_ulp_tf_shared_session_resources_get(struct bnxt_ulp_context *ulp_ctx, 259 struct tf_session_resources *res) 260 { 261 struct bnxt_ulp_resource_resv_info *unnamed; 262 struct bnxt_ulp_glb_resource_info *named; 263 uint32_t unum, nnum; 264 int32_t rc; 265 266 if (ulp_ctx == NULL || res == NULL) { 267 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n"); 268 return -EINVAL; 269 } 270 271 /* Make sure the resources are zero before accumulating. */ 272 memset(res, 0, sizeof(struct tf_session_resources)); 273 274 /* 275 * Shared resources are comprised of both named and unnamed resources. 276 * First get the unnamed counts, and then add the named to the result. 277 */ 278 /* Get the baseline counts */ 279 unnamed = bnxt_ulp_app_resource_resv_list_get(&unum); 280 if (unnamed == NULL) { 281 BNXT_TF_DBG(ERR, "Unable to get shared resource resv list.\n"); 282 return -EINVAL; 283 } 284 rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, res); 285 if (rc) { 286 BNXT_TF_DBG(ERR, "Unable to calc resources for shared session.\n"); 287 return -EINVAL; 288 } 289 290 /* Get the named list and add the totals */ 291 named = bnxt_ulp_app_glb_resource_info_list_get(&nnum); 292 if (named == NULL) { 293 BNXT_TF_DBG(ERR, "Unable to get app global resource list\n"); 294 return -EINVAL; 295 } 296 rc = bnxt_ulp_named_resources_calc(ulp_ctx, named, nnum, res); 297 if (rc) 298 BNXT_TF_DBG(ERR, "Unable to calc named resources\n"); 299 300 return rc; 301 } 302 303 int32_t 304 bnxt_ulp_cntxt_app_caps_init(struct bnxt_ulp_context *ulp_ctx, 305 uint8_t app_id, uint32_t dev_id) 306 { 307 struct bnxt_ulp_app_capabilities_info *info; 308 uint32_t num = 0; 309 uint16_t i; 310 bool found = false; 311 312 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(ulp_ctx->cfg_data->ulp_flags)) { 313 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 314 app_id, dev_id); 315 return -EINVAL; 316 } 317 318 info = bnxt_ulp_app_cap_list_get(&num); 319 if (!info || !num) { 320 BNXT_TF_DBG(ERR, "Failed to get app capabilities.\n"); 321 return -EINVAL; 322 } 323 324 for (i = 0; i < num; i++) { 325 if (info[i].app_id != app_id || info[i].device_id != dev_id) 326 continue; 327 found = true; 328 if (info[i].flags & BNXT_ULP_APP_CAP_SHARED_EN) 329 ulp_ctx->cfg_data->ulp_flags |= 330 BNXT_ULP_SHARED_SESSION_ENABLED; 331 if (info[i].flags & BNXT_ULP_APP_CAP_HOT_UPGRADE_EN) 332 ulp_ctx->cfg_data->ulp_flags |= 333 BNXT_ULP_HIGH_AVAIL_ENABLED; 334 if (info[i].flags & BNXT_ULP_APP_CAP_UNICAST_ONLY) 335 ulp_ctx->cfg_data->ulp_flags |= 336 BNXT_ULP_APP_UNICAST_ONLY; 337 } 338 if (!found) { 339 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 340 app_id, dev_id); 341 ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_APP_DEV_UNSUPPORTED; 342 return -EINVAL; 343 } 344 345 return 0; 346 } 347 348 static void 349 ulp_ctx_shared_session_close(struct bnxt *bp, 350 struct bnxt_ulp_session_state *session) 351 { 352 struct tf *tfp; 353 int32_t rc; 354 355 if (!bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) 356 return; 357 358 tfp = bnxt_ulp_cntxt_shared_tfp_get(bp->ulp_ctx); 359 if (!tfp) { 360 /* 361 * Log it under debug since this is likely a case of the 362 * shared session not being created. For example, a failed 363 * initialization. 364 */ 365 BNXT_TF_DBG(DEBUG, "Failed to get shared tfp on close.\n"); 366 return; 367 } 368 rc = tf_close_session(tfp); 369 if (rc) 370 BNXT_TF_DBG(ERR, "Failed to close the shared session rc=%d.\n", 371 rc); 372 (void)bnxt_ulp_cntxt_shared_tfp_set(bp->ulp_ctx, NULL); 373 374 session->g_shared_tfp.session = NULL; 375 } 376 377 static int32_t 378 ulp_ctx_shared_session_open(struct bnxt *bp, 379 struct bnxt_ulp_session_state *session) 380 { 381 struct rte_eth_dev *ethdev = bp->eth_dev; 382 struct tf_session_resources *resources; 383 struct tf_open_session_parms parms; 384 size_t copy_nbytes; 385 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 386 int32_t rc = 0; 387 388 /* only perform this if shared session is enabled. */ 389 if (!bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) 390 return 0; 391 392 memset(&parms, 0, sizeof(parms)); 393 394 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 395 parms.ctrl_chan_name); 396 if (rc) { 397 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n", 398 ethdev->data->port_id, rc); 399 return rc; 400 } 401 resources = &parms.resources; 402 403 /* 404 * Need to account for size of ctrl_chan_name and 1 extra for Null 405 * terminator 406 */ 407 copy_nbytes = sizeof(parms.ctrl_chan_name) - 408 strlen(parms.ctrl_chan_name) - 1; 409 410 /* 411 * Build the ctrl_chan_name with shared token. 412 * When HA is enabled, the WC TCAM needs extra management by the core, 413 * so add the wc_tcam string to the control channel. 414 */ 415 if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) 416 strncat(parms.ctrl_chan_name, "-tf_shared-wc_tcam", 417 copy_nbytes); 418 else 419 strncat(parms.ctrl_chan_name, "-tf_shared", copy_nbytes); 420 421 rc = bnxt_ulp_tf_shared_session_resources_get(bp->ulp_ctx, resources); 422 if (rc) 423 return rc; 424 425 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 426 if (rc) { 427 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n"); 428 return rc; 429 } 430 431 switch (ulp_dev_id) { 432 case BNXT_ULP_DEVICE_ID_WH_PLUS: 433 parms.device_type = TF_DEVICE_TYPE_WH; 434 break; 435 case BNXT_ULP_DEVICE_ID_STINGRAY: 436 parms.device_type = TF_DEVICE_TYPE_SR; 437 break; 438 case BNXT_ULP_DEVICE_ID_THOR: 439 parms.device_type = TF_DEVICE_TYPE_THOR; 440 break; 441 default: 442 BNXT_TF_DBG(ERR, "Unable to determine dev for opening session.\n"); 443 return rc; 444 } 445 446 parms.shadow_copy = true; 447 parms.bp = bp; 448 449 /* 450 * Open the session here, but the collect the resources during the 451 * mapper initialization. 452 */ 453 rc = tf_open_session(&bp->tfp_shared, &parms); 454 if (rc) 455 return rc; 456 457 if (parms.shared_session_creator) 458 BNXT_TF_DBG(DEBUG, "Shared session creator.\n"); 459 else 460 BNXT_TF_DBG(DEBUG, "Shared session attached.\n"); 461 462 /* Save the shared session in global data */ 463 if (!session->g_shared_tfp.session) 464 session->g_shared_tfp.session = bp->tfp_shared.session; 465 466 rc = bnxt_ulp_cntxt_shared_tfp_set(bp->ulp_ctx, &bp->tfp_shared); 467 if (rc) 468 BNXT_TF_DBG(ERR, "Failed to add shared tfp to ulp (%d)\n", rc); 469 470 return rc; 471 } 472 473 static int32_t 474 ulp_ctx_shared_session_attach(struct bnxt *bp, 475 struct bnxt_ulp_session_state *session) 476 { 477 int32_t rc = 0; 478 479 /* Simply return success if shared session not enabled */ 480 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 481 bp->tfp_shared.session = session->g_shared_tfp.session; 482 rc = ulp_ctx_shared_session_open(bp, session); 483 } 484 485 return rc; 486 } 487 488 static void 489 ulp_ctx_shared_session_detach(struct bnxt *bp) 490 { 491 if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) { 492 if (bp->tfp_shared.session) { 493 tf_close_session(&bp->tfp_shared); 494 bp->tfp_shared.session = NULL; 495 } 496 } 497 } 498 499 /* 500 * Initialize an ULP session. 501 * An ULP session will contain all the resources needed to support rte flow 502 * offloads. A session is initialized as part of rte_eth_device start. 503 * A single vswitch instance can have multiple uplinks which means 504 * rte_eth_device start will be called for each of these devices. 505 * ULP session manager will make sure that a single ULP session is only 506 * initialized once. Apart from this, it also initializes MARK database, 507 * EEM table & flow database. ULP session manager also manages a list of 508 * all opened ULP sessions. 509 */ 510 static int32_t 511 ulp_ctx_session_open(struct bnxt *bp, 512 struct bnxt_ulp_session_state *session) 513 { 514 struct rte_eth_dev *ethdev = bp->eth_dev; 515 int32_t rc = 0; 516 struct tf_open_session_parms params; 517 struct tf_session_resources *resources; 518 uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST; 519 520 memset(¶ms, 0, sizeof(params)); 521 522 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 523 params.ctrl_chan_name); 524 if (rc) { 525 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n", 526 ethdev->data->port_id, rc); 527 return rc; 528 } 529 530 params.shadow_copy = true; 531 532 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 533 if (rc) { 534 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n"); 535 return rc; 536 } 537 538 switch (ulp_dev_id) { 539 case BNXT_ULP_DEVICE_ID_WH_PLUS: 540 params.device_type = TF_DEVICE_TYPE_WH; 541 break; 542 case BNXT_ULP_DEVICE_ID_STINGRAY: 543 params.device_type = TF_DEVICE_TYPE_SR; 544 break; 545 case BNXT_ULP_DEVICE_ID_THOR: 546 params.device_type = TF_DEVICE_TYPE_THOR; 547 break; 548 default: 549 BNXT_TF_DBG(ERR, "Unable to determine device for opening session.\n"); 550 return rc; 551 } 552 553 resources = ¶ms.resources; 554 rc = bnxt_ulp_tf_resources_get(bp->ulp_ctx, resources); 555 if (rc) 556 return rc; 557 558 params.bp = bp; 559 rc = tf_open_session(&bp->tfp, ¶ms); 560 if (rc) { 561 BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n", 562 params.ctrl_chan_name, rc); 563 return -EINVAL; 564 } 565 if (!session->session_opened) { 566 session->session_opened = 1; 567 session->g_tfp = rte_zmalloc("bnxt_ulp_session_tfp", 568 sizeof(struct tf), 0); 569 session->g_tfp->session = bp->tfp.session; 570 } 571 return rc; 572 } 573 574 /* 575 * Close the ULP session. 576 * It takes the ulp context pointer. 577 */ 578 static void 579 ulp_ctx_session_close(struct bnxt *bp, 580 struct bnxt_ulp_session_state *session) 581 { 582 /* close the session in the hardware */ 583 if (session->session_opened) 584 tf_close_session(&bp->tfp); 585 session->session_opened = 0; 586 rte_free(session->g_tfp); 587 session->g_tfp = NULL; 588 } 589 590 static void 591 bnxt_init_tbl_scope_parms(struct bnxt *bp, 592 struct tf_alloc_tbl_scope_parms *params) 593 { 594 struct bnxt_ulp_device_params *dparms; 595 uint32_t dev_id; 596 int rc; 597 598 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 599 if (rc) 600 /* TBD: For now, just use default. */ 601 dparms = 0; 602 else 603 dparms = bnxt_ulp_device_params_get(dev_id); 604 605 /* 606 * Set the flush timer for EEM entries. The value is in 100ms intervals, 607 * so 100 is 10s. 608 */ 609 params->hw_flow_cache_flush_timer = 100; 610 611 if (!dparms) { 612 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 613 params->rx_max_action_entry_sz_in_bits = 614 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 615 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 616 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS; 617 618 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 619 params->tx_max_action_entry_sz_in_bits = 620 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 621 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 622 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS; 623 } else { 624 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 625 params->rx_max_action_entry_sz_in_bits = 626 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 627 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 628 params->rx_num_flows_in_k = 629 dparms->ext_flow_db_num_entries / 1024; 630 631 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 632 params->tx_max_action_entry_sz_in_bits = 633 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 634 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 635 params->tx_num_flows_in_k = 636 dparms->ext_flow_db_num_entries / 1024; 637 } 638 BNXT_TF_DBG(INFO, "Table Scope initialized with %uK flows.\n", 639 params->rx_num_flows_in_k); 640 } 641 642 /* Initialize Extended Exact Match host memory. */ 643 static int32_t 644 ulp_eem_tbl_scope_init(struct bnxt *bp) 645 { 646 struct tf_alloc_tbl_scope_parms params = {0}; 647 struct bnxt_ulp_device_params *dparms; 648 enum bnxt_ulp_flow_mem_type mtype; 649 uint32_t dev_id; 650 int rc; 651 652 /* Get the dev specific number of flows that needed to be supported. */ 653 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 654 BNXT_TF_DBG(ERR, "Invalid device id\n"); 655 return -EINVAL; 656 } 657 658 dparms = bnxt_ulp_device_params_get(dev_id); 659 if (!dparms) { 660 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 661 return -ENODEV; 662 } 663 664 if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype)) 665 return -EINVAL; 666 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 667 BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n"); 668 return 0; 669 } 670 671 bnxt_init_tbl_scope_parms(bp, ¶ms); 672 rc = tf_alloc_tbl_scope(&bp->tfp, ¶ms); 673 if (rc) { 674 BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n", 675 rc); 676 return rc; 677 } 678 rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id); 679 if (rc) { 680 BNXT_TF_DBG(ERR, "Unable to set table scope id\n"); 681 return rc; 682 } 683 684 return 0; 685 } 686 687 /* Free Extended Exact Match host memory */ 688 static int32_t 689 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 690 { 691 struct tf_free_tbl_scope_parms params = {0}; 692 struct tf *tfp; 693 int32_t rc = 0; 694 struct bnxt_ulp_device_params *dparms; 695 enum bnxt_ulp_flow_mem_type mtype; 696 uint32_t dev_id; 697 698 if (!ulp_ctx || !ulp_ctx->cfg_data) 699 return -EINVAL; 700 701 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO); 702 if (!tfp) { 703 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n"); 704 return -EINVAL; 705 } 706 707 /* Get the dev specific number of flows that needed to be supported. */ 708 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 709 BNXT_TF_DBG(ERR, "Invalid device id\n"); 710 return -EINVAL; 711 } 712 713 dparms = bnxt_ulp_device_params_get(dev_id); 714 if (!dparms) { 715 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 716 return -ENODEV; 717 } 718 719 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype)) 720 return -EINVAL; 721 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 722 BNXT_TF_DBG(INFO, "Table Scope free is not required\n"); 723 return 0; 724 } 725 726 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, ¶ms.tbl_scope_id); 727 if (rc) { 728 BNXT_TF_DBG(ERR, "Failed to get the table scope id\n"); 729 return -EINVAL; 730 } 731 732 rc = tf_free_tbl_scope(tfp, ¶ms); 733 if (rc) { 734 BNXT_TF_DBG(ERR, "Unable to free table scope\n"); 735 return -EINVAL; 736 } 737 return rc; 738 } 739 740 /* The function to free and deinit the ulp context data. */ 741 static int32_t 742 ulp_ctx_deinit(struct bnxt *bp, 743 struct bnxt_ulp_session_state *session) 744 { 745 /* close the tf session */ 746 ulp_ctx_session_close(bp, session); 747 748 /* The shared session must be closed last. */ 749 ulp_ctx_shared_session_close(bp, session); 750 751 /* Free the contents */ 752 if (session->cfg_data) { 753 rte_free(session->cfg_data); 754 bp->ulp_ctx->cfg_data = NULL; 755 session->cfg_data = NULL; 756 } 757 return 0; 758 } 759 760 /* The function to allocate and initialize the ulp context data. */ 761 static int32_t 762 ulp_ctx_init(struct bnxt *bp, 763 struct bnxt_ulp_session_state *session) 764 { 765 struct bnxt_ulp_data *ulp_data; 766 int32_t rc = 0; 767 enum bnxt_ulp_device_id devid; 768 769 /* Initialize the context entries list */ 770 bnxt_ulp_cntxt_list_init(); 771 772 /* Add the context to the context entries list */ 773 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 774 if (rc) { 775 BNXT_TF_DBG(ERR, "Failed to add the context list entry\n"); 776 return -ENOMEM; 777 } 778 779 /* Allocate memory to hold ulp context data. */ 780 ulp_data = rte_zmalloc("bnxt_ulp_data", 781 sizeof(struct bnxt_ulp_data), 0); 782 if (!ulp_data) { 783 BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n"); 784 return -ENOMEM; 785 } 786 787 /* Increment the ulp context data reference count usage. */ 788 bp->ulp_ctx->cfg_data = ulp_data; 789 session->cfg_data = ulp_data; 790 ulp_data->ref_cnt++; 791 ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED; 792 793 rc = bnxt_ulp_devid_get(bp, &devid); 794 if (rc) { 795 BNXT_TF_DBG(ERR, "Unable to determine device for ULP init.\n"); 796 goto error_deinit; 797 } 798 799 rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid); 800 if (rc) { 801 BNXT_TF_DBG(ERR, "Unable to set device for ULP init.\n"); 802 goto error_deinit; 803 } 804 805 rc = bnxt_ulp_cntxt_app_id_set(bp->ulp_ctx, bp->app_id); 806 if (rc) { 807 BNXT_TF_DBG(ERR, "Unable to set app_id for ULP init.\n"); 808 goto error_deinit; 809 } 810 811 rc = bnxt_ulp_cntxt_app_caps_init(bp->ulp_ctx, bp->app_id, devid); 812 if (rc) { 813 BNXT_TF_DBG(ERR, "Unable to set caps for app(%x)/dev(%x)\n", 814 bp->app_id, devid); 815 goto error_deinit; 816 } 817 818 /* 819 * Shared session must be created before first regular session but after 820 * the ulp_ctx is valid. 821 */ 822 rc = ulp_ctx_shared_session_open(bp, session); 823 if (rc) { 824 BNXT_TF_DBG(ERR, "Unable to open shared session (%d)\n", rc); 825 goto error_deinit; 826 } 827 828 /* Open the ulp session. */ 829 rc = ulp_ctx_session_open(bp, session); 830 if (rc) 831 goto error_deinit; 832 833 ulp_tun_tbl_init(ulp_data->tun_tbl); 834 835 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp); 836 return rc; 837 838 error_deinit: 839 session->session_opened = 1; 840 (void)ulp_ctx_deinit(bp, session); 841 return rc; 842 } 843 844 /* The function to initialize ulp dparms with devargs */ 845 static int32_t 846 ulp_dparms_init(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 847 { 848 struct bnxt_ulp_device_params *dparms; 849 uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST; 850 851 if (!bp->max_num_kflows) { 852 /* Defaults to Internal */ 853 bnxt_ulp_cntxt_mem_type_set(ulp_ctx, 854 BNXT_ULP_FLOW_MEM_TYPE_INT); 855 return 0; 856 } 857 858 /* The max_num_kflows were set, so move to external */ 859 if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT)) 860 return -EINVAL; 861 862 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 863 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 864 return -EINVAL; 865 } 866 867 dparms = bnxt_ulp_device_params_get(dev_id); 868 if (!dparms) { 869 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n"); 870 return -EINVAL; 871 } 872 873 /* num_flows = max_num_kflows * 1024 */ 874 dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024; 875 /* GFID = 2 * num_flows */ 876 dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2; 877 BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n", 878 dparms->ext_flow_db_num_entries); 879 880 return 0; 881 } 882 883 /* The function to initialize bp flags with truflow features */ 884 static int32_t 885 ulp_dparms_dev_port_intf_update(struct bnxt *bp, 886 struct bnxt_ulp_context *ulp_ctx) 887 { 888 enum bnxt_ulp_flow_mem_type mtype; 889 890 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype)) 891 return -EINVAL; 892 /* Update the bp flag with gfid flag */ 893 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT) 894 bp->flags |= BNXT_FLAG_GFID_ENABLE; 895 896 return 0; 897 } 898 899 static int32_t 900 ulp_ctx_attach(struct bnxt *bp, 901 struct bnxt_ulp_session_state *session) 902 { 903 int32_t rc = 0; 904 uint32_t flags, dev_id = BNXT_ULP_DEVICE_ID_LAST; 905 uint8_t app_id; 906 907 /* Increment the ulp context data reference count usage. */ 908 bp->ulp_ctx->cfg_data = session->cfg_data; 909 bp->ulp_ctx->cfg_data->ref_cnt++; 910 911 /* update the session details in bnxt tfp */ 912 bp->tfp.session = session->g_tfp->session; 913 914 /* Add the context to the context entries list */ 915 rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx); 916 if (rc) { 917 BNXT_TF_DBG(ERR, "Failed to add the context list entry\n"); 918 return -EINVAL; 919 } 920 921 /* 922 * The supported flag will be set during the init. Use it now to 923 * know if we should go through the attach. 924 */ 925 rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id); 926 if (rc) { 927 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n"); 928 return -EINVAL; 929 } 930 931 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 932 if (rc) { 933 BNXT_TF_DBG(ERR, "Unable do get the dev_id.\n"); 934 return -EINVAL; 935 } 936 937 flags = bp->ulp_ctx->cfg_data->ulp_flags; 938 if (ULP_APP_DEV_UNSUPPORTED_ENABLED(flags)) { 939 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n", 940 app_id, dev_id); 941 return -EINVAL; 942 } 943 944 /* Create a TF Client */ 945 rc = ulp_ctx_session_open(bp, session); 946 if (rc) { 947 PMD_DRV_LOG(ERR, "Failed to open ctxt session, rc:%d\n", rc); 948 bp->tfp.session = NULL; 949 return rc; 950 } 951 952 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp); 953 return rc; 954 } 955 956 static void 957 ulp_ctx_detach(struct bnxt *bp) 958 { 959 if (bp->tfp.session) { 960 tf_close_session(&bp->tfp); 961 bp->tfp.session = NULL; 962 } 963 } 964 965 /* 966 * Initialize the state of an ULP session. 967 * If the state of an ULP session is not initialized, set it's state to 968 * initialized. If the state is already initialized, do nothing. 969 */ 970 static void 971 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init) 972 { 973 pthread_mutex_lock(&session->bnxt_ulp_mutex); 974 975 if (!session->bnxt_ulp_init) { 976 session->bnxt_ulp_init = true; 977 *init = false; 978 } else { 979 *init = true; 980 } 981 982 pthread_mutex_unlock(&session->bnxt_ulp_mutex); 983 } 984 985 /* 986 * Check if an ULP session is already allocated for a specific PCI 987 * domain & bus. If it is already allocated simply return the session 988 * pointer, otherwise allocate a new session. 989 */ 990 static struct bnxt_ulp_session_state * 991 ulp_get_session(struct rte_pci_addr *pci_addr) 992 { 993 struct bnxt_ulp_session_state *session; 994 995 STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) { 996 if (session->pci_info.domain == pci_addr->domain && 997 session->pci_info.bus == pci_addr->bus) { 998 return session; 999 } 1000 } 1001 return NULL; 1002 } 1003 1004 /* 1005 * Allocate and Initialize an ULP session and set it's state to INITIALIZED. 1006 * If it's already initialized simply return the already existing session. 1007 */ 1008 static struct bnxt_ulp_session_state * 1009 ulp_session_init(struct bnxt *bp, 1010 bool *init) 1011 { 1012 struct rte_pci_device *pci_dev; 1013 struct rte_pci_addr *pci_addr; 1014 struct bnxt_ulp_session_state *session; 1015 int rc = 0; 1016 1017 if (!bp) 1018 return NULL; 1019 1020 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 1021 pci_addr = &pci_dev->addr; 1022 1023 pthread_mutex_lock(&bnxt_ulp_global_mutex); 1024 1025 session = ulp_get_session(pci_addr); 1026 if (!session) { 1027 /* Not Found the session Allocate a new one */ 1028 session = rte_zmalloc("bnxt_ulp_session", 1029 sizeof(struct bnxt_ulp_session_state), 1030 0); 1031 if (!session) { 1032 BNXT_TF_DBG(ERR, 1033 "Allocation failed for bnxt_ulp_session\n"); 1034 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1035 return NULL; 1036 1037 } else { 1038 /* Add it to the queue */ 1039 session->pci_info.domain = pci_addr->domain; 1040 session->pci_info.bus = pci_addr->bus; 1041 rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL); 1042 if (rc) { 1043 BNXT_TF_DBG(ERR, "mutex create failed\n"); 1044 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1045 return NULL; 1046 } 1047 STAILQ_INSERT_TAIL(&bnxt_ulp_session_list, 1048 session, next); 1049 } 1050 } 1051 ulp_context_initialized(session, init); 1052 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1053 return session; 1054 } 1055 1056 /* 1057 * When a device is closed, remove it's associated session from the global 1058 * session list. 1059 */ 1060 static void 1061 ulp_session_deinit(struct bnxt_ulp_session_state *session) 1062 { 1063 if (!session) 1064 return; 1065 1066 if (!session->cfg_data) { 1067 pthread_mutex_lock(&bnxt_ulp_global_mutex); 1068 STAILQ_REMOVE(&bnxt_ulp_session_list, session, 1069 bnxt_ulp_session_state, next); 1070 pthread_mutex_destroy(&session->bnxt_ulp_mutex); 1071 rte_free(session); 1072 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1073 } 1074 } 1075 1076 /* 1077 * Internal api to enable NAT feature. 1078 * Set set_flag to 1 to set the value or zero to reset the value. 1079 * returns 0 on success. 1080 */ 1081 static int32_t 1082 bnxt_ulp_global_cfg_update(struct bnxt *bp, 1083 enum tf_dir dir, 1084 enum tf_global_config_type type, 1085 uint32_t offset, 1086 uint32_t value, 1087 uint32_t set_flag) 1088 { 1089 uint32_t global_cfg = 0; 1090 int rc; 1091 struct tf_global_cfg_parms parms = { 0 }; 1092 1093 /* Initialize the params */ 1094 parms.dir = dir, 1095 parms.type = type, 1096 parms.offset = offset, 1097 parms.config = (uint8_t *)&global_cfg, 1098 parms.config_sz_in_bytes = sizeof(global_cfg); 1099 1100 rc = tf_get_global_cfg(&bp->tfp, &parms); 1101 if (rc) { 1102 BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n", 1103 type, rc); 1104 return rc; 1105 } 1106 1107 if (set_flag) 1108 global_cfg |= value; 1109 else 1110 global_cfg &= ~value; 1111 1112 /* SET the register RE_CFA_REG_ACT_TECT */ 1113 rc = tf_set_global_cfg(&bp->tfp, &parms); 1114 if (rc) { 1115 BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n", 1116 type, rc); 1117 return rc; 1118 } 1119 return rc; 1120 } 1121 1122 /* Internal function to delete all the flows belonging to the given port */ 1123 static void 1124 bnxt_ulp_flush_port_flows(struct bnxt *bp) 1125 { 1126 uint16_t func_id; 1127 1128 /* it is assumed that port is either TVF or PF */ 1129 if (ulp_port_db_port_func_id_get(bp->ulp_ctx, 1130 bp->eth_dev->data->port_id, 1131 &func_id)) { 1132 BNXT_TF_DBG(ERR, "Invalid argument\n"); 1133 return; 1134 } 1135 (void)ulp_flow_db_function_flow_flush(bp->ulp_ctx, func_id); 1136 } 1137 1138 /* Internal function to delete the VFR default flows */ 1139 static void 1140 bnxt_ulp_destroy_vfr_default_rules(struct bnxt *bp, bool global) 1141 { 1142 struct bnxt_ulp_vfr_rule_info *info; 1143 uint16_t port_id; 1144 struct rte_eth_dev *vfr_eth_dev; 1145 struct bnxt_representor *vfr_bp; 1146 1147 if (!BNXT_TRUFLOW_EN(bp) || BNXT_ETH_DEV_IS_REPRESENTOR(bp->eth_dev)) 1148 return; 1149 1150 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 1151 return; 1152 1153 /* Delete default rules for all ports */ 1154 for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { 1155 info = &bp->ulp_ctx->cfg_data->vfr_rule_info[port_id]; 1156 if (!info->valid) 1157 continue; 1158 1159 if (!global && info->parent_port_id != 1160 bp->eth_dev->data->port_id) 1161 continue; 1162 1163 /* Destroy the flows */ 1164 ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id); 1165 /* Clean up the tx action pointer */ 1166 vfr_eth_dev = &rte_eth_devices[port_id]; 1167 if (vfr_eth_dev) { 1168 vfr_bp = vfr_eth_dev->data->dev_private; 1169 vfr_bp->vfr_tx_cfa_action = 0; 1170 } 1171 memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info)); 1172 } 1173 } 1174 1175 /* 1176 * When a port is deinit'ed by dpdk. This function is called 1177 * and this function clears the ULP context and rest of the 1178 * infrastructure associated with it. 1179 */ 1180 static void 1181 bnxt_ulp_deinit(struct bnxt *bp, 1182 struct bnxt_ulp_session_state *session) 1183 { 1184 bool ha_enabled; 1185 1186 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 1187 return; 1188 1189 ha_enabled = bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx); 1190 if (ha_enabled && session->session_opened) { 1191 int32_t rc = ulp_ha_mgr_close(bp->ulp_ctx); 1192 if (rc) 1193 BNXT_TF_DBG(ERR, "Failed to close HA (%d)\n", rc); 1194 } 1195 1196 /* clean up default flows */ 1197 bnxt_ulp_destroy_df_rules(bp, true); 1198 1199 /* clean up default VFR flows */ 1200 bnxt_ulp_destroy_vfr_default_rules(bp, true); 1201 1202 /* clean up regular flows */ 1203 ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR); 1204 1205 /* cleanup the eem table scope */ 1206 ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx); 1207 1208 /* cleanup the flow database */ 1209 ulp_flow_db_deinit(bp->ulp_ctx); 1210 1211 /* Delete the Mark database */ 1212 ulp_mark_db_deinit(bp->ulp_ctx); 1213 1214 /* cleanup the ulp mapper */ 1215 ulp_mapper_deinit(bp->ulp_ctx); 1216 1217 /* Delete the Flow Counter Manager */ 1218 ulp_fc_mgr_deinit(bp->ulp_ctx); 1219 1220 /* Delete the Port database */ 1221 ulp_port_db_deinit(bp->ulp_ctx); 1222 1223 /* Disable NAT feature */ 1224 (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 1225 TF_TUNNEL_ENCAP_NAT, 1226 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 1227 1228 (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 1229 TF_TUNNEL_ENCAP_NAT, 1230 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 1231 1232 /* free the flow db lock */ 1233 pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock); 1234 1235 if (ha_enabled) 1236 ulp_ha_mgr_deinit(bp->ulp_ctx); 1237 1238 /* Delete the ulp context and tf session and free the ulp context */ 1239 ulp_ctx_deinit(bp, session); 1240 BNXT_TF_DBG(DEBUG, "ulp ctx has been deinitialized\n"); 1241 } 1242 1243 /* 1244 * When a port is initialized by dpdk. This functions is called 1245 * and this function initializes the ULP context and rest of the 1246 * infrastructure associated with it. 1247 */ 1248 static int32_t 1249 bnxt_ulp_init(struct bnxt *bp, 1250 struct bnxt_ulp_session_state *session) 1251 { 1252 int rc; 1253 1254 /* Allocate and Initialize the ulp context. */ 1255 rc = ulp_ctx_init(bp, session); 1256 if (rc) { 1257 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n"); 1258 goto jump_to_error; 1259 } 1260 1261 rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL); 1262 if (rc) { 1263 BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n"); 1264 goto jump_to_error; 1265 } 1266 1267 /* Initialize ulp dparms with values devargs passed */ 1268 rc = ulp_dparms_init(bp, bp->ulp_ctx); 1269 if (rc) { 1270 BNXT_TF_DBG(ERR, "Failed to initialize the dparms\n"); 1271 goto jump_to_error; 1272 } 1273 1274 /* create the port database */ 1275 rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt); 1276 if (rc) { 1277 BNXT_TF_DBG(ERR, "Failed to create the port database\n"); 1278 goto jump_to_error; 1279 } 1280 1281 /* Create the Mark database. */ 1282 rc = ulp_mark_db_init(bp->ulp_ctx); 1283 if (rc) { 1284 BNXT_TF_DBG(ERR, "Failed to create the mark database\n"); 1285 goto jump_to_error; 1286 } 1287 1288 /* Create the flow database. */ 1289 rc = ulp_flow_db_init(bp->ulp_ctx); 1290 if (rc) { 1291 BNXT_TF_DBG(ERR, "Failed to create the flow database\n"); 1292 goto jump_to_error; 1293 } 1294 1295 /* Create the eem table scope. */ 1296 rc = ulp_eem_tbl_scope_init(bp); 1297 if (rc) { 1298 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n"); 1299 goto jump_to_error; 1300 } 1301 1302 rc = ulp_mapper_init(bp->ulp_ctx); 1303 if (rc) { 1304 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n"); 1305 goto jump_to_error; 1306 } 1307 1308 rc = ulp_fc_mgr_init(bp->ulp_ctx); 1309 if (rc) { 1310 BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n"); 1311 goto jump_to_error; 1312 } 1313 1314 /* 1315 * Enable NAT feature. Set the global configuration register 1316 * Tunnel encap to enable NAT with the reuse of existing inner 1317 * L2 header smac and dmac 1318 */ 1319 rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 1320 TF_TUNNEL_ENCAP_NAT, 1321 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 1322 if (rc) { 1323 BNXT_TF_DBG(ERR, "Failed to set rx global configuration\n"); 1324 goto jump_to_error; 1325 } 1326 1327 rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 1328 TF_TUNNEL_ENCAP_NAT, 1329 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 1330 if (rc) { 1331 BNXT_TF_DBG(ERR, "Failed to set tx global configuration\n"); 1332 goto jump_to_error; 1333 } 1334 1335 if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) { 1336 rc = ulp_ha_mgr_init(bp->ulp_ctx); 1337 if (rc) { 1338 BNXT_TF_DBG(ERR, "Failed to initialize HA %d\n", rc); 1339 goto jump_to_error; 1340 } 1341 rc = ulp_ha_mgr_open(bp->ulp_ctx); 1342 if (rc) { 1343 BNXT_TF_DBG(ERR, "Failed to Process HA Open %d\n", rc); 1344 goto jump_to_error; 1345 } 1346 } 1347 BNXT_TF_DBG(DEBUG, "ulp ctx has been initialized\n"); 1348 return rc; 1349 1350 jump_to_error: 1351 bnxt_ulp_deinit(bp, session); 1352 return rc; 1353 } 1354 1355 /* 1356 * When a port is initialized by dpdk. This functions sets up 1357 * the port specific details. 1358 */ 1359 int32_t 1360 bnxt_ulp_port_init(struct bnxt *bp) 1361 { 1362 struct bnxt_ulp_session_state *session; 1363 bool initialized; 1364 enum bnxt_ulp_device_id devid = BNXT_ULP_DEVICE_ID_LAST; 1365 uint32_t ulp_flags; 1366 int32_t rc = 0; 1367 1368 if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) { 1369 BNXT_TF_DBG(ERR, 1370 "Skip ulp init for port: %d, not a TVF or PF\n", 1371 bp->eth_dev->data->port_id); 1372 return rc; 1373 } 1374 1375 if (!BNXT_TRUFLOW_EN(bp)) { 1376 BNXT_TF_DBG(DEBUG, 1377 "Skip ulp init for port: %d, truflow is not enabled\n", 1378 bp->eth_dev->data->port_id); 1379 return rc; 1380 } 1381 1382 if (bp->ulp_ctx) { 1383 BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n"); 1384 return rc; 1385 } 1386 1387 bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx", 1388 sizeof(struct bnxt_ulp_context), 0); 1389 if (!bp->ulp_ctx) { 1390 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n"); 1391 return -ENOMEM; 1392 } 1393 1394 /* 1395 * Multiple uplink ports can be associated with a single vswitch. 1396 * Make sure only the port that is started first will initialize 1397 * the TF session. 1398 */ 1399 session = ulp_session_init(bp, &initialized); 1400 if (!session) { 1401 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n"); 1402 rc = -EIO; 1403 goto jump_to_error; 1404 } 1405 1406 if (initialized) { 1407 /* 1408 * If ULP is already initialized for a specific domain then 1409 * simply assign the ulp context to this rte_eth_dev. 1410 */ 1411 rc = ulp_ctx_attach(bp, session); 1412 if (rc) { 1413 BNXT_TF_DBG(ERR, "Failed to attach the ulp context\n"); 1414 goto jump_to_error; 1415 } 1416 1417 /* 1418 * Attach to the shared session, must be called after the 1419 * ulp_ctx_attach in order to ensure that ulp data is available 1420 * for attaching. 1421 */ 1422 rc = ulp_ctx_shared_session_attach(bp, session); 1423 if (rc) { 1424 BNXT_TF_DBG(ERR, 1425 "Failed attach to shared session (%d)", rc); 1426 goto jump_to_error; 1427 } 1428 } else { 1429 rc = bnxt_ulp_init(bp, session); 1430 if (rc) { 1431 BNXT_TF_DBG(ERR, "Failed to initialize the ulp init\n"); 1432 goto jump_to_error; 1433 } 1434 } 1435 1436 /* Update bnxt driver flags */ 1437 rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx); 1438 if (rc) { 1439 BNXT_TF_DBG(ERR, "Failed to update driver flags\n"); 1440 goto jump_to_error; 1441 } 1442 1443 /* update the port database for the given interface */ 1444 rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev); 1445 if (rc) { 1446 BNXT_TF_DBG(ERR, "Failed to update port database\n"); 1447 goto jump_to_error; 1448 } 1449 /* create the default rules */ 1450 rc = bnxt_ulp_create_df_rules(bp); 1451 if (rc) { 1452 BNXT_TF_DBG(ERR, "Failed to create default flow\n"); 1453 goto jump_to_error; 1454 } 1455 1456 rc = bnxt_ulp_devid_get(bp, &devid); 1457 if (rc) { 1458 BNXT_TF_DBG(ERR, "Unable to determine device for ULP port init.\n"); 1459 goto jump_to_error; 1460 } 1461 1462 if (devid != BNXT_ULP_DEVICE_ID_THOR && BNXT_ACCUM_STATS_EN(bp)) 1463 bp->ulp_ctx->cfg_data->accum_stats = true; 1464 1465 BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port init, accum_stats:%d\n", 1466 bp->eth_dev->data->port_id, 1467 bp->ulp_ctx->cfg_data->accum_stats); 1468 1469 /* set the unicast mode */ 1470 if (bnxt_ulp_cntxt_ptr2_ulp_flags_get(bp->ulp_ctx, &ulp_flags)) { 1471 BNXT_TF_DBG(ERR, "Error in getting ULP context flags\n"); 1472 goto jump_to_error; 1473 } 1474 if (ulp_flags & BNXT_ULP_APP_UNICAST_ONLY) { 1475 if (bnxt_pmd_set_unicast_rxmask(bp->eth_dev)) { 1476 BNXT_TF_DBG(ERR, "Error in setting unicast rxmode\n"); 1477 goto jump_to_error; 1478 } 1479 } 1480 1481 return rc; 1482 1483 jump_to_error: 1484 bnxt_ulp_port_deinit(bp); 1485 return rc; 1486 } 1487 1488 /* 1489 * When a port is de-initialized by dpdk. This functions clears up 1490 * the port specific details. 1491 */ 1492 void 1493 bnxt_ulp_port_deinit(struct bnxt *bp) 1494 { 1495 struct bnxt_ulp_session_state *session; 1496 struct rte_pci_device *pci_dev; 1497 struct rte_pci_addr *pci_addr; 1498 1499 if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) { 1500 BNXT_TF_DBG(ERR, 1501 "Skip ULP deinit port:%d, not a TVF or PF\n", 1502 bp->eth_dev->data->port_id); 1503 return; 1504 } 1505 1506 if (!BNXT_TRUFLOW_EN(bp)) { 1507 BNXT_TF_DBG(DEBUG, 1508 "Skip ULP deinit for port:%d, truflow is not enabled\n", 1509 bp->eth_dev->data->port_id); 1510 return; 1511 } 1512 1513 if (!bp->ulp_ctx) { 1514 BNXT_TF_DBG(DEBUG, "ulp ctx already de-allocated\n"); 1515 return; 1516 } 1517 1518 BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n", 1519 bp->eth_dev->data->port_id); 1520 1521 /* Free the ulp context in the context entry list */ 1522 bnxt_ulp_cntxt_list_del(bp->ulp_ctx); 1523 1524 /* Get the session details */ 1525 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 1526 pci_addr = &pci_dev->addr; 1527 pthread_mutex_lock(&bnxt_ulp_global_mutex); 1528 session = ulp_get_session(pci_addr); 1529 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1530 1531 /* session not found then just exit */ 1532 if (!session) { 1533 /* Free the ulp context */ 1534 rte_free(bp->ulp_ctx); 1535 bp->ulp_ctx = NULL; 1536 return; 1537 } 1538 1539 /* Check the reference count to deinit or deattach*/ 1540 if (bp->ulp_ctx->cfg_data && bp->ulp_ctx->cfg_data->ref_cnt) { 1541 bp->ulp_ctx->cfg_data->ref_cnt--; 1542 if (bp->ulp_ctx->cfg_data->ref_cnt) { 1543 /* free the port details */ 1544 /* Free the default flow rule associated to this port */ 1545 bnxt_ulp_destroy_df_rules(bp, false); 1546 bnxt_ulp_destroy_vfr_default_rules(bp, false); 1547 1548 /* free flows associated with this port */ 1549 bnxt_ulp_flush_port_flows(bp); 1550 1551 /* close the session associated with this port */ 1552 ulp_ctx_detach(bp); 1553 1554 /* always detach/close shared after the session. */ 1555 ulp_ctx_shared_session_detach(bp); 1556 } else { 1557 /* Perform ulp ctx deinit */ 1558 bnxt_ulp_deinit(bp, session); 1559 } 1560 } 1561 1562 /* clean up the session */ 1563 ulp_session_deinit(session); 1564 1565 /* Free the ulp context */ 1566 rte_free(bp->ulp_ctx); 1567 bp->ulp_ctx = NULL; 1568 } 1569 1570 /* Below are the access functions to access internal data of ulp context. */ 1571 /* Function to set the Mark DB into the context */ 1572 int32_t 1573 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx, 1574 struct bnxt_ulp_mark_tbl *mark_tbl) 1575 { 1576 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1577 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1578 return -EINVAL; 1579 } 1580 1581 ulp_ctx->cfg_data->mark_tbl = mark_tbl; 1582 1583 return 0; 1584 } 1585 1586 /* Function to retrieve the Mark DB from the context. */ 1587 struct bnxt_ulp_mark_tbl * 1588 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx) 1589 { 1590 if (!ulp_ctx || !ulp_ctx->cfg_data) 1591 return NULL; 1592 1593 return ulp_ctx->cfg_data->mark_tbl; 1594 } 1595 1596 bool 1597 bnxt_ulp_cntxt_shared_session_enabled(struct bnxt_ulp_context *ulp_ctx) 1598 { 1599 return ULP_SHARED_SESSION_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags); 1600 } 1601 1602 int32_t 1603 bnxt_ulp_cntxt_app_id_set(struct bnxt_ulp_context *ulp_ctx, uint8_t app_id) 1604 { 1605 if (!ulp_ctx) 1606 return -EINVAL; 1607 ulp_ctx->cfg_data->app_id = app_id; 1608 return 0; 1609 } 1610 1611 int32_t 1612 bnxt_ulp_cntxt_app_id_get(struct bnxt_ulp_context *ulp_ctx, uint8_t *app_id) 1613 { 1614 /* Default APP id is zero */ 1615 if (!ulp_ctx || !app_id) 1616 return -EINVAL; 1617 *app_id = ulp_ctx->cfg_data->app_id; 1618 return 0; 1619 } 1620 1621 /* Function to set the device id of the hardware. */ 1622 int32_t 1623 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx, 1624 uint32_t dev_id) 1625 { 1626 if (ulp_ctx && ulp_ctx->cfg_data) { 1627 ulp_ctx->cfg_data->dev_id = dev_id; 1628 return 0; 1629 } 1630 1631 return -EINVAL; 1632 } 1633 1634 /* Function to get the device id of the hardware. */ 1635 int32_t 1636 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx, 1637 uint32_t *dev_id) 1638 { 1639 if (ulp_ctx && ulp_ctx->cfg_data) { 1640 *dev_id = ulp_ctx->cfg_data->dev_id; 1641 return 0; 1642 } 1643 *dev_id = BNXT_ULP_DEVICE_ID_LAST; 1644 BNXT_TF_DBG(ERR, "Failed to read dev_id from ulp ctxt\n"); 1645 return -EINVAL; 1646 } 1647 1648 int32_t 1649 bnxt_ulp_cntxt_mem_type_set(struct bnxt_ulp_context *ulp_ctx, 1650 enum bnxt_ulp_flow_mem_type mem_type) 1651 { 1652 if (ulp_ctx && ulp_ctx->cfg_data) { 1653 ulp_ctx->cfg_data->mem_type = mem_type; 1654 return 0; 1655 } 1656 BNXT_TF_DBG(ERR, "Failed to write mem_type in ulp ctxt\n"); 1657 return -EINVAL; 1658 } 1659 1660 int32_t 1661 bnxt_ulp_cntxt_mem_type_get(struct bnxt_ulp_context *ulp_ctx, 1662 enum bnxt_ulp_flow_mem_type *mem_type) 1663 { 1664 if (ulp_ctx && ulp_ctx->cfg_data) { 1665 *mem_type = ulp_ctx->cfg_data->mem_type; 1666 return 0; 1667 } 1668 *mem_type = BNXT_ULP_FLOW_MEM_TYPE_LAST; 1669 BNXT_TF_DBG(ERR, "Failed to read mem_type in ulp ctxt\n"); 1670 return -EINVAL; 1671 } 1672 1673 /* Function to get the table scope id of the EEM table. */ 1674 int32_t 1675 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx, 1676 uint32_t *tbl_scope_id) 1677 { 1678 if (ulp_ctx && ulp_ctx->cfg_data) { 1679 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id; 1680 return 0; 1681 } 1682 1683 return -EINVAL; 1684 } 1685 1686 /* Function to set the table scope id of the EEM table. */ 1687 int32_t 1688 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx, 1689 uint32_t tbl_scope_id) 1690 { 1691 if (ulp_ctx && ulp_ctx->cfg_data) { 1692 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id; 1693 return 0; 1694 } 1695 1696 return -EINVAL; 1697 } 1698 1699 /* Function to set the shared tfp session details from the ulp context. */ 1700 int32_t 1701 bnxt_ulp_cntxt_shared_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp) 1702 { 1703 if (!ulp) { 1704 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 1705 return -EINVAL; 1706 } 1707 1708 if (tfp == NULL) { 1709 if (ulp->cfg_data->num_shared_clients > 0) 1710 ulp->cfg_data->num_shared_clients--; 1711 } else { 1712 ulp->cfg_data->num_shared_clients++; 1713 } 1714 1715 ulp->g_shared_tfp = tfp; 1716 return 0; 1717 } 1718 1719 /* Function to get the shared tfp session details from the ulp context. */ 1720 struct tf * 1721 bnxt_ulp_cntxt_shared_tfp_get(struct bnxt_ulp_context *ulp) 1722 { 1723 if (!ulp) { 1724 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 1725 return NULL; 1726 } 1727 return ulp->g_shared_tfp; 1728 } 1729 1730 /* Function to get the number of shared clients attached */ 1731 uint8_t 1732 bnxt_ulp_cntxt_num_shared_clients_get(struct bnxt_ulp_context *ulp) 1733 { 1734 if (ulp == NULL || ulp->cfg_data == NULL) { 1735 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 1736 return 0; 1737 } 1738 return ulp->cfg_data->num_shared_clients; 1739 } 1740 1741 /* Function to set the tfp session details from the ulp context. */ 1742 int32_t 1743 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp) 1744 { 1745 if (!ulp) { 1746 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 1747 return -EINVAL; 1748 } 1749 1750 ulp->g_tfp = tfp; 1751 return 0; 1752 } 1753 1754 /* Function to get the tfp session details from the ulp context. */ 1755 struct tf * 1756 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp, 1757 enum bnxt_ulp_shared_session shared) 1758 { 1759 if (!ulp) { 1760 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 1761 return NULL; 1762 } 1763 if (shared) 1764 return ulp->g_shared_tfp; 1765 else 1766 return ulp->g_tfp; 1767 } 1768 1769 /* 1770 * Get the device table entry based on the device id. 1771 * 1772 * dev_id [in] The device id of the hardware 1773 * 1774 * Returns the pointer to the device parameters. 1775 */ 1776 struct bnxt_ulp_device_params * 1777 bnxt_ulp_device_params_get(uint32_t dev_id) 1778 { 1779 if (dev_id < BNXT_ULP_MAX_NUM_DEVICES) 1780 return &ulp_device_params[dev_id]; 1781 return NULL; 1782 } 1783 1784 /* Function to set the flow database to the ulp context. */ 1785 int32_t 1786 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx, 1787 struct bnxt_ulp_flow_db *flow_db) 1788 { 1789 if (!ulp_ctx || !ulp_ctx->cfg_data) 1790 return -EINVAL; 1791 1792 ulp_ctx->cfg_data->flow_db = flow_db; 1793 return 0; 1794 } 1795 1796 /* Function to get the flow database from the ulp context. */ 1797 struct bnxt_ulp_flow_db * 1798 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx) 1799 { 1800 if (!ulp_ctx || !ulp_ctx->cfg_data) 1801 return NULL; 1802 1803 return ulp_ctx->cfg_data->flow_db; 1804 } 1805 1806 /* Function to get the tunnel cache table info from the ulp context. */ 1807 struct bnxt_tun_cache_entry * 1808 bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx) 1809 { 1810 if (!ulp_ctx || !ulp_ctx->cfg_data) 1811 return NULL; 1812 1813 return ulp_ctx->cfg_data->tun_tbl; 1814 } 1815 1816 /* Function to get the ulp context from eth device. */ 1817 struct bnxt_ulp_context * 1818 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev) 1819 { 1820 struct bnxt *bp = (struct bnxt *)dev->data->dev_private; 1821 1822 if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) { 1823 struct bnxt_representor *vfr = dev->data->dev_private; 1824 1825 bp = vfr->parent_dev->data->dev_private; 1826 } 1827 1828 if (!bp) { 1829 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n"); 1830 return NULL; 1831 } 1832 return bp->ulp_ctx; 1833 } 1834 1835 int32_t 1836 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx, 1837 void *mapper_data) 1838 { 1839 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1840 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1841 return -EINVAL; 1842 } 1843 1844 ulp_ctx->cfg_data->mapper_data = mapper_data; 1845 return 0; 1846 } 1847 1848 void * 1849 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx) 1850 { 1851 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1852 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1853 return NULL; 1854 } 1855 1856 return ulp_ctx->cfg_data->mapper_data; 1857 } 1858 1859 /* Function to set the port database to the ulp context. */ 1860 int32_t 1861 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx, 1862 struct bnxt_ulp_port_db *port_db) 1863 { 1864 if (!ulp_ctx || !ulp_ctx->cfg_data) 1865 return -EINVAL; 1866 1867 ulp_ctx->cfg_data->port_db = port_db; 1868 return 0; 1869 } 1870 1871 /* Function to get the port database from the ulp context. */ 1872 struct bnxt_ulp_port_db * 1873 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx) 1874 { 1875 if (!ulp_ctx || !ulp_ctx->cfg_data) 1876 return NULL; 1877 1878 return ulp_ctx->cfg_data->port_db; 1879 } 1880 1881 /* Function to set the flow counter info into the context */ 1882 int32_t 1883 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx, 1884 struct bnxt_ulp_fc_info *ulp_fc_info) 1885 { 1886 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1887 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1888 return -EINVAL; 1889 } 1890 1891 ulp_ctx->cfg_data->fc_info = ulp_fc_info; 1892 1893 return 0; 1894 } 1895 1896 /* Function to retrieve the flow counter info from the context. */ 1897 struct bnxt_ulp_fc_info * 1898 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx) 1899 { 1900 if (!ulp_ctx || !ulp_ctx->cfg_data) 1901 return NULL; 1902 1903 return ulp_ctx->cfg_data->fc_info; 1904 } 1905 1906 /* Function to get the ulp flags from the ulp context. */ 1907 int32_t 1908 bnxt_ulp_cntxt_ptr2_ulp_flags_get(struct bnxt_ulp_context *ulp_ctx, 1909 uint32_t *flags) 1910 { 1911 if (!ulp_ctx || !ulp_ctx->cfg_data) 1912 return -1; 1913 1914 *flags = ulp_ctx->cfg_data->ulp_flags; 1915 return 0; 1916 } 1917 1918 /* Function to get the ulp vfr info from the ulp context. */ 1919 struct bnxt_ulp_vfr_rule_info* 1920 bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(struct bnxt_ulp_context *ulp_ctx, 1921 uint32_t port_id) 1922 { 1923 if (!ulp_ctx || !ulp_ctx->cfg_data || port_id >= RTE_MAX_ETHPORTS) 1924 return NULL; 1925 1926 return &ulp_ctx->cfg_data->vfr_rule_info[port_id]; 1927 } 1928 1929 /* Function to acquire the flow database lock from the ulp context. */ 1930 int32_t 1931 bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context *ulp_ctx) 1932 { 1933 if (!ulp_ctx || !ulp_ctx->cfg_data) 1934 return -1; 1935 1936 if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) { 1937 BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n"); 1938 return -1; 1939 } 1940 return 0; 1941 } 1942 1943 /* Function to release the flow database lock from the ulp context. */ 1944 void 1945 bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context *ulp_ctx) 1946 { 1947 if (!ulp_ctx || !ulp_ctx->cfg_data) 1948 return; 1949 1950 pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock); 1951 } 1952 1953 /* Function to set the ha info into the context */ 1954 int32_t 1955 bnxt_ulp_cntxt_ptr2_ha_info_set(struct bnxt_ulp_context *ulp_ctx, 1956 struct bnxt_ulp_ha_mgr_info *ulp_ha_info) 1957 { 1958 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) { 1959 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1960 return -EINVAL; 1961 } 1962 ulp_ctx->cfg_data->ha_info = ulp_ha_info; 1963 return 0; 1964 } 1965 1966 /* Function to retrieve the ha info from the context. */ 1967 struct bnxt_ulp_ha_mgr_info * 1968 bnxt_ulp_cntxt_ptr2_ha_info_get(struct bnxt_ulp_context *ulp_ctx) 1969 { 1970 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 1971 return NULL; 1972 return ulp_ctx->cfg_data->ha_info; 1973 } 1974 1975 bool 1976 bnxt_ulp_cntxt_ha_enabled(struct bnxt_ulp_context *ulp_ctx) 1977 { 1978 if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) 1979 return false; 1980 return !!ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags); 1981 } 1982 1983 static int32_t 1984 bnxt_ulp_cntxt_list_init(void) 1985 { 1986 /* Create the cntxt spin lock */ 1987 rte_spinlock_init(&bnxt_ulp_ctxt_lock); 1988 1989 return 0; 1990 } 1991 1992 static int32_t 1993 bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx) 1994 { 1995 struct ulp_context_list_entry *entry; 1996 1997 entry = rte_zmalloc(NULL, sizeof(struct ulp_context_list_entry), 0); 1998 if (entry == NULL) { 1999 BNXT_TF_DBG(ERR, "unable to allocate memory\n"); 2000 return -ENOMEM; 2001 } 2002 2003 rte_spinlock_lock(&bnxt_ulp_ctxt_lock); 2004 entry->ulp_ctx = ulp_ctx; 2005 TAILQ_INSERT_TAIL(&ulp_cntx_list, entry, next); 2006 rte_spinlock_unlock(&bnxt_ulp_ctxt_lock); 2007 return 0; 2008 } 2009 2010 static void 2011 bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx) 2012 { 2013 struct ulp_context_list_entry *entry, *temp; 2014 2015 rte_spinlock_lock(&bnxt_ulp_ctxt_lock); 2016 TAILQ_FOREACH_SAFE(entry, &ulp_cntx_list, next, temp) { 2017 if (entry->ulp_ctx == ulp_ctx) { 2018 TAILQ_REMOVE(&ulp_cntx_list, entry, next); 2019 rte_free(entry); 2020 break; 2021 } 2022 } 2023 rte_spinlock_unlock(&bnxt_ulp_ctxt_lock); 2024 } 2025 2026 struct bnxt_ulp_context * 2027 bnxt_ulp_cntxt_entry_acquire(void) 2028 { 2029 struct ulp_context_list_entry *entry; 2030 2031 /* take a lock and get the first ulp context available */ 2032 if (rte_spinlock_trylock(&bnxt_ulp_ctxt_lock)) { 2033 TAILQ_FOREACH(entry, &ulp_cntx_list, next) 2034 if (entry->ulp_ctx) 2035 return entry->ulp_ctx; 2036 } 2037 return NULL; 2038 } 2039 2040 void 2041 bnxt_ulp_cntxt_entry_release(void) 2042 { 2043 rte_spinlock_unlock(&bnxt_ulp_ctxt_lock); 2044 } 2045