xref: /linux/drivers/net/ethernet/cisco/enic/vnic_dev.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1e6550b3eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a6a5580cSJeff Kirsher /*
3a6a5580cSJeff Kirsher  * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
4a6a5580cSJeff Kirsher  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
5a6a5580cSJeff Kirsher  */
6a6a5580cSJeff Kirsher 
7a6a5580cSJeff Kirsher #include <linux/kernel.h>
8a6a5580cSJeff Kirsher #include <linux/errno.h>
9a6a5580cSJeff Kirsher #include <linux/types.h>
10a6a5580cSJeff Kirsher #include <linux/pci.h>
11a6a5580cSJeff Kirsher #include <linux/delay.h>
12a6a5580cSJeff Kirsher #include <linux/if_ether.h>
13a6a5580cSJeff Kirsher 
14a6a5580cSJeff Kirsher #include "vnic_resource.h"
15a6a5580cSJeff Kirsher #include "vnic_devcmd.h"
16a6a5580cSJeff Kirsher #include "vnic_dev.h"
17373fb087SGovindarajulu Varadarajan #include "vnic_wq.h"
18a6a5580cSJeff Kirsher #include "vnic_stats.h"
196a3c2f83SGovindarajulu Varadarajan #include "enic.h"
20a6a5580cSJeff Kirsher 
21a6a5580cSJeff Kirsher #define VNIC_MAX_RES_HDR_SIZE \
22a6a5580cSJeff Kirsher 	(sizeof(struct vnic_resource_header) + \
23a6a5580cSJeff Kirsher 	sizeof(struct vnic_resource) * RES_TYPE_MAX)
24a6a5580cSJeff Kirsher #define VNIC_RES_STRIDE	128
25a6a5580cSJeff Kirsher 
vnic_dev_priv(struct vnic_dev * vdev)26a6a5580cSJeff Kirsher void *vnic_dev_priv(struct vnic_dev *vdev)
27a6a5580cSJeff Kirsher {
28a6a5580cSJeff Kirsher 	return vdev->priv;
29a6a5580cSJeff Kirsher }
30a6a5580cSJeff Kirsher 
vnic_dev_discover_res(struct vnic_dev * vdev,struct vnic_dev_bar * bar,unsigned int num_bars)31a6a5580cSJeff Kirsher static int vnic_dev_discover_res(struct vnic_dev *vdev,
32a6a5580cSJeff Kirsher 	struct vnic_dev_bar *bar, unsigned int num_bars)
33a6a5580cSJeff Kirsher {
34a6a5580cSJeff Kirsher 	struct vnic_resource_header __iomem *rh;
35a6a5580cSJeff Kirsher 	struct mgmt_barmap_hdr __iomem *mrh;
36a6a5580cSJeff Kirsher 	struct vnic_resource __iomem *r;
37a6a5580cSJeff Kirsher 	u8 type;
38a6a5580cSJeff Kirsher 
39a6a5580cSJeff Kirsher 	if (num_bars == 0)
40a6a5580cSJeff Kirsher 		return -EINVAL;
41a6a5580cSJeff Kirsher 
42a6a5580cSJeff Kirsher 	if (bar->len < VNIC_MAX_RES_HDR_SIZE) {
43e327f4e1SJoe Perches 		vdev_err(vdev, "vNIC BAR0 res hdr length error\n");
44a6a5580cSJeff Kirsher 		return -EINVAL;
45a6a5580cSJeff Kirsher 	}
46a6a5580cSJeff Kirsher 
47a6a5580cSJeff Kirsher 	rh  = bar->vaddr;
48a6a5580cSJeff Kirsher 	mrh = bar->vaddr;
49a6a5580cSJeff Kirsher 	if (!rh) {
50e327f4e1SJoe Perches 		vdev_err(vdev, "vNIC BAR0 res hdr not mem-mapped\n");
51a6a5580cSJeff Kirsher 		return -EINVAL;
52a6a5580cSJeff Kirsher 	}
53a6a5580cSJeff Kirsher 
54a6a5580cSJeff Kirsher 	/* Check for mgmt vnic in addition to normal vnic */
55a6a5580cSJeff Kirsher 	if ((ioread32(&rh->magic) != VNIC_RES_MAGIC) ||
56a6a5580cSJeff Kirsher 		(ioread32(&rh->version) != VNIC_RES_VERSION)) {
57a6a5580cSJeff Kirsher 		if ((ioread32(&mrh->magic) != MGMTVNIC_MAGIC) ||
58a6a5580cSJeff Kirsher 			(ioread32(&mrh->version) != MGMTVNIC_VERSION)) {
59e327f4e1SJoe Perches 			vdev_err(vdev, "vNIC BAR0 res magic/version error exp (%lx/%lx) or (%lx/%lx), curr (%x/%x)\n",
60a6a5580cSJeff Kirsher 				 VNIC_RES_MAGIC, VNIC_RES_VERSION,
61a6a5580cSJeff Kirsher 				 MGMTVNIC_MAGIC, MGMTVNIC_VERSION,
62a6a5580cSJeff Kirsher 				 ioread32(&rh->magic), ioread32(&rh->version));
63a6a5580cSJeff Kirsher 			return -EINVAL;
64a6a5580cSJeff Kirsher 		}
65a6a5580cSJeff Kirsher 	}
66a6a5580cSJeff Kirsher 
67a6a5580cSJeff Kirsher 	if (ioread32(&mrh->magic) == MGMTVNIC_MAGIC)
68a6a5580cSJeff Kirsher 		r = (struct vnic_resource __iomem *)(mrh + 1);
69a6a5580cSJeff Kirsher 	else
70a6a5580cSJeff Kirsher 		r = (struct vnic_resource __iomem *)(rh + 1);
71a6a5580cSJeff Kirsher 
72a6a5580cSJeff Kirsher 
73a6a5580cSJeff Kirsher 	while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
74a6a5580cSJeff Kirsher 
75a6a5580cSJeff Kirsher 		u8 bar_num = ioread8(&r->bar);
76a6a5580cSJeff Kirsher 		u32 bar_offset = ioread32(&r->bar_offset);
77a6a5580cSJeff Kirsher 		u32 count = ioread32(&r->count);
78a6a5580cSJeff Kirsher 		u32 len;
79a6a5580cSJeff Kirsher 
80a6a5580cSJeff Kirsher 		r++;
81a6a5580cSJeff Kirsher 
82a6a5580cSJeff Kirsher 		if (bar_num >= num_bars)
83a6a5580cSJeff Kirsher 			continue;
84a6a5580cSJeff Kirsher 
85a6a5580cSJeff Kirsher 		if (!bar[bar_num].len || !bar[bar_num].vaddr)
86a6a5580cSJeff Kirsher 			continue;
87a6a5580cSJeff Kirsher 
88a6a5580cSJeff Kirsher 		switch (type) {
89a6a5580cSJeff Kirsher 		case RES_TYPE_WQ:
90a6a5580cSJeff Kirsher 		case RES_TYPE_RQ:
91a6a5580cSJeff Kirsher 		case RES_TYPE_CQ:
92a6a5580cSJeff Kirsher 		case RES_TYPE_INTR_CTRL:
93a6a5580cSJeff Kirsher 			/* each count is stride bytes long */
94a6a5580cSJeff Kirsher 			len = count * VNIC_RES_STRIDE;
95a6a5580cSJeff Kirsher 			if (len + bar_offset > bar[bar_num].len) {
96e327f4e1SJoe Perches 				vdev_err(vdev, "vNIC BAR0 resource %d out-of-bounds, offset 0x%x + size 0x%x > bar len 0x%lx\n",
976a3c2f83SGovindarajulu Varadarajan 					 type, bar_offset, len,
98a6a5580cSJeff Kirsher 					 bar[bar_num].len);
99a6a5580cSJeff Kirsher 				return -EINVAL;
100a6a5580cSJeff Kirsher 			}
101a6a5580cSJeff Kirsher 			break;
102a6a5580cSJeff Kirsher 		case RES_TYPE_INTR_PBA_LEGACY:
103a6a5580cSJeff Kirsher 		case RES_TYPE_DEVCMD:
104373fb087SGovindarajulu Varadarajan 		case RES_TYPE_DEVCMD2:
105a6a5580cSJeff Kirsher 			len = count;
106a6a5580cSJeff Kirsher 			break;
107a6a5580cSJeff Kirsher 		default:
108a6a5580cSJeff Kirsher 			continue;
109a6a5580cSJeff Kirsher 		}
110a6a5580cSJeff Kirsher 
111a6a5580cSJeff Kirsher 		vdev->res[type].count = count;
112a6a5580cSJeff Kirsher 		vdev->res[type].vaddr = (char __iomem *)bar[bar_num].vaddr +
113a6a5580cSJeff Kirsher 			bar_offset;
114a6a5580cSJeff Kirsher 		vdev->res[type].bus_addr = bar[bar_num].bus_addr + bar_offset;
115a6a5580cSJeff Kirsher 	}
116a6a5580cSJeff Kirsher 
117a6a5580cSJeff Kirsher 	return 0;
118a6a5580cSJeff Kirsher }
119a6a5580cSJeff Kirsher 
vnic_dev_get_res_count(struct vnic_dev * vdev,enum vnic_res_type type)120a6a5580cSJeff Kirsher unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
121a6a5580cSJeff Kirsher 	enum vnic_res_type type)
122a6a5580cSJeff Kirsher {
123a6a5580cSJeff Kirsher 	return vdev->res[type].count;
124a6a5580cSJeff Kirsher }
1254a50ddfdSgovindarajulu.v EXPORT_SYMBOL(vnic_dev_get_res_count);
126a6a5580cSJeff Kirsher 
vnic_dev_get_res(struct vnic_dev * vdev,enum vnic_res_type type,unsigned int index)127a6a5580cSJeff Kirsher void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
128a6a5580cSJeff Kirsher 	unsigned int index)
129a6a5580cSJeff Kirsher {
130a6a5580cSJeff Kirsher 	if (!vdev->res[type].vaddr)
131a6a5580cSJeff Kirsher 		return NULL;
132a6a5580cSJeff Kirsher 
133a6a5580cSJeff Kirsher 	switch (type) {
134a6a5580cSJeff Kirsher 	case RES_TYPE_WQ:
135a6a5580cSJeff Kirsher 	case RES_TYPE_RQ:
136a6a5580cSJeff Kirsher 	case RES_TYPE_CQ:
137a6a5580cSJeff Kirsher 	case RES_TYPE_INTR_CTRL:
138a6a5580cSJeff Kirsher 		return (char __iomem *)vdev->res[type].vaddr +
139a6a5580cSJeff Kirsher 			index * VNIC_RES_STRIDE;
140a6a5580cSJeff Kirsher 	default:
141a6a5580cSJeff Kirsher 		return (char __iomem *)vdev->res[type].vaddr;
142a6a5580cSJeff Kirsher 	}
143a6a5580cSJeff Kirsher }
1444a50ddfdSgovindarajulu.v EXPORT_SYMBOL(vnic_dev_get_res);
145a6a5580cSJeff Kirsher 
vnic_dev_desc_ring_size(struct vnic_dev_ring * ring,unsigned int desc_count,unsigned int desc_size)146a6a5580cSJeff Kirsher static unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
147a6a5580cSJeff Kirsher 	unsigned int desc_count, unsigned int desc_size)
148a6a5580cSJeff Kirsher {
149a6a5580cSJeff Kirsher 
150*369dac68SSatish Kharat 	/* Descriptor ring base address alignment in bytes*/
151*369dac68SSatish Kharat 	ring->base_align = VNIC_DESC_BASE_ALIGN;
152a6a5580cSJeff Kirsher 
153*369dac68SSatish Kharat 	/* A count of 0 means the maximum descriptors */
154a6a5580cSJeff Kirsher 	if (desc_count == 0)
155*369dac68SSatish Kharat 		desc_count = VNIC_DESC_MAX_COUNT;
156a6a5580cSJeff Kirsher 
157*369dac68SSatish Kharat 	/* Descriptor count aligned in groups of VNIC_DESC_COUNT_ALIGN descriptors */
158*369dac68SSatish Kharat 	ring->desc_count = ALIGN(desc_count, VNIC_DESC_COUNT_ALIGN);
159a6a5580cSJeff Kirsher 
160*369dac68SSatish Kharat 	/* Descriptor size alignment in bytes */
161*369dac68SSatish Kharat 	ring->desc_size = ALIGN(desc_size, VNIC_DESC_SIZE_ALIGN);
162a6a5580cSJeff Kirsher 
163a6a5580cSJeff Kirsher 	ring->size = ring->desc_count * ring->desc_size;
164a6a5580cSJeff Kirsher 	ring->size_unaligned = ring->size + ring->base_align;
165a6a5580cSJeff Kirsher 
166a6a5580cSJeff Kirsher 	return ring->size_unaligned;
167a6a5580cSJeff Kirsher }
168a6a5580cSJeff Kirsher 
vnic_dev_clear_desc_ring(struct vnic_dev_ring * ring)169a6a5580cSJeff Kirsher void vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring)
170a6a5580cSJeff Kirsher {
171a6a5580cSJeff Kirsher 	memset(ring->descs, 0, ring->size);
172a6a5580cSJeff Kirsher }
173a6a5580cSJeff Kirsher 
vnic_dev_alloc_desc_ring(struct vnic_dev * vdev,struct vnic_dev_ring * ring,unsigned int desc_count,unsigned int desc_size)174a6a5580cSJeff Kirsher int vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
175a6a5580cSJeff Kirsher 	unsigned int desc_count, unsigned int desc_size)
176a6a5580cSJeff Kirsher {
177a6a5580cSJeff Kirsher 	vnic_dev_desc_ring_size(ring, desc_count, desc_size);
178a6a5580cSJeff Kirsher 
17902a20d4fSChristophe JAILLET 	ring->descs_unaligned = dma_alloc_coherent(&vdev->pdev->dev,
180a6a5580cSJeff Kirsher 						   ring->size_unaligned,
18102a20d4fSChristophe JAILLET 						   &ring->base_addr_unaligned,
18202a20d4fSChristophe JAILLET 						   GFP_KERNEL);
183a6a5580cSJeff Kirsher 
184a6a5580cSJeff Kirsher 	if (!ring->descs_unaligned) {
185e327f4e1SJoe Perches 		vdev_err(vdev, "Failed to allocate ring (size=%d), aborting\n",
186a6a5580cSJeff Kirsher 			 (int)ring->size);
187a6a5580cSJeff Kirsher 		return -ENOMEM;
188a6a5580cSJeff Kirsher 	}
189a6a5580cSJeff Kirsher 
190a6a5580cSJeff Kirsher 	ring->base_addr = ALIGN(ring->base_addr_unaligned,
191a6a5580cSJeff Kirsher 		ring->base_align);
192a6a5580cSJeff Kirsher 	ring->descs = (u8 *)ring->descs_unaligned +
193a6a5580cSJeff Kirsher 		(ring->base_addr - ring->base_addr_unaligned);
194a6a5580cSJeff Kirsher 
195a6a5580cSJeff Kirsher 	vnic_dev_clear_desc_ring(ring);
196a6a5580cSJeff Kirsher 
197a6a5580cSJeff Kirsher 	ring->desc_avail = ring->desc_count - 1;
198a6a5580cSJeff Kirsher 
199a6a5580cSJeff Kirsher 	return 0;
200a6a5580cSJeff Kirsher }
201a6a5580cSJeff Kirsher 
vnic_dev_free_desc_ring(struct vnic_dev * vdev,struct vnic_dev_ring * ring)202a6a5580cSJeff Kirsher void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
203a6a5580cSJeff Kirsher {
204a6a5580cSJeff Kirsher 	if (ring->descs) {
20502a20d4fSChristophe JAILLET 		dma_free_coherent(&vdev->pdev->dev, ring->size_unaligned,
206a6a5580cSJeff Kirsher 				  ring->descs_unaligned,
207a6a5580cSJeff Kirsher 				  ring->base_addr_unaligned);
208a6a5580cSJeff Kirsher 		ring->descs = NULL;
209a6a5580cSJeff Kirsher 	}
210a6a5580cSJeff Kirsher }
211a6a5580cSJeff Kirsher 
_vnic_dev_cmd(struct vnic_dev * vdev,enum vnic_devcmd_cmd cmd,int wait)212a6a5580cSJeff Kirsher static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
213a6a5580cSJeff Kirsher 	int wait)
214a6a5580cSJeff Kirsher {
215a6a5580cSJeff Kirsher 	struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
216a6a5580cSJeff Kirsher 	unsigned int i;
217a6a5580cSJeff Kirsher 	int delay;
218a6a5580cSJeff Kirsher 	u32 status;
219a6a5580cSJeff Kirsher 	int err;
220a6a5580cSJeff Kirsher 
221a6a5580cSJeff Kirsher 	status = ioread32(&devcmd->status);
222a6a5580cSJeff Kirsher 	if (status == 0xFFFFFFFF) {
223a6a5580cSJeff Kirsher 		/* PCI-e target device is gone */
224a6a5580cSJeff Kirsher 		return -ENODEV;
225a6a5580cSJeff Kirsher 	}
226a6a5580cSJeff Kirsher 	if (status & STAT_BUSY) {
227e327f4e1SJoe Perches 		vdev_neterr(vdev, "Busy devcmd %d\n", _CMD_N(cmd));
228a6a5580cSJeff Kirsher 		return -EBUSY;
229a6a5580cSJeff Kirsher 	}
230a6a5580cSJeff Kirsher 
231a6a5580cSJeff Kirsher 	if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
232a6a5580cSJeff Kirsher 		for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
233a6a5580cSJeff Kirsher 			writeq(vdev->args[i], &devcmd->args[i]);
234a6a5580cSJeff Kirsher 		wmb();
235a6a5580cSJeff Kirsher 	}
236a6a5580cSJeff Kirsher 
237a6a5580cSJeff Kirsher 	iowrite32(cmd, &devcmd->cmd);
238a6a5580cSJeff Kirsher 
239a6a5580cSJeff Kirsher 	if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
240a6a5580cSJeff Kirsher 		return 0;
241a6a5580cSJeff Kirsher 
242a6a5580cSJeff Kirsher 	for (delay = 0; delay < wait; delay++) {
243a6a5580cSJeff Kirsher 
244a6a5580cSJeff Kirsher 		udelay(100);
245a6a5580cSJeff Kirsher 
246a6a5580cSJeff Kirsher 		status = ioread32(&devcmd->status);
247a6a5580cSJeff Kirsher 		if (status == 0xFFFFFFFF) {
248a6a5580cSJeff Kirsher 			/* PCI-e target device is gone */
249a6a5580cSJeff Kirsher 			return -ENODEV;
250a6a5580cSJeff Kirsher 		}
251a6a5580cSJeff Kirsher 
252a6a5580cSJeff Kirsher 		if (!(status & STAT_BUSY)) {
253a6a5580cSJeff Kirsher 
254a6a5580cSJeff Kirsher 			if (status & STAT_ERROR) {
255a6a5580cSJeff Kirsher 				err = (int)readq(&devcmd->args[0]);
25607783f39SStefan Assmann 				if (err == ERR_EINVAL &&
25707783f39SStefan Assmann 				    cmd == CMD_CAPABILITY)
25810cc8844SGovindarajulu Varadarajan 					return -err;
259a6a5580cSJeff Kirsher 				if (err != ERR_ECMDUNKNOWN ||
260a6a5580cSJeff Kirsher 				    cmd != CMD_CAPABILITY)
261e327f4e1SJoe Perches 					vdev_neterr(vdev, "Error %d devcmd %d\n",
262a6a5580cSJeff Kirsher 						    err, _CMD_N(cmd));
26310cc8844SGovindarajulu Varadarajan 				return -err;
264a6a5580cSJeff Kirsher 			}
265a6a5580cSJeff Kirsher 
266a6a5580cSJeff Kirsher 			if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
267a6a5580cSJeff Kirsher 				rmb();
268a6a5580cSJeff Kirsher 				for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
269a6a5580cSJeff Kirsher 					vdev->args[i] = readq(&devcmd->args[i]);
270a6a5580cSJeff Kirsher 			}
271a6a5580cSJeff Kirsher 
272a6a5580cSJeff Kirsher 			return 0;
273a6a5580cSJeff Kirsher 		}
274a6a5580cSJeff Kirsher 	}
275a6a5580cSJeff Kirsher 
276e327f4e1SJoe Perches 	vdev_neterr(vdev, "Timedout devcmd %d\n", _CMD_N(cmd));
277a6a5580cSJeff Kirsher 	return -ETIMEDOUT;
278a6a5580cSJeff Kirsher }
279a6a5580cSJeff Kirsher 
_vnic_dev_cmd2(struct vnic_dev * vdev,enum vnic_devcmd_cmd cmd,int wait)280373fb087SGovindarajulu Varadarajan static int _vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
281373fb087SGovindarajulu Varadarajan 			  int wait)
282373fb087SGovindarajulu Varadarajan {
283373fb087SGovindarajulu Varadarajan 	struct devcmd2_controller *dc2c = vdev->devcmd2;
284ca7f41a4SSandeep Pillai 	struct devcmd2_result *result;
285ca7f41a4SSandeep Pillai 	u8 color;
286373fb087SGovindarajulu Varadarajan 	unsigned int i;
287373fb087SGovindarajulu Varadarajan 	int delay, err;
288dafc2199SGovindarajulu Varadarajan 	u32 fetch_index, new_posted;
289dafc2199SGovindarajulu Varadarajan 	u32 posted = dc2c->posted;
290373fb087SGovindarajulu Varadarajan 
291373fb087SGovindarajulu Varadarajan 	fetch_index = ioread32(&dc2c->wq_ctrl->fetch_index);
292373fb087SGovindarajulu Varadarajan 
293dafc2199SGovindarajulu Varadarajan 	if (fetch_index == 0xFFFFFFFF)
294373fb087SGovindarajulu Varadarajan 		return -ENODEV;
295373fb087SGovindarajulu Varadarajan 
296373fb087SGovindarajulu Varadarajan 	new_posted = (posted + 1) % DEVCMD2_RING_SIZE;
297373fb087SGovindarajulu Varadarajan 
298373fb087SGovindarajulu Varadarajan 	if (new_posted == fetch_index) {
299e327f4e1SJoe Perches 		vdev_neterr(vdev, "devcmd2 %d: wq is full. fetch index: %u, posted index: %u\n",
300373fb087SGovindarajulu Varadarajan 			    _CMD_N(cmd), fetch_index, posted);
301373fb087SGovindarajulu Varadarajan 		return -EBUSY;
302373fb087SGovindarajulu Varadarajan 	}
303373fb087SGovindarajulu Varadarajan 	dc2c->cmd_ring[posted].cmd = cmd;
304373fb087SGovindarajulu Varadarajan 	dc2c->cmd_ring[posted].flags = 0;
305373fb087SGovindarajulu Varadarajan 
306373fb087SGovindarajulu Varadarajan 	if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
307373fb087SGovindarajulu Varadarajan 		dc2c->cmd_ring[posted].flags |= DEVCMD2_FNORESULT;
308373fb087SGovindarajulu Varadarajan 	if (_CMD_DIR(cmd) & _CMD_DIR_WRITE)
309373fb087SGovindarajulu Varadarajan 		for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
310373fb087SGovindarajulu Varadarajan 			dc2c->cmd_ring[posted].args[i] = vdev->args[i];
311373fb087SGovindarajulu Varadarajan 
312373fb087SGovindarajulu Varadarajan 	/* Adding write memory barrier prevents compiler and/or CPU reordering,
313373fb087SGovindarajulu Varadarajan 	 * thus avoiding descriptor posting before descriptor is initialized.
314373fb087SGovindarajulu Varadarajan 	 * Otherwise, hardware can read stale descriptor fields.
315373fb087SGovindarajulu Varadarajan 	 */
316373fb087SGovindarajulu Varadarajan 	wmb();
317373fb087SGovindarajulu Varadarajan 	iowrite32(new_posted, &dc2c->wq_ctrl->posted_index);
318dafc2199SGovindarajulu Varadarajan 	dc2c->posted = new_posted;
319373fb087SGovindarajulu Varadarajan 
320373fb087SGovindarajulu Varadarajan 	if (dc2c->cmd_ring[posted].flags & DEVCMD2_FNORESULT)
321373fb087SGovindarajulu Varadarajan 		return 0;
322373fb087SGovindarajulu Varadarajan 
323ca7f41a4SSandeep Pillai 	result = dc2c->result + dc2c->next_result;
324ca7f41a4SSandeep Pillai 	color = dc2c->color;
325ca7f41a4SSandeep Pillai 
326373fb087SGovindarajulu Varadarajan 	dc2c->next_result++;
327373fb087SGovindarajulu Varadarajan 	if (dc2c->next_result == dc2c->result_size) {
328373fb087SGovindarajulu Varadarajan 		dc2c->next_result = 0;
329373fb087SGovindarajulu Varadarajan 		dc2c->color = dc2c->color ? 0 : 1;
330373fb087SGovindarajulu Varadarajan 	}
331ca7f41a4SSandeep Pillai 
332ca7f41a4SSandeep Pillai 	for (delay = 0; delay < wait; delay++) {
333ca7f41a4SSandeep Pillai 		if (result->color == color) {
334373fb087SGovindarajulu Varadarajan 			if (result->error) {
335373fb087SGovindarajulu Varadarajan 				err = result->error;
336373fb087SGovindarajulu Varadarajan 				if (err != ERR_ECMDUNKNOWN ||
337373fb087SGovindarajulu Varadarajan 				    cmd != CMD_CAPABILITY)
338e327f4e1SJoe Perches 					vdev_neterr(vdev, "Error %d devcmd %d\n",
339373fb087SGovindarajulu Varadarajan 						    err, _CMD_N(cmd));
340373fb087SGovindarajulu Varadarajan 				return -err;
341373fb087SGovindarajulu Varadarajan 			}
342373fb087SGovindarajulu Varadarajan 			if (_CMD_DIR(cmd) & _CMD_DIR_READ)
343373fb087SGovindarajulu Varadarajan 				for (i = 0; i < VNIC_DEVCMD2_NARGS; i++)
344373fb087SGovindarajulu Varadarajan 					vdev->args[i] = result->results[i];
345373fb087SGovindarajulu Varadarajan 
346373fb087SGovindarajulu Varadarajan 			return 0;
347373fb087SGovindarajulu Varadarajan 		}
348373fb087SGovindarajulu Varadarajan 		udelay(100);
349373fb087SGovindarajulu Varadarajan 	}
350373fb087SGovindarajulu Varadarajan 
351e327f4e1SJoe Perches 	vdev_neterr(vdev, "devcmd %d timed out\n", _CMD_N(cmd));
352373fb087SGovindarajulu Varadarajan 
353373fb087SGovindarajulu Varadarajan 	return -ETIMEDOUT;
354373fb087SGovindarajulu Varadarajan }
355373fb087SGovindarajulu Varadarajan 
vnic_dev_init_devcmd1(struct vnic_dev * vdev)356373fb087SGovindarajulu Varadarajan static int vnic_dev_init_devcmd1(struct vnic_dev *vdev)
357373fb087SGovindarajulu Varadarajan {
358373fb087SGovindarajulu Varadarajan 	vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
359373fb087SGovindarajulu Varadarajan 	if (!vdev->devcmd)
360373fb087SGovindarajulu Varadarajan 		return -ENODEV;
361373fb087SGovindarajulu Varadarajan 	vdev->devcmd_rtn = _vnic_dev_cmd;
362373fb087SGovindarajulu Varadarajan 
363373fb087SGovindarajulu Varadarajan 	return 0;
364373fb087SGovindarajulu Varadarajan }
365373fb087SGovindarajulu Varadarajan 
vnic_dev_init_devcmd2(struct vnic_dev * vdev)366373fb087SGovindarajulu Varadarajan static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
367373fb087SGovindarajulu Varadarajan {
368373fb087SGovindarajulu Varadarajan 	int err;
369373fb087SGovindarajulu Varadarajan 	unsigned int fetch_index;
370373fb087SGovindarajulu Varadarajan 
371373fb087SGovindarajulu Varadarajan 	if (vdev->devcmd2)
372373fb087SGovindarajulu Varadarajan 		return 0;
373373fb087SGovindarajulu Varadarajan 
374373fb087SGovindarajulu Varadarajan 	vdev->devcmd2 = kzalloc(sizeof(*vdev->devcmd2), GFP_KERNEL);
375373fb087SGovindarajulu Varadarajan 	if (!vdev->devcmd2)
376373fb087SGovindarajulu Varadarajan 		return -ENOMEM;
377373fb087SGovindarajulu Varadarajan 
378373fb087SGovindarajulu Varadarajan 	vdev->devcmd2->color = 1;
379373fb087SGovindarajulu Varadarajan 	vdev->devcmd2->result_size = DEVCMD2_RING_SIZE;
3803dc33e23SDavid S. Miller 	err = enic_wq_devcmd2_alloc(vdev, &vdev->devcmd2->wq, DEVCMD2_RING_SIZE,
381373fb087SGovindarajulu Varadarajan 				    DEVCMD2_DESC_SIZE);
382373fb087SGovindarajulu Varadarajan 	if (err)
383373fb087SGovindarajulu Varadarajan 		goto err_free_devcmd2;
384373fb087SGovindarajulu Varadarajan 
385373fb087SGovindarajulu Varadarajan 	fetch_index = ioread32(&vdev->devcmd2->wq.ctrl->fetch_index);
386373fb087SGovindarajulu Varadarajan 	if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone  */
387e327f4e1SJoe Perches 		vdev_err(vdev, "Fatal error in devcmd2 init - hardware surprise removal\n");
388fdf99b3fSChristophe Jaillet 		err = -ENODEV;
389fdf99b3fSChristophe Jaillet 		goto err_free_wq;
390373fb087SGovindarajulu Varadarajan 	}
391373fb087SGovindarajulu Varadarajan 
3923dc33e23SDavid S. Miller 	enic_wq_init_start(&vdev->devcmd2->wq, 0, fetch_index, fetch_index, 0,
393373fb087SGovindarajulu Varadarajan 			   0);
394dafc2199SGovindarajulu Varadarajan 	vdev->devcmd2->posted = fetch_index;
395373fb087SGovindarajulu Varadarajan 	vnic_wq_enable(&vdev->devcmd2->wq);
396373fb087SGovindarajulu Varadarajan 
397373fb087SGovindarajulu Varadarajan 	err = vnic_dev_alloc_desc_ring(vdev, &vdev->devcmd2->results_ring,
398373fb087SGovindarajulu Varadarajan 				       DEVCMD2_RING_SIZE, DEVCMD2_DESC_SIZE);
399373fb087SGovindarajulu Varadarajan 	if (err)
400fdf99b3fSChristophe Jaillet 		goto err_disable_wq;
401373fb087SGovindarajulu Varadarajan 
402373fb087SGovindarajulu Varadarajan 	vdev->devcmd2->result = vdev->devcmd2->results_ring.descs;
403373fb087SGovindarajulu Varadarajan 	vdev->devcmd2->cmd_ring = vdev->devcmd2->wq.ring.descs;
404373fb087SGovindarajulu Varadarajan 	vdev->devcmd2->wq_ctrl = vdev->devcmd2->wq.ctrl;
405373fb087SGovindarajulu Varadarajan 	vdev->args[0] = (u64)vdev->devcmd2->results_ring.base_addr |
406373fb087SGovindarajulu Varadarajan 			VNIC_PADDR_TARGET;
407373fb087SGovindarajulu Varadarajan 	vdev->args[1] = DEVCMD2_RING_SIZE;
408373fb087SGovindarajulu Varadarajan 
409373fb087SGovindarajulu Varadarajan 	err = _vnic_dev_cmd2(vdev, CMD_INITIALIZE_DEVCMD2, 1000);
410373fb087SGovindarajulu Varadarajan 	if (err)
411373fb087SGovindarajulu Varadarajan 		goto err_free_desc_ring;
412373fb087SGovindarajulu Varadarajan 
413373fb087SGovindarajulu Varadarajan 	vdev->devcmd_rtn = _vnic_dev_cmd2;
414373fb087SGovindarajulu Varadarajan 
415373fb087SGovindarajulu Varadarajan 	return 0;
416373fb087SGovindarajulu Varadarajan 
417373fb087SGovindarajulu Varadarajan err_free_desc_ring:
418373fb087SGovindarajulu Varadarajan 	vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
419fdf99b3fSChristophe Jaillet err_disable_wq:
420373fb087SGovindarajulu Varadarajan 	vnic_wq_disable(&vdev->devcmd2->wq);
421fdf99b3fSChristophe Jaillet err_free_wq:
422373fb087SGovindarajulu Varadarajan 	vnic_wq_free(&vdev->devcmd2->wq);
423373fb087SGovindarajulu Varadarajan err_free_devcmd2:
424373fb087SGovindarajulu Varadarajan 	kfree(vdev->devcmd2);
425373fb087SGovindarajulu Varadarajan 	vdev->devcmd2 = NULL;
426373fb087SGovindarajulu Varadarajan 
427373fb087SGovindarajulu Varadarajan 	return err;
428373fb087SGovindarajulu Varadarajan }
429373fb087SGovindarajulu Varadarajan 
vnic_dev_deinit_devcmd2(struct vnic_dev * vdev)430373fb087SGovindarajulu Varadarajan static void vnic_dev_deinit_devcmd2(struct vnic_dev *vdev)
431373fb087SGovindarajulu Varadarajan {
432373fb087SGovindarajulu Varadarajan 	vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
433373fb087SGovindarajulu Varadarajan 	vnic_wq_disable(&vdev->devcmd2->wq);
434373fb087SGovindarajulu Varadarajan 	vnic_wq_free(&vdev->devcmd2->wq);
435373fb087SGovindarajulu Varadarajan 	kfree(vdev->devcmd2);
436373fb087SGovindarajulu Varadarajan }
437373fb087SGovindarajulu Varadarajan 
vnic_dev_cmd_proxy(struct vnic_dev * vdev,enum vnic_devcmd_cmd proxy_cmd,enum vnic_devcmd_cmd cmd,u64 * a0,u64 * a1,int wait)438889d13f5SRoopa Prabhu static int vnic_dev_cmd_proxy(struct vnic_dev *vdev,
439889d13f5SRoopa Prabhu 	enum vnic_devcmd_cmd proxy_cmd, enum vnic_devcmd_cmd cmd,
440889d13f5SRoopa Prabhu 	u64 *a0, u64 *a1, int wait)
441a6a5580cSJeff Kirsher {
442a6a5580cSJeff Kirsher 	u32 status;
443a6a5580cSJeff Kirsher 	int err;
444a6a5580cSJeff Kirsher 
445a6a5580cSJeff Kirsher 	memset(vdev->args, 0, sizeof(vdev->args));
446a6a5580cSJeff Kirsher 
447889d13f5SRoopa Prabhu 	vdev->args[0] = vdev->proxy_index;
448a6a5580cSJeff Kirsher 	vdev->args[1] = cmd;
449a6a5580cSJeff Kirsher 	vdev->args[2] = *a0;
450a6a5580cSJeff Kirsher 	vdev->args[3] = *a1;
451a6a5580cSJeff Kirsher 
452373fb087SGovindarajulu Varadarajan 	err = vdev->devcmd_rtn(vdev, proxy_cmd, wait);
453a6a5580cSJeff Kirsher 	if (err)
454a6a5580cSJeff Kirsher 		return err;
455a6a5580cSJeff Kirsher 
456a6a5580cSJeff Kirsher 	status = (u32)vdev->args[0];
457a6a5580cSJeff Kirsher 	if (status & STAT_ERROR) {
458a6a5580cSJeff Kirsher 		err = (int)vdev->args[1];
459a6a5580cSJeff Kirsher 		if (err != ERR_ECMDUNKNOWN ||
460a6a5580cSJeff Kirsher 		    cmd != CMD_CAPABILITY)
461e327f4e1SJoe Perches 			vdev_neterr(vdev, "Error %d proxy devcmd %d\n",
462e327f4e1SJoe Perches 				    err, _CMD_N(cmd));
463a6a5580cSJeff Kirsher 		return err;
464a6a5580cSJeff Kirsher 	}
465a6a5580cSJeff Kirsher 
466a6a5580cSJeff Kirsher 	*a0 = vdev->args[1];
467a6a5580cSJeff Kirsher 	*a1 = vdev->args[2];
468a6a5580cSJeff Kirsher 
469a6a5580cSJeff Kirsher 	return 0;
470a6a5580cSJeff Kirsher }
471a6a5580cSJeff Kirsher 
vnic_dev_cmd_no_proxy(struct vnic_dev * vdev,enum vnic_devcmd_cmd cmd,u64 * a0,u64 * a1,int wait)472a6a5580cSJeff Kirsher static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
473a6a5580cSJeff Kirsher 	enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
474a6a5580cSJeff Kirsher {
475a6a5580cSJeff Kirsher 	int err;
476a6a5580cSJeff Kirsher 
477a6a5580cSJeff Kirsher 	vdev->args[0] = *a0;
478a6a5580cSJeff Kirsher 	vdev->args[1] = *a1;
479a6a5580cSJeff Kirsher 
480373fb087SGovindarajulu Varadarajan 	err = vdev->devcmd_rtn(vdev, cmd, wait);
481a6a5580cSJeff Kirsher 
482a6a5580cSJeff Kirsher 	*a0 = vdev->args[0];
483a6a5580cSJeff Kirsher 	*a1 = vdev->args[1];
484a6a5580cSJeff Kirsher 
485a6a5580cSJeff Kirsher 	return err;
486a6a5580cSJeff Kirsher }
487a6a5580cSJeff Kirsher 
vnic_dev_cmd_proxy_by_index_start(struct vnic_dev * vdev,u16 index)488889d13f5SRoopa Prabhu void vnic_dev_cmd_proxy_by_index_start(struct vnic_dev *vdev, u16 index)
489889d13f5SRoopa Prabhu {
490889d13f5SRoopa Prabhu 	vdev->proxy = PROXY_BY_INDEX;
491889d13f5SRoopa Prabhu 	vdev->proxy_index = index;
492889d13f5SRoopa Prabhu }
493889d13f5SRoopa Prabhu 
vnic_dev_cmd_proxy_end(struct vnic_dev * vdev)494889d13f5SRoopa Prabhu void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev)
495889d13f5SRoopa Prabhu {
496889d13f5SRoopa Prabhu 	vdev->proxy = PROXY_NONE;
497889d13f5SRoopa Prabhu 	vdev->proxy_index = 0;
498889d13f5SRoopa Prabhu }
499889d13f5SRoopa Prabhu 
vnic_dev_cmd(struct vnic_dev * vdev,enum vnic_devcmd_cmd cmd,u64 * a0,u64 * a1,int wait)500a6a5580cSJeff Kirsher int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
501a6a5580cSJeff Kirsher 	u64 *a0, u64 *a1, int wait)
502a6a5580cSJeff Kirsher {
503a6a5580cSJeff Kirsher 	memset(vdev->args, 0, sizeof(vdev->args));
504a6a5580cSJeff Kirsher 
505a6a5580cSJeff Kirsher 	switch (vdev->proxy) {
506889d13f5SRoopa Prabhu 	case PROXY_BY_INDEX:
507889d13f5SRoopa Prabhu 		return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_INDEX, cmd,
508889d13f5SRoopa Prabhu 				a0, a1, wait);
509a6a5580cSJeff Kirsher 	case PROXY_BY_BDF:
510889d13f5SRoopa Prabhu 		return vnic_dev_cmd_proxy(vdev, CMD_PROXY_BY_BDF, cmd,
511889d13f5SRoopa Prabhu 				a0, a1, wait);
512a6a5580cSJeff Kirsher 	case PROXY_NONE:
513a6a5580cSJeff Kirsher 	default:
514a6a5580cSJeff Kirsher 		return vnic_dev_cmd_no_proxy(vdev, cmd, a0, a1, wait);
515a6a5580cSJeff Kirsher 	}
516a6a5580cSJeff Kirsher }
517a6a5580cSJeff Kirsher 
vnic_dev_capable(struct vnic_dev * vdev,enum vnic_devcmd_cmd cmd)518a6a5580cSJeff Kirsher static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
519a6a5580cSJeff Kirsher {
520a6a5580cSJeff Kirsher 	u64 a0 = (u32)cmd, a1 = 0;
521a6a5580cSJeff Kirsher 	int wait = 1000;
522a6a5580cSJeff Kirsher 	int err;
523a6a5580cSJeff Kirsher 
524a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
525a6a5580cSJeff Kirsher 
526a6a5580cSJeff Kirsher 	return !(err || a0);
527a6a5580cSJeff Kirsher }
528a6a5580cSJeff Kirsher 
vnic_dev_fw_info(struct vnic_dev * vdev,struct vnic_devcmd_fw_info ** fw_info)529a6a5580cSJeff Kirsher int vnic_dev_fw_info(struct vnic_dev *vdev,
530a6a5580cSJeff Kirsher 	struct vnic_devcmd_fw_info **fw_info)
531a6a5580cSJeff Kirsher {
532a6a5580cSJeff Kirsher 	u64 a0, a1 = 0;
533a6a5580cSJeff Kirsher 	int wait = 1000;
534a6a5580cSJeff Kirsher 	int err = 0;
535a6a5580cSJeff Kirsher 
536a6a5580cSJeff Kirsher 	if (!vdev->fw_info) {
53702a20d4fSChristophe JAILLET 		vdev->fw_info = dma_alloc_coherent(&vdev->pdev->dev,
538a6a5580cSJeff Kirsher 						   sizeof(struct vnic_devcmd_fw_info),
53902a20d4fSChristophe JAILLET 						   &vdev->fw_info_pa, GFP_ATOMIC);
540a6a5580cSJeff Kirsher 		if (!vdev->fw_info)
541a6a5580cSJeff Kirsher 			return -ENOMEM;
542a6a5580cSJeff Kirsher 
543a6a5580cSJeff Kirsher 		a0 = vdev->fw_info_pa;
544a6a5580cSJeff Kirsher 		a1 = sizeof(struct vnic_devcmd_fw_info);
545a6a5580cSJeff Kirsher 
546a6a5580cSJeff Kirsher 		/* only get fw_info once and cache it */
547f8a6dd59SNeel Patel 		if (vnic_dev_capable(vdev, CMD_MCPU_FW_INFO))
548f8a6dd59SNeel Patel 			err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO,
549f8a6dd59SNeel Patel 				&a0, &a1, wait);
550f8a6dd59SNeel Patel 		else
551a6a5580cSJeff Kirsher 			err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO_OLD,
552a6a5580cSJeff Kirsher 				&a0, &a1, wait);
553a6a5580cSJeff Kirsher 	}
554a6a5580cSJeff Kirsher 
555a6a5580cSJeff Kirsher 	*fw_info = vdev->fw_info;
556a6a5580cSJeff Kirsher 
557a6a5580cSJeff Kirsher 	return err;
558a6a5580cSJeff Kirsher }
559a6a5580cSJeff Kirsher 
vnic_dev_spec(struct vnic_dev * vdev,unsigned int offset,unsigned int size,void * value)560a6a5580cSJeff Kirsher int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
561a6a5580cSJeff Kirsher 	void *value)
562a6a5580cSJeff Kirsher {
563a6a5580cSJeff Kirsher 	u64 a0, a1;
564a6a5580cSJeff Kirsher 	int wait = 1000;
565a6a5580cSJeff Kirsher 	int err;
566a6a5580cSJeff Kirsher 
567a6a5580cSJeff Kirsher 	a0 = offset;
568a6a5580cSJeff Kirsher 	a1 = size;
569a6a5580cSJeff Kirsher 
570a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait);
571a6a5580cSJeff Kirsher 
572a6a5580cSJeff Kirsher 	switch (size) {
573a6a5580cSJeff Kirsher 	case 1: *(u8 *)value = (u8)a0; break;
574a6a5580cSJeff Kirsher 	case 2: *(u16 *)value = (u16)a0; break;
575a6a5580cSJeff Kirsher 	case 4: *(u32 *)value = (u32)a0; break;
576a6a5580cSJeff Kirsher 	case 8: *(u64 *)value = a0; break;
577a6a5580cSJeff Kirsher 	default: BUG(); break;
578a6a5580cSJeff Kirsher 	}
579a6a5580cSJeff Kirsher 
580a6a5580cSJeff Kirsher 	return err;
581a6a5580cSJeff Kirsher }
582a6a5580cSJeff Kirsher 
vnic_dev_stats_dump(struct vnic_dev * vdev,struct vnic_stats ** stats)583a6a5580cSJeff Kirsher int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
584a6a5580cSJeff Kirsher {
585a6a5580cSJeff Kirsher 	u64 a0, a1;
586a6a5580cSJeff Kirsher 	int wait = 1000;
587a6a5580cSJeff Kirsher 
588a6a5580cSJeff Kirsher 	if (!vdev->stats) {
58902a20d4fSChristophe JAILLET 		vdev->stats = dma_alloc_coherent(&vdev->pdev->dev,
59002a20d4fSChristophe JAILLET 						 sizeof(struct vnic_stats),
59102a20d4fSChristophe JAILLET 						 &vdev->stats_pa, GFP_ATOMIC);
592a6a5580cSJeff Kirsher 		if (!vdev->stats)
593a6a5580cSJeff Kirsher 			return -ENOMEM;
594a6a5580cSJeff Kirsher 	}
595a6a5580cSJeff Kirsher 
596a6a5580cSJeff Kirsher 	*stats = vdev->stats;
597a6a5580cSJeff Kirsher 	a0 = vdev->stats_pa;
598a6a5580cSJeff Kirsher 	a1 = sizeof(struct vnic_stats);
599a6a5580cSJeff Kirsher 
600a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
601a6a5580cSJeff Kirsher }
602a6a5580cSJeff Kirsher 
vnic_dev_close(struct vnic_dev * vdev)603a6a5580cSJeff Kirsher int vnic_dev_close(struct vnic_dev *vdev)
604a6a5580cSJeff Kirsher {
605a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
606a6a5580cSJeff Kirsher 	int wait = 1000;
607a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
608a6a5580cSJeff Kirsher }
609a6a5580cSJeff Kirsher 
vnic_dev_enable_wait(struct vnic_dev * vdev)610a6a5580cSJeff Kirsher int vnic_dev_enable_wait(struct vnic_dev *vdev)
611a6a5580cSJeff Kirsher {
612a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
613a6a5580cSJeff Kirsher 	int wait = 1000;
614a6a5580cSJeff Kirsher 
615f8a6dd59SNeel Patel 	if (vnic_dev_capable(vdev, CMD_ENABLE_WAIT))
616f8a6dd59SNeel Patel 		return vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
617f8a6dd59SNeel Patel 	else
618a6a5580cSJeff Kirsher 		return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
619a6a5580cSJeff Kirsher }
620a6a5580cSJeff Kirsher 
vnic_dev_disable(struct vnic_dev * vdev)621a6a5580cSJeff Kirsher int vnic_dev_disable(struct vnic_dev *vdev)
622a6a5580cSJeff Kirsher {
623a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
624a6a5580cSJeff Kirsher 	int wait = 1000;
625a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait);
626a6a5580cSJeff Kirsher }
627a6a5580cSJeff Kirsher 
vnic_dev_open(struct vnic_dev * vdev,int arg)628a6a5580cSJeff Kirsher int vnic_dev_open(struct vnic_dev *vdev, int arg)
629a6a5580cSJeff Kirsher {
630a6a5580cSJeff Kirsher 	u64 a0 = (u32)arg, a1 = 0;
631a6a5580cSJeff Kirsher 	int wait = 1000;
632a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait);
633a6a5580cSJeff Kirsher }
634a6a5580cSJeff Kirsher 
vnic_dev_open_done(struct vnic_dev * vdev,int * done)635a6a5580cSJeff Kirsher int vnic_dev_open_done(struct vnic_dev *vdev, int *done)
636a6a5580cSJeff Kirsher {
637a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
638a6a5580cSJeff Kirsher 	int wait = 1000;
639a6a5580cSJeff Kirsher 	int err;
640a6a5580cSJeff Kirsher 
641a6a5580cSJeff Kirsher 	*done = 0;
642a6a5580cSJeff Kirsher 
643a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
644a6a5580cSJeff Kirsher 	if (err)
645a6a5580cSJeff Kirsher 		return err;
646a6a5580cSJeff Kirsher 
647a6a5580cSJeff Kirsher 	*done = (a0 == 0);
648a6a5580cSJeff Kirsher 
649a6a5580cSJeff Kirsher 	return 0;
650a6a5580cSJeff Kirsher }
651a6a5580cSJeff Kirsher 
vnic_dev_soft_reset(struct vnic_dev * vdev,int arg)652937317c7SGovindarajulu Varadarajan int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
653a6a5580cSJeff Kirsher {
654a6a5580cSJeff Kirsher 	u64 a0 = (u32)arg, a1 = 0;
655a6a5580cSJeff Kirsher 	int wait = 1000;
656a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
657a6a5580cSJeff Kirsher }
658a6a5580cSJeff Kirsher 
vnic_dev_soft_reset_done(struct vnic_dev * vdev,int * done)659937317c7SGovindarajulu Varadarajan int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
660a6a5580cSJeff Kirsher {
661a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
662a6a5580cSJeff Kirsher 	int wait = 1000;
663a6a5580cSJeff Kirsher 	int err;
664a6a5580cSJeff Kirsher 
665a6a5580cSJeff Kirsher 	*done = 0;
666a6a5580cSJeff Kirsher 
667a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_SOFT_RESET_STATUS, &a0, &a1, wait);
668a6a5580cSJeff Kirsher 	if (err)
669a6a5580cSJeff Kirsher 		return err;
670a6a5580cSJeff Kirsher 
671a6a5580cSJeff Kirsher 	*done = (a0 == 0);
672a6a5580cSJeff Kirsher 
673a6a5580cSJeff Kirsher 	return 0;
674a6a5580cSJeff Kirsher }
675a6a5580cSJeff Kirsher 
vnic_dev_hang_reset(struct vnic_dev * vdev,int arg)676a6a5580cSJeff Kirsher int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg)
677a6a5580cSJeff Kirsher {
678a6a5580cSJeff Kirsher 	u64 a0 = (u32)arg, a1 = 0;
679a6a5580cSJeff Kirsher 	int wait = 1000;
680a6a5580cSJeff Kirsher 	int err;
681a6a5580cSJeff Kirsher 
682f8a6dd59SNeel Patel 	if (vnic_dev_capable(vdev, CMD_HANG_RESET)) {
683f8a6dd59SNeel Patel 		return vnic_dev_cmd(vdev, CMD_HANG_RESET,
684f8a6dd59SNeel Patel 				&a0, &a1, wait);
685f8a6dd59SNeel Patel 	} else {
686a6a5580cSJeff Kirsher 		err = vnic_dev_soft_reset(vdev, arg);
687a6a5580cSJeff Kirsher 		if (err)
688a6a5580cSJeff Kirsher 			return err;
689a6a5580cSJeff Kirsher 		return vnic_dev_init(vdev, 0);
690a6a5580cSJeff Kirsher 	}
691a6a5580cSJeff Kirsher }
692a6a5580cSJeff Kirsher 
vnic_dev_hang_reset_done(struct vnic_dev * vdev,int * done)693a6a5580cSJeff Kirsher int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done)
694a6a5580cSJeff Kirsher {
695a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
696a6a5580cSJeff Kirsher 	int wait = 1000;
697a6a5580cSJeff Kirsher 	int err;
698a6a5580cSJeff Kirsher 
699a6a5580cSJeff Kirsher 	*done = 0;
700a6a5580cSJeff Kirsher 
701f8a6dd59SNeel Patel 	if (vnic_dev_capable(vdev, CMD_HANG_RESET_STATUS)) {
702f8a6dd59SNeel Patel 		err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS,
703f8a6dd59SNeel Patel 				&a0, &a1, wait);
704f8a6dd59SNeel Patel 		if (err)
705a6a5580cSJeff Kirsher 			return err;
706f8a6dd59SNeel Patel 	} else {
707f8a6dd59SNeel Patel 		return vnic_dev_soft_reset_done(vdev, done);
708a6a5580cSJeff Kirsher 	}
709a6a5580cSJeff Kirsher 
710a6a5580cSJeff Kirsher 	*done = (a0 == 0);
711a6a5580cSJeff Kirsher 
712a6a5580cSJeff Kirsher 	return 0;
713a6a5580cSJeff Kirsher }
714a6a5580cSJeff Kirsher 
vnic_dev_hang_notify(struct vnic_dev * vdev)715a6a5580cSJeff Kirsher int vnic_dev_hang_notify(struct vnic_dev *vdev)
716a6a5580cSJeff Kirsher {
717a6a5580cSJeff Kirsher 	u64 a0, a1;
718a6a5580cSJeff Kirsher 	int wait = 1000;
719a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
720a6a5580cSJeff Kirsher }
721a6a5580cSJeff Kirsher 
vnic_dev_get_mac_addr(struct vnic_dev * vdev,u8 * mac_addr)722b13423eeSRoopa Prabhu int vnic_dev_get_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
723a6a5580cSJeff Kirsher {
724a6a5580cSJeff Kirsher 	u64 a0, a1;
725a6a5580cSJeff Kirsher 	int wait = 1000;
726a6a5580cSJeff Kirsher 	int err, i;
727a6a5580cSJeff Kirsher 
728a6a5580cSJeff Kirsher 	for (i = 0; i < ETH_ALEN; i++)
729a6a5580cSJeff Kirsher 		mac_addr[i] = 0;
730a6a5580cSJeff Kirsher 
731b13423eeSRoopa Prabhu 	err = vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
732a6a5580cSJeff Kirsher 	if (err)
733a6a5580cSJeff Kirsher 		return err;
734a6a5580cSJeff Kirsher 
735a6a5580cSJeff Kirsher 	for (i = 0; i < ETH_ALEN; i++)
736a6a5580cSJeff Kirsher 		mac_addr[i] = ((u8 *)&a0)[i];
737a6a5580cSJeff Kirsher 
738a6a5580cSJeff Kirsher 	return 0;
739a6a5580cSJeff Kirsher }
740a6a5580cSJeff Kirsher 
vnic_dev_packet_filter(struct vnic_dev * vdev,int directed,int multicast,int broadcast,int promisc,int allmulti)741a6a5580cSJeff Kirsher int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
742a6a5580cSJeff Kirsher 	int broadcast, int promisc, int allmulti)
743a6a5580cSJeff Kirsher {
744a6a5580cSJeff Kirsher 	u64 a0, a1 = 0;
745a6a5580cSJeff Kirsher 	int wait = 1000;
746a6a5580cSJeff Kirsher 	int err;
747a6a5580cSJeff Kirsher 
748a6a5580cSJeff Kirsher 	a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
749a6a5580cSJeff Kirsher 	     (multicast ? CMD_PFILTER_MULTICAST : 0) |
750a6a5580cSJeff Kirsher 	     (broadcast ? CMD_PFILTER_BROADCAST : 0) |
751a6a5580cSJeff Kirsher 	     (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
752a6a5580cSJeff Kirsher 	     (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
753a6a5580cSJeff Kirsher 
754a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait);
755a6a5580cSJeff Kirsher 	if (err)
756e327f4e1SJoe Perches 		vdev_neterr(vdev, "Can't set packet filter\n");
757a6a5580cSJeff Kirsher 
758a6a5580cSJeff Kirsher 	return err;
759a6a5580cSJeff Kirsher }
760a6a5580cSJeff Kirsher 
vnic_dev_add_addr(struct vnic_dev * vdev,const u8 * addr)761f009618aSAlexander Duyck int vnic_dev_add_addr(struct vnic_dev *vdev, const u8 *addr)
762a6a5580cSJeff Kirsher {
763a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
764a6a5580cSJeff Kirsher 	int wait = 1000;
765a6a5580cSJeff Kirsher 	int err;
766a6a5580cSJeff Kirsher 	int i;
767a6a5580cSJeff Kirsher 
768a6a5580cSJeff Kirsher 	for (i = 0; i < ETH_ALEN; i++)
769a6a5580cSJeff Kirsher 		((u8 *)&a0)[i] = addr[i];
770a6a5580cSJeff Kirsher 
771a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
772a6a5580cSJeff Kirsher 	if (err)
773e327f4e1SJoe Perches 		vdev_neterr(vdev, "Can't add addr [%pM], %d\n", addr, err);
774a6a5580cSJeff Kirsher 
775a6a5580cSJeff Kirsher 	return err;
776a6a5580cSJeff Kirsher }
777a6a5580cSJeff Kirsher 
vnic_dev_del_addr(struct vnic_dev * vdev,const u8 * addr)778f009618aSAlexander Duyck int vnic_dev_del_addr(struct vnic_dev *vdev, const u8 *addr)
779a6a5580cSJeff Kirsher {
780a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
781a6a5580cSJeff Kirsher 	int wait = 1000;
782a6a5580cSJeff Kirsher 	int err;
783a6a5580cSJeff Kirsher 	int i;
784a6a5580cSJeff Kirsher 
785a6a5580cSJeff Kirsher 	for (i = 0; i < ETH_ALEN; i++)
786a6a5580cSJeff Kirsher 		((u8 *)&a0)[i] = addr[i];
787a6a5580cSJeff Kirsher 
788a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
789a6a5580cSJeff Kirsher 	if (err)
790e327f4e1SJoe Perches 		vdev_neterr(vdev, "Can't del addr [%pM], %d\n", addr, err);
791a6a5580cSJeff Kirsher 
792a6a5580cSJeff Kirsher 	return err;
793a6a5580cSJeff Kirsher }
794a6a5580cSJeff Kirsher 
vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev * vdev,u8 ig_vlan_rewrite_mode)795a6a5580cSJeff Kirsher int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev,
796a6a5580cSJeff Kirsher 	u8 ig_vlan_rewrite_mode)
797a6a5580cSJeff Kirsher {
798a6a5580cSJeff Kirsher 	u64 a0 = ig_vlan_rewrite_mode, a1 = 0;
799a6a5580cSJeff Kirsher 	int wait = 1000;
800a6a5580cSJeff Kirsher 
801f8a6dd59SNeel Patel 	if (vnic_dev_capable(vdev, CMD_IG_VLAN_REWRITE_MODE))
802f8a6dd59SNeel Patel 		return vnic_dev_cmd(vdev, CMD_IG_VLAN_REWRITE_MODE,
803f8a6dd59SNeel Patel 				&a0, &a1, wait);
804f8a6dd59SNeel Patel 	else
805a6a5580cSJeff Kirsher 		return 0;
806a6a5580cSJeff Kirsher }
807a6a5580cSJeff Kirsher 
vnic_dev_notify_setcmd(struct vnic_dev * vdev,void * notify_addr,dma_addr_t notify_pa,u16 intr)808a6a5580cSJeff Kirsher static int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
809a6a5580cSJeff Kirsher 	void *notify_addr, dma_addr_t notify_pa, u16 intr)
810a6a5580cSJeff Kirsher {
811a6a5580cSJeff Kirsher 	u64 a0, a1;
812a6a5580cSJeff Kirsher 	int wait = 1000;
813a6a5580cSJeff Kirsher 	int r;
814a6a5580cSJeff Kirsher 
815a6a5580cSJeff Kirsher 	memset(notify_addr, 0, sizeof(struct vnic_devcmd_notify));
816a6a5580cSJeff Kirsher 	vdev->notify = notify_addr;
817a6a5580cSJeff Kirsher 	vdev->notify_pa = notify_pa;
818a6a5580cSJeff Kirsher 
819a6a5580cSJeff Kirsher 	a0 = (u64)notify_pa;
820a6a5580cSJeff Kirsher 	a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
821a6a5580cSJeff Kirsher 	a1 += sizeof(struct vnic_devcmd_notify);
822a6a5580cSJeff Kirsher 
823a6a5580cSJeff Kirsher 	r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
824a6a5580cSJeff Kirsher 	vdev->notify_sz = (r == 0) ? (u32)a1 : 0;
825a6a5580cSJeff Kirsher 	return r;
826a6a5580cSJeff Kirsher }
827a6a5580cSJeff Kirsher 
vnic_dev_notify_set(struct vnic_dev * vdev,u16 intr)828a6a5580cSJeff Kirsher int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
829a6a5580cSJeff Kirsher {
830a6a5580cSJeff Kirsher 	void *notify_addr;
831a6a5580cSJeff Kirsher 	dma_addr_t notify_pa;
832a6a5580cSJeff Kirsher 
833a6a5580cSJeff Kirsher 	if (vdev->notify || vdev->notify_pa) {
834e327f4e1SJoe Perches 		vdev_neterr(vdev, "notify block %p still allocated\n",
835e327f4e1SJoe Perches 			    vdev->notify);
836a6a5580cSJeff Kirsher 		return -EINVAL;
837a6a5580cSJeff Kirsher 	}
838a6a5580cSJeff Kirsher 
83902a20d4fSChristophe JAILLET 	notify_addr = dma_alloc_coherent(&vdev->pdev->dev,
840a6a5580cSJeff Kirsher 					 sizeof(struct vnic_devcmd_notify),
84102a20d4fSChristophe JAILLET 					 &notify_pa, GFP_ATOMIC);
842a6a5580cSJeff Kirsher 	if (!notify_addr)
843a6a5580cSJeff Kirsher 		return -ENOMEM;
844a6a5580cSJeff Kirsher 
845a6a5580cSJeff Kirsher 	return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr);
846a6a5580cSJeff Kirsher }
847a6a5580cSJeff Kirsher 
vnic_dev_notify_unsetcmd(struct vnic_dev * vdev)848a6a5580cSJeff Kirsher static int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
849a6a5580cSJeff Kirsher {
850a6a5580cSJeff Kirsher 	u64 a0, a1;
851a6a5580cSJeff Kirsher 	int wait = 1000;
852a6a5580cSJeff Kirsher 	int err;
853a6a5580cSJeff Kirsher 
854a6a5580cSJeff Kirsher 	a0 = 0;  /* paddr = 0 to unset notify buffer */
855a6a5580cSJeff Kirsher 	a1 = 0x0000ffff00000000ULL; /* intr num = -1 to unreg for intr */
856a6a5580cSJeff Kirsher 	a1 += sizeof(struct vnic_devcmd_notify);
857a6a5580cSJeff Kirsher 
858a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
859a6a5580cSJeff Kirsher 	vdev->notify = NULL;
860a6a5580cSJeff Kirsher 	vdev->notify_pa = 0;
861a6a5580cSJeff Kirsher 	vdev->notify_sz = 0;
862a6a5580cSJeff Kirsher 
863a6a5580cSJeff Kirsher 	return err;
864a6a5580cSJeff Kirsher }
865a6a5580cSJeff Kirsher 
vnic_dev_notify_unset(struct vnic_dev * vdev)866a6a5580cSJeff Kirsher int vnic_dev_notify_unset(struct vnic_dev *vdev)
867a6a5580cSJeff Kirsher {
868a6a5580cSJeff Kirsher 	if (vdev->notify) {
86902a20d4fSChristophe JAILLET 		dma_free_coherent(&vdev->pdev->dev,
870a6a5580cSJeff Kirsher 				  sizeof(struct vnic_devcmd_notify),
87102a20d4fSChristophe JAILLET 				  vdev->notify, vdev->notify_pa);
872a6a5580cSJeff Kirsher 	}
873a6a5580cSJeff Kirsher 
874a6a5580cSJeff Kirsher 	return vnic_dev_notify_unsetcmd(vdev);
875a6a5580cSJeff Kirsher }
876a6a5580cSJeff Kirsher 
vnic_dev_notify_ready(struct vnic_dev * vdev)877a6a5580cSJeff Kirsher static int vnic_dev_notify_ready(struct vnic_dev *vdev)
878a6a5580cSJeff Kirsher {
879a6a5580cSJeff Kirsher 	u32 *words;
880a6a5580cSJeff Kirsher 	unsigned int nwords = vdev->notify_sz / 4;
881a6a5580cSJeff Kirsher 	unsigned int i;
882a6a5580cSJeff Kirsher 	u32 csum;
883a6a5580cSJeff Kirsher 
884a6a5580cSJeff Kirsher 	if (!vdev->notify || !vdev->notify_sz)
885a6a5580cSJeff Kirsher 		return 0;
886a6a5580cSJeff Kirsher 
887a6a5580cSJeff Kirsher 	do {
888a6a5580cSJeff Kirsher 		csum = 0;
889a6a5580cSJeff Kirsher 		memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz);
890a6a5580cSJeff Kirsher 		words = (u32 *)&vdev->notify_copy;
891a6a5580cSJeff Kirsher 		for (i = 1; i < nwords; i++)
892a6a5580cSJeff Kirsher 			csum += words[i];
893a6a5580cSJeff Kirsher 	} while (csum != words[0]);
894a6a5580cSJeff Kirsher 
895a6a5580cSJeff Kirsher 	return 1;
896a6a5580cSJeff Kirsher }
897a6a5580cSJeff Kirsher 
vnic_dev_init(struct vnic_dev * vdev,int arg)898a6a5580cSJeff Kirsher int vnic_dev_init(struct vnic_dev *vdev, int arg)
899a6a5580cSJeff Kirsher {
900a6a5580cSJeff Kirsher 	u64 a0 = (u32)arg, a1 = 0;
901a6a5580cSJeff Kirsher 	int wait = 1000;
902a6a5580cSJeff Kirsher 	int r = 0;
903a6a5580cSJeff Kirsher 
904a6a5580cSJeff Kirsher 	if (vnic_dev_capable(vdev, CMD_INIT))
905a6a5580cSJeff Kirsher 		r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
906a6a5580cSJeff Kirsher 	else {
907a6a5580cSJeff Kirsher 		vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
908a6a5580cSJeff Kirsher 		if (a0 & CMD_INITF_DEFAULT_MAC) {
909a6a5580cSJeff Kirsher 			/* Emulate these for old CMD_INIT_v1 which
910a6a5580cSJeff Kirsher 			 * didn't pass a0 so no CMD_INITF_*.
911a6a5580cSJeff Kirsher 			 */
912b13423eeSRoopa Prabhu 			vnic_dev_cmd(vdev, CMD_GET_MAC_ADDR, &a0, &a1, wait);
913a6a5580cSJeff Kirsher 			vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
914a6a5580cSJeff Kirsher 		}
915a6a5580cSJeff Kirsher 	}
916a6a5580cSJeff Kirsher 	return r;
917a6a5580cSJeff Kirsher }
918a6a5580cSJeff Kirsher 
vnic_dev_deinit(struct vnic_dev * vdev)919a6a5580cSJeff Kirsher int vnic_dev_deinit(struct vnic_dev *vdev)
920a6a5580cSJeff Kirsher {
921a6a5580cSJeff Kirsher 	u64 a0 = 0, a1 = 0;
922a6a5580cSJeff Kirsher 	int wait = 1000;
923a6a5580cSJeff Kirsher 
924a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait);
925a6a5580cSJeff Kirsher }
926a6a5580cSJeff Kirsher 
vnic_dev_intr_coal_timer_info_default(struct vnic_dev * vdev)927a6a5580cSJeff Kirsher void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev)
928a6a5580cSJeff Kirsher {
929a6a5580cSJeff Kirsher 	/* Default: hardware intr coal timer is in units of 1.5 usecs */
930a6a5580cSJeff Kirsher 	vdev->intr_coal_timer_info.mul = 2;
931a6a5580cSJeff Kirsher 	vdev->intr_coal_timer_info.div = 3;
932a6a5580cSJeff Kirsher 	vdev->intr_coal_timer_info.max_usec =
933a6a5580cSJeff Kirsher 		vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff);
934a6a5580cSJeff Kirsher }
935a6a5580cSJeff Kirsher 
vnic_dev_intr_coal_timer_info(struct vnic_dev * vdev)936a6a5580cSJeff Kirsher int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev)
937a6a5580cSJeff Kirsher {
938a6a5580cSJeff Kirsher 	int wait = 1000;
939a6a5580cSJeff Kirsher 	int err;
940a6a5580cSJeff Kirsher 
941a6a5580cSJeff Kirsher 	memset(vdev->args, 0, sizeof(vdev->args));
942a6a5580cSJeff Kirsher 
943f8a6dd59SNeel Patel 	if (vnic_dev_capable(vdev, CMD_INTR_COAL_CONVERT))
944373fb087SGovindarajulu Varadarajan 		err = vdev->devcmd_rtn(vdev, CMD_INTR_COAL_CONVERT, wait);
945f8a6dd59SNeel Patel 	else
946f8a6dd59SNeel Patel 		err = ERR_ECMDUNKNOWN;
947a6a5580cSJeff Kirsher 
948a6a5580cSJeff Kirsher 	/* Use defaults when firmware doesn't support the devcmd at all or
949a6a5580cSJeff Kirsher 	 * supports it for only specific hardware
950a6a5580cSJeff Kirsher 	 */
951a6a5580cSJeff Kirsher 	if ((err == ERR_ECMDUNKNOWN) ||
952a6a5580cSJeff Kirsher 		(!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) {
953e327f4e1SJoe Perches 		vdev_netwarn(vdev, "Using default conversion factor for interrupt coalesce timer\n");
954a6a5580cSJeff Kirsher 		vnic_dev_intr_coal_timer_info_default(vdev);
955a6a5580cSJeff Kirsher 		return 0;
956a6a5580cSJeff Kirsher 	}
957a6a5580cSJeff Kirsher 
958f8a6dd59SNeel Patel 	if (!err) {
959a6a5580cSJeff Kirsher 		vdev->intr_coal_timer_info.mul = (u32) vdev->args[0];
960a6a5580cSJeff Kirsher 		vdev->intr_coal_timer_info.div = (u32) vdev->args[1];
961a6a5580cSJeff Kirsher 		vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2];
962f8a6dd59SNeel Patel 	}
963a6a5580cSJeff Kirsher 
964a6a5580cSJeff Kirsher 	return err;
965a6a5580cSJeff Kirsher }
966a6a5580cSJeff Kirsher 
vnic_dev_link_status(struct vnic_dev * vdev)967a6a5580cSJeff Kirsher int vnic_dev_link_status(struct vnic_dev *vdev)
968a6a5580cSJeff Kirsher {
969a6a5580cSJeff Kirsher 	if (!vnic_dev_notify_ready(vdev))
970a6a5580cSJeff Kirsher 		return 0;
971a6a5580cSJeff Kirsher 
972a6a5580cSJeff Kirsher 	return vdev->notify_copy.link_state;
973a6a5580cSJeff Kirsher }
974a6a5580cSJeff Kirsher 
vnic_dev_port_speed(struct vnic_dev * vdev)975a6a5580cSJeff Kirsher u32 vnic_dev_port_speed(struct vnic_dev *vdev)
976a6a5580cSJeff Kirsher {
977a6a5580cSJeff Kirsher 	if (!vnic_dev_notify_ready(vdev))
978a6a5580cSJeff Kirsher 		return 0;
979a6a5580cSJeff Kirsher 
980a6a5580cSJeff Kirsher 	return vdev->notify_copy.port_speed;
981a6a5580cSJeff Kirsher }
982a6a5580cSJeff Kirsher 
vnic_dev_msg_lvl(struct vnic_dev * vdev)983a6a5580cSJeff Kirsher u32 vnic_dev_msg_lvl(struct vnic_dev *vdev)
984a6a5580cSJeff Kirsher {
985a6a5580cSJeff Kirsher 	if (!vnic_dev_notify_ready(vdev))
986a6a5580cSJeff Kirsher 		return 0;
987a6a5580cSJeff Kirsher 
988a6a5580cSJeff Kirsher 	return vdev->notify_copy.msglvl;
989a6a5580cSJeff Kirsher }
990a6a5580cSJeff Kirsher 
vnic_dev_mtu(struct vnic_dev * vdev)991a6a5580cSJeff Kirsher u32 vnic_dev_mtu(struct vnic_dev *vdev)
992a6a5580cSJeff Kirsher {
993a6a5580cSJeff Kirsher 	if (!vnic_dev_notify_ready(vdev))
994a6a5580cSJeff Kirsher 		return 0;
995a6a5580cSJeff Kirsher 
996a6a5580cSJeff Kirsher 	return vdev->notify_copy.mtu;
997a6a5580cSJeff Kirsher }
998a6a5580cSJeff Kirsher 
vnic_dev_set_intr_mode(struct vnic_dev * vdev,enum vnic_dev_intr_mode intr_mode)999a6a5580cSJeff Kirsher void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
1000a6a5580cSJeff Kirsher 	enum vnic_dev_intr_mode intr_mode)
1001a6a5580cSJeff Kirsher {
1002a6a5580cSJeff Kirsher 	vdev->intr_mode = intr_mode;
1003a6a5580cSJeff Kirsher }
1004a6a5580cSJeff Kirsher 
vnic_dev_get_intr_mode(struct vnic_dev * vdev)1005a6a5580cSJeff Kirsher enum vnic_dev_intr_mode vnic_dev_get_intr_mode(
1006a6a5580cSJeff Kirsher 	struct vnic_dev *vdev)
1007a6a5580cSJeff Kirsher {
1008a6a5580cSJeff Kirsher 	return vdev->intr_mode;
1009a6a5580cSJeff Kirsher }
1010a6a5580cSJeff Kirsher 
vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev * vdev,u32 usec)1011a6a5580cSJeff Kirsher u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec)
1012a6a5580cSJeff Kirsher {
1013a6a5580cSJeff Kirsher 	return (usec * vdev->intr_coal_timer_info.mul) /
1014a6a5580cSJeff Kirsher 		vdev->intr_coal_timer_info.div;
1015a6a5580cSJeff Kirsher }
1016a6a5580cSJeff Kirsher 
vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev * vdev,u32 hw_cycles)1017a6a5580cSJeff Kirsher u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles)
1018a6a5580cSJeff Kirsher {
1019a6a5580cSJeff Kirsher 	return (hw_cycles * vdev->intr_coal_timer_info.div) /
1020a6a5580cSJeff Kirsher 		vdev->intr_coal_timer_info.mul;
1021a6a5580cSJeff Kirsher }
1022a6a5580cSJeff Kirsher 
vnic_dev_get_intr_coal_timer_max(struct vnic_dev * vdev)1023a6a5580cSJeff Kirsher u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev)
1024a6a5580cSJeff Kirsher {
1025a6a5580cSJeff Kirsher 	return vdev->intr_coal_timer_info.max_usec;
1026a6a5580cSJeff Kirsher }
1027a6a5580cSJeff Kirsher 
vnic_dev_unregister(struct vnic_dev * vdev)1028a6a5580cSJeff Kirsher void vnic_dev_unregister(struct vnic_dev *vdev)
1029a6a5580cSJeff Kirsher {
1030a6a5580cSJeff Kirsher 	if (vdev) {
1031a6a5580cSJeff Kirsher 		if (vdev->notify)
103202a20d4fSChristophe JAILLET 			dma_free_coherent(&vdev->pdev->dev,
1033a6a5580cSJeff Kirsher 					  sizeof(struct vnic_devcmd_notify),
103402a20d4fSChristophe JAILLET 					  vdev->notify, vdev->notify_pa);
1035a6a5580cSJeff Kirsher 		if (vdev->stats)
103602a20d4fSChristophe JAILLET 			dma_free_coherent(&vdev->pdev->dev,
1037a6a5580cSJeff Kirsher 					  sizeof(struct vnic_stats),
1038a6a5580cSJeff Kirsher 					  vdev->stats, vdev->stats_pa);
1039a6a5580cSJeff Kirsher 		if (vdev->fw_info)
104002a20d4fSChristophe JAILLET 			dma_free_coherent(&vdev->pdev->dev,
1041a6a5580cSJeff Kirsher 					  sizeof(struct vnic_devcmd_fw_info),
1042a6a5580cSJeff Kirsher 					  vdev->fw_info, vdev->fw_info_pa);
1043373fb087SGovindarajulu Varadarajan 		if (vdev->devcmd2)
1044373fb087SGovindarajulu Varadarajan 			vnic_dev_deinit_devcmd2(vdev);
1045373fb087SGovindarajulu Varadarajan 
1046a6a5580cSJeff Kirsher 		kfree(vdev);
1047a6a5580cSJeff Kirsher 	}
1048a6a5580cSJeff Kirsher }
10494a50ddfdSgovindarajulu.v EXPORT_SYMBOL(vnic_dev_unregister);
1050a6a5580cSJeff Kirsher 
vnic_dev_register(struct vnic_dev * vdev,void * priv,struct pci_dev * pdev,struct vnic_dev_bar * bar,unsigned int num_bars)1051a6a5580cSJeff Kirsher struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
1052a6a5580cSJeff Kirsher 	void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
1053a6a5580cSJeff Kirsher 	unsigned int num_bars)
1054a6a5580cSJeff Kirsher {
1055a6a5580cSJeff Kirsher 	if (!vdev) {
1056039b1d5eSJia-Ju Bai 		vdev = kzalloc(sizeof(struct vnic_dev), GFP_KERNEL);
1057a6a5580cSJeff Kirsher 		if (!vdev)
1058a6a5580cSJeff Kirsher 			return NULL;
1059a6a5580cSJeff Kirsher 	}
1060a6a5580cSJeff Kirsher 
1061a6a5580cSJeff Kirsher 	vdev->priv = priv;
1062a6a5580cSJeff Kirsher 	vdev->pdev = pdev;
1063a6a5580cSJeff Kirsher 
1064a6a5580cSJeff Kirsher 	if (vnic_dev_discover_res(vdev, bar, num_bars))
1065a6a5580cSJeff Kirsher 		goto err_out;
1066a6a5580cSJeff Kirsher 
1067a6a5580cSJeff Kirsher 	return vdev;
1068a6a5580cSJeff Kirsher 
1069a6a5580cSJeff Kirsher err_out:
1070a6a5580cSJeff Kirsher 	vnic_dev_unregister(vdev);
1071a6a5580cSJeff Kirsher 	return NULL;
1072a6a5580cSJeff Kirsher }
10734a50ddfdSgovindarajulu.v EXPORT_SYMBOL(vnic_dev_register);
10744a50ddfdSgovindarajulu.v 
vnic_dev_get_pdev(struct vnic_dev * vdev)10754a50ddfdSgovindarajulu.v struct pci_dev *vnic_dev_get_pdev(struct vnic_dev *vdev)
10764a50ddfdSgovindarajulu.v {
10774a50ddfdSgovindarajulu.v 	return vdev->pdev;
10784a50ddfdSgovindarajulu.v }
10794a50ddfdSgovindarajulu.v EXPORT_SYMBOL(vnic_dev_get_pdev);
1080a6a5580cSJeff Kirsher 
vnic_devcmd_init(struct vnic_dev * vdev)1081373fb087SGovindarajulu Varadarajan int vnic_devcmd_init(struct vnic_dev *vdev)
1082373fb087SGovindarajulu Varadarajan {
1083f376d4adSDavid S. Miller 	void __iomem *res;
1084373fb087SGovindarajulu Varadarajan 	int err;
1085373fb087SGovindarajulu Varadarajan 
1086373fb087SGovindarajulu Varadarajan 	res = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD2, 0);
1087373fb087SGovindarajulu Varadarajan 	if (res) {
1088373fb087SGovindarajulu Varadarajan 		err = vnic_dev_init_devcmd2(vdev);
1089373fb087SGovindarajulu Varadarajan 		if (err)
1090e327f4e1SJoe Perches 			vdev_warn(vdev, "DEVCMD2 init failed: %d, Using DEVCMD1\n",
1091373fb087SGovindarajulu Varadarajan 				  err);
1092373fb087SGovindarajulu Varadarajan 		else
1093373fb087SGovindarajulu Varadarajan 			return 0;
1094373fb087SGovindarajulu Varadarajan 	} else {
1095e327f4e1SJoe Perches 		vdev_warn(vdev, "DEVCMD2 resource not found (old firmware?) Using DEVCMD1\n");
1096373fb087SGovindarajulu Varadarajan 	}
1097373fb087SGovindarajulu Varadarajan 	err = vnic_dev_init_devcmd1(vdev);
1098373fb087SGovindarajulu Varadarajan 	if (err)
1099e327f4e1SJoe Perches 		vdev_err(vdev, "DEVCMD1 initialization failed: %d\n", err);
1100373fb087SGovindarajulu Varadarajan 
1101373fb087SGovindarajulu Varadarajan 	return err;
1102373fb087SGovindarajulu Varadarajan }
1103373fb087SGovindarajulu Varadarajan 
vnic_dev_init_prov2(struct vnic_dev * vdev,u8 * buf,u32 len)1104a6a5580cSJeff Kirsher int vnic_dev_init_prov2(struct vnic_dev *vdev, u8 *buf, u32 len)
1105a6a5580cSJeff Kirsher {
1106a6a5580cSJeff Kirsher 	u64 a0, a1 = len;
1107a6a5580cSJeff Kirsher 	int wait = 1000;
1108a6a5580cSJeff Kirsher 	dma_addr_t prov_pa;
1109a6a5580cSJeff Kirsher 	void *prov_buf;
1110a6a5580cSJeff Kirsher 	int ret;
1111a6a5580cSJeff Kirsher 
111202a20d4fSChristophe JAILLET 	prov_buf = dma_alloc_coherent(&vdev->pdev->dev, len, &prov_pa, GFP_ATOMIC);
1113a6a5580cSJeff Kirsher 	if (!prov_buf)
1114a6a5580cSJeff Kirsher 		return -ENOMEM;
1115a6a5580cSJeff Kirsher 
1116a6a5580cSJeff Kirsher 	memcpy(prov_buf, buf, len);
1117a6a5580cSJeff Kirsher 
1118a6a5580cSJeff Kirsher 	a0 = prov_pa;
1119a6a5580cSJeff Kirsher 
1120a6a5580cSJeff Kirsher 	ret = vnic_dev_cmd(vdev, CMD_INIT_PROV_INFO2, &a0, &a1, wait);
1121a6a5580cSJeff Kirsher 
112202a20d4fSChristophe JAILLET 	dma_free_coherent(&vdev->pdev->dev, len, prov_buf, prov_pa);
1123a6a5580cSJeff Kirsher 
1124a6a5580cSJeff Kirsher 	return ret;
1125a6a5580cSJeff Kirsher }
1126a6a5580cSJeff Kirsher 
vnic_dev_enable2(struct vnic_dev * vdev,int active)1127a6a5580cSJeff Kirsher int vnic_dev_enable2(struct vnic_dev *vdev, int active)
1128a6a5580cSJeff Kirsher {
1129a6a5580cSJeff Kirsher 	u64 a0, a1 = 0;
1130a6a5580cSJeff Kirsher 	int wait = 1000;
1131a6a5580cSJeff Kirsher 
1132a6a5580cSJeff Kirsher 	a0 = (active ? CMD_ENABLE2_ACTIVE : 0);
1133a6a5580cSJeff Kirsher 
1134a6a5580cSJeff Kirsher 	return vnic_dev_cmd(vdev, CMD_ENABLE2, &a0, &a1, wait);
1135a6a5580cSJeff Kirsher }
1136a6a5580cSJeff Kirsher 
vnic_dev_cmd_status(struct vnic_dev * vdev,enum vnic_devcmd_cmd cmd,int * status)1137a6a5580cSJeff Kirsher static int vnic_dev_cmd_status(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
1138a6a5580cSJeff Kirsher 	int *status)
1139a6a5580cSJeff Kirsher {
1140a6a5580cSJeff Kirsher 	u64 a0 = cmd, a1 = 0;
1141a6a5580cSJeff Kirsher 	int wait = 1000;
1142a6a5580cSJeff Kirsher 	int ret;
1143a6a5580cSJeff Kirsher 
1144a6a5580cSJeff Kirsher 	ret = vnic_dev_cmd(vdev, CMD_STATUS, &a0, &a1, wait);
1145a6a5580cSJeff Kirsher 	if (!ret)
1146a6a5580cSJeff Kirsher 		*status = (int)a0;
1147a6a5580cSJeff Kirsher 
1148a6a5580cSJeff Kirsher 	return ret;
1149a6a5580cSJeff Kirsher }
1150a6a5580cSJeff Kirsher 
vnic_dev_enable2_done(struct vnic_dev * vdev,int * status)1151a6a5580cSJeff Kirsher int vnic_dev_enable2_done(struct vnic_dev *vdev, int *status)
1152a6a5580cSJeff Kirsher {
1153a6a5580cSJeff Kirsher 	return vnic_dev_cmd_status(vdev, CMD_ENABLE2, status);
1154a6a5580cSJeff Kirsher }
1155a6a5580cSJeff Kirsher 
vnic_dev_deinit_done(struct vnic_dev * vdev,int * status)1156a6a5580cSJeff Kirsher int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status)
1157a6a5580cSJeff Kirsher {
1158a6a5580cSJeff Kirsher 	return vnic_dev_cmd_status(vdev, CMD_DEINIT, status);
1159a6a5580cSJeff Kirsher }
1160d6c81bc6SRoopa Prabhu 
vnic_dev_set_mac_addr(struct vnic_dev * vdev,u8 * mac_addr)1161d6c81bc6SRoopa Prabhu int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
1162d6c81bc6SRoopa Prabhu {
1163d6c81bc6SRoopa Prabhu 	u64 a0, a1;
1164d6c81bc6SRoopa Prabhu 	int wait = 1000;
1165d6c81bc6SRoopa Prabhu 	int i;
1166d6c81bc6SRoopa Prabhu 
1167d6c81bc6SRoopa Prabhu 	for (i = 0; i < ETH_ALEN; i++)
1168d6c81bc6SRoopa Prabhu 		((u8 *)&a0)[i] = mac_addr[i];
1169d6c81bc6SRoopa Prabhu 
1170d6c81bc6SRoopa Prabhu 	return vnic_dev_cmd(vdev, CMD_SET_MAC_ADDR, &a0, &a1, wait);
1171d6c81bc6SRoopa Prabhu }
117263118527SGovindarajulu Varadarajan 
117363118527SGovindarajulu Varadarajan /* vnic_dev_classifier: Add/Delete classifier entries
117463118527SGovindarajulu Varadarajan  * @vdev: vdev of the device
117563118527SGovindarajulu Varadarajan  * @cmd: CLSF_ADD for Add filter
117663118527SGovindarajulu Varadarajan  *	 CLSF_DEL for Delete filter
117763118527SGovindarajulu Varadarajan  * @entry: In case of ADD filter, the caller passes the RQ number in this
117863118527SGovindarajulu Varadarajan  *	   variable.
117963118527SGovindarajulu Varadarajan  *
118063118527SGovindarajulu Varadarajan  *	   This function stores the filter_id returned by the firmware in the
118163118527SGovindarajulu Varadarajan  *	   same variable before return;
118263118527SGovindarajulu Varadarajan  *
118363118527SGovindarajulu Varadarajan  *	   In case of DEL filter, the caller passes the RQ number. Return
118463118527SGovindarajulu Varadarajan  *	   value is irrelevant.
118563118527SGovindarajulu Varadarajan  * @data: filter data
118663118527SGovindarajulu Varadarajan  */
vnic_dev_classifier(struct vnic_dev * vdev,u8 cmd,u16 * entry,struct filter * data)118763118527SGovindarajulu Varadarajan int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry,
118863118527SGovindarajulu Varadarajan 			struct filter *data)
118963118527SGovindarajulu Varadarajan {
119063118527SGovindarajulu Varadarajan 	u64 a0, a1;
119163118527SGovindarajulu Varadarajan 	int wait = 1000;
119263118527SGovindarajulu Varadarajan 	dma_addr_t tlv_pa;
119363118527SGovindarajulu Varadarajan 	int ret = -EINVAL;
119463118527SGovindarajulu Varadarajan 	struct filter_tlv *tlv, *tlv_va;
119563118527SGovindarajulu Varadarajan 	struct filter_action *action;
119663118527SGovindarajulu Varadarajan 	u64 tlv_size;
119763118527SGovindarajulu Varadarajan 
119863118527SGovindarajulu Varadarajan 	if (cmd == CLSF_ADD) {
119963118527SGovindarajulu Varadarajan 		tlv_size = sizeof(struct filter) +
120063118527SGovindarajulu Varadarajan 			   sizeof(struct filter_action) +
120163118527SGovindarajulu Varadarajan 			   2 * sizeof(struct filter_tlv);
120202a20d4fSChristophe JAILLET 		tlv_va = dma_alloc_coherent(&vdev->pdev->dev, tlv_size,
120302a20d4fSChristophe JAILLET 					    &tlv_pa, GFP_ATOMIC);
120463118527SGovindarajulu Varadarajan 		if (!tlv_va)
120563118527SGovindarajulu Varadarajan 			return -ENOMEM;
120663118527SGovindarajulu Varadarajan 		tlv = tlv_va;
120763118527SGovindarajulu Varadarajan 		a0 = tlv_pa;
120863118527SGovindarajulu Varadarajan 		a1 = tlv_size;
120963118527SGovindarajulu Varadarajan 		memset(tlv, 0, tlv_size);
121063118527SGovindarajulu Varadarajan 		tlv->type = CLSF_TLV_FILTER;
121163118527SGovindarajulu Varadarajan 		tlv->length = sizeof(struct filter);
121263118527SGovindarajulu Varadarajan 		*(struct filter *)&tlv->val = *data;
121363118527SGovindarajulu Varadarajan 
121463118527SGovindarajulu Varadarajan 		tlv = (struct filter_tlv *)((char *)tlv +
121563118527SGovindarajulu Varadarajan 					    sizeof(struct filter_tlv) +
121663118527SGovindarajulu Varadarajan 					    sizeof(struct filter));
121763118527SGovindarajulu Varadarajan 
121863118527SGovindarajulu Varadarajan 		tlv->type = CLSF_TLV_ACTION;
121963118527SGovindarajulu Varadarajan 		tlv->length = sizeof(struct filter_action);
122063118527SGovindarajulu Varadarajan 		action = (struct filter_action *)&tlv->val;
122163118527SGovindarajulu Varadarajan 		action->type = FILTER_ACTION_RQ_STEERING;
122263118527SGovindarajulu Varadarajan 		action->u.rq_idx = *entry;
122363118527SGovindarajulu Varadarajan 
122463118527SGovindarajulu Varadarajan 		ret = vnic_dev_cmd(vdev, CMD_ADD_FILTER, &a0, &a1, wait);
122563118527SGovindarajulu Varadarajan 		*entry = (u16)a0;
122602a20d4fSChristophe JAILLET 		dma_free_coherent(&vdev->pdev->dev, tlv_size, tlv_va, tlv_pa);
122763118527SGovindarajulu Varadarajan 	} else if (cmd == CLSF_DEL) {
122863118527SGovindarajulu Varadarajan 		a0 = *entry;
122963118527SGovindarajulu Varadarajan 		ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait);
123063118527SGovindarajulu Varadarajan 	}
123163118527SGovindarajulu Varadarajan 
123263118527SGovindarajulu Varadarajan 	return ret;
123363118527SGovindarajulu Varadarajan }
1234ca029179SGovindarajulu Varadarajan 
vnic_dev_overlay_offload_ctrl(struct vnic_dev * vdev,u8 overlay,u8 config)1235ca029179SGovindarajulu Varadarajan int vnic_dev_overlay_offload_ctrl(struct vnic_dev *vdev, u8 overlay, u8 config)
1236ca029179SGovindarajulu Varadarajan {
1237ca029179SGovindarajulu Varadarajan 	u64 a0 = overlay;
1238ca029179SGovindarajulu Varadarajan 	u64 a1 = config;
1239ca029179SGovindarajulu Varadarajan 	int wait = 1000;
1240ca029179SGovindarajulu Varadarajan 
1241ca029179SGovindarajulu Varadarajan 	return vnic_dev_cmd(vdev, CMD_OVERLAY_OFFLOAD_CTRL, &a0, &a1, wait);
1242ca029179SGovindarajulu Varadarajan }
1243ca029179SGovindarajulu Varadarajan 
vnic_dev_overlay_offload_cfg(struct vnic_dev * vdev,u8 overlay,u16 vxlan_udp_port_number)1244ca029179SGovindarajulu Varadarajan int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay,
1245ca029179SGovindarajulu Varadarajan 				 u16 vxlan_udp_port_number)
1246ca029179SGovindarajulu Varadarajan {
1247ca029179SGovindarajulu Varadarajan 	u64 a1 = vxlan_udp_port_number;
1248ca029179SGovindarajulu Varadarajan 	u64 a0 = overlay;
1249ca029179SGovindarajulu Varadarajan 	int wait = 1000;
1250ca029179SGovindarajulu Varadarajan 
1251ca029179SGovindarajulu Varadarajan 	return vnic_dev_cmd(vdev, CMD_OVERLAY_OFFLOAD_CFG, &a0, &a1, wait);
1252ca029179SGovindarajulu Varadarajan }
1253ca029179SGovindarajulu Varadarajan 
vnic_dev_get_supported_feature_ver(struct vnic_dev * vdev,u8 feature,u64 * supported_versions,u64 * a1)1254ca029179SGovindarajulu Varadarajan int vnic_dev_get_supported_feature_ver(struct vnic_dev *vdev, u8 feature,
1255d1179094SGovindarajulu Varadarajan 				       u64 *supported_versions, u64 *a1)
1256ca029179SGovindarajulu Varadarajan {
1257ca029179SGovindarajulu Varadarajan 	u64 a0 = feature;
1258ca029179SGovindarajulu Varadarajan 	int wait = 1000;
1259ca029179SGovindarajulu Varadarajan 	int ret;
1260ca029179SGovindarajulu Varadarajan 
1261d1179094SGovindarajulu Varadarajan 	ret = vnic_dev_cmd(vdev, CMD_GET_SUPP_FEATURE_VER, &a0, a1, wait);
1262ca029179SGovindarajulu Varadarajan 	if (!ret)
1263ca029179SGovindarajulu Varadarajan 		*supported_versions = a0;
1264ca029179SGovindarajulu Varadarajan 
1265ca029179SGovindarajulu Varadarajan 	return ret;
1266ca029179SGovindarajulu Varadarajan }
126748398b6eSGovindarajulu Varadarajan 
vnic_dev_capable_rss_hash_type(struct vnic_dev * vdev,u8 * rss_hash_type)12684016a7f1SGovindarajulu Varadarajan int vnic_dev_capable_rss_hash_type(struct vnic_dev *vdev, u8 *rss_hash_type)
126948398b6eSGovindarajulu Varadarajan {
127048398b6eSGovindarajulu Varadarajan 	u64 a0 = CMD_NIC_CFG, a1 = 0;
127148398b6eSGovindarajulu Varadarajan 	int wait = 1000;
127248398b6eSGovindarajulu Varadarajan 	int err;
127348398b6eSGovindarajulu Varadarajan 
127448398b6eSGovindarajulu Varadarajan 	err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
12754016a7f1SGovindarajulu Varadarajan 	/* rss_hash_type is valid only when a0 is 1. Adapter which does not
12764016a7f1SGovindarajulu Varadarajan 	 * support CMD_CAPABILITY for rss_hash_type has a0 = 0
12774016a7f1SGovindarajulu Varadarajan 	 */
12784016a7f1SGovindarajulu Varadarajan 	if (err || (a0 != 1))
12794016a7f1SGovindarajulu Varadarajan 		return -EOPNOTSUPP;
128048398b6eSGovindarajulu Varadarajan 
12814016a7f1SGovindarajulu Varadarajan 	a1 = (a1 >> NIC_CFG_RSS_HASH_TYPE_SHIFT) &
128248398b6eSGovindarajulu Varadarajan 	     NIC_CFG_RSS_HASH_TYPE_MASK_FIELD;
128348398b6eSGovindarajulu Varadarajan 
12844016a7f1SGovindarajulu Varadarajan 	*rss_hash_type = (u8)a1;
12854016a7f1SGovindarajulu Varadarajan 
12864016a7f1SGovindarajulu Varadarajan 	return 0;
128748398b6eSGovindarajulu Varadarajan }
1288