mmc: core: Add SD card quirk for broken discard
authorAvri Altman <avri.altman@wdc.com>
Wed, 28 Sep 2022 09:57:44 +0000 (12:57 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 29 Oct 2022 08:12:58 +0000 (10:12 +0200)
commit 07d2872bf4c864eb83d034263c155746a2fb7a3b upstream.

Some SD-cards from Sandisk that are SDA-6.0 compliant reports they supports
discard, while they actually don't. This might cause mk2fs to fail while
trying to format the card and revert it to a read-only mode.

To fix this problem, let's add a card quirk (MMC_QUIRK_BROKEN_SD_DISCARD)
to indicate that we shall fall-back to use the legacy erase command
instead.

Signed-off-by: Avri Altman <avri.altman@wdc.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20220928095744.16455-1-avri.altman@wdc.com
[Ulf: Updated the commit message]
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mmc/core/block.c
drivers/mmc/core/card.h
drivers/mmc/core/quirks.h
include/linux/mmc/card.h

index 3222a9d0c2451f510439ec0761ba91d7bfab8b91..b2533be3a453fc08a144bfc78b5086c67fd0d6e7 100644 (file)
@@ -1107,6 +1107,11 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
        nr = blk_rq_sectors(req);
 
        do {
+               unsigned int erase_arg = card->erase_arg;
+
+               if (mmc_card_broken_sd_discard(card))
+                       erase_arg = SD_ERASE_ARG;
+
                err = 0;
                if (card->quirks & MMC_QUIRK_INAND_CMD38) {
                        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1117,7 +1122,7 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
                                         card->ext_csd.generic_cmd6_time);
                }
                if (!err)
-                       err = mmc_erase(card, from, nr, card->erase_arg);
+                       err = mmc_erase(card, from, nr, erase_arg);
        } while (err == -EIO && !mmc_blk_reset(md, card->host, type));
        if (err)
                status = BLK_STS_IOERR;
index 7bd392d55cfa5fa0ba1e1c3f04117354c8e8bd7a..5c6986131faff3719c3b4e40a0df2ebb63b23c28 100644 (file)
@@ -70,6 +70,7 @@ struct mmc_fixup {
 #define EXT_CSD_REV_ANY (-1u)
 
 #define CID_MANFID_SANDISK      0x2
+#define CID_MANFID_SANDISK_SD   0x3
 #define CID_MANFID_ATP          0x9
 #define CID_MANFID_TOSHIBA      0x11
 #define CID_MANFID_MICRON       0x13
@@ -222,4 +223,9 @@ static inline int mmc_card_broken_hpi(const struct mmc_card *c)
        return c->quirks & MMC_QUIRK_BROKEN_HPI;
 }
 
+static inline int mmc_card_broken_sd_discard(const struct mmc_card *c)
+{
+       return c->quirks & MMC_QUIRK_BROKEN_SD_DISCARD;
+}
+
 #endif
index d68e6e513a4f426c1ef5eb543dd6ff62c7444b80..c8c0f50a2076de540b07158995b0167858403b80 100644 (file)
@@ -99,6 +99,12 @@ 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),
 
+       /*
+        * Some SD cards reports discard support while they don't
+        */
+       MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd,
+                 MMC_QUIRK_BROKEN_SD_DISCARD),
+
        END_FIXUP
 };
 
index 37f975875102029e2ea30868258a788855d97d11..12c7f2d3e2107e88ea535a931cdb4bd3067bcd0c 100644 (file)
@@ -292,6 +292,7 @@ struct mmc_card {
 #define MMC_QUIRK_BROKEN_IRQ_POLLING   (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */
 #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 */
 
        bool                    reenable_cmdq;  /* Re-enable Command Queue */