1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2020 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 12 #include "bnxt_ulp.h" 13 #include "bnxt_tf_common.h" 14 #include "bnxt.h" 15 #include "tf_core.h" 16 #include "tf_ext_flow_handle.h" 17 18 #include "ulp_template_db_enum.h" 19 #include "ulp_template_struct.h" 20 #include "ulp_mark_mgr.h" 21 #include "ulp_fc_mgr.h" 22 #include "ulp_flow_db.h" 23 #include "ulp_mapper.h" 24 #include "ulp_port_db.h" 25 26 /* Linked list of all TF sessions. */ 27 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list = 28 STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list); 29 30 /* Mutex to synchronize bnxt_ulp_session_list operations. */ 31 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER; 32 33 /* 34 * Allow the deletion of context only for the bnxt device that 35 * created the session 36 * TBD - The implementation of the function should change to 37 * using the reference count once tf_session_attach functionality 38 * is fixed. 39 */ 40 bool 41 ulp_ctx_deinit_allowed(void *ptr) 42 { 43 struct bnxt *bp = (struct bnxt *)ptr; 44 45 if (!bp) 46 return 0; 47 48 if (&bp->tfp == bp->ulp_ctx->g_tfp) 49 return 1; 50 51 return 0; 52 } 53 54 /* 55 * Initialize an ULP session. 56 * An ULP session will contain all the resources needed to support rte flow 57 * offloads. A session is initialized as part of rte_eth_device start. 58 * A single vswitch instance can have multiple uplinks which means 59 * rte_eth_device start will be called for each of these devices. 60 * ULP session manager will make sure that a single ULP session is only 61 * initialized once. Apart from this, it also initializes MARK database, 62 * EEM table & flow database. ULP session manager also manages a list of 63 * all opened ULP sessions. 64 */ 65 static int32_t 66 ulp_ctx_session_open(struct bnxt *bp, 67 struct bnxt_ulp_session_state *session) 68 { 69 struct rte_eth_dev *ethdev = bp->eth_dev; 70 int32_t rc = 0; 71 struct tf_open_session_parms params; 72 struct tf_session_resources *resources; 73 74 memset(¶ms, 0, sizeof(params)); 75 76 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 77 params.ctrl_chan_name); 78 if (rc) { 79 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n", 80 ethdev->data->port_id, rc); 81 return rc; 82 } 83 84 params.shadow_copy = false; 85 params.device_type = TF_DEVICE_TYPE_WH; 86 resources = ¶ms.resources; 87 /** RX **/ 88 /* Identifiers */ 89 resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT] = 16; 90 resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 8; 91 resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 8; 92 resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 8; 93 94 /* Table Types */ 95 resources->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 720; 96 resources->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 720; 97 98 /* TCAMs */ 99 resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM] = 16; 100 resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 8; 101 resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 416; 102 103 /* EM */ 104 resources->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 2048; 105 106 /* EEM */ 107 resources->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1; 108 109 /** TX **/ 110 /* Identifiers */ 111 resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT] = 8; 112 resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 8; 113 resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 8; 114 resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 8; 115 116 /* Table Types */ 117 resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 16; 118 resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16; 119 120 /* ENCAP */ 121 resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 16; 122 resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 16; 123 124 /* TCAMs */ 125 resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM] = 8; 126 resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 8; 127 resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 8; 128 129 /* EM */ 130 resources->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 8; 131 132 /* EEM */ 133 resources->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1; 134 135 /* SP */ 136 resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 128; 137 138 rc = tf_open_session(&bp->tfp, ¶ms); 139 if (rc) { 140 BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n", 141 params.ctrl_chan_name, rc); 142 return -EINVAL; 143 } 144 session->session_opened = 1; 145 session->g_tfp = &bp->tfp; 146 return rc; 147 } 148 149 /* 150 * Close the ULP session. 151 * It takes the ulp context pointer. 152 */ 153 static void 154 ulp_ctx_session_close(struct bnxt *bp, 155 struct bnxt_ulp_session_state *session) 156 { 157 /* close the session in the hardware */ 158 if (session->session_opened) 159 tf_close_session(&bp->tfp); 160 session->session_opened = 0; 161 session->g_tfp = NULL; 162 bp->ulp_ctx->g_tfp = NULL; 163 } 164 165 static void 166 bnxt_init_tbl_scope_parms(struct bnxt *bp, 167 struct tf_alloc_tbl_scope_parms *params) 168 { 169 struct bnxt_ulp_device_params *dparms; 170 uint32_t dev_id; 171 int rc; 172 173 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 174 if (rc) 175 /* TBD: For now, just use default. */ 176 dparms = 0; 177 else 178 dparms = bnxt_ulp_device_params_get(dev_id); 179 180 /* 181 * Set the flush timer for EEM entries. The value is in 100ms intervals, 182 * so 100 is 10s. 183 */ 184 params->hw_flow_cache_flush_timer = 100; 185 186 if (!dparms) { 187 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 188 params->rx_max_action_entry_sz_in_bits = 189 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 190 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 191 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS; 192 params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID; 193 194 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 195 params->tx_max_action_entry_sz_in_bits = 196 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 197 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 198 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS; 199 params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID; 200 } else { 201 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 202 params->rx_max_action_entry_sz_in_bits = 203 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 204 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 205 params->rx_num_flows_in_k = dparms->flow_db_num_entries / 1024; 206 params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID; 207 208 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 209 params->tx_max_action_entry_sz_in_bits = 210 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 211 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 212 params->tx_num_flows_in_k = dparms->flow_db_num_entries / 1024; 213 params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID; 214 } 215 } 216 217 /* Initialize Extended Exact Match host memory. */ 218 static int32_t 219 ulp_eem_tbl_scope_init(struct bnxt *bp) 220 { 221 struct tf_alloc_tbl_scope_parms params = {0}; 222 uint32_t dev_id; 223 struct bnxt_ulp_device_params *dparms; 224 int rc; 225 226 /* Get the dev specific number of flows that needed to be supported. */ 227 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 228 BNXT_TF_DBG(ERR, "Invalid device id\n"); 229 return -EINVAL; 230 } 231 232 dparms = bnxt_ulp_device_params_get(dev_id); 233 if (!dparms) { 234 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 235 return -ENODEV; 236 } 237 238 if (dparms->flow_mem_type != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 239 BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n"); 240 return 0; 241 } 242 243 bnxt_init_tbl_scope_parms(bp, ¶ms); 244 245 rc = tf_alloc_tbl_scope(&bp->tfp, ¶ms); 246 if (rc) { 247 BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n", 248 rc); 249 return rc; 250 } 251 252 rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id); 253 if (rc) { 254 BNXT_TF_DBG(ERR, "Unable to set table scope id\n"); 255 return rc; 256 } 257 258 return 0; 259 } 260 261 /* Free Extended Exact Match host memory */ 262 static int32_t 263 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 264 { 265 struct tf_free_tbl_scope_parms params = {0}; 266 struct tf *tfp; 267 int32_t rc = 0; 268 struct bnxt_ulp_device_params *dparms; 269 uint32_t dev_id; 270 271 if (!ulp_ctx || !ulp_ctx->cfg_data) 272 return -EINVAL; 273 274 /* Free the resources for the last device */ 275 if (!ulp_ctx_deinit_allowed(bp)) 276 return rc; 277 278 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 279 if (!tfp) { 280 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n"); 281 return -EINVAL; 282 } 283 284 /* Get the dev specific number of flows that needed to be supported. */ 285 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 286 BNXT_TF_DBG(ERR, "Invalid device id\n"); 287 return -EINVAL; 288 } 289 290 dparms = bnxt_ulp_device_params_get(dev_id); 291 if (!dparms) { 292 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 293 return -ENODEV; 294 } 295 296 if (dparms->flow_mem_type != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 297 BNXT_TF_DBG(INFO, "Table Scope free is not required\n"); 298 return 0; 299 } 300 301 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, ¶ms.tbl_scope_id); 302 if (rc) { 303 BNXT_TF_DBG(ERR, "Failed to get the table scope id\n"); 304 return -EINVAL; 305 } 306 307 rc = tf_free_tbl_scope(tfp, ¶ms); 308 if (rc) { 309 BNXT_TF_DBG(ERR, "Unable to free table scope\n"); 310 return -EINVAL; 311 } 312 return rc; 313 } 314 315 /* The function to free and deinit the ulp context data. */ 316 static int32_t 317 ulp_ctx_deinit(struct bnxt *bp, 318 struct bnxt_ulp_session_state *session) 319 { 320 if (!session || !bp) { 321 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 322 return -EINVAL; 323 } 324 325 /* close the tf session */ 326 ulp_ctx_session_close(bp, session); 327 328 /* Free the contents */ 329 if (session->cfg_data) { 330 rte_free(session->cfg_data); 331 bp->ulp_ctx->cfg_data = NULL; 332 session->cfg_data = NULL; 333 } 334 return 0; 335 } 336 337 /* The function to allocate and initialize the ulp context data. */ 338 static int32_t 339 ulp_ctx_init(struct bnxt *bp, 340 struct bnxt_ulp_session_state *session) 341 { 342 struct bnxt_ulp_data *ulp_data; 343 int32_t rc = 0; 344 345 if (!session || !bp) { 346 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 347 return -EINVAL; 348 } 349 350 /* Allocate memory to hold ulp context data. */ 351 ulp_data = rte_zmalloc("bnxt_ulp_data", 352 sizeof(struct bnxt_ulp_data), 0); 353 if (!ulp_data) { 354 BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n"); 355 return -ENOMEM; 356 } 357 358 /* Increment the ulp context data reference count usage. */ 359 bp->ulp_ctx->cfg_data = ulp_data; 360 session->cfg_data = ulp_data; 361 ulp_data->ref_cnt++; 362 363 /* Open the ulp session. */ 364 rc = ulp_ctx_session_open(bp, session); 365 if (rc) { 366 (void)ulp_ctx_deinit(bp, session); 367 return rc; 368 } 369 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session->g_tfp); 370 return rc; 371 } 372 373 /* The function to initialize ulp dparms with devargs */ 374 static int32_t 375 ulp_dparms_init(struct bnxt *bp, 376 struct bnxt_ulp_context *ulp_ctx) 377 { 378 struct bnxt_ulp_device_params *dparms; 379 uint32_t dev_id; 380 381 if (!bp->max_num_kflows) 382 return -EINVAL; 383 384 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 385 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 386 return -EINVAL; 387 } 388 389 dparms = bnxt_ulp_device_params_get(dev_id); 390 if (!dparms) { 391 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n"); 392 return -EINVAL; 393 } 394 395 /* num_flows = max_num_kflows * 1024 */ 396 dparms->flow_db_num_entries = bp->max_num_kflows * 1024; 397 /* GFID = 2 * num_flows */ 398 dparms->mark_db_gfid_entries = dparms->flow_db_num_entries * 2; 399 BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n", 400 dparms->flow_db_num_entries); 401 402 return 0; 403 } 404 405 /* The function to initialize bp flags with truflow features */ 406 static int32_t 407 ulp_dparms_dev_port_intf_update(struct bnxt *bp, 408 struct bnxt_ulp_context *ulp_ctx) 409 { 410 struct bnxt_ulp_device_params *dparms; 411 uint32_t dev_id; 412 413 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 414 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 415 return -EINVAL; 416 } 417 418 dparms = bnxt_ulp_device_params_get(dev_id); 419 if (!dparms) { 420 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n"); 421 return -EINVAL; 422 } 423 424 /* Update the bp flag with gfid flag */ 425 if (dparms->flow_mem_type == BNXT_ULP_FLOW_MEM_TYPE_EXT) 426 bp->flags |= BNXT_FLAG_GFID_ENABLE; 427 428 return 0; 429 } 430 431 static int32_t 432 ulp_ctx_attach(struct bnxt_ulp_context *ulp_ctx, 433 struct bnxt_ulp_session_state *session) 434 { 435 if (!ulp_ctx || !session) { 436 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 437 return -EINVAL; 438 } 439 440 /* Increment the ulp context data reference count usage. */ 441 ulp_ctx->cfg_data = session->cfg_data; 442 ulp_ctx->cfg_data->ref_cnt++; 443 444 /* TBD call TF_session_attach. */ 445 ulp_ctx->g_tfp = session->g_tfp; 446 return 0; 447 } 448 449 static int32_t 450 ulp_ctx_detach(struct bnxt *bp, 451 struct bnxt_ulp_session_state *session) 452 { 453 struct bnxt_ulp_context *ulp_ctx; 454 455 if (!bp || !session) { 456 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 457 return -EINVAL; 458 } 459 ulp_ctx = bp->ulp_ctx; 460 461 if (!ulp_ctx->cfg_data) 462 return 0; 463 464 /* TBD call TF_session_detach */ 465 466 /* Increment the ulp context data reference count usage. */ 467 if (ulp_ctx->cfg_data->ref_cnt >= 1) { 468 ulp_ctx->cfg_data->ref_cnt--; 469 if (ulp_ctx_deinit_allowed(bp)) 470 ulp_ctx_deinit(bp, session); 471 ulp_ctx->cfg_data = NULL; 472 ulp_ctx->g_tfp = NULL; 473 return 0; 474 } 475 BNXT_TF_DBG(ERR, "context deatach on invalid data\n"); 476 return 0; 477 } 478 479 /* 480 * Initialize the state of an ULP session. 481 * If the state of an ULP session is not initialized, set it's state to 482 * initialized. If the state is already initialized, do nothing. 483 */ 484 static void 485 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init) 486 { 487 pthread_mutex_lock(&session->bnxt_ulp_mutex); 488 489 if (!session->bnxt_ulp_init) { 490 session->bnxt_ulp_init = true; 491 *init = false; 492 } else { 493 *init = true; 494 } 495 496 pthread_mutex_unlock(&session->bnxt_ulp_mutex); 497 } 498 499 /* 500 * Check if an ULP session is already allocated for a specific PCI 501 * domain & bus. If it is already allocated simply return the session 502 * pointer, otherwise allocate a new session. 503 */ 504 static struct bnxt_ulp_session_state * 505 ulp_get_session(struct rte_pci_addr *pci_addr) 506 { 507 struct bnxt_ulp_session_state *session; 508 509 STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) { 510 if (session->pci_info.domain == pci_addr->domain && 511 session->pci_info.bus == pci_addr->bus) { 512 return session; 513 } 514 } 515 return NULL; 516 } 517 518 /* 519 * Allocate and Initialize an ULP session and set it's state to INITIALIZED. 520 * If it's already initialized simply return the already existing session. 521 */ 522 static struct bnxt_ulp_session_state * 523 ulp_session_init(struct bnxt *bp, 524 bool *init) 525 { 526 struct rte_pci_device *pci_dev; 527 struct rte_pci_addr *pci_addr; 528 struct bnxt_ulp_session_state *session; 529 530 if (!bp) 531 return NULL; 532 533 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 534 pci_addr = &pci_dev->addr; 535 536 pthread_mutex_lock(&bnxt_ulp_global_mutex); 537 538 session = ulp_get_session(pci_addr); 539 if (!session) { 540 /* Not Found the session Allocate a new one */ 541 session = rte_zmalloc("bnxt_ulp_session", 542 sizeof(struct bnxt_ulp_session_state), 543 0); 544 if (!session) { 545 BNXT_TF_DBG(ERR, 546 "Allocation failed for bnxt_ulp_session\n"); 547 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 548 return NULL; 549 550 } else { 551 /* Add it to the queue */ 552 session->pci_info.domain = pci_addr->domain; 553 session->pci_info.bus = pci_addr->bus; 554 pthread_mutex_init(&session->bnxt_ulp_mutex, NULL); 555 STAILQ_INSERT_TAIL(&bnxt_ulp_session_list, 556 session, next); 557 } 558 } 559 ulp_context_initialized(session, init); 560 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 561 return session; 562 } 563 564 /* 565 * When a device is closed, remove it's associated session from the global 566 * session list. 567 */ 568 static void 569 ulp_session_deinit(struct bnxt_ulp_session_state *session) 570 { 571 if (!session) 572 return; 573 574 if (!session->cfg_data) { 575 pthread_mutex_lock(&bnxt_ulp_global_mutex); 576 STAILQ_REMOVE(&bnxt_ulp_session_list, session, 577 bnxt_ulp_session_state, next); 578 pthread_mutex_destroy(&session->bnxt_ulp_mutex); 579 rte_free(session); 580 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 581 } 582 } 583 584 /* 585 * When a port is initialized by dpdk. This functions is called 586 * and this function initializes the ULP context and rest of the 587 * infrastructure associated with it. 588 */ 589 int32_t 590 bnxt_ulp_init(struct bnxt *bp) 591 { 592 struct bnxt_ulp_session_state *session; 593 bool init; 594 int rc; 595 596 if (bp->ulp_ctx) { 597 BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n"); 598 return -EINVAL; 599 } 600 601 /* 602 * Multiple uplink ports can be associated with a single vswitch. 603 * Make sure only the port that is started first will initialize 604 * the TF session. 605 */ 606 session = ulp_session_init(bp, &init); 607 if (!session) { 608 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n"); 609 return -EINVAL; 610 } 611 612 bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx", 613 sizeof(struct bnxt_ulp_context), 0); 614 if (!bp->ulp_ctx) { 615 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n"); 616 ulp_session_deinit(session); 617 return -ENOMEM; 618 } 619 620 /* 621 * If ULP is already initialized for a specific domain then simply 622 * assign the ulp context to this rte_eth_dev. 623 */ 624 if (init) { 625 rc = ulp_ctx_attach(bp->ulp_ctx, session); 626 if (rc) { 627 BNXT_TF_DBG(ERR, 628 "Failed to attach the ulp context\n"); 629 ulp_session_deinit(session); 630 rte_free(bp->ulp_ctx); 631 return rc; 632 } 633 634 /* Update bnxt driver flags */ 635 rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx); 636 if (rc) { 637 BNXT_TF_DBG(ERR, "Failed to update driver flags\n"); 638 ulp_ctx_detach(bp, session); 639 ulp_session_deinit(session); 640 rte_free(bp->ulp_ctx); 641 return rc; 642 } 643 644 /* update the port database */ 645 rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev); 646 if (rc) { 647 BNXT_TF_DBG(ERR, 648 "Failed to update port database\n"); 649 ulp_ctx_detach(bp, session); 650 ulp_session_deinit(session); 651 rte_free(bp->ulp_ctx); 652 } 653 return rc; 654 } 655 656 /* Allocate and Initialize the ulp context. */ 657 rc = ulp_ctx_init(bp, session); 658 if (rc) { 659 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n"); 660 goto jump_to_error; 661 } 662 663 /* Initialize ulp dparms with values devargs passed */ 664 rc = ulp_dparms_init(bp, bp->ulp_ctx); 665 666 /* create the port database */ 667 rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt); 668 if (rc) { 669 BNXT_TF_DBG(ERR, "Failed to create the port database\n"); 670 goto jump_to_error; 671 } 672 673 /* Update bnxt driver flags */ 674 rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx); 675 if (rc) { 676 BNXT_TF_DBG(ERR, "Failed to update driver flags\n"); 677 goto jump_to_error; 678 } 679 680 /* update the port database */ 681 rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev); 682 if (rc) { 683 BNXT_TF_DBG(ERR, "Failed to update port database\n"); 684 goto jump_to_error; 685 } 686 687 /* Create the Mark database. */ 688 rc = ulp_mark_db_init(bp->ulp_ctx); 689 if (rc) { 690 BNXT_TF_DBG(ERR, "Failed to create the mark database\n"); 691 goto jump_to_error; 692 } 693 694 /* Create the flow database. */ 695 rc = ulp_flow_db_init(bp->ulp_ctx); 696 if (rc) { 697 BNXT_TF_DBG(ERR, "Failed to create the flow database\n"); 698 goto jump_to_error; 699 } 700 701 /* Create the eem table scope. */ 702 rc = ulp_eem_tbl_scope_init(bp); 703 if (rc) { 704 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n"); 705 goto jump_to_error; 706 } 707 708 rc = ulp_mapper_init(bp->ulp_ctx); 709 if (rc) { 710 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n"); 711 goto jump_to_error; 712 } 713 714 rc = ulp_fc_mgr_init(bp->ulp_ctx); 715 if (rc) { 716 BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n"); 717 goto jump_to_error; 718 } 719 720 return rc; 721 722 jump_to_error: 723 bnxt_ulp_deinit(bp); 724 return -ENOMEM; 725 } 726 727 /* Below are the access functions to access internal data of ulp context. */ 728 729 /* 730 * When a port is deinit'ed by dpdk. This function is called 731 * and this function clears the ULP context and rest of the 732 * infrastructure associated with it. 733 */ 734 void 735 bnxt_ulp_deinit(struct bnxt *bp) 736 { 737 struct bnxt_ulp_session_state *session; 738 struct rte_pci_device *pci_dev; 739 struct rte_pci_addr *pci_addr; 740 741 /* Get the session first */ 742 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 743 pci_addr = &pci_dev->addr; 744 pthread_mutex_lock(&bnxt_ulp_global_mutex); 745 session = ulp_get_session(pci_addr); 746 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 747 748 /* session not found then just exit */ 749 if (!session) 750 return; 751 752 /* clean up regular flows */ 753 ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE); 754 755 /* cleanup the eem table scope */ 756 ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx); 757 758 /* cleanup the flow database */ 759 ulp_flow_db_deinit(bp->ulp_ctx); 760 761 /* Delete the Mark database */ 762 ulp_mark_db_deinit(bp->ulp_ctx); 763 764 /* cleanup the ulp mapper */ 765 ulp_mapper_deinit(bp->ulp_ctx); 766 767 /* Delete the Flow Counter Manager */ 768 ulp_fc_mgr_deinit(bp->ulp_ctx); 769 770 /* Delete the Port database */ 771 ulp_port_db_deinit(bp->ulp_ctx); 772 773 /* Delete the ulp context and tf session */ 774 ulp_ctx_detach(bp, session); 775 776 /* Finally delete the bnxt session*/ 777 ulp_session_deinit(session); 778 779 rte_free(bp->ulp_ctx); 780 } 781 782 /* Function to set the Mark DB into the context */ 783 int32_t 784 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx, 785 struct bnxt_ulp_mark_tbl *mark_tbl) 786 { 787 if (!ulp_ctx || !ulp_ctx->cfg_data) { 788 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 789 return -EINVAL; 790 } 791 792 ulp_ctx->cfg_data->mark_tbl = mark_tbl; 793 794 return 0; 795 } 796 797 /* Function to retrieve the Mark DB from the context. */ 798 struct bnxt_ulp_mark_tbl * 799 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx) 800 { 801 if (!ulp_ctx || !ulp_ctx->cfg_data) 802 return NULL; 803 804 return ulp_ctx->cfg_data->mark_tbl; 805 } 806 807 /* Function to set the device id of the hardware. */ 808 int32_t 809 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx, 810 uint32_t dev_id) 811 { 812 if (ulp_ctx && ulp_ctx->cfg_data) { 813 ulp_ctx->cfg_data->dev_id = dev_id; 814 return 0; 815 } 816 817 return -EINVAL; 818 } 819 820 /* Function to get the device id of the hardware. */ 821 int32_t 822 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx, 823 uint32_t *dev_id) 824 { 825 if (ulp_ctx && ulp_ctx->cfg_data) { 826 *dev_id = ulp_ctx->cfg_data->dev_id; 827 return 0; 828 } 829 830 return -EINVAL; 831 } 832 833 /* Function to get the table scope id of the EEM table. */ 834 int32_t 835 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx, 836 uint32_t *tbl_scope_id) 837 { 838 if (ulp_ctx && ulp_ctx->cfg_data) { 839 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id; 840 return 0; 841 } 842 843 return -EINVAL; 844 } 845 846 /* Function to set the table scope id of the EEM table. */ 847 int32_t 848 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx, 849 uint32_t tbl_scope_id) 850 { 851 if (ulp_ctx && ulp_ctx->cfg_data) { 852 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id; 853 return 0; 854 } 855 856 return -EINVAL; 857 } 858 859 /* Function to set the tfp session details from the ulp context. */ 860 int32_t 861 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp) 862 { 863 if (!ulp) { 864 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 865 return -EINVAL; 866 } 867 868 /* TBD The tfp should be removed once tf_attach is implemented. */ 869 ulp->g_tfp = tfp; 870 return 0; 871 } 872 873 /* Function to get the tfp session details from the ulp context. */ 874 struct tf * 875 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp) 876 { 877 if (!ulp) { 878 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 879 return NULL; 880 } 881 /* TBD The tfp should be removed once tf_attach is implemented. */ 882 return ulp->g_tfp; 883 } 884 885 /* 886 * Get the device table entry based on the device id. 887 * 888 * dev_id [in] The device id of the hardware 889 * 890 * Returns the pointer to the device parameters. 891 */ 892 struct bnxt_ulp_device_params * 893 bnxt_ulp_device_params_get(uint32_t dev_id) 894 { 895 if (dev_id < BNXT_ULP_MAX_NUM_DEVICES) 896 return &ulp_device_params[dev_id]; 897 return NULL; 898 } 899 900 /* Function to set the flow database to the ulp context. */ 901 int32_t 902 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx, 903 struct bnxt_ulp_flow_db *flow_db) 904 { 905 if (!ulp_ctx || !ulp_ctx->cfg_data) 906 return -EINVAL; 907 908 ulp_ctx->cfg_data->flow_db = flow_db; 909 return 0; 910 } 911 912 /* Function to get the flow database from the ulp context. */ 913 struct bnxt_ulp_flow_db * 914 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx) 915 { 916 if (!ulp_ctx || !ulp_ctx->cfg_data) 917 return NULL; 918 919 return ulp_ctx->cfg_data->flow_db; 920 } 921 922 /* Function to get the ulp context from eth device. */ 923 struct bnxt_ulp_context * 924 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev) 925 { 926 struct bnxt *bp = (struct bnxt *)dev->data->dev_private; 927 928 if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) { 929 struct bnxt_vf_representor *vfr = dev->data->dev_private; 930 bp = vfr->parent_dev->data->dev_private; 931 } 932 933 if (!bp) { 934 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n"); 935 return NULL; 936 } 937 return bp->ulp_ctx; 938 } 939 940 int32_t 941 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx, 942 void *mapper_data) 943 { 944 if (!ulp_ctx || !ulp_ctx->cfg_data) { 945 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 946 return -EINVAL; 947 } 948 949 ulp_ctx->cfg_data->mapper_data = mapper_data; 950 return 0; 951 } 952 953 void * 954 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx) 955 { 956 if (!ulp_ctx || !ulp_ctx->cfg_data) { 957 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 958 return NULL; 959 } 960 961 return ulp_ctx->cfg_data->mapper_data; 962 } 963 964 /* Function to set the port database to the ulp context. */ 965 int32_t 966 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx, 967 struct bnxt_ulp_port_db *port_db) 968 { 969 if (!ulp_ctx || !ulp_ctx->cfg_data) 970 return -EINVAL; 971 972 ulp_ctx->cfg_data->port_db = port_db; 973 return 0; 974 } 975 976 /* Function to get the port database from the ulp context. */ 977 struct bnxt_ulp_port_db * 978 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx) 979 { 980 if (!ulp_ctx || !ulp_ctx->cfg_data) 981 return NULL; 982 983 return ulp_ctx->cfg_data->port_db; 984 } 985 986 /* Function to set the flow counter info into the context */ 987 int32_t 988 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx, 989 struct bnxt_ulp_fc_info *ulp_fc_info) 990 { 991 if (!ulp_ctx || !ulp_ctx->cfg_data) { 992 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 993 return -EINVAL; 994 } 995 996 ulp_ctx->cfg_data->fc_info = ulp_fc_info; 997 998 return 0; 999 } 1000 1001 /* Function to retrieve the flow counter info from the context. */ 1002 struct bnxt_ulp_fc_info * 1003 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx) 1004 { 1005 if (!ulp_ctx || !ulp_ctx->cfg_data) 1006 return NULL; 1007 1008 return ulp_ctx->cfg_data->fc_info; 1009 } 1010