summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2010-12-30 00:58:23 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2010-12-30 00:58:23 +0000
commit32bd7fe9c773fabea4ccb046c85401487e38828d (patch)
treea03ec56bc46059ed0a400bef1ebd1e6519c1395c /sys/dev
parentc42032db4e5a5b1ee9bd960e0214fb455fac52e8 (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.c30
-rw-r--r--sys/dev/pci/ppb.c16
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);
}