xref: /dpdk/drivers/net/ngbe/ngbe_pf.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
160229dcfSJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause
260229dcfSJiawen Wu  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
360229dcfSJiawen Wu  * Copyright(c) 2010-2017 Intel Corporation
460229dcfSJiawen Wu  */
560229dcfSJiawen Wu 
660229dcfSJiawen Wu #include <rte_ether.h>
760229dcfSJiawen Wu #include <ethdev_driver.h>
860229dcfSJiawen Wu #include <rte_malloc.h>
91f37cb2bSDavid Marchand #include <bus_pci_driver.h>
1060229dcfSJiawen Wu 
1160229dcfSJiawen Wu #include "base/ngbe.h"
1260229dcfSJiawen Wu #include "ngbe_ethdev.h"
1360229dcfSJiawen Wu 
1460229dcfSJiawen Wu #define NGBE_MAX_VFTA     (128)
15e2a289a7SJiawen Wu #define NGBE_VF_MSG_SIZE_DEFAULT 1
16e2a289a7SJiawen Wu #define NGBE_VF_GET_QUEUE_MSG_SIZE 5
1760229dcfSJiawen Wu 
1860229dcfSJiawen Wu static inline uint16_t
1960229dcfSJiawen Wu dev_num_vf(struct rte_eth_dev *eth_dev)
2060229dcfSJiawen Wu {
2160229dcfSJiawen Wu 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
2260229dcfSJiawen Wu 
2360229dcfSJiawen Wu 	/* EM only support 7 VFs. */
2460229dcfSJiawen Wu 	return pci_dev->max_vfs;
2560229dcfSJiawen Wu }
2660229dcfSJiawen Wu 
2760229dcfSJiawen Wu static inline
2860229dcfSJiawen Wu int ngbe_vf_perm_addr_gen(struct rte_eth_dev *dev, uint16_t vf_num)
2960229dcfSJiawen Wu {
3060229dcfSJiawen Wu 	unsigned char vf_mac_addr[RTE_ETHER_ADDR_LEN];
3160229dcfSJiawen Wu 	struct ngbe_vf_info *vfinfo = *NGBE_DEV_VFDATA(dev);
3260229dcfSJiawen Wu 	uint16_t vfn;
3360229dcfSJiawen Wu 
3460229dcfSJiawen Wu 	for (vfn = 0; vfn < vf_num; vfn++) {
3560229dcfSJiawen Wu 		rte_eth_random_addr(vf_mac_addr);
3660229dcfSJiawen Wu 		/* keep the random address as default */
3760229dcfSJiawen Wu 		memcpy(vfinfo[vfn].vf_mac_addresses, vf_mac_addr,
3860229dcfSJiawen Wu 			   RTE_ETHER_ADDR_LEN);
3960229dcfSJiawen Wu 	}
4060229dcfSJiawen Wu 
4160229dcfSJiawen Wu 	return 0;
4260229dcfSJiawen Wu }
4360229dcfSJiawen Wu 
44e2a289a7SJiawen Wu static inline int
45e2a289a7SJiawen Wu ngbe_mb_intr_setup(struct rte_eth_dev *dev)
46e2a289a7SJiawen Wu {
47e2a289a7SJiawen Wu 	struct ngbe_interrupt *intr = ngbe_dev_intr(dev);
48e2a289a7SJiawen Wu 
49e2a289a7SJiawen Wu 	intr->mask_misc |= NGBE_ICRMISC_VFMBX;
50e2a289a7SJiawen Wu 
51e2a289a7SJiawen Wu 	return 0;
52e2a289a7SJiawen Wu }
53e2a289a7SJiawen Wu 
5460229dcfSJiawen Wu int ngbe_pf_host_init(struct rte_eth_dev *eth_dev)
5560229dcfSJiawen Wu {
5660229dcfSJiawen Wu 	struct ngbe_vf_info **vfinfo = NGBE_DEV_VFDATA(eth_dev);
5760229dcfSJiawen Wu 	struct ngbe_uta_info *uta_info = NGBE_DEV_UTA_INFO(eth_dev);
5860229dcfSJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
5960229dcfSJiawen Wu 	uint16_t vf_num;
6060229dcfSJiawen Wu 	uint8_t nb_queue = 1;
6160229dcfSJiawen Wu 	int ret = 0;
6260229dcfSJiawen Wu 
6360229dcfSJiawen Wu 	PMD_INIT_FUNC_TRACE();
6460229dcfSJiawen Wu 
6560229dcfSJiawen Wu 	RTE_ETH_DEV_SRIOV(eth_dev).active = 0;
6660229dcfSJiawen Wu 	vf_num = dev_num_vf(eth_dev);
6760229dcfSJiawen Wu 	if (vf_num == 0)
6860229dcfSJiawen Wu 		return ret;
6960229dcfSJiawen Wu 
7060229dcfSJiawen Wu 	*vfinfo = rte_zmalloc("vf_info",
7160229dcfSJiawen Wu 			sizeof(struct ngbe_vf_info) * vf_num, 0);
7260229dcfSJiawen Wu 	if (*vfinfo == NULL) {
7360229dcfSJiawen Wu 		PMD_INIT_LOG(ERR,
74*f665790aSDavid Marchand 			"Cannot allocate memory for private VF data");
7560229dcfSJiawen Wu 		return -ENOMEM;
7660229dcfSJiawen Wu 	}
7760229dcfSJiawen Wu 
7860229dcfSJiawen Wu 	ret = rte_eth_switch_domain_alloc(&(*vfinfo)->switch_domain_id);
7960229dcfSJiawen Wu 	if (ret) {
8060229dcfSJiawen Wu 		PMD_INIT_LOG(ERR,
8160229dcfSJiawen Wu 			"failed to allocate switch domain for device %d", ret);
8260229dcfSJiawen Wu 		rte_free(*vfinfo);
8360229dcfSJiawen Wu 		*vfinfo = NULL;
8460229dcfSJiawen Wu 		return ret;
8560229dcfSJiawen Wu 	}
8660229dcfSJiawen Wu 
8760229dcfSJiawen Wu 	memset(uta_info, 0, sizeof(struct ngbe_uta_info));
8860229dcfSJiawen Wu 	hw->mac.mc_filter_type = 0;
8960229dcfSJiawen Wu 
9060229dcfSJiawen Wu 	RTE_ETH_DEV_SRIOV(eth_dev).active = RTE_ETH_8_POOLS;
9160229dcfSJiawen Wu 	RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = nb_queue;
9260229dcfSJiawen Wu 	RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx =
9360229dcfSJiawen Wu 			(uint16_t)(vf_num * nb_queue);
9460229dcfSJiawen Wu 
9560229dcfSJiawen Wu 	ngbe_vf_perm_addr_gen(eth_dev, vf_num);
9660229dcfSJiawen Wu 
9760229dcfSJiawen Wu 	/* init_mailbox_params */
9860229dcfSJiawen Wu 	hw->mbx.init_params(hw);
9960229dcfSJiawen Wu 
100e2a289a7SJiawen Wu 	/* set mb interrupt mask */
101e2a289a7SJiawen Wu 	ngbe_mb_intr_setup(eth_dev);
102e2a289a7SJiawen Wu 
10360229dcfSJiawen Wu 	return ret;
10460229dcfSJiawen Wu }
10560229dcfSJiawen Wu 
10660229dcfSJiawen Wu void ngbe_pf_host_uninit(struct rte_eth_dev *eth_dev)
10760229dcfSJiawen Wu {
10860229dcfSJiawen Wu 	struct ngbe_vf_info **vfinfo;
10960229dcfSJiawen Wu 	uint16_t vf_num;
11060229dcfSJiawen Wu 	int ret;
11160229dcfSJiawen Wu 
11260229dcfSJiawen Wu 	PMD_INIT_FUNC_TRACE();
11360229dcfSJiawen Wu 
11460229dcfSJiawen Wu 	RTE_ETH_DEV_SRIOV(eth_dev).active = 0;
11560229dcfSJiawen Wu 	RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = 0;
11660229dcfSJiawen Wu 	RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = 0;
11760229dcfSJiawen Wu 
11860229dcfSJiawen Wu 	vf_num = dev_num_vf(eth_dev);
11960229dcfSJiawen Wu 	if (vf_num == 0)
12060229dcfSJiawen Wu 		return;
12160229dcfSJiawen Wu 
12260229dcfSJiawen Wu 	vfinfo = NGBE_DEV_VFDATA(eth_dev);
12360229dcfSJiawen Wu 	if (*vfinfo == NULL)
12460229dcfSJiawen Wu 		return;
12560229dcfSJiawen Wu 
12660229dcfSJiawen Wu 	ret = rte_eth_switch_domain_free((*vfinfo)->switch_domain_id);
12760229dcfSJiawen Wu 	if (ret)
12860229dcfSJiawen Wu 		PMD_INIT_LOG(WARNING, "failed to free switch domain: %d", ret);
12960229dcfSJiawen Wu 
13060229dcfSJiawen Wu 	rte_free(*vfinfo);
13160229dcfSJiawen Wu 	*vfinfo = NULL;
13260229dcfSJiawen Wu }
13360229dcfSJiawen Wu 
13460229dcfSJiawen Wu int ngbe_pf_host_configure(struct rte_eth_dev *eth_dev)
13560229dcfSJiawen Wu {
13660229dcfSJiawen Wu 	uint32_t vtctl, fcrth;
13760229dcfSJiawen Wu 	uint32_t vfre_offset;
13860229dcfSJiawen Wu 	uint16_t vf_num;
13960229dcfSJiawen Wu 	const uint8_t VFRE_SHIFT = 5;  /* VFRE 32 bits per slot */
14060229dcfSJiawen Wu 	const uint8_t VFRE_MASK = (uint8_t)((1U << VFRE_SHIFT) - 1);
14160229dcfSJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
14260229dcfSJiawen Wu 	uint32_t gpie;
14360229dcfSJiawen Wu 	uint32_t gcr_ext;
14460229dcfSJiawen Wu 	uint32_t vlanctrl;
14560229dcfSJiawen Wu 	int i;
14660229dcfSJiawen Wu 
14760229dcfSJiawen Wu 	vf_num = dev_num_vf(eth_dev);
14860229dcfSJiawen Wu 	if (vf_num == 0)
14960229dcfSJiawen Wu 		return -1;
15060229dcfSJiawen Wu 
15160229dcfSJiawen Wu 	/* set the default pool for PF */
15260229dcfSJiawen Wu 	vtctl = rd32(hw, NGBE_POOLCTL);
15360229dcfSJiawen Wu 	vtctl &= ~NGBE_POOLCTL_DEFPL_MASK;
15460229dcfSJiawen Wu 	vtctl |= NGBE_POOLCTL_DEFPL(vf_num);
15560229dcfSJiawen Wu 	vtctl |= NGBE_POOLCTL_RPLEN;
15660229dcfSJiawen Wu 	wr32(hw, NGBE_POOLCTL, vtctl);
15760229dcfSJiawen Wu 
15860229dcfSJiawen Wu 	vfre_offset = vf_num & VFRE_MASK;
15960229dcfSJiawen Wu 
16060229dcfSJiawen Wu 	/* Enable pools reserved to PF only */
16160229dcfSJiawen Wu 	wr32(hw, NGBE_POOLRXENA(0), (~0U) << vfre_offset);
16260229dcfSJiawen Wu 	wr32(hw, NGBE_POOLTXENA(0), (~0U) << vfre_offset);
16360229dcfSJiawen Wu 
16460229dcfSJiawen Wu 	wr32(hw, NGBE_PSRCTL, NGBE_PSRCTL_LBENA);
16560229dcfSJiawen Wu 
1667be78d02SJosh Soref 	/* clear VMDq map to permanent rar 0 */
16760229dcfSJiawen Wu 	hw->mac.clear_vmdq(hw, 0, BIT_MASK32);
16860229dcfSJiawen Wu 
16960229dcfSJiawen Wu 	/* clear VMDq map to scan rar 31 */
17060229dcfSJiawen Wu 	wr32(hw, NGBE_ETHADDRIDX, hw->mac.num_rar_entries);
17160229dcfSJiawen Wu 	wr32(hw, NGBE_ETHADDRASS, 0);
17260229dcfSJiawen Wu 
17360229dcfSJiawen Wu 	/* set VMDq map to default PF pool */
17460229dcfSJiawen Wu 	hw->mac.set_vmdq(hw, 0, vf_num);
17560229dcfSJiawen Wu 
17660229dcfSJiawen Wu 	/*
17760229dcfSJiawen Wu 	 * SW msut set PORTCTL.VT_Mode the same as GPIE.VT_Mode
17860229dcfSJiawen Wu 	 */
17960229dcfSJiawen Wu 	gpie = rd32(hw, NGBE_GPIE);
18060229dcfSJiawen Wu 	gpie |= NGBE_GPIE_MSIX;
18160229dcfSJiawen Wu 	gcr_ext = rd32(hw, NGBE_PORTCTL);
18260229dcfSJiawen Wu 	gcr_ext &= ~NGBE_PORTCTL_NUMVT_MASK;
18360229dcfSJiawen Wu 
18460229dcfSJiawen Wu 	if (RTE_ETH_DEV_SRIOV(eth_dev).active == RTE_ETH_8_POOLS)
18560229dcfSJiawen Wu 		gcr_ext |= NGBE_PORTCTL_NUMVT_8;
18660229dcfSJiawen Wu 
18760229dcfSJiawen Wu 	wr32(hw, NGBE_PORTCTL, gcr_ext);
18860229dcfSJiawen Wu 	wr32(hw, NGBE_GPIE, gpie);
18960229dcfSJiawen Wu 
19060229dcfSJiawen Wu 	/*
19160229dcfSJiawen Wu 	 * enable vlan filtering and allow all vlan tags through
19260229dcfSJiawen Wu 	 */
19360229dcfSJiawen Wu 	vlanctrl = rd32(hw, NGBE_VLANCTL);
19460229dcfSJiawen Wu 	vlanctrl |= NGBE_VLANCTL_VFE; /* enable vlan filters */
19560229dcfSJiawen Wu 	wr32(hw, NGBE_VLANCTL, vlanctrl);
19660229dcfSJiawen Wu 
19760229dcfSJiawen Wu 	/* enable all vlan filters */
19860229dcfSJiawen Wu 	for (i = 0; i < NGBE_MAX_VFTA; i++)
19960229dcfSJiawen Wu 		wr32(hw, NGBE_VLANTBL(i), 0xFFFFFFFF);
20060229dcfSJiawen Wu 
20160229dcfSJiawen Wu 	/* Enable MAC Anti-Spoofing */
20260229dcfSJiawen Wu 	hw->mac.set_mac_anti_spoofing(hw, FALSE, vf_num);
20360229dcfSJiawen Wu 
20460229dcfSJiawen Wu 	/* set flow control threshold to max to avoid tx switch hang */
20560229dcfSJiawen Wu 	wr32(hw, NGBE_FCWTRLO, 0);
20660229dcfSJiawen Wu 	fcrth = rd32(hw, NGBE_PBRXSIZE) - 32;
20760229dcfSJiawen Wu 	wr32(hw, NGBE_FCWTRHI, fcrth);
20860229dcfSJiawen Wu 
20960229dcfSJiawen Wu 	return 0;
21060229dcfSJiawen Wu }
21160229dcfSJiawen Wu 
212e2a289a7SJiawen Wu static void
213e2a289a7SJiawen Wu ngbe_set_rx_mode(struct rte_eth_dev *eth_dev)
214e2a289a7SJiawen Wu {
215e2a289a7SJiawen Wu 	struct rte_eth_dev_data *dev_data = eth_dev->data;
216e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
217e2a289a7SJiawen Wu 	u32 fctrl, vmolr;
218e2a289a7SJiawen Wu 	uint16_t vfn = dev_num_vf(eth_dev);
219e2a289a7SJiawen Wu 
220e2a289a7SJiawen Wu 	/* disable store-bad-packets */
221e2a289a7SJiawen Wu 	wr32m(hw, NGBE_SECRXCTL, NGBE_SECRXCTL_SAVEBAD, 0);
222e2a289a7SJiawen Wu 
223e2a289a7SJiawen Wu 	/* Check for Promiscuous and All Multicast modes */
224e2a289a7SJiawen Wu 	fctrl = rd32m(hw, NGBE_PSRCTL,
225e2a289a7SJiawen Wu 			~(NGBE_PSRCTL_UCP | NGBE_PSRCTL_MCP));
226e2a289a7SJiawen Wu 	fctrl |= NGBE_PSRCTL_BCA |
227e2a289a7SJiawen Wu 		 NGBE_PSRCTL_MCHFENA;
228e2a289a7SJiawen Wu 
229e2a289a7SJiawen Wu 	vmolr = rd32m(hw, NGBE_POOLETHCTL(vfn),
230e2a289a7SJiawen Wu 			~(NGBE_POOLETHCTL_UCP |
231e2a289a7SJiawen Wu 			  NGBE_POOLETHCTL_MCP |
232e2a289a7SJiawen Wu 			  NGBE_POOLETHCTL_UCHA |
233e2a289a7SJiawen Wu 			  NGBE_POOLETHCTL_MCHA));
234e2a289a7SJiawen Wu 	vmolr |= NGBE_POOLETHCTL_BCA |
235e2a289a7SJiawen Wu 		 NGBE_POOLETHCTL_UTA |
236e2a289a7SJiawen Wu 		 NGBE_POOLETHCTL_VLA;
237e2a289a7SJiawen Wu 
238e2a289a7SJiawen Wu 	if (dev_data->promiscuous) {
239e2a289a7SJiawen Wu 		fctrl |= NGBE_PSRCTL_UCP |
240e2a289a7SJiawen Wu 			 NGBE_PSRCTL_MCP;
241e2a289a7SJiawen Wu 		/* pf don't want packets routing to vf, so clear UPE */
242e2a289a7SJiawen Wu 		vmolr |= NGBE_POOLETHCTL_MCP;
243e2a289a7SJiawen Wu 	} else if (dev_data->all_multicast) {
244e2a289a7SJiawen Wu 		fctrl |= NGBE_PSRCTL_MCP;
245e2a289a7SJiawen Wu 		vmolr |= NGBE_POOLETHCTL_MCP;
246e2a289a7SJiawen Wu 	} else {
247e2a289a7SJiawen Wu 		vmolr |= NGBE_POOLETHCTL_UCHA;
248e2a289a7SJiawen Wu 		vmolr |= NGBE_POOLETHCTL_MCHA;
249e2a289a7SJiawen Wu 	}
250e2a289a7SJiawen Wu 
251e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLETHCTL(vfn), vmolr);
252e2a289a7SJiawen Wu 
253e2a289a7SJiawen Wu 	wr32(hw, NGBE_PSRCTL, fctrl);
254e2a289a7SJiawen Wu 
255e2a289a7SJiawen Wu 	ngbe_vlan_hw_strip_config(eth_dev);
256e2a289a7SJiawen Wu }
257e2a289a7SJiawen Wu 
258e2a289a7SJiawen Wu static inline void
259e2a289a7SJiawen Wu ngbe_vf_reset_event(struct rte_eth_dev *eth_dev, uint16_t vf)
260e2a289a7SJiawen Wu {
261e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
262e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *(NGBE_DEV_VFDATA(eth_dev));
263e2a289a7SJiawen Wu 	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
264e2a289a7SJiawen Wu 	uint32_t vmolr = rd32(hw, NGBE_POOLETHCTL(vf));
265e2a289a7SJiawen Wu 
266e2a289a7SJiawen Wu 	vmolr |= (NGBE_POOLETHCTL_UCHA |
267e2a289a7SJiawen Wu 			NGBE_POOLETHCTL_BCA | NGBE_POOLETHCTL_UTA);
268e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLETHCTL(vf), vmolr);
269e2a289a7SJiawen Wu 
270e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLTAG(vf), 0);
271e2a289a7SJiawen Wu 
272e2a289a7SJiawen Wu 	/* reset multicast table array for vf */
273e2a289a7SJiawen Wu 	vfinfo[vf].num_vf_mc_hashes = 0;
274e2a289a7SJiawen Wu 
275e2a289a7SJiawen Wu 	/* reset rx mode */
276e2a289a7SJiawen Wu 	ngbe_set_rx_mode(eth_dev);
277e2a289a7SJiawen Wu 
278e2a289a7SJiawen Wu 	hw->mac.clear_rar(hw, rar_entry);
279e2a289a7SJiawen Wu }
280e2a289a7SJiawen Wu 
281e2a289a7SJiawen Wu static inline void
282e2a289a7SJiawen Wu ngbe_vf_reset_msg(struct rte_eth_dev *eth_dev, uint16_t vf)
283e2a289a7SJiawen Wu {
284e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
285e2a289a7SJiawen Wu 	uint32_t reg;
286e2a289a7SJiawen Wu 	uint32_t vf_shift;
287e2a289a7SJiawen Wu 	const uint8_t VFRE_SHIFT = 5;  /* VFRE 32 bits per slot */
288e2a289a7SJiawen Wu 	const uint8_t VFRE_MASK = (uint8_t)((1U << VFRE_SHIFT) - 1);
289e2a289a7SJiawen Wu 	uint8_t  nb_q_per_pool;
290e2a289a7SJiawen Wu 	int i;
291e2a289a7SJiawen Wu 
292e2a289a7SJiawen Wu 	vf_shift = vf & VFRE_MASK;
293e2a289a7SJiawen Wu 
294e2a289a7SJiawen Wu 	/* enable transmit for vf */
295e2a289a7SJiawen Wu 	reg = rd32(hw, NGBE_POOLTXENA(0));
296e2a289a7SJiawen Wu 	reg |= (1 << vf_shift);
297e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLTXENA(0), reg);
298e2a289a7SJiawen Wu 
299e2a289a7SJiawen Wu 	/* enable all queue drop for IOV */
300e2a289a7SJiawen Wu 	nb_q_per_pool = RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool;
301e2a289a7SJiawen Wu 	for (i = vf * nb_q_per_pool; i < (vf + 1) * nb_q_per_pool; i++) {
302e2a289a7SJiawen Wu 		ngbe_flush(hw);
303e2a289a7SJiawen Wu 		reg = 1 << (i % 32);
304e2a289a7SJiawen Wu 		wr32m(hw, NGBE_QPRXDROP, reg, reg);
305e2a289a7SJiawen Wu 	}
306e2a289a7SJiawen Wu 
307e2a289a7SJiawen Wu 	/* enable receive for vf */
308e2a289a7SJiawen Wu 	reg = rd32(hw, NGBE_POOLRXENA(0));
309e2a289a7SJiawen Wu 	reg |= (reg | (1 << vf_shift));
310e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLRXENA(0), reg);
311e2a289a7SJiawen Wu 
312e2a289a7SJiawen Wu 	ngbe_vf_reset_event(eth_dev, vf);
313e2a289a7SJiawen Wu }
314e2a289a7SJiawen Wu 
315e2a289a7SJiawen Wu static int
316e2a289a7SJiawen Wu ngbe_disable_vf_mc_promisc(struct rte_eth_dev *eth_dev, uint32_t vf)
317e2a289a7SJiawen Wu {
318e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
319e2a289a7SJiawen Wu 	uint32_t vmolr;
320e2a289a7SJiawen Wu 
321e2a289a7SJiawen Wu 	vmolr = rd32(hw, NGBE_POOLETHCTL(vf));
322e2a289a7SJiawen Wu 
323*f665790aSDavid Marchand 	PMD_DRV_LOG(INFO, "VF %u: disabling multicast promiscuous", vf);
324e2a289a7SJiawen Wu 
325e2a289a7SJiawen Wu 	vmolr &= ~NGBE_POOLETHCTL_MCP;
326e2a289a7SJiawen Wu 
327e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLETHCTL(vf), vmolr);
328e2a289a7SJiawen Wu 
329e2a289a7SJiawen Wu 	return 0;
330e2a289a7SJiawen Wu }
331e2a289a7SJiawen Wu 
332e2a289a7SJiawen Wu static int
333e2a289a7SJiawen Wu ngbe_vf_reset(struct rte_eth_dev *eth_dev, uint16_t vf, uint32_t *msgbuf)
334e2a289a7SJiawen Wu {
335e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
336e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *(NGBE_DEV_VFDATA(eth_dev));
337e2a289a7SJiawen Wu 	unsigned char *vf_mac = vfinfo[vf].vf_mac_addresses;
338e2a289a7SJiawen Wu 	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
339e2a289a7SJiawen Wu 	uint8_t *new_mac = (uint8_t *)(&msgbuf[1]);
340e2a289a7SJiawen Wu 
341e2a289a7SJiawen Wu 	ngbe_vf_reset_msg(eth_dev, vf);
342e2a289a7SJiawen Wu 
343e2a289a7SJiawen Wu 	hw->mac.set_rar(hw, rar_entry, vf_mac, vf, true);
344e2a289a7SJiawen Wu 
345e2a289a7SJiawen Wu 	/* Disable multicast promiscuous at reset */
346e2a289a7SJiawen Wu 	ngbe_disable_vf_mc_promisc(eth_dev, vf);
347e2a289a7SJiawen Wu 
348e2a289a7SJiawen Wu 	/* reply to reset with ack and vf mac address */
349e2a289a7SJiawen Wu 	msgbuf[0] = NGBE_VF_RESET | NGBE_VT_MSGTYPE_ACK;
350e2a289a7SJiawen Wu 	rte_memcpy(new_mac, vf_mac, RTE_ETHER_ADDR_LEN);
351e2a289a7SJiawen Wu 	/*
352e2a289a7SJiawen Wu 	 * Piggyback the multicast filter type so VF can compute the
353e2a289a7SJiawen Wu 	 * correct vectors
354e2a289a7SJiawen Wu 	 */
355e2a289a7SJiawen Wu 	msgbuf[3] = hw->mac.mc_filter_type;
356e2a289a7SJiawen Wu 	ngbe_write_mbx(hw, msgbuf, NGBE_VF_PERMADDR_MSG_LEN, vf);
357e2a289a7SJiawen Wu 
358e2a289a7SJiawen Wu 	return 0;
359e2a289a7SJiawen Wu }
360e2a289a7SJiawen Wu 
361e2a289a7SJiawen Wu static int
362e2a289a7SJiawen Wu ngbe_vf_set_mac_addr(struct rte_eth_dev *eth_dev,
363e2a289a7SJiawen Wu 		uint32_t vf, uint32_t *msgbuf)
364e2a289a7SJiawen Wu {
365e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
366e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *(NGBE_DEV_VFDATA(eth_dev));
367e2a289a7SJiawen Wu 	int rar_entry = hw->mac.num_rar_entries - (vf + 1);
368e2a289a7SJiawen Wu 	uint8_t *new_mac = (uint8_t *)(&msgbuf[1]);
369e2a289a7SJiawen Wu 	struct rte_ether_addr *ea = (struct rte_ether_addr *)new_mac;
370e2a289a7SJiawen Wu 
371e2a289a7SJiawen Wu 	if (rte_is_valid_assigned_ether_addr(ea)) {
372e2a289a7SJiawen Wu 		rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, 6);
373e2a289a7SJiawen Wu 		return hw->mac.set_rar(hw, rar_entry, new_mac, vf, true);
374e2a289a7SJiawen Wu 	}
375e2a289a7SJiawen Wu 	return -1;
376e2a289a7SJiawen Wu }
377e2a289a7SJiawen Wu 
378e2a289a7SJiawen Wu static int
379e2a289a7SJiawen Wu ngbe_vf_set_multicast(struct rte_eth_dev *eth_dev,
380e2a289a7SJiawen Wu 		uint32_t vf, uint32_t *msgbuf)
381e2a289a7SJiawen Wu {
382e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
383e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *(NGBE_DEV_VFDATA(eth_dev));
384e2a289a7SJiawen Wu 	int nb_entries = (msgbuf[0] & NGBE_VT_MSGINFO_MASK) >>
385e2a289a7SJiawen Wu 		NGBE_VT_MSGINFO_SHIFT;
386e2a289a7SJiawen Wu 	uint16_t *hash_list = (uint16_t *)&msgbuf[1];
387e2a289a7SJiawen Wu 	uint32_t mta_idx;
388e2a289a7SJiawen Wu 	uint32_t mta_shift;
389e2a289a7SJiawen Wu 	const uint32_t NGBE_MTA_INDEX_MASK = 0x7F;
390e2a289a7SJiawen Wu 	const uint32_t NGBE_MTA_BIT_SHIFT = 5;
391e2a289a7SJiawen Wu 	const uint32_t NGBE_MTA_BIT_MASK = (0x1 << NGBE_MTA_BIT_SHIFT) - 1;
392e2a289a7SJiawen Wu 	uint32_t reg_val;
393e2a289a7SJiawen Wu 	int i;
394e2a289a7SJiawen Wu 	u32 vmolr = rd32(hw, NGBE_POOLETHCTL(vf));
395e2a289a7SJiawen Wu 
396e2a289a7SJiawen Wu 	/* Disable multicast promiscuous first */
397e2a289a7SJiawen Wu 	ngbe_disable_vf_mc_promisc(eth_dev, vf);
398e2a289a7SJiawen Wu 
399e2a289a7SJiawen Wu 	/* only so many hash values supported */
400e2a289a7SJiawen Wu 	nb_entries = RTE_MIN(nb_entries, NGBE_MAX_VF_MC_ENTRIES);
401e2a289a7SJiawen Wu 
402e2a289a7SJiawen Wu 	/* store the mc entries  */
403e2a289a7SJiawen Wu 	vfinfo->num_vf_mc_hashes = (uint16_t)nb_entries;
404e2a289a7SJiawen Wu 	for (i = 0; i < nb_entries; i++)
405e2a289a7SJiawen Wu 		vfinfo->vf_mc_hashes[i] = hash_list[i];
406e2a289a7SJiawen Wu 
407e2a289a7SJiawen Wu 	if (nb_entries == 0) {
408e2a289a7SJiawen Wu 		vmolr &= ~NGBE_POOLETHCTL_MCHA;
409e2a289a7SJiawen Wu 		wr32(hw, NGBE_POOLETHCTL(vf), vmolr);
410e2a289a7SJiawen Wu 		return 0;
411e2a289a7SJiawen Wu 	}
412e2a289a7SJiawen Wu 
413e2a289a7SJiawen Wu 	for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) {
414e2a289a7SJiawen Wu 		mta_idx = (vfinfo->vf_mc_hashes[i] >> NGBE_MTA_BIT_SHIFT)
415e2a289a7SJiawen Wu 				& NGBE_MTA_INDEX_MASK;
416e2a289a7SJiawen Wu 		mta_shift = vfinfo->vf_mc_hashes[i] & NGBE_MTA_BIT_MASK;
417e2a289a7SJiawen Wu 		reg_val = rd32(hw, NGBE_MCADDRTBL(mta_idx));
418e2a289a7SJiawen Wu 		reg_val |= (1 << mta_shift);
419e2a289a7SJiawen Wu 		wr32(hw, NGBE_MCADDRTBL(mta_idx), reg_val);
420e2a289a7SJiawen Wu 	}
421e2a289a7SJiawen Wu 
422e2a289a7SJiawen Wu 	vmolr |= NGBE_POOLETHCTL_MCHA;
423e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLETHCTL(vf), vmolr);
424e2a289a7SJiawen Wu 
425e2a289a7SJiawen Wu 	return 0;
426e2a289a7SJiawen Wu }
427e2a289a7SJiawen Wu 
428e2a289a7SJiawen Wu static int
429e2a289a7SJiawen Wu ngbe_vf_set_vlan(struct rte_eth_dev *eth_dev, uint32_t vf, uint32_t *msgbuf)
430e2a289a7SJiawen Wu {
431e2a289a7SJiawen Wu 	int add, vid;
432e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
433e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *(NGBE_DEV_VFDATA(eth_dev));
434e2a289a7SJiawen Wu 
435e2a289a7SJiawen Wu 	add = (msgbuf[0] & NGBE_VT_MSGINFO_MASK)
436e2a289a7SJiawen Wu 		>> NGBE_VT_MSGINFO_SHIFT;
437e2a289a7SJiawen Wu 	vid = NGBE_PSRVLAN_VID(msgbuf[1]);
438e2a289a7SJiawen Wu 
439e2a289a7SJiawen Wu 	if (add)
440e2a289a7SJiawen Wu 		vfinfo[vf].vlan_count++;
441e2a289a7SJiawen Wu 	else if (vfinfo[vf].vlan_count)
442e2a289a7SJiawen Wu 		vfinfo[vf].vlan_count--;
443e2a289a7SJiawen Wu 	return hw->mac.set_vfta(hw, vid, vf, (bool)add, false);
444e2a289a7SJiawen Wu }
445e2a289a7SJiawen Wu 
446e2a289a7SJiawen Wu static int
447e2a289a7SJiawen Wu ngbe_set_vf_lpe(struct rte_eth_dev *eth_dev,
448e2a289a7SJiawen Wu 		__rte_unused uint32_t vf, uint32_t *msgbuf)
449e2a289a7SJiawen Wu {
450e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
451e2a289a7SJiawen Wu 	uint32_t max_frame = msgbuf[1];
452e2a289a7SJiawen Wu 	uint32_t max_frs;
453e2a289a7SJiawen Wu 
454e2a289a7SJiawen Wu 	if (max_frame < RTE_ETHER_MIN_LEN ||
455e2a289a7SJiawen Wu 			max_frame > RTE_ETHER_MAX_JUMBO_FRAME_LEN)
456e2a289a7SJiawen Wu 		return -1;
457e2a289a7SJiawen Wu 
458e2a289a7SJiawen Wu 	max_frs = rd32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK);
459e2a289a7SJiawen Wu 	if (max_frs < max_frame) {
460e2a289a7SJiawen Wu 		wr32m(hw, NGBE_FRMSZ, NGBE_FRMSZ_MAX_MASK,
461e2a289a7SJiawen Wu 			NGBE_FRMSZ_MAX(max_frame));
462e2a289a7SJiawen Wu 	}
463e2a289a7SJiawen Wu 
464e2a289a7SJiawen Wu 	return 0;
465e2a289a7SJiawen Wu }
466e2a289a7SJiawen Wu 
467e2a289a7SJiawen Wu static int
468e2a289a7SJiawen Wu ngbe_negotiate_vf_api(struct rte_eth_dev *eth_dev,
469e2a289a7SJiawen Wu 		uint32_t vf, uint32_t *msgbuf)
470e2a289a7SJiawen Wu {
471e2a289a7SJiawen Wu 	uint32_t api_version = msgbuf[1];
472e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *NGBE_DEV_VFDATA(eth_dev);
473e2a289a7SJiawen Wu 
474e2a289a7SJiawen Wu 	switch (api_version) {
475e2a289a7SJiawen Wu 	case ngbe_mbox_api_10:
476e2a289a7SJiawen Wu 	case ngbe_mbox_api_11:
477e2a289a7SJiawen Wu 	case ngbe_mbox_api_12:
478e2a289a7SJiawen Wu 	case ngbe_mbox_api_13:
479e2a289a7SJiawen Wu 		vfinfo[vf].api_version = (uint8_t)api_version;
480e2a289a7SJiawen Wu 		return 0;
481e2a289a7SJiawen Wu 	default:
482e2a289a7SJiawen Wu 		break;
483e2a289a7SJiawen Wu 	}
484e2a289a7SJiawen Wu 
485*f665790aSDavid Marchand 	PMD_DRV_LOG(ERR, "Negotiate invalid api version %u from VF %d",
486e2a289a7SJiawen Wu 		api_version, vf);
487e2a289a7SJiawen Wu 
488e2a289a7SJiawen Wu 	return -1;
489e2a289a7SJiawen Wu }
490e2a289a7SJiawen Wu 
491e2a289a7SJiawen Wu static int
492e2a289a7SJiawen Wu ngbe_get_vf_queues(struct rte_eth_dev *eth_dev, uint32_t vf, uint32_t *msgbuf)
493e2a289a7SJiawen Wu {
494e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *NGBE_DEV_VFDATA(eth_dev);
495e2a289a7SJiawen Wu 	uint32_t default_q = 0;
496e2a289a7SJiawen Wu 
497e2a289a7SJiawen Wu 	/* Verify if the PF supports the mbox APIs version or not */
498e2a289a7SJiawen Wu 	switch (vfinfo[vf].api_version) {
499e2a289a7SJiawen Wu 	case ngbe_mbox_api_20:
500e2a289a7SJiawen Wu 	case ngbe_mbox_api_11:
501e2a289a7SJiawen Wu 	case ngbe_mbox_api_12:
502e2a289a7SJiawen Wu 	case ngbe_mbox_api_13:
503e2a289a7SJiawen Wu 		break;
504e2a289a7SJiawen Wu 	default:
505e2a289a7SJiawen Wu 		return -1;
506e2a289a7SJiawen Wu 	}
507e2a289a7SJiawen Wu 
508e2a289a7SJiawen Wu 	/* Notify VF of Rx and Tx queue number */
509e2a289a7SJiawen Wu 	msgbuf[NGBE_VF_RX_QUEUES] = RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool;
510e2a289a7SJiawen Wu 	msgbuf[NGBE_VF_TX_QUEUES] = RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool;
511e2a289a7SJiawen Wu 
512e2a289a7SJiawen Wu 	/* Notify VF of default queue */
513e2a289a7SJiawen Wu 	msgbuf[NGBE_VF_DEF_QUEUE] = default_q;
514e2a289a7SJiawen Wu 
515e2a289a7SJiawen Wu 	msgbuf[NGBE_VF_TRANS_VLAN] = 0;
516e2a289a7SJiawen Wu 
517e2a289a7SJiawen Wu 	return 0;
518e2a289a7SJiawen Wu }
519e2a289a7SJiawen Wu 
520e2a289a7SJiawen Wu static int
521e2a289a7SJiawen Wu ngbe_set_vf_mc_promisc(struct rte_eth_dev *eth_dev,
522e2a289a7SJiawen Wu 		uint32_t vf, uint32_t *msgbuf)
523e2a289a7SJiawen Wu {
524e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *(NGBE_DEV_VFDATA(eth_dev));
525e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
526e2a289a7SJiawen Wu 	int xcast_mode = msgbuf[1];	/* msgbuf contains the flag to enable */
527e2a289a7SJiawen Wu 	u32 vmolr, fctrl, disable, enable;
528e2a289a7SJiawen Wu 
529e2a289a7SJiawen Wu 	switch (vfinfo[vf].api_version) {
530e2a289a7SJiawen Wu 	case ngbe_mbox_api_12:
531e2a289a7SJiawen Wu 		/* promisc introduced in 1.3 version */
532e2a289a7SJiawen Wu 		if (xcast_mode == NGBEVF_XCAST_MODE_PROMISC)
533e2a289a7SJiawen Wu 			return -EOPNOTSUPP;
534e2a289a7SJiawen Wu 		break;
535e2a289a7SJiawen Wu 		/* Fall threw */
536e2a289a7SJiawen Wu 	case ngbe_mbox_api_13:
537e2a289a7SJiawen Wu 		break;
538e2a289a7SJiawen Wu 	default:
539e2a289a7SJiawen Wu 		return -1;
540e2a289a7SJiawen Wu 	}
541e2a289a7SJiawen Wu 
542e2a289a7SJiawen Wu 	if (vfinfo[vf].xcast_mode == xcast_mode)
543e2a289a7SJiawen Wu 		goto out;
544e2a289a7SJiawen Wu 
545e2a289a7SJiawen Wu 	switch (xcast_mode) {
546e2a289a7SJiawen Wu 	case NGBEVF_XCAST_MODE_NONE:
547e2a289a7SJiawen Wu 		disable = NGBE_POOLETHCTL_BCA | NGBE_POOLETHCTL_MCHA |
548e2a289a7SJiawen Wu 			  NGBE_POOLETHCTL_MCP | NGBE_POOLETHCTL_UCP |
549e2a289a7SJiawen Wu 			  NGBE_POOLETHCTL_VLP;
550e2a289a7SJiawen Wu 		enable = 0;
551e2a289a7SJiawen Wu 		break;
552e2a289a7SJiawen Wu 	case NGBEVF_XCAST_MODE_MULTI:
553e2a289a7SJiawen Wu 		disable = NGBE_POOLETHCTL_MCP | NGBE_POOLETHCTL_UCP |
554e2a289a7SJiawen Wu 			  NGBE_POOLETHCTL_VLP;
555e2a289a7SJiawen Wu 		enable = NGBE_POOLETHCTL_BCA | NGBE_POOLETHCTL_MCHA;
556e2a289a7SJiawen Wu 		break;
557e2a289a7SJiawen Wu 	case NGBEVF_XCAST_MODE_ALLMULTI:
558e2a289a7SJiawen Wu 		disable = NGBE_POOLETHCTL_UCP | NGBE_POOLETHCTL_VLP;
559e2a289a7SJiawen Wu 		enable = NGBE_POOLETHCTL_BCA | NGBE_POOLETHCTL_MCHA |
560e2a289a7SJiawen Wu 			 NGBE_POOLETHCTL_MCP;
561e2a289a7SJiawen Wu 		break;
562e2a289a7SJiawen Wu 	case NGBEVF_XCAST_MODE_PROMISC:
563e2a289a7SJiawen Wu 		fctrl = rd32(hw, NGBE_PSRCTL);
564e2a289a7SJiawen Wu 		if (!(fctrl & NGBE_PSRCTL_UCP)) {
565e2a289a7SJiawen Wu 			/* VF promisc requires PF in promisc */
566e2a289a7SJiawen Wu 			PMD_DRV_LOG(ERR,
567*f665790aSDavid Marchand 			       "Enabling VF promisc requires PF in promisc");
568e2a289a7SJiawen Wu 			return -1;
569e2a289a7SJiawen Wu 		}
570e2a289a7SJiawen Wu 
571e2a289a7SJiawen Wu 		disable = 0;
572e2a289a7SJiawen Wu 		enable = NGBE_POOLETHCTL_BCA | NGBE_POOLETHCTL_MCHA |
573e2a289a7SJiawen Wu 			 NGBE_POOLETHCTL_MCP | NGBE_POOLETHCTL_UCP |
574e2a289a7SJiawen Wu 			 NGBE_POOLETHCTL_VLP;
575e2a289a7SJiawen Wu 		break;
576e2a289a7SJiawen Wu 	default:
577e2a289a7SJiawen Wu 		return -1;
578e2a289a7SJiawen Wu 	}
579e2a289a7SJiawen Wu 
580e2a289a7SJiawen Wu 	vmolr = rd32(hw, NGBE_POOLETHCTL(vf));
581e2a289a7SJiawen Wu 	vmolr &= ~disable;
582e2a289a7SJiawen Wu 	vmolr |= enable;
583e2a289a7SJiawen Wu 	wr32(hw, NGBE_POOLETHCTL(vf), vmolr);
584e2a289a7SJiawen Wu 	vfinfo[vf].xcast_mode = xcast_mode;
585e2a289a7SJiawen Wu 
586e2a289a7SJiawen Wu out:
587e2a289a7SJiawen Wu 	msgbuf[1] = xcast_mode;
588e2a289a7SJiawen Wu 
589e2a289a7SJiawen Wu 	return 0;
590e2a289a7SJiawen Wu }
591e2a289a7SJiawen Wu 
592e2a289a7SJiawen Wu static int
593e2a289a7SJiawen Wu ngbe_set_vf_macvlan_msg(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf)
594e2a289a7SJiawen Wu {
595e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(dev);
596e2a289a7SJiawen Wu 	struct ngbe_vf_info *vf_info = *(NGBE_DEV_VFDATA(dev));
597e2a289a7SJiawen Wu 	uint8_t *new_mac = (uint8_t *)(&msgbuf[1]);
598e2a289a7SJiawen Wu 	struct rte_ether_addr *ea = (struct rte_ether_addr *)new_mac;
599e2a289a7SJiawen Wu 	int index = (msgbuf[0] & NGBE_VT_MSGINFO_MASK) >>
600e2a289a7SJiawen Wu 		    NGBE_VT_MSGINFO_SHIFT;
601e2a289a7SJiawen Wu 
602e2a289a7SJiawen Wu 	if (index) {
603e2a289a7SJiawen Wu 		if (!rte_is_valid_assigned_ether_addr(ea)) {
604*f665790aSDavid Marchand 			PMD_DRV_LOG(ERR, "set invalid mac vf:%d", vf);
605e2a289a7SJiawen Wu 			return -1;
606e2a289a7SJiawen Wu 		}
607e2a289a7SJiawen Wu 
608e2a289a7SJiawen Wu 		vf_info[vf].mac_count++;
609e2a289a7SJiawen Wu 
610e2a289a7SJiawen Wu 		hw->mac.set_rar(hw, vf_info[vf].mac_count,
611e2a289a7SJiawen Wu 				new_mac, vf, true);
612e2a289a7SJiawen Wu 	} else {
613e2a289a7SJiawen Wu 		if (vf_info[vf].mac_count) {
614e2a289a7SJiawen Wu 			hw->mac.clear_rar(hw, vf_info[vf].mac_count);
615e2a289a7SJiawen Wu 			vf_info[vf].mac_count = 0;
616e2a289a7SJiawen Wu 		}
617e2a289a7SJiawen Wu 	}
618e2a289a7SJiawen Wu 	return 0;
619e2a289a7SJiawen Wu }
620e2a289a7SJiawen Wu 
621e2a289a7SJiawen Wu static int
622e2a289a7SJiawen Wu ngbe_rcv_msg_from_vf(struct rte_eth_dev *eth_dev, uint16_t vf)
623e2a289a7SJiawen Wu {
624e2a289a7SJiawen Wu 	uint16_t mbx_size = NGBE_P2VMBX_SIZE;
625e2a289a7SJiawen Wu 	uint16_t msg_size = NGBE_VF_MSG_SIZE_DEFAULT;
626e2a289a7SJiawen Wu 	uint32_t msgbuf[NGBE_P2VMBX_SIZE];
627e2a289a7SJiawen Wu 	int32_t retval;
628e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
629e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *NGBE_DEV_VFDATA(eth_dev);
630e2a289a7SJiawen Wu 	struct ngbe_mb_event_param ret_param;
631e2a289a7SJiawen Wu 
632e2a289a7SJiawen Wu 	retval = ngbe_read_mbx(hw, msgbuf, mbx_size, vf);
633e2a289a7SJiawen Wu 	if (retval) {
634e2a289a7SJiawen Wu 		PMD_DRV_LOG(ERR, "Error mbx recv msg from VF %d", vf);
635e2a289a7SJiawen Wu 		return retval;
636e2a289a7SJiawen Wu 	}
637e2a289a7SJiawen Wu 
638e2a289a7SJiawen Wu 	/* do nothing with the message already been processed */
639e2a289a7SJiawen Wu 	if (msgbuf[0] & (NGBE_VT_MSGTYPE_ACK | NGBE_VT_MSGTYPE_NACK))
640e2a289a7SJiawen Wu 		return retval;
641e2a289a7SJiawen Wu 
642e2a289a7SJiawen Wu 	/* flush the ack before we write any messages back */
643e2a289a7SJiawen Wu 	ngbe_flush(hw);
644e2a289a7SJiawen Wu 
645e2a289a7SJiawen Wu 	/**
646e2a289a7SJiawen Wu 	 * initialise structure to send to user application
647e2a289a7SJiawen Wu 	 * will return response from user in retval field
648e2a289a7SJiawen Wu 	 */
649e2a289a7SJiawen Wu 	ret_param.retval = NGBE_MB_EVENT_PROCEED;
650e2a289a7SJiawen Wu 	ret_param.vfid = vf;
651e2a289a7SJiawen Wu 	ret_param.msg_type = msgbuf[0] & 0xFFFF;
652e2a289a7SJiawen Wu 	ret_param.msg = (void *)msgbuf;
653e2a289a7SJiawen Wu 
654e2a289a7SJiawen Wu 	/* perform VF reset */
655e2a289a7SJiawen Wu 	if (msgbuf[0] == NGBE_VF_RESET) {
656e2a289a7SJiawen Wu 		int ret = ngbe_vf_reset(eth_dev, vf, msgbuf);
657e2a289a7SJiawen Wu 
658e2a289a7SJiawen Wu 		vfinfo[vf].clear_to_send = true;
659e2a289a7SJiawen Wu 
660e2a289a7SJiawen Wu 		/* notify application about VF reset */
661e2a289a7SJiawen Wu 		rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_VF_MBOX,
662e2a289a7SJiawen Wu 					      &ret_param);
663e2a289a7SJiawen Wu 		return ret;
664e2a289a7SJiawen Wu 	}
665e2a289a7SJiawen Wu 
666e2a289a7SJiawen Wu 	/**
667e2a289a7SJiawen Wu 	 * ask user application if we allowed to perform those functions
668e2a289a7SJiawen Wu 	 * if we get ret_param.retval == RTE_PMD_COMPAT_MB_EVENT_PROCEED
669e2a289a7SJiawen Wu 	 * then business as usual,
670e2a289a7SJiawen Wu 	 * if 0, do nothing and send ACK to VF
671e2a289a7SJiawen Wu 	 * if ret_param.retval > 1, do nothing and send NAK to VF
672e2a289a7SJiawen Wu 	 */
673e2a289a7SJiawen Wu 	rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_VF_MBOX,
674e2a289a7SJiawen Wu 				      &ret_param);
675e2a289a7SJiawen Wu 
676e2a289a7SJiawen Wu 	retval = ret_param.retval;
677e2a289a7SJiawen Wu 
678e2a289a7SJiawen Wu 	/* check & process VF to PF mailbox message */
679e2a289a7SJiawen Wu 	switch ((msgbuf[0] & 0xFFFF)) {
680e2a289a7SJiawen Wu 	case NGBE_VF_SET_MAC_ADDR:
681e2a289a7SJiawen Wu 		if (retval == NGBE_MB_EVENT_PROCEED)
682e2a289a7SJiawen Wu 			retval = ngbe_vf_set_mac_addr(eth_dev, vf, msgbuf);
683e2a289a7SJiawen Wu 		break;
684e2a289a7SJiawen Wu 	case NGBE_VF_SET_MULTICAST:
685e2a289a7SJiawen Wu 		if (retval == NGBE_MB_EVENT_PROCEED)
686e2a289a7SJiawen Wu 			retval = ngbe_vf_set_multicast(eth_dev, vf, msgbuf);
687e2a289a7SJiawen Wu 		break;
688e2a289a7SJiawen Wu 	case NGBE_VF_SET_LPE:
689e2a289a7SJiawen Wu 		if (retval == NGBE_MB_EVENT_PROCEED)
690e2a289a7SJiawen Wu 			retval = ngbe_set_vf_lpe(eth_dev, vf, msgbuf);
691e2a289a7SJiawen Wu 		break;
692e2a289a7SJiawen Wu 	case NGBE_VF_SET_VLAN:
693e2a289a7SJiawen Wu 		if (retval == NGBE_MB_EVENT_PROCEED)
694e2a289a7SJiawen Wu 			retval = ngbe_vf_set_vlan(eth_dev, vf, msgbuf);
695e2a289a7SJiawen Wu 		break;
696e2a289a7SJiawen Wu 	case NGBE_VF_API_NEGOTIATE:
697e2a289a7SJiawen Wu 		retval = ngbe_negotiate_vf_api(eth_dev, vf, msgbuf);
698e2a289a7SJiawen Wu 		break;
699e2a289a7SJiawen Wu 	case NGBE_VF_GET_QUEUES:
700e2a289a7SJiawen Wu 		retval = ngbe_get_vf_queues(eth_dev, vf, msgbuf);
701e2a289a7SJiawen Wu 		msg_size = NGBE_VF_GET_QUEUE_MSG_SIZE;
702e2a289a7SJiawen Wu 		break;
703e2a289a7SJiawen Wu 	case NGBE_VF_UPDATE_XCAST_MODE:
704e2a289a7SJiawen Wu 		if (retval == NGBE_MB_EVENT_PROCEED)
705e2a289a7SJiawen Wu 			retval = ngbe_set_vf_mc_promisc(eth_dev, vf, msgbuf);
706e2a289a7SJiawen Wu 		break;
707e2a289a7SJiawen Wu 	case NGBE_VF_SET_MACVLAN:
708e2a289a7SJiawen Wu 		if (retval == NGBE_MB_EVENT_PROCEED)
709e2a289a7SJiawen Wu 			retval = ngbe_set_vf_macvlan_msg(eth_dev, vf, msgbuf);
710e2a289a7SJiawen Wu 		break;
711e2a289a7SJiawen Wu 	default:
712e2a289a7SJiawen Wu 		PMD_DRV_LOG(DEBUG, "Unhandled Msg %8.8x", (uint32_t)msgbuf[0]);
713e2a289a7SJiawen Wu 		retval = NGBE_ERR_MBX;
714e2a289a7SJiawen Wu 		break;
715e2a289a7SJiawen Wu 	}
716e2a289a7SJiawen Wu 
717e2a289a7SJiawen Wu 	/* response the VF according to the message process result */
718e2a289a7SJiawen Wu 	if (retval)
719e2a289a7SJiawen Wu 		msgbuf[0] |= NGBE_VT_MSGTYPE_NACK;
720e2a289a7SJiawen Wu 	else
721e2a289a7SJiawen Wu 		msgbuf[0] |= NGBE_VT_MSGTYPE_ACK;
722e2a289a7SJiawen Wu 
723e2a289a7SJiawen Wu 	msgbuf[0] |= NGBE_VT_MSGTYPE_CTS;
724e2a289a7SJiawen Wu 
725e2a289a7SJiawen Wu 	ngbe_write_mbx(hw, msgbuf, msg_size, vf);
726e2a289a7SJiawen Wu 
727e2a289a7SJiawen Wu 	return retval;
728e2a289a7SJiawen Wu }
729e2a289a7SJiawen Wu 
730e2a289a7SJiawen Wu static inline void
731e2a289a7SJiawen Wu ngbe_rcv_ack_from_vf(struct rte_eth_dev *eth_dev, uint16_t vf)
732e2a289a7SJiawen Wu {
733e2a289a7SJiawen Wu 	uint32_t msg = NGBE_VT_MSGTYPE_NACK;
734e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
735e2a289a7SJiawen Wu 	struct ngbe_vf_info *vfinfo = *NGBE_DEV_VFDATA(eth_dev);
736e2a289a7SJiawen Wu 
737e2a289a7SJiawen Wu 	if (!vfinfo[vf].clear_to_send)
738e2a289a7SJiawen Wu 		ngbe_write_mbx(hw, &msg, 1, vf);
739e2a289a7SJiawen Wu }
740e2a289a7SJiawen Wu 
741e2a289a7SJiawen Wu void ngbe_pf_mbx_process(struct rte_eth_dev *eth_dev)
742e2a289a7SJiawen Wu {
743e2a289a7SJiawen Wu 	uint16_t vf;
744e2a289a7SJiawen Wu 	struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
745e2a289a7SJiawen Wu 
746e2a289a7SJiawen Wu 	for (vf = 0; vf < dev_num_vf(eth_dev); vf++) {
747e2a289a7SJiawen Wu 		/* check & process vf function level reset */
748e2a289a7SJiawen Wu 		if (!ngbe_check_for_rst(hw, vf))
749e2a289a7SJiawen Wu 			ngbe_vf_reset_event(eth_dev, vf);
750e2a289a7SJiawen Wu 
751e2a289a7SJiawen Wu 		/* check & process vf mailbox messages */
752e2a289a7SJiawen Wu 		if (!ngbe_check_for_msg(hw, vf))
753e2a289a7SJiawen Wu 			ngbe_rcv_msg_from_vf(eth_dev, vf);
754e2a289a7SJiawen Wu 
755e2a289a7SJiawen Wu 		/* check & process acks from vf */
756e2a289a7SJiawen Wu 		if (!ngbe_check_for_ack(hw, vf))
757e2a289a7SJiawen Wu 			ngbe_rcv_ack_from_vf(eth_dev, vf);
758e2a289a7SJiawen Wu 	}
759e2a289a7SJiawen Wu }
760