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