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