Skip to content

Commit

Permalink
vfio: add local lock for virqfd instead of depending on VFIO PCI
Browse files Browse the repository at this point in the history
The Virqfd code needs to keep accesses to any struct *virqfd safe, but
this comes into play only when creating or destroying eventfds, so sharing
the same spinlock with the VFIO bus driver is not necessary.

Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Tested-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
  • Loading branch information
Antonios Motakis authored and Alex Williamson committed Mar 16, 2015
1 parent bb78e9e commit 9269c39
Showing 1 changed file with 16 additions and 15 deletions.
31 changes: 16 additions & 15 deletions drivers/vfio/pci/vfio_pci_intrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct virqfd {
};

static struct workqueue_struct *vfio_irqfd_cleanup_wq;
DEFINE_SPINLOCK(virqfd_lock);

int __init vfio_virqfd_init(void)
{
Expand Down Expand Up @@ -80,21 +81,21 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)

if (flags & POLLHUP) {
unsigned long flags;
spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
spin_lock_irqsave(&virqfd_lock, flags);

/*
* The eventfd is closing, if the virqfd has not yet been
* queued for release, as determined by testing whether the
* vdev pointer to it is still valid, queue it now. As
* virqfd pointer to it is still valid, queue it now. As
* with kvm irqfds, we know we won't race against the virqfd
* going away because we hold wqh->lock to get here.
* going away because we hold the lock to get here.
*/
if (*(virqfd->pvirqfd) == virqfd) {
*(virqfd->pvirqfd) = NULL;
virqfd_deactivate(virqfd);
}

spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
spin_unlock_irqrestore(&virqfd_lock, flags);
}

return 0;
Expand Down Expand Up @@ -170,16 +171,16 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
* we update the pointer to the virqfd under lock to avoid
* pushing multiple jobs to release the same virqfd.
*/
spin_lock_irq(&vdev->irqlock);
spin_lock_irq(&virqfd_lock);

if (*pvirqfd) {
spin_unlock_irq(&vdev->irqlock);
spin_unlock_irq(&virqfd_lock);
ret = -EBUSY;
goto err_busy;
}
*pvirqfd = virqfd;

spin_unlock_irq(&vdev->irqlock);
spin_unlock_irq(&virqfd_lock);

/*
* Install our own custom wake-up handling so we are notified via
Expand Down Expand Up @@ -217,18 +218,18 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
}
EXPORT_SYMBOL_GPL(vfio_virqfd_enable);

void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
void vfio_virqfd_disable(struct virqfd **pvirqfd)
{
unsigned long flags;

spin_lock_irqsave(&vdev->irqlock, flags);
spin_lock_irqsave(&virqfd_lock, flags);

if (*pvirqfd) {
virqfd_deactivate(*pvirqfd);
*pvirqfd = NULL;
}

spin_unlock_irqrestore(&vdev->irqlock, flags);
spin_unlock_irqrestore(&virqfd_lock, flags);

/*
* Block until we know all outstanding shutdown jobs have completed.
Expand Down Expand Up @@ -441,8 +442,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
static void vfio_intx_disable(struct vfio_pci_device *vdev)
{
vfio_intx_set_signal(vdev, -1);
vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
vfio_virqfd_disable(&vdev->ctx[0].unmask);
vfio_virqfd_disable(&vdev->ctx[0].mask);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
vdev->num_ctx = 0;
kfree(vdev->ctx);
Expand Down Expand Up @@ -606,8 +607,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);

for (i = 0; i < vdev->num_ctx; i++) {
vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
vfio_virqfd_disable(&vdev->ctx[i].unmask);
vfio_virqfd_disable(&vdev->ctx[i].mask);
}

if (msix) {
Expand Down Expand Up @@ -645,7 +646,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
vfio_send_intx_eventfd, NULL,
&vdev->ctx[0].unmask, fd);

vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
vfio_virqfd_disable(&vdev->ctx[0].unmask);
}

return 0;
Expand Down

0 comments on commit 9269c39

Please sign in to comment.