diff options
Diffstat (limited to 'drivers/vfio/pci/vfio_pci.c')
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 09d2e3ffd6fc..ac3725440d64 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
@@ -201,7 +201,9 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) | |||
201 | 201 | ||
202 | return (flags & PCI_MSIX_FLAGS_QSIZE) + 1; | 202 | return (flags & PCI_MSIX_FLAGS_QSIZE) + 1; |
203 | } | 203 | } |
204 | } | 204 | } else if (irq_type == VFIO_PCI_ERR_IRQ_INDEX) |
205 | if (pci_is_pcie(vdev->pdev)) | ||
206 | return 1; | ||
205 | 207 | ||
206 | return 0; | 208 | return 0; |
207 | } | 209 | } |
@@ -317,6 +319,17 @@ static long vfio_pci_ioctl(void *device_data, | |||
317 | if (info.argsz < minsz || info.index >= VFIO_PCI_NUM_IRQS) | 319 | if (info.argsz < minsz || info.index >= VFIO_PCI_NUM_IRQS) |
318 | return -EINVAL; | 320 | return -EINVAL; |
319 | 321 | ||
322 | switch (info.index) { | ||
323 | case VFIO_PCI_INTX_IRQ_INDEX ... VFIO_PCI_MSIX_IRQ_INDEX: | ||
324 | break; | ||
325 | case VFIO_PCI_ERR_IRQ_INDEX: | ||
326 | if (pci_is_pcie(vdev->pdev)) | ||
327 | break; | ||
328 | /* pass thru to return error */ | ||
329 | default: | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | |||
320 | info.flags = VFIO_IRQ_INFO_EVENTFD; | 333 | info.flags = VFIO_IRQ_INFO_EVENTFD; |
321 | 334 | ||
322 | info.count = vfio_pci_get_irq_count(vdev, info.index); | 335 | info.count = vfio_pci_get_irq_count(vdev, info.index); |
@@ -552,11 +565,40 @@ static void vfio_pci_remove(struct pci_dev *pdev) | |||
552 | kfree(vdev); | 565 | kfree(vdev); |
553 | } | 566 | } |
554 | 567 | ||
568 | static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, | ||
569 | pci_channel_state_t state) | ||
570 | { | ||
571 | struct vfio_pci_device *vdev; | ||
572 | struct vfio_device *device; | ||
573 | |||
574 | device = vfio_device_get_from_dev(&pdev->dev); | ||
575 | if (device == NULL) | ||
576 | return PCI_ERS_RESULT_DISCONNECT; | ||
577 | |||
578 | vdev = vfio_device_data(device); | ||
579 | if (vdev == NULL) { | ||
580 | vfio_device_put(device); | ||
581 | return PCI_ERS_RESULT_DISCONNECT; | ||
582 | } | ||
583 | |||
584 | if (vdev->err_trigger) | ||
585 | eventfd_signal(vdev->err_trigger, 1); | ||
586 | |||
587 | vfio_device_put(device); | ||
588 | |||
589 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
590 | } | ||
591 | |||
592 | static struct pci_error_handlers vfio_err_handlers = { | ||
593 | .error_detected = vfio_pci_aer_err_detected, | ||
594 | }; | ||
595 | |||
555 | static struct pci_driver vfio_pci_driver = { | 596 | static struct pci_driver vfio_pci_driver = { |
556 | .name = "vfio-pci", | 597 | .name = "vfio-pci", |
557 | .id_table = NULL, /* only dynamic ids */ | 598 | .id_table = NULL, /* only dynamic ids */ |
558 | .probe = vfio_pci_probe, | 599 | .probe = vfio_pci_probe, |
559 | .remove = vfio_pci_remove, | 600 | .remove = vfio_pci_remove, |
601 | .err_handler = &vfio_err_handlers, | ||
560 | }; | 602 | }; |
561 | 603 | ||
562 | static void __exit vfio_pci_cleanup(void) | 604 | static void __exit vfio_pci_cleanup(void) |