1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_malloc.h> 7 #include "bnxt.h" 8 #include "bnxt_vnic.h" 9 #include "bnxt_tf_common.h" 10 #include "ulp_port_db.h" 11 12 static uint32_t 13 ulp_port_db_allocate_ifindex(struct bnxt_ulp_port_db *port_db) 14 { 15 uint32_t idx = 1; 16 17 while (idx < port_db->ulp_intf_list_size && 18 port_db->ulp_intf_list[idx].type != BNXT_ULP_INTF_TYPE_INVALID) 19 idx++; 20 21 if (idx >= port_db->ulp_intf_list_size) { 22 BNXT_TF_DBG(ERR, "Port DB interface list is full\n"); 23 return 0; 24 } 25 return idx; 26 } 27 28 /* 29 * Initialize the port database. Memory is allocated in this 30 * call and assigned to the port database. 31 * 32 * ulp_ctxt [in] Ptr to ulp context 33 * 34 * Returns 0 on success or negative number on failure. 35 */ 36 int32_t ulp_port_db_init(struct bnxt_ulp_context *ulp_ctxt, uint8_t port_cnt) 37 { 38 struct bnxt_ulp_port_db *port_db; 39 40 port_db = rte_zmalloc("bnxt_ulp_port_db", 41 sizeof(struct bnxt_ulp_port_db), 0); 42 if (!port_db) { 43 BNXT_TF_DBG(ERR, 44 "Failed to allocate memory for port db\n"); 45 return -ENOMEM; 46 } 47 48 /* Attach the port database to the ulp context. */ 49 bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, port_db); 50 51 /* index 0 is not being used hence add 1 to size */ 52 port_db->ulp_intf_list_size = BNXT_PORT_DB_MAX_INTF_LIST + 1; 53 /* Allocate the port tables */ 54 port_db->ulp_intf_list = rte_zmalloc("bnxt_ulp_port_db_intf_list", 55 port_db->ulp_intf_list_size * 56 sizeof(struct ulp_interface_info), 57 0); 58 if (!port_db->ulp_intf_list) { 59 BNXT_TF_DBG(ERR, 60 "Failed to allocate mem for port interface list\n"); 61 goto error_free; 62 } 63 64 /* Allocate the phy port list */ 65 port_db->phy_port_list = rte_zmalloc("bnxt_ulp_phy_port_list", 66 port_cnt * 67 sizeof(struct ulp_phy_port_info), 68 0); 69 if (!port_db->phy_port_list) { 70 BNXT_TF_DBG(ERR, 71 "Failed to allocate mem for phy port list\n"); 72 goto error_free; 73 } 74 port_db->phy_port_cnt = port_cnt; 75 return 0; 76 77 error_free: 78 ulp_port_db_deinit(ulp_ctxt); 79 return -ENOMEM; 80 } 81 82 /* 83 * Deinitialize the port database. Memory is deallocated in 84 * this call. 85 * 86 * ulp_ctxt [in] Ptr to ulp context 87 * 88 * Returns 0 on success. 89 */ 90 int32_t ulp_port_db_deinit(struct bnxt_ulp_context *ulp_ctxt) 91 { 92 struct bnxt_ulp_port_db *port_db; 93 94 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 95 if (!port_db) { 96 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 97 return -EINVAL; 98 } 99 100 /* Detach the flow database from the ulp context. */ 101 bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, NULL); 102 103 /* Free up all the memory. */ 104 rte_free(port_db->phy_port_list); 105 rte_free(port_db->ulp_intf_list); 106 rte_free(port_db); 107 return 0; 108 } 109 110 /* 111 * Update the port database.This api is called when the port 112 * details are available during the startup. 113 * 114 * ulp_ctxt [in] Ptr to ulp context 115 * bp [in]. ptr to the device function. 116 * 117 * Returns 0 on success or negative number on failure. 118 */ 119 int32_t ulp_port_db_dev_port_intf_update(struct bnxt_ulp_context *ulp_ctxt, 120 struct rte_eth_dev *eth_dev) 121 { 122 uint32_t port_id = eth_dev->data->port_id; 123 struct ulp_phy_port_info *port_data; 124 struct bnxt_ulp_port_db *port_db; 125 struct ulp_interface_info *intf; 126 struct ulp_func_if_info *func; 127 uint32_t ifindex; 128 int32_t rc; 129 130 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 131 if (!port_db) { 132 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 133 return -EINVAL; 134 } 135 136 rc = ulp_port_db_dev_port_to_ulp_index(ulp_ctxt, port_id, &ifindex); 137 if (rc == -ENOENT) { 138 /* port not found, allocate one */ 139 ifindex = ulp_port_db_allocate_ifindex(port_db); 140 if (!ifindex) 141 return -ENOMEM; 142 port_db->dev_port_list[port_id] = ifindex; 143 } else if (rc == -EINVAL) { 144 return -EINVAL; 145 } 146 147 /* update the interface details */ 148 intf = &port_db->ulp_intf_list[ifindex]; 149 150 intf->type = bnxt_get_interface_type(port_id); 151 intf->drv_func_id = bnxt_get_fw_func_id(port_id, 152 BNXT_ULP_INTF_TYPE_INVALID); 153 154 func = &port_db->ulp_func_id_tbl[intf->drv_func_id]; 155 if (!func->func_valid) { 156 func->func_svif = bnxt_get_svif(port_id, true, 157 BNXT_ULP_INTF_TYPE_INVALID); 158 func->func_spif = bnxt_get_phy_port_id(port_id); 159 func->func_parif = 160 bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID); 161 func->func_vnic = 162 bnxt_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_INVALID); 163 func->phy_port_id = bnxt_get_phy_port_id(port_id); 164 func->func_valid = true; 165 func->ifindex = ifindex; 166 } 167 168 if (intf->type == BNXT_ULP_INTF_TYPE_VF_REP) { 169 intf->vf_func_id = 170 bnxt_get_fw_func_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP); 171 172 func = &port_db->ulp_func_id_tbl[intf->vf_func_id]; 173 func->func_svif = 174 bnxt_get_svif(port_id, true, BNXT_ULP_INTF_TYPE_VF_REP); 175 func->func_spif = 176 bnxt_get_phy_port_id(port_id); 177 func->func_parif = 178 bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID); 179 func->func_vnic = 180 bnxt_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP); 181 func->phy_port_id = bnxt_get_phy_port_id(port_id); 182 func->ifindex = ifindex; 183 } 184 185 port_data = &port_db->phy_port_list[func->phy_port_id]; 186 if (!port_data->port_valid) { 187 port_data->port_svif = 188 bnxt_get_svif(port_id, false, 189 BNXT_ULP_INTF_TYPE_INVALID); 190 port_data->port_spif = bnxt_get_phy_port_id(port_id); 191 port_data->port_parif = 192 bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID); 193 port_data->port_vport = bnxt_get_vport(port_id); 194 port_data->port_valid = true; 195 } 196 197 return 0; 198 } 199 200 /* 201 * Api to get the ulp ifindex for a given device port. 202 * 203 * ulp_ctxt [in] Ptr to ulp context 204 * port_id [in].device port id 205 * ifindex [out] ulp ifindex 206 * 207 * Returns 0 on success or negative number on failure. 208 */ 209 int32_t 210 ulp_port_db_dev_port_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt, 211 uint32_t port_id, 212 uint32_t *ifindex) 213 { 214 struct bnxt_ulp_port_db *port_db; 215 216 *ifindex = 0; 217 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 218 if (!port_db || port_id >= RTE_MAX_ETHPORTS) { 219 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 220 return -EINVAL; 221 } 222 if (!port_db->dev_port_list[port_id]) 223 return -ENOENT; 224 225 *ifindex = port_db->dev_port_list[port_id]; 226 return 0; 227 } 228 229 /* 230 * Api to get the function id for a given ulp ifindex. 231 * 232 * ulp_ctxt [in] Ptr to ulp context 233 * ifindex [in] ulp ifindex 234 * func_id [out] the function id of the given ifindex. 235 * 236 * Returns 0 on success or negative number on failure. 237 */ 238 int32_t 239 ulp_port_db_function_id_get(struct bnxt_ulp_context *ulp_ctxt, 240 uint32_t ifindex, 241 uint32_t fid_type, 242 uint16_t *func_id) 243 { 244 struct bnxt_ulp_port_db *port_db; 245 246 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 247 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) { 248 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 249 return -EINVAL; 250 } 251 252 if (fid_type == BNXT_ULP_DRV_FUNC_FID) 253 *func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 254 else 255 *func_id = port_db->ulp_intf_list[ifindex].vf_func_id; 256 257 return 0; 258 } 259 260 /* 261 * Api to get the svif for a given ulp ifindex. 262 * 263 * ulp_ctxt [in] Ptr to ulp context 264 * ifindex [in] ulp ifindex 265 * svif_type [in] the svif type of the given ifindex. 266 * svif [out] the svif of the given ifindex. 267 * 268 * Returns 0 on success or negative number on failure. 269 */ 270 int32_t 271 ulp_port_db_svif_get(struct bnxt_ulp_context *ulp_ctxt, 272 uint32_t ifindex, 273 uint32_t svif_type, 274 uint16_t *svif) 275 { 276 struct bnxt_ulp_port_db *port_db; 277 uint16_t phy_port_id, func_id; 278 279 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 280 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) { 281 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 282 return -EINVAL; 283 } 284 285 if (svif_type == BNXT_ULP_DRV_FUNC_SVIF) { 286 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 287 *svif = port_db->ulp_func_id_tbl[func_id].func_svif; 288 } else if (svif_type == BNXT_ULP_VF_FUNC_SVIF) { 289 func_id = port_db->ulp_intf_list[ifindex].vf_func_id; 290 *svif = port_db->ulp_func_id_tbl[func_id].func_svif; 291 } else { 292 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 293 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id; 294 *svif = port_db->phy_port_list[phy_port_id].port_svif; 295 } 296 297 return 0; 298 } 299 300 /* 301 * Api to get the spif for a given ulp ifindex. 302 * 303 * ulp_ctxt [in] Ptr to ulp context 304 * ifindex [in] ulp ifindex 305 * spif_type [in] the spif type of the given ifindex. 306 * spif [out] the spif of the given ifindex. 307 * 308 * Returns 0 on success or negative number on failure. 309 */ 310 int32_t 311 ulp_port_db_spif_get(struct bnxt_ulp_context *ulp_ctxt, 312 uint32_t ifindex, 313 uint32_t spif_type, 314 uint16_t *spif) 315 { 316 struct bnxt_ulp_port_db *port_db; 317 uint16_t phy_port_id, func_id; 318 319 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 320 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) { 321 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 322 return -EINVAL; 323 } 324 325 if (spif_type == BNXT_ULP_DRV_FUNC_SPIF) { 326 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 327 *spif = port_db->ulp_func_id_tbl[func_id].func_spif; 328 } else if (spif_type == BNXT_ULP_VF_FUNC_SPIF) { 329 func_id = port_db->ulp_intf_list[ifindex].vf_func_id; 330 *spif = port_db->ulp_func_id_tbl[func_id].func_spif; 331 } else { 332 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 333 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id; 334 *spif = port_db->phy_port_list[phy_port_id].port_spif; 335 } 336 337 return 0; 338 } 339 340 /* 341 * Api to get the parif for a given ulp ifindex. 342 * 343 * ulp_ctxt [in] Ptr to ulp context 344 * ifindex [in] ulp ifindex 345 * parif_type [in] the parif type of the given ifindex. 346 * parif [out] the parif of the given ifindex. 347 * 348 * Returns 0 on success or negative number on failure. 349 */ 350 int32_t 351 ulp_port_db_parif_get(struct bnxt_ulp_context *ulp_ctxt, 352 uint32_t ifindex, 353 uint32_t parif_type, 354 uint16_t *parif) 355 { 356 struct bnxt_ulp_port_db *port_db; 357 uint16_t phy_port_id, func_id; 358 359 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 360 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) { 361 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 362 return -EINVAL; 363 } 364 if (parif_type == BNXT_ULP_DRV_FUNC_PARIF) { 365 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 366 *parif = port_db->ulp_func_id_tbl[func_id].func_parif; 367 } else if (parif_type == BNXT_ULP_VF_FUNC_PARIF) { 368 func_id = port_db->ulp_intf_list[ifindex].vf_func_id; 369 *parif = port_db->ulp_func_id_tbl[func_id].func_parif; 370 } else { 371 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 372 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id; 373 *parif = port_db->phy_port_list[phy_port_id].port_parif; 374 } 375 /* Parif needs to be reset to a free partition */ 376 *parif += BNXT_ULP_FREE_PARIF_BASE; 377 378 return 0; 379 } 380 381 /* 382 * Api to get the vnic id for a given ulp ifindex. 383 * 384 * ulp_ctxt [in] Ptr to ulp context 385 * ifindex [in] ulp ifindex 386 * vnic [out] the vnic of the given ifindex. 387 * 388 * Returns 0 on success or negative number on failure. 389 */ 390 int32_t 391 ulp_port_db_default_vnic_get(struct bnxt_ulp_context *ulp_ctxt, 392 uint32_t ifindex, 393 uint32_t vnic_type, 394 uint16_t *vnic) 395 { 396 struct bnxt_ulp_port_db *port_db; 397 uint16_t func_id; 398 399 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 400 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) { 401 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 402 return -EINVAL; 403 } 404 405 if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC) { 406 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 407 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic; 408 } else { 409 func_id = port_db->ulp_intf_list[ifindex].vf_func_id; 410 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic; 411 } 412 413 return 0; 414 } 415 416 /* 417 * Api to get the vport id for a given ulp ifindex. 418 * 419 * ulp_ctxt [in] Ptr to ulp context 420 * ifindex [in] ulp ifindex 421 * vport [out] the port of the given ifindex. 422 * 423 * Returns 0 on success or negative number on failure. 424 */ 425 int32_t 426 ulp_port_db_vport_get(struct bnxt_ulp_context *ulp_ctxt, 427 uint32_t ifindex, uint16_t *vport) 428 { 429 struct bnxt_ulp_port_db *port_db; 430 uint16_t phy_port_id, func_id; 431 432 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 433 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) { 434 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 435 return -EINVAL; 436 } 437 438 func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 439 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id; 440 *vport = port_db->phy_port_list[phy_port_id].port_vport; 441 return 0; 442 } 443 444 /* 445 * Api to get the vport for a given physical port. 446 * 447 * ulp_ctxt [in] Ptr to ulp context 448 * phy_port [in] physical port index 449 * out_port [out] the port of the given physical index 450 * 451 * Returns 0 on success or negative number on failure. 452 */ 453 int32_t 454 ulp_port_db_phy_port_vport_get(struct bnxt_ulp_context *ulp_ctxt, 455 uint32_t phy_port, 456 uint16_t *out_port) 457 { 458 struct bnxt_ulp_port_db *port_db; 459 460 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 461 if (!port_db || phy_port >= port_db->phy_port_cnt) { 462 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 463 return -EINVAL; 464 } 465 *out_port = port_db->phy_port_list[phy_port].port_vport; 466 return 0; 467 } 468 469 /* 470 * Api to get the svif for a given physical port. 471 * 472 * ulp_ctxt [in] Ptr to ulp context 473 * phy_port [in] physical port index 474 * svif [out] the svif of the given physical index 475 * 476 * Returns 0 on success or negative number on failure. 477 */ 478 int32_t 479 ulp_port_db_phy_port_svif_get(struct bnxt_ulp_context *ulp_ctxt, 480 uint32_t phy_port, 481 uint16_t *svif) 482 { 483 struct bnxt_ulp_port_db *port_db; 484 485 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 486 if (!port_db || phy_port >= port_db->phy_port_cnt) { 487 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 488 return -EINVAL; 489 } 490 *svif = port_db->phy_port_list[phy_port].port_svif; 491 return 0; 492 } 493 494 /* 495 * Api to get the port type for a given ulp ifindex. 496 * 497 * ulp_ctxt [in] Ptr to ulp context 498 * ifindex [in] ulp ifindex 499 * 500 * Returns port type. 501 */ 502 enum bnxt_ulp_intf_type 503 ulp_port_db_port_type_get(struct bnxt_ulp_context *ulp_ctxt, 504 uint32_t ifindex) 505 { 506 struct bnxt_ulp_port_db *port_db; 507 508 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 509 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) { 510 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 511 return BNXT_ULP_INTF_TYPE_INVALID; 512 } 513 return port_db->ulp_intf_list[ifindex].type; 514 } 515 516 /* 517 * Api to get the ulp ifindex for a given function id. 518 * 519 * ulp_ctxt [in] Ptr to ulp context 520 * func_id [in].device func id 521 * ifindex [out] ulp ifindex 522 * 523 * Returns 0 on success or negative number on failure. 524 */ 525 int32_t 526 ulp_port_db_dev_func_id_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt, 527 uint32_t func_id, uint32_t *ifindex) 528 { 529 struct bnxt_ulp_port_db *port_db; 530 531 *ifindex = 0; 532 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 533 if (!port_db || func_id >= BNXT_PORT_DB_MAX_FUNC) { 534 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 535 return -EINVAL; 536 } 537 if (!port_db->ulp_func_id_tbl[func_id].func_valid) 538 return -ENOENT; 539 540 *ifindex = port_db->ulp_func_id_tbl[func_id].ifindex; 541 return 0; 542 } 543 544 /* 545 * Api to get the function id for a given port id. 546 * 547 * ulp_ctxt [in] Ptr to ulp context 548 * port_id [in] dpdk port id 549 * func_id [out] the function id of the given ifindex. 550 * 551 * Returns 0 on success or negative number on failure. 552 */ 553 int32_t 554 ulp_port_db_port_func_id_get(struct bnxt_ulp_context *ulp_ctxt, 555 uint16_t port_id, uint16_t *func_id) 556 { 557 struct bnxt_ulp_port_db *port_db; 558 uint32_t ifindex; 559 560 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt); 561 if (!port_db || port_id >= RTE_MAX_ETHPORTS) { 562 BNXT_TF_DBG(ERR, "Invalid Arguments\n"); 563 return -EINVAL; 564 } 565 ifindex = port_db->dev_port_list[port_id]; 566 if (!ifindex) 567 return -ENOENT; 568 569 switch (port_db->ulp_intf_list[ifindex].type) { 570 case BNXT_ULP_INTF_TYPE_TRUSTED_VF: 571 case BNXT_ULP_INTF_TYPE_PF: 572 *func_id = port_db->ulp_intf_list[ifindex].drv_func_id; 573 break; 574 case BNXT_ULP_INTF_TYPE_VF: 575 case BNXT_ULP_INTF_TYPE_VF_REP: 576 *func_id = port_db->ulp_intf_list[ifindex].vf_func_id; 577 break; 578 default: 579 *func_id = 0; 580 break; 581 } 582 return 0; 583 } 584