xref: /f-stack/dpdk/drivers/net/i40e/i40e_pf.c (revision 031be553)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/queue.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <stdarg.h>
41 #include <inttypes.h>
42 
43 #include <rte_string_fns.h>
44 #include <rte_pci.h>
45 #include <rte_ether.h>
46 #include <rte_ethdev.h>
47 #include <rte_malloc.h>
48 #include <rte_memcpy.h>
49 
50 #include "i40e_logs.h"
51 #include "base/i40e_prototype.h"
52 #include "base/i40e_adminq_cmd.h"
53 #include "base/i40e_type.h"
54 #include "i40e_ethdev.h"
55 #include "i40e_rxtx.h"
56 #include "i40e_pf.h"
57 #include "rte_pmd_i40e.h"
58 
59 #define I40E_CFG_CRCSTRIP_DEFAULT 1
60 
61 static int
62 i40e_pf_host_switch_queues(struct i40e_pf_vf *vf,
63 			   struct virtchnl_queue_select *qsel,
64 			   bool on);
65 
66 /**
67  * Bind PF queues with VSI and VF.
68  **/
69 static int
70 i40e_pf_vf_queues_mapping(struct i40e_pf_vf *vf)
71 {
72 	int i;
73 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
74 	uint16_t vsi_id = vf->vsi->vsi_id;
75 	uint16_t vf_id  = vf->vf_idx;
76 	uint16_t nb_qps = vf->vsi->nb_qps;
77 	uint16_t qbase  = vf->vsi->base_queue;
78 	uint16_t q1, q2;
79 	uint32_t val;
80 
81 	/*
82 	 * VF should use scatter range queues. So, it needn't
83 	 * to set QBASE in this register.
84 	 */
85 	i40e_write_rx_ctl(hw, I40E_VSILAN_QBASE(vsi_id),
86 			  I40E_VSILAN_QBASE_VSIQTABLE_ENA_MASK);
87 
88 	/* Set to enable VFLAN_QTABLE[] registers valid */
89 	I40E_WRITE_REG(hw, I40E_VPLAN_MAPENA(vf_id),
90 		I40E_VPLAN_MAPENA_TXRX_ENA_MASK);
91 
92 	/* map PF queues to VF */
93 	for (i = 0; i < nb_qps; i++) {
94 		val = ((qbase + i) & I40E_VPLAN_QTABLE_QINDEX_MASK);
95 		I40E_WRITE_REG(hw, I40E_VPLAN_QTABLE(i, vf_id), val);
96 	}
97 
98 	/* map PF queues to VSI */
99 	for (i = 0; i < I40E_MAX_QP_NUM_PER_VF / 2; i++) {
100 		if (2 * i > nb_qps - 1)
101 			q1 = I40E_VSILAN_QTABLE_QINDEX_0_MASK;
102 		else
103 			q1 = qbase + 2 * i;
104 
105 		if (2 * i + 1 > nb_qps - 1)
106 			q2 = I40E_VSILAN_QTABLE_QINDEX_0_MASK;
107 		else
108 			q2 = qbase + 2 * i + 1;
109 
110 		val = (q2 << I40E_VSILAN_QTABLE_QINDEX_1_SHIFT) + q1;
111 		i40e_write_rx_ctl(hw, I40E_VSILAN_QTABLE(i, vsi_id), val);
112 	}
113 	I40E_WRITE_FLUSH(hw);
114 
115 	return I40E_SUCCESS;
116 }
117 
118 
119 /**
120  * Proceed VF reset operation.
121  */
122 int
123 i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset)
124 {
125 	uint32_t val, i;
126 	struct i40e_hw *hw;
127 	struct i40e_pf *pf;
128 	uint16_t vf_id, abs_vf_id, vf_msix_num;
129 	int ret;
130 	struct virtchnl_queue_select qsel;
131 
132 	if (vf == NULL)
133 		return -EINVAL;
134 
135 	pf = vf->pf;
136 	hw = I40E_PF_TO_HW(vf->pf);
137 	vf_id = vf->vf_idx;
138 	abs_vf_id = vf_id + hw->func_caps.vf_base_id;
139 
140 	/* Notify VF that we are in VFR progress */
141 	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), VIRTCHNL_VFR_INPROGRESS);
142 
143 	/*
144 	 * If require a SW VF reset, a VFLR interrupt will be generated,
145 	 * this function will be called again. To avoid it,
146 	 * disable interrupt first.
147 	 */
148 	if (do_hw_reset) {
149 		vf->state = I40E_VF_INRESET;
150 		val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id));
151 		val |= I40E_VPGEN_VFRTRIG_VFSWR_MASK;
152 		I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val);
153 		I40E_WRITE_FLUSH(hw);
154 	}
155 
156 #define VFRESET_MAX_WAIT_CNT 100
157 	/* Wait until VF reset is done */
158 	for (i = 0; i < VFRESET_MAX_WAIT_CNT; i++) {
159 		rte_delay_us(10);
160 		val = I40E_READ_REG(hw, I40E_VPGEN_VFRSTAT(vf_id));
161 		if (val & I40E_VPGEN_VFRSTAT_VFRD_MASK)
162 			break;
163 	}
164 
165 	if (i >= VFRESET_MAX_WAIT_CNT) {
166 		PMD_DRV_LOG(ERR, "VF reset timeout");
167 		return -ETIMEDOUT;
168 	}
169 	/* This is not first time to do reset, do cleanup job first */
170 	if (vf->vsi) {
171 		/* Disable queues */
172 		memset(&qsel, 0, sizeof(qsel));
173 		for (i = 0; i < vf->vsi->nb_qps; i++)
174 			qsel.rx_queues |= 1 << i;
175 		qsel.tx_queues = qsel.rx_queues;
176 		ret = i40e_pf_host_switch_queues(vf, &qsel, false);
177 		if (ret != I40E_SUCCESS) {
178 			PMD_DRV_LOG(ERR, "Disable VF queues failed");
179 			return -EFAULT;
180 		}
181 
182 		/* Disable VF interrupt setting */
183 		vf_msix_num = hw->func_caps.num_msix_vectors_vf;
184 		for (i = 0; i < vf_msix_num; i++) {
185 			if (!i)
186 				val = I40E_VFINT_DYN_CTL0(vf_id);
187 			else
188 				val = I40E_VFINT_DYN_CTLN(((vf_msix_num - 1) *
189 							(vf_id)) + (i - 1));
190 			I40E_WRITE_REG(hw, val, I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
191 		}
192 		I40E_WRITE_FLUSH(hw);
193 
194 		/* remove VSI */
195 		ret = i40e_vsi_release(vf->vsi);
196 		if (ret != I40E_SUCCESS) {
197 			PMD_DRV_LOG(ERR, "Release VSI failed");
198 			return -EFAULT;
199 		}
200 	}
201 
202 #define I40E_VF_PCI_ADDR  0xAA
203 #define I40E_VF_PEND_MASK 0x20
204 	/* Check the pending transactions of this VF */
205 	/* Use absolute VF id, refer to datasheet for details */
206 	I40E_WRITE_REG(hw, I40E_PF_PCI_CIAA, I40E_VF_PCI_ADDR |
207 		(abs_vf_id << I40E_PF_PCI_CIAA_VF_NUM_SHIFT));
208 	for (i = 0; i < VFRESET_MAX_WAIT_CNT; i++) {
209 		rte_delay_us(1);
210 		val = I40E_READ_REG(hw, I40E_PF_PCI_CIAD);
211 		if ((val & I40E_VF_PEND_MASK) == 0)
212 			break;
213 	}
214 
215 	if (i >= VFRESET_MAX_WAIT_CNT) {
216 		PMD_DRV_LOG(ERR, "Wait VF PCI transaction end timeout");
217 		return -ETIMEDOUT;
218 	}
219 
220 	/* Reset done, Set COMPLETE flag and clear reset bit */
221 	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), VIRTCHNL_VFR_COMPLETED);
222 	val = I40E_READ_REG(hw, I40E_VPGEN_VFRTRIG(vf_id));
223 	val &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
224 	I40E_WRITE_REG(hw, I40E_VPGEN_VFRTRIG(vf_id), val);
225 	vf->reset_cnt++;
226 	I40E_WRITE_FLUSH(hw);
227 
228 	/* Allocate resource again */
229 	if (pf->floating_veb && pf->floating_veb_list[vf_id]) {
230 		vf->vsi = i40e_vsi_setup(vf->pf, I40E_VSI_SRIOV,
231 					 NULL, vf->vf_idx);
232 	} else {
233 		vf->vsi = i40e_vsi_setup(vf->pf, I40E_VSI_SRIOV,
234 					 vf->pf->main_vsi, vf->vf_idx);
235 	}
236 
237 	if (vf->vsi == NULL) {
238 		PMD_DRV_LOG(ERR, "Add vsi failed");
239 		return -EFAULT;
240 	}
241 
242 	ret = i40e_pf_vf_queues_mapping(vf);
243 	if (ret != I40E_SUCCESS) {
244 		PMD_DRV_LOG(ERR, "queue mapping error");
245 		i40e_vsi_release(vf->vsi);
246 		return -EFAULT;
247 	}
248 
249 	I40E_WRITE_REG(hw, I40E_VFGEN_RSTAT1(vf_id), VIRTCHNL_VFR_VFACTIVE);
250 
251 	return ret;
252 }
253 
254 int
255 i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf,
256 			    uint32_t opcode,
257 			    uint32_t retval,
258 			    uint8_t *msg,
259 			    uint16_t msglen)
260 {
261 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
262 	uint16_t abs_vf_id = hw->func_caps.vf_base_id + vf->vf_idx;
263 	int ret;
264 
265 	ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, opcode, retval,
266 						msg, msglen, NULL);
267 	if (ret) {
268 		PMD_INIT_LOG(ERR, "Fail to send message to VF, err %u",
269 			     hw->aq.asq_last_status);
270 	}
271 
272 	return ret;
273 }
274 
275 static void
276 i40e_pf_host_process_cmd_version(struct i40e_pf_vf *vf, bool b_op)
277 {
278 	struct virtchnl_version_info info;
279 
280 	/* Respond like a Linux PF host in order to support both DPDK VF and
281 	 * Linux VF driver. The expense is original DPDK host specific feature
282 	 * like CFG_VLAN_PVID and CONFIG_VSI_QUEUES_EXT will not available.
283 	 *
284 	 * DPDK VF also can't identify host driver by version number returned.
285 	 * It always assume talking with Linux PF.
286 	 */
287 	info.major = VIRTCHNL_VERSION_MAJOR;
288 	info.minor = VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;
289 
290 	if (b_op)
291 		i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_VERSION,
292 					    I40E_SUCCESS,
293 					    (uint8_t *)&info,
294 					    sizeof(info));
295 	else
296 		i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_VERSION,
297 					    I40E_NOT_SUPPORTED,
298 					    (uint8_t *)&info,
299 					    sizeof(info));
300 }
301 
302 static int
303 i40e_pf_host_process_cmd_reset_vf(struct i40e_pf_vf *vf)
304 {
305 	i40e_pf_host_vf_reset(vf, 1);
306 
307 	/* No feedback will be sent to VF for VFLR */
308 	return I40E_SUCCESS;
309 }
310 
311 static int
312 i40e_pf_host_process_cmd_get_vf_resource(struct i40e_pf_vf *vf, bool b_op)
313 {
314 	struct virtchnl_vf_resource *vf_res = NULL;
315 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
316 	uint32_t len = 0;
317 	int ret = I40E_SUCCESS;
318 
319 	if (!b_op) {
320 		i40e_pf_host_send_msg_to_vf(vf,
321 					    VIRTCHNL_OP_GET_VF_RESOURCES,
322 					    I40E_NOT_SUPPORTED, NULL, 0);
323 		return ret;
324 	}
325 
326 	/* only have 1 VSI by default */
327 	len =  sizeof(struct virtchnl_vf_resource) +
328 				I40E_DEFAULT_VF_VSI_NUM *
329 		sizeof(struct virtchnl_vsi_resource);
330 
331 	vf_res = rte_zmalloc("i40e_vf_res", len, 0);
332 	if (vf_res == NULL) {
333 		PMD_DRV_LOG(ERR, "failed to allocate mem");
334 		ret = I40E_ERR_NO_MEMORY;
335 		vf_res = NULL;
336 		len = 0;
337 		goto send_msg;
338 	}
339 
340 	vf_res->vf_offload_flags = VIRTCHNL_VF_OFFLOAD_L2 |
341 				VIRTCHNL_VF_OFFLOAD_VLAN;
342 	vf_res->max_vectors = hw->func_caps.num_msix_vectors_vf;
343 	vf_res->num_queue_pairs = vf->vsi->nb_qps;
344 	vf_res->num_vsis = I40E_DEFAULT_VF_VSI_NUM;
345 
346 	/* Change below setting if PF host can support more VSIs for VF */
347 	vf_res->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV;
348 	vf_res->vsi_res[0].vsi_id = vf->vsi->vsi_id;
349 	vf_res->vsi_res[0].num_queue_pairs = vf->vsi->nb_qps;
350 	ether_addr_copy(&vf->mac_addr,
351 		(struct ether_addr *)vf_res->vsi_res[0].default_mac_addr);
352 
353 send_msg:
354 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_GET_VF_RESOURCES,
355 					ret, (uint8_t *)vf_res, len);
356 	rte_free(vf_res);
357 
358 	return ret;
359 }
360 
361 static int
362 i40e_pf_host_hmc_config_rxq(struct i40e_hw *hw,
363 			    struct i40e_pf_vf *vf,
364 			    struct virtchnl_rxq_info *rxq,
365 			    uint8_t crcstrip)
366 {
367 	int err = I40E_SUCCESS;
368 	struct i40e_hmc_obj_rxq rx_ctx;
369 	uint16_t abs_queue_id = vf->vsi->base_queue + rxq->queue_id;
370 
371 	/* Clear the context structure first */
372 	memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq));
373 	rx_ctx.dbuff = rxq->databuffer_size >> I40E_RXQ_CTX_DBUFF_SHIFT;
374 	rx_ctx.hbuff = rxq->hdr_size >> I40E_RXQ_CTX_HBUFF_SHIFT;
375 	rx_ctx.base = rxq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT;
376 	rx_ctx.qlen = rxq->ring_len;
377 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
378 	rx_ctx.dsize = 1;
379 #endif
380 
381 	if (rxq->splithdr_enabled) {
382 		rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_ALL;
383 		rx_ctx.dtype = i40e_header_split_enabled;
384 	} else {
385 		rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE;
386 		rx_ctx.dtype = i40e_header_split_none;
387 	}
388 	rx_ctx.rxmax = rxq->max_pkt_size;
389 	rx_ctx.tphrdesc_ena = 1;
390 	rx_ctx.tphwdesc_ena = 1;
391 	rx_ctx.tphdata_ena = 1;
392 	rx_ctx.tphhead_ena = 1;
393 	rx_ctx.lrxqthresh = 2;
394 	rx_ctx.crcstrip = crcstrip;
395 	rx_ctx.l2tsel = 1;
396 	rx_ctx.prefena = 1;
397 
398 	err = i40e_clear_lan_rx_queue_context(hw, abs_queue_id);
399 	if (err != I40E_SUCCESS)
400 		return err;
401 	err = i40e_set_lan_rx_queue_context(hw, abs_queue_id, &rx_ctx);
402 
403 	return err;
404 }
405 
406 static inline uint8_t
407 i40e_vsi_get_tc_of_queue(struct i40e_vsi *vsi,
408 		uint16_t queue_id)
409 {
410 	struct i40e_aqc_vsi_properties_data *info = &vsi->info;
411 	uint16_t bsf, qp_idx;
412 	uint8_t i;
413 
414 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
415 		if (vsi->enabled_tc & (1 << i)) {
416 			qp_idx = rte_le_to_cpu_16((info->tc_mapping[i] &
417 				I40E_AQ_VSI_TC_QUE_OFFSET_MASK) >>
418 				I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT);
419 			bsf = rte_le_to_cpu_16((info->tc_mapping[i] &
420 				I40E_AQ_VSI_TC_QUE_NUMBER_MASK) >>
421 				I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT);
422 			if (queue_id >= qp_idx && queue_id < qp_idx + (1 << bsf))
423 				return i;
424 		}
425 	}
426 	return 0;
427 }
428 
429 static int
430 i40e_pf_host_hmc_config_txq(struct i40e_hw *hw,
431 			    struct i40e_pf_vf *vf,
432 			    struct virtchnl_txq_info *txq)
433 {
434 	int err = I40E_SUCCESS;
435 	struct i40e_hmc_obj_txq tx_ctx;
436 	struct i40e_vsi *vsi = vf->vsi;
437 	uint32_t qtx_ctl;
438 	uint16_t abs_queue_id = vsi->base_queue + txq->queue_id;
439 	uint8_t dcb_tc;
440 
441 	/* clear the context structure first */
442 	memset(&tx_ctx, 0, sizeof(tx_ctx));
443 	tx_ctx.base = txq->dma_ring_addr / I40E_QUEUE_BASE_ADDR_UNIT;
444 	tx_ctx.qlen = txq->ring_len;
445 	dcb_tc = i40e_vsi_get_tc_of_queue(vsi, txq->queue_id);
446 	tx_ctx.rdylist = rte_le_to_cpu_16(vsi->info.qs_handle[dcb_tc]);
447 	tx_ctx.head_wb_ena = txq->headwb_enabled;
448 	tx_ctx.head_wb_addr = txq->dma_headwb_addr;
449 
450 	err = i40e_clear_lan_tx_queue_context(hw, abs_queue_id);
451 	if (err != I40E_SUCCESS)
452 		return err;
453 
454 	err = i40e_set_lan_tx_queue_context(hw, abs_queue_id, &tx_ctx);
455 	if (err != I40E_SUCCESS)
456 		return err;
457 
458 	/* bind queue with VF function, since TX/QX will appear in pair,
459 	 * so only has QTX_CTL to set.
460 	 */
461 	qtx_ctl = (I40E_QTX_CTL_VF_QUEUE << I40E_QTX_CTL_PFVF_Q_SHIFT) |
462 				((hw->pf_id << I40E_QTX_CTL_PF_INDX_SHIFT) &
463 				I40E_QTX_CTL_PF_INDX_MASK) |
464 				(((vf->vf_idx + hw->func_caps.vf_base_id) <<
465 				I40E_QTX_CTL_VFVM_INDX_SHIFT) &
466 				I40E_QTX_CTL_VFVM_INDX_MASK);
467 	I40E_WRITE_REG(hw, I40E_QTX_CTL(abs_queue_id), qtx_ctl);
468 	I40E_WRITE_FLUSH(hw);
469 
470 	return I40E_SUCCESS;
471 }
472 
473 static int
474 i40e_pf_host_process_cmd_config_vsi_queues(struct i40e_pf_vf *vf,
475 					   uint8_t *msg,
476 					   uint16_t msglen,
477 					   bool b_op)
478 {
479 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
480 	struct i40e_vsi *vsi = vf->vsi;
481 	struct virtchnl_vsi_queue_config_info *vc_vqci =
482 		(struct virtchnl_vsi_queue_config_info *)msg;
483 	struct virtchnl_queue_pair_info *vc_qpi;
484 	int i, ret = I40E_SUCCESS;
485 
486 	if (!b_op) {
487 		i40e_pf_host_send_msg_to_vf(vf,
488 					    VIRTCHNL_OP_CONFIG_VSI_QUEUES,
489 					    I40E_NOT_SUPPORTED, NULL, 0);
490 		return ret;
491 	}
492 
493 	if (!msg || vc_vqci->num_queue_pairs > vsi->nb_qps ||
494 		vc_vqci->num_queue_pairs > I40E_MAX_VSI_QP ||
495 		msglen < I40E_VIRTCHNL_CONFIG_VSI_QUEUES_SIZE(vc_vqci,
496 					vc_vqci->num_queue_pairs)) {
497 		PMD_DRV_LOG(ERR, "vsi_queue_config_info argument wrong");
498 		ret = I40E_ERR_PARAM;
499 		goto send_msg;
500 	}
501 
502 	vc_qpi = vc_vqci->qpair;
503 	for (i = 0; i < vc_vqci->num_queue_pairs; i++) {
504 		if (vc_qpi[i].rxq.queue_id > vsi->nb_qps - 1 ||
505 			vc_qpi[i].txq.queue_id > vsi->nb_qps - 1) {
506 			ret = I40E_ERR_PARAM;
507 			goto send_msg;
508 		}
509 
510 		/*
511 		 * Apply VF RX queue setting to HMC.
512 		 * If the opcode is VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
513 		 * then the extra information of
514 		 * 'struct virtchnl_queue_pair_extra_info' is needed,
515 		 * otherwise set the last parameter to NULL.
516 		 */
517 		if (i40e_pf_host_hmc_config_rxq(hw, vf, &vc_qpi[i].rxq,
518 			I40E_CFG_CRCSTRIP_DEFAULT) != I40E_SUCCESS) {
519 			PMD_DRV_LOG(ERR, "Configure RX queue HMC failed");
520 			ret = I40E_ERR_PARAM;
521 			goto send_msg;
522 		}
523 
524 		/* Apply VF TX queue setting to HMC */
525 		if (i40e_pf_host_hmc_config_txq(hw, vf,
526 			&vc_qpi[i].txq) != I40E_SUCCESS) {
527 			PMD_DRV_LOG(ERR, "Configure TX queue HMC failed");
528 			ret = I40E_ERR_PARAM;
529 			goto send_msg;
530 		}
531 	}
532 
533 send_msg:
534 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
535 							ret, NULL, 0);
536 
537 	return ret;
538 }
539 
540 static void
541 i40e_pf_config_irq_link_list(struct i40e_pf_vf *vf,
542 			      struct virtchnl_vector_map *vvm)
543 {
544 #define BITS_PER_CHAR 8
545 	uint64_t linklistmap = 0, tempmap;
546 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
547 	uint16_t qid;
548 	bool b_first_q = true;
549 	enum i40e_queue_type qtype;
550 	uint16_t vector_id;
551 	uint32_t reg, reg_idx;
552 	uint16_t itr_idx = 0, i;
553 
554 	vector_id = vvm->vector_id;
555 	/* setup the head */
556 	if (!vector_id)
557 		reg_idx = I40E_VPINT_LNKLST0(vf->vf_idx);
558 	else
559 		reg_idx = I40E_VPINT_LNKLSTN(
560 		((hw->func_caps.num_msix_vectors_vf - 1) * vf->vf_idx)
561 		+ (vector_id - 1));
562 
563 	if (vvm->rxq_map == 0 && vvm->txq_map == 0) {
564 		I40E_WRITE_REG(hw, reg_idx,
565 			I40E_VPINT_LNKLST0_FIRSTQ_INDX_MASK);
566 		goto cfg_irq_done;
567 	}
568 
569 	/* sort all rx and tx queues */
570 	tempmap = vvm->rxq_map;
571 	for (i = 0; i < sizeof(vvm->rxq_map) * BITS_PER_CHAR; i++) {
572 		if (tempmap & 0x1)
573 			linklistmap |= (1 << (2 * i));
574 		tempmap >>= 1;
575 	}
576 
577 	tempmap = vvm->txq_map;
578 	for (i = 0; i < sizeof(vvm->txq_map) * BITS_PER_CHAR; i++) {
579 		if (tempmap & 0x1)
580 			linklistmap |= (1 << (2 * i + 1));
581 		tempmap >>= 1;
582 	}
583 
584 	/* Link all rx and tx queues into a chained list */
585 	tempmap = linklistmap;
586 	i = 0;
587 	b_first_q = true;
588 	do {
589 		if (tempmap & 0x1) {
590 			qtype = (enum i40e_queue_type)(i % 2);
591 			qid = vf->vsi->base_queue + i / 2;
592 			if (b_first_q) {
593 				/* This is header */
594 				b_first_q = false;
595 				reg = ((qtype <<
596 				I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_SHIFT)
597 				| qid);
598 			} else {
599 				/* element in the link list */
600 				reg = (vector_id) |
601 				(qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
602 				(qid << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
603 				BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
604 				(itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
605 			}
606 			I40E_WRITE_REG(hw, reg_idx, reg);
607 			/* find next register to program */
608 			switch (qtype) {
609 			case I40E_QUEUE_TYPE_RX:
610 				reg_idx = I40E_QINT_RQCTL(qid);
611 				itr_idx = vvm->rxitr_idx;
612 				break;
613 			case I40E_QUEUE_TYPE_TX:
614 				reg_idx = I40E_QINT_TQCTL(qid);
615 				itr_idx = vvm->txitr_idx;
616 				break;
617 			default:
618 				break;
619 			}
620 		}
621 		i++;
622 		tempmap >>= 1;
623 	} while (tempmap);
624 
625 	/* Terminate the link list */
626 	reg = (vector_id) |
627 		(0 << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) |
628 		(0x7FF << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) |
629 		BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) |
630 		(itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT);
631 	I40E_WRITE_REG(hw, reg_idx, reg);
632 
633 cfg_irq_done:
634 	I40E_WRITE_FLUSH(hw);
635 }
636 
637 static int
638 i40e_pf_host_process_cmd_config_irq_map(struct i40e_pf_vf *vf,
639 					uint8_t *msg, uint16_t msglen,
640 					bool b_op)
641 {
642 	int ret = I40E_SUCCESS;
643 	struct i40e_pf *pf = vf->pf;
644 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
645 	struct virtchnl_irq_map_info *irqmap =
646 	    (struct virtchnl_irq_map_info *)msg;
647 	struct virtchnl_vector_map *map;
648 	int i;
649 	uint16_t vector_id, itr_idx;
650 	unsigned long qbit_max;
651 
652 	if (!b_op) {
653 		i40e_pf_host_send_msg_to_vf(
654 			vf,
655 			VIRTCHNL_OP_CONFIG_IRQ_MAP,
656 			I40E_NOT_SUPPORTED, NULL, 0);
657 		return ret;
658 	}
659 
660 	if (msg == NULL || msglen < sizeof(struct virtchnl_irq_map_info)) {
661 		PMD_DRV_LOG(ERR, "buffer too short");
662 		ret = I40E_ERR_PARAM;
663 		goto send_msg;
664 	}
665 
666 	/* PF host will support both DPDK VF or Linux VF driver, identify by
667 	 * number of vectors requested.
668 	 */
669 
670 	/* DPDK VF only requires single vector */
671 	if (irqmap->num_vectors == 1) {
672 		/* This MSIX intr store the intr in VF range */
673 		vf->vsi->msix_intr = irqmap->vecmap[0].vector_id;
674 		vf->vsi->nb_msix = irqmap->num_vectors;
675 		vf->vsi->nb_used_qps = vf->vsi->nb_qps;
676 		itr_idx = irqmap->vecmap[0].rxitr_idx;
677 
678 		/* Don't care how the TX/RX queue mapping with this vector.
679 		 * Link all VF RX queues together. Only did mapping work.
680 		 * VF can disable/enable the intr by itself.
681 		 */
682 		i40e_vsi_queues_bind_intr(vf->vsi, itr_idx);
683 		goto send_msg;
684 	}
685 
686 	/* Then, it's Linux VF driver */
687 	qbit_max = 1 << pf->vf_nb_qp_max;
688 	for (i = 0; i < irqmap->num_vectors; i++) {
689 		map = &irqmap->vecmap[i];
690 
691 		vector_id = map->vector_id;
692 		/* validate msg params */
693 		if (vector_id >= hw->func_caps.num_msix_vectors_vf) {
694 			ret = I40E_ERR_PARAM;
695 			goto send_msg;
696 		}
697 
698 		if ((map->rxq_map < qbit_max) && (map->txq_map < qbit_max)) {
699 			i40e_pf_config_irq_link_list(vf, map);
700 		} else {
701 			/* configured queue size excceed limit */
702 			ret = I40E_ERR_PARAM;
703 			goto send_msg;
704 		}
705 	}
706 
707 send_msg:
708 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_IRQ_MAP,
709 							ret, NULL, 0);
710 
711 	return ret;
712 }
713 
714 static int
715 i40e_pf_host_switch_queues(struct i40e_pf_vf *vf,
716 			   struct virtchnl_queue_select *qsel,
717 			   bool on)
718 {
719 	int ret = I40E_SUCCESS;
720 	int i;
721 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
722 	uint16_t baseq = vf->vsi->base_queue;
723 
724 	if (qsel->rx_queues + qsel->tx_queues == 0)
725 		return I40E_ERR_PARAM;
726 
727 	/* always enable RX first and disable last */
728 	/* Enable RX if it's enable */
729 	if (on) {
730 		for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++)
731 			if (qsel->rx_queues & (1 << i)) {
732 				ret = i40e_switch_rx_queue(hw, baseq + i, on);
733 				if (ret != I40E_SUCCESS)
734 					return ret;
735 			}
736 	}
737 
738 	/* Enable/Disable TX */
739 	for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++)
740 		if (qsel->tx_queues & (1 << i)) {
741 			ret = i40e_switch_tx_queue(hw, baseq + i, on);
742 			if (ret != I40E_SUCCESS)
743 				return ret;
744 		}
745 
746 	/* disable RX last if it's disable */
747 	if (!on) {
748 		/* disable RX */
749 		for (i = 0; i < I40E_MAX_QP_NUM_PER_VF; i++)
750 			if (qsel->rx_queues & (1 << i)) {
751 				ret = i40e_switch_rx_queue(hw, baseq + i, on);
752 				if (ret != I40E_SUCCESS)
753 					return ret;
754 			}
755 	}
756 
757 	return ret;
758 }
759 
760 static int
761 i40e_pf_host_process_cmd_enable_queues(struct i40e_pf_vf *vf,
762 				       uint8_t *msg,
763 				       uint16_t msglen)
764 {
765 	int ret = I40E_SUCCESS;
766 	struct virtchnl_queue_select *q_sel =
767 		(struct virtchnl_queue_select *)msg;
768 
769 	if (msg == NULL || msglen != sizeof(*q_sel)) {
770 		ret = I40E_ERR_PARAM;
771 		goto send_msg;
772 	}
773 	ret = i40e_pf_host_switch_queues(vf, q_sel, true);
774 
775 send_msg:
776 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_QUEUES,
777 							ret, NULL, 0);
778 
779 	return ret;
780 }
781 
782 static int
783 i40e_pf_host_process_cmd_disable_queues(struct i40e_pf_vf *vf,
784 					uint8_t *msg,
785 					uint16_t msglen,
786 					bool b_op)
787 {
788 	int ret = I40E_SUCCESS;
789 	struct virtchnl_queue_select *q_sel =
790 		(struct virtchnl_queue_select *)msg;
791 
792 	if (!b_op) {
793 		i40e_pf_host_send_msg_to_vf(
794 			vf,
795 			VIRTCHNL_OP_DISABLE_QUEUES,
796 			I40E_NOT_SUPPORTED, NULL, 0);
797 		return ret;
798 	}
799 
800 	if (msg == NULL || msglen != sizeof(*q_sel)) {
801 		ret = I40E_ERR_PARAM;
802 		goto send_msg;
803 	}
804 	ret = i40e_pf_host_switch_queues(vf, q_sel, false);
805 
806 send_msg:
807 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_QUEUES,
808 							ret, NULL, 0);
809 
810 	return ret;
811 }
812 
813 
814 static int
815 i40e_pf_host_process_cmd_add_ether_address(struct i40e_pf_vf *vf,
816 					   uint8_t *msg,
817 					   uint16_t msglen,
818 					   bool b_op)
819 {
820 	int ret = I40E_SUCCESS;
821 	struct virtchnl_ether_addr_list *addr_list =
822 			(struct virtchnl_ether_addr_list *)msg;
823 	struct i40e_mac_filter_info filter;
824 	int i;
825 	struct ether_addr *mac;
826 
827 	if (!b_op) {
828 		i40e_pf_host_send_msg_to_vf(
829 			vf,
830 			VIRTCHNL_OP_ADD_ETH_ADDR,
831 			I40E_NOT_SUPPORTED, NULL, 0);
832 		return ret;
833 	}
834 
835 	memset(&filter, 0 , sizeof(struct i40e_mac_filter_info));
836 
837 	if (msg == NULL || msglen <= sizeof(*addr_list)) {
838 		PMD_DRV_LOG(ERR, "add_ether_address argument too short");
839 		ret = I40E_ERR_PARAM;
840 		goto send_msg;
841 	}
842 
843 	for (i = 0; i < addr_list->num_elements; i++) {
844 		mac = (struct ether_addr *)(addr_list->list[i].addr);
845 		rte_memcpy(&filter.mac_addr, mac, ETHER_ADDR_LEN);
846 		filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
847 		if (is_zero_ether_addr(mac) ||
848 		    i40e_vsi_add_mac(vf->vsi, &filter)) {
849 			ret = I40E_ERR_INVALID_MAC_ADDR;
850 			goto send_msg;
851 		}
852 	}
853 
854 send_msg:
855 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
856 							ret, NULL, 0);
857 
858 	return ret;
859 }
860 
861 static int
862 i40e_pf_host_process_cmd_del_ether_address(struct i40e_pf_vf *vf,
863 					   uint8_t *msg,
864 					   uint16_t msglen,
865 					   bool b_op)
866 {
867 	int ret = I40E_SUCCESS;
868 	struct virtchnl_ether_addr_list *addr_list =
869 		(struct virtchnl_ether_addr_list *)msg;
870 	int i;
871 	struct ether_addr *mac;
872 
873 	if (!b_op) {
874 		i40e_pf_host_send_msg_to_vf(
875 			vf,
876 			VIRTCHNL_OP_DEL_ETH_ADDR,
877 			I40E_NOT_SUPPORTED, NULL, 0);
878 		return ret;
879 	}
880 
881 	if (msg == NULL || msglen <= sizeof(*addr_list)) {
882 		PMD_DRV_LOG(ERR, "delete_ether_address argument too short");
883 		ret = I40E_ERR_PARAM;
884 		goto send_msg;
885 	}
886 
887 	for (i = 0; i < addr_list->num_elements; i++) {
888 		mac = (struct ether_addr *)(addr_list->list[i].addr);
889 		if(is_zero_ether_addr(mac) ||
890 			i40e_vsi_delete_mac(vf->vsi, mac)) {
891 			ret = I40E_ERR_INVALID_MAC_ADDR;
892 			goto send_msg;
893 		}
894 	}
895 
896 send_msg:
897 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
898 							ret, NULL, 0);
899 
900 	return ret;
901 }
902 
903 static int
904 i40e_pf_host_process_cmd_add_vlan(struct i40e_pf_vf *vf,
905 				uint8_t *msg, uint16_t msglen,
906 				bool b_op)
907 {
908 	int ret = I40E_SUCCESS;
909 	struct virtchnl_vlan_filter_list *vlan_filter_list =
910 		(struct virtchnl_vlan_filter_list *)msg;
911 	int i;
912 	uint16_t *vid;
913 
914 	if (!b_op) {
915 		i40e_pf_host_send_msg_to_vf(
916 			vf,
917 			VIRTCHNL_OP_ADD_VLAN,
918 			I40E_NOT_SUPPORTED, NULL, 0);
919 		return ret;
920 	}
921 
922 	if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
923 		PMD_DRV_LOG(ERR, "add_vlan argument too short");
924 		ret = I40E_ERR_PARAM;
925 		goto send_msg;
926 	}
927 
928 	vid = vlan_filter_list->vlan_id;
929 
930 	for (i = 0; i < vlan_filter_list->num_elements; i++) {
931 		ret = i40e_vsi_add_vlan(vf->vsi, vid[i]);
932 		if(ret != I40E_SUCCESS)
933 			goto send_msg;
934 	}
935 
936 send_msg:
937 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_VLAN,
938 						ret, NULL, 0);
939 
940 	return ret;
941 }
942 
943 static int
944 i40e_pf_host_process_cmd_del_vlan(struct i40e_pf_vf *vf,
945 				  uint8_t *msg,
946 				  uint16_t msglen,
947 				  bool b_op)
948 {
949 	int ret = I40E_SUCCESS;
950 	struct virtchnl_vlan_filter_list *vlan_filter_list =
951 			(struct virtchnl_vlan_filter_list *)msg;
952 	int i;
953 	uint16_t *vid;
954 
955 	if (!b_op) {
956 		i40e_pf_host_send_msg_to_vf(
957 			vf,
958 			VIRTCHNL_OP_DEL_VLAN,
959 			I40E_NOT_SUPPORTED, NULL, 0);
960 		return ret;
961 	}
962 
963 	if (msg == NULL || msglen <= sizeof(*vlan_filter_list)) {
964 		PMD_DRV_LOG(ERR, "delete_vlan argument too short");
965 		ret = I40E_ERR_PARAM;
966 		goto send_msg;
967 	}
968 
969 	vid = vlan_filter_list->vlan_id;
970 	for (i = 0; i < vlan_filter_list->num_elements; i++) {
971 		ret = i40e_vsi_delete_vlan(vf->vsi, vid[i]);
972 		if(ret != I40E_SUCCESS)
973 			goto send_msg;
974 	}
975 
976 send_msg:
977 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_VLAN,
978 						ret, NULL, 0);
979 
980 	return ret;
981 }
982 
983 static int
984 i40e_pf_host_process_cmd_config_promisc_mode(
985 					struct i40e_pf_vf *vf,
986 					uint8_t *msg,
987 					uint16_t msglen,
988 					bool b_op)
989 {
990 	int ret = I40E_SUCCESS;
991 	struct virtchnl_promisc_info *promisc =
992 				(struct virtchnl_promisc_info *)msg;
993 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
994 	bool unicast = FALSE, multicast = FALSE;
995 
996 	if (!b_op) {
997 		i40e_pf_host_send_msg_to_vf(
998 			vf,
999 			VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
1000 			I40E_NOT_SUPPORTED, NULL, 0);
1001 		return ret;
1002 	}
1003 
1004 	if (msg == NULL || msglen != sizeof(*promisc)) {
1005 		ret = I40E_ERR_PARAM;
1006 		goto send_msg;
1007 	}
1008 
1009 	if (promisc->flags & FLAG_VF_UNICAST_PROMISC)
1010 		unicast = TRUE;
1011 	ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
1012 			vf->vsi->seid, unicast, NULL, true);
1013 	if (ret != I40E_SUCCESS)
1014 		goto send_msg;
1015 
1016 	if (promisc->flags & FLAG_VF_MULTICAST_PROMISC)
1017 		multicast = TRUE;
1018 	ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vf->vsi->seid,
1019 						multicast, NULL);
1020 
1021 send_msg:
1022 	i40e_pf_host_send_msg_to_vf(vf,
1023 		VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, ret, NULL, 0);
1024 
1025 	return ret;
1026 }
1027 
1028 static int
1029 i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf, bool b_op)
1030 {
1031 	i40e_update_vsi_stats(vf->vsi);
1032 
1033 	if (b_op)
1034 		i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_GET_STATS,
1035 					    I40E_SUCCESS,
1036 					    (uint8_t *)&vf->vsi->eth_stats,
1037 					    sizeof(vf->vsi->eth_stats));
1038 	else
1039 		i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_GET_STATS,
1040 					    I40E_NOT_SUPPORTED,
1041 					    (uint8_t *)&vf->vsi->eth_stats,
1042 					    sizeof(vf->vsi->eth_stats));
1043 
1044 	return I40E_SUCCESS;
1045 }
1046 
1047 static int
1048 i40e_pf_host_process_cmd_enable_vlan_strip(struct i40e_pf_vf *vf, bool b_op)
1049 {
1050 	int ret = I40E_SUCCESS;
1051 
1052 	if (!b_op) {
1053 		i40e_pf_host_send_msg_to_vf(
1054 			vf,
1055 			VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
1056 			I40E_NOT_SUPPORTED, NULL, 0);
1057 		return ret;
1058 	}
1059 
1060 	ret = i40e_vsi_config_vlan_stripping(vf->vsi, TRUE);
1061 	if (ret != 0)
1062 		PMD_DRV_LOG(ERR, "Failed to enable vlan stripping");
1063 
1064 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
1065 				    ret, NULL, 0);
1066 
1067 	return ret;
1068 }
1069 
1070 static int
1071 i40e_pf_host_process_cmd_disable_vlan_strip(struct i40e_pf_vf *vf, bool b_op)
1072 {
1073 	int ret = I40E_SUCCESS;
1074 
1075 	if (!b_op) {
1076 		i40e_pf_host_send_msg_to_vf(
1077 			vf,
1078 			VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
1079 			I40E_NOT_SUPPORTED, NULL, 0);
1080 		return ret;
1081 	}
1082 
1083 	ret = i40e_vsi_config_vlan_stripping(vf->vsi, FALSE);
1084 	if (ret != 0)
1085 		PMD_DRV_LOG(ERR, "Failed to disable vlan stripping");
1086 
1087 	i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
1088 				    ret, NULL, 0);
1089 
1090 	return ret;
1091 }
1092 
1093 void
1094 i40e_notify_vf_link_status(struct rte_eth_dev *dev, struct i40e_pf_vf *vf)
1095 {
1096 	struct i40e_hw *hw = I40E_PF_TO_HW(vf->pf);
1097 	struct virtchnl_pf_event event;
1098 	uint16_t vf_id = vf->vf_idx;
1099 	uint32_t tval, rval;
1100 
1101 	event.event = VIRTCHNL_EVENT_LINK_CHANGE;
1102 	event.event_data.link_event.link_status =
1103 		dev->data->dev_link.link_status;
1104 
1105 	/* need to convert the ETH_SPEED_xxx into VIRTCHNL_LINK_SPEED_xxx */
1106 	switch (dev->data->dev_link.link_speed) {
1107 	case ETH_SPEED_NUM_100M:
1108 		event.event_data.link_event.link_speed = VIRTCHNL_LINK_SPEED_100MB;
1109 		break;
1110 	case ETH_SPEED_NUM_1G:
1111 		event.event_data.link_event.link_speed = VIRTCHNL_LINK_SPEED_1GB;
1112 		break;
1113 	case ETH_SPEED_NUM_10G:
1114 		event.event_data.link_event.link_speed = VIRTCHNL_LINK_SPEED_10GB;
1115 		break;
1116 	case ETH_SPEED_NUM_20G:
1117 		event.event_data.link_event.link_speed = VIRTCHNL_LINK_SPEED_20GB;
1118 		break;
1119 	case ETH_SPEED_NUM_25G:
1120 		event.event_data.link_event.link_speed = VIRTCHNL_LINK_SPEED_25GB;
1121 		break;
1122 	case ETH_SPEED_NUM_40G:
1123 		event.event_data.link_event.link_speed = VIRTCHNL_LINK_SPEED_40GB;
1124 		break;
1125 	default:
1126 		event.event_data.link_event.link_speed =
1127 			VIRTCHNL_LINK_SPEED_UNKNOWN;
1128 		break;
1129 	}
1130 
1131 	tval = I40E_READ_REG(hw, I40E_VF_ATQLEN(vf_id));
1132 	rval = I40E_READ_REG(hw, I40E_VF_ARQLEN(vf_id));
1133 
1134 	if (tval & I40E_VF_ATQLEN_ATQLEN_MASK ||
1135 	    tval & I40E_VF_ATQLEN_ATQENABLE_MASK ||
1136 	    rval & I40E_VF_ARQLEN_ARQLEN_MASK ||
1137 	    rval & I40E_VF_ARQLEN_ARQENABLE_MASK)
1138 		i40e_pf_host_send_msg_to_vf(vf, VIRTCHNL_OP_EVENT,
1139 			I40E_SUCCESS, (uint8_t *)&event, sizeof(event));
1140 }
1141 
1142 void
1143 i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
1144 			   uint16_t abs_vf_id, uint32_t opcode,
1145 			   __rte_unused uint32_t retval,
1146 			   uint8_t *msg,
1147 			   uint16_t msglen)
1148 {
1149 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1150 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1151 	struct i40e_pf_vf *vf;
1152 	/* AdminQ will pass absolute VF id, transfer to internal vf id */
1153 	uint16_t vf_id = abs_vf_id - hw->func_caps.vf_base_id;
1154 	struct rte_pmd_i40e_mb_event_param ret_param;
1155 	bool b_op = TRUE;
1156 
1157 	if (vf_id > pf->vf_num - 1 || !pf->vfs) {
1158 		PMD_DRV_LOG(ERR, "invalid argument");
1159 		return;
1160 	}
1161 
1162 	vf = &pf->vfs[vf_id];
1163 	if (!vf->vsi) {
1164 		PMD_DRV_LOG(ERR, "NO VSI associated with VF found");
1165 		i40e_pf_host_send_msg_to_vf(vf, opcode,
1166 			I40E_ERR_NO_AVAILABLE_VSI, NULL, 0);
1167 		return;
1168 	}
1169 
1170 	/**
1171 	 * initialise structure to send to user application
1172 	 * will return response from user in retval field
1173 	 */
1174 	ret_param.retval = RTE_PMD_I40E_MB_EVENT_PROCEED;
1175 	ret_param.vfid = vf_id;
1176 	ret_param.msg_type = opcode;
1177 	ret_param.msg = (void *)msg;
1178 	ret_param.msglen = msglen;
1179 
1180 	/**
1181 	 * Ask user application if we're allowed to perform those functions.
1182 	 * If we get ret_param.retval == RTE_PMD_I40E_MB_EVENT_PROCEED,
1183 	 * then business as usual.
1184 	 * If RTE_PMD_I40E_MB_EVENT_NOOP_ACK or RTE_PMD_I40E_MB_EVENT_NOOP_NACK,
1185 	 * do nothing and send not_supported to VF. As PF must send a response
1186 	 * to VF and ACK/NACK is not defined.
1187 	 */
1188 	_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_VF_MBOX,
1189 				      NULL, &ret_param);
1190 	if (ret_param.retval != RTE_PMD_I40E_MB_EVENT_PROCEED) {
1191 		PMD_DRV_LOG(WARNING, "VF to PF message(%d) is not permitted!",
1192 			    opcode);
1193 		b_op = FALSE;
1194 	}
1195 
1196 	switch (opcode) {
1197 	case VIRTCHNL_OP_VERSION:
1198 		PMD_DRV_LOG(INFO, "OP_VERSION received");
1199 		i40e_pf_host_process_cmd_version(vf, b_op);
1200 		break;
1201 	case VIRTCHNL_OP_RESET_VF:
1202 		PMD_DRV_LOG(INFO, "OP_RESET_VF received");
1203 		i40e_pf_host_process_cmd_reset_vf(vf);
1204 		break;
1205 	case VIRTCHNL_OP_GET_VF_RESOURCES:
1206 		PMD_DRV_LOG(INFO, "OP_GET_VF_RESOURCES received");
1207 		i40e_pf_host_process_cmd_get_vf_resource(vf, b_op);
1208 		break;
1209 	case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
1210 		PMD_DRV_LOG(INFO, "OP_CONFIG_VSI_QUEUES received");
1211 		i40e_pf_host_process_cmd_config_vsi_queues(vf, msg,
1212 							   msglen, b_op);
1213 		break;
1214 	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
1215 		PMD_DRV_LOG(INFO, "OP_CONFIG_IRQ_MAP received");
1216 		i40e_pf_host_process_cmd_config_irq_map(vf, msg, msglen, b_op);
1217 		break;
1218 	case VIRTCHNL_OP_ENABLE_QUEUES:
1219 		PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
1220 		if (b_op) {
1221 			i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
1222 			i40e_notify_vf_link_status(dev, vf);
1223 		} else {
1224 			i40e_pf_host_send_msg_to_vf(
1225 				vf, VIRTCHNL_OP_ENABLE_QUEUES,
1226 				I40E_NOT_SUPPORTED, NULL, 0);
1227 		}
1228 		break;
1229 	case VIRTCHNL_OP_DISABLE_QUEUES:
1230 		PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
1231 		i40e_pf_host_process_cmd_disable_queues(vf, msg, msglen, b_op);
1232 		break;
1233 	case VIRTCHNL_OP_ADD_ETH_ADDR:
1234 		PMD_DRV_LOG(INFO, "OP_ADD_ETHER_ADDRESS received");
1235 		i40e_pf_host_process_cmd_add_ether_address(vf, msg,
1236 							   msglen, b_op);
1237 		break;
1238 	case VIRTCHNL_OP_DEL_ETH_ADDR:
1239 		PMD_DRV_LOG(INFO, "OP_DEL_ETHER_ADDRESS received");
1240 		i40e_pf_host_process_cmd_del_ether_address(vf, msg,
1241 							   msglen, b_op);
1242 		break;
1243 	case VIRTCHNL_OP_ADD_VLAN:
1244 		PMD_DRV_LOG(INFO, "OP_ADD_VLAN received");
1245 		i40e_pf_host_process_cmd_add_vlan(vf, msg, msglen, b_op);
1246 		break;
1247 	case VIRTCHNL_OP_DEL_VLAN:
1248 		PMD_DRV_LOG(INFO, "OP_DEL_VLAN received");
1249 		i40e_pf_host_process_cmd_del_vlan(vf, msg, msglen, b_op);
1250 		break;
1251 	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
1252 		PMD_DRV_LOG(INFO, "OP_CONFIG_PROMISCUOUS_MODE received");
1253 		i40e_pf_host_process_cmd_config_promisc_mode(vf, msg,
1254 							     msglen, b_op);
1255 		break;
1256 	case VIRTCHNL_OP_GET_STATS:
1257 		PMD_DRV_LOG(INFO, "OP_GET_STATS received");
1258 		i40e_pf_host_process_cmd_get_stats(vf, b_op);
1259 		break;
1260 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
1261 		PMD_DRV_LOG(INFO, "OP_ENABLE_VLAN_STRIPPING received");
1262 		i40e_pf_host_process_cmd_enable_vlan_strip(vf, b_op);
1263 		break;
1264 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
1265 		PMD_DRV_LOG(INFO, "OP_DISABLE_VLAN_STRIPPING received");
1266 		i40e_pf_host_process_cmd_disable_vlan_strip(vf, b_op);
1267 		break;
1268 	/* Don't add command supported below, which will
1269 	 * return an error code.
1270 	 */
1271 	default:
1272 		PMD_DRV_LOG(ERR, "%u received, not supported", opcode);
1273 		i40e_pf_host_send_msg_to_vf(vf, opcode, I40E_ERR_PARAM,
1274 								NULL, 0);
1275 		break;
1276 	}
1277 }
1278 
1279 int
1280 i40e_pf_host_init(struct rte_eth_dev *dev)
1281 {
1282 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1283 	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
1284 	int ret, i;
1285 	uint32_t val;
1286 
1287 	PMD_INIT_FUNC_TRACE();
1288 
1289 	/**
1290 	 * return if SRIOV not enabled, VF number not configured or
1291 	 * no queue assigned.
1292 	 */
1293 	if(!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 || pf->vf_nb_qps == 0)
1294 		return I40E_SUCCESS;
1295 
1296 	/* Allocate memory to store VF structure */
1297 	pf->vfs = rte_zmalloc("i40e_pf_vf",sizeof(*pf->vfs) * pf->vf_num, 0);
1298 	if(pf->vfs == NULL)
1299 		return -ENOMEM;
1300 
1301 	/* Disable irq0 for VFR event */
1302 	i40e_pf_disable_irq0(hw);
1303 
1304 	/* Disable VF link status interrupt */
1305 	val = I40E_READ_REG(hw, I40E_PFGEN_PORTMDIO_NUM);
1306 	val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK;
1307 	I40E_WRITE_REG(hw, I40E_PFGEN_PORTMDIO_NUM, val);
1308 	I40E_WRITE_FLUSH(hw);
1309 
1310 	for (i = 0; i < pf->vf_num; i++) {
1311 		pf->vfs[i].pf = pf;
1312 		pf->vfs[i].state = I40E_VF_INACTIVE;
1313 		pf->vfs[i].vf_idx = i;
1314 		ret = i40e_pf_host_vf_reset(&pf->vfs[i], 0);
1315 		if (ret != I40E_SUCCESS)
1316 			goto fail;
1317 	}
1318 
1319 	RTE_ETH_DEV_SRIOV(dev).active = pf->vf_num;
1320 	/* restore irq0 */
1321 	i40e_pf_enable_irq0(hw);
1322 
1323 	return I40E_SUCCESS;
1324 
1325 fail:
1326 	rte_free(pf->vfs);
1327 	i40e_pf_enable_irq0(hw);
1328 
1329 	return ret;
1330 }
1331 
1332 int
1333 i40e_pf_host_uninit(struct rte_eth_dev *dev)
1334 {
1335 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1336 	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
1337 	uint32_t val;
1338 
1339 	PMD_INIT_FUNC_TRACE();
1340 
1341 	/**
1342 	 * return if SRIOV not enabled, VF number not configured or
1343 	 * no queue assigned.
1344 	 */
1345 	if ((!hw->func_caps.sr_iov_1_1) ||
1346 		(pf->vf_num == 0) ||
1347 		(pf->vf_nb_qps == 0))
1348 		return I40E_SUCCESS;
1349 
1350 	/* free memory to store VF structure */
1351 	rte_free(pf->vfs);
1352 	pf->vfs = NULL;
1353 
1354 	/* Disable irq0 for VFR event */
1355 	i40e_pf_disable_irq0(hw);
1356 
1357 	/* Disable VF link status interrupt */
1358 	val = I40E_READ_REG(hw, I40E_PFGEN_PORTMDIO_NUM);
1359 	val &= ~I40E_PFGEN_PORTMDIO_NUM_VFLINK_STAT_ENA_MASK;
1360 	I40E_WRITE_REG(hw, I40E_PFGEN_PORTMDIO_NUM, val);
1361 	I40E_WRITE_FLUSH(hw);
1362 
1363 	return I40E_SUCCESS;
1364 }
1365