--- /dev/null
+From 7194efb8f063ee3aa0cb50d9002348887e68ec10 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Thu, 5 Apr 2012 14:45:47 +0300
+Subject: mmc: fixes for eMMC v4.5 discard operation
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit 7194efb8f063ee3aa0cb50d9002348887e68ec10 upstream.
+
+eMMC v4.5 discard operation is significantly different from the
+existing trim operation because it is not guaranteed to work with
+the new sanitize operation. Consequently mmc_can_trim() is
+separated from mmc_can_discard().
+
+Also the new discard operation does not result in the sectors being
+set to all-zeros, so discard_zeroes_data must not be set.
+
+In addition, the new discard has the same timeout as trim, but from
+v4.5 trim is defined to use the hc timeout. The timeout calculation
+is adjusted accordingly.
+
+Fixes apply to linux 3.2 on.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mmc/card/queue.c | 2 +-
+ drivers/mmc/core/core.c | 7 ++++---
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/mmc/card/queue.c
++++ b/drivers/mmc/card/queue.c
+@@ -139,7 +139,7 @@ static void mmc_queue_setup_discard(stru
+
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+ q->limits.max_discard_sectors = max_discard;
+- if (card->erased_byte == 0)
++ if (card->erased_byte == 0 && !mmc_can_discard(card))
+ q->limits.discard_zeroes_data = 1;
+ q->limits.discard_granularity = card->pref_erase << 9;
+ /* granularity must not be greater than max. discard */
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -1557,7 +1557,10 @@ static unsigned int mmc_mmc_erase_timeou
+ {
+ unsigned int erase_timeout;
+
+- if (card->ext_csd.erase_group_def & 1) {
++ if (arg == MMC_DISCARD_ARG ||
++ (arg == MMC_TRIM_ARG && card->ext_csd.rev >= 6)) {
++ erase_timeout = card->ext_csd.trim_timeout;
++ } else if (card->ext_csd.erase_group_def & 1) {
+ /* High Capacity Erase Group Size uses HC timeouts */
+ if (arg == MMC_TRIM_ARG)
+ erase_timeout = card->ext_csd.trim_timeout;
+@@ -1829,8 +1832,6 @@ int mmc_can_trim(struct mmc_card *card)
+ {
+ if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)
+ return 1;
+- if (mmc_can_discard(card))
+- return 1;
+ return 0;
+ }
+ EXPORT_SYMBOL(mmc_can_trim);
--- /dev/null
+From 283028122db37621b124f079ca8eae5b64807ad4 Mon Sep 17 00:00:00 2001
+From: Adrian Hunter <adrian.hunter@intel.com>
+Date: Thu, 5 Apr 2012 14:45:48 +0300
+Subject: mmc: fixes for eMMC v4.5 sanitize operation
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+commit 283028122db37621b124f079ca8eae5b64807ad4 upstream.
+
+eMMC v4.5 sanitize operation erases all copies of unmapped
+data. However trim or erase operations must be used first
+to unmap the required sectors. That was not being done.
+
+Fixes apply to linux 3.2 on.
+
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mmc/card/block.c | 54 +++++++++++++++++++++++++++++++++--------------
+ drivers/mmc/core/core.c | 2 +
+ 2 files changed, 40 insertions(+), 16 deletions(-)
+
+--- a/drivers/mmc/card/block.c
++++ b/drivers/mmc/card/block.c
+@@ -874,7 +874,7 @@ static int mmc_blk_issue_secdiscard_rq(s
+ {
+ struct mmc_blk_data *md = mq->data;
+ struct mmc_card *card = md->queue.card;
+- unsigned int from, nr, arg;
++ unsigned int from, nr, arg, trim_arg, erase_arg;
+ int err = 0, type = MMC_BLK_SECDISCARD;
+
+ if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
+@@ -882,20 +882,26 @@ static int mmc_blk_issue_secdiscard_rq(s
+ goto out;
+ }
+
++ from = blk_rq_pos(req);
++ nr = blk_rq_sectors(req);
++
+ /* The sanitize operation is supported at v4.5 only */
+ if (mmc_can_sanitize(card)) {
+- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+- EXT_CSD_SANITIZE_START, 1, 0);
+- goto out;
++ erase_arg = MMC_ERASE_ARG;
++ trim_arg = MMC_TRIM_ARG;
++ } else {
++ erase_arg = MMC_SECURE_ERASE_ARG;
++ trim_arg = MMC_SECURE_TRIM1_ARG;
+ }
+
+- from = blk_rq_pos(req);
+- nr = blk_rq_sectors(req);
+-
+- if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
+- arg = MMC_SECURE_TRIM1_ARG;
+- else
+- arg = MMC_SECURE_ERASE_ARG;
++ if (mmc_erase_group_aligned(card, from, nr))
++ arg = erase_arg;
++ else if (mmc_can_trim(card))
++ arg = trim_arg;
++ else {
++ err = -EINVAL;
++ goto out;
++ }
+ retry:
+ if (card->quirks & MMC_QUIRK_INAND_CMD38) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+@@ -905,25 +911,41 @@ retry:
+ INAND_CMD38_ARG_SECERASE,
+ 0);
+ if (err)
+- goto out;
++ goto out_retry;
+ }
++
+ err = mmc_erase(card, from, nr, arg);
+- if (!err && arg == MMC_SECURE_TRIM1_ARG) {
++ if (err == -EIO)
++ goto out_retry;
++ if (err)
++ goto out;
++
++ if (arg == MMC_SECURE_TRIM1_ARG) {
+ if (card->quirks & MMC_QUIRK_INAND_CMD38) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ INAND_CMD38_ARG_EXT_CSD,
+ INAND_CMD38_ARG_SECTRIM2,
+ 0);
+ if (err)
+- goto out;
++ goto out_retry;
+ }
++
+ err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
++ if (err == -EIO)
++ goto out_retry;
++ if (err)
++ goto out;
+ }
+-out:
+- if (err == -EIO && !mmc_blk_reset(md, card->host, type))
++
++ if (mmc_can_sanitize(card))
++ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
++ EXT_CSD_SANITIZE_START, 1, 0);
++out_retry:
++ if (err && !mmc_blk_reset(md, card->host, type))
+ goto retry;
+ if (!err)
+ mmc_blk_reset_success(md, type);
++out:
+ spin_lock_irq(&md->lock);
+ __blk_end_request(req, err, blk_rq_bytes(req));
+ spin_unlock_irq(&md->lock);
+--- a/drivers/mmc/core/core.c
++++ b/drivers/mmc/core/core.c
+@@ -1850,6 +1850,8 @@ EXPORT_SYMBOL(mmc_can_discard);
+
+ int mmc_can_sanitize(struct mmc_card *card)
+ {
++ if (!mmc_can_trim(card) && !mmc_can_erase(card))
++ return 0;
+ if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
+ return 1;
+ return 0;
--- /dev/null
+From 87b87a3fc0eec58d95e4216392f889a26439ad22 Mon Sep 17 00:00:00 2001
+From: Daniel Drake <dsd@laptop.org>
+Date: Tue, 10 Apr 2012 00:14:20 +0100
+Subject: mmc: sdhci: refine non-removable card checking for card detection
+
+From: Daniel Drake <dsd@laptop.org>
+
+commit 87b87a3fc0eec58d95e4216392f889a26439ad22 upstream.
+
+Commit c79396c191bc19 ("mmc: sdhci: prevent card detection activity
+for non-removable cards") disables card detection where the cards
+are marked as non-removable.
+
+This makes sense, but the implementation detail of calling
+mmc_card_is_removable() causes some problems, because
+mmc_card_is_removable() is overloaded with CONFIG_MMC_UNSAFE_RESUME
+semantics.
+
+In the OLPC XO case, we need CONFIG_MMC_UNSAFE_RESUME because our root
+filesystem is stored on SD, but we also have external SD card slots
+where we want automatic card detection.
+
+Refine the check to only apply to hosts marked as MMC_CAP_NONREMOVABLE,
+which is defined to mean that the card is *really* nonremovable. This
+could be revisited in future if we find a way to improve
+CONFIG_MMC_UNSAFE_RESUME semantics.
+
+Signed-off-by: Daniel Drake <dsd@laptop.org>
+Acked-by: Chuanxiao Dong <chuanxiao.dong@intel.com>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mmc/host/sdhci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -147,7 +147,7 @@ static void sdhci_set_card_detection(str
+ u32 present, irqs;
+
+ if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
+- !mmc_card_is_removable(host->mmc))
++ (host->mmc->caps & MMC_CAP_NONREMOVABLE))
+ return;
+
+ present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
--- /dev/null
+From b89152824f993a9572b47eb31f4579feadeac34c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Eric=20B=C3=A9nard?= <eric@eukrea.com>
+Date: Wed, 18 Apr 2012 02:30:20 +0200
+Subject: mmc: unbreak sdhci-esdhc-imx on i.MX25
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Bénard <eric@eukrea.com>
+
+commit b89152824f993a9572b47eb31f4579feadeac34c upstream.
+
+This was broken by me in 37865fe91582582a6f6c00652f6a2b1ff71f8a78
+("mmc: sdhci-esdhc-imx: fix timeout on i.MX's sdhci") where more
+extensive tests would have shown that read or write of data to the
+card were failing (even if the partition table was correctly read).
+
+Signed-off-by: Eric Bénard <eric@eukrea.com>
+Acked-by: Wolfram Sang <w.sang@pengutronix.de>
+Signed-off-by: Chris Ball <cjb@laptop.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -467,8 +467,7 @@ static int __devinit sdhci_esdhc_imx_pro
+ clk_enable(clk);
+ pltfm_host->clk = clk;
+
+- if (!is_imx25_esdhc(imx_data))
+- host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
++ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+
+ if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
+ /* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
arm-at91-fix-at91sam9261ek-ethernet-dm9000-irq.patch
arm-omap1-dmtimer-fix-broken-timer-clock-source-selection.patch
arm-omap-serial-fix-the-ocp-smart-idlemode-handling-bug.patch
+mmc-fixes-for-emmc-v4.5-discard-operation.patch
+mmc-fixes-for-emmc-v4.5-sanitize-operation.patch
+mmc-sdhci-refine-non-removable-card-checking-for-card-detection.patch
+mmc-unbreak-sdhci-esdhc-imx-on-i.mx25.patch