summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
561d72d)
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>
MODULE_PARM_DESC(disable_vga, "Disable VGA resource access through vfio-pci");
#endif
MODULE_PARM_DESC(disable_vga, "Disable VGA resource access through vfio-pci");
#endif
+static bool disable_idle_d3;
+module_param(disable_idle_d3, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(disable_idle_d3,
+ "Disable using the PCI D3 low power state for idle, unused devices");
+
static DEFINE_MUTEX(driver_lock);
static inline bool vfio_vga_disabled(void)
static DEFINE_MUTEX(driver_lock);
static inline bool vfio_vga_disabled(void)
+ pci_set_power_state(pdev, PCI_D0);
+
/* Don't allow our initial saved state to include busmaster */
pci_clear_master(pdev);
/* Don't allow our initial saved state to include busmaster */
pci_clear_master(pdev);
pci_disable_device(pdev);
vfio_pci_try_bus_reset(vdev);
pci_disable_device(pdev);
vfio_pci_try_bus_reset(vdev);
+
+ if (!disable_idle_d3)
+ pci_set_power_state(pdev, PCI_D3hot);
}
static void vfio_pci_release(void *device_data)
}
static void vfio_pci_release(void *device_data)
vfio_pci_set_vga_decode(vdev, false));
}
vfio_pci_set_vga_decode(vdev, false));
}
+ if (!disable_idle_d3) {
+ /*
+ * pci-core sets the device power state to an unknown value at
+ * bootup and after being removed from a driver. The only
+ * transition it allows from this unknown state is to D0, which
+ * typically happens when a driver calls pci_enable_device().
+ * We're not ready to enable the device yet, but we do want to
+ * be able to get to D3. Therefore first do a D0 transition
+ * before going to D3.
+ */
+ pci_set_power_state(pdev, PCI_D0);
+ pci_set_power_state(pdev, PCI_D3hot);
+ }
+
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
}
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM |
VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
}
+
+ if (!disable_idle_d3)
+ pci_set_power_state(pdev, PCI_D0);
}
static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
}
static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
put_devs:
for (i = 0; i < devs.cur_index; i++) {
put_devs:
for (i = 0; i < devs.cur_index; i++) {
- if (!ret) {
- tmp = vfio_device_data(devs.devices[i]);
+ tmp = vfio_device_data(devs.devices[i]);
+ if (!ret)
tmp->needs_reset = false;
tmp->needs_reset = false;
+
+ if (!tmp->refcnt && !disable_idle_d3)
+ pci_set_power_state(tmp->pdev, PCI_D3hot);
+
vfio_device_put(devs.devices[i]);
}
vfio_device_put(devs.devices[i]);
}