aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2015-04-07 13:14:46 -0400
committerAlex Williamson <alex.williamson@redhat.com>2015-04-07 13:14:46 -0400
commit6eb7018705de09b4138ca05d6a157203e0ea791a (patch)
tree3febc7c9c86ca1ec65c57529501f70c26d9322ba /drivers/vfio
parent561d72ddbbe480e2cae6c1a63c688986586ef2b1 (diff)
vfio-pci: Move idle devices to D3hot power state
We can save some power by putting devices that are bound to vfio-pci but not in use by the user in the D3hot power state. Devices get woken into D0 when opened by the user. Resets return the device to D0, so we need to re-apply the low power state after a bus reset. It's tempting to try to use D3cold, but we have no reason to inhibit hotplug of idle devices and we might get into a loop of having the device disappear before we have a chance to try to use it. A new module parameter allows this feature to be disabled if there are devices that misbehave as a result of this change. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r--drivers/vfio/pci/vfio_pci.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index d0f1e7026d5d..049b9e9e0a41 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -50,6 +50,11 @@ module_param(disable_vga, bool, S_IRUGO);
50MODULE_PARM_DESC(disable_vga, "Disable VGA resource access through vfio-pci"); 50MODULE_PARM_DESC(disable_vga, "Disable VGA resource access through vfio-pci");
51#endif 51#endif
52 52
53static bool disable_idle_d3;
54module_param(disable_idle_d3, bool, S_IRUGO | S_IWUSR);
55MODULE_PARM_DESC(disable_idle_d3,
56 "Disable using the PCI D3 low power state for idle, unused devices");
57
53static DEFINE_MUTEX(driver_lock); 58static DEFINE_MUTEX(driver_lock);
54 59
55static inline bool vfio_vga_disabled(void) 60static inline bool vfio_vga_disabled(void)
@@ -114,6 +119,8 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev)
114 u16 cmd; 119 u16 cmd;
115 u8 msix_pos; 120 u8 msix_pos;
116 121
122 pci_set_power_state(pdev, PCI_D0);
123
117 /* Don't allow our initial saved state to include busmaster */ 124 /* Don't allow our initial saved state to include busmaster */
118 pci_clear_master(pdev); 125 pci_clear_master(pdev);
119 126
@@ -225,6 +232,9 @@ out:
225 pci_disable_device(pdev); 232 pci_disable_device(pdev);
226 233
227 vfio_pci_try_bus_reset(vdev); 234 vfio_pci_try_bus_reset(vdev);
235
236 if (!disable_idle_d3)
237 pci_set_power_state(pdev, PCI_D3hot);
228} 238}
229 239
230static void vfio_pci_release(void *device_data) 240static void vfio_pci_release(void *device_data)
@@ -951,6 +961,20 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
951 vfio_pci_set_vga_decode(vdev, false)); 961 vfio_pci_set_vga_decode(vdev, false));
952 } 962 }
953 963
964 if (!disable_idle_d3) {
965 /*
966 * pci-core sets the device power state to an unknown value at
967 * bootup and after being removed from a driver. The only
968 * transition it allows from this unknown state is to D0, which
969 * typically happens when a driver calls pci_enable_device().
970 * We're not ready to enable the device yet, but we do want to
971 * be able to get to D3. Therefore first do a D0 transition
972 * before going to D3.
973 */
974 pci_set_power_state(pdev, PCI_D0);
975 pci_set_power_state(pdev, PCI_D3hot);
976 }
977
954 return ret; 978 return ret;
955} 979}
956 980
@@ -971,6 +995,9 @@ static void vfio_pci_remove(struct pci_dev *pdev)
971 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM | 995 VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
972 VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); 996 VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
973 } 997 }
998
999 if (!disable_idle_d3)
1000 pci_set_power_state(pdev, PCI_D0);
974} 1001}
975 1002
976static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, 1003static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
@@ -1089,10 +1116,13 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_device *vdev)
1089 1116
1090put_devs: 1117put_devs:
1091 for (i = 0; i < devs.cur_index; i++) { 1118 for (i = 0; i < devs.cur_index; i++) {
1092 if (!ret) { 1119 tmp = vfio_device_data(devs.devices[i]);
1093 tmp = vfio_device_data(devs.devices[i]); 1120 if (!ret)
1094 tmp->needs_reset = false; 1121 tmp->needs_reset = false;
1095 } 1122
1123 if (!tmp->refcnt && !disable_idle_d3)
1124 pci_set_power_state(tmp->pdev, PCI_D3hot);
1125
1096 vfio_device_put(devs.devices[i]); 1126 vfio_device_put(devs.devices[i]);
1097 } 1127 }
1098 1128