diff options
author | iwasaki <iwasaki@FreeBSD.org> | 2003-09-17 08:32:44 +0000 |
---|---|---|
committer | iwasaki <iwasaki@FreeBSD.org> | 2003-09-17 08:32:44 +0000 |
commit | 9fac14e51fbda70a693d9001fd1ab05d3560cc98 (patch) | |
tree | df08b28e66ee6ccb78c1f44513d4a14348e26794 /sys/dev | |
parent | ab6ce03a9b2691492b4e4996f2f14960556c42e8 (diff) | |
download | FreeBSD-src-9fac14e51fbda70a693d9001fd1ab05d3560cc98.zip FreeBSD-src-9fac14e51fbda70a693d9001fd1ab05d3560cc98.tar.gz |
Add pci_resume() to reestablish interrupt routing after
suspend/resume.
Especially after hibernation, interrupt routing went back to initial
status on some machines.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/acpica/acpi_pci.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/pci.c | 34 | ||||
-rw-r--r-- | sys/dev/pci/pci_private.h | 1 |
3 files changed, 35 insertions, 2 deletions
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c index b8bf11e..85b6b1c 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 a4e1a54..a7f320e 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 3123c61..816106d 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_ */ |