diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2012-12-07 15:43:51 -0500 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2012-12-07 15:43:51 -0500 |
commit | 9a92c5091a42c565ede818fdf204c4f60004d0d8 (patch) | |
tree | 2b6d75e83a08b892c3500b09855feeaecc9d9f60 /drivers | |
parent | 05bf3aac930752408bf38a3f070061fc5f1b9c73 (diff) |
vfio-pci: Enable device before attempting reset
Devices making use of PM reset are getting incorrectly identified as
not supporting reset because pci_pm_reset() fails unless the device is
in D0 power state. When first attached to vfio_pci devices are
typically in an unknown power state. We can fix this by explicitly
setting the power state or simply calling pci_enable_device() before
attempting a pci_reset_function(). We need to enable the device
anyway, so move this up in our vfio_pci_enable() function, which also
simplifies the error path a bit.
Note that pci_disable_device() does not explicitly set the power
state, so there's no need to re-order vfio_pci_disable().
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 23 |
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 306b90cf051f..b28e66c4376a 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
@@ -43,6 +43,10 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) | |||
43 | u16 cmd; | 43 | u16 cmd; |
44 | u8 msix_pos; | 44 | u8 msix_pos; |
45 | 45 | ||
46 | ret = pci_enable_device(pdev); | ||
47 | if (ret) | ||
48 | return ret; | ||
49 | |||
46 | vdev->reset_works = (pci_reset_function(pdev) == 0); | 50 | vdev->reset_works = (pci_reset_function(pdev) == 0); |
47 | pci_save_state(pdev); | 51 | pci_save_state(pdev); |
48 | vdev->pci_saved_state = pci_store_saved_state(pdev); | 52 | vdev->pci_saved_state = pci_store_saved_state(pdev); |
@@ -51,8 +55,11 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) | |||
51 | __func__, dev_name(&pdev->dev)); | 55 | __func__, dev_name(&pdev->dev)); |
52 | 56 | ||
53 | ret = vfio_config_init(vdev); | 57 | ret = vfio_config_init(vdev); |
54 | if (ret) | 58 | if (ret) { |
55 | goto out; | 59 | pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state); |
60 | pci_disable_device(pdev); | ||
61 | return ret; | ||
62 | } | ||
56 | 63 | ||
57 | if (likely(!nointxmask)) | 64 | if (likely(!nointxmask)) |
58 | vdev->pci_2_3 = pci_intx_mask_supported(pdev); | 65 | vdev->pci_2_3 = pci_intx_mask_supported(pdev); |
@@ -77,17 +84,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) | |||
77 | } else | 84 | } else |
78 | vdev->msix_bar = 0xFF; | 85 | vdev->msix_bar = 0xFF; |
79 | 86 | ||
80 | ret = pci_enable_device(pdev); | 87 | return 0; |
81 | if (ret) | ||
82 | goto out; | ||
83 | |||
84 | return ret; | ||
85 | |||
86 | out: | ||
87 | kfree(vdev->pci_saved_state); | ||
88 | vdev->pci_saved_state = NULL; | ||
89 | vfio_config_free(vdev); | ||
90 | return ret; | ||
91 | } | 88 | } |
92 | 89 | ||
93 | static void vfio_pci_disable(struct vfio_pci_device *vdev) | 90 | static void vfio_pci_disable(struct vfio_pci_device *vdev) |