diff options
| -rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 43 |
1 files changed, 31 insertions, 12 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index a4dc21b9cb06..b179f5a357f6 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
| @@ -92,9 +92,10 @@ out: | |||
| 92 | 92 | ||
| 93 | static void vfio_pci_disable(struct vfio_pci_device *vdev) | 93 | static void vfio_pci_disable(struct vfio_pci_device *vdev) |
| 94 | { | 94 | { |
| 95 | struct pci_dev *pdev = vdev->pdev; | ||
| 95 | int bar; | 96 | int bar; |
| 96 | 97 | ||
| 97 | pci_disable_device(vdev->pdev); | 98 | pci_disable_device(pdev); |
| 98 | 99 | ||
| 99 | vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE | | 100 | vfio_pci_set_irqs_ioctl(vdev, VFIO_IRQ_SET_DATA_NONE | |
| 100 | VFIO_IRQ_SET_ACTION_TRIGGER, | 101 | VFIO_IRQ_SET_ACTION_TRIGGER, |
| @@ -104,22 +105,40 @@ static void vfio_pci_disable(struct vfio_pci_device *vdev) | |||
| 104 | 105 | ||
| 105 | vfio_config_free(vdev); | 106 | vfio_config_free(vdev); |
| 106 | 107 | ||
| 107 | pci_reset_function(vdev->pdev); | ||
| 108 | |||
| 109 | if (pci_load_and_free_saved_state(vdev->pdev, | ||
| 110 | &vdev->pci_saved_state) == 0) | ||
| 111 | pci_restore_state(vdev->pdev); | ||
| 112 | else | ||
| 113 | pr_info("%s: Couldn't reload %s saved state\n", | ||
| 114 | __func__, dev_name(&vdev->pdev->dev)); | ||
| 115 | |||
| 116 | for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) { | 108 | for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) { |
| 117 | if (!vdev->barmap[bar]) | 109 | if (!vdev->barmap[bar]) |
| 118 | continue; | 110 | continue; |
| 119 | pci_iounmap(vdev->pdev, vdev->barmap[bar]); | 111 | pci_iounmap(pdev, vdev->barmap[bar]); |
| 120 | pci_release_selected_regions(vdev->pdev, 1 << bar); | 112 | pci_release_selected_regions(pdev, 1 << bar); |
| 121 | vdev->barmap[bar] = NULL; | 113 | vdev->barmap[bar] = NULL; |
| 122 | } | 114 | } |
| 115 | |||
| 116 | /* | ||
| 117 | * If we have saved state, restore it. If we can reset the device, | ||
| 118 | * even better. Resetting with current state seems better than | ||
| 119 | * nothing, but saving and restoring current state without reset | ||
| 120 | * is just busy work. | ||
| 121 | */ | ||
| 122 | if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) { | ||
| 123 | pr_info("%s: Couldn't reload %s saved state\n", | ||
| 124 | __func__, dev_name(&pdev->dev)); | ||
| 125 | |||
| 126 | if (!vdev->reset_works) | ||
| 127 | return; | ||
| 128 | |||
| 129 | pci_save_state(pdev); | ||
| 130 | } | ||
| 131 | |||
| 132 | /* | ||
| 133 | * Disable INTx and MSI, presumably to avoid spurious interrupts | ||
| 134 | * during reset. Stolen from pci_reset_function() | ||
| 135 | */ | ||
| 136 | pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE); | ||
| 137 | |||
| 138 | if (vdev->reset_works) | ||
| 139 | __pci_reset_function(pdev); | ||
| 140 | |||
| 141 | pci_restore_state(pdev); | ||
| 123 | } | 142 | } |
| 124 | 143 | ||
| 125 | static void vfio_pci_release(void *device_data) | 144 | static void vfio_pci_release(void *device_data) |
