summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsinghome_lee <singhome_lee@asus.com>2012-09-20 13:54:43 +0800
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2015-02-03 16:46:22 +0100
commitba18f86d405f3188eb2656dbf629845aa5b4759f (patch)
tree6d43e07781936dd4fbe06910bf92af4f2a1060d0
parentdadec4519ba16fa9fd4d95270d009f08a1811577 (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
-rw-r--r--drivers/mmc/card/block.c60
-rw-r--r--drivers/mmc/card/queue.c2
-rwxr-xr-x[-rw-r--r--]drivers/mmc/core/core.c13
-rwxr-xr-x[-rw-r--r--]drivers/mmc/core/mmc.c3
-rw-r--r--include/linux/mmc/card.h3
-rw-r--r--include/linux/mmc/core.h2
6 files changed, 25 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;
}
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 85f17ff14e7e..ff194e553634 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -88,6 +88,9 @@ struct mmc_ext_csd {
__kernel_time_t last_tv_sec; /* last time a block was refreshed */
__kernel_time_t last_bkops_tv_sec; /* last time bkops was done */
unsigned int sec_count;
+
+ unsigned int feature_support;
+#define MMC_DISCARD_FEATURE BIT(0)
};
struct sd_scr {
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 0c4472eff796..921c4f6a2e0e 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -154,6 +154,7 @@ extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
#define MMC_ERASE_ARG 0x00000000
#define MMC_SECURE_ERASE_ARG 0x80000000
#define MMC_TRIM_ARG 0x00000001
+#define MMC_DISCARD_ARG 0x00000003
#define MMC_SECURE_TRIM1_ARG 0x80000001
#define MMC_SECURE_TRIM2_ARG 0x80008000
@@ -164,6 +165,7 @@ extern int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
unsigned int arg);
extern int mmc_can_erase(struct mmc_card *card);
extern int mmc_can_trim(struct mmc_card *card);
+extern int mmc_can_discard(struct mmc_card *card);
extern int mmc_can_secure_erase_trim(struct mmc_card *card);
extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
unsigned int nr);