diff options
author | singhome_lee <singhome_lee@asus.com> | 2012-09-20 13:54:43 +0800 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2015-02-03 16:46:22 +0100 |
commit | ba18f86d405f3188eb2656dbf629845aa5b4759f (patch) | |
tree | 6d43e07781936dd4fbe06910bf92af4f2a1060d0 /drivers | |
parent | dadec4519ba16fa9fd4d95270d009f08a1811577 (diff) |
mmc: core: new discard feature support at Samsung eMMC v4.41+.
Support discard feature if MID field in the CID register is 0x15, EXT.CSD[192]
(device version) is 5 and Bit 0 in the EXT.CSD[64] is 1. Also removed REQ_SECURE flag
check to avoid kernel hang.
This patch is released from samsung.
Change-Id: I4023a900680e9bca10c40311b09ed077a22617db
(cherry picked from commit 4acc227edfb631d377e14911287c1b73682fc9c2)
Conflicts:
drivers/mmc/card/block.c
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/card/block.c | 60 | ||||
-rw-r--r-- | drivers/mmc/card/queue.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | drivers/mmc/core/core.c | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | drivers/mmc/core/mmc.c | 3 |
4 files changed, 20 insertions, 58 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index ee16f1102e04..586b4ca4725e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -703,7 +703,9 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) from = blk_rq_pos(req); nr = blk_rq_sectors(req); - if (mmc_can_trim(card)) + if (mmc_can_discard(card)) + arg = MMC_DISCARD_ARG; + else if (mmc_can_trim(card)) arg = MMC_TRIM_ARG; else arg = MMC_ERASE_ARG; @@ -727,57 +729,6 @@ out: return err ? 0 : 1; } -static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq, - struct request *req) -{ - struct mmc_blk_data *md = mq->data; - struct mmc_card *card = md->queue.card; - unsigned int from, nr, arg; - int err = 0; - - if (!mmc_can_secure_erase_trim(card)) { - err = -EOPNOTSUPP; - goto out; - } - - 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 (card->quirks & MMC_QUIRK_INAND_CMD38) { - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - INAND_CMD38_ARG_EXT_CSD, - arg == MMC_SECURE_TRIM1_ARG ? - INAND_CMD38_ARG_SECTRIM1 : - INAND_CMD38_ARG_SECERASE, - 0); - if (err) - goto out; - } - err = mmc_erase(card, from, nr, arg); - if (!err && 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; - } - err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG); - } -out: - spin_lock_irq(&md->lock); - __blk_end_request(req, err, blk_rq_bytes(req)); - spin_unlock_irq(&md->lock); - - return err ? 0 : 1; -} - static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) { struct mmc_blk_data *md = mq->data; @@ -1222,10 +1173,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); - if (req->cmd_flags & REQ_SECURE) - ret = mmc_blk_issue_secdiscard_rq(mq, req); - else - ret = mmc_blk_issue_discard_rq(mq, req); + ret = mmc_blk_issue_discard_rq(mq, req); } else if (req && req->cmd_flags & REQ_FLUSH) { /* complete ongoing async transfer before issuing flush */ if (card->host->areq) diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 01c0357656a7..ba38a2fe12f5 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -142,7 +142,7 @@ static void mmc_queue_setup_discard(struct request_queue *q, 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 */ diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index bc200be1b3c0..58a38153db63 100644..100755 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1579,7 +1579,10 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, { 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; @@ -1855,6 +1858,14 @@ int mmc_can_trim(struct mmc_card *card) } EXPORT_SYMBOL(mmc_can_trim); +int mmc_can_discard(struct mmc_card *card) +{ + if (card->ext_csd.feature_support & MMC_DISCARD_FEATURE) + return 1; + return 0; +} +EXPORT_SYMBOL( mmc_can_discard); + int mmc_can_secure_erase_trim(struct mmc_card *card) { if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index a5e09b8ee068..9af23fe2ae8f 100644..100755 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -443,6 +443,9 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) else card->erased_byte = 0x0; + if ((card->cid.manfid == 0x15) && (ext_csd[64] & 0x01)) + card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; + out: return err; } |