git: c0bed9bd0bda - main - mmc: Use bus_topo_lock and taskqueue_bus while adding/removing child devices

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Mon, 10 Mar 2025 17:35:41 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=c0bed9bd0bda2ca9239f5913cd2d5c1bd5d29bfa

commit c0bed9bd0bda2ca9239f5913cd2d5c1bd5d29bfa
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-03-10 17:32:53 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-03-10 17:32:53 +0000

    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
---
 sys/arm/allwinner/aw_mmc.c    | 11 ++++-------
 sys/dev/mmc/host/dwmmc.c      | 22 +++++++++-------------
 sys/dev/mmc/mmc_fdt_helpers.c | 10 +++++-----
 sys/dev/rtsx/rtsx.c           | 18 +++++++++++-------
 4 files changed, 29 insertions(+), 32 deletions(-)

diff --git a/sys/arm/allwinner/aw_mmc.c b/sys/arm/allwinner/aw_mmc.c
index 9f61e1560658..6bebf5e5fb5e 100644
--- a/sys/arm/allwinner/aw_mmc.c
+++ b/sys/arm/allwinner/aw_mmc.c
@@ -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 */
 }
 
diff --git a/sys/dev/mmc/host/dwmmc.c b/sys/dev/mmc/host/dwmmc.c
index 51709bcbb7e9..57992571982c 100644
--- a/sys/dev/mmc/host/dwmmc.c
+++ b/sys/dev/mmc/host/dwmmc.c
@@ -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);
diff --git a/sys/dev/mmc/mmc_fdt_helpers.c b/sys/dev/mmc/mmc_fdt_helpers.c
index 752e5d14bcb0..aed85dab55f4 100644
--- a/sys/dev/mmc/mmc_fdt_helpers.c
+++ b/sys/dev/mmc/mmc_fdt_helpers.c
@@ -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
diff --git a/sys/dev/rtsx/rtsx.c b/sys/dev/rtsx/rtsx.c
index f06b493e0c15..aed0bd6c8b8c 100644
--- a/sys/dev/rtsx/rtsx.c
+++ b/sys/dev/rtsx/rtsx.c
@@ -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);