diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-12-30 00:58:23 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-12-30 00:58:23 +0000 |
commit | 32bd7fe9c773fabea4ccb046c85401487e38828d (patch) | |
tree | a03ec56bc46059ed0a400bef1ebd1e6519c1395c /sys/dev | |
parent | c42032db4e5a5b1ee9bd960e0214fb455fac52e8 (diff) |
Only disable I/O and memory space and bus mastering if we're actually going
to put the device into D3. Fixes PCI power management issues that prevented
acpi (and perhaps apm) suspend on some machines.
tested by & ok mlarkin@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/pci.c | 30 | ||||
-rw-r--r-- | sys/dev/pci/ppb.c | 16 |
2 files changed, 19 insertions, 27 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 12af24d0172..c073ac705f7 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci.c,v 1.87 2010/12/04 17:08:20 miod Exp $ */ +/* $OpenBSD: pci.c,v 1.88 2010/12/30 00:58:22 kettenis Exp $ */ /* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */ /* @@ -215,7 +215,7 @@ void pci_suspend(struct pci_softc *sc) { struct pci_dev *pd; - pcireg_t bhlc, csr; + pcireg_t bhlc; int i; LIST_FOREACH(pd, &sc->sc_devs, pd_next) { @@ -240,18 +240,7 @@ pci_suspend(struct pci_softc *sc) PCI_INTERRUPT_REG); if (pci_dopm) { - /* - * Place the device into D3. The PCI Power - * Management spec says we should disable I/O - * and memory space as well as bus mastering - * before we do so. - */ - csr = pd->pd_csr; - csr &= ~PCI_COMMAND_IO_ENABLE; - csr &= ~PCI_COMMAND_MEM_ENABLE; - csr &= ~PCI_COMMAND_MASTER_ENABLE; - pci_conf_write(sc->sc_pc, pd->pd_tag, - PCI_COMMAND_STATUS_REG, csr); + /* Place the device into D3. */ pd->pd_pmcsr_state = pci_get_powerstate(sc->sc_pc, pd->pd_tag); pci_set_powerstate(sc->sc_pc, pd->pd_tag, @@ -567,6 +556,19 @@ pci_set_powerstate(pci_chipset_tag_t pc, pcitag_t tag, int state) int offset; if (pci_get_capability(pc, tag, PCI_CAP_PWRMGMT, &offset, 0)) { + if (state == PCI_PMCSR_STATE_D3) { + /* + * The PCI Power Management spec says we + * should disable I/O and memory space as well + * as bus mastering before we place the device + * into D3. + */ + reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); + reg &= ~PCI_COMMAND_IO_ENABLE; + reg &= ~PCI_COMMAND_MEM_ENABLE; + reg &= ~PCI_COMMAND_MASTER_ENABLE; + pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg); + } reg = pci_conf_read(pc, tag, offset + PCI_PMCSR); if ((reg & PCI_PMCSR_STATE_MASK) != state) { pci_conf_write(pc, tag, offset + PCI_PMCSR, diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c index e07e5f9f50a..9524bc80fad 100644 --- a/sys/dev/pci/ppb.c +++ b/sys/dev/pci/ppb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ppb.c,v 1.46 2010/09/25 19:23:39 mlarkin Exp $ */ +/* $OpenBSD: ppb.c,v 1.47 2010/12/30 00:58:22 kettenis Exp $ */ /* $NetBSD: ppb.c,v 1.16 1997/06/06 23:48:05 thorpej Exp $ */ /* @@ -346,7 +346,7 @@ ppbactivate(struct device *self, int act) struct ppb_softc *sc = (void *)self; pci_chipset_tag_t pc = sc->sc_pc; pcitag_t tag = sc->sc_tag; - pcireg_t blr, csr, reg; + pcireg_t blr, reg; int rv = 0; switch (act) { @@ -367,17 +367,7 @@ ppbactivate(struct device *self, int act) sc->sc_cap_off + PCI_PCIE_SLCSR); if (pci_dopm) { - /* - * Place the bridge into D3. The PCI Power - * Management spec says we should disable I/O - * and memory space as well as bus mastering - * before we do so. - */ - csr = sc->sc_csr; - csr &= ~PCI_COMMAND_IO_ENABLE; - csr &= ~PCI_COMMAND_MEM_ENABLE; - csr &= ~PCI_COMMAND_MASTER_ENABLE; - pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); + /* Place the bridge into D3. */ sc->sc_pmcsr_state = pci_get_powerstate(pc, tag); pci_set_powerstate(pc, tag, PCI_PMCSR_STATE_D3); } |