diff mbox series

[v2] mmc: Add MMC_QUIRK_BROKEN_SD_CACHE for Kingston Canvas Go Plus from 11/2019

Message ID 20230620102713.7701-1-marex@denx.de (mailing list archive)
State New, archived
Headers show
Series [v2] mmc: Add MMC_QUIRK_BROKEN_SD_CACHE for Kingston Canvas Go Plus from 11/2019 | expand

Commit Message

Marek Vasut June 20, 2023, 10:27 a.m. UTC
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>
---
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Avri Altman <avri.altman@wdc.com>
Cc: Brian Norris <briannorris@chromium.org>
Cc: ChanWoo Lee <cw9316.lee@samsung.com>
Cc: Liang He <windhl@126.com>
Cc: Seunghui Lee <sh043.lee@samsung.com>
Cc: Ulf Hansson <ulf.hansson@linaro.org>
Cc: Xander Li <xander_li@kingston.com.tw>
Cc: Zhen Lei <thunder.leizhen@huawei.com>
Cc: linux-mmc@vger.kernel.org
---
V2: Drop the unnecessary bail out points
---
 drivers/mmc/core/card.h   | 30 +++++++++++++++++++++++-------
 drivers/mmc/core/quirks.h | 13 +++++++++++++
 drivers/mmc/core/sd.c     |  2 +-
 include/linux/mmc/card.h  |  1 +
 4 files changed, 38 insertions(+), 8 deletions(-)

Comments

Ulf Hansson June 20, 2023, 11:20 a.m. UTC | #1
On Tue, 20 Jun 2023 at 12:27, Marek Vasut <marex@denx.de> wrote:
>
> 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>

Applied for next and by adding a stable tag, thanks!

Kind regards
Uffe


> ---
> Cc: Adrian Hunter <adrian.hunter@intel.com>
> Cc: Avri Altman <avri.altman@wdc.com>
> Cc: Brian Norris <briannorris@chromium.org>
> Cc: ChanWoo Lee <cw9316.lee@samsung.com>
> Cc: Liang He <windhl@126.com>
> Cc: Seunghui Lee <sh043.lee@samsung.com>
> Cc: Ulf Hansson <ulf.hansson@linaro.org>
> Cc: Xander Li <xander_li@kingston.com.tw>
> Cc: Zhen Lei <thunder.leizhen@huawei.com>
> Cc: linux-mmc@vger.kernel.org
> ---
> V2: Drop the unnecessary bail out points
> ---
>  drivers/mmc/core/card.h   | 30 +++++++++++++++++++++++-------
>  drivers/mmc/core/quirks.h | 13 +++++++++++++
>  drivers/mmc/core/sd.c     |  2 +-
>  include/linux/mmc/card.h  |  1 +
>  4 files changed, 38 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
> index cfdd1ff40b865..4edf9057fa79d 100644
> --- a/drivers/mmc/core/card.h
> +++ b/drivers/mmc/core/card.h
> @@ -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
> diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
> index 29b9497936df9..bf7fb72ab8b57 100644
> --- a/drivers/mmc/core/quirks.h
> +++ b/drivers/mmc/core/quirks.h
> @@ -100,6 +100,15 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
>         MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
>                   MMC_QUIRK_TRIM_BROKEN),
>
> +       /*
> +        * 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 reports discard support while they don't
>          */
> @@ -209,6 +218,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);
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index 72b664ed90cf6..246ce027ae0aa 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -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). */
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index c726ea7812552..daa2f40d9ce65 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -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 */
>
> --
> 2.39.2
>
diff mbox series

Patch

diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h
index cfdd1ff40b865..4edf9057fa79d 100644
--- a/drivers/mmc/core/card.h
+++ b/drivers/mmc/core/card.h
@@ -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
diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
index 29b9497936df9..bf7fb72ab8b57 100644
--- a/drivers/mmc/core/quirks.h
+++ b/drivers/mmc/core/quirks.h
@@ -100,6 +100,15 @@  static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
 	MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
 		  MMC_QUIRK_TRIM_BROKEN),
 
+	/*
+	 * 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 reports discard support while they don't
 	 */
@@ -209,6 +218,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);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 72b664ed90cf6..246ce027ae0aa 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -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). */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index c726ea7812552..daa2f40d9ce65 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -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 */