brcm2708: rename all patches from raspberrypi git tree to use 950 prefix
[openwrt/staging/lynxis.git] / target / linux / brcm2708 / patches-4.9 / 950-0036-mmc-Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch
diff --git a/target/linux/brcm2708/patches-4.9/950-0036-mmc-Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch b/target/linux/brcm2708/patches-4.9/950-0036-mmc-Add-MMC_QUIRK_ERASE_BROKEN-for-some-cards.patch
new file mode 100644 (file)
index 0000000..d84a0fe
--- /dev/null
@@ -0,0 +1,132 @@
+From 6d11059a087b8101cf34a09a1e3342bb4f1576de Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 11 May 2016 12:50:33 +0100
+Subject: [PATCH] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards
+
+Some SD cards have been found that corrupt data when small blocks
+are erased. Add a quirk to indicate that ERASE should not be used,
+and set it for cards of that type.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+
+mmc: Apply QUIRK_BROKEN_ERASE to other capacities
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+
+mmc: Add card_quirks module parameter, log quirks
+
+Use mmc_block.card_quirks to override the quirks for all SD or MMC
+cards. The value is a bitfield using the bit positions defined in
+include/linux/mmc/card.h. If the module parameter is placed in the
+kernel command line (or bootargs) stored on the card then, assuming the
+device only has one SD card interface, the override effectively becomes
+card-specific.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/card/block.c | 39 ++++++++++++++++++++++++++++++++++++---
+ drivers/mmc/core/core.c  |  3 ++-
+ include/linux/mmc/card.h |  3 +++
+ 3 files changed, 41 insertions(+), 4 deletions(-)
+
+--- a/drivers/mmc/card/block.c
++++ b/drivers/mmc/card/block.c
+@@ -135,6 +135,13 @@ enum {
+ module_param(perdev_minors, int, 0444);
+ MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
++/*
++ * Allow quirks to be overridden for the current card
++ */
++static char *card_quirks;
++module_param(card_quirks, charp, 0644);
++MODULE_PARM_DESC(card_quirks, "Force the use of the indicated quirks (a bitfield)");
++
+ static inline int mmc_blk_part_switch(struct mmc_card *card,
+                                     struct mmc_blk_data *md);
+ static int get_card_status(struct mmc_card *card, u32 *status, int retries);
+@@ -2573,6 +2580,17 @@ static const struct mmc_fixup blk_fixups
+       MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_TRIM_BROKEN),
++      /*
++       *  On some Kingston SD cards, multiple erases of less than 64
++       *  sectors can cause corruption.
++       */
++      MMC_FIXUP("SD16G", 0x41, 0x3432, add_quirk_mmc,
++                MMC_QUIRK_ERASE_BROKEN),
++      MMC_FIXUP("SD32G", 0x41, 0x3432, add_quirk_mmc,
++                MMC_QUIRK_ERASE_BROKEN),
++      MMC_FIXUP("SD64G", 0x41, 0x3432, add_quirk_mmc,
++                MMC_QUIRK_ERASE_BROKEN),
++
+       END_FIXUP
+ };
+@@ -2580,6 +2598,7 @@ static int mmc_blk_probe(struct mmc_card
+ {
+       struct mmc_blk_data *md, *part_md;
+       char cap_str[10];
++      char quirk_str[24];
+       /*
+        * Check that the card supports the command class(es) we need.
+@@ -2587,7 +2606,16 @@ static int mmc_blk_probe(struct mmc_card
+       if (!(card->csd.cmdclass & CCC_BLOCK_READ))
+               return -ENODEV;
+-      mmc_fixup_device(card, blk_fixups);
++      if (card_quirks) {
++              unsigned long quirks;
++              if (kstrtoul(card_quirks, 0, &quirks) == 0)
++                      card->quirks = (unsigned int)quirks;
++              else
++                      pr_err("mmc_block: Invalid card_quirks parameter '%s'\n",
++                             card_quirks);
++      }
++      else
++              mmc_fixup_device(card, blk_fixups);
+       md = mmc_blk_alloc(card);
+       if (IS_ERR(md))
+@@ -2595,9 +2623,14 @@ static int mmc_blk_probe(struct mmc_card
+       string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
+                       cap_str, sizeof(cap_str));
+-      pr_info("%s: %s %s %s %s\n",
++      if (card->quirks)
++              snprintf(quirk_str, sizeof(quirk_str),
++                       " (quirks 0x%08x)", card->quirks);
++      else
++              quirk_str[0] = '\0';
++      pr_info("%s: %s %s %s%s%s\n",
+               md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
+-              cap_str, md->read_only ? "(ro)" : "");
++              cap_str, md->read_only ? " (ro)" : "", quirk_str);
+       if (mmc_blk_alloc_parts(card, md))
+               goto out;
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -2409,7 +2409,8 @@ EXPORT_SYMBOL(mmc_erase);
+ int mmc_can_erase(struct mmc_card *card)
+ {
+       if ((card->host->caps & MMC_CAP_ERASE) &&
+-          (card->csd.cmdclass & CCC_ERASE) && card->erase_size)
++          (card->csd.cmdclass & CCC_ERASE) && card->erase_size &&
++          !(card->quirks & MMC_QUIRK_ERASE_BROKEN))
+               return 1;
+       return 0;
+ }
+--- a/include/linux/mmc/card.h
++++ b/include/linux/mmc/card.h
+@@ -283,6 +283,9 @@ struct mmc_card {
+ #define MMC_QUIRK_BROKEN_HPI  (1<<13)         /* Disable broken HPI support */
++#define MMC_QUIRK_ERASE_BROKEN        (1<<31)         /* Skip erase */
++
++
+       unsigned int            erase_size;     /* erase size in sectors */
+       unsigned int            erase_shift;    /* if erase unit is power 2 */
+       unsigned int            pref_erase;     /* in sectors */