xref: /freebsd/sys/dev/iavf/iavf_vc_common.c (revision e9a4d3969a3164d41d41480bacd3520fcf05ccbf)
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