1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
12 #include <rte_byteorder.h>
13 #include <rte_common.h>
15 #include <rte_debug.h>
16 #include <rte_atomic.h>
18 #include <rte_ether.h>
19 #include <rte_ethdev.h>
23 #include "base/avf_prototype.h"
24 #include "base/avf_adminq_cmd.h"
25 #include "base/avf_type.h"
29 #define MAX_TRY_TIMES 200
30 #define ASQ_DELAY_MS 10
32 /* Read data in admin queue to get msg from pf driver */
33 static enum avf_status_code
34 avf_read_msg_from_pf(struct avf_adapter *adapter, uint16_t buf_len,
37 struct avf_hw *hw = AVF_DEV_PRIVATE_TO_HW(adapter);
38 struct avf_info *vf = AVF_DEV_PRIVATE_TO_VF(adapter);
39 struct avf_arq_event_info event;
40 enum virtchnl_ops opcode;
43 event.buf_len = buf_len;
45 ret = avf_clean_arq_element(hw, &event, NULL);
46 /* Can't read any msg from adminQ */
48 PMD_DRV_LOG(DEBUG, "Can't read msg from AQ");
52 opcode = (enum virtchnl_ops)rte_le_to_cpu_32(event.desc.cookie_high);
53 vf->cmd_retval = (enum virtchnl_status_code)rte_le_to_cpu_32(
54 event.desc.cookie_low);
56 PMD_DRV_LOG(DEBUG, "AQ from pf carries opcode %u, retval %d",
57 opcode, vf->cmd_retval);
59 if (opcode != vf->pend_cmd)
60 PMD_DRV_LOG(WARNING, "command mismatch, expect %u, get %u",
61 vf->pend_cmd, opcode);
67 avf_execute_vf_cmd(struct avf_adapter *adapter, struct avf_cmd_info *args)
69 struct avf_hw *hw = AVF_DEV_PRIVATE_TO_HW(adapter);
70 struct avf_info *vf = AVF_DEV_PRIVATE_TO_VF(adapter);
71 struct avf_arq_event_info event_info;
72 enum avf_status_code ret;
76 if (_atomic_set_cmd(vf, args->ops))
79 ret = avf_aq_send_msg_to_pf(hw, args->ops, AVF_SUCCESS,
80 args->in_args, args->in_args_size, NULL);
82 PMD_DRV_LOG(ERR, "fail to send cmd %d", args->ops);
88 case VIRTCHNL_OP_RESET_VF:
89 /*no need to wait for response */
92 case VIRTCHNL_OP_VERSION:
93 case VIRTCHNL_OP_GET_VF_RESOURCES:
94 /* for init virtchnl ops, need to poll the response */
96 ret = avf_read_msg_from_pf(adapter, args->out_size,
98 if (ret == AVF_SUCCESS)
100 rte_delay_ms(ASQ_DELAY_MS);
101 } while (i++ < MAX_TRY_TIMES);
102 if (i >= MAX_TRY_TIMES ||
103 vf->cmd_retval != VIRTCHNL_STATUS_SUCCESS) {
105 PMD_DRV_LOG(ERR, "No response or return failure (%d)"
106 " for cmd %d", vf->cmd_retval, args->ops);
112 /* For other virtchnl ops in running time,
113 * wait for the cmd done flag.
116 if (vf->pend_cmd == VIRTCHNL_OP_UNKNOWN)
118 rte_delay_ms(ASQ_DELAY_MS);
119 /* If don't read msg or read sys event, continue */
120 } while (i++ < MAX_TRY_TIMES);
121 /* If there's no response is received, clear command */
122 if (i >= MAX_TRY_TIMES ||
123 vf->cmd_retval != VIRTCHNL_STATUS_SUCCESS) {
125 PMD_DRV_LOG(ERR, "No response or return failure (%d)"
126 " for cmd %d", vf->cmd_retval, args->ops);
136 avf_handle_virtchnl_msg(struct rte_eth_dev *dev)
138 struct avf_hw *hw = AVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
139 struct avf_info *vf = AVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
140 struct avf_arq_event_info info;
141 uint16_t pending, aq_opc;
142 enum virtchnl_ops msg_opc;
143 enum avf_status_code msg_ret;
146 info.buf_len = AVF_AQ_BUF_SZ;
148 PMD_DRV_LOG(ERR, "Buffer for adminq resp should not be NULL");
151 info.msg_buf = vf->aq_resp;
155 ret = avf_clean_arq_element(hw, &info, &pending);
157 if (ret != AVF_SUCCESS) {
158 PMD_DRV_LOG(INFO, "Failed to read msg from AdminQ,"
162 aq_opc = rte_le_to_cpu_16(info.desc.opcode);
163 /* For the message sent from pf to vf, opcode is stored in
164 * cookie_high of struct avf_aq_desc, while return error code
165 * are stored in cookie_low, Which is done by PF driver.
167 msg_opc = (enum virtchnl_ops)rte_le_to_cpu_32(
168 info.desc.cookie_high);
169 msg_ret = (enum avf_status_code)rte_le_to_cpu_32(
170 info.desc.cookie_low);
172 case avf_aqc_opc_send_msg_to_vf:
173 if (msg_opc == VIRTCHNL_OP_EVENT) {
176 /* read message and it's expected one */
177 if (msg_opc == vf->pend_cmd) {
178 vf->cmd_retval = msg_ret;
179 /* prevent compiler reordering */
180 rte_compiler_barrier();
183 PMD_DRV_LOG(ERR, "command mismatch,"
185 vf->pend_cmd, msg_opc);
187 "adminq response is received,"
188 " opcode = %d", msg_opc);
192 PMD_DRV_LOG(ERR, "Request %u is not supported yet",
199 #define VIRTCHNL_VERSION_MAJOR_START 1
200 #define VIRTCHNL_VERSION_MINOR_START 1
202 /* Check API version with sync wait until version read from admin queue */
204 avf_check_api_version(struct avf_adapter *adapter)
206 struct avf_info *vf = AVF_DEV_PRIVATE_TO_VF(adapter);
207 struct virtchnl_version_info version, *pver;
208 struct avf_cmd_info args;
211 version.major = VIRTCHNL_VERSION_MAJOR;
212 version.minor = VIRTCHNL_VERSION_MINOR;
214 args.ops = VIRTCHNL_OP_VERSION;
215 args.in_args = (uint8_t *)&version;
216 args.in_args_size = sizeof(version);
217 args.out_buffer = vf->aq_resp;
218 args.out_size = AVF_AQ_BUF_SZ;
220 err = avf_execute_vf_cmd(adapter, &args);
222 PMD_INIT_LOG(ERR, "Fail to execute command of OP_VERSION");
226 pver = (struct virtchnl_version_info *)args.out_buffer;
227 vf->virtchnl_version = *pver;
229 if (vf->virtchnl_version.major < VIRTCHNL_VERSION_MAJOR_START ||
230 (vf->virtchnl_version.major == VIRTCHNL_VERSION_MAJOR_START &&
231 vf->virtchnl_version.minor < VIRTCHNL_VERSION_MINOR_START)) {
232 PMD_INIT_LOG(ERR, "VIRTCHNL API version should not be lower"
233 " than (%u.%u) to support Adapative VF",
234 VIRTCHNL_VERSION_MAJOR_START,
235 VIRTCHNL_VERSION_MAJOR_START);
237 } else if (vf->virtchnl_version.major > VIRTCHNL_VERSION_MAJOR ||
238 (vf->virtchnl_version.major == VIRTCHNL_VERSION_MAJOR &&
239 vf->virtchnl_version.minor > VIRTCHNL_VERSION_MINOR)) {
240 PMD_INIT_LOG(ERR, "PF/VF API version mismatch:(%u.%u)-(%u.%u)",
241 vf->virtchnl_version.major,
242 vf->virtchnl_version.minor,
243 VIRTCHNL_VERSION_MAJOR,
244 VIRTCHNL_VERSION_MINOR);
248 PMD_DRV_LOG(DEBUG, "Peer is supported PF host");
253 avf_get_vf_resource(struct avf_adapter *adapter)
255 struct avf_hw *hw = AVF_DEV_PRIVATE_TO_HW(adapter);
256 struct avf_info *vf = AVF_DEV_PRIVATE_TO_VF(adapter);
257 struct avf_cmd_info args;
261 args.ops = VIRTCHNL_OP_GET_VF_RESOURCES;
262 args.out_buffer = vf->aq_resp;
263 args.out_size = AVF_AQ_BUF_SZ;
265 /* TODO: basic offload capabilities, need to
266 * add advanced/optional offload capabilities
269 caps = AVF_BASIC_OFFLOAD_CAPS;
271 args.in_args = (uint8_t *)∩︀
272 args.in_args_size = sizeof(caps);
274 err = avf_execute_vf_cmd(adapter, &args);
277 PMD_DRV_LOG(ERR, "Failed to execute command of "
278 "OP_GET_VF_RESOURCE");
282 len = sizeof(struct virtchnl_vf_resource) +
283 AVF_MAX_VF_VSI * sizeof(struct virtchnl_vsi_resource);
285 rte_memcpy(vf->vf_res, args.out_buffer,
286 RTE_MIN(args.out_size, len));
287 /* parse VF config message back from PF*/
288 avf_parse_hw_config(hw, vf->vf_res);
289 for (i = 0; i < vf->vf_res->num_vsis; i++) {
290 if (vf->vf_res->vsi_res[i].vsi_type == VIRTCHNL_VSI_SRIOV)
291 vf->vsi_res = &vf->vf_res->vsi_res[i];
295 PMD_INIT_LOG(ERR, "no LAN VSI found");
299 vf->vsi.vsi_id = vf->vsi_res->vsi_id;
300 vf->vsi.nb_qps = vf->vsi_res->num_queue_pairs;
301 vf->vsi.adapter = adapter;