diff options
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r-- | drivers/mmc/card/block.c | 42 | ||||
-rw-r--r-- | drivers/mmc/card/queue.c | 14 | ||||
-rw-r--r-- | drivers/mmc/card/queue.h | 18 |
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 |