aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
authorMitsuru IWASAKI <iwasaki@FreeBSD.org>2003-09-17 08:32:44 +0000
committerMitsuru IWASAKI <iwasaki@FreeBSD.org>2003-09-17 08:32:44 +0000
commit526b5e659d72dc2d4298f38eaaabafc83097f26b (patch)
treedf08b28e66ee6ccb78c1f44513d4a14348e26794 /sys/dev/pci/pci.c
parenta2f19df9cc4da8a9651bd46bc8e2b9ac28a24b72 (diff)
downloadsrc-526b5e659d72dc2d4298f38eaaabafc83097f26b.tar.gz
src-526b5e659d72dc2d4298f38eaaabafc83097f26b.zip
Add pci_resume() to reestablish interrupt routing after
suspend/resume. Especially after hibernation, interrupt routing went back to initial status on some machines.
Notes
Notes: svn path=/head/; revision=120155
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r--sys/dev/pci/pci.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index a4e1a542e0a0..a7f320efbc47 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -89,7 +89,7 @@ static device_method_t pci_methods[] = {
DEVMETHOD(device_attach, pci_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_resume, pci_resume),
/* Bus interface */
DEVMETHOD(bus_print_child, pci_print_child),
@@ -1509,3 +1509,35 @@ pci_modevent(module_t mod, int what, void *arg)
return (0);
}
+
+int
+pci_resume(device_t dev)
+{
+ int numdevs;
+ int i;
+ device_t *children;
+ device_t child;
+ struct pci_devinfo *dinfo;
+ pcicfgregs *cfg;
+
+ device_get_children(dev, &children, &numdevs);
+
+ for (i = 0; i < numdevs; i++) {
+ child = children[i];
+
+ dinfo = device_get_ivars(child);
+ cfg = &dinfo->cfg;
+ if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) {
+ cfg->intline = PCI_ASSIGN_INTERRUPT(dev, child);
+ if (PCI_INTERRUPT_VALID(cfg->intline)) {
+ pci_write_config(child, PCIR_INTLINE,
+ cfg->intline, 1);
+ }
+ }
+ }
+
+ free(children, M_TEMP);
+
+ return (bus_generic_resume(dev));
+}
+