1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright (c) 2021, Intel Corporation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
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.
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.
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.
34 * @file iavf_vc_common.c
35 * @brief Common virtchnl interface functions
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.
41 #include "iavf_vc_common.h"
43 /* busy wait delay in msec */
44 #define IAVF_BUSY_WAIT_DELAY 10
45 #define IAVF_BUSY_WAIT_COUNT 50
47 /* Static function decls */
48 static void iavf_handle_link_event(struct iavf_sc *sc,
49 struct virtchnl_pf_event *vpe);
52 * iavf_send_pf_msg - Send virtchnl message to PF device
55 * @msg: message contents
56 * @len: length of the message
58 * Send a message to the PF device over the virtchnl connection. Print
59 * a status code if the message reports an error.
61 * @returns zero on success, or an error code on failure.
64 iavf_send_pf_msg(struct iavf_sc *sc,
65 enum virtchnl_ops op, u8 *msg, u16 len)
67 struct iavf_hw *hw = &sc->hw;
68 device_t dev = sc->dev;
69 enum iavf_status status;
72 /* Validating message before sending it to the PF */
73 val_err = virtchnl_vc_validate_vf_msg(&sc->version, op, msg, len);
75 device_printf(dev, "Error validating msg to PF for op %d,"
76 " msglen %d: error %d\n", op, len, val_err);
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));
85 if (op != VIRTCHNL_OP_GET_STATS)
87 "Sending msg (op=%s[%d]) to PF\n",
88 iavf_vc_opcode_str(op), op);
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));
102 * iavf_send_api_ver - Send the API version we support to the PF
105 * Send API version admin queue message to the PF. The reply is not checked
108 * @returns 0 if the message was successfully sent, or one of the
109 * IAVF_ADMIN_QUEUE_ERROR_ statuses if not.
112 iavf_send_api_ver(struct iavf_sc *sc)
114 struct virtchnl_version_info vvi;
116 vvi.major = VIRTCHNL_VERSION_MAJOR;
117 vvi.minor = VIRTCHNL_VERSION_MINOR;
119 return iavf_send_pf_msg(sc, VIRTCHNL_OP_VERSION,
120 (u8 *)&vvi, sizeof(vvi));
124 * iavf_verify_api_ver - Verify the PF supports our API version
127 * Compare API versions with the PF. Must be called after admin queue is
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.
134 iavf_verify_api_ver(struct iavf_sc *sc)
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;
144 event.buf_len = IAVF_AQ_BUF_SZ;
145 event.msg_buf = (u8 *)malloc(event.buf_len, M_IAVF, M_WAITOK);
148 if (++retries > IAVF_AQ_MAX_ERR)
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)
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 */
169 status = (enum iavf_status)le32toh(event.desc.cookie_low);
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");
184 sc->version.major = pf_vvi->major;
185 sc->version.minor = pf_vvi->minor;
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);
194 free(event.msg_buf, M_IAVF);
199 * iavf_send_vf_config_msg - Send VF configuration request
202 * Send VF configuration request admin queue message to the PF. The reply
203 * is not checked in this function.
205 * @returns 0 if the message was successfully sent, or one of the
206 * IAVF_ADMIN_QUEUE_ERROR_ statuses if not.
209 iavf_send_vf_config_msg(struct iavf_sc *sc)
213 /* Support the base mode functionality, as well as advanced
214 * speed reporting capability.
216 caps = VF_BASE_MODE_OFFLOADS |
217 VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
219 iavf_dbg_info(sc, "Sending offload flags: 0x%b\n",
220 caps, IAVF_PRINTF_VF_OFFLOAD_FLAGS);
222 if (sc->version.minor == VIRTCHNL_VERSION_MINOR_NO_VF_CAPS)
223 return iavf_send_pf_msg(sc, VIRTCHNL_OP_GET_VF_RESOURCES,
226 return iavf_send_pf_msg(sc, VIRTCHNL_OP_GET_VF_RESOURCES,
227 (u8 *)&caps, sizeof(caps));
231 * iavf_get_vf_config - Get the VF configuration from the PF
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.
239 * @returns zero on success, or an error code on failure
242 iavf_get_vf_config(struct iavf_sc *sc)
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;
252 /* Note this assumes a single VSI */
253 len = sizeof(struct virtchnl_vf_resource) +
254 sizeof(struct virtchnl_vsi_resource);
256 event.msg_buf = (u8 *)malloc(event.buf_len, M_IAVF, M_WAITOK);
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)
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",
268 le32toh(event.desc.cookie_high),
269 le32toh(event.desc.cookie_low));
273 status = (enum iavf_status)le32toh(event.desc.cookie_low);
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));
282 /* We retrieved the config message, with no errors */
286 if (retries > IAVF_AQ_MAX_ERR) {
288 "%s: Did not receive response after %d tries.",
295 memcpy(sc->vf_res, event.msg_buf, min(event.msg_len, len));
296 iavf_vf_parse_hw_config(hw, sc->vf_res);
299 free(event.msg_buf, M_IAVF);
304 * iavf_enable_queues - Enable queues
307 * Request that the PF enable all of our queues.
309 * @remark the reply from the PF is not checked by this function.
314 iavf_enable_queues(struct iavf_sc *sc)
316 struct virtchnl_queue_select vqs;
317 struct iavf_vsi *vsi = &sc->vsi;
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));
328 * iavf_disable_queues - Disable queues
331 * Request that the PF disable all of our queues.
333 * @remark the reply from the PF is not checked by this function.
338 iavf_disable_queues(struct iavf_sc *sc)
340 struct virtchnl_queue_select vqs;
341 struct iavf_vsi *vsi = &sc->vsi;
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));
352 * iavf_add_vlans - Add VLAN filters
355 * Scan the Filter List looking for vlans that need
356 * to be added, then create the data to hand to the AQ
359 * @returns zero on success, or an error code on failure.
362 iavf_add_vlans(struct iavf_sc *sc)
364 struct virtchnl_vlan_filter_list *v;
365 struct iavf_vlan_filter *f, *ftmp;
366 device_t dev = sc->dev;
370 /* Get count of VLAN filters to add */
371 SLIST_FOREACH(f, sc->vlan_filters, next) {
372 if (f->flags & IAVF_FILTER_ADD)
376 if (!cnt) /* no work... */
379 len = sizeof(struct virtchnl_vlan_filter_list) +
382 if (len > IAVF_AQ_BUF_SZ) {
383 device_printf(dev, "%s: Exceeded Max AQ Buf size\n",
388 v = (struct virtchnl_vlan_filter_list *)malloc(len, M_IAVF, M_NOWAIT | M_ZERO);
390 device_printf(dev, "%s: unable to allocate memory\n",
395 v->vsi_id = sc->vsi_res->vsi_id;
396 v->num_elements = cnt;
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;
409 iavf_send_pf_msg(sc, VIRTCHNL_OP_ADD_VLAN, (u8 *)v, len);
416 * iavf_del_vlans - Delete VLAN filters
419 * Scan the Filter Table looking for vlans that need
420 * to be removed, then create the data to hand to the AQ
423 * @returns zero on success, or an error code on failure.
426 iavf_del_vlans(struct iavf_sc *sc)
428 struct virtchnl_vlan_filter_list *v;
429 struct iavf_vlan_filter *f, *ftmp;
430 device_t dev = sc->dev;
434 /* Get count of VLAN filters to delete */
435 SLIST_FOREACH(f, sc->vlan_filters, next) {
436 if (f->flags & IAVF_FILTER_DEL)
440 if (!cnt) /* no work... */
443 len = sizeof(struct virtchnl_vlan_filter_list) +
446 if (len > IAVF_AQ_BUF_SZ) {
447 device_printf(dev, "%s: Exceeded Max AQ Buf size\n",
452 v = (struct virtchnl_vlan_filter_list *)
453 malloc(len, M_IAVF, M_NOWAIT | M_ZERO);
455 device_printf(dev, "%s: unable to allocate memory\n",
460 v->vsi_id = sc->vsi_res->vsi_id;
461 v->num_elements = cnt;
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));
468 SLIST_REMOVE(sc->vlan_filters, f, iavf_vlan_filter, next);
475 iavf_send_pf_msg(sc, VIRTCHNL_OP_DEL_VLAN, (u8 *)v, len);
482 * iavf_add_ether_filters - Add MAC filters
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.
489 * @returns zero on success, or an error code on failure.
492 iavf_add_ether_filters(struct iavf_sc *sc)
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;
500 /* Get count of MAC addresses to add */
501 SLIST_FOREACH(f, sc->mac_filters, next) {
502 if (f->flags & IAVF_FILTER_ADD)
505 if (cnt == 0) { /* Should not happen... */
506 iavf_dbg_vc(sc, "%s: cnt == 0, exiting...\n", __func__);
510 len = sizeof(struct virtchnl_ether_addr_list) +
511 (cnt * sizeof(struct virtchnl_ether_addr));
513 a = (struct virtchnl_ether_addr_list *)
514 malloc(len, M_IAVF, M_NOWAIT | M_ZERO);
516 device_printf(dev, "%s: Failed to get memory for "
517 "virtchnl_ether_addr_list\n", __func__);
520 a->vsi_id = sc->vsi.id;
521 a->num_elements = cnt;
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;
530 iavf_dbg_vc(sc, "%s: ADD: " MAC_FORMAT "\n",
531 __func__, MAC_FORMAT_ARGS(f->macaddr));
536 iavf_dbg_vc(sc, "%s: len %d, j %d, cnt %d\n", __func__,
539 error = iavf_send_pf_msg(sc,
540 VIRTCHNL_OP_ADD_ETH_ADDR, (u8 *)a, len);
547 * iavf_del_ether_filters - Delete MAC filters
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.
554 * @returns zero on success, or an error code on failure.
557 iavf_del_ether_filters(struct iavf_sc *sc)
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;
564 /* Get count of MAC addresses to delete */
565 SLIST_FOREACH(f, sc->mac_filters, next) {
566 if (f->flags & IAVF_FILTER_DEL)
570 iavf_dbg_vc(sc, "%s: cnt == 0, exiting...\n", __func__);
574 len = sizeof(struct virtchnl_ether_addr_list) +
575 (cnt * sizeof(struct virtchnl_ether_addr));
577 d = (struct virtchnl_ether_addr_list *)
578 malloc(len, M_IAVF, M_NOWAIT | M_ZERO);
580 device_printf(dev, "%s: Failed to get memory for "
581 "virtchnl_ether_addr_list\n", __func__);
584 d->vsi_id = sc->vsi.id;
585 d->num_elements = cnt;
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));
594 SLIST_REMOVE(sc->mac_filters, f, iavf_mac_filter, next);
601 VIRTCHNL_OP_DEL_ETH_ADDR, (u8 *)d, len);
608 * iavf_request_reset - Request a device reset
611 * Request that the PF reset this VF. No response is expected.
616 iavf_request_reset(struct iavf_sc *sc)
619 ** Set the reset status to "in progress" before
620 ** the request, this avoids any possibility of
621 ** a mistaken early detection of completion.
623 wr32(&sc->hw, IAVF_VFGEN_RSTAT, VIRTCHNL_VFR_INPROGRESS);
624 iavf_send_pf_msg(sc, VIRTCHNL_OP_RESET_VF, NULL, 0);
629 * iavf_request_stats - Request VF stats
632 * Request the statistics for this VF's VSI from PF.
634 * @remark prints an error message on failure to obtain stats, but does not
635 * return with an error code.
640 iavf_request_stats(struct iavf_sc *sc)
642 struct virtchnl_queue_select vqs;
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));
650 device_printf(sc->dev, "Error sending stats request to PF: %d\n", error);
656 * iavf_update_stats_counters - Update driver statistics
658 * @es: ethernet stats storage
660 * Updates driver's stats counters with VSI stats returned from PF.
663 iavf_update_stats_counters(struct iavf_sc *sc, struct iavf_eth_stats *es)
665 struct iavf_vsi *vsi = &sc->vsi;
666 uint64_t tx_discards;
668 tx_discards = es->tx_discards;
670 /* Update ifnet stats */
671 IAVF_SET_IPACKETS(vsi, es->rx_unicast +
674 IAVF_SET_OPACKETS(vsi, es->tx_unicast +
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);
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);
688 vsi->eth_stats = *es;
692 * iavf_config_rss_key - Configure RSS key over virtchnl
695 * Send a message to the PF to configure the RSS key using the virtchnl
698 * @remark this does not check the reply from the PF.
700 * @returns zero on success, or an error code on failure.
703 iavf_config_rss_key(struct iavf_sc *sc)
705 struct virtchnl_rss_key *rss_key_msg;
706 int msg_len, key_length;
707 u8 rss_seed[IAVF_RSS_KEY_SIZE];
710 /* Fetch the configured RSS key */
711 rss_getkey((uint8_t *) &rss_seed);
713 iavf_get_default_rss_key((u32 *)rss_seed);
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");
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);
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);
733 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_RSS_KEY,
734 (u8 *)rss_key_msg, msg_len);
736 free(rss_key_msg, M_IAVF);
741 * iavf_set_rss_hena - Configure the RSS HENA
744 * Configure the RSS HENA values by sending a virtchnl message to the PF
746 * @remark the reply from the PF is not checked by this function.
751 iavf_set_rss_hena(struct iavf_sc *sc)
753 struct virtchnl_rss_hena hena;
754 struct iavf_hw *hw = &sc->hw;
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;
761 hena.hena = IAVF_DEFAULT_RSS_HENA_BASE;
763 iavf_send_pf_msg(sc, VIRTCHNL_OP_SET_RSS_HENA,
764 (u8 *)&hena, sizeof(hena));
769 * iavf_config_rss_lut - Configure RSS lookup table
772 * Configure the RSS lookup table by sending a virtchnl message to the PF.
774 * @remark the reply from the PF is not checked in this function.
776 * @returns zero on success, or an error code on failure.
779 iavf_config_rss_lut(struct iavf_sc *sc)
781 struct virtchnl_rss_lut *rss_lut_msg;
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");
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;
800 /* Populate the LUT with max no. of queues in round robin fashion */
801 for (i = 0; i < lut_length; i++) {
804 * Fetch the RSS bucket id for the given indirection entry.
805 * Cap it at the number of configured buckets (which is
808 que_id = rss_get_indirection_to_bucket(i);
809 que_id = que_id % sc->vsi.num_rx_queues;
811 que_id = i % sc->vsi.num_rx_queues;
813 lut = que_id & IAVF_RSS_VSI_LUT_ENTRY_MASK;
814 rss_lut_msg->lut[i] = lut;
817 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_RSS_LUT,
818 (u8 *)rss_lut_msg, msg_len);
820 free(rss_lut_msg, M_IAVF);
825 * iavf_config_promisc_mode - Configure promiscuous mode
828 * Configure the device into promiscuous mode by sending a virtchnl message to
831 * @remark the reply from the PF is not checked in this function.
836 iavf_config_promisc_mode(struct iavf_sc *sc)
838 struct virtchnl_promisc_info pinfo;
840 pinfo.vsi_id = sc->vsi_res->vsi_id;
841 pinfo.flags = sc->promisc_flags;
843 iavf_send_pf_msg(sc, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
844 (u8 *)&pinfo, sizeof(pinfo));
849 * iavf_vc_send_cmd - Convert request into virtchnl calls
851 * @request: the requested command to run
853 * Send the proper virtchnl call based on the request value.
855 * @returns zero on success, or an error code on failure. Note that unknown
856 * requests will return zero.
859 iavf_vc_send_cmd(struct iavf_sc *sc, uint32_t request)
862 case IAVF_FLAG_AQ_MAP_VECTORS:
863 return iavf_map_queues(sc);
865 case IAVF_FLAG_AQ_ADD_MAC_FILTER:
866 return iavf_add_ether_filters(sc);
868 case IAVF_FLAG_AQ_ADD_VLAN_FILTER:
869 return iavf_add_vlans(sc);
871 case IAVF_FLAG_AQ_DEL_MAC_FILTER:
872 return iavf_del_ether_filters(sc);
874 case IAVF_FLAG_AQ_DEL_VLAN_FILTER:
875 return iavf_del_vlans(sc);
877 case IAVF_FLAG_AQ_CONFIGURE_QUEUES:
878 return iavf_configure_queues(sc);
880 case IAVF_FLAG_AQ_DISABLE_QUEUES:
881 return iavf_disable_queues(sc);
883 case IAVF_FLAG_AQ_ENABLE_QUEUES:
884 return iavf_enable_queues(sc);
886 case IAVF_FLAG_AQ_CONFIG_RSS_KEY:
887 return iavf_config_rss_key(sc);
889 case IAVF_FLAG_AQ_SET_RSS_HENA:
890 return iavf_set_rss_hena(sc);
892 case IAVF_FLAG_AQ_CONFIG_RSS_LUT:
893 return iavf_config_rss_lut(sc);
895 case IAVF_FLAG_AQ_CONFIGURE_PROMISC:
896 return iavf_config_promisc_mode(sc);
903 * iavf_vc_get_op_chan - Get op channel for a request
905 * @request: the request type
907 * @returns the op channel for the given request, or NULL if no channel is
911 iavf_vc_get_op_chan(struct iavf_sc *sc, uint32_t 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);
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
928 * @returns the human readable string representing the specified error code.
931 iavf_vc_stat_str(struct iavf_hw *hw, enum virtchnl_status_code stat_err)
934 case VIRTCHNL_STATUS_SUCCESS:
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";
952 snprintf(hw->err_str, sizeof(hw->err_str), "%d", stat_err);
957 * iavf_adv_speed_to_ext_speed - Convert numeric speed to iavf speed enum
958 * @adv_link_speed: link speed in Mb/s
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.
963 * @returns the link speed as an iavf_ext_link_speed enum value
965 enum iavf_ext_link_speed
966 iavf_adv_speed_to_ext_speed(u32 adv_link_speed)
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;
991 return IAVF_EXT_LINK_SPEED_UNKNOWN;
995 * iavf_ext_speed_to_ifmedia - Convert internal iavf speed to ifmedia value
996 * @link_speed: the link speed
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
1003 * @returns a suitable ifmedia type for the given link speed.
1006 iavf_ext_speed_to_ifmedia(enum iavf_ext_link_speed link_speed)
1008 switch (link_speed) {
1009 case IAVF_EXT_LINK_SPEED_100GB:
1010 return IFM_100G_SR4;
1011 case IAVF_EXT_LINK_SPEED_50GB:
1013 case IAVF_EXT_LINK_SPEED_40GB:
1015 case IAVF_EXT_LINK_SPEED_25GB:
1017 case IAVF_EXT_LINK_SPEED_20GB:
1019 case IAVF_EXT_LINK_SPEED_10GB:
1021 case IAVF_EXT_LINK_SPEED_5GB:
1023 case IAVF_EXT_LINK_SPEED_2500MB:
1025 case IAVF_EXT_LINK_SPEED_1000MB:
1027 case IAVF_EXT_LINK_SPEED_100MB:
1029 case IAVF_EXT_LINK_SPEED_10MB:
1031 case IAVF_EXT_LINK_SPEED_UNKNOWN:
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
1042 * @returns the link speed in the native iavf format.
1044 enum iavf_ext_link_speed
1045 iavf_vc_speed_to_ext_speed(enum virtchnl_link_speed link_speed)
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:
1062 return IAVF_EXT_LINK_SPEED_UNKNOWN;
1067 * iavf_vc_speed_to_string - Convert virtchnl speed to a string
1068 * @link_speed: the speed to convert
1070 * @returns string representing the link speed as reported by the virtchnl
1074 iavf_vc_speed_to_string(enum virtchnl_link_speed link_speed)
1076 return iavf_ext_speed_to_str(iavf_vc_speed_to_ext_speed(link_speed));
1080 * iavf_ext_speed_to_str - Convert iavf speed enum to string representation
1081 * @link_speed: link speed enum value
1083 * XXX: This is an iavf-modified copy of ice_aq_speed_to_str()
1085 * @returns the string representation of the given link speed.
1088 iavf_ext_speed_to_str(enum iavf_ext_link_speed link_speed)
1090 switch (link_speed) {
1091 case IAVF_EXT_LINK_SPEED_100GB:
1093 case IAVF_EXT_LINK_SPEED_50GB:
1095 case IAVF_EXT_LINK_SPEED_40GB:
1097 case IAVF_EXT_LINK_SPEED_25GB:
1099 case IAVF_EXT_LINK_SPEED_20GB:
1101 case IAVF_EXT_LINK_SPEED_10GB:
1103 case IAVF_EXT_LINK_SPEED_5GB:
1105 case IAVF_EXT_LINK_SPEED_2500MB:
1107 case IAVF_EXT_LINK_SPEED_1000MB:
1109 case IAVF_EXT_LINK_SPEED_100MB:
1111 case IAVF_EXT_LINK_SPEED_10MB:
1113 case IAVF_EXT_LINK_SPEED_UNKNOWN:
1120 * iavf_vc_opcode_str - Convert virtchnl opcode to string
1121 * @op: the virtchnl op code
1123 * @returns the string representation of the given virtchnl op code
1126 iavf_vc_opcode_str(uint16_t op)
1129 case VIRTCHNL_OP_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:
1161 case VIRTCHNL_OP_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");
1177 * iavf_vc_completion - Handle PF reply messages
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
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.
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)
1193 device_t dev = sc->dev;
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));
1199 if (v_opcode == VIRTCHNL_OP_EVENT) {
1200 struct virtchnl_pf_event *vpe =
1201 (struct virtchnl_pf_event *)msg;
1203 switch (vpe->event) {
1204 case VIRTCHNL_EVENT_LINK_CHANGE:
1205 iavf_handle_link_event(sc, vpe);
1207 case VIRTCHNL_EVENT_RESET_IMPENDING:
1208 device_printf(dev, "PF initiated reset!\n");
1209 iavf_set_state(&sc->state, IAVF_STATE_RESET_PENDING);
1212 iavf_dbg_vc(sc, "Unknown event %d from AQ\n",
1220 /* Catch-all error response */
1222 bool print_error = true;
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");
1229 case VIRTCHNL_OP_ENABLE_QUEUES:
1230 sc->enable_queues_chan = 1;
1231 wakeup_one(&sc->enable_queues_chan);
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.
1239 if (!(sc->dbg_mask & IAVF_DBG_VC))
1240 print_error = false;
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));
1255 case VIRTCHNL_OP_GET_STATS:
1256 iavf_update_stats_counters(sc, (struct iavf_eth_stats *)msg);
1258 case VIRTCHNL_OP_ADD_ETH_ADDR:
1260 case VIRTCHNL_OP_DEL_ETH_ADDR:
1262 case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
1264 case VIRTCHNL_OP_ADD_VLAN:
1266 case VIRTCHNL_OP_DEL_VLAN:
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);
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);
1278 case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
1280 case VIRTCHNL_OP_CONFIG_IRQ_MAP:
1282 case VIRTCHNL_OP_CONFIG_RSS_KEY:
1284 case VIRTCHNL_OP_SET_RSS_HENA:
1286 case VIRTCHNL_OP_CONFIG_RSS_LUT:
1290 "Received unexpected message %s from PF.\n",
1291 iavf_vc_opcode_str(v_opcode));
1297 * iavf_handle_link_event - Handle Link event virtchml message
1299 * @vpe: virtchnl PF link event structure
1301 * Process a virtchnl PF link event and update the driver and stack status of
1305 iavf_handle_link_event(struct iavf_sc *sc, struct virtchnl_pf_event *vpe)
1307 MPASS(vpe->event == VIRTCHNL_EVENT_LINK_CHANGE);
1309 if (sc->vf_res->vf_cap_flags & VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
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);
1315 vpe->event_data.link_event_adv.link_status;
1316 sc->link_speed_adv =
1317 vpe->event_data.link_event_adv.link_speed;
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);
1324 vpe->event_data.link_event.link_status;
1326 vpe->event_data.link_event.link_speed;
1329 iavf_update_link_status(sc);