aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index e8d695b3f54e..b134befbfd0e 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -763,46 +763,60 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
763 return 0; 763 return 0;
764} 764}
765 765
766static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev, 766static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,
767 unsigned index, unsigned start, 767 uint32_t flags, void *data)
768 unsigned count, uint32_t flags, void *data)
769{ 768{
770 int32_t fd = *(int32_t *)data; 769 int32_t fd = *(int32_t *)data;
771 770
772 if ((index != VFIO_PCI_ERR_IRQ_INDEX) || 771 if (!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
773 !(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
774 return -EINVAL; 772 return -EINVAL;
775 773
776 /* DATA_NONE/DATA_BOOL enables loopback testing */ 774 /* DATA_NONE/DATA_BOOL enables loopback testing */
777 if (flags & VFIO_IRQ_SET_DATA_NONE) { 775 if (flags & VFIO_IRQ_SET_DATA_NONE) {
778 if (vdev->err_trigger) 776 if (*ctx)
779 eventfd_signal(vdev->err_trigger, 1); 777 eventfd_signal(*ctx, 1);
780 return 0; 778 return 0;
781 } else if (flags & VFIO_IRQ_SET_DATA_BOOL) { 779 } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
782 uint8_t trigger = *(uint8_t *)data; 780 uint8_t trigger = *(uint8_t *)data;
783 if (trigger && vdev->err_trigger) 781 if (trigger && *ctx)
784 eventfd_signal(vdev->err_trigger, 1); 782 eventfd_signal(*ctx, 1);
785 return 0; 783 return 0;
786 } 784 }
787 785
788 /* Handle SET_DATA_EVENTFD */ 786 /* Handle SET_DATA_EVENTFD */
789 if (fd == -1) { 787 if (fd == -1) {
790 if (vdev->err_trigger) 788 if (*ctx)
791 eventfd_ctx_put(vdev->err_trigger); 789 eventfd_ctx_put(*ctx);
792 vdev->err_trigger = NULL; 790 *ctx = NULL;
793 return 0; 791 return 0;
794 } else if (fd >= 0) { 792 } else if (fd >= 0) {
795 struct eventfd_ctx *efdctx; 793 struct eventfd_ctx *efdctx;
796 efdctx = eventfd_ctx_fdget(fd); 794 efdctx = eventfd_ctx_fdget(fd);
797 if (IS_ERR(efdctx)) 795 if (IS_ERR(efdctx))
798 return PTR_ERR(efdctx); 796 return PTR_ERR(efdctx);
799 if (vdev->err_trigger) 797 if (*ctx)
800 eventfd_ctx_put(vdev->err_trigger); 798 eventfd_ctx_put(*ctx);
801 vdev->err_trigger = efdctx; 799 *ctx = efdctx;
802 return 0; 800 return 0;
803 } else 801 } else
804 return -EINVAL; 802 return -EINVAL;
805} 803}
804
805static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
806 unsigned index, unsigned start,
807 unsigned count, uint32_t flags, void *data)
808{
809 if (index != VFIO_PCI_ERR_IRQ_INDEX)
810 return -EINVAL;
811
812 /*
813 * We should sanitize start & count, but that wasn't caught
814 * originally, so this IRQ index must forever ignore them :-(
815 */
816
817 return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data);
818}
819
806int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags, 820int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
807 unsigned index, unsigned start, unsigned count, 821 unsigned index, unsigned start, unsigned count,
808 void *data) 822 void *data)