]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mmc: Add MMC_QUIRK_BROKEN_SD_CACHE for Kingston Canvas Go Plus from 11/2019
authorMarek Vasut <marex@denx.de>
Tue, 20 Jun 2023 10:27:13 +0000 (12:27 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 20 Jun 2023 11:19:34 +0000 (13:19 +0200)
This microSD card never clears Flush Cache bit after cache flush has
been started in sd_flush_cache(). This leads e.g. to failure to mount
file system. Add a quirk which disables the SD cache for this specific
card from specific manufacturing date of 11/2019, since on newer dated
cards from 05/2023 the cache flush works correctly.

Fixes: 08ebf903af57 ("mmc: core: Fixup support for writeback-cache for eMMC and SD")
Signed-off-by: Marek Vasut <marex@denx.de>
Link: https://lore.kernel.org/r/20230620102713.7701-1-marex@denx.de
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 cfdd1ff40b865e4a4a8b4be002170106f4fc3e57..4edf9057fa79d320ef24dd47f066f1eb32c47600 100644 (file)
@@ -53,6 +53,10 @@ struct mmc_fixup {
        unsigned int manfid;
        unsigned short oemid;
 
+       /* Manufacturing date */
+       unsigned short year;
+       unsigned char month;
+
        /* SDIO-specific fields. You can use SDIO_ANY_ID here of course */
        u16 cis_vendor, cis_device;
 
@@ -68,6 +72,8 @@ struct mmc_fixup {
 
 #define CID_MANFID_ANY (-1u)
 #define CID_OEMID_ANY ((unsigned short) -1)
+#define CID_YEAR_ANY ((unsigned short) -1)
+#define CID_MONTH_ANY ((unsigned char) -1)
 #define CID_NAME_ANY (NULL)
 
 #define EXT_CSD_REV_ANY (-1u)
@@ -81,17 +87,21 @@ struct mmc_fixup {
 #define CID_MANFID_APACER       0x27
 #define CID_MANFID_KINGSTON     0x70
 #define CID_MANFID_HYNIX       0x90
+#define CID_MANFID_KINGSTON_SD 0x9F
 #define CID_MANFID_NUMONYX     0xFE
 
 #define END_FIXUP { NULL }
 
-#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end,       \
-                  _cis_vendor, _cis_device,                            \
-                  _fixup, _data, _ext_csd_rev)                         \
+#define _FIXUP_EXT(_name, _manfid, _oemid, _year, _month,      \
+                  _rev_start, _rev_end,                        \
+                  _cis_vendor, _cis_device,                    \
+                  _fixup, _data, _ext_csd_rev)                 \
        {                                               \
                .name = (_name),                        \
                .manfid = (_manfid),                    \
                .oemid = (_oemid),                      \
+               .year = (_year),                        \
+               .month = (_month),                      \
                .rev_start = (_rev_start),              \
                .rev_end = (_rev_end),                  \
                .cis_vendor = (_cis_vendor),            \
@@ -103,8 +113,8 @@ struct mmc_fixup {
 
 #define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end,    \
                      _fixup, _data, _ext_csd_rev)                      \
-       _FIXUP_EXT(_name, _manfid,                                      \
-                  _oemid, _rev_start, _rev_end,                        \
+       _FIXUP_EXT(_name, _manfid, _oemid, CID_YEAR_ANY, CID_MONTH_ANY, \
+                  _rev_start, _rev_end,                                \
                   SDIO_ANY_ID, SDIO_ANY_ID,                            \
                   _fixup, _data, _ext_csd_rev)                         \
 
@@ -118,8 +128,9 @@ struct mmc_fixup {
                      _ext_csd_rev)
 
 #define SDIO_FIXUP(_vendor, _device, _fixup, _data)                    \
-       _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY,                        \
-                   CID_OEMID_ANY, 0, -1ull,                            \
+       _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, CID_OEMID_ANY,         \
+                  CID_YEAR_ANY, CID_MONTH_ANY,                         \
+                  0, -1ull,                                            \
                   _vendor, _device,                                    \
                   _fixup, _data, EXT_CSD_REV_ANY)                      \
 
@@ -264,4 +275,9 @@ static inline int mmc_card_broken_sd_discard(const struct mmc_card *c)
        return c->quirks & MMC_QUIRK_BROKEN_SD_DISCARD;
 }
 
+static inline int mmc_card_broken_sd_cache(const struct mmc_card *c)
+{
+       return c->quirks & MMC_QUIRK_BROKEN_SD_CACHE;
+}
+
 #endif
index 8decb788a3dbfe57290bb618b00f870e399c49f0..32b64b564fb1fd774b1546d0f21c918647e71159 100644 (file)
@@ -53,6 +53,15 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
        MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
                  MMC_QUIRK_BLK_NO_CMD23),
 
+       /*
+        * Kingston Canvas Go! Plus microSD cards never finish SD cache flush.
+        * This has so far only been observed on cards from 11/2019, while new
+        * cards from 2023/05 do not exhibit this behavior.
+        */
+       _FIXUP_EXT("SD64G", CID_MANFID_KINGSTON_SD, 0x5449, 2019, 11,
+                  0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd,
+                  MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY),
+
        /*
         * Some SD cards lockup while using CMD23 multiblock transfers.
         */
@@ -223,6 +232,10 @@ static inline void mmc_fixup_device(struct mmc_card *card,
                if (f->of_compatible &&
                    !mmc_fixup_of_compatible_match(card, f->of_compatible))
                        continue;
+               if (f->year != CID_YEAR_ANY && f->year != card->cid.year)
+                       continue;
+               if (f->month != CID_MONTH_ANY && f->month != card->cid.month)
+                       continue;
 
                dev_dbg(&card->dev, "calling %ps\n", f->vendor_fixup);
                f->vendor_fixup(card, f->data);
index 72b664ed90cf6b7f5cc2c978eb7501d428427389..246ce027ae0aac41fe09ad6ec2db2b2b07ba8867 100644 (file)
@@ -1170,7 +1170,7 @@ static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page,
                card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT;
 
        /* Cache support at bit 0. */
-       if (reg_buf[4] & BIT(0))
+       if ((reg_buf[4] & BIT(0)) && !mmc_card_broken_sd_cache(card))
                card->ext_perf.feature_support |= SD_EXT_PERF_CACHE;
 
        /* Command queue support indicated via queue depth bits (0 to 4). */
index c726ea781255257070197f4802b62c9f3b38fc32..daa2f40d9ce65f6654676946a92b89ddbb594c19 100644 (file)
@@ -294,6 +294,7 @@ struct mmc_card {
 #define MMC_QUIRK_TRIM_BROKEN  (1<<12)         /* Skip trim */
 #define MMC_QUIRK_BROKEN_HPI   (1<<13)         /* Disable broken HPI support */
 #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 */
 
        bool                    reenable_cmdq;  /* Re-enable Command Queue */