diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2012-12-07 15:43:50 -0500 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2012-12-07 15:43:50 -0500 |
commit | 2007722a606bf9f195217f7afd2fbee4bc202c42 (patch) | |
tree | 991cbafd15d3686e028a9314804db8f3c264cd5d /drivers/vfio/pci | |
parent | 3a1f7041ddd59ec3aceb042892f811cc76e05288 (diff) |
vfio-pci: Re-order device reset
Move the device reset to the end of our disable path, the device
should already be stopped from pci_disable_device(). This also allows
us to manipulate the save/restore to avoid the save/reset/restore +
save/restore that we had before.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio/pci')
-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) |