Index: sys/dev/pci/pci_pci.c =================================================================== --- sys/dev/pci/pci_pci.c +++ sys/dev/pci/pci_pci.c @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -1370,27 +1371,10 @@ } static void -pcib_setup_hotplug(struct pcib_softc *sc) +pcib_pcihp_enable(void *xsc) { - device_t dev; uint16_t mask, val; - - dev = sc->dev; - callout_init(&sc->pcie_ab_timer, 0); - callout_init(&sc->pcie_cc_timer, 0); - callout_init(&sc->pcie_dll_timer, 0); - TASK_INIT(&sc->pcie_hp_task, 0, pcib_pcie_hotplug_task, sc); - sc->pcie_hp_lock = &Giant; - - /* Allocate IRQ. */ - if (pcib_alloc_pcie_irq(sc) != 0) - return; - - sc->pcie_link_sta = pcie_read_config(dev, PCIER_LINK_STA, 2); - sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2); - - /* Clear any events previously pending. */ - pcie_write_config(dev, PCIER_SLOT_STA, sc->pcie_slot_sta, 2); + struct pcib_softc *sc = xsc; /* Enable HotPlug events. */ mask = PCIEM_SLOT_CTL_DLLSCE | PCIEM_SLOT_CTL_HPIE | @@ -1415,6 +1399,37 @@ pcib_pcie_hotplug_update(sc, val, mask, false); } +static void +pcib_setup_hotplug(struct pcib_softc *sc) +{ + device_t dev; + + dev = sc->dev; + callout_init(&sc->pcie_ab_timer, 0); + callout_init(&sc->pcie_cc_timer, 0); + callout_init(&sc->pcie_dll_timer, 0); + TASK_INIT(&sc->pcie_hp_task, 0, pcib_pcie_hotplug_task, sc); + sc->pcie_hp_lock = &Giant; + + /* Allocate IRQ. */ + if (pcib_alloc_pcie_irq(sc) != 0) + return; + + sc->pcie_link_sta = pcie_read_config(dev, PCIER_LINK_STA, 2); + sc->pcie_slot_sta = pcie_read_config(dev, PCIER_SLOT_STA, 2); + + /* Clear any events previously pending. */ + pcie_write_config(dev, PCIER_SLOT_STA, sc->pcie_slot_sta, 2); + + /* + * Defer enabling hot plug interrupts until after the config_intrhook + * have run. Otherwise we can race devices that have attached and registered + * a config intrhook, but whose hook isn't yet complete. + */ + EVENTHANDLER_REGISTER(config_intrhook_bootdone, pcib_pcihp_enable, sc, + EVENTHANDLER_PRI_FIRST); +} + static int pcib_detach_hotplug(struct pcib_softc *sc) { Index: sys/kern/subr_autoconf.c =================================================================== --- sys/kern/subr_autoconf.c +++ sys/kern/subr_autoconf.c @@ -42,6 +42,7 @@ #include "opt_ddb.h" #include +#include #include #include #include @@ -171,6 +172,7 @@ } mtx_unlock(&intr_config_hook_lock); TSUNWAIT("config hooks"); + EVENTHANDLER_INVOKE(config_intrhook_bootdone); } SYSINIT(intr_config_hooks, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_FIRST, Index: sys/sys/eventhandler.h =================================================================== --- sys/sys/eventhandler.h +++ sys/sys/eventhandler.h @@ -317,4 +317,8 @@ typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int); EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn); +/* Config intrhook events */ +typedef void (*config_intrhook_bootdone_fn)(void *); +EVENTHANDLER_DECLARE(config_intrhook_bootdone, config_intrhook_bootdone_fn); + #endif /* _SYS_EVENTHANDLER_H_ */