summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/pci_pci.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2015-06-05 17:05:09 +0000
committerjhb <jhb@FreeBSD.org>2015-06-05 17:05:09 +0000
commitea5a6516aeb67dca2e45aa5a871a8527b67dda88 (patch)
treed4a8e7126a03e56a8bae00ff3e56ccc51abfcd76 /sys/dev/pci/pci_pci.c
parent8f2fc91d60ff78daf82d3b608c4bb5a50f20122a (diff)
downloadFreeBSD-src-ea5a6516aeb67dca2e45aa5a871a8527b67dda88.zip
FreeBSD-src-ea5a6516aeb67dca2e45aa5a871a8527b67dda88.tar.gz
MFC 274633,274639,274663,277233-277235,281870,281871,281873,281874:
Various fixes for suspend and resume of PCI to PCI and PCI to Cardbus bridges. 274633: Remove stray empty comment. The code is adequately explained in the block comment above, so there's nothing to add here. 274639: Modernize comments about BIOSes being lame since in this detail they aren't lame, the rules changed along the way. Catch up to 1999 or so with the new rules. 274663: Fix typo pointed out by avg@ and Joerg Sonnenberger. Add a clarifying sentence too. 277233: Suspend and resume were the only two functions not to follow the brdev convention here, so fix that. 277234: Move the suspsned and resume functions to the bus attachment. They were accessing PCI config registers, which won't work for the ISA version. 277235: Always enable I/O, memory and dma cycles. Some BIOSes don't enable them, sometimes they are reset for power state transitions or during whatever happens while suspended. Also, it is good practice to always do this. 281870: Cosmetic change: use PCIR_SECLAT_2 rather than PCIR_SECLAT_1. 281871: The minimim grant and maximum latency PCI config registers are only valid for type 0 devices, not type 1 or 2 bridges. Don't read them for bridge devices during bus scans and return an error when attempting to read them as ivars for bridge devices. 281873: Don't explicitly manage power states for PCI-PCI bridge devices in the driver's suspend and resume routines. These have been redundant no-ops since r214065 changed the PCI bus driver to manage power states for all devices (including type 1/2 bridge devices) during suspend and resume. 281874: Update the pci_cfg_save/restore routines to operate on bridge devices (type 1 and type 2) as well as leaf devices (type 0). In particular, this allows the existing PCI bus logic to save and restore capability registers such as MSI and PCI-express work for bridge devices rather than requiring that code to be duplicated in bridge drivers. It also means that bridge drivers no longer need to save and restore basic registers such as the PCI command register or BARs nor manage powerstates for the bridge device. While here, pci_setup_secbus() has been changed to initialize the 'sec' and 'sub' fields in the 'secbus' structure instead of requiring the pcib and pccbb drivers to do this in the NEW_PCIB + PCI_RES_BUS case.
Diffstat (limited to 'sys/dev/pci/pci_pci.c')
-rw-r--r--sys/dev/pci/pci_pci.c62
1 files changed, 23 insertions, 39 deletions
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index b2c18d6..30cb681 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -549,18 +549,22 @@ void
pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count)
{
char buf[64];
- int error, rid;
+ int error, rid, sec_reg;
switch (pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) {
case PCIM_HDRTYPE_BRIDGE:
+ sec_reg = PCIR_SECBUS_1;
bus->sub_reg = PCIR_SUBBUS_1;
break;
case PCIM_HDRTYPE_CARDBUS:
+ sec_reg = PCIR_SECBUS_2;
bus->sub_reg = PCIR_SUBBUS_2;
break;
default:
panic("not a PCI bridge");
}
+ bus->sec = pci_read_config(dev, sec_reg, 1);
+ bus->sub = pci_read_config(dev, bus->sub_reg, 1);
bus->dev = dev;
bus->rman.rm_start = 0;
bus->rman.rm_end = PCI_BUSMAX;
@@ -845,20 +849,16 @@ pcib_set_mem_decode(struct pcib_softc *sc)
static void
pcib_cfg_save(struct pcib_softc *sc)
{
+#ifndef NEW_PCIB
device_t dev;
+ uint16_t command;
dev = sc->dev;
- sc->command = pci_read_config(dev, PCIR_COMMAND, 2);
- sc->pribus = pci_read_config(dev, PCIR_PRIBUS_1, 1);
- sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1);
- sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1);
- sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
- sc->seclat = pci_read_config(dev, PCIR_SECLAT_1, 1);
-#ifndef NEW_PCIB
- if (sc->command & PCIM_CMD_PORTEN)
+ command = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (command & PCIM_CMD_PORTEN)
pcib_get_io_decode(sc);
- if (sc->command & PCIM_CMD_MEMEN)
+ if (command & PCIM_CMD_MEMEN)
pcib_get_mem_decode(sc);
#endif
}
@@ -870,21 +870,18 @@ static void
pcib_cfg_restore(struct pcib_softc *sc)
{
device_t dev;
-
+#ifndef NEW_PCIB
+ uint16_t command;
+#endif
dev = sc->dev;
- pci_write_config(dev, PCIR_COMMAND, sc->command, 2);
- pci_write_config(dev, PCIR_PRIBUS_1, sc->pribus, 1);
- pci_write_config(dev, PCIR_SECBUS_1, sc->bus.sec, 1);
- pci_write_config(dev, PCIR_SUBBUS_1, sc->bus.sub, 1);
- pci_write_config(dev, PCIR_BRIDGECTL_1, sc->bridgectl, 2);
- pci_write_config(dev, PCIR_SECLAT_1, sc->seclat, 1);
#ifdef NEW_PCIB
pcib_write_windows(sc, WIN_IO | WIN_MEM | WIN_PMEM);
#else
- if (sc->command & PCIM_CMD_PORTEN)
+ command = pci_read_config(dev, PCIR_COMMAND, 2);
+ if (command & PCIM_CMD_PORTEN)
pcib_set_io_decode(sc);
- if (sc->command & PCIM_CMD_MEMEN)
+ if (command & PCIM_CMD_MEMEN)
pcib_set_mem_decode(sc);
#endif
}
@@ -918,7 +915,11 @@ pcib_attach_common(device_t dev)
* Get current bridge configuration.
*/
sc->domain = pci_get_domain(dev);
- sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2);
+#if !(defined(NEW_PCIB) && defined(PCI_RES_BUS))
+ sc->bus.sec = pci_read_config(dev, PCIR_SECBUS_1, 1);
+ sc->bus.sub = pci_read_config(dev, PCIR_SUBBUS_1, 1);
+#endif
+ sc->bridgectl = pci_read_config(dev, PCIR_BRIDGECTL_1, 2);
pcib_cfg_save(sc);
/*
@@ -1097,32 +1098,15 @@ pcib_attach(device_t dev)
int
pcib_suspend(device_t dev)
{
- device_t pcib;
- int dstate, error;
pcib_cfg_save(device_get_softc(dev));
- error = bus_generic_suspend(dev);
- if (error == 0 && pci_do_power_suspend) {
- dstate = PCI_POWERSTATE_D3;
- pcib = device_get_parent(device_get_parent(dev));
- if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
- pci_set_powerstate(dev, dstate);
- }
- return (error);
+ return (bus_generic_suspend(dev));
}
int
pcib_resume(device_t dev)
{
- device_t pcib;
- int dstate;
-
- if (pci_do_power_resume) {
- pcib = device_get_parent(device_get_parent(dev));
- dstate = PCI_POWERSTATE_D0;
- if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
- pci_set_powerstate(dev, dstate);
- }
+
pcib_cfg_restore(device_get_softc(dev));
return (bus_generic_resume(dev));
}
OpenPOWER on IntegriCloud