summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2010-10-15 21:39:51 +0000
committerjkim <jkim@FreeBSD.org>2010-10-15 21:39:51 +0000
commit59bb6f5773b58d7dfda84887b29b47eae0bbe680 (patch)
treedc65cff2d974aef397a851659ad14f57e4ce3a86 /sys/dev
parent1cef14c1d4d84dd65444d4db2df33c2521d3a5a8 (diff)
downloadFreeBSD-src-59bb6f5773b58d7dfda84887b29b47eae0bbe680.zip
FreeBSD-src-59bb6f5773b58d7dfda84887b29b47eae0bbe680.tar.gz
Move setting power state for children into a separate function as they were
essentially the same. This also restores hw.pci.do_power_resume tunable, which was broken since r211430. Reviewed by: jhb
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/pci.c78
1 files changed, 40 insertions, 38 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 071f257..9dedbdc 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -2903,12 +2903,43 @@ pci_attach(device_t dev)
return (bus_generic_attach(dev));
}
+static void
+pci_set_power_children(device_t dev, device_t *devlist, int numdevs,
+ int state)
+{
+ device_t child, pcib;
+ struct pci_devinfo *dinfo;
+ int dstate, i;
+
+ if (!pci_do_power_resume)
+ return;
+
+ /*
+ * Set the device to the given state. If the firmware suggests
+ * a different power state, use it instead. If power management
+ * is not present, the firmware is responsible for managing
+ * device power. Skip children who aren't attached since they
+ * are handled separately. Only manage type 0 devices for now.
+ */
+ pcib = device_get_parent(dev);
+ for (i = 0; i < numdevs; i++) {
+ child = devlist[i];
+ dinfo = device_get_ivars(child);
+ dstate = state;
+ if (device_is_attached(child) &&
+ (dinfo->cfg.hdrtype & PCIM_HDRTYPE) ==
+ PCIM_HDRTYPE_NORMAL &&
+ PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
+ pci_set_powerstate(child, dstate);
+ }
+}
+
int
pci_suspend(device_t dev)
{
- int dstate, error, i, numdevs;
- device_t child, *devlist, pcib;
+ device_t child, *devlist;
struct pci_devinfo *dinfo;
+ int error, i, numdevs;
/*
* Save the PCI configuration space for each child and set the
@@ -2928,26 +2959,7 @@ pci_suspend(device_t dev)
free(devlist, M_TEMP);
return (error);
}
-
- /*
- * Always set the device to D3. If the firmware suggests a
- * different power state, use it instead. If power management
- * is not present, the firmware is responsible for managing
- * device power. Skip children who aren't attached since they
- * are powered down separately. Only manage type 0 devices
- * for now.
- */
- pcib = device_get_parent(dev);
- for (i = 0; pci_do_power_resume && i < numdevs; i++) {
- child = devlist[i];
- dinfo = (struct pci_devinfo *) device_get_ivars(child);
- dstate = PCI_POWERSTATE_D3;
- if (device_is_attached(child) &&
- (dinfo->cfg.hdrtype & PCIM_HDRTYPE) ==
- PCIM_HDRTYPE_NORMAL &&
- PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
- pci_set_powerstate(child, dstate);
- }
+ pci_set_power_children(dev, devlist, numdevs, PCI_POWERSTATE_D3);
free(devlist, M_TEMP);
return (0);
}
@@ -2955,32 +2967,22 @@ pci_suspend(device_t dev)
int
pci_resume(device_t dev)
{
- int i, numdevs, error;
- device_t child, *devlist, pcib;
+ device_t child, *devlist;
struct pci_devinfo *dinfo;
+ int error, i, numdevs;
/*
* Set each child to D0 and restore its PCI configuration space.
*/
if ((error = device_get_children(dev, &devlist, &numdevs)) != 0)
return (error);
- pcib = device_get_parent(dev);
+ pci_set_power_children(dev, devlist, numdevs, PCI_POWERSTATE_D0);
+
+ /* Now the device is powered up, restore its config space. */
for (i = 0; i < numdevs; i++) {
- /*
- * Notify power managment we're going to D0 but ignore
- * the result. If power management is not present,
- * the firmware is responsible for managing device
- * power. Only manage type 0 devices for now.
- */
child = devlist[i];
- dinfo = (struct pci_devinfo *) device_get_ivars(child);
- if (device_is_attached(child) &&
- (dinfo->cfg.hdrtype & PCIM_HDRTYPE) ==
- PCIM_HDRTYPE_NORMAL &&
- PCIB_POWER_FOR_SLEEP(pcib, dev, NULL) == 0)
- pci_set_powerstate(child, PCI_POWERSTATE_D0);
+ dinfo = device_get_ivars(child);
- /* Now the device is powered up, restore its config space. */
pci_cfg_restore(child, dinfo);
if (!device_is_attached(child))
pci_cfg_save(child, dinfo, 1);
OpenPOWER on IntegriCloud