aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/block.c42
-rw-r--r--drivers/mmc/card/queue.c14
-rw-r--r--drivers/mmc/card/queue.h18
3 files changed, 71 insertions, 3 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index a47f1ea..7406c4b 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1015,7 +1015,8 @@ static int mmc_blk_err_check(struct mmc_card *card,
if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
brq->data.error) {
#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \
- defined(CONFIG_MACH_C1_USA_ATT)
+ defined(CONFIG_MACH_C1_USA_ATT) \
+ || defined(CONFIG_MACH_GRANDE) || defined(CONFIG_MACH_IRON)
if (mmc_card_mmc(card)) {
pr_err("brq->sbc.opcode=%d,"
"brq->cmd.opcode=%d.\n",
@@ -1354,6 +1355,11 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
}
while (reqs < max_packed_rw - 1) {
+ /* We should stop no-more packing its nopacked_period */
+ if ((card->host->caps2 & MMC_CAP2_ADAPT_PACKED)
+ && mmc_is_nopacked_period(mq))
+ break;
+
spin_lock_irq(q->queue_lock);
next = blk_fetch_request(q);
spin_unlock_irq(q->queue_lock);
@@ -1939,7 +1945,8 @@ snd_packed_rd:
}
}
#if defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_P4NOTE) || \
- defined(CONFIG_MACH_C1_USA_ATT)
+ defined(CONFIG_MACH_C1_USA_ATT) \
+ || defined(CONFIG_MACH_GRANDE) || defined(CONFIG_MACH_IRON)
/*
* It's for Engineering DEBUGGING only
* This has to be removed before PVR(guessing)
@@ -2016,7 +2023,8 @@ 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)
+ if (req->cmd_flags & REQ_SECURE &&
+ !(card->quirks & MMC_QUIRK_MOVINAND_SECURE))
ret = mmc_blk_issue_secdiscard_rq(mq, req);
else
ret = mmc_blk_issue_discard_rq(mq, req);
@@ -2289,6 +2297,8 @@ static int mmc_add_disk(struct mmc_blk_data *md)
return ret;
}
+#define CID_MANFID_SAMSUNG 0x15
+
static const struct mmc_fixup blk_fixups[] =
{
MMC_FIXUP("SEM02G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
@@ -2311,6 +2321,28 @@ static const struct mmc_fixup blk_fixups[] =
MMC_QUIRK_BLK_NO_CMD23),
MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc,
MMC_QUIRK_BLK_NO_CMD23),
+
+ /*
+ * Some issue about secure erase/secure trim for Samsung MoviNAND
+ */
+
+ MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+ MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+ MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+ MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+ MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+ MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+ MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+ MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_MOVINAND_SECURE),
+
END_FIXUP
};
@@ -2458,7 +2490,11 @@ static void __exit mmc_blk_exit(void)
unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
}
+#ifdef CONFIG_FAST_RESUME
+beforeresume_initcall(mmc_blk_init);
+#else
module_init(mmc_blk_init);
+#endif
module_exit(mmc_blk_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index bf5d183..b384995 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -62,6 +62,9 @@ static int mmc_queue_thread(void *d)
spin_lock_irq(q->queue_lock);
set_current_state(TASK_INTERRUPTIBLE);
req = blk_fetch_request(q);
+ /* set nopacked_period if next request is RT class */
+ if (req && IS_RT_CLASS_REQ(req))
+ mmc_set_nopacked_period(mq, HZ);
mq->mqrq_cur->req = req;
spin_unlock_irq(q->queue_lock);
@@ -100,6 +103,7 @@ static void mmc_request(struct request_queue *q)
{
struct mmc_queue *mq = q->queuedata;
struct request *req;
+ struct io_context *ioc;
if (!mq) {
while ((req = blk_fetch_request(q)) != NULL) {
@@ -109,6 +113,14 @@ static void mmc_request(struct request_queue *q)
return;
}
+ ioc = get_io_context(GFP_NOWAIT, 0);
+ if (ioc) {
+ /* Set nopacked period if requesting process is RT class */
+ if (IOPRIO_PRIO_CLASS(ioc->ioprio) == IOPRIO_CLASS_RT)
+ mmc_set_nopacked_period(mq, HZ);
+ put_io_context(ioc);
+ }
+
if (!mq->mqrq_cur->req && !mq->mqrq_prev->req)
wake_up_process(mq->thread);
}
@@ -182,6 +194,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
mq->mqrq_cur = mqrq_cur;
mq->mqrq_prev = mqrq_prev;
mq->queue->queuedata = mq;
+ mq->nopacked_period = 0;
+
blk_queue_prep_rq(mq->queue, mmc_prep_request);
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index be58b3c..f1ba6df 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -46,6 +46,8 @@ struct mmc_queue {
struct mmc_queue_req mqrq[2];
struct mmc_queue_req *mqrq_cur;
struct mmc_queue_req *mqrq_prev;
+ /* Jiffies until which disable packed command. */
+ unsigned long nopacked_period;
};
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
@@ -59,4 +61,20 @@ extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
extern void mmc_queue_bounce_post(struct mmc_queue_req *);
+#define IS_RT_CLASS_REQ(x) \
+ (IOPRIO_PRIO_CLASS(req_get_ioprio(x)) == IOPRIO_CLASS_RT)
+
+static inline void mmc_set_nopacked_period(struct mmc_queue *mq,
+ unsigned long nopacked_jiffies)
+{
+ mq->nopacked_period = jiffies + nopacked_jiffies;
+ smp_wmb();
+}
+
+static inline int mmc_is_nopacked_period(struct mmc_queue *mq)
+{
+ smp_rmb();
+ return (int)time_is_after_jiffies(mq->nopacked_period);
+}
+
#endif