Index: sys/dev/pci/pci.c =================================================================== --- sys/dev/pci/pci.c +++ sys/dev/pci/pci.c @@ -138,7 +138,7 @@ DEVMETHOD(device_attach, pci_attach), DEVMETHOD(device_detach, pci_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_suspend, pci_suspend), DEVMETHOD(device_resume, pci_resume), /* Bus interface */ @@ -4383,13 +4383,32 @@ /* Suspend devices before potentially powering them down. */ error = bus_generic_suspend_child(dev, child); + return (error); +} - if (error) +int +pci_suspend(device_t dev) +{ + device_t child, *devlist; + int error, i, numdevs; + + if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) return (error); - if (pci_do_power_suspend) - pci_set_power_child(dev, child, PCI_POWERSTATE_D3); + error = bus_generic_suspend(dev); + if (error != 0) { + free(devlist, M_TEMP); + return (error); + } + /* After drivers are suspended, power down the devices. */ + if (pci_do_power_suspend) { + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + pci_set_power_child(dev, child, PCI_POWERSTATE_D3); + } + } + free(devlist, M_TEMP); return (0); } @@ -4398,16 +4417,12 @@ { struct pci_devinfo *dinfo; - if (pci_do_power_resume) - pci_set_power_child(dev, child, PCI_POWERSTATE_D0); - dinfo = device_get_ivars(child); pci_cfg_restore(child, dinfo); if (!device_is_attached(child)) pci_cfg_save(child, dinfo, 1); bus_generic_resume_child(dev, child); - return (0); } @@ -4419,6 +4434,14 @@ if ((error = device_get_children(dev, &devlist, &numdevs)) != 0) return (error); + + /* Before anything else, power up the devices. */ + if (pci_do_power_resume) { + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + pci_set_power_child(dev, child, PCI_POWERSTATE_D0); + } + } /* * Resume critical devices first, then everything else later. Index: sys/dev/pci/pci_private.h =================================================================== --- sys/dev/pci/pci_private.h +++ sys/dev/pci/pci_private.h @@ -138,6 +138,7 @@ char *buf, size_t buflen); int pci_assign_interrupt_method(device_t dev, device_t child); int pci_resume(device_t dev); +int pci_suspend(device_t dev); int pci_resume_child(device_t dev, device_t child); int pci_suspend_child(device_t dev, device_t child); bus_dma_tag_t pci_get_dma_tag(device_t bus, device_t dev);