diff options
Diffstat (limited to 'drivers/net/enic/vnic_dev.c')
-rw-r--r-- | drivers/net/enic/vnic_dev.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 69b9b70c7da..d43a9d43bbf 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -23,6 +23,7 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/if_ether.h> +#include <linux/slab.h> #include "vnic_resource.h" #include "vnic_devcmd.h" @@ -573,22 +574,18 @@ int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr) return err; } -int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) +int vnic_dev_notify_setcmd(struct vnic_dev *vdev, + void *notify_addr, dma_addr_t notify_pa, u16 intr) { u64 a0, a1; int wait = 1000; int r; - if (!vdev->notify) { - vdev->notify = pci_alloc_consistent(vdev->pdev, - sizeof(struct vnic_devcmd_notify), - &vdev->notify_pa); - if (!vdev->notify) - return -ENOMEM; - memset(vdev->notify, 0, sizeof(struct vnic_devcmd_notify)); - } + memset(notify_addr, 0, sizeof(struct vnic_devcmd_notify)); + vdev->notify = notify_addr; + vdev->notify_pa = notify_pa; - a0 = vdev->notify_pa; + a0 = (u64)notify_pa; a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; a1 += sizeof(struct vnic_devcmd_notify); @@ -597,7 +594,27 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) return r; } -void vnic_dev_notify_unset(struct vnic_dev *vdev) +int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) +{ + void *notify_addr; + dma_addr_t notify_pa; + + if (vdev->notify || vdev->notify_pa) { + printk(KERN_ERR "notify block %p still allocated", + vdev->notify); + return -EINVAL; + } + + notify_addr = pci_alloc_consistent(vdev->pdev, + sizeof(struct vnic_devcmd_notify), + ¬ify_pa); + if (!notify_addr) + return -ENOMEM; + + return vnic_dev_notify_setcmd(vdev, notify_addr, notify_pa, intr); +} + +void vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) { u64 a0, a1; int wait = 1000; @@ -607,9 +624,23 @@ void vnic_dev_notify_unset(struct vnic_dev *vdev) a1 += sizeof(struct vnic_devcmd_notify); vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); + vdev->notify = NULL; + vdev->notify_pa = 0; vdev->notify_sz = 0; } +void vnic_dev_notify_unset(struct vnic_dev *vdev) +{ + if (vdev->notify) { + pci_free_consistent(vdev->pdev, + sizeof(struct vnic_devcmd_notify), + vdev->notify, + vdev->notify_pa); + } + + vnic_dev_notify_unsetcmd(vdev); +} + static int vnic_dev_notify_ready(struct vnic_dev *vdev) { u32 *words; |