Another small piece of the puzzle. I'd appreciate it if people could give this a quick test on their machines. If you have working suspend/resume, please make sure it doesn't break with this diff.
Index: pci.c =================================================================== RCS file: /cvs/src/sys/dev/pci/pci.c,v retrieving revision 1.89 diff -u -p -r1.89 pci.c --- pci.c 12 Apr 2011 20:29:35 -0000 1.89 +++ pci.c 14 May 2011 09:58:57 -0000 @@ -63,6 +63,10 @@ struct pci_dev { pcireg_t pd_int; pcireg_t pd_map[NMAPREG]; pcireg_t pd_mask[NMAPREG]; + pcireg_t pd_msi_mc; + pcireg_t pd_msi_ma; + pcireg_t pd_msi_mau32; + pcireg_t pd_msi_md; int pd_pmcsr_state; }; @@ -215,8 +219,8 @@ void pci_suspend(struct pci_softc *sc) { struct pci_dev *pd; - pcireg_t bhlc; - int i; + pcireg_t bhlc, reg; + int off, i; LIST_FOREACH(pd, &sc->sc_devs, pd_next) { /* @@ -239,6 +243,22 @@ pci_suspend(struct pci_softc *sc) pd->pd_int = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_INTERRUPT_REG); + if (pci_get_capability(sc->sc_pc, pd->pd_tag, + PCI_CAP_MSI, &off, ®)) { + pd->pd_msi_ma = pci_conf_read(sc->sc_pc, pd->pd_tag, + off + PCI_MSI_MA); + if (reg & PCI_MSI_MC_C64) { + pd->pd_msi_mau32 = pci_conf_read(sc->sc_pc, + pd->pd_tag, off + PCI_MSI_MAU32); + pd->pd_msi_md = pci_conf_read(sc->sc_pc, + pd->pd_tag, off + PCI_MSI_MD64); + } else { + pd->pd_msi_md = pci_conf_read(sc->sc_pc, + pd->pd_tag, off + PCI_MSI_MD32); + } + pd->pd_msi_mc = reg; + } + if (pci_dopm) { /* Place the device into D3. */ pd->pd_pmcsr_state = pci_get_powerstate(sc->sc_pc, @@ -254,7 +274,7 @@ pci_resume(struct pci_softc *sc) { struct pci_dev *pd; pcireg_t bhlc, reg; - int i; + int off, i; LIST_FOREACH(pd, &sc->sc_devs, pd_next) { /* @@ -284,6 +304,23 @@ pci_resume(struct pci_softc *sc) pd->pd_bhlc); pci_conf_write(sc->sc_pc, pd->pd_tag, PCI_INTERRUPT_REG, pd->pd_int); + + if (pci_get_capability(sc->sc_pc, pd->pd_tag, + PCI_CAP_MSI, &off, ®)) { + pci_conf_write(sc->sc_pc, pd->pd_tag, + off + PCI_MSI_MA, pd->pd_msi_ma); + if (reg & PCI_MSI_MC_C64) { + pci_conf_write(sc->sc_pc, pd->pd_tag, + off + PCI_MSI_MAU32, pd->pd_msi_mau32); + pci_conf_write(sc->sc_pc, pd->pd_tag, + off + PCI_MSI_MD64, pd->pd_msi_md); + } else { + pci_conf_write(sc->sc_pc, pd->pd_tag, + off + PCI_MSI_MD32, pd->pd_msi_md); + } + pci_conf_write(sc->sc_pc, pd->pd_tag, + off + PCI_MSI_MC, pd->pd_msi_mc); + } } }