]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mmc: core: Add SD card quirk for broken poweroff notification
authorKeita Aihara <keita.aihara@sony.com>
Fri, 13 Sep 2024 09:44:17 +0000 (18:44 +0900)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 14 Oct 2024 10:29:00 +0000 (12:29 +0200)
GIGASTONE Gaming Plus microSD cards manufactured on 02/2022 report that
they support poweroff notification and cache, but they are not working
correctly.

Flush Cache bit never gets cleared in sd_flush_cache() and Poweroff
Notification Ready bit also never gets set to 1 within 1 second from the
end of busy of CMD49 in sd_poweroff_notify().

This leads to I/O error and runtime PM error state.

I observed that the same card manufactured on 01/2024 works as expected.

This problem seems similar to the Kingston cards fixed with
commit c467c8f08185 ("mmc: Add MMC_QUIRK_BROKEN_SD_CACHE for Kingston
Canvas Go Plus from 11/2019") and should be handled using quirks.

CID for the problematic card is here.
12345641535443002000000145016200

Manufacturer ID is 0x12 and defined as CID_MANFID_GIGASTONE as of now,
but would like comments on what naming is appropriate because MID list
is not public and not sure it's right.

Signed-off-by: Keita Aihara <keita.aihara@sony.com>
Link: https://lore.kernel.org/r/20240913094417.GA4191647@sony.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/core/card.h
drivers/mmc/core/quirks.h
drivers/mmc/core/sd.c
include/linux/mmc/card.h

index b7754a1b8d9788c7f672da0ce8d443cf3cd40968..8476754b1b170c5698ea7da3d4e1008a70ead1c6 100644 (file)
@@ -82,6 +82,7 @@ struct mmc_fixup {
 #define CID_MANFID_SANDISK_SD   0x3
 #define CID_MANFID_ATP          0x9
 #define CID_MANFID_TOSHIBA      0x11
+#define CID_MANFID_GIGASTONE    0x12
 #define CID_MANFID_MICRON       0x13
 #define CID_MANFID_SAMSUNG      0x15
 #define CID_MANFID_APACER       0x27
@@ -284,4 +285,10 @@ static inline int mmc_card_broken_cache_flush(const struct mmc_card *c)
 {
        return c->quirks & MMC_QUIRK_BROKEN_CACHE_FLUSH;
 }
+
+static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c)
+{
+       return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY;
+}
+
 #endif
index 92905fc46436dd107563d7ec2985780539e385a0..89b512905be1400334322484805c3cca01dc69c6 100644 (file)
@@ -25,6 +25,15 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = {
                   0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
                   MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY),
 
+       /*
+        * GIGASTONE Gaming Plus microSD cards manufactured on 02/2022 never
+        * clear Flush Cache bit and set Poweroff Notification Ready bit.
+        */
+       _FIXUP_EXT("ASTC", CID_MANFID_GIGASTONE, 0x3456, 2022, 2,
+                  0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
+                  MMC_QUIRK_BROKEN_SD_CACHE | MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY,
+                  EXT_CSD_REV_ANY),
+
        END_FIXUP
 };
 
index 12fe282bea77ef96c210f408a36449a310abae8a..9e62cb7055fef96e041410ebe1ce8e1d93ee92bf 100644 (file)
@@ -1107,7 +1107,7 @@ static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page,
        card->ext_power.rev = reg_buf[0] & 0xf;
 
        /* Power Off Notification support at bit 4. */
-       if (reg_buf[1] & BIT(4))
+       if ((reg_buf[1] & BIT(4)) && !mmc_card_broken_sd_poweroff_notify(card))
                card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY;
 
        /* Power Sustenance support at bit 5. */
index f34407cc27888d8bccf550eea7645e3671ef89c2..543446392776fa28f8eb3a9c6be721b9a41b7be0 100644 (file)
@@ -294,6 +294,7 @@ struct mmc_card {
 #define MMC_QUIRK_BROKEN_SD_DISCARD    (1<<14) /* Disable broken SD discard support */
 #define MMC_QUIRK_BROKEN_SD_CACHE      (1<<15) /* Disable broken SD cache support */
 #define MMC_QUIRK_BROKEN_CACHE_FLUSH   (1<<16) /* Don't flush cache until the write has occurred */
+#define MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY    (1<<17) /* Disable broken SD poweroff notify support */
 
        bool                    written_flag;   /* Indicates eMMC has been written since power on */
        bool                    reenable_cmdq;  /* Re-enable Command Queue */