sdhc: avoid taking adaptive mutex while holding spin mutex the clock_bus pre- and post- callbacks used in sdhc_bus_clock_ddr() are called with a spin mutex held, and the new sdhc@acpi ends up calling into (sleeping) ACPI code, triggering lockdebug assertion. introduce an adaptive mutex that is held around these callbacks, and reduce the spin mutex held time in sdhc_bus_clock_ddr(). Index: sys/dev/sdmmc/sdhc.c =================================================================== RCS file: /cvsroot/src/sys/dev/sdmmc/sdhc.c,v retrieving revision 1.113 diff -p -u -r1.113 sdhc.c --- sys/dev/sdmmc/sdhc.c 15 Jan 2022 14:33:36 -0000 1.113 +++ sys/dev/sdmmc/sdhc.c 15 Jan 2022 22:26:58 -0000 @@ -77,6 +77,7 @@ struct sdhc_host { uint16_t intr_status; /* soft interrupt status */ uint16_t intr_error_status; /* soft error status */ kmutex_t intr_lock; + kmutex_t bus_clock_lock; kcondvar_t intr_cv; callout_t tuning_timer; @@ -296,6 +297,7 @@ sdhc_host_found(struct sdhc_softc *sc, b hp->dmat = sc->sc_dmat; mutex_init(&hp->intr_lock, MUTEX_DEFAULT, IPL_SDMMC); + mutex_init(&hp->bus_clock_lock, MUTEX_DEFAULT, IPL_NONE); cv_init(&hp->intr_cv, "sdhcintr"); callout_init(&hp->tuning_timer, CALLOUT_MPSAFE); callout_setfunc(&hp->tuning_timer, sdhc_tuning_timer, hp); @@ -650,6 +652,7 @@ adma_done: err: callout_destroy(&hp->tuning_timer); cv_destroy(&hp->intr_cv); + mutex_destroy(&hp->bus_clock_lock); mutex_destroy(&hp->intr_lock); free(hp, M_DEVBUF); sc->sc_host[--sc->sc_nhosts] = NULL; @@ -1097,8 +1100,6 @@ sdhc_bus_clock_ddr(sdmmc_chipset_handle_ int error = 0; bool present __diagused; - mutex_enter(&hp->intr_lock); - #ifdef DIAGNOSTIC present = ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK); @@ -1110,11 +1111,15 @@ sdhc_bus_clock_ddr(sdmmc_chipset_handle_ #endif if (hp->sc->sc_vendor_bus_clock) { + mutex_enter(&hp->bus_clock_lock); error = (*hp->sc->sc_vendor_bus_clock)(hp->sc, freq); + mutex_exit(&hp->bus_clock_lock); if (error != 0) - goto out; + return error; } + mutex_enter(&hp->intr_lock); + /* * Stop SD clock before changing the frequency. */ @@ -1275,11 +1280,14 @@ sdhc_bus_clock_ddr(sdmmc_chipset_handle_ HCLR1(hp, SDHC_HOST_CTL, SDHC_HIGH_SPEED); } + mutex_exit(&hp->intr_lock); + if (hp->sc->sc_vendor_bus_clock_post) { + mutex_enter(&hp->bus_clock_lock); error = (*hp->sc->sc_vendor_bus_clock_post)(hp->sc, freq); - if (error != 0) - goto out; + mutex_exit(&hp->bus_clock_lock); } + return error; out: mutex_exit(&hp->intr_lock);