summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card/block.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-05-15 08:39:25 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-15 08:39:25 -0300
commit69ecdbac144147a80747914d9b6ea3472e2d93e7 (patch)
treee1bb68c3568f370cd6a7d2ae29a051bee244ce0f /drivers/mmc/card/block.c
parentb7dc4cd17506284a47eeb9160207e43c7d5486fe (diff)
parentb6255ee3d82798eb1eee9fb1cca713317b5afae8 (diff)
Merge remote-tracking branch 'linus/master' into staging/for_v3.5
* linus/master: (805 commits) tty: Fix LED error return openvswitch: checking wrong variable in queue_userspace_packet() bonding: Fix LACPDU rx_dropped commit. Linux 3.4-rc7 ARM: EXYNOS: fix ctrlbit for exynos5_clk_pdma1 ARM: EXYNOS: use s5p-timer for UniversalC210 board ARM / mach-shmobile: Invalidate caches when booting secondary cores ARM / mach-shmobile: sh73a0 SMP TWD boot regression fix ARM / mach-shmobile: r8a7779 SMP TWD boot regression fix ARM: mach-shmobile: convert ag5evm to use the generic MMC GPIO hotplug helper ARM: mach-shmobile: convert mackerel to use the generic MMC GPIO hotplug helper MAINTAINERS: Add myself as the cpufreq maintainer dm mpath: check if scsi_dh module already loaded before trying to load dm thin: correct module description dm thin: fix unprotected use of prepared_discards list dm thin: reinstate missing mempool_free in cell_release_singleton gpio/exynos: Fix compiler warnings when non-exynos machines are selected gpio: pch9: Use proper flow type handlers powerpc/irq: Fix another case of lazy IRQ state getting out of sync ks8851: Update link status during link change interrupt ... Conflicts: drivers/media/common/tuners/xc5000.c drivers/media/common/tuners/xc5000.h drivers/usb/gadget/uvc_queue.c
Diffstat (limited to 'drivers/mmc/card/block.c')
-rw-r--r--drivers/mmc/card/block.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index b1809650b7a..dabec556ebb 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -873,7 +873,7 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
{
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))) {
@@ -881,20 +881,26 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
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,
@@ -904,25 +910,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);
@@ -1802,7 +1824,7 @@ static void mmc_blk_remove(struct mmc_card *card)
}
#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
+static int mmc_blk_suspend(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
struct mmc_blk_data *md = mmc_get_drvdata(card);