mirror of
https://github.com/opnsense/src.git
synced 2026-06-13 18:50:31 -04:00
mmc: Use bus_topo_lock and taskqueue_bus while adding/removing child devices
Some drivers held regular mutexes across some new-bus calls; instead depend on bus_topo_lock to protect the relevant softc members. This also fixes the bus_topo_lock to be explicit in these drivers rather than relying on the implicit Giant from taskqueue_swi_giant. It avoids calling sleepable routines like device_probe_and_attach from an swi context. Differential Revision: https://reviews.freebsd.org/D49270
This commit is contained in:
parent
b23314ecb9
commit
c0bed9bd0b
4 changed files with 29 additions and 32 deletions
|
|
@ -322,32 +322,29 @@ aw_mmc_helper_cd_handler(device_t dev, bool present)
|
|||
#ifdef MMCCAM
|
||||
mmc_cam_sim_discover(&sc->mmc_sim);
|
||||
#else
|
||||
AW_MMC_LOCK(sc);
|
||||
bus_topo_lock();
|
||||
if (present) {
|
||||
if (sc->child == NULL) {
|
||||
if (__predict_false(aw_mmc_debug & AW_MMC_DEBUG_CARD))
|
||||
device_printf(sc->aw_dev, "Card inserted\n");
|
||||
|
||||
sc->child = device_add_child(sc->aw_dev, "mmc", DEVICE_UNIT_ANY);
|
||||
AW_MMC_UNLOCK(sc);
|
||||
if (sc->child) {
|
||||
device_set_ivars(sc->child, sc);
|
||||
(void)device_probe_and_attach(sc->child);
|
||||
}
|
||||
} else
|
||||
AW_MMC_UNLOCK(sc);
|
||||
}
|
||||
} else {
|
||||
/* Card isn't present, detach if necessary */
|
||||
if (sc->child != NULL) {
|
||||
if (__predict_false(aw_mmc_debug & AW_MMC_DEBUG_CARD))
|
||||
device_printf(sc->aw_dev, "Card removed\n");
|
||||
|
||||
AW_MMC_UNLOCK(sc);
|
||||
device_delete_child(sc->aw_dev, sc->child);
|
||||
sc->child = NULL;
|
||||
} else
|
||||
AW_MMC_UNLOCK(sc);
|
||||
}
|
||||
}
|
||||
bus_topo_unlock();
|
||||
#endif /* MMCCAM */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -462,10 +462,10 @@ dwmmc_handle_card_present(struct dwmmc_softc *sc, bool is_present)
|
|||
was_present = sc->child != NULL;
|
||||
|
||||
if (!was_present && is_present) {
|
||||
taskqueue_enqueue_timeout(taskqueue_swi_giant,
|
||||
taskqueue_enqueue_timeout(taskqueue_bus,
|
||||
&sc->card_delayed_task, -(hz / 2));
|
||||
} else if (was_present && !is_present) {
|
||||
taskqueue_enqueue(taskqueue_swi_giant, &sc->card_task);
|
||||
taskqueue_enqueue(taskqueue_bus, &sc->card_task);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -477,8 +477,7 @@ dwmmc_card_task(void *arg, int pending __unused)
|
|||
#ifdef MMCCAM
|
||||
mmc_cam_sim_discover(&sc->mmc_sim);
|
||||
#else
|
||||
DWMMC_LOCK(sc);
|
||||
|
||||
bus_topo_lock();
|
||||
if (READ4(sc, SDMMC_CDETECT) == 0 ||
|
||||
(sc->mmc_helper.props & MMC_PROP_BROKEN_CD)) {
|
||||
if (sc->child == NULL) {
|
||||
|
|
@ -486,25 +485,22 @@ dwmmc_card_task(void *arg, int pending __unused)
|
|||
device_printf(sc->dev, "Card inserted\n");
|
||||
|
||||
sc->child = device_add_child(sc->dev, "mmc", DEVICE_UNIT_ANY);
|
||||
DWMMC_UNLOCK(sc);
|
||||
if (sc->child) {
|
||||
device_set_ivars(sc->child, sc);
|
||||
(void)device_probe_and_attach(sc->child);
|
||||
}
|
||||
} else
|
||||
DWMMC_UNLOCK(sc);
|
||||
}
|
||||
} else {
|
||||
/* Card isn't present, detach if necessary */
|
||||
if (sc->child != NULL) {
|
||||
if (bootverbose)
|
||||
device_printf(sc->dev, "Card removed\n");
|
||||
|
||||
DWMMC_UNLOCK(sc);
|
||||
device_delete_child(sc->dev, sc->child);
|
||||
sc->child = NULL;
|
||||
} else
|
||||
DWMMC_UNLOCK(sc);
|
||||
}
|
||||
}
|
||||
bus_topo_unlock();
|
||||
#endif /* MMCCAM */
|
||||
}
|
||||
|
||||
|
|
@ -751,7 +747,7 @@ dwmmc_attach(device_t dev)
|
|||
WRITE4(sc, SDMMC_CTRL, SDMMC_CTRL_INT_ENABLE);
|
||||
|
||||
TASK_INIT(&sc->card_task, 0, dwmmc_card_task, sc);
|
||||
TIMEOUT_TASK_INIT(taskqueue_swi_giant, &sc->card_delayed_task, 0,
|
||||
TIMEOUT_TASK_INIT(taskqueue_bus, &sc->card_delayed_task, 0,
|
||||
dwmmc_card_task, sc);
|
||||
|
||||
#ifdef MMCCAM
|
||||
|
|
@ -782,8 +778,8 @@ dwmmc_detach(device_t dev)
|
|||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
taskqueue_drain(taskqueue_swi_giant, &sc->card_task);
|
||||
taskqueue_drain_timeout(taskqueue_swi_giant, &sc->card_delayed_task);
|
||||
taskqueue_drain(taskqueue_bus, &sc->card_task);
|
||||
taskqueue_drain_timeout(taskqueue_bus, &sc->card_delayed_task);
|
||||
|
||||
if (sc->intr_cookie != NULL) {
|
||||
ret = bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ cd_intr(void *arg)
|
|||
{
|
||||
struct mmc_helper *helper = arg;
|
||||
|
||||
taskqueue_enqueue_timeout(taskqueue_swi_giant,
|
||||
taskqueue_enqueue_timeout(taskqueue_bus,
|
||||
&helper->cd_delayed_task, -(hz / 2));
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ cd_card_task(void *arg, int pending __unused)
|
|||
|
||||
/* If we're polling re-schedule the task */
|
||||
if (helper->cd_ihandler == NULL)
|
||||
taskqueue_enqueue_timeout_sbt(taskqueue_swi_giant,
|
||||
taskqueue_enqueue_timeout_sbt(taskqueue_bus,
|
||||
&helper->cd_delayed_task, mstosbt(500), 0, C_PREL(2));
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ cd_setup(struct mmc_helper *helper, phandle_t node)
|
|||
|
||||
dev = helper->dev;
|
||||
|
||||
TIMEOUT_TASK_INIT(taskqueue_swi_giant, &helper->cd_delayed_task, 0,
|
||||
TIMEOUT_TASK_INIT(taskqueue_bus, &helper->cd_delayed_task, 0,
|
||||
cd_card_task, helper);
|
||||
|
||||
/*
|
||||
|
|
@ -280,7 +280,7 @@ mmc_fdt_gpio_setup(device_t dev, phandle_t node, struct mmc_helper *helper,
|
|||
/*
|
||||
* Schedule a card detection
|
||||
*/
|
||||
taskqueue_enqueue_timeout_sbt(taskqueue_swi_giant,
|
||||
taskqueue_enqueue_timeout_sbt(taskqueue_bus,
|
||||
&helper->cd_delayed_task, mstosbt(500), 0, C_PREL(2));
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -301,7 +301,7 @@ mmc_fdt_gpio_teardown(struct mmc_helper *helper)
|
|||
if (helper->cd_ires != NULL)
|
||||
bus_release_resource(helper->dev, SYS_RES_IRQ, 0, helper->cd_ires);
|
||||
|
||||
taskqueue_drain_timeout(taskqueue_swi_giant, &helper->cd_delayed_task);
|
||||
taskqueue_drain_timeout(taskqueue_bus, &helper->cd_delayed_task);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -633,10 +633,10 @@ rtsx_handle_card_present(struct rtsx_softc *sc)
|
|||
* (sometimes the card detect pin stabilizes
|
||||
* before the other pins have made good contact).
|
||||
*/
|
||||
taskqueue_enqueue_timeout(taskqueue_swi_giant,
|
||||
taskqueue_enqueue_timeout(taskqueue_bus,
|
||||
&sc->rtsx_card_insert_task, -hz);
|
||||
} else if (was_present && !is_present) {
|
||||
taskqueue_enqueue(taskqueue_swi_giant, &sc->rtsx_card_remove_task);
|
||||
taskqueue_enqueue(taskqueue_bus, &sc->rtsx_card_remove_task);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -648,6 +648,9 @@ rtsx_card_task(void *arg, int pending __unused)
|
|||
{
|
||||
struct rtsx_softc *sc = arg;
|
||||
|
||||
#ifndef MMCCAM
|
||||
bus_topo_lock();
|
||||
#endif
|
||||
if (rtsx_is_card_present(sc)) {
|
||||
sc->rtsx_flags |= RTSX_F_CARD_PRESENT;
|
||||
/* Card is present, attach if necessary. */
|
||||
|
|
@ -664,9 +667,7 @@ rtsx_card_task(void *arg, int pending __unused)
|
|||
sc->rtsx_cam_status = 1;
|
||||
mmc_cam_sim_discover(&sc->rtsx_mmc_sim);
|
||||
#else /* !MMCCAM */
|
||||
RTSX_LOCK(sc);
|
||||
sc->rtsx_mmc_dev = device_add_child(sc->rtsx_dev, "mmc", DEVICE_UNIT_ANY);
|
||||
RTSX_UNLOCK(sc);
|
||||
if (sc->rtsx_mmc_dev == NULL) {
|
||||
device_printf(sc->rtsx_dev, "Adding MMC bus failed\n");
|
||||
} else {
|
||||
|
|
@ -699,6 +700,9 @@ rtsx_card_task(void *arg, int pending __unused)
|
|||
#endif /* MMCCAM */
|
||||
}
|
||||
}
|
||||
#ifndef MMCCAM
|
||||
bus_topo_unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -3690,7 +3694,7 @@ rtsx_attach(device_t dev)
|
|||
sc->rtsx_mem_btag = rman_get_bustag(sc->rtsx_mem_res);
|
||||
sc->rtsx_mem_bhandle = rman_get_bushandle(sc->rtsx_mem_res);
|
||||
|
||||
TIMEOUT_TASK_INIT(taskqueue_swi_giant, &sc->rtsx_card_insert_task, 0,
|
||||
TIMEOUT_TASK_INIT(taskqueue_bus, &sc->rtsx_card_insert_task, 0,
|
||||
rtsx_card_task, sc);
|
||||
TASK_INIT(&sc->rtsx_card_remove_task, 0, rtsx_card_task, sc);
|
||||
|
||||
|
|
@ -3789,8 +3793,8 @@ rtsx_detach(device_t dev)
|
|||
return (error);
|
||||
sc->rtsx_mmc_dev = NULL;
|
||||
|
||||
taskqueue_drain_timeout(taskqueue_swi_giant, &sc->rtsx_card_insert_task);
|
||||
taskqueue_drain(taskqueue_swi_giant, &sc->rtsx_card_remove_task);
|
||||
taskqueue_drain_timeout(taskqueue_bus, &sc->rtsx_card_insert_task);
|
||||
taskqueue_drain(taskqueue_bus, &sc->rtsx_card_remove_task);
|
||||
|
||||
/* Teardown the state in our softc created in our attach routine. */
|
||||
rtsx_dma_free(sc);
|
||||
|
|
|
|||
Loading…
Reference in a new issue