diff options
Diffstat (limited to 'drivers/misc/vmw_vmci/vmci_guest.c')
| -rw-r--r-- | drivers/misc/vmw_vmci/vmci_guest.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c index 60c01999f48..e0d5017785e 100644 --- a/drivers/misc/vmw_vmci/vmci_guest.c +++ b/drivers/misc/vmw_vmci/vmci_guest.c @@ -65,9 +65,11 @@ struct vmci_guest_device { void *data_buffer; void *notification_bitmap; + dma_addr_t notification_base; }; /* vmci_dev singleton device and supporting data*/ +struct pci_dev *vmci_pdev; static struct vmci_guest_device *vmci_dev_g; static DEFINE_SPINLOCK(vmci_dev_spinlock); @@ -163,7 +165,7 @@ static void vmci_guest_cid_update(u32 sub_id, * true if required hypercalls (or fallback hypercalls) are * supported by the host, false otherwise. */ -static bool vmci_check_host_caps(struct pci_dev *pdev) +static int vmci_check_host_caps(struct pci_dev *pdev) { bool result; struct vmci_resource_query_msg *msg; @@ -174,7 +176,7 @@ static bool vmci_check_host_caps(struct pci_dev *pdev) check_msg = kmalloc(msg_size, GFP_KERNEL); if (!check_msg) { dev_err(&pdev->dev, "%s: Insufficient memory\n", __func__); - return false; + return -ENOMEM; } check_msg->dst = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID, @@ -194,7 +196,7 @@ static bool vmci_check_host_caps(struct pci_dev *pdev) __func__, result ? "PASSED" : "FAILED"); /* We need the vector. There are no fallbacks. */ - return result; + return result ? 0 : -ENXIO; } /* @@ -381,11 +383,12 @@ static int vmci_enable_msix(struct pci_dev *pdev, vmci_dev->msix_entries[i].vector = i; } - result = pci_enable_msix(pdev, vmci_dev->msix_entries, VMCI_MAX_INTRS); + result = pci_enable_msix_exact(pdev, + vmci_dev->msix_entries, VMCI_MAX_INTRS); if (result == 0) vmci_dev->exclusive_vectors = true; - else if (result > 0) - result = pci_enable_msix(pdev, vmci_dev->msix_entries, 1); + else if (result == -ENOSPC) + result = pci_enable_msix_exact(pdev, vmci_dev->msix_entries, 1); return result; } @@ -528,7 +531,9 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, * well. */ if (capabilities & VMCI_CAPS_NOTIFICATIONS) { - vmci_dev->notification_bitmap = vmalloc(PAGE_SIZE); + vmci_dev->notification_bitmap = dma_alloc_coherent( + &pdev->dev, PAGE_SIZE, &vmci_dev->notification_base, + GFP_KERNEL); if (!vmci_dev->notification_bitmap) { dev_warn(&pdev->dev, "Unable to allocate notification bitmap\n"); @@ -546,6 +551,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, /* Set up global device so that we can start sending datagrams */ spin_lock_irq(&vmci_dev_spinlock); vmci_dev_g = vmci_dev; + vmci_pdev = pdev; spin_unlock_irq(&vmci_dev_spinlock); /* @@ -553,19 +559,20 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, * used. */ if (capabilities & VMCI_CAPS_NOTIFICATIONS) { - struct page *page = - vmalloc_to_page(vmci_dev->notification_bitmap); - unsigned long bitmap_ppn = page_to_pfn(page); + unsigned long bitmap_ppn = + vmci_dev->notification_base >> PAGE_SHIFT; if (!vmci_dbell_register_notification_bitmap(bitmap_ppn)) { dev_warn(&pdev->dev, "VMCI device unable to register notification bitmap with PPN 0x%x\n", (u32) bitmap_ppn); + error = -ENXIO; goto err_remove_vmci_dev_g; } } /* Check host capabilities. */ - if (!vmci_check_host_caps(pdev)) + error = vmci_check_host_caps(pdev); + if (error) goto err_remove_bitmap; /* Enable device. */ @@ -645,7 +652,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, return 0; err_free_irq: - free_irq(vmci_dev->irq, &vmci_dev); + free_irq(vmci_dev->irq, vmci_dev); tasklet_kill(&vmci_dev->datagram_tasklet); tasklet_kill(&vmci_dev->bm_tasklet); @@ -665,11 +672,14 @@ err_remove_bitmap: if (vmci_dev->notification_bitmap) { iowrite32(VMCI_CONTROL_RESET, vmci_dev->iobase + VMCI_CONTROL_ADDR); - vfree(vmci_dev->notification_bitmap); + dma_free_coherent(&pdev->dev, PAGE_SIZE, + vmci_dev->notification_bitmap, + vmci_dev->notification_base); } err_remove_vmci_dev_g: spin_lock_irq(&vmci_dev_spinlock); + vmci_pdev = NULL; vmci_dev_g = NULL; spin_unlock_irq(&vmci_dev_spinlock); @@ -699,6 +709,7 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) spin_lock_irq(&vmci_dev_spinlock); vmci_dev_g = NULL; + vmci_pdev = NULL; spin_unlock_irq(&vmci_dev_spinlock); dev_dbg(&pdev->dev, "Resetting vmci device\n"); @@ -727,7 +738,9 @@ static void vmci_guest_remove_device(struct pci_dev *pdev) * device, so we can safely free it here. */ - vfree(vmci_dev->notification_bitmap); + dma_free_coherent(&pdev->dev, PAGE_SIZE, + vmci_dev->notification_bitmap, + vmci_dev->notification_base); } vfree(vmci_dev->data_buffer); |
