diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 09:36:57 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 14:46:23 +0200 |
commit | de8a76da2f374792594ce03a203b3f30e4889f6f (patch) | |
tree | 12b5e1e59358005c3c522955c08aee4795e4829c /freebsd/sys/dev/pci | |
parent | Enable bridging by default (diff) | |
download | rtems-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.c | 9 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pci_pci.c | 106 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pci_private.h | 2 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pcib_private.h | 2 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pcireg.h | 21 |
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 */ |