mmc: Allow non-sleeping GPIO cd
authorEvan Green <evgreen@chromium.org>
Fri, 25 May 2018 19:25:23 +0000 (12:25 -0700)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 29 May 2018 10:24:26 +0000 (12:24 +0200)
This change uses the appropriate _cansleep or non-sleeping API for
reading GPIO card detect state. This allows users with GPIOs that
never sleep to avoid a warning when certain quirks are present.

The sdhci controller has an SDHCI_QUIRK_NO_CARD_NO_RESET, which
indicates that a controller will not reset properly if no card is
inserted. With this quirk enabled, mmc_get_cd_gpio is called in
several places with a spinlock held and interrupts disabled.
gpiod_get_raw_value_cansleep is not happy with this situation,
and throws out a warning.

For boards that a) use controllers that have this quirk, and b) wire
card detect up to a GPIO that doesn't sleep, this is a spurious warning.
This change silences that warning, at the cost of pushing this problem
down to users that have sleeping GPIOs and controllers with this quirk.

Signed-off-by: Evan Green <evgreen@chromium.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/core/slot-gpio.c

index 56559351d2e1fe373225a74f7697acf3331e7980..ef05e00393782d16d77f2f1ecf16803f69461217 100644 (file)
@@ -79,15 +79,22 @@ EXPORT_SYMBOL(mmc_gpio_get_ro);
 int mmc_gpio_get_cd(struct mmc_host *host)
 {
        struct mmc_gpio *ctx = host->slot.handler_priv;
+       int cansleep;
 
        if (!ctx || !ctx->cd_gpio)
                return -ENOSYS;
 
-       if (ctx->override_cd_active_level)
-               return !gpiod_get_raw_value_cansleep(ctx->cd_gpio) ^
-                       !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
+       cansleep = gpiod_cansleep(ctx->cd_gpio);
+       if (ctx->override_cd_active_level) {
+               int value = cansleep ?
+                               gpiod_get_raw_value_cansleep(ctx->cd_gpio) :
+                               gpiod_get_raw_value(ctx->cd_gpio);
+               return !value ^ !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
+       }
 
-       return gpiod_get_value_cansleep(ctx->cd_gpio);
+       return cansleep ?
+               gpiod_get_value_cansleep(ctx->cd_gpio) :
+               gpiod_get_value(ctx->cd_gpio);
 }
 EXPORT_SYMBOL(mmc_gpio_get_cd);