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