summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/pci
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-04-04 09:36:57 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-04-04 14:46:23 +0200
commitde8a76da2f374792594ce03a203b3f30e4889f6f (patch)
tree12b5e1e59358005c3c522955c08aee4795e4829c /freebsd/sys/dev/pci
parentEnable bridging by default (diff)
downloadrtems-libbsd-de8a76da2f374792594ce03a203b3f30e4889f6f.tar.bz2
Update to FreeBSD head 2017-04-04
Git mirror commit 642b174daddbd0efd9bb5f242c43f4ab4db6869f.
Diffstat (limited to 'freebsd/sys/dev/pci')
-rw-r--r--freebsd/sys/dev/pci/pci.c9
-rw-r--r--freebsd/sys/dev/pci/pci_pci.c106
-rw-r--r--freebsd/sys/dev/pci/pci_private.h2
-rw-r--r--freebsd/sys/dev/pci/pcib_private.h2
-rw-r--r--freebsd/sys/dev/pci/pcireg.h21
5 files changed, 106 insertions, 34 deletions
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index 2eba4ca2..3209f893 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -283,13 +283,14 @@ static const struct pci_quirk pci_quirks[] = {
{ 0x43851002, PCI_QUIRK_UNMAP_REG, 0x14, 0 },
/*
- * Atheros AR8161/AR8162/E2200/E2400 Ethernet controllers have a
- * bug that MSI interrupt does not assert if PCIM_CMD_INTxDIS bit
+ * Atheros AR8161/AR8162/E2200/E2400/E2500 Ethernet controllers have
+ * a bug that MSI interrupt does not assert if PCIM_CMD_INTxDIS bit
* of the command register is set.
*/
{ 0x10911969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
{ 0xE0911969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
{ 0xE0A11969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+ { 0xE0B11969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
{ 0x10901969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
/*
@@ -3099,7 +3100,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl,
* If base is 0, then we have problems if this architecture does
* not allow that. It is best to ignore such entries for the
* moment. These will be allocated later if the driver specifically
- * requests them. However, some removable busses look better when
+ * requests them. However, some removable buses look better when
* all resources are allocated, so allow '0' to be overriden.
*
* Similarly treat maps whose values is the same as the test value
@@ -4188,7 +4189,7 @@ pci_attach(device_t dev)
/*
* Since there can be multiple independently numbered PCI
- * busses on systems with multiple PCI domains, we can't use
+ * buses on systems with multiple PCI domains, we can't use
* the unit number to decide which bus we are probing. We ask
* the parent pcib what our domain and bus numbers are.
*/
diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c
index 7d763dd9..d468ca2e 100644
--- a/freebsd/sys/dev/pci/pci_pci.c
+++ b/freebsd/sys/dev/pci/pci_pci.c
@@ -78,6 +78,8 @@ static void pcib_pcie_ab_timeout(void *arg);
static void pcib_pcie_cc_timeout(void *arg);
static void pcib_pcie_dll_timeout(void *arg);
#endif
+static int pcib_request_feature(device_t pcib, device_t dev,
+ enum pci_feature feature);
static device_method_t pcib_methods[] = {
/* Device interface */
@@ -121,6 +123,7 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(pcib_try_enable_ari, pcib_try_enable_ari),
DEVMETHOD(pcib_ari_enabled, pcib_ari_enabled),
DEVMETHOD(pcib_decode_rid, pcib_ari_decode_rid),
+ DEVMETHOD(pcib_request_feature, pcib_request_feature),
DEVMETHOD_END
};
@@ -920,6 +923,7 @@ static void
pcib_probe_hotplug(struct pcib_softc *sc)
{
device_t dev;
+ uint32_t link_cap;
uint16_t link_sta, slot_sta;
if (!pci_enable_pcie_hp)
@@ -932,11 +936,13 @@ pcib_probe_hotplug(struct pcib_softc *sc)
if (!(pcie_read_config(dev, PCIER_FLAGS, 2) & PCIEM_FLAGS_SLOT))
return;
- sc->pcie_link_cap = pcie_read_config(dev, PCIER_LINK_CAP, 4);
sc->pcie_slot_cap = pcie_read_config(dev, PCIER_SLOT_CAP, 4);
if ((sc->pcie_slot_cap & PCIEM_SLOT_CAP_HPC) == 0)
return;
+ link_cap = pcie_read_config(dev, PCIER_LINK_CAP, 4);
+ if ((link_cap & PCIEM_LINK_CAP_DL_ACTIVE) == 0)
+ return;
/*
* Some devices report that they have an MRL when they actually
@@ -947,8 +953,7 @@ pcib_probe_hotplug(struct pcib_softc *sc)
* If there is an open MRL but the Data Link Layer is active,
* the MRL is not real.
*/
- if ((sc->pcie_slot_cap & PCIEM_SLOT_CAP_MRLSP) != 0 &&
- (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) != 0) {
+ if ((sc->pcie_slot_cap & PCIEM_SLOT_CAP_MRLSP) != 0) {
link_sta = pcie_read_config(dev, PCIER_LINK_STA, 2);
slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2);
if ((slot_sta & PCIEM_SLOT_STA_MRLSS) != 0 &&
@@ -957,6 +962,17 @@ pcib_probe_hotplug(struct pcib_softc *sc)
}
}
+ /*
+ * Now that we're sure we want to do hot plug, ask the
+ * firmware, if any, if that's OK.
+ */
+ if (pcib_request_feature(device_get_parent(device_get_parent(dev)), dev,
+ PCI_FEATURE_HP) != 0) {
+ if (bootverbose)
+ device_printf(dev, "Unable to activate hot plug feature.\n");
+ return;
+ }
+
sc->flags |= PCIB_HOTPLUG;
}
@@ -1061,10 +1077,8 @@ pcib_hotplug_present(struct pcib_softc *sc)
return (0);
/* Require the Data Link Layer to be active. */
- if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) {
- if (!(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE))
- return (0);
- }
+ if (!(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE))
+ return (0);
return (-1);
}
@@ -1121,20 +1135,18 @@ pcib_pcie_hotplug_update(struct pcib_softc *sc, uint16_t val, uint16_t mask,
* changed on this interrupt. Stop any scheduled timer if
* the Data Link Layer is active.
*/
- if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) {
- if (card_inserted &&
- !(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE) &&
- sc->pcie_slot_sta &
- (PCIEM_SLOT_STA_MRLSC | PCIEM_SLOT_STA_PDC)) {
- if (cold)
- device_printf(sc->dev,
- "Data Link Layer inactive\n");
- else
- callout_reset(&sc->pcie_dll_timer, hz,
- pcib_pcie_dll_timeout, sc);
- } else if (sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE)
- callout_stop(&sc->pcie_dll_timer);
- }
+ if (card_inserted &&
+ !(sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE) &&
+ sc->pcie_slot_sta &
+ (PCIEM_SLOT_STA_MRLSC | PCIEM_SLOT_STA_PDC)) {
+ if (cold)
+ device_printf(sc->dev,
+ "Data Link Layer inactive\n");
+ else
+ callout_reset(&sc->pcie_dll_timer, hz,
+ pcib_pcie_dll_timeout, sc);
+ } else if (sc->pcie_link_sta & PCIEM_LINK_STA_DL_ACTIVE)
+ callout_stop(&sc->pcie_dll_timer);
pcib_pcie_hotplug_command(sc, val, mask);
@@ -1149,7 +1161,7 @@ pcib_pcie_hotplug_update(struct pcib_softc *sc, uint16_t val, uint16_t mask,
}
static void
-pcib_pcie_intr(void *arg)
+pcib_pcie_intr_hotplug(void *arg)
{
struct pcib_softc *sc;
device_t dev;
@@ -1262,7 +1274,7 @@ pcib_pcie_cc_timeout(void *arg)
} else {
device_printf(dev,
"Missed HotPlug interrupt waiting for Command Completion\n");
- pcib_pcie_intr(sc);
+ pcib_pcie_intr_hotplug(sc);
}
}
@@ -1285,7 +1297,7 @@ pcib_pcie_dll_timeout(void *arg)
} else if (sta != sc->pcie_link_sta) {
device_printf(dev,
"Missed HotPlug interrupt waiting for DLL Active\n");
- pcib_pcie_intr(sc);
+ pcib_pcie_intr_hotplug(sc);
}
}
@@ -1331,7 +1343,7 @@ pcib_alloc_pcie_irq(struct pcib_softc *sc)
}
error = bus_setup_intr(dev, sc->pcie_irq, INTR_TYPE_MISC,
- NULL, pcib_pcie_intr, sc, &sc->pcie_ihand);
+ NULL, pcib_pcie_intr_hotplug, sc, &sc->pcie_ihand);
if (error) {
device_printf(dev, "Failed to setup PCI-e interrupt handler\n");
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->pcie_irq);
@@ -1384,7 +1396,7 @@ pcib_setup_hotplug(struct pcib_softc *sc)
mask = PCIEM_SLOT_CTL_DLLSCE | PCIEM_SLOT_CTL_HPIE |
PCIEM_SLOT_CTL_CCIE | PCIEM_SLOT_CTL_PDCE | PCIEM_SLOT_CTL_MRLSCE |
PCIEM_SLOT_CTL_PFDE | PCIEM_SLOT_CTL_ABPE;
- val = PCIEM_SLOT_CTL_PDCE | PCIEM_SLOT_CTL_HPIE;
+ val = PCIEM_SLOT_CTL_DLLSCE | PCIEM_SLOT_CTL_HPIE | PCIEM_SLOT_CTL_PDCE;
if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_APB)
val |= PCIEM_SLOT_CTL_ABPE;
if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_PCP)
@@ -1393,8 +1405,6 @@ pcib_setup_hotplug(struct pcib_softc *sc)
val |= PCIEM_SLOT_CTL_MRLSCE;
if (!(sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS))
val |= PCIEM_SLOT_CTL_CCIE;
- if (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE)
- val |= PCIEM_SLOT_CTL_DLLSCE;
/* Turn the attention indicator off. */
if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_AIP) {
@@ -2835,3 +2845,43 @@ pcib_try_enable_ari(device_t pcib, device_t dev)
return (0);
}
+
+int
+pcib_request_feature_allow(device_t pcib, device_t dev,
+ enum pci_feature feature)
+{
+ /*
+ * No host firmware we have to negotiate with, so we allow
+ * every valid feature requested.
+ */
+ switch (feature) {
+ case PCI_FEATURE_AER:
+ case PCI_FEATURE_HP:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+/*
+ * Pass the request to use this PCI feature up the tree. Either there's a
+ * firmware like ACPI that's using this feature that will approve (or deny) the
+ * request to take it over, or the platform has no such firmware, in which case
+ * the request will be approved. If the request is approved, the OS is expected
+ * to make use of the feature or render it harmless.
+ */
+static int
+pcib_request_feature(device_t pcib, device_t dev, enum pci_feature feature)
+{
+ device_t bus;
+
+ /*
+ * Our parent is necessarily a pci bus. Its parent will either be
+ * another pci bridge (which passes it up) or a host bridge that can
+ * approve or reject the request.
+ */
+ bus = device_get_parent(pcib);
+ return (PCIB_REQUEST_FEATURE(device_get_parent(bus), dev, feature));
+}
diff --git a/freebsd/sys/dev/pci/pci_private.h b/freebsd/sys/dev/pci/pci_private.h
index b0f14818..6c5a1677 100644
--- a/freebsd/sys/dev/pci/pci_private.h
+++ b/freebsd/sys/dev/pci/pci_private.h
@@ -34,7 +34,7 @@
/*
* Export definitions of the pci bus so that we can more easily share
- * it with "subclass" busses.
+ * it with "subclass" buses.
*/
DECLARE_CLASS(pci_driver);
diff --git a/freebsd/sys/dev/pci/pcib_private.h b/freebsd/sys/dev/pci/pcib_private.h
index 65aec8d4..1004e133 100644
--- a/freebsd/sys/dev/pci/pcib_private.h
+++ b/freebsd/sys/dev/pci/pcib_private.h
@@ -132,7 +132,6 @@ struct pcib_softc
uint16_t bridgectl; /* bridge control register */
uint16_t pcie_link_sta;
uint16_t pcie_slot_sta;
- uint32_t pcie_link_cap;
uint32_t pcie_slot_cap;
struct resource *pcie_irq;
void *pcie_ihand;
@@ -194,5 +193,6 @@ int pcib_get_id(device_t pcib, device_t dev, enum pci_id_type type,
uintptr_t *id);
void pcib_decode_rid(device_t pcib, uint16_t rid, int *bus,
int *slot, int *func);
+int pcib_request_feature_allow(device_t pcib, device_t dev, enum pci_feature feature);
#endif
diff --git a/freebsd/sys/dev/pci/pcireg.h b/freebsd/sys/dev/pci/pcireg.h
index 291bb2ea..b434b2e6 100644
--- a/freebsd/sys/dev/pci/pcireg.h
+++ b/freebsd/sys/dev/pci/pcireg.h
@@ -478,6 +478,11 @@
#define PCIS_DASP_MGMT_CARD 0x20
#define PCIS_DASP_OTHER 0x80
+#define PCIC_ACCEL 0x12
+#define PCIS_ACCEL_PROCESSING 0x00
+
+#define PCIC_INSTRUMENT 0x13
+
#define PCIC_OTHER 0xff
/* Bridge Control Values. */
@@ -1040,3 +1045,19 @@
#define PCIR_SRIOV_BARS 0x24
#define PCIR_SRIOV_BAR(x) (PCIR_SRIOV_BARS + (x) * 4)
+/*
+ * PCI Express Firmware Interface definitions
+ */
+#define PCI_OSC_STATUS 0
+#define PCI_OSC_SUPPORT 1
+#define PCIM_OSC_SUPPORT_EXT_PCI_CONF 0x01 /* Extended PCI Config Space */
+#define PCIM_OSC_SUPPORT_ASPM 0x02 /* Active State Power Management */
+#define PCIM_OSC_SUPPORT_CPMC 0x04 /* Clock Power Management Cap */
+#define PCIM_OSC_SUPPORT_SEG_GROUP 0x08 /* PCI Segment Groups supported */
+#define PCIM_OSC_SUPPORT_MSI 0x10 /* MSI signalling supported */
+#define PCI_OSC_CTL 2
+#define PCIM_OSC_CTL_PCIE_HP 0x01 /* PCIe Native Hot Plug */
+#define PCIM_OSC_CTL_SHPC_HP 0x02 /* SHPC Native Hot Plug */
+#define PCIM_OSC_CTL_PCIE_PME 0x04 /* PCIe Native Power Mgt Events */
+#define PCIM_OSC_CTL_PCIE_AER 0x08 /* PCIe Advanced Error Reporting */
+#define PCIM_OSC_CTL_PCIE_CAP_STRUCT 0x10 /* Various Capability Structures */