The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/iavf/iavf_vc_common.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 }

Cache object: 5c58de359498bf05fc33d73b45431449


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.