xref: /dpdk/drivers/net/enic/base/vnic_dev.c (revision 00ce43111dc5b364722c882cdd37d3664d87b6cc)
12e99ea80SHyong Youb Kim /* SPDX-License-Identifier: BSD-3-Clause
22e99ea80SHyong Youb Kim  * Copyright 2008-2017 Cisco Systems, Inc.  All rights reserved.
372f3de30SBruce Richardson  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
472f3de30SBruce Richardson  */
572f3de30SBruce Richardson 
672f3de30SBruce Richardson #include <rte_memzone.h>
772f3de30SBruce Richardson #include <rte_memcpy.h>
872f3de30SBruce Richardson #include <rte_string_fns.h>
9846ac76cSJohn Daley #include <rte_ether.h>
1072f3de30SBruce Richardson 
1172f3de30SBruce Richardson #include "vnic_dev.h"
1272f3de30SBruce Richardson #include "vnic_resource.h"
1372f3de30SBruce Richardson #include "vnic_devcmd.h"
149bd04182SJohn Daley #include "vnic_nic.h"
1572f3de30SBruce Richardson #include "vnic_stats.h"
16ea7768b5SHyong Youb Kim #include "vnic_flowman.h"
1772f3de30SBruce Richardson 
1872f3de30SBruce Richardson 
1972f3de30SBruce Richardson enum vnic_proxy_type {
2072f3de30SBruce Richardson 	PROXY_NONE,
2172f3de30SBruce Richardson 	PROXY_BY_BDF,
2272f3de30SBruce Richardson 	PROXY_BY_INDEX,
2372f3de30SBruce Richardson };
2472f3de30SBruce Richardson 
2572f3de30SBruce Richardson struct vnic_res {
2672f3de30SBruce Richardson 	void __iomem *vaddr;
2772f3de30SBruce Richardson 	dma_addr_t bus_addr;
2872f3de30SBruce Richardson 	unsigned int count;
2972f3de30SBruce Richardson };
3072f3de30SBruce Richardson 
3172f3de30SBruce Richardson struct vnic_intr_coal_timer_info {
3204e8ec74SJohn Daley 	uint32_t mul;
3304e8ec74SJohn Daley 	uint32_t div;
3404e8ec74SJohn Daley 	uint32_t max_usec;
3572f3de30SBruce Richardson };
3672f3de30SBruce Richardson 
3772f3de30SBruce Richardson struct vnic_dev {
3872f3de30SBruce Richardson 	void *priv;
3972f3de30SBruce Richardson 	struct rte_pci_device *pdev;
4072f3de30SBruce Richardson 	struct vnic_res res[RES_TYPE_MAX];
4172f3de30SBruce Richardson 	enum vnic_dev_intr_mode intr_mode;
4272f3de30SBruce Richardson 	struct vnic_devcmd __iomem *devcmd;
4372f3de30SBruce Richardson 	struct vnic_devcmd_notify *notify;
4472f3de30SBruce Richardson 	struct vnic_devcmd_notify notify_copy;
4572f3de30SBruce Richardson 	dma_addr_t notify_pa;
4604e8ec74SJohn Daley 	uint32_t notify_sz;
4772f3de30SBruce Richardson 	dma_addr_t linkstatus_pa;
4872f3de30SBruce Richardson 	struct vnic_stats *stats;
4972f3de30SBruce Richardson 	dma_addr_t stats_pa;
50*00ce4311SHyong Youb Kim 	struct vnic_sriov_stats *sriov_stats;
51*00ce4311SHyong Youb Kim 	dma_addr_t sriov_stats_pa;
5272f3de30SBruce Richardson 	struct vnic_devcmd_fw_info *fw_info;
5372f3de30SBruce Richardson 	dma_addr_t fw_info_pa;
54ea7768b5SHyong Youb Kim 	struct fm_info *flowman_info;
55ea7768b5SHyong Youb Kim 	dma_addr_t flowman_info_pa;
5672f3de30SBruce Richardson 	enum vnic_proxy_type proxy;
5704e8ec74SJohn Daley 	uint32_t proxy_index;
5804e8ec74SJohn Daley 	uint64_t args[VNIC_DEVCMD_NARGS];
5972f3de30SBruce Richardson 	int in_reset;
6072f3de30SBruce Richardson 	struct vnic_intr_coal_timer_info intr_coal_timer_info;
6172f3de30SBruce Richardson 	void *(*alloc_consistent)(void *priv, size_t size,
6204e8ec74SJohn Daley 		dma_addr_t *dma_handle, uint8_t *name);
63da5f560bSNelson Escobar 	void (*free_consistent)(void *priv,
6472f3de30SBruce Richardson 		size_t size, void *vaddr,
6572f3de30SBruce Richardson 		dma_addr_t dma_handle);
660e7312b9SHyong Youb Kim 	/*
670e7312b9SHyong Youb Kim 	 * Used to serialize devcmd access, currently from PF and its
680e7312b9SHyong Youb Kim 	 * VF representors. When there are no representors, lock is
690e7312b9SHyong Youb Kim 	 * not used.
700e7312b9SHyong Youb Kim 	 */
710e7312b9SHyong Youb Kim 	int locked;
720e7312b9SHyong Youb Kim 	void (*lock)(void *priv);
730e7312b9SHyong Youb Kim 	void (*unlock)(void *priv);
740e7312b9SHyong Youb Kim 	struct vnic_dev *pf_vdev;
750e7312b9SHyong Youb Kim 	int vf_id;
7672f3de30SBruce Richardson };
7772f3de30SBruce Richardson 
7872f3de30SBruce Richardson #define VNIC_MAX_RES_HDR_SIZE \
7972f3de30SBruce Richardson 	(sizeof(struct vnic_resource_header) + \
8072f3de30SBruce Richardson 	sizeof(struct vnic_resource) * RES_TYPE_MAX)
8172f3de30SBruce Richardson #define VNIC_RES_STRIDE	128
8272f3de30SBruce Richardson 
8372f3de30SBruce Richardson void *vnic_dev_priv(struct vnic_dev *vdev)
8472f3de30SBruce Richardson {
8572f3de30SBruce Richardson 	return vdev->priv;
8672f3de30SBruce Richardson }
8772f3de30SBruce Richardson 
8872f3de30SBruce Richardson void vnic_register_cbacks(struct vnic_dev *vdev,
8972f3de30SBruce Richardson 	void *(*alloc_consistent)(void *priv, size_t size,
9004e8ec74SJohn Daley 	    dma_addr_t *dma_handle, uint8_t *name),
91da5f560bSNelson Escobar 	void (*free_consistent)(void *priv,
9272f3de30SBruce Richardson 	    size_t size, void *vaddr,
9372f3de30SBruce Richardson 	    dma_addr_t dma_handle))
9472f3de30SBruce Richardson {
9572f3de30SBruce Richardson 	vdev->alloc_consistent = alloc_consistent;
9672f3de30SBruce Richardson 	vdev->free_consistent = free_consistent;
9772f3de30SBruce Richardson }
9872f3de30SBruce Richardson 
990e7312b9SHyong Youb Kim void vnic_register_lock(struct vnic_dev *vdev, void (*lock)(void *priv),
1000e7312b9SHyong Youb Kim 	void (*unlock)(void *priv))
1010e7312b9SHyong Youb Kim {
1020e7312b9SHyong Youb Kim 	vdev->lock = lock;
1030e7312b9SHyong Youb Kim 	vdev->unlock = unlock;
1040e7312b9SHyong Youb Kim 	vdev->locked = 0;
1050e7312b9SHyong Youb Kim }
1060e7312b9SHyong Youb Kim 
10772f3de30SBruce Richardson static int vnic_dev_discover_res(struct vnic_dev *vdev,
10872f3de30SBruce Richardson 	struct vnic_dev_bar *bar, unsigned int num_bars)
10972f3de30SBruce Richardson {
11072f3de30SBruce Richardson 	struct vnic_resource_header __iomem *rh;
11172f3de30SBruce Richardson 	struct mgmt_barmap_hdr __iomem *mrh;
11272f3de30SBruce Richardson 	struct vnic_resource __iomem *r;
11304e8ec74SJohn Daley 	uint8_t type;
11472f3de30SBruce Richardson 
11572f3de30SBruce Richardson 	if (num_bars == 0)
11672f3de30SBruce Richardson 		return -EINVAL;
11772f3de30SBruce Richardson 
11872f3de30SBruce Richardson 	if (bar->len < VNIC_MAX_RES_HDR_SIZE) {
11972f3de30SBruce Richardson 		pr_err("vNIC BAR0 res hdr length error\n");
12072f3de30SBruce Richardson 		return -EINVAL;
12172f3de30SBruce Richardson 	}
12272f3de30SBruce Richardson 
12372f3de30SBruce Richardson 	rh  = bar->vaddr;
12472f3de30SBruce Richardson 	mrh = bar->vaddr;
12572f3de30SBruce Richardson 	if (!rh) {
12672f3de30SBruce Richardson 		pr_err("vNIC BAR0 res hdr not mem-mapped\n");
12772f3de30SBruce Richardson 		return -EINVAL;
12872f3de30SBruce Richardson 	}
12972f3de30SBruce Richardson 
13072f3de30SBruce Richardson 	/* Check for mgmt vnic in addition to normal vnic */
13172f3de30SBruce Richardson 	if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) ||
13272f3de30SBruce Richardson 		(ioread32(&rh->version) != VNIC_RES_VERSION)) {
13372f3de30SBruce Richardson 		if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) ||
13472f3de30SBruce Richardson 			(ioread32(&mrh->version) != MGMTVNIC_VERSION)) {
13572f3de30SBruce Richardson 			pr_err("vNIC BAR0 res magic/version error " \
13672f3de30SBruce Richardson 				"exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n",
13772f3de30SBruce Richardson 				VNIC_RES_MAGIC, VNIC_RES_VERSION,
13872f3de30SBruce Richardson 				MGMTVNIC_MAGIC, MGMTVNIC_VERSION,
13972f3de30SBruce Richardson 				ioread32(&rh->magic), ioread32(&rh->version));
14072f3de30SBruce Richardson 			return -EINVAL;
14172f3de30SBruce Richardson 		}
14272f3de30SBruce Richardson 	}
14372f3de30SBruce Richardson 
14472f3de30SBruce Richardson 	if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC)
14572f3de30SBruce Richardson 		r = (struct vnic_resource __iomem *)(mrh + 1);
14672f3de30SBruce Richardson 	else
14772f3de30SBruce Richardson 		r = (struct vnic_resource __iomem *)(rh + 1);
14872f3de30SBruce Richardson 
14972f3de30SBruce Richardson 
15072f3de30SBruce Richardson 	while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
15104e8ec74SJohn Daley 		uint8_t bar_num = ioread8(&r->bar);
15204e8ec74SJohn Daley 		uint32_t bar_offset = ioread32(&r->bar_offset);
15304e8ec74SJohn Daley 		uint32_t count = ioread32(&r->count);
15404e8ec74SJohn Daley 		uint32_t len;
15572f3de30SBruce Richardson 
15672f3de30SBruce Richardson 		r++;
15772f3de30SBruce Richardson 
15872f3de30SBruce Richardson 		if (bar_num >= num_bars)
15972f3de30SBruce Richardson 			continue;
16072f3de30SBruce Richardson 
16172f3de30SBruce Richardson 		if (!bar[bar_num].len || !bar[bar_num].vaddr)
16272f3de30SBruce Richardson 			continue;
16372f3de30SBruce Richardson 
16472f3de30SBruce Richardson 		switch (type) {
16572f3de30SBruce Richardson 		case RES_TYPE_WQ:
16672f3de30SBruce Richardson 		case RES_TYPE_RQ:
16772f3de30SBruce Richardson 		case RES_TYPE_CQ:
16872f3de30SBruce Richardson 		case RES_TYPE_INTR_CTRL:
169*00ce4311SHyong Youb Kim 		case RES_TYPE_ADMIN_WQ:
170*00ce4311SHyong Youb Kim 		case RES_TYPE_ADMIN_RQ:
171*00ce4311SHyong Youb Kim 		case RES_TYPE_ADMIN_CQ:
17272f3de30SBruce Richardson 			/* each count is stride bytes long */
17372f3de30SBruce Richardson 			len = count * VNIC_RES_STRIDE;
17472f3de30SBruce Richardson 			if (len + bar_offset > bar[bar_num].len) {
17572f3de30SBruce Richardson 				pr_err("vNIC BAR0 resource %d " \
17672f3de30SBruce Richardson 					"out-of-bounds, offset 0x%x + " \
17772f3de30SBruce Richardson 					"size 0x%x > bar len 0x%lx\n",
17872f3de30SBruce Richardson 					type, bar_offset,
17972f3de30SBruce Richardson 					len,
18072f3de30SBruce Richardson 					bar[bar_num].len);
18172f3de30SBruce Richardson 				return -EINVAL;
18272f3de30SBruce Richardson 			}
18372f3de30SBruce Richardson 			break;
18472f3de30SBruce Richardson 		case RES_TYPE_INTR_PBA_LEGACY:
18572f3de30SBruce Richardson 		case RES_TYPE_DEVCMD:
18672f3de30SBruce Richardson 			len = count;
18772f3de30SBruce Richardson 			break;
18872f3de30SBruce Richardson 		default:
18972f3de30SBruce Richardson 			continue;
19072f3de30SBruce Richardson 		}
19172f3de30SBruce Richardson 
19272f3de30SBruce Richardson 		vdev->res[type].count = count;
19372f3de30SBruce Richardson 		vdev->res[type].vaddr = (char __iomem *)bar[bar_num].vaddr +
19472f3de30SBruce Richardson 		    bar_offset;
19572f3de30SBruce Richardson 		vdev->res[type].bus_addr = bar[bar_num].bus_addr + bar_offset;
19672f3de30SBruce Richardson 	}
19772f3de30SBruce Richardson 
19872f3de30SBruce Richardson 	return 0;
19972f3de30SBruce Richardson }
20072f3de30SBruce Richardson 
20172f3de30SBruce Richardson unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
20272f3de30SBruce Richardson 	enum vnic_res_type type)
20372f3de30SBruce Richardson {
20472f3de30SBruce Richardson 	return vdev->res[type].count;
20572f3de30SBruce Richardson }
20672f3de30SBruce Richardson 
20772f3de30SBruce Richardson void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
20872f3de30SBruce Richardson 	unsigned int index)
20972f3de30SBruce Richardson {
21072f3de30SBruce Richardson 	if (!vdev->res[type].vaddr)
21172f3de30SBruce Richardson 		return NULL;
21272f3de30SBruce Richardson 
21372f3de30SBruce Richardson 	switch (type) {
21472f3de30SBruce Richardson 	case RES_TYPE_WQ:
21572f3de30SBruce Richardson 	case RES_TYPE_RQ:
21672f3de30SBruce Richardson 	case RES_TYPE_CQ:
21772f3de30SBruce Richardson 	case RES_TYPE_INTR_CTRL:
218*00ce4311SHyong Youb Kim 	case RES_TYPE_ADMIN_WQ:
219*00ce4311SHyong Youb Kim 	case RES_TYPE_ADMIN_RQ:
220*00ce4311SHyong Youb Kim 	case RES_TYPE_ADMIN_CQ:
22172f3de30SBruce Richardson 		return (char __iomem *)vdev->res[type].vaddr +
22272f3de30SBruce Richardson 			index * VNIC_RES_STRIDE;
22372f3de30SBruce Richardson 	default:
22472f3de30SBruce Richardson 		return (char __iomem *)vdev->res[type].vaddr;
22572f3de30SBruce Richardson 	}
22672f3de30SBruce Richardson }
22772f3de30SBruce Richardson 
22872f3de30SBruce Richardson unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
22972f3de30SBruce Richardson 	unsigned int desc_count, unsigned int desc_size)
23072f3de30SBruce Richardson {
23172f3de30SBruce Richardson 	/* The base address of the desc rings must be 512 byte aligned.
23272f3de30SBruce Richardson 	 * Descriptor count is aligned to groups of 32 descriptors.  A
23372f3de30SBruce Richardson 	 * count of 0 means the maximum 4096 descriptors.  Descriptor
23472f3de30SBruce Richardson 	 * size is aligned to 16 bytes.
23572f3de30SBruce Richardson 	 */
23672f3de30SBruce Richardson 
23772f3de30SBruce Richardson 	unsigned int count_align = 32;
23872f3de30SBruce Richardson 	unsigned int desc_align = 16;
23972f3de30SBruce Richardson 
24072f3de30SBruce Richardson 	ring->base_align = 512;
24172f3de30SBruce Richardson 
24272f3de30SBruce Richardson 	if (desc_count == 0)
24372f3de30SBruce Richardson 		desc_count = 4096;
24472f3de30SBruce Richardson 
24572f3de30SBruce Richardson 	ring->desc_count = VNIC_ALIGN(desc_count, count_align);
24672f3de30SBruce Richardson 
24772f3de30SBruce Richardson 	ring->desc_size = VNIC_ALIGN(desc_size, desc_align);
24872f3de30SBruce Richardson 
24972f3de30SBruce Richardson 	ring->size = ring->desc_count * ring->desc_size;
25072f3de30SBruce Richardson 	ring->size_unaligned = ring->size + ring->base_align;
25172f3de30SBruce Richardson 
25272f3de30SBruce Richardson 	return ring->size_unaligned;
25372f3de30SBruce Richardson }
25472f3de30SBruce Richardson 
25572f3de30SBruce Richardson void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring)
25672f3de30SBruce Richardson {
25772f3de30SBruce Richardson 	memset(ring->descs, 0, ring->size);
25872f3de30SBruce Richardson }
25972f3de30SBruce Richardson 
260d1079807SNelson Escobar int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev,
26172f3de30SBruce Richardson 	struct vnic_dev_ring *ring,
262d1079807SNelson Escobar 	unsigned int desc_count, unsigned int desc_size,
263f2fc83b4SThomas Monjalon 	__rte_unused unsigned int socket_id,
26472f3de30SBruce Richardson 	char *z_name)
26572f3de30SBruce Richardson {
26661789822SAaron Conole 	void *alloc_addr;
267d1079807SNelson Escobar 	dma_addr_t alloc_pa = 0;
26872f3de30SBruce Richardson 
26972f3de30SBruce Richardson 	vnic_dev_desc_ring_size(ring, desc_count, desc_size);
270d1079807SNelson Escobar 	alloc_addr = vdev->alloc_consistent(vdev->priv,
271d1079807SNelson Escobar 					    ring->size_unaligned,
27204e8ec74SJohn Daley 					    &alloc_pa, (uint8_t *)z_name);
273d1079807SNelson Escobar 	if (!alloc_addr) {
27472f3de30SBruce Richardson 		pr_err("Failed to allocate ring (size=%d), aborting\n",
27572f3de30SBruce Richardson 			(int)ring->size);
27672f3de30SBruce Richardson 		return -ENOMEM;
27772f3de30SBruce Richardson 	}
278d1079807SNelson Escobar 	ring->descs_unaligned = alloc_addr;
279d1079807SNelson Escobar 	if (!alloc_pa) {
28072f3de30SBruce Richardson 		pr_err("Failed to map allocated ring (size=%d), aborting\n",
28172f3de30SBruce Richardson 			(int)ring->size);
282d1079807SNelson Escobar 		vdev->free_consistent(vdev->priv,
283d1079807SNelson Escobar 				      ring->size_unaligned,
284d1079807SNelson Escobar 				      alloc_addr,
285d1079807SNelson Escobar 				      alloc_pa);
28672f3de30SBruce Richardson 		return -ENOMEM;
28772f3de30SBruce Richardson 	}
288d1079807SNelson Escobar 	ring->base_addr_unaligned = alloc_pa;
28972f3de30SBruce Richardson 
29072f3de30SBruce Richardson 	ring->base_addr = VNIC_ALIGN(ring->base_addr_unaligned,
29172f3de30SBruce Richardson 		ring->base_align);
29204e8ec74SJohn Daley 	ring->descs = (uint8_t *)ring->descs_unaligned +
29372f3de30SBruce Richardson 	    (ring->base_addr - ring->base_addr_unaligned);
29472f3de30SBruce Richardson 
29572f3de30SBruce Richardson 	vnic_dev_clear_desc_ring(ring);
29672f3de30SBruce Richardson 
29772f3de30SBruce Richardson 	ring->desc_avail = ring->desc_count - 1;
29872f3de30SBruce Richardson 
29972f3de30SBruce Richardson 	return 0;
30072f3de30SBruce Richardson }
30172f3de30SBruce Richardson 
302f2fc83b4SThomas Monjalon void vnic_dev_free_desc_ring(__rte_unused  struct vnic_dev *vdev,
30372f3de30SBruce Richardson 	struct vnic_dev_ring *ring)
30472f3de30SBruce Richardson {
305d1079807SNelson Escobar 	if (ring->descs) {
306d1079807SNelson Escobar 		vdev->free_consistent(vdev->priv,
307d1079807SNelson Escobar 				      ring->size_unaligned,
308d1079807SNelson Escobar 				      ring->descs_unaligned,
309d1079807SNelson Escobar 				      ring->base_addr_unaligned);
31072f3de30SBruce Richardson 		ring->descs = NULL;
31172f3de30SBruce Richardson 	}
312d1079807SNelson Escobar }
31372f3de30SBruce Richardson 
31472f3de30SBruce Richardson static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
31572f3de30SBruce Richardson 	int wait)
31672f3de30SBruce Richardson {
31772f3de30SBruce Richardson 	struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
31872f3de30SBruce Richardson 	unsigned int i;
31972f3de30SBruce Richardson 	int delay;
32004e8ec74SJohn Daley 	uint32_t status;
32172f3de30SBruce Richardson 	int err;
32272f3de30SBruce Richardson 
32372f3de30SBruce Richardson 	status = ioread32(&devcmd->status);
32472f3de30SBruce Richardson 	if (status == 0xFFFFFFFF) {
32572f3de30SBruce Richardson 		/* PCI-e target device is gone */
32672f3de30SBruce Richardson 		return -ENODEV;
32772f3de30SBruce Richardson 	}
32872f3de30SBruce Richardson 	if (status & STAT_BUSY) {
32972f3de30SBruce Richardson 
33072f3de30SBruce Richardson 		pr_err("Busy devcmd %d\n",  _CMD_N(cmd));
33172f3de30SBruce Richardson 		return -EBUSY;
33272f3de30SBruce Richardson 	}
33372f3de30SBruce Richardson 
33472f3de30SBruce Richardson 	if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
33572f3de30SBruce Richardson 		for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
33672f3de30SBruce Richardson 			writeq(vdev->args[i], &devcmd->args[i]);
33704e8ec74SJohn Daley 		rte_wmb(); /* complete all writes initiated till now */
33872f3de30SBruce Richardson 	}
33972f3de30SBruce Richardson 
34072f3de30SBruce Richardson 	iowrite32(cmd, &devcmd->cmd);
34172f3de30SBruce Richardson 
34272f3de30SBruce Richardson 	if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
34372f3de30SBruce Richardson 		return 0;
34472f3de30SBruce Richardson 
34572f3de30SBruce Richardson 	for (delay = 0; delay < wait; delay++) {
34672f3de30SBruce Richardson 
34704e8ec74SJohn Daley 		usleep(100);
34872f3de30SBruce Richardson 
34972f3de30SBruce Richardson 		status = ioread32(&devcmd->status);
35072f3de30SBruce Richardson 		if (status == 0xFFFFFFFF) {
35172f3de30SBruce Richardson 			/* PCI-e target device is gone */
35272f3de30SBruce Richardson 			return -ENODEV;
35372f3de30SBruce Richardson 		}
35472f3de30SBruce Richardson 
35572f3de30SBruce Richardson 		if (!(status & STAT_BUSY)) {
35672f3de30SBruce Richardson 			if (status & STAT_ERROR) {
35772f3de30SBruce Richardson 				err = -(int)readq(&devcmd->args[0]);
3587e6be797SHyong Youb Kim 				if (cmd != CMD_CAPABILITY &&
3597e6be797SHyong Youb Kim 				    cmd != CMD_OVERLAY_OFFLOAD_CTRL &&
3607e6be797SHyong Youb Kim 				    cmd != CMD_GET_SUPP_FEATURE_VER)
36172f3de30SBruce Richardson 					pr_err("Devcmd %d failed " \
36272f3de30SBruce Richardson 						"with error code %d\n",
36372f3de30SBruce Richardson 						_CMD_N(cmd), err);
36472f3de30SBruce Richardson 				return err;
36572f3de30SBruce Richardson 			}
36672f3de30SBruce Richardson 
36772f3de30SBruce Richardson 			if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
36804e8ec74SJohn Daley 				rte_rmb();/* finish all reads */
36972f3de30SBruce Richardson 				for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
37072f3de30SBruce Richardson 					vdev->args[i] = readq(&devcmd->args[i]);
37172f3de30SBruce Richardson 			}
37272f3de30SBruce Richardson 
37372f3de30SBruce Richardson 			return 0;
37472f3de30SBruce Richardson 		}
37572f3de30SBruce Richardson 	}
37672f3de30SBruce Richardson 
37772f3de30SBruce Richardson 	pr_err("Timedout devcmd %d\n", _CMD_N(cmd));
37872f3de30SBruce Richardson 	return -ETIMEDOUT;
37972f3de30SBruce Richardson }
38072f3de30SBruce Richardson 
38172f3de30SBruce Richardson static int vnic_dev_cmd_proxy(struct vnic_dev *vdev,
38272f3de30SBruce Richardson 	enum vnic_devcmd_cmd proxy_cmd, enum vnic_devcmd_cmd cmd,
38304e8ec74SJohn Daley 	uint64_t *args, int nargs, int wait)
38472f3de30SBruce Richardson {
38504e8ec74SJohn Daley 	uint32_t status;
38672f3de30SBruce Richardson 	int err;
38772f3de30SBruce Richardson 
388322b355fSJohn Daley 	/*
389322b355fSJohn Daley 	 * Proxy command consumes 2 arguments. One for proxy index,
390322b355fSJohn Daley 	 * the other is for command to be proxied
391322b355fSJohn Daley 	 */
392322b355fSJohn Daley 	if (nargs > VNIC_DEVCMD_NARGS - 2) {
393322b355fSJohn Daley 		pr_err("number of args %d exceeds the maximum\n", nargs);
394322b355fSJohn Daley 		return -EINVAL;
395322b355fSJohn Daley 	}
39672f3de30SBruce Richardson 	memset(vdev->args, 0, sizeof(vdev->args));
39772f3de30SBruce Richardson 
39872f3de30SBruce Richardson 	vdev->args[0] = vdev->proxy_index;
39972f3de30SBruce Richardson 	vdev->args[1] = cmd;
400322b355fSJohn Daley 	memcpy(&vdev->args[2], args, nargs * sizeof(args[0]));
40172f3de30SBruce Richardson 
40272f3de30SBruce Richardson 	err = _vnic_dev_cmd(vdev, proxy_cmd, wait);
40372f3de30SBruce Richardson 	if (err)
40472f3de30SBruce Richardson 		return err;
40572f3de30SBruce Richardson 
40604e8ec74SJohn Daley 	status = (uint32_t)vdev->args[0];
40772f3de30SBruce Richardson 	if (status & STAT_ERROR) {
40872f3de30SBruce Richardson 		err = (int)vdev->args[1];
40972f3de30SBruce Richardson 		if (err != ERR_ECMDUNKNOWN ||
41072f3de30SBruce Richardson 		    cmd != CMD_CAPABILITY)
41172f3de30SBruce Richardson 			pr_err("Error %d proxy devcmd %d\n", err, _CMD_N(cmd));
41272f3de30SBruce Richardson 		return err;
41372f3de30SBruce Richardson 	}
41472f3de30SBruce Richardson 
415322b355fSJohn Daley 	memcpy(args, &vdev->args[1], nargs * sizeof(args[0]));
41672f3de30SBruce Richardson 
41772f3de30SBruce Richardson 	return 0;
41872f3de30SBruce Richardson }
41972f3de30SBruce Richardson 
42072f3de30SBruce Richardson static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
42104e8ec74SJohn Daley 	enum vnic_devcmd_cmd cmd, uint64_t *args, int nargs, int wait)
42272f3de30SBruce Richardson {
42372f3de30SBruce Richardson 	int err;
42472f3de30SBruce Richardson 
425322b355fSJohn Daley 	if (nargs > VNIC_DEVCMD_NARGS) {
426322b355fSJohn Daley 		pr_err("number of args %d exceeds the maximum\n", nargs);
427322b355fSJohn Daley 		return -EINVAL;
428322b355fSJohn Daley 	}
429322b355fSJohn Daley 	memset(vdev->args, 0, sizeof(vdev->args));
430322b355fSJohn Daley 	memcpy(vdev->args, args, nargs * sizeof(args[0]));
43172f3de30SBruce Richardson 
43272f3de30SBruce Richardson 	err = _vnic_dev_cmd(vdev, cmd, wait);
43372f3de30SBruce Richardson 
434322b355fSJohn Daley 	memcpy(args, vdev->args, nargs * sizeof(args[0]));
43572f3de30SBruce Richardson 
43672f3de30SBruce Richardson 	return err;
43772f3de30SBruce Richardson }
43872f3de30SBruce Richardson 
4390e7312b9SHyong Youb Kim void vnic_dev_cmd_proxy_by_index_start(struct vnic_dev *vdev, uint16_t index)
4400e7312b9SHyong Youb Kim {
4410e7312b9SHyong Youb Kim 	vdev->proxy = PROXY_BY_INDEX;
4420e7312b9SHyong Youb Kim 	vdev->proxy_index = index;
4430e7312b9SHyong Youb Kim }
4440e7312b9SHyong Youb Kim 
4450e7312b9SHyong Youb Kim void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev)
4460e7312b9SHyong Youb Kim {
4470e7312b9SHyong Youb Kim 	vdev->proxy = PROXY_NONE;
4480e7312b9SHyong Youb Kim 	vdev->proxy_index = 0;
4490e7312b9SHyong Youb Kim }
4500e7312b9SHyong Youb Kim 
45172f3de30SBruce Richardson int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
45204e8ec74SJohn Daley 	uint64_t *a0, uint64_t *a1, int wait)
45372f3de30SBruce Richardson {
45404e8ec74SJohn Daley 	uint64_t args[2];
4550e7312b9SHyong Youb Kim 	bool vf_rep;
4560e7312b9SHyong Youb Kim 	int vf_idx;
457322b355fSJohn Daley 	int err;
458322b355fSJohn Daley 
4590e7312b9SHyong Youb Kim 	vf_rep = false;
4600e7312b9SHyong Youb Kim 	if (vdev->pf_vdev) {
4610e7312b9SHyong Youb Kim 		vf_rep = true;
4620e7312b9SHyong Youb Kim 		vf_idx = vdev->vf_id;
4630e7312b9SHyong Youb Kim 		/* Everything below assumes PF vdev */
4640e7312b9SHyong Youb Kim 		vdev = vdev->pf_vdev;
4650e7312b9SHyong Youb Kim 	}
4660e7312b9SHyong Youb Kim 	if (vdev->lock)
4670e7312b9SHyong Youb Kim 		vdev->lock(vdev->priv);
4680e7312b9SHyong Youb Kim 	/* For VF representor, proxy devcmd to VF index */
4690e7312b9SHyong Youb Kim 	if (vf_rep)
4700e7312b9SHyong Youb Kim 		vnic_dev_cmd_proxy_by_index_start(vdev, vf_idx);
4710e7312b9SHyong Youb Kim 
472322b355fSJohn Daley 	args[0] = *a0;
473322b355fSJohn Daley 	args[1] = *a1;
47472f3de30SBruce Richardson 	memset(vdev->args, 0, sizeof(vdev->args));
47572f3de30SBruce Richardson 
47672f3de30SBruce Richardson 	switch (vdev->proxy) {
47772f3de30SBruce Richardson 	case PROXY_BY_INDEX:
478322b355fSJohn Daley 		err =  vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_INDEX, cmd,
479322b355fSJohn Daley 				args, ARRAY_SIZE(args), wait);
480322b355fSJohn Daley 		break;
48172f3de30SBruce Richardson 	case PROXY_BY_BDF:
482322b355fSJohn Daley 		err =  vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_BDF, cmd,
483322b355fSJohn Daley 				args, ARRAY_SIZE(args), wait);
484322b355fSJohn Daley 		break;
48572f3de30SBruce Richardson 	case PROXY_NONE:
48672f3de30SBruce Richardson 	default:
487322b355fSJohn Daley 		err = vnic_dev_cmd_no_proxy(vdev, cmd, args, 2, wait);
488322b355fSJohn Daley 		break;
48972f3de30SBruce Richardson 	}
490322b355fSJohn Daley 
4910e7312b9SHyong Youb Kim 	if (vf_rep)
4920e7312b9SHyong Youb Kim 		vnic_dev_cmd_proxy_end(vdev);
4930e7312b9SHyong Youb Kim 	if (vdev->unlock)
4940e7312b9SHyong Youb Kim 		vdev->unlock(vdev->priv);
495322b355fSJohn Daley 	if (err == 0) {
496322b355fSJohn Daley 		*a0 = args[0];
497322b355fSJohn Daley 		*a1 = args[1];
498322b355fSJohn Daley 	}
499322b355fSJohn Daley 
500322b355fSJohn Daley 	return err;
501322b355fSJohn Daley }
502322b355fSJohn Daley 
503322b355fSJohn Daley int vnic_dev_cmd_args(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
50404e8ec74SJohn Daley 		      uint64_t *args, int nargs, int wait)
505322b355fSJohn Daley {
5060e7312b9SHyong Youb Kim 	bool vf_rep;
5070e7312b9SHyong Youb Kim 	int vf_idx;
5080e7312b9SHyong Youb Kim 	int err;
5090e7312b9SHyong Youb Kim 
5100e7312b9SHyong Youb Kim 	vf_rep = false;
5110e7312b9SHyong Youb Kim 	if (vdev->pf_vdev) {
5120e7312b9SHyong Youb Kim 		vf_rep = true;
5130e7312b9SHyong Youb Kim 		vf_idx = vdev->vf_id;
5140e7312b9SHyong Youb Kim 		vdev = vdev->pf_vdev;
5150e7312b9SHyong Youb Kim 	}
5160e7312b9SHyong Youb Kim 	if (vdev->lock)
5170e7312b9SHyong Youb Kim 		vdev->lock(vdev->priv);
5180e7312b9SHyong Youb Kim 	if (vf_rep)
5190e7312b9SHyong Youb Kim 		vnic_dev_cmd_proxy_by_index_start(vdev, vf_idx);
5200e7312b9SHyong Youb Kim 
521322b355fSJohn Daley 	switch (vdev->proxy) {
522322b355fSJohn Daley 	case PROXY_BY_INDEX:
5230e7312b9SHyong Youb Kim 		err = vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_INDEX, cmd,
524322b355fSJohn Daley 				args, nargs, wait);
5250e7312b9SHyong Youb Kim 		break;
526322b355fSJohn Daley 	case PROXY_BY_BDF:
5270e7312b9SHyong Youb Kim 		err = vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_BDF, cmd,
528322b355fSJohn Daley 				args, nargs, wait);
5290e7312b9SHyong Youb Kim 		break;
530322b355fSJohn Daley 	case PROXY_NONE:
531322b355fSJohn Daley 	default:
5320e7312b9SHyong Youb Kim 		err = vnic_dev_cmd_no_proxy(vdev, cmd, args, nargs, wait);
5330e7312b9SHyong Youb Kim 		break;
534322b355fSJohn Daley 	}
5350e7312b9SHyong Youb Kim 
5360e7312b9SHyong Youb Kim 	if (vf_rep)
5370e7312b9SHyong Youb Kim 		vnic_dev_cmd_proxy_end(vdev);
5380e7312b9SHyong Youb Kim 	if (vdev->unlock)
5390e7312b9SHyong Youb Kim 		vdev->unlock(vdev->priv);
5400e7312b9SHyong Youb Kim 	return err;
541322b355fSJohn Daley }
542322b355fSJohn Daley 
54329343067SHyong Youb Kim int vnic_dev_fw_info(struct vnic_dev *vdev,
54429343067SHyong Youb Kim 		     struct vnic_devcmd_fw_info **fw_info)
54529343067SHyong Youb Kim {
546846ac76cSJohn Daley 	char name[RTE_MEMZONE_NAMESIZE];
54704e8ec74SJohn Daley 	uint64_t a0, a1 = 0;
54829343067SHyong Youb Kim 	int wait = 1000;
54929343067SHyong Youb Kim 	int err = 0;
55004e8ec74SJohn Daley 	static uint32_t instance;
55129343067SHyong Youb Kim 
55229343067SHyong Youb Kim 	if (!vdev->fw_info) {
55329343067SHyong Youb Kim 		snprintf((char *)name, sizeof(name), "vnic_fw_info-%u",
55429343067SHyong Youb Kim 			 instance++);
55529343067SHyong Youb Kim 		vdev->fw_info = vdev->alloc_consistent(vdev->priv,
55629343067SHyong Youb Kim 			sizeof(struct vnic_devcmd_fw_info),
55704e8ec74SJohn Daley 			&vdev->fw_info_pa, (uint8_t *)name);
55829343067SHyong Youb Kim 		if (!vdev->fw_info)
55929343067SHyong Youb Kim 			return -ENOMEM;
56029343067SHyong Youb Kim 		a0 = vdev->fw_info_pa;
56129343067SHyong Youb Kim 		a1 = sizeof(struct vnic_devcmd_fw_info);
56229343067SHyong Youb Kim 		err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO,
56329343067SHyong Youb Kim 				   &a0, &a1, wait);
56429343067SHyong Youb Kim 	}
56529343067SHyong Youb Kim 	*fw_info = vdev->fw_info;
56629343067SHyong Youb Kim 	return err;
56729343067SHyong Youb Kim }
56829343067SHyong Youb Kim 
56904e8ec74SJohn Daley static int vnic_dev_advanced_filters_cap(struct vnic_dev *vdev, uint64_t *args,
570322b355fSJohn Daley 		int nargs)
571322b355fSJohn Daley {
572322b355fSJohn Daley 	memset(args, 0, nargs * sizeof(*args));
573322b355fSJohn Daley 	args[0] = CMD_ADD_ADV_FILTER;
574322b355fSJohn Daley 	args[1] = FILTER_CAP_MODE_V1_FLAG;
575322b355fSJohn Daley 	return vnic_dev_cmd_args(vdev, CMD_CAPABILITY, args, nargs, 1000);
57672f3de30SBruce Richardson }
57772f3de30SBruce Richardson 
578dfbd6a9cSJohn Daley int vnic_dev_capable_adv_filters(struct vnic_dev *vdev)
579dfbd6a9cSJohn Daley {
58004e8ec74SJohn Daley 	uint64_t a0 = CMD_ADD_ADV_FILTER, a1 = 0;
581dfbd6a9cSJohn Daley 	int wait = 1000;
582dfbd6a9cSJohn Daley 	int err;
583dfbd6a9cSJohn Daley 
584dfbd6a9cSJohn Daley 	err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
585dfbd6a9cSJohn Daley 	if (err)
586dfbd6a9cSJohn Daley 		return 0;
58704e8ec74SJohn Daley 	return (a1 >= (uint32_t)FILTER_DPDK_1);
588dfbd6a9cSJohn Daley }
589dfbd6a9cSJohn Daley 
59004e8ec74SJohn Daley int vnic_dev_flowman_cmd(struct vnic_dev *vdev, uint64_t *args, int nargs)
591ea7768b5SHyong Youb Kim {
592ea7768b5SHyong Youb Kim 	int wait = 1000;
593ea7768b5SHyong Youb Kim 
594ea7768b5SHyong Youb Kim 	return vnic_dev_cmd_args(vdev, CMD_FLOW_MANAGER_OP, args, nargs, wait);
595ea7768b5SHyong Youb Kim }
596ea7768b5SHyong Youb Kim 
59704e8ec74SJohn Daley static int vnic_dev_flowman_enable(struct vnic_dev *vdev, uint32_t *mode,
59804e8ec74SJohn Daley 				   uint8_t *filter_actions)
599ea7768b5SHyong Youb Kim {
600846ac76cSJohn Daley 	char name[RTE_MEMZONE_NAMESIZE];
60104e8ec74SJohn Daley 	uint64_t args[3];
60204e8ec74SJohn Daley 	uint64_t ops;
60304e8ec74SJohn Daley 	static uint32_t instance;
604ea7768b5SHyong Youb Kim 
605af397b3cSHyong Youb Kim 	/* Advanced filtering is a prerequisite */
606af397b3cSHyong Youb Kim 	if (!vnic_dev_capable_adv_filters(vdev))
607af397b3cSHyong Youb Kim 		return 0;
608ea7768b5SHyong Youb Kim 	/* flowman devcmd available? */
609ea7768b5SHyong Youb Kim 	if (!vnic_dev_capable(vdev, CMD_FLOW_MANAGER_OP))
610ea7768b5SHyong Youb Kim 		return 0;
611ea7768b5SHyong Youb Kim 	/* Have the version we are using? */
612ea7768b5SHyong Youb Kim 	args[0] = FM_API_VERSION_QUERY;
613ea7768b5SHyong Youb Kim 	if (vnic_dev_flowman_cmd(vdev, args, 1))
614ea7768b5SHyong Youb Kim 		return 0;
615ea7768b5SHyong Youb Kim 	if ((args[0] & (1ULL << FM_VERSION)) == 0)
616ea7768b5SHyong Youb Kim 		return 0;
617ea7768b5SHyong Youb Kim 	/* Select the version */
618ea7768b5SHyong Youb Kim 	args[0] = FM_API_VERSION_SELECT;
619ea7768b5SHyong Youb Kim 	args[1] = FM_VERSION;
620ea7768b5SHyong Youb Kim 	if (vnic_dev_flowman_cmd(vdev, args, 2))
621ea7768b5SHyong Youb Kim 		return 0;
622ea7768b5SHyong Youb Kim 	/* Can we get fm_info? */
623ea7768b5SHyong Youb Kim 	if (!vdev->flowman_info) {
624846ac76cSJohn Daley 		snprintf((char *)name, sizeof(name), "vnic_fm_info-%u",
625ea7768b5SHyong Youb Kim 			 instance++);
626ea7768b5SHyong Youb Kim 		vdev->flowman_info = vdev->alloc_consistent(vdev->priv,
627ea7768b5SHyong Youb Kim 			sizeof(struct fm_info),
62804e8ec74SJohn Daley 			&vdev->flowman_info_pa, (uint8_t *)name);
629ea7768b5SHyong Youb Kim 		if (!vdev->flowman_info)
630ea7768b5SHyong Youb Kim 			return 0;
631ea7768b5SHyong Youb Kim 	}
632ea7768b5SHyong Youb Kim 	args[0] = FM_INFO_QUERY;
633ea7768b5SHyong Youb Kim 	args[1] = vdev->flowman_info_pa;
634ea7768b5SHyong Youb Kim 	args[2] = sizeof(struct fm_info);
635ea7768b5SHyong Youb Kim 	if (vnic_dev_flowman_cmd(vdev, args, 3))
636ea7768b5SHyong Youb Kim 		return 0;
637ea7768b5SHyong Youb Kim 	/* Have required operations? */
638ea7768b5SHyong Youb Kim 	ops = (1ULL << FMOP_END) |
639ea7768b5SHyong Youb Kim 		(1ULL << FMOP_DROP) |
640ea7768b5SHyong Youb Kim 		(1ULL << FMOP_RQ_STEER) |
641ea7768b5SHyong Youb Kim 		(1ULL << FMOP_EXACT_MATCH) |
642ea7768b5SHyong Youb Kim 		(1ULL << FMOP_MARK) |
643ea7768b5SHyong Youb Kim 		(1ULL << FMOP_TAG) |
644ea7768b5SHyong Youb Kim 		(1ULL << FMOP_EG_HAIRPIN) |
645ea7768b5SHyong Youb Kim 		(1ULL << FMOP_ENCAP) |
646ea7768b5SHyong Youb Kim 		(1ULL << FMOP_DECAP_NOSTRIP);
647ea7768b5SHyong Youb Kim 	if ((vdev->flowman_info->fm_op_mask & ops) != ops)
648ea7768b5SHyong Youb Kim 		return 0;
649ea7768b5SHyong Youb Kim 	/* Good to use flowman now */
650ea7768b5SHyong Youb Kim 	*mode = FILTER_FLOWMAN;
651ea7768b5SHyong Youb Kim 	*filter_actions = FILTER_ACTION_RQ_STEERING_FLAG |
652ea7768b5SHyong Youb Kim 		FILTER_ACTION_FILTER_ID_FLAG |
653ea7768b5SHyong Youb Kim 		FILTER_ACTION_COUNTER_FLAG |
654ea7768b5SHyong Youb Kim 		FILTER_ACTION_DROP_FLAG;
655ea7768b5SHyong Youb Kim 	return 1;
656ea7768b5SHyong Youb Kim }
657ea7768b5SHyong Youb Kim 
658fb927454SHyong Youb Kim /*  Determine the "best" filtering mode VIC is capable of. Returns one of 4
659fb927454SHyong Youb Kim  *  value or 0 if filtering is unavailble:
660ea7768b5SHyong Youb Kim  *	FILTER_FLOWMAN- flowman api capable
661322b355fSJohn Daley  *	FILTER_DPDK_1- advanced filters availabile
662322b355fSJohn Daley  *	FILTER_USNIC_IP_FLAG - advanced filters but with the restriction that
663322b355fSJohn Daley  *		the IP layer must explicitly specified. I.e. cannot have a UDP
664322b355fSJohn Daley  *		filter that matches both IPv4 and IPv6.
665322b355fSJohn Daley  *	FILTER_IPV4_5TUPLE - fallback if either of the 2 above aren't available.
666322b355fSJohn Daley  *		all other filter types are not available.
667322b355fSJohn Daley  *   Retrun true in filter_tags if supported
668322b355fSJohn Daley  */
66904e8ec74SJohn Daley int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, uint32_t *mode,
67004e8ec74SJohn Daley 				 uint8_t *filter_actions)
671322b355fSJohn Daley {
67204e8ec74SJohn Daley 	uint64_t args[4];
673322b355fSJohn Daley 	int err;
67404e8ec74SJohn Daley 	uint32_t max_level = 0;
675322b355fSJohn Daley 
676ea7768b5SHyong Youb Kim 	/* If flowman is available, use it as it is the most capable API */
677ea7768b5SHyong Youb Kim 	if (vnic_dev_flowman_enable(vdev, mode, filter_actions))
678ea7768b5SHyong Youb Kim 		return 0;
679ea7768b5SHyong Youb Kim 
680322b355fSJohn Daley 	err = vnic_dev_advanced_filters_cap(vdev, args, 4);
681322b355fSJohn Daley 
682036c545dSHyong Youb Kim 	/* determine supported filter actions */
683036c545dSHyong Youb Kim 	*filter_actions = FILTER_ACTION_RQ_STEERING_FLAG; /* always available */
684036c545dSHyong Youb Kim 	if (args[2] == FILTER_CAP_MODE_V1)
685036c545dSHyong Youb Kim 		*filter_actions = args[3];
686322b355fSJohn Daley 
687322b355fSJohn Daley 	if (err || ((args[0] == 1) && (args[1] == 0))) {
688322b355fSJohn Daley 		/* Adv filter Command not supported or adv filters available but
689322b355fSJohn Daley 		 * not enabled. Try the normal filter capability command.
690322b355fSJohn Daley 		 */
691322b355fSJohn Daley 		args[0] = CMD_ADD_FILTER;
692322b355fSJohn Daley 		args[1] = 0;
693322b355fSJohn Daley 		err = vnic_dev_cmd_args(vdev, CMD_CAPABILITY, args, 2, 1000);
694fb927454SHyong Youb Kim 		/*
695fb927454SHyong Youb Kim 		 * ERR_EPERM may be returned if, for example, vNIC is
696fb927454SHyong Youb Kim 		 * on a VF. It simply means no filtering is available
697fb927454SHyong Youb Kim 		 */
698fb927454SHyong Youb Kim 		if (err == -ERR_EPERM) {
699fb927454SHyong Youb Kim 			*mode = 0;
700fb927454SHyong Youb Kim 			return 0;
701fb927454SHyong Youb Kim 		}
702322b355fSJohn Daley 		if (err)
703322b355fSJohn Daley 			return err;
704322b355fSJohn Daley 		max_level = args[1];
705322b355fSJohn Daley 		goto parse_max_level;
706322b355fSJohn Daley 	} else if (args[2] == FILTER_CAP_MODE_V1) {
707322b355fSJohn Daley 		/* parse filter capability mask in args[1] */
708322b355fSJohn Daley 		if (args[1] & FILTER_DPDK_1_FLAG)
709322b355fSJohn Daley 			*mode = FILTER_DPDK_1;
710322b355fSJohn Daley 		else if (args[1] & FILTER_USNIC_IP_FLAG)
711322b355fSJohn Daley 			*mode = FILTER_USNIC_IP;
712322b355fSJohn Daley 		else if (args[1] & FILTER_IPV4_5TUPLE_FLAG)
713322b355fSJohn Daley 			*mode = FILTER_IPV4_5TUPLE;
714322b355fSJohn Daley 		return 0;
715322b355fSJohn Daley 	}
716322b355fSJohn Daley 	max_level = args[1];
717322b355fSJohn Daley parse_max_level:
71804e8ec74SJohn Daley 	if (max_level >= (uint32_t)FILTER_USNIC_IP)
719322b355fSJohn Daley 		*mode = FILTER_USNIC_IP;
720322b355fSJohn Daley 	else
721322b355fSJohn Daley 		*mode = FILTER_IPV4_5TUPLE;
722322b355fSJohn Daley 	return 0;
723322b355fSJohn Daley }
724322b355fSJohn Daley 
7255bc989e6SHyong Youb Kim void vnic_dev_capable_udp_rss_weak(struct vnic_dev *vdev, bool *cfg_chk,
7265bc989e6SHyong Youb Kim 				   bool *weak)
7275bc989e6SHyong Youb Kim {
72804e8ec74SJohn Daley 	uint64_t a0 = CMD_NIC_CFG, a1 = 0;
7295bc989e6SHyong Youb Kim 	int wait = 1000;
7305bc989e6SHyong Youb Kim 	int err;
7315bc989e6SHyong Youb Kim 
7325bc989e6SHyong Youb Kim 	*cfg_chk = false;
7335bc989e6SHyong Youb Kim 	*weak = false;
7345bc989e6SHyong Youb Kim 	err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
7355bc989e6SHyong Youb Kim 	if (err == 0 && a0 != 0 && a1 != 0) {
7365bc989e6SHyong Youb Kim 		*cfg_chk = true;
7375bc989e6SHyong Youb Kim 		*weak = !!((a1 >> 32) & CMD_NIC_CFG_CAPF_UDP_WEAK);
7385bc989e6SHyong Youb Kim 	}
7395bc989e6SHyong Youb Kim }
7405bc989e6SHyong Youb Kim 
741322b355fSJohn Daley int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
74272f3de30SBruce Richardson {
74304e8ec74SJohn Daley 	uint64_t a0 = (uint32_t)cmd, a1 = 0;
74472f3de30SBruce Richardson 	int wait = 1000;
74572f3de30SBruce Richardson 	int err;
74672f3de30SBruce Richardson 
74772f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
74872f3de30SBruce Richardson 
74972f3de30SBruce Richardson 	return !(err || a0);
75072f3de30SBruce Richardson }
75172f3de30SBruce Richardson 
75272f3de30SBruce Richardson int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, size_t size,
75372f3de30SBruce Richardson 	void *value)
75472f3de30SBruce Richardson {
75504e8ec74SJohn Daley 	uint64_t a0, a1;
75672f3de30SBruce Richardson 	int wait = 1000;
75772f3de30SBruce Richardson 	int err;
75872f3de30SBruce Richardson 
75972f3de30SBruce Richardson 	a0 = offset;
76072f3de30SBruce Richardson 	a1 = size;
76172f3de30SBruce Richardson 
76272f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait);
76372f3de30SBruce Richardson 
76472f3de30SBruce Richardson 	switch (size) {
76572f3de30SBruce Richardson 	case 1:
76604e8ec74SJohn Daley 		*(uint8_t *)value = (uint8_t)a0;
76772f3de30SBruce Richardson 		break;
76872f3de30SBruce Richardson 	case 2:
76904e8ec74SJohn Daley 		*(uint16_t *)value = (uint16_t)a0;
77072f3de30SBruce Richardson 		break;
77172f3de30SBruce Richardson 	case 4:
77204e8ec74SJohn Daley 		*(uint32_t *)value = (uint32_t)a0;
77372f3de30SBruce Richardson 		break;
77472f3de30SBruce Richardson 	case 8:
77504e8ec74SJohn Daley 		*(uint64_t *)value = a0;
77672f3de30SBruce Richardson 		break;
77772f3de30SBruce Richardson 	default:
77872f3de30SBruce Richardson 		BUG();
77972f3de30SBruce Richardson 		break;
78072f3de30SBruce Richardson 	}
78172f3de30SBruce Richardson 
78272f3de30SBruce Richardson 	return err;
78372f3de30SBruce Richardson }
78472f3de30SBruce Richardson 
78572f3de30SBruce Richardson int vnic_dev_stats_clear(struct vnic_dev *vdev)
78672f3de30SBruce Richardson {
78704e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
78872f3de30SBruce Richardson 	int wait = 1000;
78972f3de30SBruce Richardson 
79072f3de30SBruce Richardson 	return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait);
79172f3de30SBruce Richardson }
79272f3de30SBruce Richardson 
79372f3de30SBruce Richardson int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
79472f3de30SBruce Richardson {
79504e8ec74SJohn Daley 	uint64_t a0, a1;
79672f3de30SBruce Richardson 	int wait = 1000;
79772f3de30SBruce Richardson 
79872f3de30SBruce Richardson 	if (!vdev->stats)
79972f3de30SBruce Richardson 		return -ENOMEM;
80072f3de30SBruce Richardson 
80172f3de30SBruce Richardson 	*stats = vdev->stats;
80272f3de30SBruce Richardson 	a0 = vdev->stats_pa;
80372f3de30SBruce Richardson 	a1 = sizeof(struct vnic_stats);
80472f3de30SBruce Richardson 
80572f3de30SBruce Richardson 	return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
80672f3de30SBruce Richardson }
80772f3de30SBruce Richardson 
80872f3de30SBruce Richardson int vnic_dev_close(struct vnic_dev *vdev)
80972f3de30SBruce Richardson {
81004e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
81172f3de30SBruce Richardson 	int wait = 1000;
81272f3de30SBruce Richardson 
81372f3de30SBruce Richardson 	return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
81472f3de30SBruce Richardson }
81572f3de30SBruce Richardson 
81672f3de30SBruce Richardson int vnic_dev_enable_wait(struct vnic_dev *vdev)
81772f3de30SBruce Richardson {
81804e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
81972f3de30SBruce Richardson 	int wait = 1000;
82072f3de30SBruce Richardson 
82172f3de30SBruce Richardson 	if (vnic_dev_capable(vdev, CMD_ENABLE_WAIT))
82272f3de30SBruce Richardson 		return vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
82372f3de30SBruce Richardson 	else
82472f3de30SBruce Richardson 		return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
82572f3de30SBruce Richardson }
82672f3de30SBruce Richardson 
82772f3de30SBruce Richardson int vnic_dev_disable(struct vnic_dev *vdev)
82872f3de30SBruce Richardson {
82904e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
83072f3de30SBruce Richardson 	int wait = 1000;
83172f3de30SBruce Richardson 
83272f3de30SBruce Richardson 	return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait);
83372f3de30SBruce Richardson }
83472f3de30SBruce Richardson 
83572f3de30SBruce Richardson int vnic_dev_open(struct vnic_dev *vdev, int arg)
83672f3de30SBruce Richardson {
83704e8ec74SJohn Daley 	uint64_t a0 = (uint32_t)arg, a1 = 0;
83872f3de30SBruce Richardson 	int wait = 1000;
83972f3de30SBruce Richardson 
84072f3de30SBruce Richardson 	return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait);
84172f3de30SBruce Richardson }
84272f3de30SBruce Richardson 
84372f3de30SBruce Richardson int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
84472f3de30SBruce Richardson {
84504e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
84672f3de30SBruce Richardson 	int wait = 1000;
84772f3de30SBruce Richardson 	int err;
84872f3de30SBruce Richardson 
84972f3de30SBruce Richardson 	*done = 0;
85072f3de30SBruce Richardson 
85172f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
85272f3de30SBruce Richardson 	if (err)
85372f3de30SBruce Richardson 		return err;
85472f3de30SBruce Richardson 
85572f3de30SBruce Richardson 	*done = (a0 == 0);
85672f3de30SBruce Richardson 
85772f3de30SBruce Richardson 	return 0;
85872f3de30SBruce Richardson }
85972f3de30SBruce Richardson 
86004e8ec74SJohn Daley int vnic_dev_get_mac_addr(struct vnic_dev *vdev, uint8_t *mac_addr)
86172f3de30SBruce Richardson {
86204e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
86372f3de30SBruce Richardson 	int wait = 1000;
86472f3de30SBruce Richardson 	int err, i;
86572f3de30SBruce Richardson 
866846ac76cSJohn Daley 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
86772f3de30SBruce Richardson 		mac_addr[i] = 0;
86872f3de30SBruce Richardson 
86972f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
87072f3de30SBruce Richardson 	if (err)
87172f3de30SBruce Richardson 		return err;
87272f3de30SBruce Richardson 
873846ac76cSJohn Daley 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
87404e8ec74SJohn Daley 		mac_addr[i] = ((uint8_t *)&a0)[i];
87572f3de30SBruce Richardson 
87672f3de30SBruce Richardson 	return 0;
87772f3de30SBruce Richardson }
87872f3de30SBruce Richardson 
87972f3de30SBruce Richardson int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
88072f3de30SBruce Richardson 	int broadcast, int promisc, int allmulti)
88172f3de30SBruce Richardson {
88204e8ec74SJohn Daley 	uint64_t a0, a1 = 0;
88372f3de30SBruce Richardson 	int wait = 1000;
88472f3de30SBruce Richardson 	int err;
88572f3de30SBruce Richardson 
88672f3de30SBruce Richardson 	a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
88772f3de30SBruce Richardson 	     (multicast ? CMD_PFILTER_MULTICAST : 0) |
88872f3de30SBruce Richardson 	     (broadcast ? CMD_PFILTER_BROADCAST : 0) |
88972f3de30SBruce Richardson 	     (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
89072f3de30SBruce Richardson 	     (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
89172f3de30SBruce Richardson 
89272f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait);
89372f3de30SBruce Richardson 	if (err)
89472f3de30SBruce Richardson 		pr_err("Can't set packet filter\n");
89572f3de30SBruce Richardson 
89672f3de30SBruce Richardson 	return err;
89772f3de30SBruce Richardson }
89872f3de30SBruce Richardson 
89904e8ec74SJohn Daley int vnic_dev_add_addr(struct vnic_dev *vdev, uint8_t *addr)
90072f3de30SBruce Richardson {
90104e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
90272f3de30SBruce Richardson 	int wait = 1000;
90372f3de30SBruce Richardson 	int err;
90472f3de30SBruce Richardson 	int i;
90572f3de30SBruce Richardson 
906846ac76cSJohn Daley 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
90704e8ec74SJohn Daley 		((uint8_t *)&a0)[i] = addr[i];
90872f3de30SBruce Richardson 
90972f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
91072f3de30SBruce Richardson 	if (err)
911c2c4f87bSAman Deep Singh 		pr_err("Can't add addr [" RTE_ETHER_ADDR_PRT_FMT "], %d\n",
91272f3de30SBruce Richardson 			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
91372f3de30SBruce Richardson 			err);
91472f3de30SBruce Richardson 
91572f3de30SBruce Richardson 	return err;
91672f3de30SBruce Richardson }
91772f3de30SBruce Richardson 
91804e8ec74SJohn Daley int vnic_dev_del_addr(struct vnic_dev *vdev, uint8_t *addr)
91972f3de30SBruce Richardson {
92004e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
92172f3de30SBruce Richardson 	int wait = 1000;
92272f3de30SBruce Richardson 	int err;
92372f3de30SBruce Richardson 	int i;
92472f3de30SBruce Richardson 
925846ac76cSJohn Daley 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
92604e8ec74SJohn Daley 		((uint8_t *)&a0)[i] = addr[i];
92772f3de30SBruce Richardson 
92872f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
92972f3de30SBruce Richardson 	if (err)
930c2c4f87bSAman Deep Singh 		pr_err("Can't del addr [" RTE_ETHER_ADDR_PRT_FMT "], %d\n",
93172f3de30SBruce Richardson 			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
93272f3de30SBruce Richardson 			err);
93372f3de30SBruce Richardson 
93472f3de30SBruce Richardson 	return err;
93572f3de30SBruce Richardson }
93672f3de30SBruce Richardson 
93772f3de30SBruce Richardson int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
93804e8ec74SJohn Daley 	uint8_t ig_vlan_rewrite_mode)
93972f3de30SBruce Richardson {
94004e8ec74SJohn Daley 	uint64_t a0 = ig_vlan_rewrite_mode, a1 = 0;
94172f3de30SBruce Richardson 	int wait = 1000;
94272f3de30SBruce Richardson 
94372f3de30SBruce Richardson 	if (vnic_dev_capable(vdev, CMD_IG_VLAN_REWRITE_MODE))
94472f3de30SBruce Richardson 		return vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE,
94572f3de30SBruce Richardson 				&a0, &a1, wait);
94672f3de30SBruce Richardson 	else
94772f3de30SBruce Richardson 		return 0;
94872f3de30SBruce Richardson }
94972f3de30SBruce Richardson 
95072f3de30SBruce Richardson void vnic_dev_set_reset_flag(struct vnic_dev *vdev, int state)
95172f3de30SBruce Richardson {
95272f3de30SBruce Richardson 	vdev->in_reset = state;
95372f3de30SBruce Richardson }
95472f3de30SBruce Richardson 
95572f3de30SBruce Richardson static inline int vnic_dev_in_reset(struct vnic_dev *vdev)
95672f3de30SBruce Richardson {
95772f3de30SBruce Richardson 	return vdev->in_reset;
95872f3de30SBruce Richardson }
95972f3de30SBruce Richardson 
96072f3de30SBruce Richardson int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
96104e8ec74SJohn Daley 	void *notify_addr, dma_addr_t notify_pa, uint16_t intr)
96272f3de30SBruce Richardson {
96304e8ec74SJohn Daley 	uint64_t a0, a1;
96472f3de30SBruce Richardson 	int wait = 1000;
96572f3de30SBruce Richardson 	int r;
96672f3de30SBruce Richardson 
96772f3de30SBruce Richardson 	memset(notify_addr, 0, sizeof(struct vnic_devcmd_notify));
96872f3de30SBruce Richardson 	if (!vnic_dev_in_reset(vdev)) {
96972f3de30SBruce Richardson 		vdev->notify = notify_addr;
97072f3de30SBruce Richardson 		vdev->notify_pa = notify_pa;
97172f3de30SBruce Richardson 	}
97272f3de30SBruce Richardson 
97304e8ec74SJohn Daley 	a0 = (uint64_t)notify_pa;
97404e8ec74SJohn Daley 	a1 = ((uint64_t)intr << 32) & 0x0000ffff00000000ULL;
97572f3de30SBruce Richardson 	a1 += sizeof(struct vnic_devcmd_notify);
97672f3de30SBruce Richardson 
97772f3de30SBruce Richardson 	r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
97872f3de30SBruce Richardson 	if (!vnic_dev_in_reset(vdev))
97904e8ec74SJohn Daley 		vdev->notify_sz = (r == 0) ? (uint32_t)a1 : 0;
98072f3de30SBruce Richardson 
98172f3de30SBruce Richardson 	return r;
98272f3de30SBruce Richardson }
98372f3de30SBruce Richardson 
98404e8ec74SJohn Daley int vnic_dev_notify_set(struct vnic_dev *vdev, uint16_t intr)
98572f3de30SBruce Richardson {
98672f3de30SBruce Richardson 	void *notify_addr = NULL;
98772f3de30SBruce Richardson 	dma_addr_t notify_pa = 0;
988846ac76cSJohn Daley 	char name[RTE_MEMZONE_NAMESIZE];
98904e8ec74SJohn Daley 	static uint32_t instance;
99072f3de30SBruce Richardson 
99172f3de30SBruce Richardson 	if (vdev->notify || vdev->notify_pa) {
9927fbf050cSJohn Daley 		return vnic_dev_notify_setcmd(vdev, vdev->notify,
9937fbf050cSJohn Daley 					      vdev->notify_pa, intr);
99472f3de30SBruce Richardson 	}
99572f3de30SBruce Richardson 	if (!vnic_dev_in_reset(vdev)) {
99672f3de30SBruce Richardson 		snprintf((char *)name, sizeof(name),
99732d1206eSAaron Conole 			"vnic_notify-%u", instance++);
99872f3de30SBruce Richardson 		notify_addr = vdev->alloc_consistent(vdev->priv,
99972f3de30SBruce Richardson 			sizeof(struct vnic_devcmd_notify),
100004e8ec74SJohn Daley 			&notify_pa, (uint8_t *)name);
100172f3de30SBruce Richardson 		if (!notify_addr)
100272f3de30SBruce Richardson 			return -ENOMEM;
100372f3de30SBruce Richardson 	}
100472f3de30SBruce Richardson 
100572f3de30SBruce Richardson 	return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr);
100672f3de30SBruce Richardson }
100772f3de30SBruce Richardson 
100872f3de30SBruce Richardson int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
100972f3de30SBruce Richardson {
101004e8ec74SJohn Daley 	uint64_t a0, a1;
101172f3de30SBruce Richardson 	int wait = 1000;
101272f3de30SBruce Richardson 	int err;
101372f3de30SBruce Richardson 
101472f3de30SBruce Richardson 	a0 = 0;  /* paddr = 0 to unset notify buffer */
101572f3de30SBruce Richardson 	a1 = 0x0000ffff00000000ULL; /* intr num = -1 to unreg for intr */
101672f3de30SBruce Richardson 	a1 += sizeof(struct vnic_devcmd_notify);
101772f3de30SBruce Richardson 
101872f3de30SBruce Richardson 	err = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
101972f3de30SBruce Richardson 	if (!vnic_dev_in_reset(vdev)) {
102072f3de30SBruce Richardson 		vdev->notify = NULL;
102172f3de30SBruce Richardson 		vdev->notify_pa = 0;
102272f3de30SBruce Richardson 		vdev->notify_sz = 0;
102372f3de30SBruce Richardson 	}
102472f3de30SBruce Richardson 
102572f3de30SBruce Richardson 	return err;
102672f3de30SBruce Richardson }
102772f3de30SBruce Richardson 
102872f3de30SBruce Richardson int vnic_dev_notify_unset(struct vnic_dev *vdev)
102972f3de30SBruce Richardson {
103072f3de30SBruce Richardson 	if (vdev->notify && !vnic_dev_in_reset(vdev)) {
1031da5f560bSNelson Escobar 		vdev->free_consistent(vdev->priv,
103272f3de30SBruce Richardson 			sizeof(struct vnic_devcmd_notify),
103372f3de30SBruce Richardson 			vdev->notify,
103472f3de30SBruce Richardson 			vdev->notify_pa);
103572f3de30SBruce Richardson 	}
103672f3de30SBruce Richardson 
103772f3de30SBruce Richardson 	return vnic_dev_notify_unsetcmd(vdev);
103872f3de30SBruce Richardson }
103972f3de30SBruce Richardson 
104072f3de30SBruce Richardson static int vnic_dev_notify_ready(struct vnic_dev *vdev)
104172f3de30SBruce Richardson {
104204e8ec74SJohn Daley 	uint32_t *words;
104372f3de30SBruce Richardson 	unsigned int nwords = vdev->notify_sz / 4;
104472f3de30SBruce Richardson 	unsigned int i;
104504e8ec74SJohn Daley 	uint32_t csum;
104672f3de30SBruce Richardson 
104772f3de30SBruce Richardson 	if (!vdev->notify || !vdev->notify_sz)
104872f3de30SBruce Richardson 		return 0;
104972f3de30SBruce Richardson 
105072f3de30SBruce Richardson 	do {
105172f3de30SBruce Richardson 		csum = 0;
105272f3de30SBruce Richardson 		rte_memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz);
105304e8ec74SJohn Daley 		words = (uint32_t *)&vdev->notify_copy;
105472f3de30SBruce Richardson 		for (i = 1; i < nwords; i++)
105572f3de30SBruce Richardson 			csum += words[i];
105672f3de30SBruce Richardson 	} while (csum != words[0]);
105772f3de30SBruce Richardson 
105872f3de30SBruce Richardson 	return 1;
105972f3de30SBruce Richardson }
106072f3de30SBruce Richardson 
106172f3de30SBruce Richardson int vnic_dev_init(struct vnic_dev *vdev, int arg)
106272f3de30SBruce Richardson {
106304e8ec74SJohn Daley 	uint64_t a0 = (uint32_t)arg, a1 = 0;
106472f3de30SBruce Richardson 	int wait = 1000;
106572f3de30SBruce Richardson 	int r = 0;
106672f3de30SBruce Richardson 
106772f3de30SBruce Richardson 	if (vnic_dev_capable(vdev, CMD_INIT))
106872f3de30SBruce Richardson 		r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
106972f3de30SBruce Richardson 	else {
107072f3de30SBruce Richardson 		vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
107172f3de30SBruce Richardson 		if (a0 & CMD_INITF_DEFAULT_MAC) {
107272f3de30SBruce Richardson 			/* Emulate these for old CMD_INIT_v1 which
107372f3de30SBruce Richardson 			 * didn't pass a0 so no CMD_INITF_*.
107472f3de30SBruce Richardson 			 */
107572f3de30SBruce Richardson 			vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
107672f3de30SBruce Richardson 			vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
107772f3de30SBruce Richardson 		}
107872f3de30SBruce Richardson 	}
107972f3de30SBruce Richardson 	return r;
108072f3de30SBruce Richardson }
108172f3de30SBruce Richardson 
108272f3de30SBruce Richardson void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev)
108372f3de30SBruce Richardson {
108472f3de30SBruce Richardson 	/* Default: hardware intr coal timer is in units of 1.5 usecs */
108572f3de30SBruce Richardson 	vdev->intr_coal_timer_info.mul = 2;
108672f3de30SBruce Richardson 	vdev->intr_coal_timer_info.div = 3;
108772f3de30SBruce Richardson 	vdev->intr_coal_timer_info.max_usec =
108872f3de30SBruce Richardson 		vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff);
108972f3de30SBruce Richardson }
109072f3de30SBruce Richardson 
109172f3de30SBruce Richardson int vnic_dev_link_status(struct vnic_dev *vdev)
109272f3de30SBruce Richardson {
109372f3de30SBruce Richardson 	if (!vnic_dev_notify_ready(vdev))
109472f3de30SBruce Richardson 		return 0;
109572f3de30SBruce Richardson 
109672f3de30SBruce Richardson 	return vdev->notify_copy.link_state;
109772f3de30SBruce Richardson }
109872f3de30SBruce Richardson 
109904e8ec74SJohn Daley uint32_t vnic_dev_port_speed(struct vnic_dev *vdev)
110072f3de30SBruce Richardson {
110172f3de30SBruce Richardson 	if (!vnic_dev_notify_ready(vdev))
110272f3de30SBruce Richardson 		return 0;
110372f3de30SBruce Richardson 
110472f3de30SBruce Richardson 	return vdev->notify_copy.port_speed;
110572f3de30SBruce Richardson }
110672f3de30SBruce Richardson 
11070e7312b9SHyong Youb Kim uint32_t vnic_dev_mtu(struct vnic_dev *vdev)
11080e7312b9SHyong Youb Kim {
11090e7312b9SHyong Youb Kim 	if (!vnic_dev_notify_ready(vdev))
11100e7312b9SHyong Youb Kim 		return 0;
11110e7312b9SHyong Youb Kim 
11120e7312b9SHyong Youb Kim 	return vdev->notify_copy.mtu;
11130e7312b9SHyong Youb Kim }
11140e7312b9SHyong Youb Kim 
11150e7312b9SHyong Youb Kim uint32_t vnic_dev_uif(struct vnic_dev *vdev)
11160e7312b9SHyong Youb Kim {
11170e7312b9SHyong Youb Kim 	if (!vnic_dev_notify_ready(vdev))
11180e7312b9SHyong Youb Kim 		return 0;
11190e7312b9SHyong Youb Kim 
11200e7312b9SHyong Youb Kim 	return vdev->notify_copy.uif;
11210e7312b9SHyong Youb Kim }
11220e7312b9SHyong Youb Kim 
112304e8ec74SJohn Daley uint32_t vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev,
112404e8ec74SJohn Daley 					     uint32_t usec)
112572f3de30SBruce Richardson {
112672f3de30SBruce Richardson 	return (usec * vdev->intr_coal_timer_info.mul) /
112772f3de30SBruce Richardson 		vdev->intr_coal_timer_info.div;
112872f3de30SBruce Richardson }
112972f3de30SBruce Richardson 
113004e8ec74SJohn Daley uint32_t vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev,
113104e8ec74SJohn Daley 					     uint32_t hw_cycles)
113272f3de30SBruce Richardson {
113372f3de30SBruce Richardson 	return (hw_cycles * vdev->intr_coal_timer_info.div) /
113472f3de30SBruce Richardson 		vdev->intr_coal_timer_info.mul;
113572f3de30SBruce Richardson }
113672f3de30SBruce Richardson 
113704e8ec74SJohn Daley uint32_t vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev)
113872f3de30SBruce Richardson {
113972f3de30SBruce Richardson 	return vdev->intr_coal_timer_info.max_usec;
114072f3de30SBruce Richardson }
114172f3de30SBruce Richardson 
11428d782f3fSHyong Youb Kim int vnic_dev_alloc_stats_mem(struct vnic_dev *vdev)
11438d782f3fSHyong Youb Kim {
1144846ac76cSJohn Daley 	char name[RTE_MEMZONE_NAMESIZE];
114504e8ec74SJohn Daley 	static uint32_t instance;
11468d782f3fSHyong Youb Kim 
11478d782f3fSHyong Youb Kim 	snprintf((char *)name, sizeof(name), "vnic_stats-%u", instance++);
11488d782f3fSHyong Youb Kim 	vdev->stats = vdev->alloc_consistent(vdev->priv,
11498d782f3fSHyong Youb Kim 					     sizeof(struct vnic_stats),
115004e8ec74SJohn Daley 					     &vdev->stats_pa, (uint8_t *)name);
11518d782f3fSHyong Youb Kim 	return vdev->stats == NULL ? -ENOMEM : 0;
11528d782f3fSHyong Youb Kim }
11538d782f3fSHyong Youb Kim 
1154*00ce4311SHyong Youb Kim int vnic_dev_alloc_sriov_stats_mem(struct vnic_dev *vdev)
1155*00ce4311SHyong Youb Kim {
1156*00ce4311SHyong Youb Kim 	char name[RTE_MEMZONE_NAMESIZE];
1157*00ce4311SHyong Youb Kim 	static uint32_t instance;
1158*00ce4311SHyong Youb Kim 
1159*00ce4311SHyong Youb Kim 	snprintf((char *)name, sizeof(name), "vnic_sriov_stats-%u", instance++);
1160*00ce4311SHyong Youb Kim 	vdev->sriov_stats = vdev->alloc_consistent(vdev->priv,
1161*00ce4311SHyong Youb Kim 					     sizeof(struct vnic_sriov_stats),
1162*00ce4311SHyong Youb Kim 					     &vdev->sriov_stats_pa, (uint8_t *)name);
1163*00ce4311SHyong Youb Kim 	return vdev->sriov_stats == NULL ? -ENOMEM : 0;
1164*00ce4311SHyong Youb Kim }
1165*00ce4311SHyong Youb Kim 
116672f3de30SBruce Richardson void vnic_dev_unregister(struct vnic_dev *vdev)
116772f3de30SBruce Richardson {
116872f3de30SBruce Richardson 	if (vdev) {
116972f3de30SBruce Richardson 		if (vdev->notify)
1170da5f560bSNelson Escobar 			vdev->free_consistent(vdev->priv,
117172f3de30SBruce Richardson 				sizeof(struct vnic_devcmd_notify),
117272f3de30SBruce Richardson 				vdev->notify,
117372f3de30SBruce Richardson 				vdev->notify_pa);
117472f3de30SBruce Richardson 		if (vdev->stats)
1175da5f560bSNelson Escobar 			vdev->free_consistent(vdev->priv,
117672f3de30SBruce Richardson 				sizeof(struct vnic_stats),
117772f3de30SBruce Richardson 				vdev->stats, vdev->stats_pa);
1178*00ce4311SHyong Youb Kim 		if (vdev->sriov_stats)
1179*00ce4311SHyong Youb Kim 			vdev->free_consistent(vdev->priv,
1180*00ce4311SHyong Youb Kim 				sizeof(struct vnic_sriov_stats),
1181*00ce4311SHyong Youb Kim 				vdev->sriov_stats, vdev->sriov_stats_pa);
1182ea7768b5SHyong Youb Kim 		if (vdev->flowman_info)
1183ea7768b5SHyong Youb Kim 			vdev->free_consistent(vdev->priv,
1184ea7768b5SHyong Youb Kim 				sizeof(struct fm_info),
1185ea7768b5SHyong Youb Kim 				vdev->flowman_info, vdev->flowman_info_pa);
118672f3de30SBruce Richardson 		if (vdev->fw_info)
1187da5f560bSNelson Escobar 			vdev->free_consistent(vdev->priv,
118872f3de30SBruce Richardson 				sizeof(struct vnic_devcmd_fw_info),
118972f3de30SBruce Richardson 				vdev->fw_info, vdev->fw_info_pa);
11900e804034SJohn Daley 		rte_free(vdev);
119172f3de30SBruce Richardson 	}
119272f3de30SBruce Richardson }
119372f3de30SBruce Richardson 
119472f3de30SBruce Richardson struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
119572f3de30SBruce Richardson 	void *priv, struct rte_pci_device *pdev, struct vnic_dev_bar *bar,
119672f3de30SBruce Richardson 	unsigned int num_bars)
119772f3de30SBruce Richardson {
119872f3de30SBruce Richardson 	if (!vdev) {
1199846ac76cSJohn Daley 		char name[RTE_MEMZONE_NAMESIZE];
12000e804034SJohn Daley 		snprintf((char *)name, sizeof(name), "%s-vnic",
12010e804034SJohn Daley 			  pdev->device.name);
12020e804034SJohn Daley 		vdev = (struct vnic_dev *)rte_zmalloc_socket(name,
12030e804034SJohn Daley 					sizeof(struct vnic_dev),
12040e804034SJohn Daley 					RTE_CACHE_LINE_SIZE,
12050e804034SJohn Daley 					pdev->device.numa_node);
120672f3de30SBruce Richardson 		if (!vdev)
120772f3de30SBruce Richardson 			return NULL;
120872f3de30SBruce Richardson 	}
120972f3de30SBruce Richardson 
121072f3de30SBruce Richardson 	vdev->priv = priv;
121172f3de30SBruce Richardson 	vdev->pdev = pdev;
121272f3de30SBruce Richardson 
121372f3de30SBruce Richardson 	if (vnic_dev_discover_res(vdev, bar, num_bars))
121472f3de30SBruce Richardson 		goto err_out;
121572f3de30SBruce Richardson 
121672f3de30SBruce Richardson 	vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
121772f3de30SBruce Richardson 	if (!vdev->devcmd)
121872f3de30SBruce Richardson 		goto err_out;
121972f3de30SBruce Richardson 
122072f3de30SBruce Richardson 	return vdev;
122172f3de30SBruce Richardson 
122272f3de30SBruce Richardson err_out:
122372f3de30SBruce Richardson 	vnic_dev_unregister(vdev);
122472f3de30SBruce Richardson 	return NULL;
122572f3de30SBruce Richardson }
122672f3de30SBruce Richardson 
12270e7312b9SHyong Youb Kim struct vnic_dev *vnic_vf_rep_register(void *priv, struct vnic_dev *pf_vdev,
12280e7312b9SHyong Youb Kim 	int vf_id)
12290e7312b9SHyong Youb Kim {
12300e7312b9SHyong Youb Kim 	struct vnic_dev *vdev;
12310e7312b9SHyong Youb Kim 
12320e7312b9SHyong Youb Kim 	vdev = (struct vnic_dev *)rte_zmalloc("enic-vf-rep-vdev",
12330e7312b9SHyong Youb Kim 				sizeof(struct vnic_dev), RTE_CACHE_LINE_SIZE);
12340e7312b9SHyong Youb Kim 	if (!vdev)
12350e7312b9SHyong Youb Kim 		return NULL;
12360e7312b9SHyong Youb Kim 	vdev->priv = priv;
12370e7312b9SHyong Youb Kim 	vdev->pf_vdev = pf_vdev;
12380e7312b9SHyong Youb Kim 	vdev->vf_id = vf_id;
12390e7312b9SHyong Youb Kim 	vdev->alloc_consistent = pf_vdev->alloc_consistent;
12400e7312b9SHyong Youb Kim 	vdev->free_consistent = pf_vdev->free_consistent;
12410e7312b9SHyong Youb Kim 	return vdev;
12420e7312b9SHyong Youb Kim }
12430e7312b9SHyong Youb Kim 
124472f3de30SBruce Richardson /*
124572f3de30SBruce Richardson  *  vnic_dev_classifier: Add/Delete classifier entries
124672f3de30SBruce Richardson  *  @vdev: vdev of the device
124772f3de30SBruce Richardson  *  @cmd: CLSF_ADD for Add filter
124872f3de30SBruce Richardson  *        CLSF_DEL for Delete filter
124972f3de30SBruce Richardson  *  @entry: In case of ADD filter, the caller passes the RQ number in this
125072f3de30SBruce Richardson  *          variable.
125172f3de30SBruce Richardson  *          This function stores the filter_id returned by the
125272f3de30SBruce Richardson  *          firmware in the same variable before return;
125372f3de30SBruce Richardson  *
125472f3de30SBruce Richardson  *          In case of DEL filter, the caller passes the RQ number. Return
125572f3de30SBruce Richardson  *          value is irrelevant.
125672f3de30SBruce Richardson  * @data: filter data
1257322b355fSJohn Daley  * @action: action data
125872f3de30SBruce Richardson  */
125904e8ec74SJohn Daley int vnic_dev_classifier(struct vnic_dev *vdev, uint8_t cmd, uint16_t *entry,
1260322b355fSJohn Daley 	struct filter_v2 *data, struct filter_action_v2 *action_v2)
126172f3de30SBruce Richardson {
126204e8ec74SJohn Daley 	uint64_t a0 = 0, a1 = 0;
126372f3de30SBruce Richardson 	int wait = 1000;
126472f3de30SBruce Richardson 	dma_addr_t tlv_pa;
126572f3de30SBruce Richardson 	int ret = -EINVAL;
126672f3de30SBruce Richardson 	struct filter_tlv *tlv, *tlv_va;
126704e8ec74SJohn Daley 	uint64_t tlv_size;
126804e8ec74SJohn Daley 	uint32_t filter_size, action_size;
126972f3de30SBruce Richardson 	static unsigned int unique_id;
127072f3de30SBruce Richardson 	char z_name[RTE_MEMZONE_NAMESIZE];
1271dfbd6a9cSJohn Daley 	enum vnic_devcmd_cmd dev_cmd;
1272dfbd6a9cSJohn Daley 
127372f3de30SBruce Richardson 	if (cmd == CLSF_ADD) {
1274322b355fSJohn Daley 		dev_cmd = (data->type >= FILTER_DPDK_1) ?
1275322b355fSJohn Daley 			  CMD_ADD_ADV_FILTER : CMD_ADD_FILTER;
1276dfbd6a9cSJohn Daley 
1277dfbd6a9cSJohn Daley 		filter_size = vnic_filter_size(data);
1278322b355fSJohn Daley 		action_size = vnic_action_size(action_v2);
1279322b355fSJohn Daley 
1280322b355fSJohn Daley 		tlv_size = filter_size + action_size +
128172f3de30SBruce Richardson 		    2*sizeof(struct filter_tlv);
128272f3de30SBruce Richardson 		snprintf((char *)z_name, sizeof(z_name),
128332d1206eSAaron Conole 			"vnic_clsf_%u", unique_id++);
128472f3de30SBruce Richardson 		tlv_va = vdev->alloc_consistent(vdev->priv,
128504e8ec74SJohn Daley 			tlv_size, &tlv_pa, (uint8_t *)z_name);
128672f3de30SBruce Richardson 		if (!tlv_va)
128772f3de30SBruce Richardson 			return -ENOMEM;
128872f3de30SBruce Richardson 		tlv = tlv_va;
128972f3de30SBruce Richardson 		a0 = tlv_pa;
129072f3de30SBruce Richardson 		a1 = tlv_size;
129172f3de30SBruce Richardson 		memset(tlv, 0, tlv_size);
129272f3de30SBruce Richardson 		tlv->type = CLSF_TLV_FILTER;
1293dfbd6a9cSJohn Daley 		tlv->length = filter_size;
1294dfbd6a9cSJohn Daley 		memcpy(&tlv->val, (void *)data, filter_size);
129572f3de30SBruce Richardson 
129672f3de30SBruce Richardson 		tlv = (struct filter_tlv *)((char *)tlv +
129772f3de30SBruce Richardson 					 sizeof(struct filter_tlv) +
1298dfbd6a9cSJohn Daley 					 filter_size);
129972f3de30SBruce Richardson 
130072f3de30SBruce Richardson 		tlv->type = CLSF_TLV_ACTION;
1301322b355fSJohn Daley 		tlv->length = action_size;
1302322b355fSJohn Daley 		memcpy(&tlv->val, (void *)action_v2, action_size);
1303dfbd6a9cSJohn Daley 		ret = vnic_dev_cmd(vdev, dev_cmd, &a0, &a1, wait);
130404e8ec74SJohn Daley 		*entry = (uint16_t)a0;
1305da5f560bSNelson Escobar 		vdev->free_consistent(vdev->priv, tlv_size, tlv_va, tlv_pa);
130672f3de30SBruce Richardson 	} else if (cmd == CLSF_DEL) {
130772f3de30SBruce Richardson 		a0 = *entry;
130872f3de30SBruce Richardson 		ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait);
130972f3de30SBruce Richardson 	}
131072f3de30SBruce Richardson 
131172f3de30SBruce Richardson 	return ret;
131272f3de30SBruce Richardson }
131393fb21fdSHyong Youb Kim 
131404e8ec74SJohn Daley int vnic_dev_overlay_offload_ctrl(struct vnic_dev *vdev, uint8_t overlay,
131504e8ec74SJohn Daley 				  uint8_t config)
131693fb21fdSHyong Youb Kim {
131704e8ec74SJohn Daley 	uint64_t a0 = overlay;
131804e8ec74SJohn Daley 	uint64_t a1 = config;
131993fb21fdSHyong Youb Kim 	int wait = 1000;
132093fb21fdSHyong Youb Kim 
132193fb21fdSHyong Youb Kim 	return vnic_dev_cmd(vdev, CMD_OVERLAY_OFFLOAD_CTRL, &a0, &a1, wait);
132293fb21fdSHyong Youb Kim }
132393fb21fdSHyong Youb Kim 
132404e8ec74SJohn Daley int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, uint8_t overlay,
132504e8ec74SJohn Daley 				 uint16_t vxlan_udp_port_number)
132693fb21fdSHyong Youb Kim {
132704e8ec74SJohn Daley 	uint64_t a1 = vxlan_udp_port_number;
132804e8ec74SJohn Daley 	uint64_t a0 = overlay;
132993fb21fdSHyong Youb Kim 	int wait = 1000;
133093fb21fdSHyong Youb Kim 
133193fb21fdSHyong Youb Kim 	return vnic_dev_cmd(vdev, CMD_OVERLAY_OFFLOAD_CFG, &a0, &a1, wait);
133293fb21fdSHyong Youb Kim }
133393fb21fdSHyong Youb Kim 
133493fb21fdSHyong Youb Kim int vnic_dev_capable_vxlan(struct vnic_dev *vdev)
133593fb21fdSHyong Youb Kim {
133604e8ec74SJohn Daley 	uint64_t a0 = VIC_FEATURE_VXLAN;
133704e8ec74SJohn Daley 	uint64_t a1 = 0;
133893fb21fdSHyong Youb Kim 	int wait = 1000;
133993fb21fdSHyong Youb Kim 	int ret;
134093fb21fdSHyong Youb Kim 
134193fb21fdSHyong Youb Kim 	ret = vnic_dev_cmd(vdev, CMD_GET_SUPP_FEATURE_VER, &a0, &a1, wait);
134293fb21fdSHyong Youb Kim 	/* 1 if the NIC can do VXLAN for both IPv4 and IPv6 with multiple WQs */
134393fb21fdSHyong Youb Kim 	return ret == 0 &&
134493fb21fdSHyong Youb Kim 		(a1 & (FEATURE_VXLAN_IPV6 | FEATURE_VXLAN_MULTI_WQ)) ==
134593fb21fdSHyong Youb Kim 		(FEATURE_VXLAN_IPV6 | FEATURE_VXLAN_MULTI_WQ);
134693fb21fdSHyong Youb Kim }
1347c02a96fcSHyong Youb Kim 
1348c02a96fcSHyong Youb Kim int vnic_dev_capable_geneve(struct vnic_dev *vdev)
1349c02a96fcSHyong Youb Kim {
135004e8ec74SJohn Daley 	uint64_t a0 = VIC_FEATURE_GENEVE;
135104e8ec74SJohn Daley 	uint64_t a1 = 0;
1352c02a96fcSHyong Youb Kim 	int wait = 1000;
1353c02a96fcSHyong Youb Kim 	int ret;
1354c02a96fcSHyong Youb Kim 
1355c02a96fcSHyong Youb Kim 	ret = vnic_dev_cmd(vdev, CMD_GET_SUPP_FEATURE_VER, &a0, &a1, wait);
135661c7b522SJohn Daley 	return ret == 0 && !!(a1 & FEATURE_GENEVE_OPTIONS);
1357c02a96fcSHyong Youb Kim }
13588b428cb5SHyong Youb Kim 
13598b428cb5SHyong Youb Kim uint64_t vnic_dev_capable_cq_entry_size(struct vnic_dev *vdev)
13608b428cb5SHyong Youb Kim {
13618b428cb5SHyong Youb Kim 	uint64_t a0 = CMD_CQ_ENTRY_SIZE_SET;
13628b428cb5SHyong Youb Kim 	uint64_t a1 = 0;
13638b428cb5SHyong Youb Kim 	int wait = 1000;
13648b428cb5SHyong Youb Kim 	int ret;
13658b428cb5SHyong Youb Kim 
13668b428cb5SHyong Youb Kim 	ret = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
13678b428cb5SHyong Youb Kim 	/* All models support 16B CQ entry by default */
13688b428cb5SHyong Youb Kim 	if (!(ret == 0 && a0 == 0))
13698b428cb5SHyong Youb Kim 		a1 = VNIC_RQ_CQ_ENTRY_SIZE_16_CAPABLE;
13708b428cb5SHyong Youb Kim 	return a1;
13718b428cb5SHyong Youb Kim }
13728b428cb5SHyong Youb Kim 
13738b428cb5SHyong Youb Kim int vnic_dev_set_cq_entry_size(struct vnic_dev *vdev, uint32_t rq_idx,
13748b428cb5SHyong Youb Kim 			       uint32_t size_flag)
13758b428cb5SHyong Youb Kim {
13768b428cb5SHyong Youb Kim 	uint64_t a0 = rq_idx;
13778b428cb5SHyong Youb Kim 	uint64_t a1 = size_flag;
13788b428cb5SHyong Youb Kim 	int wait = 1000;
13798b428cb5SHyong Youb Kim 
13808b428cb5SHyong Youb Kim 	return vnic_dev_cmd(vdev, CMD_CQ_ENTRY_SIZE_SET, &a0, &a1, wait);
13818b428cb5SHyong Youb Kim }
1382*00ce4311SHyong Youb Kim 
1383*00ce4311SHyong Youb Kim int vnic_dev_enable_admin_qp(struct vnic_dev *vdev, uint32_t enable)
1384*00ce4311SHyong Youb Kim {
1385*00ce4311SHyong Youb Kim 	uint64_t a0, a1;
1386*00ce4311SHyong Youb Kim 	int wait = 1000;
1387*00ce4311SHyong Youb Kim 
1388*00ce4311SHyong Youb Kim 	a0 = QP_TYPE_ADMIN;
1389*00ce4311SHyong Youb Kim 	a1 = enable;
1390*00ce4311SHyong Youb Kim 	return vnic_dev_cmd(vdev, CMD_QP_TYPE_SET, &a0, &a1, wait);
1391*00ce4311SHyong Youb Kim }
1392*00ce4311SHyong Youb Kim 
1393*00ce4311SHyong Youb Kim int vnic_dev_sriov_stats(struct vnic_dev *vdev, struct vnic_sriov_stats **stats)
1394*00ce4311SHyong Youb Kim {
1395*00ce4311SHyong Youb Kim 	uint64_t a0, a1;
1396*00ce4311SHyong Youb Kim 	int wait = 1000;
1397*00ce4311SHyong Youb Kim 	int err;
1398*00ce4311SHyong Youb Kim 
1399*00ce4311SHyong Youb Kim 	a0 = vdev->sriov_stats_pa;
1400*00ce4311SHyong Youb Kim 	a1 = sizeof(struct vnic_sriov_stats);
1401*00ce4311SHyong Youb Kim 	err = vnic_dev_cmd(vdev, CMD_SRIOV_STATS_GET, &a0, &a1, wait);
1402*00ce4311SHyong Youb Kim 	if (!err)
1403*00ce4311SHyong Youb Kim 		*stats = vdev->sriov_stats;
1404*00ce4311SHyong Youb Kim 	return err;
1405*00ce4311SHyong Youb Kim }
1406