Loading drivers/mmc/card/block.c +36 −14 Original line number Diff line number Diff line Loading @@ -2823,6 +2823,15 @@ static int mmc_blk_cmdq_issue_rw_rq(struct mmc_queue *mq, struct request *req) mc_rq = mmc_blk_cmdq_rw_prep(active_mqrq, mq); ret = mmc_blk_cmdq_start_req(card->host, mc_rq); if (!ret && (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD)) { unsigned int sectors = blk_rq_sectors(req); if (((sectors > 0) && (sectors < 8)) && (rq_data_dir(req) == READ)) host->cmdq_ctx.active_small_sector_read_reqs++; } return ret; } Loading Loading @@ -3396,26 +3405,39 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req) } if (req) { if (cmd_flags & REQ_DISCARD) { if (cmd_flags & REQ_SECURE && !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) ret = mmc_blk_cmdq_issue_secdiscard_rq(mq, req); else ret = mmc_blk_cmdq_issue_discard_rq(mq, req); } else if (cmd_flags & REQ_FLUSH) { if (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_FLUSH) { ret = wait_event_interruptible( card->host->cmdq_ctx.queue_empty_wq, (!card->host->cmdq_ctx.active_reqs)); struct mmc_host *host = card->host; struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx; if ((cmd_flags & (REQ_FLUSH | REQ_DISCARD)) && (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD) && ctx->active_small_sector_read_reqs) { ret = wait_event_interruptible(ctx->queue_empty_wq, !ctx->active_reqs); if (ret) { pr_err("%s: failed while waiting for the CMDQ to be empty %s err (%d)\n", mmc_hostname(card->host), mmc_hostname(host), __func__, ret); BUG_ON(1); } /* clear the counter now */ ctx->active_small_sector_read_reqs = 0; /* * If there were small sector (less than 8 sectors) read * operations in progress then we have to wait for the * outstanding requests to finish and should also have * atleast 6 microseconds delay before queuing the DCMD * request. */ udelay(MMC_QUIRK_CMDQ_DELAY_BEFORE_DCMD); } if (cmd_flags & REQ_DISCARD) { if (cmd_flags & REQ_SECURE && !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) ret = mmc_blk_cmdq_issue_secdiscard_rq(mq, req); else ret = mmc_blk_cmdq_issue_discard_rq(mq, req); } else if (cmd_flags & REQ_FLUSH) { ret = mmc_blk_cmdq_issue_flush_rq(mq, req); } else { ret = mmc_blk_cmdq_issue_rw_rq(mq, req); Loading Loading @@ -3874,7 +3896,7 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), MMC_FIXUP(CID_NAME_ANY, CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_CMDQ_EMPTY_BEFORE_FLUSH), add_quirk_mmc, MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD), /* * Some Micron MMC cards needs longer data read timeout than Loading include/linux/mmc/card.h +4 −2 Original line number Diff line number Diff line Loading @@ -332,6 +332,8 @@ enum mmc_pon_type { MMC_SHRT_PON, }; #define MMC_QUIRK_CMDQ_DELAY_BEFORE_DCMD 6 /* microseconds */ /* * MMC device */ Loading Loading @@ -383,8 +385,8 @@ struct mmc_card { #define MMC_QUIRK_QCA6574_SETTINGS (1 << 15) /* QCA6574 card settings*/ #define MMC_QUIRK_QCA9377_SETTINGS (1 << 16) /* QCA9377 card settings*/ /* Make sure CMDQ is empty before queuing cache flush */ #define MMC_QUIRK_CMDQ_EMPTY_BEFORE_FLUSH (1 << 17) /* Make sure CMDQ is empty before queuing DCMD */ #define MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD (1 << 17) unsigned int erase_size; /* erase size in sectors */ unsigned int erase_shift; /* if erase unit is power 2 */ Loading include/linux/mmc/host.h +1 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,7 @@ struct mmc_cmdq_context_info { #define CMDQ_STATE_HALT 2 wait_queue_head_t queue_empty_wq; wait_queue_head_t wait; int active_small_sector_read_reqs; }; /** Loading Loading
drivers/mmc/card/block.c +36 −14 Original line number Diff line number Diff line Loading @@ -2823,6 +2823,15 @@ static int mmc_blk_cmdq_issue_rw_rq(struct mmc_queue *mq, struct request *req) mc_rq = mmc_blk_cmdq_rw_prep(active_mqrq, mq); ret = mmc_blk_cmdq_start_req(card->host, mc_rq); if (!ret && (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD)) { unsigned int sectors = blk_rq_sectors(req); if (((sectors > 0) && (sectors < 8)) && (rq_data_dir(req) == READ)) host->cmdq_ctx.active_small_sector_read_reqs++; } return ret; } Loading Loading @@ -3396,26 +3405,39 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req) } if (req) { if (cmd_flags & REQ_DISCARD) { if (cmd_flags & REQ_SECURE && !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) ret = mmc_blk_cmdq_issue_secdiscard_rq(mq, req); else ret = mmc_blk_cmdq_issue_discard_rq(mq, req); } else if (cmd_flags & REQ_FLUSH) { if (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_FLUSH) { ret = wait_event_interruptible( card->host->cmdq_ctx.queue_empty_wq, (!card->host->cmdq_ctx.active_reqs)); struct mmc_host *host = card->host; struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx; if ((cmd_flags & (REQ_FLUSH | REQ_DISCARD)) && (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD) && ctx->active_small_sector_read_reqs) { ret = wait_event_interruptible(ctx->queue_empty_wq, !ctx->active_reqs); if (ret) { pr_err("%s: failed while waiting for the CMDQ to be empty %s err (%d)\n", mmc_hostname(card->host), mmc_hostname(host), __func__, ret); BUG_ON(1); } /* clear the counter now */ ctx->active_small_sector_read_reqs = 0; /* * If there were small sector (less than 8 sectors) read * operations in progress then we have to wait for the * outstanding requests to finish and should also have * atleast 6 microseconds delay before queuing the DCMD * request. */ udelay(MMC_QUIRK_CMDQ_DELAY_BEFORE_DCMD); } if (cmd_flags & REQ_DISCARD) { if (cmd_flags & REQ_SECURE && !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) ret = mmc_blk_cmdq_issue_secdiscard_rq(mq, req); else ret = mmc_blk_cmdq_issue_discard_rq(mq, req); } else if (cmd_flags & REQ_FLUSH) { ret = mmc_blk_cmdq_issue_flush_rq(mq, req); } else { ret = mmc_blk_cmdq_issue_rw_rq(mq, req); Loading Loading @@ -3874,7 +3896,7 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), MMC_FIXUP(CID_NAME_ANY, CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_CMDQ_EMPTY_BEFORE_FLUSH), add_quirk_mmc, MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD), /* * Some Micron MMC cards needs longer data read timeout than Loading
include/linux/mmc/card.h +4 −2 Original line number Diff line number Diff line Loading @@ -332,6 +332,8 @@ enum mmc_pon_type { MMC_SHRT_PON, }; #define MMC_QUIRK_CMDQ_DELAY_BEFORE_DCMD 6 /* microseconds */ /* * MMC device */ Loading Loading @@ -383,8 +385,8 @@ struct mmc_card { #define MMC_QUIRK_QCA6574_SETTINGS (1 << 15) /* QCA6574 card settings*/ #define MMC_QUIRK_QCA9377_SETTINGS (1 << 16) /* QCA9377 card settings*/ /* Make sure CMDQ is empty before queuing cache flush */ #define MMC_QUIRK_CMDQ_EMPTY_BEFORE_FLUSH (1 << 17) /* Make sure CMDQ is empty before queuing DCMD */ #define MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD (1 << 17) unsigned int erase_size; /* erase size in sectors */ unsigned int erase_shift; /* if erase unit is power 2 */ Loading
include/linux/mmc/host.h +1 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,7 @@ struct mmc_cmdq_context_info { #define CMDQ_STATE_HALT 2 wait_queue_head_t queue_empty_wq; wait_queue_head_t wait; int active_small_sector_read_reqs; }; /** Loading