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, &reg)) {
+                       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, &reg)) {
+                       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);
+               }
        }
 }

Reply via email to