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