diff options
author | Andrei Warkentin <andreiw@motorola.com> | 2011-04-12 16:06:53 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-05-24 21:01:34 -0400 |
commit | 6a7a6b45f454686a1549729bfbae31f0b3b595d6 (patch) | |
tree | dafdeae86c51d07c0115065114906d438781a50d /drivers/mmc | |
parent | f6a03cbf43e586211f8ea088148c8ecd3fc4b5be (diff) |
mmc: quirks: Fix erase/trim for certain SanDisk cards.
CMD38 argument is passed through EXT_CSD[113].
Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 288d27394ef9..c20995323348 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -48,6 +48,13 @@ MODULE_ALIAS("mmc:block"); | |||
48 | #endif | 48 | #endif |
49 | #define MODULE_PARAM_PREFIX "mmcblk." | 49 | #define MODULE_PARAM_PREFIX "mmcblk." |
50 | 50 | ||
51 | #define INAND_CMD38_ARG_EXT_CSD 113 | ||
52 | #define INAND_CMD38_ARG_ERASE 0x00 | ||
53 | #define INAND_CMD38_ARG_TRIM 0x01 | ||
54 | #define INAND_CMD38_ARG_SECERASE 0x80 | ||
55 | #define INAND_CMD38_ARG_SECTRIM1 0x81 | ||
56 | #define INAND_CMD38_ARG_SECTRIM2 0x88 | ||
57 | |||
51 | #define REL_WRITES_SUPPORTED(card) (mmc_card_mmc((card)) && \ | 58 | #define REL_WRITES_SUPPORTED(card) (mmc_card_mmc((card)) && \ |
52 | (((card)->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || \ | 59 | (((card)->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || \ |
53 | ((card)->ext_csd.rel_sectors))) | 60 | ((card)->ext_csd.rel_sectors))) |
@@ -356,6 +363,16 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) | |||
356 | else | 363 | else |
357 | arg = MMC_ERASE_ARG; | 364 | arg = MMC_ERASE_ARG; |
358 | 365 | ||
366 | if (card->quirks & MMC_QUIRK_INAND_CMD38) { | ||
367 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
368 | INAND_CMD38_ARG_EXT_CSD, | ||
369 | arg == MMC_TRIM_ARG ? | ||
370 | INAND_CMD38_ARG_TRIM : | ||
371 | INAND_CMD38_ARG_ERASE, | ||
372 | 0); | ||
373 | if (err) | ||
374 | goto out; | ||
375 | } | ||
359 | err = mmc_erase(card, from, nr, arg); | 376 | err = mmc_erase(card, from, nr, arg); |
360 | out: | 377 | out: |
361 | spin_lock_irq(&md->lock); | 378 | spin_lock_irq(&md->lock); |
@@ -386,9 +403,28 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, | |||
386 | else | 403 | else |
387 | arg = MMC_SECURE_ERASE_ARG; | 404 | arg = MMC_SECURE_ERASE_ARG; |
388 | 405 | ||
406 | if (card->quirks & MMC_QUIRK_INAND_CMD38) { | ||
407 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
408 | INAND_CMD38_ARG_EXT_CSD, | ||
409 | arg == MMC_SECURE_TRIM1_ARG ? | ||
410 | INAND_CMD38_ARG_SECTRIM1 : | ||
411 | INAND_CMD38_ARG_SECERASE, | ||
412 | 0); | ||
413 | if (err) | ||
414 | goto out; | ||
415 | } | ||
389 | err = mmc_erase(card, from, nr, arg); | 416 | err = mmc_erase(card, from, nr, arg); |
390 | if (!err && arg == MMC_SECURE_TRIM1_ARG) | 417 | if (!err && arg == MMC_SECURE_TRIM1_ARG) { |
418 | if (card->quirks & MMC_QUIRK_INAND_CMD38) { | ||
419 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
420 | INAND_CMD38_ARG_EXT_CSD, | ||
421 | INAND_CMD38_ARG_SECTRIM2, | ||
422 | 0); | ||
423 | if (err) | ||
424 | goto out; | ||
425 | } | ||
391 | err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); | 426 | err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); |
427 | } | ||
392 | out: | 428 | out: |
393 | spin_lock_irq(&md->lock); | 429 | spin_lock_irq(&md->lock); |
394 | __blk_end_request(req, err, blk_rq_bytes(req)); | 430 | __blk_end_request(req, err, blk_rq_bytes(req)); |
@@ -941,6 +977,11 @@ static int mmc_add_disk(struct mmc_blk_data *md) | |||
941 | 977 | ||
942 | static const struct mmc_fixup blk_fixups[] = | 978 | static const struct mmc_fixup blk_fixups[] = |
943 | { | 979 | { |
980 | MMC_FIXUP("SEM02G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | ||
981 | MMC_FIXUP("SEM04G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | ||
982 | MMC_FIXUP("SEM08G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | ||
983 | MMC_FIXUP("SEM16G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | ||
984 | MMC_FIXUP("SEM32G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | ||
944 | END_FIXUP | 985 | END_FIXUP |
945 | }; | 986 | }; |
946 | 987 | ||