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 12 #include "bnxt.h" 13 #include "bnxt_ulp.h" 14 #include "bnxt_tf_common.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 */ 37 bool 38 ulp_ctx_deinit_allowed(struct bnxt_ulp_context *ulp_ctx) 39 { 40 if (!ulp_ctx || !ulp_ctx->cfg_data) 41 return false; 42 43 if (!ulp_ctx->cfg_data->ref_cnt) { 44 BNXT_TF_DBG(DEBUG, "ulp ctx shall initiate deinit\n"); 45 return true; 46 } 47 48 return false; 49 } 50 51 static int32_t 52 bnxt_ulp_devid_get(struct bnxt *bp, 53 enum bnxt_ulp_device_id *ulp_dev_id) 54 { 55 if (BNXT_CHIP_P5(bp)) 56 return -EINVAL; 57 /* Assuming Whitney */ 58 *ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS; 59 60 if (BNXT_STINGRAY(bp)) 61 *ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY; 62 else 63 /* Assuming Whitney */ 64 *ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS; 65 return 0; 66 } 67 68 static int32_t 69 bnxt_ulp_tf_session_resources_get(struct bnxt *bp, 70 struct tf_session_resources *res) 71 { 72 uint32_t dev_id; 73 int32_t rc; 74 75 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 76 if (rc) { 77 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n"); 78 return -EINVAL; 79 } 80 81 switch (dev_id) { 82 case BNXT_ULP_DEVICE_ID_WH_PLUS: 83 /** RX **/ 84 /* Identifiers */ 85 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 422; 86 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 6; 87 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 192; 88 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64; 89 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 192; 90 91 /* Table Types */ 92 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192; 93 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384; 94 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023; 95 96 /* ENCAP */ 97 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 511; 98 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 63; 99 100 /* TCAMs */ 101 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = 102 422; 103 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = 104 6; 105 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960; 106 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 88; 107 108 /* EM */ 109 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 13168; 110 111 /* EEM */ 112 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1; 113 114 /* SP */ 115 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_SP_SMAC] = 255; 116 117 /** TX **/ 118 /* Identifiers */ 119 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 292; 120 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 148; 121 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 192; 122 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64; 123 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 192; 124 125 /* Table Types */ 126 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192; 127 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384; 128 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023; 129 130 /* ENCAP */ 131 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 511; 132 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 223; 133 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 255; 134 135 /* TCAMs */ 136 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = 137 292; 138 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = 139 144; 140 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960; 141 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 928; 142 143 /* EM */ 144 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 15232; 145 146 /* EEM */ 147 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1; 148 149 /* SP */ 150 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 488; 151 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = 511; 152 break; 153 case BNXT_ULP_DEVICE_ID_STINGRAY: 154 /** RX **/ 155 /* Identifiers */ 156 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 315; 157 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 6; 158 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 192; 159 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64; 160 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 192; 161 162 /* Table Types */ 163 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192; 164 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384; 165 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023; 166 167 /* ENCAP */ 168 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 511; 169 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 63; 170 171 /* TCAMs */ 172 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = 173 315; 174 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = 175 6; 176 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960; 177 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 112; 178 179 /* EM */ 180 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 13200; 181 182 /* EEM */ 183 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1; 184 185 /* SP */ 186 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_SP_SMAC] = 256; 187 188 /** TX **/ 189 /* Identifiers */ 190 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 292; 191 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 127; 192 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 192; 193 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64; 194 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 192; 195 196 /* Table Types */ 197 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192; 198 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384; 199 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023; 200 201 /* ENCAP */ 202 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 367; 203 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 223; 204 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 255; 205 206 /* TCAMs */ 207 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = 208 292; 209 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = 210 127; 211 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960; 212 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 928; 213 214 /* EM */ 215 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 15232; 216 217 /* EEM */ 218 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1; 219 220 /* SP */ 221 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 488; 222 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = 512; 223 break; 224 default: 225 return -EINVAL; 226 } 227 228 return 0; 229 } 230 231 /* 232 * Initialize an ULP session. 233 * An ULP session will contain all the resources needed to support rte flow 234 * offloads. A session is initialized as part of rte_eth_device start. 235 * A single vswitch instance can have multiple uplinks which means 236 * rte_eth_device start will be called for each of these devices. 237 * ULP session manager will make sure that a single ULP session is only 238 * initialized once. Apart from this, it also initializes MARK database, 239 * EEM table & flow database. ULP session manager also manages a list of 240 * all opened ULP sessions. 241 */ 242 static int32_t 243 ulp_ctx_session_open(struct bnxt *bp, 244 struct bnxt_ulp_session_state *session) 245 { 246 struct rte_eth_dev *ethdev = bp->eth_dev; 247 int32_t rc = 0; 248 struct tf_open_session_parms params; 249 struct tf_session_resources *resources; 250 uint32_t ulp_dev_id; 251 252 memset(¶ms, 0, sizeof(params)); 253 254 rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id, 255 params.ctrl_chan_name); 256 if (rc) { 257 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n", 258 ethdev->data->port_id, rc); 259 return rc; 260 } 261 262 params.shadow_copy = true; 263 264 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id); 265 if (rc) { 266 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n"); 267 return rc; 268 } 269 270 switch (ulp_dev_id) { 271 case BNXT_ULP_DEVICE_ID_WH_PLUS: 272 params.device_type = TF_DEVICE_TYPE_WH; 273 break; 274 case BNXT_ULP_DEVICE_ID_STINGRAY: 275 params.device_type = TF_DEVICE_TYPE_SR; 276 break; 277 default: 278 BNXT_TF_DBG(ERR, "Unable to determine device for " 279 "opening session.\n"); 280 return rc; 281 } 282 283 resources = ¶ms.resources; 284 rc = bnxt_ulp_tf_session_resources_get(bp, resources); 285 if (rc) { 286 BNXT_TF_DBG(ERR, "Unable to determine tf resources for " 287 "session open.\n"); 288 return rc; 289 } 290 291 rc = tf_open_session(&bp->tfp, ¶ms); 292 if (rc) { 293 BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n", 294 params.ctrl_chan_name, rc); 295 return -EINVAL; 296 } 297 if (!session->session_opened) { 298 session->session_opened = 1; 299 session->g_tfp = rte_zmalloc("bnxt_ulp_session_tfp", 300 sizeof(struct tf), 0); 301 session->g_tfp->session = bp->tfp.session; 302 } 303 return rc; 304 } 305 306 /* 307 * Close the ULP session. 308 * It takes the ulp context pointer. 309 */ 310 static void 311 ulp_ctx_session_close(struct bnxt *bp, 312 struct bnxt_ulp_session_state *session) 313 { 314 /* close the session in the hardware */ 315 if (session->session_opened) 316 tf_close_session(&bp->tfp); 317 session->session_opened = 0; 318 rte_free(session->g_tfp); 319 session->g_tfp = NULL; 320 } 321 322 static void 323 bnxt_init_tbl_scope_parms(struct bnxt *bp, 324 struct tf_alloc_tbl_scope_parms *params) 325 { 326 struct bnxt_ulp_device_params *dparms; 327 uint32_t dev_id; 328 int rc; 329 330 rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id); 331 if (rc) 332 /* TBD: For now, just use default. */ 333 dparms = 0; 334 else 335 dparms = bnxt_ulp_device_params_get(dev_id); 336 337 /* 338 * Set the flush timer for EEM entries. The value is in 100ms intervals, 339 * so 100 is 10s. 340 */ 341 params->hw_flow_cache_flush_timer = 100; 342 343 if (!dparms) { 344 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 345 params->rx_max_action_entry_sz_in_bits = 346 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 347 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 348 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS; 349 params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID; 350 351 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 352 params->tx_max_action_entry_sz_in_bits = 353 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 354 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 355 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS; 356 params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID; 357 } else { 358 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY; 359 params->rx_max_action_entry_sz_in_bits = 360 BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY; 361 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM; 362 params->rx_num_flows_in_k = 363 dparms->ext_flow_db_num_entries / 1024; 364 params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID; 365 366 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY; 367 params->tx_max_action_entry_sz_in_bits = 368 BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY; 369 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM; 370 params->tx_num_flows_in_k = 371 dparms->ext_flow_db_num_entries / 1024; 372 params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID; 373 } 374 BNXT_TF_DBG(INFO, "Table Scope initialized with %uK flows.\n", 375 params->rx_num_flows_in_k); 376 } 377 378 /* Initialize Extended Exact Match host memory. */ 379 static int32_t 380 ulp_eem_tbl_scope_init(struct bnxt *bp) 381 { 382 struct tf_alloc_tbl_scope_parms params = {0}; 383 struct bnxt_ulp_device_params *dparms; 384 enum bnxt_ulp_flow_mem_type mtype; 385 uint32_t dev_id; 386 int rc; 387 388 /* Get the dev specific number of flows that needed to be supported. */ 389 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 390 BNXT_TF_DBG(ERR, "Invalid device id\n"); 391 return -EINVAL; 392 } 393 394 dparms = bnxt_ulp_device_params_get(dev_id); 395 if (!dparms) { 396 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 397 return -ENODEV; 398 } 399 400 if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype)) 401 return -EINVAL; 402 403 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 404 BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n"); 405 return 0; 406 } 407 408 bnxt_init_tbl_scope_parms(bp, ¶ms); 409 410 rc = tf_alloc_tbl_scope(&bp->tfp, ¶ms); 411 if (rc) { 412 BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n", 413 rc); 414 return rc; 415 } 416 417 rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id); 418 if (rc) { 419 BNXT_TF_DBG(ERR, "Unable to set table scope id\n"); 420 return rc; 421 } 422 423 return 0; 424 } 425 426 /* Free Extended Exact Match host memory */ 427 static int32_t 428 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx) 429 { 430 struct tf_free_tbl_scope_parms params = {0}; 431 struct tf *tfp; 432 int32_t rc = 0; 433 struct bnxt_ulp_device_params *dparms; 434 enum bnxt_ulp_flow_mem_type mtype; 435 uint32_t dev_id; 436 437 if (!ulp_ctx || !ulp_ctx->cfg_data) 438 return -EINVAL; 439 440 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx); 441 if (!tfp) { 442 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n"); 443 return -EINVAL; 444 } 445 446 /* Get the dev specific number of flows that needed to be supported. */ 447 if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) { 448 BNXT_TF_DBG(ERR, "Invalid device id\n"); 449 return -EINVAL; 450 } 451 452 dparms = bnxt_ulp_device_params_get(dev_id); 453 if (!dparms) { 454 BNXT_TF_DBG(ERR, "could not fetch the device params\n"); 455 return -ENODEV; 456 } 457 458 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype)) 459 return -EINVAL; 460 if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) { 461 BNXT_TF_DBG(INFO, "Table Scope free is not required\n"); 462 return 0; 463 } 464 465 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, ¶ms.tbl_scope_id); 466 if (rc) { 467 BNXT_TF_DBG(ERR, "Failed to get the table scope id\n"); 468 return -EINVAL; 469 } 470 471 rc = tf_free_tbl_scope(tfp, ¶ms); 472 if (rc) { 473 BNXT_TF_DBG(ERR, "Unable to free table scope\n"); 474 return -EINVAL; 475 } 476 return rc; 477 } 478 479 /* The function to free and deinit the ulp context data. */ 480 static int32_t 481 ulp_ctx_deinit(struct bnxt *bp, 482 struct bnxt_ulp_session_state *session) 483 { 484 /* close the tf session */ 485 ulp_ctx_session_close(bp, session); 486 487 /* Free the contents */ 488 if (session->cfg_data) { 489 rte_free(session->cfg_data); 490 bp->ulp_ctx->cfg_data = NULL; 491 session->cfg_data = NULL; 492 } 493 return 0; 494 } 495 496 /* The function to allocate and initialize the ulp context data. */ 497 static int32_t 498 ulp_ctx_init(struct bnxt *bp, 499 struct bnxt_ulp_session_state *session) 500 { 501 struct bnxt_ulp_data *ulp_data; 502 int32_t rc = 0; 503 enum bnxt_ulp_device_id devid; 504 505 /* Allocate memory to hold ulp context data. */ 506 ulp_data = rte_zmalloc("bnxt_ulp_data", 507 sizeof(struct bnxt_ulp_data), 0); 508 if (!ulp_data) { 509 BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n"); 510 return -ENOMEM; 511 } 512 513 /* Increment the ulp context data reference count usage. */ 514 bp->ulp_ctx->cfg_data = ulp_data; 515 session->cfg_data = ulp_data; 516 ulp_data->ref_cnt++; 517 ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED; 518 519 rc = bnxt_ulp_devid_get(bp, &devid); 520 if (rc) { 521 BNXT_TF_DBG(ERR, "Unable to determine device for ULP init.\n"); 522 goto error_deinit; 523 } 524 525 rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid); 526 if (rc) { 527 BNXT_TF_DBG(ERR, "Unable to set device for ULP init.\n"); 528 goto error_deinit; 529 } 530 531 /* Open the ulp session. */ 532 rc = ulp_ctx_session_open(bp, session); 533 if (rc) 534 goto error_deinit; 535 536 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp); 537 return rc; 538 539 error_deinit: 540 session->session_opened = 1; 541 (void)ulp_ctx_deinit(bp, session); 542 return rc; 543 } 544 545 /* The function to initialize ulp dparms with devargs */ 546 static int32_t 547 ulp_dparms_init(struct bnxt *bp, 548 struct bnxt_ulp_context *ulp_ctx) 549 { 550 struct bnxt_ulp_device_params *dparms; 551 uint32_t dev_id; 552 553 if (!bp->max_num_kflows) { 554 /* Defaults to Internal */ 555 bnxt_ulp_cntxt_mem_type_set(ulp_ctx, 556 BNXT_ULP_FLOW_MEM_TYPE_INT); 557 return 0; 558 } 559 560 /* The max_num_kflows were set, so move to external */ 561 if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT)) 562 return -EINVAL; 563 564 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) { 565 BNXT_TF_DBG(DEBUG, "Failed to get device id\n"); 566 return -EINVAL; 567 } 568 569 dparms = bnxt_ulp_device_params_get(dev_id); 570 if (!dparms) { 571 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n"); 572 return -EINVAL; 573 } 574 575 /* num_flows = max_num_kflows * 1024 */ 576 dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024; 577 /* GFID = 2 * num_flows */ 578 dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2; 579 BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n", 580 dparms->ext_flow_db_num_entries); 581 582 return 0; 583 } 584 585 /* The function to initialize bp flags with truflow features */ 586 static int32_t 587 ulp_dparms_dev_port_intf_update(struct bnxt *bp, 588 struct bnxt_ulp_context *ulp_ctx) 589 { 590 enum bnxt_ulp_flow_mem_type mtype; 591 592 if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype)) 593 return -EINVAL; 594 /* Update the bp flag with gfid flag */ 595 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT) 596 bp->flags |= BNXT_FLAG_GFID_ENABLE; 597 598 return 0; 599 } 600 601 static int32_t 602 ulp_ctx_attach(struct bnxt *bp, 603 struct bnxt_ulp_session_state *session) 604 { 605 int32_t rc = 0; 606 607 /* Increment the ulp context data reference count usage. */ 608 bp->ulp_ctx->cfg_data = session->cfg_data; 609 bp->ulp_ctx->cfg_data->ref_cnt++; 610 611 /* update the session details in bnxt tfp */ 612 bp->tfp.session = session->g_tfp->session; 613 614 /* Create a TF Client */ 615 rc = ulp_ctx_session_open(bp, session); 616 if (rc) { 617 PMD_DRV_LOG(ERR, "Failed to open ctxt session, rc:%d\n", rc); 618 bp->tfp.session = NULL; 619 return rc; 620 } 621 622 bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp); 623 return rc; 624 } 625 626 static void 627 ulp_ctx_detach(struct bnxt *bp) 628 { 629 if (bp->tfp.session) { 630 tf_close_session(&bp->tfp); 631 bp->tfp.session = NULL; 632 } 633 } 634 635 /* 636 * Initialize the state of an ULP session. 637 * If the state of an ULP session is not initialized, set it's state to 638 * initialized. If the state is already initialized, do nothing. 639 */ 640 static void 641 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init) 642 { 643 pthread_mutex_lock(&session->bnxt_ulp_mutex); 644 645 if (!session->bnxt_ulp_init) { 646 session->bnxt_ulp_init = true; 647 *init = false; 648 } else { 649 *init = true; 650 } 651 652 pthread_mutex_unlock(&session->bnxt_ulp_mutex); 653 } 654 655 /* 656 * Check if an ULP session is already allocated for a specific PCI 657 * domain & bus. If it is already allocated simply return the session 658 * pointer, otherwise allocate a new session. 659 */ 660 static struct bnxt_ulp_session_state * 661 ulp_get_session(struct rte_pci_addr *pci_addr) 662 { 663 struct bnxt_ulp_session_state *session; 664 665 STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) { 666 if (session->pci_info.domain == pci_addr->domain && 667 session->pci_info.bus == pci_addr->bus) { 668 return session; 669 } 670 } 671 return NULL; 672 } 673 674 /* 675 * Allocate and Initialize an ULP session and set it's state to INITIALIZED. 676 * If it's already initialized simply return the already existing session. 677 */ 678 static struct bnxt_ulp_session_state * 679 ulp_session_init(struct bnxt *bp, 680 bool *init) 681 { 682 struct rte_pci_device *pci_dev; 683 struct rte_pci_addr *pci_addr; 684 struct bnxt_ulp_session_state *session; 685 int rc = 0; 686 687 if (!bp) 688 return NULL; 689 690 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 691 pci_addr = &pci_dev->addr; 692 693 pthread_mutex_lock(&bnxt_ulp_global_mutex); 694 695 session = ulp_get_session(pci_addr); 696 if (!session) { 697 /* Not Found the session Allocate a new one */ 698 session = rte_zmalloc("bnxt_ulp_session", 699 sizeof(struct bnxt_ulp_session_state), 700 0); 701 if (!session) { 702 BNXT_TF_DBG(ERR, 703 "Allocation failed for bnxt_ulp_session\n"); 704 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 705 return NULL; 706 707 } else { 708 /* Add it to the queue */ 709 session->pci_info.domain = pci_addr->domain; 710 session->pci_info.bus = pci_addr->bus; 711 rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL); 712 if (rc) { 713 BNXT_TF_DBG(ERR, "mutex create failed\n"); 714 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 715 return NULL; 716 } 717 STAILQ_INSERT_TAIL(&bnxt_ulp_session_list, 718 session, next); 719 } 720 } 721 ulp_context_initialized(session, init); 722 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 723 return session; 724 } 725 726 /* 727 * When a device is closed, remove it's associated session from the global 728 * session list. 729 */ 730 static void 731 ulp_session_deinit(struct bnxt_ulp_session_state *session) 732 { 733 if (!session) 734 return; 735 736 if (!session->cfg_data) { 737 pthread_mutex_lock(&bnxt_ulp_global_mutex); 738 STAILQ_REMOVE(&bnxt_ulp_session_list, session, 739 bnxt_ulp_session_state, next); 740 pthread_mutex_destroy(&session->bnxt_ulp_mutex); 741 rte_free(session); 742 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 743 } 744 } 745 746 /* 747 * Internal api to enable NAT feature. 748 * Set set_flag to 1 to set the value or zero to reset the value. 749 * returns 0 on success. 750 */ 751 static int32_t 752 bnxt_ulp_global_cfg_update(struct bnxt *bp, 753 enum tf_dir dir, 754 enum tf_global_config_type type, 755 uint32_t offset, 756 uint32_t value, 757 uint32_t set_flag) 758 { 759 uint32_t global_cfg = 0; 760 int rc; 761 struct tf_global_cfg_parms parms = { 0 }; 762 763 /* Initialize the params */ 764 parms.dir = dir, 765 parms.type = type, 766 parms.offset = offset, 767 parms.config = (uint8_t *)&global_cfg, 768 parms.config_sz_in_bytes = sizeof(global_cfg); 769 770 rc = tf_get_global_cfg(&bp->tfp, &parms); 771 if (rc) { 772 BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n", 773 type, rc); 774 return rc; 775 } 776 777 if (set_flag) 778 global_cfg |= value; 779 else 780 global_cfg &= ~value; 781 782 /* SET the register RE_CFA_REG_ACT_TECT */ 783 rc = tf_set_global_cfg(&bp->tfp, &parms); 784 if (rc) { 785 BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n", 786 type, rc); 787 return rc; 788 } 789 return rc; 790 } 791 792 /* Internal function to delete all the flows belonging to the given port */ 793 static void 794 bnxt_ulp_flush_port_flows(struct bnxt *bp) 795 { 796 uint16_t func_id; 797 798 /* it is assumed that port is either TVF or PF */ 799 if (ulp_port_db_port_func_id_get(bp->ulp_ctx, 800 bp->eth_dev->data->port_id, 801 &func_id)) { 802 BNXT_TF_DBG(ERR, "Invalid argument\n"); 803 return; 804 } 805 (void)ulp_flow_db_function_flow_flush(bp->ulp_ctx, func_id); 806 } 807 808 /* Internal function to delete the VFR default flows */ 809 static void 810 bnxt_ulp_destroy_vfr_default_rules(struct bnxt *bp, bool global) 811 { 812 struct bnxt_ulp_vfr_rule_info *info; 813 uint16_t port_id; 814 struct rte_eth_dev *vfr_eth_dev; 815 struct bnxt_representor *vfr_bp; 816 817 if (!BNXT_TRUFLOW_EN(bp) || BNXT_ETH_DEV_IS_REPRESENTOR(bp->eth_dev)) 818 return; 819 820 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 821 return; 822 823 /* Delete default rules for all ports */ 824 for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { 825 info = &bp->ulp_ctx->cfg_data->vfr_rule_info[port_id]; 826 if (!info->valid) 827 continue; 828 829 if (!global && info->parent_port_id != 830 bp->eth_dev->data->port_id) 831 continue; 832 833 /* Destroy the flows */ 834 ulp_default_flow_destroy(bp->eth_dev, info->rep2vf_flow_id); 835 ulp_default_flow_destroy(bp->eth_dev, info->vf2rep_flow_id); 836 /* Clean up the tx action pointer */ 837 vfr_eth_dev = &rte_eth_devices[port_id]; 838 if (vfr_eth_dev) { 839 vfr_bp = vfr_eth_dev->data->dev_private; 840 vfr_bp->vfr_tx_cfa_action = 0; 841 } 842 memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info)); 843 } 844 } 845 846 /* 847 * When a port is deinit'ed by dpdk. This function is called 848 * and this function clears the ULP context and rest of the 849 * infrastructure associated with it. 850 */ 851 static void 852 bnxt_ulp_deinit(struct bnxt *bp, 853 struct bnxt_ulp_session_state *session) 854 { 855 if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data) 856 return; 857 858 /* clean up default flows */ 859 bnxt_ulp_destroy_df_rules(bp, true); 860 861 /* clean up default VFR flows */ 862 bnxt_ulp_destroy_vfr_default_rules(bp, true); 863 864 /* clean up regular flows */ 865 ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR); 866 867 /* cleanup the eem table scope */ 868 ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx); 869 870 /* cleanup the flow database */ 871 ulp_flow_db_deinit(bp->ulp_ctx); 872 873 /* Delete the Mark database */ 874 ulp_mark_db_deinit(bp->ulp_ctx); 875 876 /* cleanup the ulp mapper */ 877 ulp_mapper_deinit(bp->ulp_ctx); 878 879 /* Delete the Flow Counter Manager */ 880 ulp_fc_mgr_deinit(bp->ulp_ctx); 881 882 /* Delete the Port database */ 883 ulp_port_db_deinit(bp->ulp_ctx); 884 885 /* Disable NAT feature */ 886 (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 887 TF_TUNNEL_ENCAP_NAT, 888 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 889 890 (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 891 TF_TUNNEL_ENCAP_NAT, 892 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0); 893 894 /* free the flow db lock */ 895 pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock); 896 897 /* Delete the ulp context and tf session and free the ulp context */ 898 ulp_ctx_deinit(bp, session); 899 BNXT_TF_DBG(DEBUG, "ulp ctx has been deinitialized\n"); 900 } 901 902 /* 903 * When a port is initialized by dpdk. This functions is called 904 * and this function initializes the ULP context and rest of the 905 * infrastructure associated with it. 906 */ 907 static int32_t 908 bnxt_ulp_init(struct bnxt *bp, 909 struct bnxt_ulp_session_state *session) 910 { 911 int rc; 912 913 /* Allocate and Initialize the ulp context. */ 914 rc = ulp_ctx_init(bp, session); 915 if (rc) { 916 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n"); 917 goto jump_to_error; 918 } 919 920 rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL); 921 if (rc) { 922 BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n"); 923 goto jump_to_error; 924 } 925 926 /* Initialize ulp dparms with values devargs passed */ 927 rc = ulp_dparms_init(bp, bp->ulp_ctx); 928 if (rc) { 929 BNXT_TF_DBG(ERR, "Failed to initialize the dparms\n"); 930 goto jump_to_error; 931 } 932 933 /* create the port database */ 934 rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt); 935 if (rc) { 936 BNXT_TF_DBG(ERR, "Failed to create the port database\n"); 937 goto jump_to_error; 938 } 939 940 /* Create the Mark database. */ 941 rc = ulp_mark_db_init(bp->ulp_ctx); 942 if (rc) { 943 BNXT_TF_DBG(ERR, "Failed to create the mark database\n"); 944 goto jump_to_error; 945 } 946 947 /* Create the flow database. */ 948 rc = ulp_flow_db_init(bp->ulp_ctx); 949 if (rc) { 950 BNXT_TF_DBG(ERR, "Failed to create the flow database\n"); 951 goto jump_to_error; 952 } 953 954 /* Create the eem table scope. */ 955 rc = ulp_eem_tbl_scope_init(bp); 956 if (rc) { 957 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n"); 958 goto jump_to_error; 959 } 960 961 rc = ulp_mapper_init(bp->ulp_ctx); 962 if (rc) { 963 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n"); 964 goto jump_to_error; 965 } 966 967 rc = ulp_fc_mgr_init(bp->ulp_ctx); 968 if (rc) { 969 BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n"); 970 goto jump_to_error; 971 } 972 973 /* 974 * Enable NAT feature. Set the global configuration register 975 * Tunnel encap to enable NAT with the reuse of existing inner 976 * L2 header smac and dmac 977 */ 978 rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP, 979 TF_TUNNEL_ENCAP_NAT, 980 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 981 if (rc) { 982 BNXT_TF_DBG(ERR, "Failed to set rx global configuration\n"); 983 goto jump_to_error; 984 } 985 986 rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP, 987 TF_TUNNEL_ENCAP_NAT, 988 BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1); 989 if (rc) { 990 BNXT_TF_DBG(ERR, "Failed to set tx global configuration\n"); 991 goto jump_to_error; 992 } 993 BNXT_TF_DBG(DEBUG, "ulp ctx has been initialized\n"); 994 return rc; 995 996 jump_to_error: 997 bnxt_ulp_deinit(bp, session); 998 return rc; 999 } 1000 1001 /* 1002 * When a port is initialized by dpdk. This functions sets up 1003 * the port specific details. 1004 */ 1005 int32_t 1006 bnxt_ulp_port_init(struct bnxt *bp) 1007 { 1008 struct bnxt_ulp_session_state *session; 1009 bool initialized; 1010 int32_t rc = 0; 1011 1012 if (!bp || !BNXT_TRUFLOW_EN(bp)) 1013 return rc; 1014 1015 if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) { 1016 BNXT_TF_DBG(ERR, 1017 "Skip ulp init for port: %d, not a TVF or PF\n", 1018 bp->eth_dev->data->port_id); 1019 return rc; 1020 } 1021 1022 if (bp->ulp_ctx) { 1023 BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n"); 1024 return rc; 1025 } 1026 1027 bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx", 1028 sizeof(struct bnxt_ulp_context), 0); 1029 if (!bp->ulp_ctx) { 1030 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n"); 1031 return -ENOMEM; 1032 } 1033 1034 /* 1035 * Multiple uplink ports can be associated with a single vswitch. 1036 * Make sure only the port that is started first will initialize 1037 * the TF session. 1038 */ 1039 session = ulp_session_init(bp, &initialized); 1040 if (!session) { 1041 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n"); 1042 rc = -EIO; 1043 goto jump_to_error; 1044 } 1045 1046 if (initialized) { 1047 /* 1048 * If ULP is already initialized for a specific domain then 1049 * simply assign the ulp context to this rte_eth_dev. 1050 */ 1051 rc = ulp_ctx_attach(bp, session); 1052 if (rc) { 1053 BNXT_TF_DBG(ERR, "Failed to attach the ulp context\n"); 1054 goto jump_to_error; 1055 } 1056 } else { 1057 rc = bnxt_ulp_init(bp, session); 1058 if (rc) { 1059 BNXT_TF_DBG(ERR, "Failed to initialize the ulp init\n"); 1060 goto jump_to_error; 1061 } 1062 } 1063 1064 /* Update bnxt driver flags */ 1065 rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx); 1066 if (rc) { 1067 BNXT_TF_DBG(ERR, "Failed to update driver flags\n"); 1068 goto jump_to_error; 1069 } 1070 1071 /* update the port database for the given interface */ 1072 rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev); 1073 if (rc) { 1074 BNXT_TF_DBG(ERR, "Failed to update port database\n"); 1075 goto jump_to_error; 1076 } 1077 /* create the default rules */ 1078 bnxt_ulp_create_df_rules(bp); 1079 BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port init\n", 1080 bp->eth_dev->data->port_id); 1081 return rc; 1082 1083 jump_to_error: 1084 bnxt_ulp_port_deinit(bp); 1085 return rc; 1086 } 1087 1088 /* 1089 * When a port is de-initialized by dpdk. This functions clears up 1090 * the port specific details. 1091 */ 1092 void 1093 bnxt_ulp_port_deinit(struct bnxt *bp) 1094 { 1095 struct bnxt_ulp_session_state *session; 1096 struct rte_pci_device *pci_dev; 1097 struct rte_pci_addr *pci_addr; 1098 1099 if (!BNXT_TRUFLOW_EN(bp)) 1100 return; 1101 1102 if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) { 1103 BNXT_TF_DBG(ERR, 1104 "Skip ULP deinit port:%d, not a TVF or PF\n", 1105 bp->eth_dev->data->port_id); 1106 return; 1107 } 1108 1109 if (!bp->ulp_ctx) { 1110 BNXT_TF_DBG(DEBUG, "ulp ctx already de-allocated\n"); 1111 return; 1112 } 1113 1114 BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n", 1115 bp->eth_dev->data->port_id); 1116 1117 /* Get the session details */ 1118 pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device); 1119 pci_addr = &pci_dev->addr; 1120 pthread_mutex_lock(&bnxt_ulp_global_mutex); 1121 session = ulp_get_session(pci_addr); 1122 pthread_mutex_unlock(&bnxt_ulp_global_mutex); 1123 1124 /* session not found then just exit */ 1125 if (!session) { 1126 /* Free the ulp context */ 1127 rte_free(bp->ulp_ctx); 1128 bp->ulp_ctx = NULL; 1129 return; 1130 } 1131 1132 /* Check the reference count to deinit or deattach*/ 1133 if (bp->ulp_ctx->cfg_data && bp->ulp_ctx->cfg_data->ref_cnt) { 1134 bp->ulp_ctx->cfg_data->ref_cnt--; 1135 if (bp->ulp_ctx->cfg_data->ref_cnt) { 1136 /* free the port details */ 1137 /* Free the default flow rule associated to this port */ 1138 bnxt_ulp_destroy_df_rules(bp, false); 1139 bnxt_ulp_destroy_vfr_default_rules(bp, false); 1140 1141 /* free flows associated with this port */ 1142 bnxt_ulp_flush_port_flows(bp); 1143 1144 /* close the session associated with this port */ 1145 ulp_ctx_detach(bp); 1146 } else { 1147 /* Perform ulp ctx deinit */ 1148 bnxt_ulp_deinit(bp, session); 1149 } 1150 } 1151 1152 /* clean up the session */ 1153 ulp_session_deinit(session); 1154 1155 /* Free the ulp context */ 1156 rte_free(bp->ulp_ctx); 1157 bp->ulp_ctx = NULL; 1158 } 1159 1160 /* Below are the access functions to access internal data of ulp context. */ 1161 /* Function to set the Mark DB into the context */ 1162 int32_t 1163 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx, 1164 struct bnxt_ulp_mark_tbl *mark_tbl) 1165 { 1166 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1167 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1168 return -EINVAL; 1169 } 1170 1171 ulp_ctx->cfg_data->mark_tbl = mark_tbl; 1172 1173 return 0; 1174 } 1175 1176 /* Function to retrieve the Mark DB from the context. */ 1177 struct bnxt_ulp_mark_tbl * 1178 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx) 1179 { 1180 if (!ulp_ctx || !ulp_ctx->cfg_data) 1181 return NULL; 1182 1183 return ulp_ctx->cfg_data->mark_tbl; 1184 } 1185 1186 /* Function to set the device id of the hardware. */ 1187 int32_t 1188 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx, 1189 uint32_t dev_id) 1190 { 1191 if (ulp_ctx && ulp_ctx->cfg_data) { 1192 ulp_ctx->cfg_data->dev_id = dev_id; 1193 return 0; 1194 } 1195 1196 return -EINVAL; 1197 } 1198 1199 /* Function to get the device id of the hardware. */ 1200 int32_t 1201 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx, 1202 uint32_t *dev_id) 1203 { 1204 if (ulp_ctx && ulp_ctx->cfg_data) { 1205 *dev_id = ulp_ctx->cfg_data->dev_id; 1206 return 0; 1207 } 1208 1209 BNXT_TF_DBG(ERR, "Failed to read dev_id from ulp ctxt\n"); 1210 return -EINVAL; 1211 } 1212 1213 int32_t 1214 bnxt_ulp_cntxt_mem_type_set(struct bnxt_ulp_context *ulp_ctx, 1215 enum bnxt_ulp_flow_mem_type mem_type) 1216 { 1217 if (ulp_ctx && ulp_ctx->cfg_data) { 1218 ulp_ctx->cfg_data->mem_type = mem_type; 1219 return 0; 1220 } 1221 BNXT_TF_DBG(ERR, "Failed to write mem_type in ulp ctxt\n"); 1222 return -EINVAL; 1223 } 1224 1225 int32_t 1226 bnxt_ulp_cntxt_mem_type_get(struct bnxt_ulp_context *ulp_ctx, 1227 enum bnxt_ulp_flow_mem_type *mem_type) 1228 { 1229 if (ulp_ctx && ulp_ctx->cfg_data) { 1230 *mem_type = ulp_ctx->cfg_data->mem_type; 1231 return 0; 1232 } 1233 BNXT_TF_DBG(ERR, "Failed to read mem_type in ulp ctxt\n"); 1234 return -EINVAL; 1235 } 1236 1237 /* Function to get the table scope id of the EEM table. */ 1238 int32_t 1239 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx, 1240 uint32_t *tbl_scope_id) 1241 { 1242 if (ulp_ctx && ulp_ctx->cfg_data) { 1243 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id; 1244 return 0; 1245 } 1246 1247 return -EINVAL; 1248 } 1249 1250 /* Function to set the table scope id of the EEM table. */ 1251 int32_t 1252 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx, 1253 uint32_t tbl_scope_id) 1254 { 1255 if (ulp_ctx && ulp_ctx->cfg_data) { 1256 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id; 1257 return 0; 1258 } 1259 1260 return -EINVAL; 1261 } 1262 1263 /* Function to set the tfp session details from the ulp context. */ 1264 int32_t 1265 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp) 1266 { 1267 if (!ulp) { 1268 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 1269 return -EINVAL; 1270 } 1271 1272 ulp->g_tfp = tfp; 1273 return 0; 1274 } 1275 1276 /* Function to get the tfp session details from the ulp context. */ 1277 struct tf * 1278 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp) 1279 { 1280 if (!ulp) { 1281 BNXT_TF_DBG(ERR, "Invalid arguments\n"); 1282 return NULL; 1283 } 1284 return ulp->g_tfp; 1285 } 1286 1287 /* 1288 * Get the device table entry based on the device id. 1289 * 1290 * dev_id [in] The device id of the hardware 1291 * 1292 * Returns the pointer to the device parameters. 1293 */ 1294 struct bnxt_ulp_device_params * 1295 bnxt_ulp_device_params_get(uint32_t dev_id) 1296 { 1297 if (dev_id < BNXT_ULP_MAX_NUM_DEVICES) 1298 return &ulp_device_params[dev_id]; 1299 return NULL; 1300 } 1301 1302 /* Function to set the flow database to the ulp context. */ 1303 int32_t 1304 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx, 1305 struct bnxt_ulp_flow_db *flow_db) 1306 { 1307 if (!ulp_ctx || !ulp_ctx->cfg_data) 1308 return -EINVAL; 1309 1310 ulp_ctx->cfg_data->flow_db = flow_db; 1311 return 0; 1312 } 1313 1314 /* Function to get the flow database from the ulp context. */ 1315 struct bnxt_ulp_flow_db * 1316 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx) 1317 { 1318 if (!ulp_ctx || !ulp_ctx->cfg_data) 1319 return NULL; 1320 1321 return ulp_ctx->cfg_data->flow_db; 1322 } 1323 1324 /* Function to get the tunnel cache table info from the ulp context. */ 1325 struct bnxt_tun_cache_entry * 1326 bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx) 1327 { 1328 if (!ulp_ctx || !ulp_ctx->cfg_data) 1329 return NULL; 1330 1331 return ulp_ctx->cfg_data->tun_tbl; 1332 } 1333 1334 /* Function to get the ulp context from eth device. */ 1335 struct bnxt_ulp_context * 1336 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev *dev) 1337 { 1338 struct bnxt *bp = (struct bnxt *)dev->data->dev_private; 1339 1340 if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) { 1341 struct bnxt_representor *vfr = dev->data->dev_private; 1342 1343 bp = vfr->parent_dev->data->dev_private; 1344 } 1345 1346 if (!bp) { 1347 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n"); 1348 return NULL; 1349 } 1350 return bp->ulp_ctx; 1351 } 1352 1353 int32_t 1354 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx, 1355 void *mapper_data) 1356 { 1357 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1358 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1359 return -EINVAL; 1360 } 1361 1362 ulp_ctx->cfg_data->mapper_data = mapper_data; 1363 return 0; 1364 } 1365 1366 void * 1367 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx) 1368 { 1369 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1370 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1371 return NULL; 1372 } 1373 1374 return ulp_ctx->cfg_data->mapper_data; 1375 } 1376 1377 /* Function to set the port database to the ulp context. */ 1378 int32_t 1379 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx, 1380 struct bnxt_ulp_port_db *port_db) 1381 { 1382 if (!ulp_ctx || !ulp_ctx->cfg_data) 1383 return -EINVAL; 1384 1385 ulp_ctx->cfg_data->port_db = port_db; 1386 return 0; 1387 } 1388 1389 /* Function to get the port database from the ulp context. */ 1390 struct bnxt_ulp_port_db * 1391 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx) 1392 { 1393 if (!ulp_ctx || !ulp_ctx->cfg_data) 1394 return NULL; 1395 1396 return ulp_ctx->cfg_data->port_db; 1397 } 1398 1399 /* Function to set the flow counter info into the context */ 1400 int32_t 1401 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx, 1402 struct bnxt_ulp_fc_info *ulp_fc_info) 1403 { 1404 if (!ulp_ctx || !ulp_ctx->cfg_data) { 1405 BNXT_TF_DBG(ERR, "Invalid ulp context data\n"); 1406 return -EINVAL; 1407 } 1408 1409 ulp_ctx->cfg_data->fc_info = ulp_fc_info; 1410 1411 return 0; 1412 } 1413 1414 /* Function to retrieve the flow counter info from the context. */ 1415 struct bnxt_ulp_fc_info * 1416 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx) 1417 { 1418 if (!ulp_ctx || !ulp_ctx->cfg_data) 1419 return NULL; 1420 1421 return ulp_ctx->cfg_data->fc_info; 1422 } 1423 1424 /* Function to get the ulp flags from the ulp context. */ 1425 int32_t 1426 bnxt_ulp_cntxt_ptr2_ulp_flags_get(struct bnxt_ulp_context *ulp_ctx, 1427 uint32_t *flags) 1428 { 1429 if (!ulp_ctx || !ulp_ctx->cfg_data) 1430 return -1; 1431 1432 *flags = ulp_ctx->cfg_data->ulp_flags; 1433 return 0; 1434 } 1435 1436 /* Function to get the ulp vfr info from the ulp context. */ 1437 struct bnxt_ulp_vfr_rule_info* 1438 bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(struct bnxt_ulp_context *ulp_ctx, 1439 uint32_t port_id) 1440 { 1441 if (!ulp_ctx || !ulp_ctx->cfg_data || port_id >= RTE_MAX_ETHPORTS) 1442 return NULL; 1443 1444 return &ulp_ctx->cfg_data->vfr_rule_info[port_id]; 1445 } 1446 1447 /* Function to acquire the flow database lock from the ulp context. */ 1448 int32_t 1449 bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context *ulp_ctx) 1450 { 1451 if (!ulp_ctx || !ulp_ctx->cfg_data) 1452 return -1; 1453 1454 if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) { 1455 BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n"); 1456 return -1; 1457 } 1458 return 0; 1459 } 1460 1461 /* Function to release the flow database lock from the ulp context. */ 1462 void 1463 bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context *ulp_ctx) 1464 { 1465 if (!ulp_ctx || !ulp_ctx->cfg_data) 1466 return; 1467 1468 pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock); 1469 } 1470