summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2015-07-25 00:14:02 +0000
committerjhb <jhb@FreeBSD.org>2015-07-25 00:14:02 +0000
commitdc79e09c5ba932c401aa38f36d81432c54923446 (patch)
tree5b07cb9ddf2877b902be73ed64cb5405191fbbc6 /sys/dev/pci
parentb3775fddfbd2146ec26a22154e3d84faba49b9c7 (diff)
downloadFreeBSD-src-dc79e09c5ba932c401aa38f36d81432c54923446.zip
FreeBSD-src-dc79e09c5ba932c401aa38f36d81432c54923446.tar.gz
Partially revert r284034. In particular, revert the final change in this
MFC (281874). It broke suspend and resume on several Thinkpads (though not all) in 10 even though it works fine on the same laptops in HEAD. PR: 201239 Reported by: Kevin Oberman and several others
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pci.c107
-rw-r--r--sys/dev/pci/pci_pci.c41
-rw-r--r--sys/dev/pci/pcib_private.h3
-rw-r--r--sys/dev/pci/pcivar.h10
4 files changed, 54 insertions, 107 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 8b1a283..e5db8e2 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -590,19 +590,9 @@ pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg)
cfg->nummaps = PCI_MAXMAPS_0;
break;
case PCIM_HDRTYPE_BRIDGE:
- cfg->bridge.br_seclat = REG(PCIR_SECLAT_1, 1);
- cfg->bridge.br_subbus = REG(PCIR_SUBBUS_1, 1);
- cfg->bridge.br_secbus = REG(PCIR_SECBUS_1, 1);
- cfg->bridge.br_pribus = REG(PCIR_PRIBUS_1, 1);
- cfg->bridge.br_control = REG(PCIR_BRIDGECTL_1, 2);
cfg->nummaps = PCI_MAXMAPS_1;
break;
case PCIM_HDRTYPE_CARDBUS:
- cfg->bridge.br_seclat = REG(PCIR_SECLAT_2, 1);
- cfg->bridge.br_subbus = REG(PCIR_SUBBUS_2, 1);
- cfg->bridge.br_secbus = REG(PCIR_SECBUS_2, 1);
- cfg->bridge.br_pribus = REG(PCIR_PRIBUS_2, 1);
- cfg->bridge.br_control = REG(PCIR_BRIDGECTL_2, 2);
cfg->subvendor = REG(PCIR_SUBVEND_2, 2);
cfg->subdevice = REG(PCIR_SUBDEV_2, 2);
cfg->nummaps = PCI_MAXMAPS_2;
@@ -4948,6 +4938,16 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
{
/*
+ * Only do header type 0 devices. Type 1 devices are bridges,
+ * which we know need special treatment. Type 2 devices are
+ * cardbus bridges which also require special treatment.
+ * Other types are unknown, and we err on the side of safety
+ * by ignoring them.
+ */
+ if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL)
+ return;
+
+ /*
* Restore the device to full power mode. We must do this
* before we restore the registers because moving from D3 to
* D0 will cause the chip's BARs and some other registers to
@@ -4957,44 +4957,16 @@ pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
*/
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0)
pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+ pci_restore_bars(dev);
pci_write_config(dev, PCIR_COMMAND, dinfo->cfg.cmdreg, 2);
pci_write_config(dev, PCIR_INTLINE, dinfo->cfg.intline, 1);
pci_write_config(dev, PCIR_INTPIN, dinfo->cfg.intpin, 1);
+ pci_write_config(dev, PCIR_MINGNT, dinfo->cfg.mingnt, 1);
+ pci_write_config(dev, PCIR_MAXLAT, dinfo->cfg.maxlat, 1);
pci_write_config(dev, PCIR_CACHELNSZ, dinfo->cfg.cachelnsz, 1);
pci_write_config(dev, PCIR_LATTIMER, dinfo->cfg.lattimer, 1);
pci_write_config(dev, PCIR_PROGIF, dinfo->cfg.progif, 1);
pci_write_config(dev, PCIR_REVID, dinfo->cfg.revid, 1);
- switch (dinfo->cfg.hdrtype & PCIM_HDRTYPE) {
- case PCIM_HDRTYPE_NORMAL:
- pci_write_config(dev, PCIR_MINGNT, dinfo->cfg.mingnt, 1);
- pci_write_config(dev, PCIR_MAXLAT, dinfo->cfg.maxlat, 1);
- break;
- case PCIM_HDRTYPE_BRIDGE:
- pci_write_config(dev, PCIR_SECLAT_1,
- dinfo->cfg.bridge.br_seclat, 1);
- pci_write_config(dev, PCIR_SUBBUS_1,
- dinfo->cfg.bridge.br_subbus, 1);
- pci_write_config(dev, PCIR_SECBUS_1,
- dinfo->cfg.bridge.br_secbus, 1);
- pci_write_config(dev, PCIR_PRIBUS_1,
- dinfo->cfg.bridge.br_pribus, 1);
- pci_write_config(dev, PCIR_BRIDGECTL_1,
- dinfo->cfg.bridge.br_control, 2);
- break;
- case PCIM_HDRTYPE_CARDBUS:
- pci_write_config(dev, PCIR_SECLAT_2,
- dinfo->cfg.bridge.br_seclat, 1);
- pci_write_config(dev, PCIR_SUBBUS_2,
- dinfo->cfg.bridge.br_subbus, 1);
- pci_write_config(dev, PCIR_SECBUS_2,
- dinfo->cfg.bridge.br_secbus, 1);
- pci_write_config(dev, PCIR_PRIBUS_2,
- dinfo->cfg.bridge.br_pribus, 1);
- pci_write_config(dev, PCIR_BRIDGECTL_2,
- dinfo->cfg.bridge.br_control, 2);
- break;
- }
- pci_restore_bars(dev);
/*
* Restore extended capabilities for PCI-Express and PCI-X
@@ -5063,57 +5035,40 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
int ps;
/*
+ * Only do header type 0 devices. Type 1 devices are bridges, which
+ * we know need special treatment. Type 2 devices are cardbus bridges
+ * which also require special treatment. Other types are unknown, and
+ * we err on the side of safety by ignoring them. Powering down
+ * bridges should not be undertaken lightly.
+ */
+ if ((dinfo->cfg.hdrtype & PCIM_HDRTYPE) != PCIM_HDRTYPE_NORMAL)
+ return;
+
+ /*
* Some drivers apparently write to these registers w/o updating our
* cached copy. No harm happens if we update the copy, so do so here
* so we can restore them. The COMMAND register is modified by the
* bus w/o updating the cache. This should represent the normally
- * writable portion of the 'defined' part of type 0/1/2 headers.
+ * writable portion of the 'defined' part of type 0 headers. In
+ * theory we also need to save/restore the PCI capability structures
+ * we know about, but apart from power we don't know any that are
+ * writable.
*/
+ dinfo->cfg.subvendor = pci_read_config(dev, PCIR_SUBVEND_0, 2);
+ dinfo->cfg.subdevice = pci_read_config(dev, PCIR_SUBDEV_0, 2);
dinfo->cfg.vendor = pci_read_config(dev, PCIR_VENDOR, 2);
dinfo->cfg.device = pci_read_config(dev, PCIR_DEVICE, 2);
dinfo->cfg.cmdreg = pci_read_config(dev, PCIR_COMMAND, 2);
dinfo->cfg.intline = pci_read_config(dev, PCIR_INTLINE, 1);
dinfo->cfg.intpin = pci_read_config(dev, PCIR_INTPIN, 1);
+ dinfo->cfg.mingnt = pci_read_config(dev, PCIR_MINGNT, 1);
+ dinfo->cfg.maxlat = pci_read_config(dev, PCIR_MAXLAT, 1);
dinfo->cfg.cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1);
dinfo->cfg.lattimer = pci_read_config(dev, PCIR_LATTIMER, 1);
dinfo->cfg.baseclass = pci_read_config(dev, PCIR_CLASS, 1);
dinfo->cfg.subclass = pci_read_config(dev, PCIR_SUBCLASS, 1);
dinfo->cfg.progif = pci_read_config(dev, PCIR_PROGIF, 1);
dinfo->cfg.revid = pci_read_config(dev, PCIR_REVID, 1);
- switch (dinfo->cfg.hdrtype & PCIM_HDRTYPE) {
- case PCIM_HDRTYPE_NORMAL:
- dinfo->cfg.subvendor = pci_read_config(dev, PCIR_SUBVEND_0, 2);
- dinfo->cfg.subdevice = pci_read_config(dev, PCIR_SUBDEV_0, 2);
- dinfo->cfg.mingnt = pci_read_config(dev, PCIR_MINGNT, 1);
- dinfo->cfg.maxlat = pci_read_config(dev, PCIR_MAXLAT, 1);
- break;
- case PCIM_HDRTYPE_BRIDGE:
- dinfo->cfg.bridge.br_seclat = pci_read_config(dev,
- PCIR_SECLAT_1, 1);
- dinfo->cfg.bridge.br_subbus = pci_read_config(dev,
- PCIR_SUBBUS_1, 1);
- dinfo->cfg.bridge.br_secbus = pci_read_config(dev,
- PCIR_SECBUS_1, 1);
- dinfo->cfg.bridge.br_pribus = pci_read_config(dev,
- PCIR_PRIBUS_1, 1);
- dinfo->cfg.bridge.br_control = pci_read_config(dev,
- PCIR_BRIDGECTL_1, 2);
- break;
- case PCIM_HDRTYPE_CARDBUS:
- dinfo->cfg.bridge.br_seclat = pci_read_config(dev,
- PCIR_SECLAT_2, 1);
- dinfo->cfg.bridge.br_subbus = pci_read_config(dev,
- PCIR_SUBBUS_2, 1);
- dinfo->cfg.bridge.br_secbus = pci_read_config(dev,
- PCIR_SECBUS_2, 1);
- dinfo->cfg.bridge.br_pribus = pci_read_config(dev,
- PCIR_PRIBUS_2, 1);
- dinfo->cfg.bridge.br_control = pci_read_config(dev,
- PCIR_BRIDGECTL_2, 2);
- dinfo->cfg.subvendor = pci_read_config(dev, PCIR_SUBVEND_2, 2);
- dinfo->cfg.subdevice = pci_read_config(dev, PCIR_SUBDEV_2, 2);
- break;
- }
if (dinfo->cfg.pcie.pcie_location != 0)
pci_cfg_save_pcie(dev, dinfo);
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 30cb681..62ddc3d 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -549,22 +549,18 @@ void
pcib_setup_secbus(device_t dev, struct pcib_secbus *bus, int min_count)
{
char buf[64];
- int error, rid, sec_reg;
+ int error, rid;
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;
@@ -849,16 +845,20 @@ 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;
- command = pci_read_config(dev, PCIR_COMMAND, 2);
- if (command & PCIM_CMD_PORTEN)
+ 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)
pcib_get_io_decode(sc);
- if (command & PCIM_CMD_MEMEN)
+ if (sc->command & PCIM_CMD_MEMEN)
pcib_get_mem_decode(sc);
#endif
}
@@ -870,18 +870,21 @@ 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
- command = pci_read_config(dev, PCIR_COMMAND, 2);
- if (command & PCIM_CMD_PORTEN)
+ if (sc->command & PCIM_CMD_PORTEN)
pcib_set_io_decode(sc);
- if (command & PCIM_CMD_MEMEN)
+ if (sc->command & PCIM_CMD_MEMEN)
pcib_set_mem_decode(sc);
#endif
}
@@ -915,11 +918,7 @@ pcib_attach_common(device_t dev)
* Get current bridge configuration.
*/
sc->domain = pci_get_domain(dev);
-#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);
+ sc->secstat = pci_read_config(dev, PCIR_SECSTAT_1, 2);
pcib_cfg_save(sc);
/*
diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h
index 8cf2280..cbc2b85 100644
--- a/sys/dev/pci/pcib_private.h
+++ b/sys/dev/pci/pcib_private.h
@@ -106,6 +106,7 @@ struct pcib_softc
#define PCIB_DISABLE_MSI 0x2
#define PCIB_DISABLE_MSIX 0x4
#define PCIB_ENABLE_ARI 0x8
+ uint16_t command; /* command register */
u_int domain; /* domain number */
u_int pribus; /* primary bus number */
struct pcib_secbus bus; /* secondary bus numbers */
@@ -121,7 +122,9 @@ struct pcib_softc
uint32_t iobase; /* base address of port window */
uint32_t iolimit; /* topmost address of port window */
#endif
+ uint16_t secstat; /* secondary bus status register */
uint16_t bridgectl; /* bridge control register */
+ uint8_t seclat; /* secondary bus latency timer */
};
#define PCIB_SUPPORTED_ARI_VER 1
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 4eb50e2..0157ee7 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -39,15 +39,6 @@
typedef uint64_t pci_addr_t;
-/* Config registers for PCI-PCI and PCI-Cardbus bridges. */
-struct pcicfg_bridge {
- uint8_t br_seclat;
- uint8_t br_subbus;
- uint8_t br_secbus;
- uint8_t br_pribus;
- uint16_t br_control;
-};
-
/* Interesting values for PCI power management */
struct pcicfg_pp {
uint16_t pp_cap; /* PCI power management capabilities */
@@ -188,7 +179,6 @@ typedef struct pcicfg {
uint8_t slot; /* config space slot address */
uint8_t func; /* config space function number */
- struct pcicfg_bridge bridge; /* Bridges */
struct pcicfg_pp pp; /* Power management */
struct pcicfg_vpd vpd; /* Vital product data */
struct pcicfg_msi msi; /* PCI MSI */
OpenPOWER on IntegriCloud