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