1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <inttypes.h> 7 #include <stdbool.h> 8 #include <unistd.h> 9 10 #include <dev_driver.h> 11 #include <ethdev_driver.h> 12 #include <rte_malloc.h> 13 #include <rte_cycles.h> 14 #include <rte_byteorder.h> 15 16 #include "bnxt.h" 17 #include "bnxt_filter.h" 18 #include "bnxt_hwrm.h" 19 #include "bnxt_vnic.h" 20 #include "rte_pmd_bnxt.h" 21 #include "hsi_struct_def_dpdk.h" 22 23 int bnxt_rcv_msg_from_vf(struct bnxt *bp, uint16_t vf_id, void *msg) 24 { 25 struct rte_pmd_bnxt_mb_event_param ret_param; 26 27 ret_param.retval = RTE_PMD_BNXT_MB_EVENT_PROCEED; 28 ret_param.vf_id = vf_id; 29 ret_param.msg = msg; 30 31 rte_eth_dev_callback_process(bp->eth_dev, RTE_ETH_EVENT_VF_MBOX, 32 &ret_param); 33 34 /* Default to approve */ 35 if (ret_param.retval == RTE_PMD_BNXT_MB_EVENT_PROCEED) 36 ret_param.retval = RTE_PMD_BNXT_MB_EVENT_NOOP_ACK; 37 38 return ret_param.retval == RTE_PMD_BNXT_MB_EVENT_NOOP_ACK ? 39 true : false; 40 } 41 42 int rte_pmd_bnxt_set_tx_loopback(uint16_t port, uint8_t on) 43 { 44 struct rte_eth_dev *eth_dev; 45 struct bnxt *bp; 46 int rc; 47 48 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 49 50 if (on > 1) 51 return -EINVAL; 52 53 eth_dev = &rte_eth_devices[port]; 54 if (!is_bnxt_supported(eth_dev)) 55 return -ENOTSUP; 56 57 bp = eth_dev->data->dev_private; 58 59 if (!BNXT_PF(bp)) { 60 PMD_DRV_LOG_LINE(ERR, 61 "Attempt to set Tx loopback on non-PF port %d!", 62 port); 63 return -ENOTSUP; 64 } 65 66 if (on) 67 bp->pf->evb_mode = BNXT_EVB_MODE_VEB; 68 else 69 bp->pf->evb_mode = BNXT_EVB_MODE_VEPA; 70 71 rc = bnxt_hwrm_pf_evb_mode(bp); 72 73 return rc; 74 } 75 76 static void 77 rte_pmd_bnxt_set_all_queues_drop_en_cb(struct bnxt_vnic_info *vnic, void *onptr) 78 { 79 uint8_t *on = onptr; 80 vnic->bd_stall = !(*on); 81 } 82 83 int rte_pmd_bnxt_set_all_queues_drop_en(uint16_t port, uint8_t on) 84 { 85 struct rte_eth_dev *eth_dev; 86 struct bnxt *bp; 87 uint32_t i; 88 int rc = -EINVAL; 89 90 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 91 92 if (on > 1) 93 return -EINVAL; 94 95 eth_dev = &rte_eth_devices[port]; 96 if (!is_bnxt_supported(eth_dev)) 97 return -ENOTSUP; 98 99 bp = eth_dev->data->dev_private; 100 101 if (!BNXT_PF(bp)) { 102 PMD_DRV_LOG_LINE(ERR, 103 "Attempt to set all queues drop on non-PF port!"); 104 return -ENOTSUP; 105 } 106 107 if (bp->vnic_info == NULL) 108 return -ENODEV; 109 110 /* Stall PF */ 111 for (i = 0; i < bp->nr_vnics; i++) { 112 bp->vnic_info[i].bd_stall = !on; 113 rc = bnxt_hwrm_vnic_cfg(bp, &bp->vnic_info[i]); 114 if (rc) { 115 PMD_DRV_LOG_LINE(ERR, "Failed to update PF VNIC %d.", i); 116 return rc; 117 } 118 } 119 120 /* Stall all active VFs */ 121 for (i = 0; i < bp->pf->active_vfs; i++) { 122 rc = bnxt_hwrm_func_vf_vnic_query_and_config(bp, i, 123 rte_pmd_bnxt_set_all_queues_drop_en_cb, &on, 124 bnxt_hwrm_vnic_cfg); 125 if (rc) { 126 PMD_DRV_LOG_LINE(ERR, "Failed to update VF VNIC %d.", i); 127 break; 128 } 129 } 130 131 return rc; 132 } 133 134 int rte_pmd_bnxt_set_vf_mac_addr(uint16_t port, uint16_t vf, 135 struct rte_ether_addr *mac_addr) 136 { 137 struct rte_eth_dev *dev; 138 struct rte_eth_dev_info dev_info; 139 struct bnxt *bp; 140 int rc; 141 142 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 143 144 dev = &rte_eth_devices[port]; 145 if (!is_bnxt_supported(dev)) 146 return -ENOTSUP; 147 148 rc = rte_eth_dev_info_get(port, &dev_info); 149 if (rc != 0) { 150 PMD_DRV_LOG_LINE(ERR, 151 "Error during getting device (port %u) info: %s", 152 port, strerror(-rc)); 153 154 return rc; 155 } 156 157 bp = dev->data->dev_private; 158 159 if (vf >= dev_info.max_vfs || mac_addr == NULL) 160 return -EINVAL; 161 162 if (!BNXT_PF(bp)) { 163 PMD_DRV_LOG_LINE(ERR, 164 "Attempt to set VF %d mac address on non-PF port %d!", 165 vf, port); 166 return -ENOTSUP; 167 } 168 169 rc = bnxt_hwrm_func_vf_mac(bp, vf, (uint8_t *)mac_addr); 170 171 return rc; 172 } 173 174 int rte_pmd_bnxt_set_vf_rate_limit(uint16_t port, uint16_t vf, 175 uint32_t tx_rate, uint64_t q_msk) 176 { 177 struct rte_eth_dev *eth_dev; 178 struct rte_eth_dev_info dev_info; 179 struct bnxt *bp; 180 uint32_t tot_rate = 0; 181 uint64_t idx; 182 int rc; 183 184 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 185 186 eth_dev = &rte_eth_devices[port]; 187 if (!is_bnxt_supported(eth_dev)) 188 return -ENOTSUP; 189 190 rc = rte_eth_dev_info_get(port, &dev_info); 191 if (rc != 0) { 192 PMD_DRV_LOG_LINE(ERR, 193 "Error during getting device (port %u) info: %s", 194 port, strerror(-rc)); 195 196 return rc; 197 } 198 bp = eth_dev->data->dev_private; 199 200 if (!bp->pf->active_vfs) 201 return -EINVAL; 202 203 if (vf >= bp->pf->max_vfs) 204 return -EINVAL; 205 206 /* Add up the per queue BW and configure MAX BW of the VF */ 207 for (idx = 0; idx < 64; idx++) { 208 if ((1ULL << idx) & q_msk) 209 tot_rate += tx_rate; 210 } 211 212 /* Requested BW can't be greater than link speed */ 213 if (tot_rate > eth_dev->data->dev_link.link_speed) { 214 PMD_DRV_LOG_LINE(ERR, "Rate > Link speed. Set to %d", tot_rate); 215 return -EINVAL; 216 } 217 218 /* Requested BW already configured */ 219 if (tot_rate == bp->pf->vf_info[vf].max_tx_rate) 220 return 0; 221 222 rc = bnxt_hwrm_func_bw_cfg(bp, vf, tot_rate, 223 HWRM_FUNC_CFG_INPUT_ENABLES_MAX_BW); 224 225 if (!rc) 226 bp->pf->vf_info[vf].max_tx_rate = tot_rate; 227 228 return rc; 229 } 230 231 int rte_pmd_bnxt_set_vf_mac_anti_spoof(uint16_t port, uint16_t vf, uint8_t on) 232 { 233 struct rte_eth_dev_info dev_info; 234 struct rte_eth_dev *dev; 235 uint32_t func_flags; 236 struct bnxt *bp; 237 int rc; 238 239 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 240 241 if (on > 1) 242 return -EINVAL; 243 244 dev = &rte_eth_devices[port]; 245 if (!is_bnxt_supported(dev)) 246 return -ENOTSUP; 247 248 rc = rte_eth_dev_info_get(port, &dev_info); 249 if (rc != 0) { 250 PMD_DRV_LOG_LINE(ERR, 251 "Error during getting device (port %u) info: %s", 252 port, strerror(-rc)); 253 254 return rc; 255 } 256 bp = dev->data->dev_private; 257 258 if (!BNXT_PF(bp)) { 259 PMD_DRV_LOG_LINE(ERR, 260 "Attempt to set mac spoof on non-PF port %d!", port); 261 return -EINVAL; 262 } 263 264 if (vf >= dev_info.max_vfs) 265 return -EINVAL; 266 267 /* Prev setting same as new setting. */ 268 if (on == bp->pf->vf_info[vf].mac_spoof_en) 269 return 0; 270 271 func_flags = bp->pf->vf_info[vf].func_cfg_flags; 272 func_flags &= ~(HWRM_FUNC_CFG_INPUT_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE | 273 HWRM_FUNC_CFG_INPUT_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE); 274 275 if (on) 276 func_flags |= 277 HWRM_FUNC_CFG_INPUT_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE; 278 else 279 func_flags |= 280 HWRM_FUNC_CFG_INPUT_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE; 281 282 rc = bnxt_hwrm_func_cfg_vf_set_flags(bp, vf, func_flags); 283 if (!rc) { 284 bp->pf->vf_info[vf].mac_spoof_en = on; 285 bp->pf->vf_info[vf].func_cfg_flags = func_flags; 286 } 287 288 return rc; 289 } 290 291 int rte_pmd_bnxt_set_vf_vlan_anti_spoof(uint16_t port, uint16_t vf, uint8_t on) 292 { 293 struct rte_eth_dev_info dev_info; 294 struct rte_eth_dev *dev; 295 struct bnxt *bp; 296 int rc; 297 298 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 299 300 if (on > 1) 301 return -EINVAL; 302 303 dev = &rte_eth_devices[port]; 304 if (!is_bnxt_supported(dev)) 305 return -ENOTSUP; 306 307 rc = rte_eth_dev_info_get(port, &dev_info); 308 if (rc != 0) { 309 PMD_DRV_LOG_LINE(ERR, 310 "Error during getting device (port %u) info: %s", 311 port, strerror(-rc)); 312 313 return rc; 314 } 315 bp = dev->data->dev_private; 316 317 if (!BNXT_PF(bp)) { 318 PMD_DRV_LOG_LINE(ERR, 319 "Attempt to set VLAN spoof on non-PF port %d!", port); 320 return -EINVAL; 321 } 322 323 if (vf >= dev_info.max_vfs) 324 return -EINVAL; 325 326 rc = bnxt_hwrm_func_cfg_vf_set_vlan_anti_spoof(bp, vf, on); 327 if (!rc) { 328 bp->pf->vf_info[vf].vlan_spoof_en = on; 329 if (on) { 330 if (bnxt_hwrm_cfa_vlan_antispoof_cfg(bp, 331 bp->pf->first_vf_id + vf, 332 bp->pf->vf_info[vf].vlan_count, 333 bp->pf->vf_info[vf].vlan_as_table)) 334 rc = -1; 335 } 336 } else { 337 PMD_DRV_LOG_LINE(ERR, "Failed to update VF VNIC %d.", vf); 338 } 339 340 return rc; 341 } 342 343 static void 344 rte_pmd_bnxt_set_vf_vlan_stripq_cb(struct bnxt_vnic_info *vnic, void *onptr) 345 { 346 uint8_t *on = onptr; 347 vnic->vlan_strip = *on; 348 } 349 350 int 351 rte_pmd_bnxt_set_vf_vlan_stripq(uint16_t port, uint16_t vf, uint8_t on) 352 { 353 struct rte_eth_dev *dev; 354 struct rte_eth_dev_info dev_info; 355 struct bnxt *bp; 356 int rc; 357 358 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 359 360 dev = &rte_eth_devices[port]; 361 if (!is_bnxt_supported(dev)) 362 return -ENOTSUP; 363 364 rc = rte_eth_dev_info_get(port, &dev_info); 365 if (rc != 0) { 366 PMD_DRV_LOG_LINE(ERR, 367 "Error during getting device (port %u) info: %s", 368 port, strerror(-rc)); 369 370 return rc; 371 } 372 bp = dev->data->dev_private; 373 374 if (vf >= dev_info.max_vfs) 375 return -EINVAL; 376 377 if (!BNXT_PF(bp)) { 378 PMD_DRV_LOG_LINE(ERR, 379 "Attempt to set VF %d stripq on non-PF port %d!", 380 vf, port); 381 return -ENOTSUP; 382 } 383 384 rc = bnxt_hwrm_func_vf_vnic_query_and_config(bp, vf, 385 rte_pmd_bnxt_set_vf_vlan_stripq_cb, &on, 386 bnxt_hwrm_vnic_cfg); 387 if (rc) 388 PMD_DRV_LOG_LINE(ERR, "Failed to update VF VNIC %d.", vf); 389 390 return rc; 391 } 392 393 int rte_pmd_bnxt_set_vf_rxmode(uint16_t port, uint16_t vf, 394 uint16_t rx_mask, uint8_t on) 395 { 396 struct rte_eth_dev *dev; 397 struct rte_eth_dev_info dev_info; 398 uint16_t flag = 0; 399 struct bnxt *bp; 400 int rc; 401 402 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 403 404 dev = &rte_eth_devices[port]; 405 if (!is_bnxt_supported(dev)) 406 return -ENOTSUP; 407 408 rc = rte_eth_dev_info_get(port, &dev_info); 409 if (rc != 0) { 410 PMD_DRV_LOG_LINE(ERR, 411 "Error during getting device (port %u) info: %s", 412 port, strerror(-rc)); 413 414 return rc; 415 } 416 bp = dev->data->dev_private; 417 418 if (!bp->pf->vf_info) 419 return -EINVAL; 420 421 if (vf >= bp->pdev->max_vfs) 422 return -EINVAL; 423 424 if (rx_mask & RTE_ETH_VMDQ_ACCEPT_UNTAG) { 425 PMD_DRV_LOG_LINE(ERR, "Currently cannot toggle this setting"); 426 return -ENOTSUP; 427 } 428 429 /* Is this really the correct mapping? VFd seems to think it is. */ 430 if (rx_mask & RTE_ETH_VMDQ_ACCEPT_HASH_UC) 431 flag |= BNXT_VNIC_INFO_PROMISC; 432 433 if (rx_mask & RTE_ETH_VMDQ_ACCEPT_BROADCAST) 434 flag |= BNXT_VNIC_INFO_BCAST; 435 if (rx_mask & RTE_ETH_VMDQ_ACCEPT_MULTICAST) 436 flag |= BNXT_VNIC_INFO_ALLMULTI | BNXT_VNIC_INFO_MCAST; 437 438 if (on) 439 bp->pf->vf_info[vf].l2_rx_mask |= flag; 440 else 441 bp->pf->vf_info[vf].l2_rx_mask &= ~flag; 442 443 rc = bnxt_hwrm_func_vf_vnic_query_and_config(bp, vf, 444 vf_vnic_set_rxmask_cb, 445 &bp->pf->vf_info[vf].l2_rx_mask, 446 bnxt_set_rx_mask_no_vlan); 447 if (rc) 448 PMD_DRV_LOG_LINE(ERR, "bnxt_hwrm_func_vf_vnic_set_rxmask failed"); 449 450 return rc; 451 } 452 453 static int bnxt_set_vf_table(struct bnxt *bp, uint16_t vf) 454 { 455 int rc = 0; 456 int dflt_vnic; 457 struct bnxt_vnic_info vnic; 458 459 if (!BNXT_PF(bp)) { 460 PMD_DRV_LOG_LINE(ERR, 461 "Attempt to set VLAN table on non-PF port!"); 462 return -EINVAL; 463 } 464 465 if (vf >= bp->pdev->max_vfs) 466 return -EINVAL; 467 468 dflt_vnic = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf); 469 if (dflt_vnic < 0) { 470 /* This simply indicates there's no driver loaded. 471 * This is not an error. 472 */ 473 PMD_DRV_LOG_LINE(ERR, "Unable to get default VNIC for VF %d", vf); 474 } else { 475 memset(&vnic, 0, sizeof(vnic)); 476 vnic.fw_vnic_id = dflt_vnic; 477 if (bnxt_hwrm_vnic_qcfg(bp, &vnic, 478 bp->pf->first_vf_id + vf) == 0) { 479 if (bnxt_hwrm_cfa_l2_set_rx_mask(bp, &vnic, 480 bp->pf->vf_info[vf].vlan_count, 481 bp->pf->vf_info[vf].vlan_table)) 482 rc = -1; 483 } else { 484 rc = -1; 485 } 486 } 487 488 return rc; 489 } 490 491 int rte_pmd_bnxt_set_vf_vlan_filter(uint16_t port, uint16_t vlan, 492 uint64_t vf_mask, uint8_t vlan_on) 493 { 494 struct bnxt_vlan_table_entry *ve; 495 struct bnxt_vlan_antispoof_table_entry *vase; 496 struct rte_eth_dev *dev; 497 struct bnxt *bp; 498 uint16_t cnt; 499 int rc = 0; 500 int i, j; 501 502 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 503 504 dev = &rte_eth_devices[port]; 505 if (!is_bnxt_supported(dev)) 506 return -ENOTSUP; 507 508 bp = dev->data->dev_private; 509 if (!bp->pf->vf_info) 510 return -EINVAL; 511 512 for (i = 0; vf_mask; i++, vf_mask >>= 1) { 513 cnt = bp->pf->vf_info[i].vlan_count; 514 if ((vf_mask & 1) == 0) 515 continue; 516 517 if (bp->pf->vf_info[i].vlan_table == NULL) { 518 rc = -1; 519 continue; 520 } 521 if (bp->pf->vf_info[i].vlan_as_table == NULL) { 522 rc = -1; 523 continue; 524 } 525 if (vlan_on) { 526 /* First, search for a duplicate... */ 527 for (j = 0; j < cnt; j++) { 528 if (rte_be_to_cpu_16( 529 bp->pf->vf_info[i].vlan_table[j].vid) == 530 vlan) 531 break; 532 } 533 if (j == cnt) { 534 /* Now check that there's space */ 535 if (cnt == getpagesize() / sizeof(struct 536 bnxt_vlan_antispoof_table_entry)) { 537 PMD_DRV_LOG_LINE(ERR, 538 "VLAN anti-spoof table is full"); 539 PMD_DRV_LOG_LINE(ERR, 540 "VF %d cannot add VLAN %u", 541 i, vlan); 542 rc = -1; 543 continue; 544 } 545 546 /* cnt is one less than vlan_count */ 547 cnt = bp->pf->vf_info[i].vlan_count++; 548 /* 549 * And finally, add to the 550 * end of the table 551 */ 552 vase = &bp->pf->vf_info[i].vlan_as_table[cnt]; 553 // TODO: Hardcoded TPID 554 vase->tpid = rte_cpu_to_be_16(0x8100); 555 vase->vid = rte_cpu_to_be_16(vlan); 556 vase->mask = rte_cpu_to_be_16(0xfff); 557 ve = &bp->pf->vf_info[i].vlan_table[cnt]; 558 /* TODO: Hardcoded TPID */ 559 ve->tpid = rte_cpu_to_be_16(0x8100); 560 ve->vid = rte_cpu_to_be_16(vlan); 561 } 562 } else { 563 for (j = 0; j < cnt; j++) { 564 if (rte_be_to_cpu_16( 565 bp->pf->vf_info[i].vlan_table[j].vid) != 566 vlan) 567 continue; 568 memmove(&bp->pf->vf_info[i].vlan_table[j], 569 &bp->pf->vf_info[i].vlan_table[j + 1], 570 getpagesize() - ((j + 1) * 571 sizeof(struct bnxt_vlan_table_entry))); 572 memmove(&bp->pf->vf_info[i].vlan_as_table[j], 573 &bp->pf->vf_info[i].vlan_as_table[j + 1], 574 getpagesize() - ((j + 1) * sizeof(struct 575 bnxt_vlan_antispoof_table_entry))); 576 j--; 577 cnt = --bp->pf->vf_info[i].vlan_count; 578 } 579 } 580 bnxt_set_vf_table(bp, i); 581 } 582 583 return rc; 584 } 585 586 int rte_pmd_bnxt_get_vf_stats(uint16_t port, 587 uint16_t vf_id, 588 struct rte_eth_stats *stats) 589 { 590 struct rte_eth_dev *dev; 591 struct rte_eth_dev_info dev_info; 592 struct bnxt *bp; 593 int rc; 594 595 dev = &rte_eth_devices[port]; 596 if (!is_bnxt_supported(dev)) 597 return -ENOTSUP; 598 599 rc = rte_eth_dev_info_get(port, &dev_info); 600 if (rc != 0) { 601 PMD_DRV_LOG_LINE(ERR, 602 "Error during getting device (port %u) info: %s", 603 port, strerror(-rc)); 604 605 return rc; 606 } 607 bp = dev->data->dev_private; 608 609 if (vf_id >= dev_info.max_vfs) 610 return -EINVAL; 611 612 if (!BNXT_PF(bp)) { 613 PMD_DRV_LOG_LINE(ERR, 614 "Attempt to get VF %d stats on non-PF port %d!", 615 vf_id, port); 616 return -ENOTSUP; 617 } 618 619 return bnxt_hwrm_func_qstats(bp, bp->pf->first_vf_id + vf_id, stats, 620 NULL); 621 } 622 623 int rte_pmd_bnxt_reset_vf_stats(uint16_t port, 624 uint16_t vf_id) 625 { 626 struct rte_eth_dev *dev; 627 struct rte_eth_dev_info dev_info; 628 struct bnxt *bp; 629 int rc; 630 631 dev = &rte_eth_devices[port]; 632 if (!is_bnxt_supported(dev)) 633 return -ENOTSUP; 634 635 rc = rte_eth_dev_info_get(port, &dev_info); 636 if (rc != 0) { 637 PMD_DRV_LOG_LINE(ERR, 638 "Error during getting device (port %u) info: %s", 639 port, strerror(-rc)); 640 641 return rc; 642 } 643 bp = dev->data->dev_private; 644 645 if (vf_id >= dev_info.max_vfs) 646 return -EINVAL; 647 648 if (!BNXT_PF(bp)) { 649 PMD_DRV_LOG_LINE(ERR, 650 "Attempt to reset VF %d stats on non-PF port %d!", 651 vf_id, port); 652 return -ENOTSUP; 653 } 654 655 return bnxt_hwrm_func_clr_stats(bp, bp->pf->first_vf_id + vf_id); 656 } 657 658 int rte_pmd_bnxt_get_vf_rx_status(uint16_t port, uint16_t vf_id) 659 { 660 struct rte_eth_dev *dev; 661 struct rte_eth_dev_info dev_info; 662 struct bnxt *bp; 663 int rc; 664 665 dev = &rte_eth_devices[port]; 666 if (!is_bnxt_supported(dev)) 667 return -ENOTSUP; 668 669 rc = rte_eth_dev_info_get(port, &dev_info); 670 if (rc != 0) { 671 PMD_DRV_LOG_LINE(ERR, 672 "Error during getting device (port %u) info: %s", 673 port, strerror(-rc)); 674 675 return rc; 676 } 677 bp = dev->data->dev_private; 678 679 if (vf_id >= dev_info.max_vfs) 680 return -EINVAL; 681 682 if (!BNXT_PF(bp)) { 683 PMD_DRV_LOG_LINE(ERR, 684 "Attempt to query VF %d RX stats on non-PF port %d!", 685 vf_id, port); 686 return -ENOTSUP; 687 } 688 689 return bnxt_vf_vnic_count(bp, vf_id); 690 } 691 692 int rte_pmd_bnxt_get_vf_tx_drop_count(uint16_t port, uint16_t vf_id, 693 uint64_t *count) 694 { 695 struct rte_eth_dev *dev; 696 struct rte_eth_dev_info dev_info; 697 struct bnxt *bp; 698 int rc; 699 700 dev = &rte_eth_devices[port]; 701 if (!is_bnxt_supported(dev)) 702 return -ENOTSUP; 703 704 rc = rte_eth_dev_info_get(port, &dev_info); 705 if (rc != 0) { 706 PMD_DRV_LOG_LINE(ERR, 707 "Error during getting device (port %u) info: %s", 708 port, strerror(-rc)); 709 710 return rc; 711 } 712 bp = dev->data->dev_private; 713 714 if (vf_id >= dev_info.max_vfs) 715 return -EINVAL; 716 717 if (!BNXT_PF(bp)) { 718 PMD_DRV_LOG_LINE(ERR, 719 "Attempt to query VF %d TX drops on non-PF port %d!", 720 vf_id, port); 721 return -ENOTSUP; 722 } 723 724 return bnxt_hwrm_func_qstats_tx_drop(bp, bp->pf->first_vf_id + vf_id, 725 count); 726 } 727 728 int rte_pmd_bnxt_mac_addr_add(uint16_t port, struct rte_ether_addr *addr, 729 uint32_t vf_id) 730 { 731 struct rte_eth_dev *dev; 732 struct rte_eth_dev_info dev_info; 733 struct bnxt *bp; 734 struct bnxt_filter_info *filter; 735 struct bnxt_vnic_info vnic; 736 struct rte_ether_addr dflt_mac; 737 int rc; 738 739 dev = &rte_eth_devices[port]; 740 if (!is_bnxt_supported(dev)) 741 return -ENOTSUP; 742 743 rc = rte_eth_dev_info_get(port, &dev_info); 744 if (rc != 0) { 745 PMD_DRV_LOG_LINE(ERR, 746 "Error during getting device (port %u) info: %s", 747 port, strerror(-rc)); 748 749 return rc; 750 } 751 bp = dev->data->dev_private; 752 753 if (vf_id >= dev_info.max_vfs) 754 return -EINVAL; 755 756 if (!BNXT_PF(bp)) { 757 PMD_DRV_LOG_LINE(ERR, 758 "Attempt to config VF %d MAC on non-PF port %d!", 759 vf_id, port); 760 return -ENOTSUP; 761 } 762 763 /* If the VF currently uses a random MAC, update default to this one */ 764 if (bp->pf->vf_info[vf_id].random_mac) { 765 if (rte_pmd_bnxt_get_vf_rx_status(port, vf_id) <= 0) 766 bnxt_hwrm_func_vf_mac(bp, vf_id, (uint8_t *)addr); 767 } 768 769 /* query the default VNIC id used by the function */ 770 rc = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf_id); 771 if (rc < 0) 772 goto exit; 773 774 memset(&vnic, 0, sizeof(struct bnxt_vnic_info)); 775 vnic.fw_vnic_id = rte_le_to_cpu_16(rc); 776 rc = bnxt_hwrm_vnic_qcfg(bp, &vnic, bp->pf->first_vf_id + vf_id); 777 if (rc < 0) 778 goto exit; 779 780 STAILQ_FOREACH(filter, &bp->pf->vf_info[vf_id].filter, next) { 781 if (filter->flags == 782 HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX && 783 filter->enables == 784 (HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | 785 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK) && 786 memcmp(addr, filter->l2_addr, RTE_ETHER_ADDR_LEN) == 0) { 787 bnxt_hwrm_clear_l2_filter(bp, filter); 788 break; 789 } 790 } 791 792 if (filter == NULL) 793 filter = bnxt_alloc_vf_filter(bp, vf_id); 794 795 filter->fw_l2_filter_id = UINT64_MAX; 796 filter->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; 797 filter->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | 798 HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK; 799 memcpy(filter->l2_addr, addr, RTE_ETHER_ADDR_LEN); 800 memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN); 801 802 /* Do not add a filter for the default MAC */ 803 if (bnxt_hwrm_func_qcfg_vf_default_mac(bp, vf_id, &dflt_mac) || 804 memcmp(filter->l2_addr, dflt_mac.addr_bytes, RTE_ETHER_ADDR_LEN)) 805 rc = bnxt_hwrm_set_l2_filter(bp, vnic.fw_vnic_id, filter); 806 807 exit: 808 return rc; 809 } 810 811 int 812 rte_pmd_bnxt_set_vf_vlan_insert(uint16_t port, uint16_t vf, 813 uint16_t vlan_id) 814 { 815 struct rte_eth_dev *dev; 816 struct rte_eth_dev_info dev_info; 817 struct bnxt *bp; 818 int rc; 819 820 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 821 822 dev = &rte_eth_devices[port]; 823 if (!is_bnxt_supported(dev)) 824 return -ENOTSUP; 825 826 rc = rte_eth_dev_info_get(port, &dev_info); 827 if (rc != 0) { 828 PMD_DRV_LOG_LINE(ERR, 829 "Error during getting device (port %u) info: %s", 830 port, strerror(-rc)); 831 832 return rc; 833 } 834 bp = dev->data->dev_private; 835 836 if (vf >= dev_info.max_vfs) 837 return -EINVAL; 838 839 if (!BNXT_PF(bp)) { 840 PMD_DRV_LOG_LINE(ERR, 841 "Attempt to set VF %d vlan insert on non-PF port %d!", 842 vf, port); 843 return -ENOTSUP; 844 } 845 846 bp->pf->vf_info[vf].dflt_vlan = vlan_id; 847 if (bnxt_hwrm_func_qcfg_current_vf_vlan(bp, vf) == 848 bp->pf->vf_info[vf].dflt_vlan) 849 return 0; 850 851 rc = bnxt_hwrm_set_vf_vlan(bp, vf); 852 853 return rc; 854 } 855 856 int rte_pmd_bnxt_set_vf_persist_stats(uint16_t port, uint16_t vf, uint8_t on) 857 { 858 struct rte_eth_dev_info dev_info; 859 struct rte_eth_dev *dev; 860 uint32_t func_flags; 861 struct bnxt *bp; 862 int rc; 863 864 RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); 865 866 if (on > 1) 867 return -EINVAL; 868 869 dev = &rte_eth_devices[port]; 870 rc = rte_eth_dev_info_get(port, &dev_info); 871 if (rc != 0) { 872 PMD_DRV_LOG_LINE(ERR, 873 "Error during getting device (port %u) info: %s", 874 port, strerror(-rc)); 875 876 return rc; 877 } 878 bp = dev->data->dev_private; 879 880 if (!BNXT_PF(bp)) { 881 PMD_DRV_LOG_LINE(ERR, 882 "Attempt to set persist stats on non-PF port %d!", 883 port); 884 return -EINVAL; 885 } 886 887 if (vf >= dev_info.max_vfs) 888 return -EINVAL; 889 890 /* Prev setting same as new setting. */ 891 if (on == bp->pf->vf_info[vf].persist_stats) 892 return 0; 893 894 func_flags = bp->pf->vf_info[vf].func_cfg_flags; 895 896 if (on) 897 func_flags |= 898 HWRM_FUNC_CFG_INPUT_FLAGS_NO_AUTOCLEAR_STATISTIC; 899 else 900 func_flags &= 901 ~HWRM_FUNC_CFG_INPUT_FLAGS_NO_AUTOCLEAR_STATISTIC; 902 903 rc = bnxt_hwrm_func_cfg_vf_set_flags(bp, vf, func_flags); 904 if (!rc) { 905 bp->pf->vf_info[vf].persist_stats = on; 906 bp->pf->vf_info[vf].func_cfg_flags = func_flags; 907 } 908 909 return rc; 910 } 911