This diff disables sdmmc device detach in the resume path if APCI reports a non-removable device. This makes hibernate work for me on a laptop with root disk on internal emmc storage.
With help from kettenis@ diff d7548b5925dd9032f6a15d6aebaed5bffcbcd366 /usr/src blob - d6afef333a35d34751bc648701701d58dbd2034a file + sys/dev/acpi/sdhc_acpi.c --- sys/dev/acpi/sdhc_acpi.c +++ sys/dev/acpi/sdhc_acpi.c @@ -237,8 +237,13 @@ sdhc_acpi_do_explore(struct aml_node *node, void *arg) /* Override card detect if we have non-removable devices. */ if (aml_evalinteger(sc->sc_acpi, node, "_RMV", 0, NULL, &rmv)) rmv = 1; - if (rmv == 0 && sc->sc.sc_card_detect == NULL) - sc->sc.sc_card_detect = sdhc_acpi_card_detect_nonremovable; + if (rmv == 0) { + sc->sc.sc_flags |= SDHC_F_NONREMOVABLE; + if (sc->sc.sc_card_detect == NULL) { + sc->sc.sc_card_detect = + sdhc_acpi_card_detect_nonremovable; + } + } sdhc_acpi_power_on(sc, node); blob - 248878293e30407ccaf8b9c7ce4a901dbd9aca6c file + sys/dev/sdmmc/sdhc.c --- sys/dev/sdmmc/sdhc.c +++ sys/dev/sdmmc/sdhc.c @@ -335,6 +335,9 @@ sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t if (ISSET(sc->sc_flags, SDHC_F_NODDR50)) saa.caps &= ~SMC_CAPS_MMC_DDR52; + if (ISSET(sc->sc_flags, SDHC_F_NONREMOVABLE)) + saa.caps |= SMC_CAPS_NONREMOVABLE; + hp->sdmmc = config_found(&sc->sc_dev, &saa, NULL); if (hp->sdmmc == NULL) { error = 0; blob - 7775015ac97e7f275f51306e5a0829cd9bd31d83 file + sys/dev/sdmmc/sdhcvar.h --- sys/dev/sdmmc/sdhcvar.h +++ sys/dev/sdmmc/sdhcvar.h @@ -48,5 +48,6 @@ void sdhc_needs_discover(struct sdhc_softc *); /* flag values */ #define SDHC_F_NOPWR0 (1 << 0) #define SDHC_F_NODDR50 (1 << 1) +#define SDHC_F_NONREMOVABLE (1 << 2) #endif blob - 32285bce1cb57c6778a90551b69f62701dc1c59a file + sys/dev/sdmmc/sdmmc.c --- sys/dev/sdmmc/sdmmc.c +++ sys/dev/sdmmc/sdmmc.c @@ -181,7 +181,8 @@ sdmmc_activate(struct device *self, int act) case DVACT_SUSPEND: rv = config_activate_children(self, act); /* If card in slot, cause a detach/re-attach */ - if (ISSET(sc->sc_flags, SMF_CARD_PRESENT)) + if (ISSET(sc->sc_flags, SMF_CARD_PRESENT) && + !ISSET(sc->sc_caps, SMC_CAPS_NONREMOVABLE)) sc->sc_dying = -1; break; case DVACT_RESUME: blob - 1cc635e3182fd8e532d4d534b8010cfa22002b51 file + sys/dev/sdmmc/sdmmcvar.h --- sys/dev/sdmmc/sdmmcvar.h +++ sys/dev/sdmmc/sdmmcvar.h @@ -200,6 +200,7 @@ struct sdmmc_softc { #define SMC_CAPS_MMC_DDR52 0x2000 /* eMMC DDR52 timing */ #define SMC_CAPS_MMC_HS200 0x4000 /* eMMC HS200 timing */ #define SMC_CAPS_MMC_HS400 0x8000 /* eMMC HS400 timing */ +#define SMC_CAPS_NONREMOVABLE 0x10000 /* non-removable devices */ int sc_function_count; /* number of I/O functions (SDIO) */ struct sdmmc_function *sc_card; /* selected card */