Date: Thu, 18 Aug 2016 21:47:00 +0000 (UTC) From: Eric van Gyzen <vangyzen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r304433 - stable/11/sys/dev/pci Message-ID: <201608182147.u7ILl0H8075368@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: vangyzen Date: Thu Aug 18 21:47:00 2016 New Revision: 304433 URL: https://svnweb.freebsd.org/changeset/base/304433 Log: MFC r304246 PCIe HotPlug: Detect bridges that are not really HotPlug capable Some devices report that they have an MRL when they actually do not. Since they always report that the MRL is open, child devices would be ignored. Try to detect these devices and ignore their claim of HotPlug support. Specifically, if there is an open MRL but the Data Link Layer is active, the MRL is not real. Revert r303645 to re-enable HotPlug support for slots with power controllers, since it works correctly in my testing. Start the DLL state-change timer if Presence /or/ MRL state changes, along with other conditions. Previously, we started the timer iff Presence changed. If there is an MRL, it must be closed for power to be turned on, so Presence is unlikely to change on an MRL-close event. Add a printf() of interesting registers on HotPlug interrupts and commands (one from erj@). These were very useful for debugging. Guard them with bootverbose, since they're spam in normal operation. In collaboration with: jhb Relnotes: yes (re-enable HotPlug support for slots with power controllers) Sponsored by: Dell Inc. Differential Revision: https://reviews.freebsd.org/D7509 Modified: stable/11/sys/dev/pci/pci_pci.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/pci/pci_pci.c ============================================================================== --- stable/11/sys/dev/pci/pci_pci.c Thu Aug 18 19:18:40 2016 (r304432) +++ stable/11/sys/dev/pci/pci_pci.c Thu Aug 18 21:47:00 2016 (r304433) @@ -918,6 +918,7 @@ static void pcib_probe_hotplug(struct pcib_softc *sc) { device_t dev; + uint16_t link_sta, slot_sta; if (!pci_enable_pcie_hp) return; @@ -932,15 +933,29 @@ pcib_probe_hotplug(struct pcib_softc *sc 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; + /* - * XXX: Handling of slots with a power controller needs to be - * reexamined. Ignore hotplug on such slots for now. + * Some devices report that they have an MRL when they actually + * do not. Since they always report that the MRL is open, child + * devices would be ignored. Try to detect these devices and + * ignore their claim of HotPlug support. + * + * 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_PCP) - return; - - if (sc->pcie_slot_cap & PCIEM_SLOT_CAP_HPC) - sc->flags |= PCIB_HOTPLUG; + if ((sc->pcie_slot_cap & PCIEM_SLOT_CAP_MRLSP) != 0 && + (sc->pcie_link_cap & PCIEM_LINK_CAP_DL_ACTIVE) != 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 && + (link_sta & PCIEM_LINK_STA_DL_ACTIVE) != 0) { + return; + } + } + + sc->flags |= PCIB_HOTPLUG; } /* @@ -966,6 +981,8 @@ pcib_pcie_hotplug_command(struct pcib_so new = (ctl & ~mask) | val; if (new == ctl) return; + if (bootverbose) + device_printf(dev, "HotPlug command: %04x -> %04x\n", ctl, new); pcie_write_config(dev, PCIER_SLOT_CTL, new, 2); if (!(sc->pcie_slot_cap & PCIEM_SLOT_CAP_NCCS) && (ctl & new) & PCIEM_SLOT_CTL_CCIE) { @@ -1028,9 +1045,6 @@ pcib_hotplug_inserted(struct pcib_softc static int pcib_hotplug_present(struct pcib_softc *sc) { - device_t dev; - - dev = sc->dev; /* Card must be inserted. */ if (!pcib_hotplug_inserted(sc)) @@ -1059,7 +1073,7 @@ pcib_pcie_hotplug_update(struct pcib_sof { bool card_inserted, ei_engaged; - /* Clear DETACHING if Present Detect has cleared. */ + /* Clear DETACHING if Presence Detect has cleared. */ if ((sc->pcie_slot_sta & (PCIEM_SLOT_STA_PDC | PCIEM_SLOT_STA_PDS)) == PCIEM_SLOT_STA_PDC) sc->flags &= ~PCIB_DETACHING; @@ -1101,14 +1115,15 @@ pcib_pcie_hotplug_update(struct pcib_sof /* * Start a timer to see if the Data Link Layer times out. - * Note that we only start the timer if Presence Detect + * Note that we only start the timer if Presence Detect or MRL Sensor * 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_PDC) { + sc->pcie_slot_sta & + (PCIEM_SLOT_STA_MRLSC | PCIEM_SLOT_STA_PDC)) { if (cold) device_printf(sc->dev, "Data Link Layer inactive\n"); @@ -1144,6 +1159,10 @@ pcib_pcie_intr(void *arg) /* Clear the events just reported. */ pcie_write_config(dev, PCIER_SLOT_STA, sc->pcie_slot_sta, 2); + if (bootverbose) + device_printf(dev, "HotPlug interrupt: %#x\n", + sc->pcie_slot_sta); + if (sc->pcie_slot_sta & PCIEM_SLOT_STA_ABP) { if (sc->flags & PCIB_DETACH_PENDING) { device_printf(dev, @@ -1165,7 +1184,7 @@ pcib_pcie_intr(void *arg) sc->pcie_slot_sta & PCIEM_SLOT_STA_MRLSS ? "open" : "closed"); if (bootverbose && sc->pcie_slot_sta & PCIEM_SLOT_STA_PDC) - device_printf(dev, "Present Detect Changed to %s\n", + device_printf(dev, "Presence Detect Changed to %s\n", sc->pcie_slot_sta & PCIEM_SLOT_STA_PDS ? "card present" : "empty"); if (sc->pcie_slot_sta & PCIEM_SLOT_STA_CC) @@ -1234,7 +1253,7 @@ pcib_pcie_cc_timeout(void *arg) sta = pcie_read_config(dev, PCIER_SLOT_STA, 2); if (!(sta & PCIEM_SLOT_STA_CC)) { device_printf(dev, - "Hotplug Command Timed Out - forcing detach\n"); + "HotPlug Command Timed Out - forcing detach\n"); sc->flags &= ~(PCIB_HOTPLUG_CMD_PENDING | PCIB_DETACH_PENDING); sc->flags |= PCIB_DETACHING; pcib_pcie_hotplug_update(sc, 0, 0, true);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608182147.u7ILl0H8075368>