aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/pci
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2012-12-07 15:43:50 -0500
committerAlex Williamson <alex.williamson@redhat.com>2012-12-07 15:43:50 -0500
commit2007722a606bf9f195217f7afd2fbee4bc202c42 (patch)
tree991cbafd15d3686e028a9314804db8f3c264cd5d /drivers/vfio/pci
parent3a1f7041ddd59ec3aceb042892f811cc76e05288 (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.c43
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
93static void vfio_pci_disable(struct vfio_pci_device *vdev) 93static 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
125static void vfio_pci_release(void *device_data) 144static void vfio_pci_release(void *device_data)