diff options
-rw-r--r-- | drivers/mmc/card/block.c | 108 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 1 | ||||
-rw-r--r-- | include/linux/mmc/core.h | 1 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 6 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 6 |
5 files changed, 93 insertions, 29 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 126c7f41c5a3..a380accaba9a 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -59,10 +59,6 @@ MODULE_ALIAS("mmc:block"); | |||
59 | #define INAND_CMD38_ARG_SECTRIM1 0x81 | 59 | #define INAND_CMD38_ARG_SECTRIM1 0x81 |
60 | #define INAND_CMD38_ARG_SECTRIM2 0x88 | 60 | #define INAND_CMD38_ARG_SECTRIM2 0x88 |
61 | 61 | ||
62 | #define REL_WRITES_SUPPORTED(card) (mmc_card_mmc((card)) && \ | ||
63 | (((card)->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || \ | ||
64 | ((card)->ext_csd.rel_sectors))) | ||
65 | |||
66 | static DEFINE_MUTEX(block_mutex); | 62 | static DEFINE_MUTEX(block_mutex); |
67 | 63 | ||
68 | /* | 64 | /* |
@@ -90,6 +86,10 @@ struct mmc_blk_data { | |||
90 | struct mmc_queue queue; | 86 | struct mmc_queue queue; |
91 | struct list_head part; | 87 | struct list_head part; |
92 | 88 | ||
89 | unsigned int flags; | ||
90 | #define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */ | ||
91 | #define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */ | ||
92 | |||
93 | unsigned int usage; | 93 | unsigned int usage; |
94 | unsigned int read_only; | 94 | unsigned int read_only; |
95 | unsigned int part_type; | 95 | unsigned int part_type; |
@@ -429,6 +429,7 @@ static const struct block_device_operations mmc_bdops = { | |||
429 | 429 | ||
430 | struct mmc_blk_request { | 430 | struct mmc_blk_request { |
431 | struct mmc_request mrq; | 431 | struct mmc_request mrq; |
432 | struct mmc_command sbc; | ||
432 | struct mmc_command cmd; | 433 | struct mmc_command cmd; |
433 | struct mmc_command stop; | 434 | struct mmc_command stop; |
434 | struct mmc_data data; | 435 | struct mmc_data data; |
@@ -652,13 +653,10 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) | |||
652 | * reliable write can handle, thus finish the request in | 653 | * reliable write can handle, thus finish the request in |
653 | * partial completions. | 654 | * partial completions. |
654 | */ | 655 | */ |
655 | static inline int mmc_apply_rel_rw(struct mmc_blk_request *brq, | 656 | static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq, |
656 | struct mmc_card *card, | 657 | struct mmc_card *card, |
657 | struct request *req) | 658 | struct request *req) |
658 | { | 659 | { |
659 | int err; | ||
660 | struct mmc_command set_count = {0}; | ||
661 | |||
662 | if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) { | 660 | if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) { |
663 | /* Legacy mode imposes restrictions on transfers. */ | 661 | /* Legacy mode imposes restrictions on transfers. */ |
664 | if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors)) | 662 | if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors)) |
@@ -669,15 +667,6 @@ static inline int mmc_apply_rel_rw(struct mmc_blk_request *brq, | |||
669 | else if (brq->data.blocks < card->ext_csd.rel_sectors) | 667 | else if (brq->data.blocks < card->ext_csd.rel_sectors) |
670 | brq->data.blocks = 1; | 668 | brq->data.blocks = 1; |
671 | } | 669 | } |
672 | |||
673 | set_count.opcode = MMC_SET_BLOCK_COUNT; | ||
674 | set_count.arg = brq->data.blocks | (1 << 31); | ||
675 | set_count.flags = MMC_RSP_R1 | MMC_CMD_AC; | ||
676 | err = mmc_wait_for_cmd(card->host, &set_count, 0); | ||
677 | if (err) | ||
678 | printk(KERN_ERR "%s: error %d SET_BLOCK_COUNT\n", | ||
679 | req->rq_disk->disk_name, err); | ||
680 | return err; | ||
681 | } | 670 | } |
682 | 671 | ||
683 | static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | 672 | static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) |
@@ -694,7 +683,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | |||
694 | bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || | 683 | bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || |
695 | (req->cmd_flags & REQ_META)) && | 684 | (req->cmd_flags & REQ_META)) && |
696 | (rq_data_dir(req) == WRITE) && | 685 | (rq_data_dir(req) == WRITE) && |
697 | REL_WRITES_SUPPORTED(card); | 686 | (md->flags & MMC_BLK_REL_WR); |
698 | 687 | ||
699 | do { | 688 | do { |
700 | struct mmc_command cmd = {0}; | 689 | struct mmc_command cmd = {0}; |
@@ -732,11 +721,9 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | |||
732 | 721 | ||
733 | if (brq.data.blocks > 1 || do_rel_wr) { | 722 | if (brq.data.blocks > 1 || do_rel_wr) { |
734 | /* SPI multiblock writes terminate using a special | 723 | /* SPI multiblock writes terminate using a special |
735 | * token, not a STOP_TRANSMISSION request. Reliable | 724 | * token, not a STOP_TRANSMISSION request. |
736 | * writes use SET_BLOCK_COUNT and do not use a | ||
737 | * STOP_TRANSMISSION request either. | ||
738 | */ | 725 | */ |
739 | if ((!mmc_host_is_spi(card->host) && !do_rel_wr) || | 726 | if (!mmc_host_is_spi(card->host) || |
740 | rq_data_dir(req) == READ) | 727 | rq_data_dir(req) == READ) |
741 | brq.mrq.stop = &brq.stop; | 728 | brq.mrq.stop = &brq.stop; |
742 | readcmd = MMC_READ_MULTIPLE_BLOCK; | 729 | readcmd = MMC_READ_MULTIPLE_BLOCK; |
@@ -754,8 +741,37 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | |||
754 | brq.data.flags |= MMC_DATA_WRITE; | 741 | brq.data.flags |= MMC_DATA_WRITE; |
755 | } | 742 | } |
756 | 743 | ||
757 | if (do_rel_wr && mmc_apply_rel_rw(&brq, card, req)) | 744 | if (do_rel_wr) |
758 | goto cmd_err; | 745 | mmc_apply_rel_rw(&brq, card, req); |
746 | |||
747 | /* | ||
748 | * Pre-defined multi-block transfers are preferable to | ||
749 | * open ended-ones (and necessary for reliable writes). | ||
750 | * However, it is not sufficient to just send CMD23, | ||
751 | * and avoid the final CMD12, as on an error condition | ||
752 | * CMD12 (stop) needs to be sent anyway. This, coupled | ||
753 | * with Auto-CMD23 enhancements provided by some | ||
754 | * hosts, means that the complexity of dealing | ||
755 | * with this is best left to the host. If CMD23 is | ||
756 | * supported by card and host, we'll fill sbc in and let | ||
757 | * the host deal with handling it correctly. This means | ||
758 | * that for hosts that don't expose MMC_CAP_CMD23, no | ||
759 | * change of behavior will be observed. | ||
760 | * | ||
761 | * N.B: Some MMC cards experience perf degradation. | ||
762 | * We'll avoid using CMD23-bounded multiblock writes for | ||
763 | * these, while retaining features like reliable writes. | ||
764 | */ | ||
765 | |||
766 | if ((md->flags & MMC_BLK_CMD23) && | ||
767 | mmc_op_multi(brq.cmd.opcode) && | ||
768 | (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) { | ||
769 | brq.sbc.opcode = MMC_SET_BLOCK_COUNT; | ||
770 | brq.sbc.arg = brq.data.blocks | | ||
771 | (do_rel_wr ? (1 << 31) : 0); | ||
772 | brq.sbc.flags = MMC_RSP_R1 | MMC_CMD_AC; | ||
773 | brq.mrq.sbc = &brq.sbc; | ||
774 | } | ||
759 | 775 | ||
760 | mmc_set_data_timeout(&brq.data, card); | 776 | mmc_set_data_timeout(&brq.data, card); |
761 | 777 | ||
@@ -792,7 +808,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | |||
792 | * until later as we need to wait for the card to leave | 808 | * until later as we need to wait for the card to leave |
793 | * programming mode even when things go wrong. | 809 | * programming mode even when things go wrong. |
794 | */ | 810 | */ |
795 | if (brq.cmd.error || brq.data.error || brq.stop.error) { | 811 | if (brq.sbc.error || brq.cmd.error || |
812 | brq.data.error || brq.stop.error) { | ||
796 | if (brq.data.blocks > 1 && rq_data_dir(req) == READ) { | 813 | if (brq.data.blocks > 1 && rq_data_dir(req) == READ) { |
797 | /* Redo read one sector at a time */ | 814 | /* Redo read one sector at a time */ |
798 | printk(KERN_WARNING "%s: retrying using single " | 815 | printk(KERN_WARNING "%s: retrying using single " |
@@ -803,6 +820,13 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) | |||
803 | status = get_card_status(card, req); | 820 | status = get_card_status(card, req); |
804 | } | 821 | } |
805 | 822 | ||
823 | if (brq.sbc.error) { | ||
824 | printk(KERN_ERR "%s: error %d sending SET_BLOCK_COUNT " | ||
825 | "command, response %#x, card status %#x\n", | ||
826 | req->rq_disk->disk_name, brq.sbc.error, | ||
827 | brq.sbc.resp[0], status); | ||
828 | } | ||
829 | |||
806 | if (brq.cmd.error) { | 830 | if (brq.cmd.error) { |
807 | printk(KERN_ERR "%s: error %d sending read/write " | 831 | printk(KERN_ERR "%s: error %d sending read/write " |
808 | "command, response %#x, card status %#x\n", | 832 | "command, response %#x, card status %#x\n", |
@@ -1014,8 +1038,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, | |||
1014 | md->disk->queue = md->queue.queue; | 1038 | md->disk->queue = md->queue.queue; |
1015 | md->disk->driverfs_dev = parent; | 1039 | md->disk->driverfs_dev = parent; |
1016 | set_disk_ro(md->disk, md->read_only || default_ro); | 1040 | set_disk_ro(md->disk, md->read_only || default_ro); |
1017 | if (REL_WRITES_SUPPORTED(card)) | ||
1018 | blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA); | ||
1019 | 1041 | ||
1020 | /* | 1042 | /* |
1021 | * As discussed on lkml, GENHD_FL_REMOVABLE should: | 1043 | * As discussed on lkml, GENHD_FL_REMOVABLE should: |
@@ -1034,6 +1056,19 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, | |||
1034 | 1056 | ||
1035 | blk_queue_logical_block_size(md->queue.queue, 512); | 1057 | blk_queue_logical_block_size(md->queue.queue, 512); |
1036 | set_capacity(md->disk, size); | 1058 | set_capacity(md->disk, size); |
1059 | |||
1060 | if (mmc_host_cmd23(card->host) && | ||
1061 | mmc_card_mmc(card)) | ||
1062 | md->flags |= MMC_BLK_CMD23; | ||
1063 | |||
1064 | if (mmc_card_mmc(card) && | ||
1065 | md->flags & MMC_BLK_CMD23 && | ||
1066 | ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || | ||
1067 | card->ext_csd.rel_sectors)) { | ||
1068 | md->flags |= MMC_BLK_REL_WR; | ||
1069 | blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA); | ||
1070 | } | ||
1071 | |||
1037 | return md; | 1072 | return md; |
1038 | 1073 | ||
1039 | err_putdisk: | 1074 | err_putdisk: |
@@ -1189,6 +1224,21 @@ static const struct mmc_fixup blk_fixups[] = | |||
1189 | MMC_FIXUP("SEM08G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | 1224 | MMC_FIXUP("SEM08G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), |
1190 | MMC_FIXUP("SEM16G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | 1225 | MMC_FIXUP("SEM16G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), |
1191 | MMC_FIXUP("SEM32G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), | 1226 | MMC_FIXUP("SEM32G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38), |
1227 | |||
1228 | /* | ||
1229 | * Some MMC cards experience performance degradation with CMD23 | ||
1230 | * instead of CMD12-bounded multiblock transfers. For now we'll | ||
1231 | * black list what's bad... | ||
1232 | * - Certain Toshiba cards. | ||
1233 | * | ||
1234 | * N.B. This doesn't affect SD cards. | ||
1235 | */ | ||
1236 | MMC_FIXUP("MMC08G", 0x11, CID_OEMID_ANY, add_quirk_mmc, | ||
1237 | MMC_QUIRK_BLK_NO_CMD23), | ||
1238 | MMC_FIXUP("MMC16G", 0x11, CID_OEMID_ANY, add_quirk_mmc, | ||
1239 | MMC_QUIRK_BLK_NO_CMD23), | ||
1240 | MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, | ||
1241 | MMC_QUIRK_BLK_NO_CMD23), | ||
1192 | END_FIXUP | 1242 | END_FIXUP |
1193 | }; | 1243 | }; |
1194 | 1244 | ||
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 7190aa2096f7..4a0e27baaea0 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -171,6 +171,7 @@ struct mmc_card { | |||
171 | #define MMC_QUIRK_NONSTD_FUNC_IF (1<<4) /* SDIO card has nonstd function interfaces */ | 171 | #define MMC_QUIRK_NONSTD_FUNC_IF (1<<4) /* SDIO card has nonstd function interfaces */ |
172 | #define MMC_QUIRK_DISABLE_CD (1<<5) /* disconnect CD/DAT[3] resistor */ | 172 | #define MMC_QUIRK_DISABLE_CD (1<<5) /* disconnect CD/DAT[3] resistor */ |
173 | #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ | 173 | #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ |
174 | #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ | ||
174 | 175 | ||
175 | unsigned int erase_size; /* erase size in sectors */ | 176 | unsigned int erase_size; /* erase size in sectors */ |
176 | unsigned int erase_shift; /* if erase unit is power 2 */ | 177 | unsigned int erase_shift; /* if erase unit is power 2 */ |
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index cbe8d55f64c4..b6718e549a51 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h | |||
@@ -120,6 +120,7 @@ struct mmc_data { | |||
120 | }; | 120 | }; |
121 | 121 | ||
122 | struct mmc_request { | 122 | struct mmc_request { |
123 | struct mmc_command *sbc; /* SET_BLOCK_COUNT for multiblock */ | ||
123 | struct mmc_command *cmd; | 124 | struct mmc_command *cmd; |
124 | struct mmc_data *data; | 125 | struct mmc_data *data; |
125 | struct mmc_command *stop; | 126 | struct mmc_command *stop; |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index de32e6aa018a..e946bd10fe3f 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -210,6 +210,7 @@ struct mmc_host { | |||
210 | #define MMC_CAP_MAX_CURRENT_400 (1 << 27) /* Host max current limit is 400mA */ | 210 | #define MMC_CAP_MAX_CURRENT_400 (1 << 27) /* Host max current limit is 400mA */ |
211 | #define MMC_CAP_MAX_CURRENT_600 (1 << 28) /* Host max current limit is 600mA */ | 211 | #define MMC_CAP_MAX_CURRENT_600 (1 << 28) /* Host max current limit is 600mA */ |
212 | #define MMC_CAP_MAX_CURRENT_800 (1 << 29) /* Host max current limit is 800mA */ | 212 | #define MMC_CAP_MAX_CURRENT_800 (1 << 29) /* Host max current limit is 800mA */ |
213 | #define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */ | ||
213 | 214 | ||
214 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 215 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
215 | 216 | ||
@@ -366,5 +367,10 @@ static inline int mmc_card_wake_sdio_irq(struct mmc_host *host) | |||
366 | { | 367 | { |
367 | return host->pm_flags & MMC_PM_WAKE_SDIO_IRQ; | 368 | return host->pm_flags & MMC_PM_WAKE_SDIO_IRQ; |
368 | } | 369 | } |
370 | |||
371 | static inline int mmc_host_cmd23(struct mmc_host *host) | ||
372 | { | ||
373 | return host->caps & MMC_CAP_CMD23; | ||
374 | } | ||
369 | #endif | 375 | #endif |
370 | 376 | ||
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 9fa5a73f393d..ac26a685cca8 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -83,6 +83,12 @@ | |||
83 | #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ | 83 | #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ |
84 | #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ | 84 | #define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ |
85 | 85 | ||
86 | static inline bool mmc_op_multi(u32 opcode) | ||
87 | { | ||
88 | return opcode == MMC_WRITE_MULTIPLE_BLOCK || | ||
89 | opcode == MMC_READ_MULTIPLE_BLOCK; | ||
90 | } | ||
91 | |||
86 | /* | 92 | /* |
87 | * MMC_SWITCH argument format: | 93 | * MMC_SWITCH argument format: |
88 | * | 94 | * |