On Wednesday 29 December 2010 18:10:16 Mark Kettenis wrote:
> For those that have problems with (acpi) suspend/resume that can be
> fixed by setting pci_dopm to 0, please test the diff below.  This
> fixes a flaw in the powermanagement code where we would disable
> devices (and in particular PCI-PCI bridges) even if those devices
> don't support powermanagement.
>
> Also, it would be interesting if people with working apm
> suspend/resume could test this diff and set pci_dopm to 1.
>
> Thanks,
>
> Mark

With this suspend/resume now works without disabling PCI power management
with the ThinkPad X100e.

>
> Index: pci.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/pci.c,v
> retrieving revision 1.87
> diff -u -p -r1.87 pci.c
> --- pci.c     4 Dec 2010 17:08:20 -0000       1.87
> +++ pci.c     29 Dec 2010 23:02:29 -0000
> @@ -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,
>       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,
> Index: ppb.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/ppb.c,v
> retrieving revision 1.46
> diff -u -p -r1.46 ppb.c
> --- ppb.c     25 Sep 2010 19:23:39 -0000      1.46
> +++ ppb.c     29 Dec 2010 23:02:29 -0000
> @@ -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);
>               }



-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to