diff options
| -rw-r--r-- | drivers/vfio/pci/vfio_pci_intrs.c | 44 |
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 | ||
| 766 | static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev, | 766 | static 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 | |||
| 805 | static 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 | |||
| 806 | int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags, | 820 | int 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) |
