aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
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
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')
-rw-r--r--sys/dev/acpica/acpi_pci.c2
-rw-r--r--sys/dev/pci/pci.c34
-rw-r--r--sys/dev/pci/pci_private.h1
3 files changed, 35 insertions, 2 deletions
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index b8bf11eacc6d..85b6b1cabce9 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -79,7 +79,7 @@ static device_method_t acpi_pci_methods[] = {
DEVMETHOD(device_attach, acpi_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),
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));
+}
+
diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h
index 3123c61cdfc7..816106d82858 100644
--- a/sys/dev/pci/pci_private.h
+++ b/sys/dev/pci/pci_private.h
@@ -73,4 +73,5 @@ int pci_child_location_str_method(device_t cbdev, device_t child,
int pci_child_pnpinfo_str_method(device_t cbdev, device_t child,
char *buf, size_t buflen);
int pci_assign_interrupt_method(device_t dev, device_t child);
+int pci_resume(device_t dev);
#endif /* _PCI_PRIVATE_H_ */