1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2021, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Intel Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /** 33 * @file iavf_vc_common.c 34 * @brief Common virtchnl interface functions 35 * 36 * Contains functions implementing the virtchnl interface for connecting to 37 * the PF driver. This file contains the functions which are common between 38 * the legacy and iflib driver implementations. 39 */ 40 #include "iavf_vc_common.h" 41 42 /* busy wait delay in msec */ 43 #define IAVF_BUSY_WAIT_DELAY 10 44 #define IAVF_BUSY_WAIT_COUNT 50 45 46 /* Static function decls */ 47 static void iavf_handle_link_event(struct iavf_sc *sc, 48 struct virtchnl_pf_event *vpe); 49 50 /** 51 * iavf_send_pf_msg - Send virtchnl message to PF device 52 * @sc: device softc 53 * @op: the op to send 54 * @msg: message contents 55 * @len: length of the message 56 * 57 * Send a message to the PF device over the virtchnl connection. Print 58 * a status code if the message reports an error. 59 * 60 * @returns zero on success, or an error code on failure. 61 */ 62 int 63 iavf_send_pf_msg(struct iavf_sc *sc, 64 enum virtchnl_ops op, u8 *msg, u16 len) 65 { 66 struct iavf_hw *hw = &sc->hw; 67 device_t dev = sc->dev; 68 enum iavf_status status; 69 int val_err; 70 71 /* Validating message before sending it to the PF */ 72 val_err = virtchnl_vc_validate_vf_msg(&sc->version, op, msg, len); 73 if (val_err) 74 device_printf(dev, "Error validating msg to PF for op %d," 75 " msglen %d: error %d\n", op, len, val_err); 76 77 if (!iavf_check_asq_alive(hw)) { 78 if (op != VIRTCHNL_OP_GET_STATS) 79 device_printf(dev, "Unable to send opcode %s to PF, " 80 "ASQ is not alive\n", iavf_vc_opcode_str(op)); 81 return (0); 82 } 83 84 if (op != VIRTCHNL_OP_GET_STATS) 85 iavf_dbg_vc(sc, 86 "Sending msg (op=%s[%d]) to PF\n", 87 iavf_vc_opcode_str(op), op); 88 89 status = iavf_aq_send_msg_to_pf(hw, op, IAVF_SUCCESS, msg, len, NULL); 90 if (status && op != VIRTCHNL_OP_GET_STATS) 91 device_printf(dev, "Unable to send opcode %s to PF, " 92 "status %s, aq error %s\n", 93 iavf_vc_opcode_str(op), 94 iavf_stat_str(hw, status), 95 iavf_aq_str(hw, hw->aq.asq_last_status)); 96 97 return (status); 98 } 99 100 /** 101 * iavf_send_api_ver - Send the API version we support to the PF 102 * @sc: device softc 103 * 104 * Send API version admin queue message to the PF. The reply is not checked 105 * in this function. 106 * 107 * @returns 0 if the message was successfully sent, or one of the 108 * IAVF_ADMIN_QUEUE_ERROR_ statuses if not. 109 */ 110 int 111 iavf_send_api_ver(struct iavf_sc *sc) 112 { 113 struct virtchnl_version_info vvi; 114 115 vvi.major = VIRTCHNL_VERSION_MAJOR; 116 vvi.minor = VIRTCHNL_VERSION_MINOR; 117 118 return iavf_send_pf_msg(sc, VIRTCHNL_OP_VERSION, 119 (u8 *)&vvi, sizeof(vvi)); 120 } 121 122 /** 123 * iavf_verify_api_ver - Verify the PF supports our API version 124 * @sc: device softc 125 * 126 * Compare API versions with the PF. Must be called after admin queue is 127 * initialized. 128 * 129 * @returns 0 if API versions match, EIO if they do not, or 130 * IAVF_ERR_ADMIN_QUEUE_NO_WORK if the admin queue is empty. 131 */ 132 int 133 iavf_verify_api_ver(struct iavf_sc *sc) 134 { 135 struct virtchnl_version_info *pf_vvi; 136 struct iavf_hw *hw = &sc->hw; 137 struct iavf_arq_event_info event; 138 enum iavf_status status; 139 device_t dev = sc->dev; 140 int error = 0; 141 int retries = 0; 142 143 event.buf_len = IAVF_AQ_BUF_SZ; 144 event.msg_buf = (u8 *)malloc(event.buf_len, M_IAVF, M_WAITOK); 145 146 for (;;) { 147 if (++retries > IAVF_AQ_MAX_ERR) 148 goto out_alloc; 149 150 /* Initial delay here is necessary */ 151 iavf_msec_pause(100); 152 status = iavf_clean_arq_element(hw, &event, NULL); 153 if (status == IAVF_ERR_ADMIN_QUEUE_NO_WORK) 154 continue; 155 else if (status) { 156 error = EIO; 157 goto out_alloc; 158 } 159 160 if ((enum virtchnl_ops)le32toh(event.desc.cookie_high) != 161 VIRTCHNL_OP_VERSION) { 162 iavf_dbg_vc(sc, "%s: Received unexpected op response: %d\n", 163 __func__, le32toh(event.desc.cookie_high)); 164 /* Don't stop looking for expected response */ 165 continue; 166 } 167 168 status = (enum iavf_status)le32toh(event.desc.cookie_low); 169 if (status) { 170 error = EIO; 171 goto out_alloc; 172 } else 173 break; 174 } 175 176 pf_vvi = (struct virtchnl_version_info *)event.msg_buf; 177 if ((pf_vvi->major > VIRTCHNL_VERSION_MAJOR) || 178 ((pf_vvi->major == VIRTCHNL_VERSION_MAJOR) && 179 (pf_vvi->minor > VIRTCHNL_VERSION_MINOR))) { 180 device_printf(dev, "Critical PF/VF API version mismatch!\n"); 181 error = EIO; 182 } else { 183 sc->version.major = pf_vvi->major; 184 sc->version.minor = pf_vvi->minor; 185 } 186 187 /* Log PF/VF api versions */ 188 device_printf(dev, "PF API %d.%d / VF API %d.%d\n", 189 pf_vvi->major, pf_vvi->minor, 190 VIRTCHNL_VERSION_MAJOR, VIRTCHNL_VERSION_MINOR); 191 192 out_alloc: 193 free(event.msg_buf, M_IAVF); 194 return (error); 195 } 196 197 /** 198 * iavf_send_vf_config_msg - Send VF configuration request 199 * @sc: device softc 200 * 201 * Send VF configuration request admin queue message to the PF. The reply 202 * is not checked in this function. 203 * 204 * @returns 0 if the message was successfully sent, or one of the 205 * IAVF_ADMIN_QUEUE_ERROR_ statuses if not. 206 */ 207 int 208 iavf_send_vf_config_msg(struct iavf_sc *sc) 209 { 210 u32 caps; 211 212 /* Support the base mode functionality, as well as advanced 213 * speed reporting capability. 214 */ 215 caps = VF_BASE_MODE_OFFLOADS | 216 VIRTCHNL_VF_CAP_ADV_LINK_SPEED; 217 218 iavf_dbg_info(sc, "Sending offload flags: 0x%b\n", 219 caps, IAVF_PRINTF_VF_OFFLOAD_FLAGS); 220 221 if (sc->version.minor == VIRTCHNL_VERSION_MINOR_NO_VF_CAPS) 222 return iavf_send_pf_msg(sc, VIRTCHNL_OP_GET_VF_RESOURCES, 223 NULL, 0); 224 else 225 return iavf_send_pf_msg(sc, VIRTCHNL_OP_GET_VF_RESOURCES, 226 (u8 *)&caps, sizeof(caps)); 227 } 228 229 /** 230 * iavf_get_vf_config - Get the VF configuration from the PF 231 * @sc: device softc 232 * 233 * Get VF configuration from PF and populate hw structure. Must be called after 234 * admin queue is initialized. Busy waits until response is received from PF, 235 * with maximum timeout. Response from PF is returned in the buffer for further 236 * processing by the caller. 237 * 238 * @returns zero on success, or an error code on failure 239 */ 240 int 241 iavf_get_vf_config(struct iavf_sc *sc) 242 { 243 struct iavf_hw *hw = &sc->hw; 244 device_t dev = sc->dev; 245 enum iavf_status status = IAVF_SUCCESS; 246 struct iavf_arq_event_info event; 247 u16 len; 248 u32 retries = 0; 249 int error = 0; 250 251 /* Note this assumes a single VSI */ 252 len = sizeof(struct virtchnl_vf_resource) + 253 sizeof(struct virtchnl_vsi_resource); 254 event.buf_len = len; 255 event.msg_buf = (u8 *)malloc(event.buf_len, M_IAVF, M_WAITOK); 256 257 for (;;) { 258 status = iavf_clean_arq_element(hw, &event, NULL); 259 if (status == IAVF_ERR_ADMIN_QUEUE_NO_WORK) { 260 if (++retries <= IAVF_AQ_MAX_ERR) 261 iavf_msec_pause(10); 262 } else if ((enum virtchnl_ops)le32toh(event.desc.cookie_high) != 263 VIRTCHNL_OP_GET_VF_RESOURCES) { 264 iavf_dbg_vc(sc, "%s: Received a response from PF," 265 " opcode %d, error %d", 266 __func__, 267 le32toh(event.desc.cookie_high), 268 le32toh(event.desc.cookie_low)); 269 retries++; 270 continue; 271 } else { 272 status = (enum iavf_status)le32toh(event.desc.cookie_low); 273 if (status) { 274 device_printf(dev, "%s: Error returned from PF," 275 " opcode %d, error %d\n", __func__, 276 le32toh(event.desc.cookie_high), 277 le32toh(event.desc.cookie_low)); 278 error = EIO; 279 goto out_alloc; 280 } 281 /* We retrieved the config message, with no errors */ 282 break; 283 } 284 285 if (retries > IAVF_AQ_MAX_ERR) { 286 iavf_dbg_vc(sc, 287 "%s: Did not receive response after %d tries.", 288 __func__, retries); 289 error = ETIMEDOUT; 290 goto out_alloc; 291 } 292 } 293 294 memcpy(sc->vf_res, event.msg_buf, min(event.msg_len, len)); 295 iavf_vf_parse_hw_config(hw, sc->vf_res); 296 297 out_alloc: 298 free(event.msg_buf, M_IAVF); 299 return (error); 300 } 301 302 /** 303 * iavf_enable_queues - Enable queues 304 * @sc: device softc 305 * 306 * Request that the PF enable all of our queues. 307 * 308 * @remark the reply from the PF is not checked by this function. 309 * 310 * @returns zero 311 */ 312 int 313 iavf_enable_queues(struct iavf_sc *sc) 314 { 315 struct virtchnl_queue_select vqs; 316 struct iavf_vsi *vsi = &sc->vsi; 317 318 vqs.vsi_id = sc->vsi_res->vsi_id; 319 vqs.tx_queues = (1 << IAVF_NTXQS(vsi)) - 1; 320 vqs.rx_queues = vqs.tx_queues; 321 iavf_send_pf_msg(sc, VIRTCHNL_OP_ENABLE_QUEUES, 322 (u8 *)&vqs, sizeof(vqs)); 323 return (0); 324 } 325 326 /** 327 * iavf_disable_queues - Disable queues 328 * @sc: device softc 329 * 330 * Request that the PF disable all of our queues. 331 * 332 * @remark the reply from the PF is not checked by this function. 333 * 334 * @returns zero 335 */ 336 int 337 iavf_disable_queues(struct iavf_sc *sc) 338 { 339 struct virtchnl_queue_select vqs; 340 struct iavf_vsi *vsi = &sc->vsi; 341 342 vqs.vsi_id = sc->vsi_res->vsi_id; 343 vqs.tx_queues = (1 << IAVF_NTXQS(vsi)) - 1; 344 vqs.rx_queues = vqs.tx_queues; 345 iavf_send_pf_msg(sc, VIRTCHNL_OP_DISABLE_QUEUES, 346 (u8 *)&vqs, sizeof(vqs)); 347 return (0); 348 } 349 350 /** 351 * iavf_add_vlans - Add VLAN filters 352 * @sc: device softc 353 * 354 * Scan the Filter List looking for vlans that need 355 * to be added, then create the data to hand to the AQ 356 * for handling. 357 * 358 * @returns zero on success, or an error code on failure. 359 */ 360 int 361 iavf_add_vlans(struct iavf_sc *sc) 362 { 363 struct virtchnl_vlan_filter_list *v; 364 struct iavf_vlan_filter *f, *ftmp; 365 device_t dev = sc->dev; 366 int i = 0, cnt = 0; 367 u32 len; 368 369 /* Get count of VLAN filters to add */ 370 SLIST_FOREACH(f, sc->vlan_filters, next) { 371 if (f->flags & IAVF_FILTER_ADD) 372 cnt++; 373 } 374 375 if (!cnt) /* no work... */ 376 return (ENOENT); 377 378 len = sizeof(struct virtchnl_vlan_filter_list) + 379 (cnt * sizeof(u16)); 380 381 if (len > IAVF_AQ_BUF_SZ) { 382 device_printf(dev, "%s: Exceeded Max AQ Buf size\n", 383 __func__); 384 return (EFBIG); 385 } 386 387 v = (struct virtchnl_vlan_filter_list *)malloc(len, M_IAVF, M_NOWAIT | M_ZERO); 388 if (!v) { 389 device_printf(dev, "%s: unable to allocate memory\n", 390 __func__); 391 return (ENOMEM); 392 } 393 394 v->vsi_id = sc->vsi_res->vsi_id; 395 v->num_elements = cnt; 396 397 /* Scan the filter array */ 398 SLIST_FOREACH_SAFE(f, sc->vlan_filters, next, ftmp) { 399 if (f->flags & IAVF_FILTER_ADD) { 400 bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16)); 401 f->flags = IAVF_FILTER_USED; 402 i++; 403 } 404 if (i == cnt) 405 break; 406 } 407 408 iavf_send_pf_msg(sc, VIRTCHNL_OP_ADD_VLAN, (u8 *)v, len); 409 free(v, M_IAVF); 410 /* add stats? */ 411 return (0); 412 } 413 414 /** 415 * iavf_del_vlans - Delete VLAN filters 416 * @sc: device softc 417 * 418 * Scan the Filter Table looking for vlans that need 419 * to be removed, then create the data to hand to the AQ 420 * for handling. 421 * 422 * @returns zero on success, or an error code on failure. 423 */ 424 int 425 iavf_del_vlans(struct iavf_sc *sc) 426 { 427 struct virtchnl_vlan_filter_list *v; 428 struct iavf_vlan_filter *f, *ftmp; 429 device_t dev = sc->dev; 430 int i = 0, cnt = 0; 431 u32 len; 432 433 /* Get count of VLAN filters to delete */ 434 SLIST_FOREACH(f, sc->vlan_filters, next) { 435 if (f->flags & IAVF_FILTER_DEL) 436 cnt++; 437 } 438 439 if (!cnt) /* no work... */ 440 return (ENOENT); 441 442 len = sizeof(struct virtchnl_vlan_filter_list) + 443 (cnt * sizeof(u16)); 444 445 if (len > IAVF_AQ_BUF_SZ) { 446 device_printf(dev, "%s: Exceeded Max AQ Buf size\n", 447 __func__); 448 return (EFBIG); 449 } 450 451 v = (struct virtchnl_vlan_filter_list *) 452 malloc(len, M_IAVF, M_NOWAIT | M_ZERO); 453 if (!v) { 454 device_printf(dev, "%s: unable to allocate memory\n", 455 __func__); 456 return (ENOMEM); 457 } 458 459 v->vsi_id = sc->vsi_res->vsi_id; 460 v->num_elements = cnt; 461 462 /* Scan the filter array */ 463 SLIST_FOREACH_SAFE(f, sc->vlan_filters, next, ftmp) { 464 if (f->flags & IAVF_FILTER_DEL) { 465 bcopy(&f->vlan, &v->vlan_id[i], sizeof(u16)); 466 i++; 467 SLIST_REMOVE(sc->vlan_filters, f, iavf_vlan_filter, next); 468 free(f, M_IAVF); 469 } 470 if (i == cnt) 471 break; 472 } 473 474 iavf_send_pf_msg(sc, VIRTCHNL_OP_DEL_VLAN, (u8 *)v, len); 475 free(v, M_IAVF); 476 /* add stats? */ 477 return (0); 478 } 479 480 /** 481 * iavf_add_ether_filters - Add MAC filters 482 * @sc: device softc 483 * 484 * This routine takes additions to the vsi filter 485 * table and creates an Admin Queue call to create 486 * the filters in the hardware. 487 * 488 * @returns zero on success, or an error code on failure. 489 */ 490 int 491 iavf_add_ether_filters(struct iavf_sc *sc) 492 { 493 struct virtchnl_ether_addr_list *a; 494 struct iavf_mac_filter *f; 495 device_t dev = sc->dev; 496 int len, j = 0, cnt = 0; 497 int error; 498 499 /* Get count of MAC addresses to add */ 500 SLIST_FOREACH(f, sc->mac_filters, next) { 501 if (f->flags & IAVF_FILTER_ADD) 502 cnt++; 503 } 504 if (cnt == 0) { /* Should not happen... */ 505 iavf_dbg_vc(sc, "%s: cnt == 0, exiting...\n", __func__); 506 return (ENOENT); 507 } 508 509 len = sizeof(struct virtchnl_ether_addr_list) + 510 (cnt * sizeof(struct virtchnl_ether_addr)); 511 512 a = (struct virtchnl_ether_addr_list *) 513 malloc(len, M_IAVF, M_NOWAIT | M_ZERO); 514 if (a == NULL) { 515 device_printf(dev, "%s: Failed to get memory for " 516 "virtchnl_ether_addr_list\n", __func__); 517 return (ENOMEM); 518 } 519 a->vsi_id = sc->vsi.id; 520 a->num_elements = cnt; 521 522 /* Scan the filter array */ 523 SLIST_FOREACH(f, sc->mac_filters, next) { 524 if (f->flags & IAVF_FILTER_ADD) { 525 bcopy(f->macaddr, a->list[j].addr, ETHER_ADDR_LEN); 526 f->flags &= ~IAVF_FILTER_ADD; 527 j++; 528 529 iavf_dbg_vc(sc, "%s: ADD: " MAC_FORMAT "\n", 530 __func__, MAC_FORMAT_ARGS(f->macaddr)); 531 } 532 if (j == cnt) 533 break; 534 } 535 iavf_dbg_vc(sc, "%s: len %d, j %d, cnt %d\n", __func__, 536 len, j, cnt); 537 538 error = iavf_send_pf_msg(sc, 539 VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)a, len); 540 /* add stats? */ 541 free(a, M_IAVF); 542 return (error); 543 } 544 545 /** 546 * iavf_del_ether_filters - Delete MAC filters 547 * @sc: device softc 548 * 549 * This routine takes filters flagged for deletion in the 550 * sc MAC filter list and creates an Admin Queue call 551 * to delete those filters in the hardware. 552 * 553 * @returns zero on success, or an error code on failure. 554 */ 555 int 556 iavf_del_ether_filters(struct iavf_sc *sc) 557 { 558 struct virtchnl_ether_addr_list *d; 559 struct iavf_mac_filter *f, *f_temp; 560 device_t dev = sc->dev; 561 int len, j = 0, cnt = 0; 562 563 /* Get count of MAC addresses to delete */ 564 SLIST_FOREACH(f, sc->mac_filters, next) { 565 if (f->flags & IAVF_FILTER_DEL) 566 cnt++; 567 } 568 if (cnt == 0) { 569 iavf_dbg_vc(sc, "%s: cnt == 0, exiting...\n", __func__); 570 return (ENOENT); 571 } 572 573 len = sizeof(struct virtchnl_ether_addr_list) + 574 (cnt * sizeof(struct virtchnl_ether_addr)); 575 576 d = (struct virtchnl_ether_addr_list *) 577 malloc(len, M_IAVF, M_NOWAIT | M_ZERO); 578 if (d == NULL) { 579 device_printf(dev, "%s: Failed to get memory for " 580 "virtchnl_ether_addr_list\n", __func__); 581 return (ENOMEM); 582 } 583 d->vsi_id = sc->vsi.id; 584 d->num_elements = cnt; 585 586 /* Scan the filter array */ 587 SLIST_FOREACH_SAFE(f, sc->mac_filters, next, f_temp) { 588 if (f->flags & IAVF_FILTER_DEL) { 589 bcopy(f->macaddr, d->list[j].addr, ETHER_ADDR_LEN); 590 iavf_dbg_vc(sc, "DEL: " MAC_FORMAT "\n", 591 MAC_FORMAT_ARGS(f->macaddr)); 592 j++; 593 SLIST_REMOVE(sc->mac_filters, f, iavf_mac_filter, next); 594 free(f, M_IAVF); 595 } 596 if (j == cnt) 597 break; 598 } 599 iavf_send_pf_msg(sc, 600 VIRTCHNL_OP_DEL_ETH_ADDR, (u8 *)d, len); 601 /* add stats? */ 602 free(d, M_IAVF); 603 return (0); 604 } 605 606 /** 607 * iavf_request_reset - Request a device reset 608 * @sc: device softc 609 * 610 * Request that the PF reset this VF. No response is expected. 611 * 612 * @returns zero 613 */ 614 int 615 iavf_request_reset(struct iavf_sc *sc) 616 { 617 /* 618 ** Set the reset status to "in progress" before 619 ** the request, this avoids any possibility of 620 ** a mistaken early detection of completion. 621 */ 622 wr32(&sc->hw, IAVF_VFGEN_RSTAT, VIRTCHNL_VFR_INPROGRESS); 623 iavf_send_pf_msg(sc, VIRTCHNL_OP_RESET_VF, NULL, 0); 624 return (0); 625 } 626 627 /** 628 * iavf_request_stats - Request VF stats 629 * @sc: device softc 630 * 631 * Request the statistics for this VF's VSI from PF. 632 * 633 * @remark prints an error message on failure to obtain stats, but does not 634 * return with an error code. 635 * 636 * @returns zero 637 */ 638 int 639 iavf_request_stats(struct iavf_sc *sc) 640 { 641 struct virtchnl_queue_select vqs; 642 int error = 0; 643 644 vqs.vsi_id = sc->vsi_res->vsi_id; 645 /* Low priority, we don't need to error check */ 646 error = iavf_send_pf_msg(sc, VIRTCHNL_OP_GET_STATS, 647 (u8 *)&vqs, sizeof(vqs)); 648 if (error) 649 device_printf(sc->dev, "Error sending stats request to PF: %d\n", error); 650 651 return (0); 652 } 653 654 /** 655 * iavf_update_stats_counters - Update driver statistics 656 * @sc: device softc 657 * @es: ethernet stats storage 658 * 659 * Updates driver's stats counters with VSI stats returned from PF. 660 */ 661 void 662 iavf_update_stats_counters(struct iavf_sc *sc, struct iavf_eth_stats *es) 663 { 664 struct iavf_vsi *vsi = &sc->vsi; 665 uint64_t tx_discards; 666 667 tx_discards = es->tx_discards; 668 669 /* Update ifnet stats */ 670 IAVF_SET_IPACKETS(vsi, es->rx_unicast + 671 es->rx_multicast + 672 es->rx_broadcast); 673 IAVF_SET_OPACKETS(vsi, es->tx_unicast + 674 es->tx_multicast + 675 es->tx_broadcast); 676 IAVF_SET_IBYTES(vsi, es->rx_bytes); 677 IAVF_SET_OBYTES(vsi, es->tx_bytes); 678 IAVF_SET_IMCASTS(vsi, es->rx_multicast); 679 IAVF_SET_OMCASTS(vsi, es->tx_multicast); 680 681 IAVF_SET_OERRORS(vsi, es->tx_errors); 682 IAVF_SET_IQDROPS(vsi, es->rx_discards); 683 IAVF_SET_OQDROPS(vsi, tx_discards); 684 IAVF_SET_NOPROTO(vsi, es->rx_unknown_protocol); 685 IAVF_SET_COLLISIONS(vsi, 0); 686 687 vsi->eth_stats = *es; 688 } 689 690 /** 691 * iavf_config_rss_key - Configure RSS key over virtchnl 692 * @sc: device softc 693 * 694 * Send a message to the PF to configure the RSS key using the virtchnl 695 * interface. 696 * 697 * @remark this does not check the reply from the PF. 698 * 699 * @returns zero on success, or an error code on failure. 700 */ 701 int 702 iavf_config_rss_key(struct iavf_sc *sc) 703 { 704 struct virtchnl_rss_key *rss_key_msg; 705 int msg_len, key_length; 706 u8 rss_seed[IAVF_RSS_KEY_SIZE]; 707 708 #ifdef RSS 709 /* Fetch the configured RSS key */ 710 rss_getkey((uint8_t *) &rss_seed); 711 #else 712 iavf_get_default_rss_key((u32 *)rss_seed); 713 #endif 714 715 /* Send the fetched key */ 716 key_length = IAVF_RSS_KEY_SIZE; 717 msg_len = sizeof(struct virtchnl_rss_key) + (sizeof(u8) * key_length) - 1; 718 rss_key_msg = (struct virtchnl_rss_key *) 719 malloc(msg_len, M_IAVF, M_NOWAIT | M_ZERO); 720 if (rss_key_msg == NULL) { 721 device_printf(sc->dev, "Unable to allocate msg memory for RSS key msg.\n"); 722 return (ENOMEM); 723 } 724 725 rss_key_msg->vsi_id = sc->vsi_res->vsi_id; 726 rss_key_msg->key_len = key_length; 727 bcopy(rss_seed, &rss_key_msg->key[0], key_length); 728 729 iavf_dbg_vc(sc, "%s: vsi_id %d, key_len %d\n", __func__, 730 rss_key_msg->vsi_id, rss_key_msg->key_len); 731 732 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_RSS_KEY, 733 (u8 *)rss_key_msg, msg_len); 734 735 free(rss_key_msg, M_IAVF); 736 return (0); 737 } 738 739 /** 740 * iavf_set_rss_hena - Configure the RSS HENA 741 * @sc: device softc 742 * 743 * Configure the RSS HENA values by sending a virtchnl message to the PF 744 * 745 * @remark the reply from the PF is not checked by this function. 746 * 747 * @returns zero 748 */ 749 int 750 iavf_set_rss_hena(struct iavf_sc *sc) 751 { 752 struct virtchnl_rss_hena hena; 753 struct iavf_hw *hw = &sc->hw; 754 755 if (hw->mac.type == IAVF_MAC_VF) 756 hena.hena = IAVF_DEFAULT_RSS_HENA_AVF; 757 else if (hw->mac.type == IAVF_MAC_X722_VF) 758 hena.hena = IAVF_DEFAULT_RSS_HENA_X722; 759 else 760 hena.hena = IAVF_DEFAULT_RSS_HENA_BASE; 761 762 iavf_send_pf_msg(sc, VIRTCHNL_OP_SET_RSS_HENA, 763 (u8 *)&hena, sizeof(hena)); 764 return (0); 765 } 766 767 /** 768 * iavf_config_rss_lut - Configure RSS lookup table 769 * @sc: device softc 770 * 771 * Configure the RSS lookup table by sending a virtchnl message to the PF. 772 * 773 * @remark the reply from the PF is not checked in this function. 774 * 775 * @returns zero on success, or an error code on failure. 776 */ 777 int 778 iavf_config_rss_lut(struct iavf_sc *sc) 779 { 780 struct virtchnl_rss_lut *rss_lut_msg; 781 int msg_len; 782 u16 lut_length; 783 u32 lut; 784 int i, que_id; 785 786 lut_length = IAVF_RSS_VSI_LUT_SIZE; 787 msg_len = sizeof(struct virtchnl_rss_lut) + (lut_length * sizeof(u8)) - 1; 788 rss_lut_msg = (struct virtchnl_rss_lut *) 789 malloc(msg_len, M_IAVF, M_NOWAIT | M_ZERO); 790 if (rss_lut_msg == NULL) { 791 device_printf(sc->dev, "Unable to allocate msg memory for RSS lut msg.\n"); 792 return (ENOMEM); 793 } 794 795 rss_lut_msg->vsi_id = sc->vsi_res->vsi_id; 796 /* Each LUT entry is a max of 1 byte, so this is easy */ 797 rss_lut_msg->lut_entries = lut_length; 798 799 /* Populate the LUT with max no. of queues in round robin fashion */ 800 for (i = 0; i < lut_length; i++) { 801 #ifdef RSS 802 /* 803 * Fetch the RSS bucket id for the given indirection entry. 804 * Cap it at the number of configured buckets (which is 805 * num_queues.) 806 */ 807 que_id = rss_get_indirection_to_bucket(i); 808 que_id = que_id % sc->vsi.num_rx_queues; 809 #else 810 que_id = i % sc->vsi.num_rx_queues; 811 #endif 812 lut = que_id & IAVF_RSS_VSI_LUT_ENTRY_MASK; 813 rss_lut_msg->lut[i] = lut; 814 } 815 816 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_RSS_LUT, 817 (u8 *)rss_lut_msg, msg_len); 818 819 free(rss_lut_msg, M_IAVF); 820 return (0); 821 } 822 823 /** 824 * iavf_config_promisc_mode - Configure promiscuous mode 825 * @sc: device softc 826 * 827 * Configure the device into promiscuous mode by sending a virtchnl message to 828 * the PF. 829 * 830 * @remark the reply from the PF is not checked in this function. 831 * 832 * @returns zero 833 */ 834 int 835 iavf_config_promisc_mode(struct iavf_sc *sc) 836 { 837 struct virtchnl_promisc_info pinfo; 838 839 pinfo.vsi_id = sc->vsi_res->vsi_id; 840 pinfo.flags = sc->promisc_flags; 841 842 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, 843 (u8 *)&pinfo, sizeof(pinfo)); 844 return (0); 845 } 846 847 /** 848 * iavf_vc_send_cmd - Convert request into virtchnl calls 849 * @sc: device softc 850 * @request: the requested command to run 851 * 852 * Send the proper virtchnl call based on the request value. 853 * 854 * @returns zero on success, or an error code on failure. Note that unknown 855 * requests will return zero. 856 */ 857 int 858 iavf_vc_send_cmd(struct iavf_sc *sc, uint32_t request) 859 { 860 switch (request) { 861 case IAVF_FLAG_AQ_MAP_VECTORS: 862 return iavf_map_queues(sc); 863 864 case IAVF_FLAG_AQ_ADD_MAC_FILTER: 865 return iavf_add_ether_filters(sc); 866 867 case IAVF_FLAG_AQ_ADD_VLAN_FILTER: 868 return iavf_add_vlans(sc); 869 870 case IAVF_FLAG_AQ_DEL_MAC_FILTER: 871 return iavf_del_ether_filters(sc); 872 873 case IAVF_FLAG_AQ_DEL_VLAN_FILTER: 874 return iavf_del_vlans(sc); 875 876 case IAVF_FLAG_AQ_CONFIGURE_QUEUES: 877 return iavf_configure_queues(sc); 878 879 case IAVF_FLAG_AQ_DISABLE_QUEUES: 880 return iavf_disable_queues(sc); 881 882 case IAVF_FLAG_AQ_ENABLE_QUEUES: 883 return iavf_enable_queues(sc); 884 885 case IAVF_FLAG_AQ_CONFIG_RSS_KEY: 886 return iavf_config_rss_key(sc); 887 888 case IAVF_FLAG_AQ_SET_RSS_HENA: 889 return iavf_set_rss_hena(sc); 890 891 case IAVF_FLAG_AQ_CONFIG_RSS_LUT: 892 return iavf_config_rss_lut(sc); 893 894 case IAVF_FLAG_AQ_CONFIGURE_PROMISC: 895 return iavf_config_promisc_mode(sc); 896 } 897 898 return (0); 899 } 900 901 /** 902 * iavf_vc_get_op_chan - Get op channel for a request 903 * @sc: device softc 904 * @request: the request type 905 * 906 * @returns the op channel for the given request, or NULL if no channel is 907 * used. 908 */ 909 void * 910 iavf_vc_get_op_chan(struct iavf_sc *sc, uint32_t request) 911 { 912 switch (request) { 913 case IAVF_FLAG_AQ_ENABLE_QUEUES: 914 return (&sc->enable_queues_chan); 915 case IAVF_FLAG_AQ_DISABLE_QUEUES: 916 return (&sc->disable_queues_chan); 917 default: 918 return (NULL); 919 } 920 } 921 922 /** 923 * iavf_vc_stat_str - convert virtchnl status err code to a string 924 * @hw: pointer to the HW structure 925 * @stat_err: the status error code to convert 926 * 927 * @returns the human readable string representing the specified error code. 928 **/ 929 const char * 930 iavf_vc_stat_str(struct iavf_hw *hw, enum virtchnl_status_code stat_err) 931 { 932 switch (stat_err) { 933 case VIRTCHNL_STATUS_SUCCESS: 934 return "OK"; 935 case VIRTCHNL_ERR_PARAM: 936 return "VIRTCHNL_ERR_PARAM"; 937 case VIRTCHNL_STATUS_ERR_NO_MEMORY: 938 return "VIRTCHNL_STATUS_ERR_NO_MEMORY"; 939 case VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH: 940 return "VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH"; 941 case VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR: 942 return "VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR"; 943 case VIRTCHNL_STATUS_ERR_INVALID_VF_ID: 944 return "VIRTCHNL_STATUS_ERR_INVALID_VF_ID"; 945 case VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR: 946 return "VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR"; 947 case VIRTCHNL_STATUS_NOT_SUPPORTED: 948 return "VIRTCHNL_STATUS_NOT_SUPPORTED"; 949 } 950 951 snprintf(hw->err_str, sizeof(hw->err_str), "%d", stat_err); 952 return hw->err_str; 953 } 954 955 /** 956 * iavf_adv_speed_to_ext_speed - Convert numeric speed to iavf speed enum 957 * @adv_link_speed: link speed in Mb/s 958 * 959 * Converts the link speed from the "advanced" link speed virtchnl op into the 960 * closest approximation of the internal iavf link speed, rounded down. 961 * 962 * @returns the link speed as an iavf_ext_link_speed enum value 963 */ 964 enum iavf_ext_link_speed 965 iavf_adv_speed_to_ext_speed(u32 adv_link_speed) 966 { 967 if (adv_link_speed >= 100000) 968 return IAVF_EXT_LINK_SPEED_100GB; 969 if (adv_link_speed >= 50000) 970 return IAVF_EXT_LINK_SPEED_50GB; 971 if (adv_link_speed >= 40000) 972 return IAVF_EXT_LINK_SPEED_40GB; 973 if (adv_link_speed >= 25000) 974 return IAVF_EXT_LINK_SPEED_25GB; 975 if (adv_link_speed >= 20000) 976 return IAVF_EXT_LINK_SPEED_20GB; 977 if (adv_link_speed >= 10000) 978 return IAVF_EXT_LINK_SPEED_10GB; 979 if (adv_link_speed >= 5000) 980 return IAVF_EXT_LINK_SPEED_5GB; 981 if (adv_link_speed >= 2500) 982 return IAVF_EXT_LINK_SPEED_2500MB; 983 if (adv_link_speed >= 1000) 984 return IAVF_EXT_LINK_SPEED_1000MB; 985 if (adv_link_speed >= 100) 986 return IAVF_EXT_LINK_SPEED_100MB; 987 if (adv_link_speed >= 10) 988 return IAVF_EXT_LINK_SPEED_10MB; 989 990 return IAVF_EXT_LINK_SPEED_UNKNOWN; 991 } 992 993 /** 994 * iavf_ext_speed_to_ifmedia - Convert internal iavf speed to ifmedia value 995 * @link_speed: the link speed 996 * 997 * @remark this is sort of a hack, because we don't actually know what media 998 * type the VF is running on. In an ideal world we might just report the media 999 * type as "virtual" and have another mechanism for reporting the link 1000 * speed. 1001 * 1002 * @returns a suitable ifmedia type for the given link speed. 1003 */ 1004 u32 1005 iavf_ext_speed_to_ifmedia(enum iavf_ext_link_speed link_speed) 1006 { 1007 switch (link_speed) { 1008 case IAVF_EXT_LINK_SPEED_100GB: 1009 return IFM_100G_SR4; 1010 case IAVF_EXT_LINK_SPEED_50GB: 1011 return IFM_50G_SR2; 1012 case IAVF_EXT_LINK_SPEED_40GB: 1013 return IFM_40G_SR4; 1014 case IAVF_EXT_LINK_SPEED_25GB: 1015 return IFM_25G_SR; 1016 case IAVF_EXT_LINK_SPEED_20GB: 1017 return IFM_20G_KR2; 1018 case IAVF_EXT_LINK_SPEED_10GB: 1019 return IFM_10G_SR; 1020 case IAVF_EXT_LINK_SPEED_5GB: 1021 return IFM_5000_T; 1022 case IAVF_EXT_LINK_SPEED_2500MB: 1023 return IFM_2500_T; 1024 case IAVF_EXT_LINK_SPEED_1000MB: 1025 return IFM_1000_T; 1026 case IAVF_EXT_LINK_SPEED_100MB: 1027 return IFM_100_TX; 1028 case IAVF_EXT_LINK_SPEED_10MB: 1029 return IFM_10_T; 1030 case IAVF_EXT_LINK_SPEED_UNKNOWN: 1031 default: 1032 return IFM_UNKNOWN; 1033 } 1034 } 1035 1036 /** 1037 * iavf_vc_speed_to_ext_speed - Convert virtchnl speed enum to native iavf 1038 * driver speed representation. 1039 * @link_speed: link speed enum value 1040 * 1041 * @returns the link speed in the native iavf format. 1042 */ 1043 enum iavf_ext_link_speed 1044 iavf_vc_speed_to_ext_speed(enum virtchnl_link_speed link_speed) 1045 { 1046 switch (link_speed) { 1047 case VIRTCHNL_LINK_SPEED_40GB: 1048 return IAVF_EXT_LINK_SPEED_40GB; 1049 case VIRTCHNL_LINK_SPEED_25GB: 1050 return IAVF_EXT_LINK_SPEED_25GB; 1051 case VIRTCHNL_LINK_SPEED_20GB: 1052 return IAVF_EXT_LINK_SPEED_20GB; 1053 case VIRTCHNL_LINK_SPEED_10GB: 1054 return IAVF_EXT_LINK_SPEED_10GB; 1055 case VIRTCHNL_LINK_SPEED_1GB: 1056 return IAVF_EXT_LINK_SPEED_1000MB; 1057 case VIRTCHNL_LINK_SPEED_100MB: 1058 return IAVF_EXT_LINK_SPEED_100MB; 1059 case VIRTCHNL_LINK_SPEED_UNKNOWN: 1060 default: 1061 return IAVF_EXT_LINK_SPEED_UNKNOWN; 1062 } 1063 } 1064 1065 /** 1066 * iavf_vc_speed_to_string - Convert virtchnl speed to a string 1067 * @link_speed: the speed to convert 1068 * 1069 * @returns string representing the link speed as reported by the virtchnl 1070 * interface. 1071 */ 1072 const char * 1073 iavf_vc_speed_to_string(enum virtchnl_link_speed link_speed) 1074 { 1075 return iavf_ext_speed_to_str(iavf_vc_speed_to_ext_speed(link_speed)); 1076 } 1077 1078 /** 1079 * iavf_ext_speed_to_str - Convert iavf speed enum to string representation 1080 * @link_speed: link speed enum value 1081 * 1082 * XXX: This is an iavf-modified copy of ice_aq_speed_to_str() 1083 * 1084 * @returns the string representation of the given link speed. 1085 */ 1086 const char * 1087 iavf_ext_speed_to_str(enum iavf_ext_link_speed link_speed) 1088 { 1089 switch (link_speed) { 1090 case IAVF_EXT_LINK_SPEED_100GB: 1091 return "100 Gbps"; 1092 case IAVF_EXT_LINK_SPEED_50GB: 1093 return "50 Gbps"; 1094 case IAVF_EXT_LINK_SPEED_40GB: 1095 return "40 Gbps"; 1096 case IAVF_EXT_LINK_SPEED_25GB: 1097 return "25 Gbps"; 1098 case IAVF_EXT_LINK_SPEED_20GB: 1099 return "20 Gbps"; 1100 case IAVF_EXT_LINK_SPEED_10GB: 1101 return "10 Gbps"; 1102 case IAVF_EXT_LINK_SPEED_5GB: 1103 return "5 Gbps"; 1104 case IAVF_EXT_LINK_SPEED_2500MB: 1105 return "2.5 Gbps"; 1106 case IAVF_EXT_LINK_SPEED_1000MB: 1107 return "1 Gbps"; 1108 case IAVF_EXT_LINK_SPEED_100MB: 1109 return "100 Mbps"; 1110 case IAVF_EXT_LINK_SPEED_10MB: 1111 return "10 Mbps"; 1112 case IAVF_EXT_LINK_SPEED_UNKNOWN: 1113 default: 1114 return "Unknown"; 1115 } 1116 } 1117 1118 /** 1119 * iavf_vc_opcode_str - Convert virtchnl opcode to string 1120 * @op: the virtchnl op code 1121 * 1122 * @returns the string representation of the given virtchnl op code 1123 */ 1124 const char * 1125 iavf_vc_opcode_str(uint16_t op) 1126 { 1127 switch (op) { 1128 case VIRTCHNL_OP_VERSION: 1129 return ("VERSION"); 1130 case VIRTCHNL_OP_RESET_VF: 1131 return ("RESET_VF"); 1132 case VIRTCHNL_OP_GET_VF_RESOURCES: 1133 return ("GET_VF_RESOURCES"); 1134 case VIRTCHNL_OP_CONFIG_TX_QUEUE: 1135 return ("CONFIG_TX_QUEUE"); 1136 case VIRTCHNL_OP_CONFIG_RX_QUEUE: 1137 return ("CONFIG_RX_QUEUE"); 1138 case VIRTCHNL_OP_CONFIG_VSI_QUEUES: 1139 return ("CONFIG_VSI_QUEUES"); 1140 case VIRTCHNL_OP_CONFIG_IRQ_MAP: 1141 return ("CONFIG_IRQ_MAP"); 1142 case VIRTCHNL_OP_ENABLE_QUEUES: 1143 return ("ENABLE_QUEUES"); 1144 case VIRTCHNL_OP_DISABLE_QUEUES: 1145 return ("DISABLE_QUEUES"); 1146 case VIRTCHNL_OP_ADD_ETH_ADDR: 1147 return ("ADD_ETH_ADDR"); 1148 case VIRTCHNL_OP_DEL_ETH_ADDR: 1149 return ("DEL_ETH_ADDR"); 1150 case VIRTCHNL_OP_ADD_VLAN: 1151 return ("ADD_VLAN"); 1152 case VIRTCHNL_OP_DEL_VLAN: 1153 return ("DEL_VLAN"); 1154 case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: 1155 return ("CONFIG_PROMISCUOUS_MODE"); 1156 case VIRTCHNL_OP_GET_STATS: 1157 return ("GET_STATS"); 1158 case VIRTCHNL_OP_RSVD: 1159 return ("RSVD"); 1160 case VIRTCHNL_OP_EVENT: 1161 return ("EVENT"); 1162 case VIRTCHNL_OP_CONFIG_RSS_KEY: 1163 return ("CONFIG_RSS_KEY"); 1164 case VIRTCHNL_OP_CONFIG_RSS_LUT: 1165 return ("CONFIG_RSS_LUT"); 1166 case VIRTCHNL_OP_GET_RSS_HENA_CAPS: 1167 return ("GET_RSS_HENA_CAPS"); 1168 case VIRTCHNL_OP_SET_RSS_HENA: 1169 return ("SET_RSS_HENA"); 1170 default: 1171 return ("UNKNOWN"); 1172 } 1173 } 1174 1175 /** 1176 * iavf_vc_completion - Handle PF reply messages 1177 * @sc: device softc 1178 * @v_opcode: virtchnl op code 1179 * @v_retval: virtchnl return value 1180 * @msg: the message to send 1181 * @msglen: length of the msg buffer 1182 * 1183 * Asynchronous completion function for admin queue messages. Rather than busy 1184 * wait, we fire off our requests and assume that no errors will be returned. 1185 * This function handles the reply messages. 1186 */ 1187 void 1188 iavf_vc_completion(struct iavf_sc *sc, 1189 enum virtchnl_ops v_opcode, 1190 enum virtchnl_status_code v_retval, u8 *msg, u16 msglen __unused) 1191 { 1192 device_t dev = sc->dev; 1193 1194 if (v_opcode != VIRTCHNL_OP_GET_STATS) 1195 iavf_dbg_vc(sc, "%s: opcode %s\n", __func__, 1196 iavf_vc_opcode_str(v_opcode)); 1197 1198 if (v_opcode == VIRTCHNL_OP_EVENT) { 1199 struct virtchnl_pf_event *vpe = 1200 (struct virtchnl_pf_event *)msg; 1201 1202 switch (vpe->event) { 1203 case VIRTCHNL_EVENT_LINK_CHANGE: 1204 iavf_handle_link_event(sc, vpe); 1205 break; 1206 case VIRTCHNL_EVENT_RESET_IMPENDING: 1207 device_printf(dev, "PF initiated reset!\n"); 1208 iavf_set_state(&sc->state, IAVF_STATE_RESET_PENDING); 1209 break; 1210 default: 1211 iavf_dbg_vc(sc, "Unknown event %d from AQ\n", 1212 vpe->event); 1213 break; 1214 } 1215 1216 return; 1217 } 1218 1219 /* Catch-all error response */ 1220 if (v_retval) { 1221 bool print_error = true; 1222 1223 switch (v_opcode) { 1224 case VIRTCHNL_OP_ADD_ETH_ADDR: 1225 device_printf(dev, "WARNING: Error adding VF mac filter!\n"); 1226 device_printf(dev, "WARNING: Device may not receive traffic!\n"); 1227 break; 1228 case VIRTCHNL_OP_ENABLE_QUEUES: 1229 sc->enable_queues_chan = 1; 1230 wakeup_one(&sc->enable_queues_chan); 1231 break; 1232 case VIRTCHNL_OP_DISABLE_QUEUES: 1233 sc->disable_queues_chan = 1; 1234 wakeup_one(&sc->disable_queues_chan); 1235 /* This may fail, but it does not necessarily mean that 1236 * something is critically wrong. 1237 */ 1238 if (!(sc->dbg_mask & IAVF_DBG_VC)) 1239 print_error = false; 1240 break; 1241 default: 1242 break; 1243 } 1244 1245 if (print_error) 1246 device_printf(dev, 1247 "%s: AQ returned error %s to our request %s!\n", 1248 __func__, iavf_vc_stat_str(&sc->hw, v_retval), 1249 iavf_vc_opcode_str(v_opcode)); 1250 return; 1251 } 1252 1253 switch (v_opcode) { 1254 case VIRTCHNL_OP_GET_STATS: 1255 iavf_update_stats_counters(sc, (struct iavf_eth_stats *)msg); 1256 break; 1257 case VIRTCHNL_OP_ADD_ETH_ADDR: 1258 break; 1259 case VIRTCHNL_OP_DEL_ETH_ADDR: 1260 break; 1261 case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: 1262 break; 1263 case VIRTCHNL_OP_ADD_VLAN: 1264 break; 1265 case VIRTCHNL_OP_DEL_VLAN: 1266 break; 1267 case VIRTCHNL_OP_ENABLE_QUEUES: 1268 atomic_store_rel_32(&sc->queues_enabled, 1); 1269 sc->enable_queues_chan = 1; 1270 wakeup_one(&sc->enable_queues_chan); 1271 break; 1272 case VIRTCHNL_OP_DISABLE_QUEUES: 1273 atomic_store_rel_32(&sc->queues_enabled, 0); 1274 sc->disable_queues_chan = 1; 1275 wakeup_one(&sc->disable_queues_chan); 1276 break; 1277 case VIRTCHNL_OP_CONFIG_VSI_QUEUES: 1278 break; 1279 case VIRTCHNL_OP_CONFIG_IRQ_MAP: 1280 break; 1281 case VIRTCHNL_OP_CONFIG_RSS_KEY: 1282 break; 1283 case VIRTCHNL_OP_SET_RSS_HENA: 1284 break; 1285 case VIRTCHNL_OP_CONFIG_RSS_LUT: 1286 break; 1287 default: 1288 iavf_dbg_vc(sc, 1289 "Received unexpected message %s from PF.\n", 1290 iavf_vc_opcode_str(v_opcode)); 1291 break; 1292 } 1293 } 1294 1295 /** 1296 * iavf_handle_link_event - Handle Link event virtchml message 1297 * @sc: device softc 1298 * @vpe: virtchnl PF link event structure 1299 * 1300 * Process a virtchnl PF link event and update the driver and stack status of 1301 * the link event. 1302 */ 1303 static void 1304 iavf_handle_link_event(struct iavf_sc *sc, struct virtchnl_pf_event *vpe) 1305 { 1306 MPASS(vpe->event == VIRTCHNL_EVENT_LINK_CHANGE); 1307 1308 if (sc->vf_res->vf_cap_flags & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) 1309 { 1310 iavf_dbg_vc(sc, "Link change (adv): status %d, speed %u\n", 1311 vpe->event_data.link_event_adv.link_status, 1312 vpe->event_data.link_event_adv.link_speed); 1313 sc->link_up = 1314 vpe->event_data.link_event_adv.link_status; 1315 sc->link_speed_adv = 1316 vpe->event_data.link_event_adv.link_speed; 1317 1318 } else { 1319 iavf_dbg_vc(sc, "Link change: status %d, speed %x\n", 1320 vpe->event_data.link_event.link_status, 1321 vpe->event_data.link_event.link_speed); 1322 sc->link_up = 1323 vpe->event_data.link_event.link_status; 1324 sc->link_speed = 1325 vpe->event_data.link_event.link_speed; 1326 } 1327 1328 iavf_update_link_status(sc); 1329 } 1330