aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2015-02-06 17:05:08 -0500
committerAlex Williamson <alex.williamson@redhat.com>2015-02-10 14:38:14 -0500
commit6140a8f5623820cec7f56c63444b9551d8d35775 (patch)
tree6493763d0a2122ca2258fc4b4b31801cd688b68f
parentcac80d6e382f63243ee4f31eb55afe22ed423e53 (diff)
vfio-pci: Add device request interface
Userspace can opt to receive a device request notification, indicating that the device should be released. This is setup the same way as the error IRQ and also supports eventfd signaling. Future support may forcefully remove the device from the user if the request is ignored. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r--drivers/vfio/pci/vfio_pci.c21
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c16
-rw-r--r--drivers/vfio/pci/vfio_pci_private.h1
-rw-r--r--include/uapi/linux/vfio.h1
4 files changed, 38 insertions, 1 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 7cc0122a18ce..f8a186381ae8 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -239,9 +239,12 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type)
239 239
240 return (flags & PCI_MSIX_FLAGS_QSIZE) + 1; 240 return (flags & PCI_MSIX_FLAGS_QSIZE) + 1;
241 } 241 }
242 } else if (irq_type == VFIO_PCI_ERR_IRQ_INDEX) 242 } else if (irq_type == VFIO_PCI_ERR_IRQ_INDEX) {
243 if (pci_is_pcie(vdev->pdev)) 243 if (pci_is_pcie(vdev->pdev))
244 return 1; 244 return 1;
245 } else if (irq_type == VFIO_PCI_REQ_IRQ_INDEX) {
246 return 1;
247 }
245 248
246 return 0; 249 return 0;
247} 250}
@@ -464,6 +467,7 @@ static long vfio_pci_ioctl(void *device_data,
464 467
465 switch (info.index) { 468 switch (info.index) {
466 case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSIX_IRQ_INDEX: 469 case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSIX_IRQ_INDEX:
470 case VFIO_PCI_REQ_IRQ_INDEX:
467 break; 471 break;
468 case VFIO_PCI_ERR_IRQ_INDEX: 472 case VFIO_PCI_ERR_IRQ_INDEX:
469 if (pci_is_pcie(vdev->pdev)) 473 if (pci_is_pcie(vdev->pdev))
@@ -828,6 +832,20 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
828 req_len, vma->vm_page_prot); 832 req_len, vma->vm_page_prot);
829} 833}
830 834
835static void vfio_pci_request(void *device_data, unsigned int count)
836{
837 struct vfio_pci_device *vdev = device_data;
838
839 mutex_lock(&vdev->igate);
840
841 if (vdev->req_trigger) {
842 dev_dbg(&vdev->pdev->dev, "Requesting device from user\n");
843 eventfd_signal(vdev->req_trigger, 1);
844 }
845
846 mutex_unlock(&vdev->igate);
847}
848
831static const struct vfio_device_ops vfio_pci_ops = { 849static const struct vfio_device_ops vfio_pci_ops = {
832 .name = "vfio-pci", 850 .name = "vfio-pci",
833 .open = vfio_pci_open, 851 .open = vfio_pci_open,
@@ -836,6 +854,7 @@ static const struct vfio_device_ops vfio_pci_ops = {
836 .read = vfio_pci_read, 854 .read = vfio_pci_read,
837 .write = vfio_pci_write, 855 .write = vfio_pci_write,
838 .mmap = vfio_pci_mmap, 856 .mmap = vfio_pci_mmap,
857 .request = vfio_pci_request,
839}; 858};
840 859
841static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 860static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index b134befbfd0e..f88bfdf5b6a0 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -817,6 +817,16 @@ static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
817 return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data); 817 return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data);
818} 818}
819 819
820static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
821 unsigned index, unsigned start,
822 unsigned count, uint32_t flags, void *data)
823{
824 if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count != 1)
825 return -EINVAL;
826
827 return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger, flags, data);
828}
829
820int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags, 830int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
821 unsigned index, unsigned start, unsigned count, 831 unsigned index, unsigned start, unsigned count,
822 void *data) 832 void *data)
@@ -858,6 +868,12 @@ int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
858 func = vfio_pci_set_err_trigger; 868 func = vfio_pci_set_err_trigger;
859 break; 869 break;
860 } 870 }
871 case VFIO_PCI_REQ_IRQ_INDEX:
872 switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
873 case VFIO_IRQ_SET_ACTION_TRIGGER:
874 func = vfio_pci_set_req_trigger;
875 break;
876 }
861 } 877 }
862 878
863 if (!func) 879 if (!func)
diff --git a/drivers/vfio/pci/vfio_pci_private.h b/drivers/vfio/pci/vfio_pci_private.h
index 671c17a6e6d0..c9f9b323f152 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -58,6 +58,7 @@ struct vfio_pci_device {
58 struct pci_saved_state *pci_saved_state; 58 struct pci_saved_state *pci_saved_state;
59 int refcnt; 59 int refcnt;
60 struct eventfd_ctx *err_trigger; 60 struct eventfd_ctx *err_trigger;
61 struct eventfd_ctx *req_trigger;
61}; 62};
62 63
63#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX) 64#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX)
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 29715d27548f..82889c30f4f5 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -333,6 +333,7 @@ enum {
333 VFIO_PCI_MSI_IRQ_INDEX, 333 VFIO_PCI_MSI_IRQ_INDEX,
334 VFIO_PCI_MSIX_IRQ_INDEX, 334 VFIO_PCI_MSIX_IRQ_INDEX,
335 VFIO_PCI_ERR_IRQ_INDEX, 335 VFIO_PCI_ERR_IRQ_INDEX,
336 VFIO_PCI_REQ_IRQ_INDEX,
336 VFIO_PCI_NUM_IRQS 337 VFIO_PCI_NUM_IRQS
337}; 338};
338 339