]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/iavf/iavf_vc_common.c
cxgbe(4): Avoid unsafe hardware access in the ifmedia ioctls.
[FreeBSD/FreeBSD.git] / sys / dev / iavf / iavf_vc_common.c
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 }