PCI hot-plug: use dedicated taskqueue for device attach / detach
Attaching and detaching devices can be heavy-weight and detaching can sleep waiting for events. For that reason using the system-wide single-threaded taskqueue_thread is not really appropriate. There is even a possibility for a deadlock if taskqueue_thread is used for detaching. In fact, there is an easy to reproduce deadlock involving nvme, pass and a sudden removal of an NVMe device. A pass peripheral would not release a reference on an nvme sim until pass_shutdown_kqueue() is executed via taskqueue_thread. But the taskqueue's thread is blocked in nvme_detach() -> ... -> cam_sim_free() because of the outstanding reference. MFC after: 10 days Sponsored by: CyberSecure Reviewed by: mav, imp Differential Revision: https://reviews.freebsd.org/D30144
This commit is contained in:
parent
420dbe763f
commit
12588ce02d
@ -925,6 +925,8 @@ SYSCTL_INT(_hw_pci, OID_AUTO, enable_pcie_hp, CTLFLAG_RDTUN,
|
|||||||
&pci_enable_pcie_hp, 0,
|
&pci_enable_pcie_hp, 0,
|
||||||
"Enable support for native PCI-express HotPlug.");
|
"Enable support for native PCI-express HotPlug.");
|
||||||
|
|
||||||
|
TASKQUEUE_DEFINE_THREAD(pci_hp);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pcib_probe_hotplug(struct pcib_softc *sc)
|
pcib_probe_hotplug(struct pcib_softc *sc)
|
||||||
{
|
{
|
||||||
@ -1154,7 +1156,7 @@ pcib_pcie_hotplug_update(struct pcib_softc *sc, uint16_t val, uint16_t mask,
|
|||||||
*/
|
*/
|
||||||
if (schedule_task &&
|
if (schedule_task &&
|
||||||
(pcib_hotplug_present(sc) != 0) != (sc->child != NULL))
|
(pcib_hotplug_present(sc) != 0) != (sc->child != NULL))
|
||||||
taskqueue_enqueue(taskqueue_thread, &sc->pcie_hp_task);
|
taskqueue_enqueue(taskqueue_pci_hp, &sc->pcie_hp_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1449,7 +1451,7 @@ pcib_detach_hotplug(struct pcib_softc *sc)
|
|||||||
error = pcib_release_pcie_irq(sc);
|
error = pcib_release_pcie_irq(sc);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
taskqueue_drain(taskqueue_thread, &sc->pcie_hp_task);
|
taskqueue_drain(taskqueue_pci_hp, &sc->pcie_hp_task);
|
||||||
callout_drain(&sc->pcie_ab_timer);
|
callout_drain(&sc->pcie_ab_timer);
|
||||||
callout_drain(&sc->pcie_cc_timer);
|
callout_drain(&sc->pcie_cc_timer);
|
||||||
callout_drain(&sc->pcie_dll_timer);
|
callout_drain(&sc->pcie_dll_timer);
|
||||||
|
Loading…
Reference in New Issue
Block a user