|
@@ -31,6 +31,7 @@
|
|
|
|
|
|
struct vnic_res {
|
|
|
void __iomem *vaddr;
|
|
|
+ dma_addr_t bus_addr;
|
|
|
unsigned int count;
|
|
|
};
|
|
|
|
|
@@ -67,12 +68,15 @@ void *vnic_dev_priv(struct vnic_dev *vdev)
|
|
|
}
|
|
|
|
|
|
static int vnic_dev_discover_res(struct vnic_dev *vdev,
|
|
|
- struct vnic_dev_bar *bar)
|
|
|
+ struct vnic_dev_bar *bar, unsigned int num_bars)
|
|
|
{
|
|
|
struct vnic_resource_header __iomem *rh;
|
|
|
struct vnic_resource __iomem *r;
|
|
|
u8 type;
|
|
|
|
|
|
+ if (num_bars == 0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
if (bar->len < VNIC_MAX_RES_HDR_SIZE) {
|
|
|
printk(KERN_ERR "vNIC BAR0 res hdr length error\n");
|
|
|
return -EINVAL;
|
|
@@ -104,7 +108,10 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
|
|
|
|
|
|
r++;
|
|
|
|
|
|
- if (bar_num != 0) /* only mapping in BAR0 resources */
|
|
|
+ if (bar_num >= num_bars)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (!bar[bar_num].len || !bar[bar_num].vaddr)
|
|
|
continue;
|
|
|
|
|
|
switch (type) {
|
|
@@ -114,13 +121,13 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
|
|
|
case RES_TYPE_INTR_CTRL:
|
|
|
/* each count is stride bytes long */
|
|
|
len = count * VNIC_RES_STRIDE;
|
|
|
- if (len + bar_offset > bar->len) {
|
|
|
+ if (len + bar_offset > bar[bar_num].len) {
|
|
|
printk(KERN_ERR "vNIC BAR0 resource %d "
|
|
|
"out-of-bounds, offset 0x%x + "
|
|
|
"size 0x%x > bar len 0x%lx\n",
|
|
|
type, bar_offset,
|
|
|
len,
|
|
|
- bar->len);
|
|
|
+ bar[bar_num].len);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
break;
|
|
@@ -133,7 +140,9 @@ static int vnic_dev_discover_res(struct vnic_dev *vdev,
|
|
|
}
|
|
|
|
|
|
vdev->res[type].count = count;
|
|
|
- vdev->res[type].vaddr = (char __iomem *)bar->vaddr + bar_offset;
|
|
|
+ vdev->res[type].vaddr = (char __iomem *)bar[bar_num].vaddr +
|
|
|
+ bar_offset;
|
|
|
+ vdev->res[type].bus_addr = bar[bar_num].bus_addr + bar_offset;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -163,6 +172,21 @@ void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+dma_addr_t vnic_dev_get_res_bus_addr(struct vnic_dev *vdev,
|
|
|
+ enum vnic_res_type type, unsigned int index)
|
|
|
+{
|
|
|
+ switch (type) {
|
|
|
+ case RES_TYPE_WQ:
|
|
|
+ case RES_TYPE_RQ:
|
|
|
+ case RES_TYPE_CQ:
|
|
|
+ case RES_TYPE_INTR_CTRL:
|
|
|
+ return vdev->res[type].bus_addr +
|
|
|
+ index * VNIC_RES_STRIDE;
|
|
|
+ default:
|
|
|
+ return vdev->res[type].bus_addr;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
unsigned int vnic_dev_desc_ring_size(struct vnic_dev_ring *ring,
|
|
|
unsigned int desc_count, unsigned int desc_size)
|
|
|
{
|
|
@@ -257,7 +281,7 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
|
|
|
iowrite32(cmd, &devcmd->cmd);
|
|
|
|
|
|
if ((_CMD_FLAGS(cmd) & _CMD_FLAGS_NOWAIT))
|
|
|
- return 0;
|
|
|
+ return 0;
|
|
|
|
|
|
for (delay = 0; delay < wait; delay++) {
|
|
|
|
|
@@ -684,7 +708,8 @@ void vnic_dev_unregister(struct vnic_dev *vdev)
|
|
|
}
|
|
|
|
|
|
struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
|
|
|
- void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar)
|
|
|
+ void *priv, struct pci_dev *pdev, struct vnic_dev_bar *bar,
|
|
|
+ unsigned int num_bars)
|
|
|
{
|
|
|
if (!vdev) {
|
|
|
vdev = kzalloc(sizeof(struct vnic_dev), GFP_ATOMIC);
|
|
@@ -695,7 +720,7 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
|
|
|
vdev->priv = priv;
|
|
|
vdev->pdev = pdev;
|
|
|
|
|
|
- if (vnic_dev_discover_res(vdev, bar))
|
|
|
+ if (vnic_dev_discover_res(vdev, bar, num_bars))
|
|
|
goto err_out;
|
|
|
|
|
|
vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
|