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);
+ }
}
}