15df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar/*
25df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
35df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
45df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar *
55df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * This program is free software; you may redistribute it and/or modify
65df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * it under the terms of the GNU General Public License as published by
75df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * the Free Software Foundation; version 2 of the License.
85df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar *
95df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar * SOFTWARE.
175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar */
185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include <linux/kernel.h>
205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include <linux/errno.h>
215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include <linux/types.h>
225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include <linux/pci.h>
235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include <linux/delay.h>
245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include <linux/if_ether.h>
255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include "vnic_resource.h"
275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include "vnic_devcmd.h"
285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include "vnic_dev.h"
295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#include "vnic_stats.h"
305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstruct vnic_res {
325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	void __iomem *vaddr;
335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	unsigned int count;
345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar};
355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstruct vnic_dev {
375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	void *priv;
385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct pci_dev *pdev;
395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_res res[RES_TYPE_MAX];
405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	enum vnic_dev_intr_mode intr_mode;
415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_devcmd __iomem *devcmd;
425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_devcmd_notify *notify;
435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_devcmd_notify notify_copy;
445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	dma_addr_t notify_pa;
455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u32 *linkstatus;
465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	dma_addr_t linkstatus_pa;
475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_stats *stats;
485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	dma_addr_t stats_pa;
495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_devcmd_fw_info *fw_info;
505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	dma_addr_t fw_info_pa;
515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar};
525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define VNIC_MAX_RES_HDR_SIZE \
545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	(sizeof(struct vnic_resource_header) + \
555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	sizeof(struct vnic_resource) * RES_TYPE_MAX)
565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar#define VNIC_RES_STRIDE	128
575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid *vnic_dev_priv(struct vnic_dev *vdev)
595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->priv;
615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstatic int vnic_dev_discover_res(struct vnic_dev *vdev,
645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_dev_bar *bar)
655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_resource_header __iomem *rh;
675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_resource __iomem *r;
685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u8 type;
695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (bar->len < VNIC_MAX_RES_HDR_SIZE) {
715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR "vNIC BAR0 res hdr length error\n");
725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return -EINVAL;
735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	rh = bar->vaddr;
765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!rh) {
775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR "vNIC BAR0 res hdr not mem-mapped\n");
785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return -EINVAL;
795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (ioread32(&rh->magic) != VNIC_RES_MAGIC ||
825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	    ioread32(&rh->version) != VNIC_RES_VERSION) {
835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR "vNIC BAR0 res magic/version error "
845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			"exp (%lx/%lx) curr (%x/%x)\n",
855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			VNIC_RES_MAGIC, VNIC_RES_VERSION,
865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			ioread32(&rh->magic), ioread32(&rh->version));
875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return -EINVAL;
885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	r = (struct vnic_resource __iomem *)(rh + 1);
915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
925df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	while ((type = ioread8(&r->type)) != RES_TYPE_EOL) {
935df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
945df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		u8 bar_num = ioread8(&r->bar);
955df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		u32 bar_offset = ioread32(&r->bar_offset);
965df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		u32 count = ioread32(&r->count);
975df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		u32 len;
985df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
995df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		r++;
1005df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1015df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (bar_num != 0)  /* only mapping in BAR0 resources */
1025df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			continue;
1035df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1045df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		switch (type) {
1055df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		case RES_TYPE_WQ:
1065df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		case RES_TYPE_RQ:
1075df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		case RES_TYPE_CQ:
1085df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		case RES_TYPE_INTR_CTRL:
1095df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			/* each count is stride bytes long */
1105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			len = count * VNIC_RES_STRIDE;
1115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			if (len + bar_offset > bar->len) {
1125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				printk(KERN_ERR "vNIC BAR0 resource %d "
1135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar					"out-of-bounds, offset 0x%x + "
1145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar					"size 0x%x > bar len 0x%lx\n",
1155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar					type, bar_offset,
1165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar					len,
1175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar					bar->len);
1185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				return -EINVAL;
1195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			}
1205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			break;
1215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		case RES_TYPE_INTR_PBA_LEGACY:
1225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		case RES_TYPE_DEVCMD:
1235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			len = count;
1245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			break;
1255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		default:
1265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			continue;
1275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		}
1285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		vdev->res[type].count = count;
1305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		vdev->res[type].vaddr = (char __iomem *)bar->vaddr + bar_offset;
1315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
1325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return 0;
1345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
1355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarunsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
1375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	enum vnic_res_type type)
1385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
1395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->res[type].count;
1405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
1415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
1435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	unsigned int index)
1445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
1455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vdev->res[type].vaddr)
1465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return NULL;
1475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	switch (type) {
1495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case RES_TYPE_WQ:
1505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case RES_TYPE_RQ:
1515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case RES_TYPE_CQ:
1525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case RES_TYPE_INTR_CTRL:
1535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return (char __iomem *)vdev->res[type].vaddr +
1545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar					index * VNIC_RES_STRIDE;
1555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	default:
1565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return (char __iomem *)vdev->res[type].vaddr;
1575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
1585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
1595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarunsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
1615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				     unsigned int desc_count,
1625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				     unsigned int desc_size)
1635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
1645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	/* The base address of the desc rings must be 512 byte aligned.
1655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	 * Descriptor count is aligned to groups of 32 descriptors.  A
1665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	 * count of 0 means the maximum 4096 descriptors.  Descriptor
1675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	 * size is aligned to 16 bytes.
1685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	 */
1695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	unsigned int count_align = 32;
1715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	unsigned int desc_align = 16;
1725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->base_align = 512;
1745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (desc_count == 0)
1765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		desc_count = 4096;
1775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->desc_count = ALIGN(desc_count, count_align);
1795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->desc_size = ALIGN(desc_size, desc_align);
1815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->size = ring->desc_count * ring->desc_size;
1835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->size_unaligned = ring->size + ring->base_align;
1845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return ring->size_unaligned;
1865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
1875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_clear_desc_ring(struct vnic_dev_ring *ring)
1895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
1905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	memset(ring->descs, 0, ring->size);
1915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
1925df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1935df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_alloc_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring,
1945df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	unsigned int desc_count, unsigned int desc_size)
1955df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
1965df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vnic_dev_desc_ring_size(ring, desc_count, desc_size);
1975df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
1985df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->descs_unaligned = pci_alloc_consistent(vdev->pdev,
1995df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		ring->size_unaligned,
2005df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		&ring->base_addr_unaligned);
2015df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2025df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!ring->descs_unaligned) {
2035df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR
2045df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		  "Failed to allocate ring (size=%d), aborting\n",
2055df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			(int)ring->size);
2065df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return -ENOMEM;
2075df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
2085df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2095df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->base_addr = ALIGN(ring->base_addr_unaligned,
2105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		ring->base_align);
2115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->descs = (u8 *)ring->descs_unaligned +
2125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		(ring->base_addr - ring->base_addr_unaligned);
2135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vnic_dev_clear_desc_ring(ring);
2155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	ring->desc_avail = ring->desc_count - 1;
2175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return 0;
2195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
2205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
2225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
2235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (ring->descs) {
2245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		pci_free_consistent(vdev->pdev,
2255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			ring->size_unaligned,
2265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			ring->descs_unaligned,
2275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			ring->base_addr_unaligned);
2285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		ring->descs = NULL;
2295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
2305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
2315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
2335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 *a0, u64 *a1, int wait)
2345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
2355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
2365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int delay;
2375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u32 status;
2385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int dev_cmd_err[] = {
2395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		/* convert from fw's version of error.h to host's version */
2405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		0,	/* ERR_SUCCESS */
2415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		EINVAL,	/* ERR_EINVAL */
2425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		EFAULT,	/* ERR_EFAULT */
2435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		EPERM,	/* ERR_EPERM */
2445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		EBUSY,  /* ERR_EBUSY */
2455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	};
2465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err;
2475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	status = ioread32(&devcmd->status);
2495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (status & STAT_BUSY) {
2505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR "Busy devcmd %d\n", _CMD_N(cmd));
2515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return -EBUSY;
2525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
2535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
2555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		writeq(*a0, &devcmd->args[0]);
2565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		writeq(*a1, &devcmd->args[1]);
2575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		wmb();
2585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
2595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	iowrite32(cmd, &devcmd->cmd);
2615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
2635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			return 0;
2645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	for (delay = 0; delay < wait; delay++) {
2665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		udelay(100);
2685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		status = ioread32(&devcmd->status);
2705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (!(status & STAT_BUSY)) {
2715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			if (status & STAT_ERROR) {
2735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				err = dev_cmd_err[(int)readq(&devcmd->args[0])];
2745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				printk(KERN_ERR "Error %d devcmd %d\n",
2755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar					err, _CMD_N(cmd));
2765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				return -err;
2775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			}
2785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
2805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				rmb();
2815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				*a0 = readq(&devcmd->args[0]);
2825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				*a1 = readq(&devcmd->args[1]);
2835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			}
2845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			return 0;
2865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		}
2875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
2885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	printk(KERN_ERR "Timedout devcmd %d\n", _CMD_N(cmd));
2905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return -ETIMEDOUT;
2915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
2925df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
2935df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_fw_info(struct vnic_dev *vdev,
2945df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_devcmd_fw_info **fw_info)
2955df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
2965df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1 = 0;
2975df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
2985df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err = 0;
2995df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3005df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vdev->fw_info) {
3015df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		vdev->fw_info = pci_alloc_consistent(vdev->pdev,
3025df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			sizeof(struct vnic_devcmd_fw_info),
3035df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			&vdev->fw_info_pa);
3045df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (!vdev->fw_info)
3055df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			return -ENOMEM;
3065df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3075df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		a0 = vdev->fw_info_pa;
3085df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3095df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		/* only get fw_info once and cache it */
3105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait);
3115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
3125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	*fw_info = vdev->fw_info;
3145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return err;
3165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
3175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
3195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	void *value)
3205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
3215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1;
3225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
3235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err;
3245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a0 = offset;
3265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a1 = size;
3275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	err = vnic_dev_cmd(vdev, CMD_DEV_SPEC, &a0, &a1, wait);
3295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	switch (size) {
3315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case 1:
3325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		*(u8 *)value = (u8)a0;
3335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		break;
3345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case 2:
3355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		*(u16 *)value = (u16)a0;
3365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		break;
3375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case 4:
3385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		*(u32 *)value = (u32)a0;
3395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		break;
3405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	case 8:
3415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		*(u64 *)value = a0;
3425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		break;
3435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	default:
3445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		BUG();
3455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		break;
3465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
3475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return err;
3495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
3505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_stats_clear(struct vnic_dev *vdev)
3525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
3535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
3545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
3555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_STATS_CLEAR, &a0, &a1, wait);
3565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
3575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
3595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
3605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1;
3615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
3625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vdev->stats) {
3645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		vdev->stats = pci_alloc_consistent(vdev->pdev,
3655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			sizeof(struct vnic_stats), &vdev->stats_pa);
3665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (!vdev->stats)
3675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			return -ENOMEM;
3685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
3695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	*stats = vdev->stats;
3715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a0 = vdev->stats_pa;
3725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a1 = sizeof(struct vnic_stats);
3735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_STATS_DUMP, &a0, &a1, wait);
3755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
3765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_close(struct vnic_dev *vdev)
3785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
3795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
3805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
3815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_CLOSE, &a0, &a1, wait);
3825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
3835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_enable(struct vnic_dev *vdev)
3855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
3865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
3875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
3885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
3895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
3905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_disable(struct vnic_dev *vdev)
3925df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
3935df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
3945df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
3955df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_DISABLE, &a0, &a1, wait);
3965df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
3975df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
3985df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_open(struct vnic_dev *vdev, int arg)
3995df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4005df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = (u32)arg, a1 = 0;
4015df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4025df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_OPEN, &a0, &a1, wait);
4035df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
4045df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4055df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_open_done(struct vnic_dev *vdev, int *done)
4065df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4075df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
4085df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4095df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err;
4105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	*done = 0;
4125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	err = vnic_dev_cmd(vdev, CMD_OPEN_STATUS, &a0, &a1, wait);
4145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (err)
4155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return err;
4165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	*done = (a0 == 0);
4185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return 0;
4205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
4215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_soft_reset(struct vnic_dev *vdev, int arg)
4235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = (u32)arg, a1 = 0;
4255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait);
4275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
4285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
4305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
4325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err;
4345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	*done = 0;
4365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	err = vnic_dev_cmd(vdev, CMD_SOFT_RESET_STATUS, &a0, &a1, wait);
4385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (err)
4395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return err;
4405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	*done = (a0 == 0);
4425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return 0;
4445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
4455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_hang_notify(struct vnic_dev *vdev)
4475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1;
4495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
4515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
4525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
4545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1;
4565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err, i;
4585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	for (i = 0; i < ETH_ALEN; i++)
4605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		mac_addr[i] = 0;
4615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
4635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (err)
4645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return err;
4655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	for (i = 0; i < ETH_ALEN; i++)
4675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		mac_addr[i] = ((u8 *)&a0)[i];
4685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return 0;
4705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
4715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
4735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int broadcast, int promisc, int allmulti)
4745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1 = 0;
4765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err;
4785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
4805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	     (multicast ? CMD_PFILTER_MULTICAST : 0) |
4815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	     (broadcast ? CMD_PFILTER_BROADCAST : 0) |
4825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	     (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
4835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	     (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
4845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER, &a0, &a1, wait);
4865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (err)
4875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR "Can't set packet filter\n");
4885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
4895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
4915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
4925df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
4935df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
4945df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err;
4955df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int i;
4965df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
4975df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	for (i = 0; i < ETH_ALEN; i++)
4985df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		((u8 *)&a0)[i] = addr[i];
4995df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5005df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
5015df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (err)
5025df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR
5035df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			"Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
5045df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
5055df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			err);
5065df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
5075df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5085df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
5095df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
5105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = 0, a1 = 0;
5115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
5125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int err;
5135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int i;
5145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	for (i = 0; i < ETH_ALEN; i++)
5165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		((u8 *)&a0)[i] = addr[i];
5175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
5195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (err)
5205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		printk(KERN_ERR
5215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			"Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
5225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
5235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			err);
5245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
5255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
5275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
5285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1;
5295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
5305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vdev->notify) {
5325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		vdev->notify = pci_alloc_consistent(vdev->pdev,
5335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			sizeof(struct vnic_devcmd_notify),
5345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			&vdev->notify_pa);
5355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (!vdev->notify)
5365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			return -ENOMEM;
5375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
5385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a0 = vdev->notify_pa;
5405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
5415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a1 += sizeof(struct vnic_devcmd_notify);
5425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
5445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
5455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_notify_unset(struct vnic_dev *vdev)
5475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
5485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0, a1;
5495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
5505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a0 = 0;  /* paddr = 0 to unset notify buffer */
5525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a1 = 0x0000ffff00000000ULL; /* intr num = -1 to unreg for intr */
5535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	a1 += sizeof(struct vnic_devcmd_notify);
5545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
5565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
5575df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstatic int vnic_dev_notify_ready(struct vnic_dev *vdev)
5595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
5605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u32 *words;
5615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4;
5625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	unsigned int i;
5635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u32 csum;
5645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vdev->notify)
5665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return 0;
5675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	do {
5695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		csum = 0;
5705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		memcpy(&vdev->notify_copy, vdev->notify,
5715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			sizeof(struct vnic_devcmd_notify));
5725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		words = (u32 *)&vdev->notify_copy;
5735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		for (i = 1; i < nwords; i++)
5745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			csum += words[i];
5755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	} while (csum != words[0]);
5765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return 1;
5785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
5795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_init(struct vnic_dev *vdev, int arg)
5815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
5825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	u64 a0 = (u32)arg, a1 = 0;
5835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	int wait = 1000;
5845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
5855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
5865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarint vnic_dev_link_status(struct vnic_dev *vdev)
5885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
5895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (vdev->linkstatus)
5905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return *vdev->linkstatus;
5915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5925df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vnic_dev_notify_ready(vdev))
5935df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return 0;
5945df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5955df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->notify_copy.link_state;
5965df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
5975df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
5985df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekaru32 vnic_dev_port_speed(struct vnic_dev *vdev)
5995df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6005df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vnic_dev_notify_ready(vdev))
6015df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return 0;
6025df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6035df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->notify_copy.port_speed;
6045df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
6055df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6065df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekaru32 vnic_dev_msg_lvl(struct vnic_dev *vdev)
6075df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6085df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vnic_dev_notify_ready(vdev))
6095df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return 0;
6105df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6115df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->notify_copy.msglvl;
6125df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
6135df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6145df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekaru32 vnic_dev_mtu(struct vnic_dev *vdev)
6155df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6165df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vnic_dev_notify_ready(vdev))
6175df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return 0;
6185df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6195df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->notify_copy.mtu;
6205df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
6215df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6225df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekaru32 vnic_dev_link_down_cnt(struct vnic_dev *vdev)
6235df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6245df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vnic_dev_notify_ready(vdev))
6255df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		return 0;
6265df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6275df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->notify_copy.link_down_cnt;
6285df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
6295df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6305df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_set_intr_mode(struct vnic_dev *vdev,
6315df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	enum vnic_dev_intr_mode intr_mode)
6325df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6335df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vdev->intr_mode = intr_mode;
6345df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
6355df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6365df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarenum vnic_dev_intr_mode vnic_dev_get_intr_mode(
6375df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	struct vnic_dev *vdev)
6385df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6395df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev->intr_mode;
6405df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
6415df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6425df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarvoid vnic_dev_unregister(struct vnic_dev *vdev)
6435df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6445df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (vdev) {
6455df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (vdev->notify)
6465df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			pci_free_consistent(vdev->pdev,
6475df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				sizeof(struct vnic_devcmd_notify),
6485df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				vdev->notify,
6495df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				vdev->notify_pa);
6505df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (vdev->linkstatus)
6515df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			pci_free_consistent(vdev->pdev,
6525df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				sizeof(u32),
6535df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				vdev->linkstatus,
6545df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				vdev->linkstatus_pa);
6555df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (vdev->stats)
6565df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			pci_free_consistent(vdev->pdev,
657c954f8aed44686569347087a57c75c590ce2782dVenkata Siva Vijayendra Bhamidipati				sizeof(struct vnic_stats),
6585df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				vdev->stats, vdev->stats_pa);
6595df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (vdev->fw_info)
6605df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			pci_free_consistent(vdev->pdev,
6615df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				sizeof(struct vnic_devcmd_fw_info),
6625df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar				vdev->fw_info, vdev->fw_info_pa);
6635df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		kfree(vdev);
6645df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
6655df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
6665df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6675df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarstruct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
6685df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar)
6695df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar{
6705df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vdev) {
6715df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		vdev = kzalloc(sizeof(struct vnic_dev), GFP_KERNEL);
6725df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		if (!vdev)
6735df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar			return NULL;
6745df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	}
6755df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6765df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vdev->priv = priv;
6775df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vdev->pdev = pdev;
6785df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6795df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (vnic_dev_discover_res(vdev, bar))
6805df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		goto err_out;
6815df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6825df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
6835df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	if (!vdev->devcmd)
6845df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar		goto err_out;
6855df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6865df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return vdev;
6875df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar
6885df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekarerr_out:
6895df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	vnic_dev_unregister(vdev);
6905df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar	return NULL;
6915df6d737dd4b0fe9eccf943abb3677cfea05a6c4Abhijeet Joglekar}
692