Commit d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023

Authored by Andrei Warkentin
Committed by Chris Ball
1 parent c59de92879

mmc: core: Use CMD23 for multiblock transfers when we can.

CMD23-prefixed instead of open-ended multiblock transfers
have a performance advantage on some MMC cards.

Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
Signed-off-by: Chris Ball <cjb@laptop.org>

Showing 5 changed files with 93 additions and 29 deletions Side-by-side Diff

drivers/mmc/card/block.c
... ... @@ -59,10 +59,6 @@
59 59 #define INAND_CMD38_ARG_SECTRIM1 0x81
60 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 62 static DEFINE_MUTEX(block_mutex);
67 63  
68 64 /*
... ... @@ -90,6 +86,10 @@
90 86 struct mmc_queue queue;
91 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 93 unsigned int usage;
94 94 unsigned int read_only;
95 95 unsigned int part_type;
... ... @@ -429,6 +429,7 @@
429 429  
430 430 struct mmc_blk_request {
431 431 struct mmc_request mrq;
  432 + struct mmc_command sbc;
432 433 struct mmc_command cmd;
433 434 struct mmc_command stop;
434 435 struct mmc_data data;
435 436  
... ... @@ -652,13 +653,10 @@
652 653 * reliable write can handle, thus finish the request in
653 654 * partial completions.
654 655 */
655   -static inline int mmc_apply_rel_rw(struct mmc_blk_request *brq,
656   - struct mmc_card *card,
657   - struct request *req)
  656 +static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
  657 + struct mmc_card *card,
  658 + struct request *req)
658 659 {
659   - int err;
660   - struct mmc_command set_count = {0};
661   -
662 660 if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
663 661 /* Legacy mode imposes restrictions on transfers. */
664 662 if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors))
... ... @@ -669,15 +667,6 @@
669 667 else if (brq->data.blocks < card->ext_csd.rel_sectors)
670 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 672 static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
... ... @@ -694,7 +683,7 @@
694 683 bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
695 684 (req->cmd_flags & REQ_META)) &&
696 685 (rq_data_dir(req) == WRITE) &&
697   - REL_WRITES_SUPPORTED(card);
  686 + (md->flags & MMC_BLK_REL_WR);
698 687  
699 688 do {
700 689 struct mmc_command cmd = {0};
701 690  
... ... @@ -732,11 +721,9 @@
732 721  
733 722 if (brq.data.blocks > 1 || do_rel_wr) {
734 723 /* SPI multiblock writes terminate using a special
735   - * token, not a STOP_TRANSMISSION request. Reliable
736   - * writes use SET_BLOCK_COUNT and do not use a
737   - * STOP_TRANSMISSION request either.
  724 + * token, not a STOP_TRANSMISSION request.
738 725 */
739   - if ((!mmc_host_is_spi(card->host) && !do_rel_wr) ||
  726 + if (!mmc_host_is_spi(card->host) ||
740 727 rq_data_dir(req) == READ)
741 728 brq.mrq.stop = &brq.stop;
742 729 readcmd = MMC_READ_MULTIPLE_BLOCK;
743 730  
... ... @@ -754,9 +741,38 @@
754 741 brq.data.flags |= MMC_DATA_WRITE;
755 742 }
756 743  
757   - if (do_rel_wr && mmc_apply_rel_rw(&brq, card, req))
758   - goto cmd_err;
  744 + if (do_rel_wr)
  745 + mmc_apply_rel_rw(&brq, card, req);
759 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 + }
  775 +
760 776 mmc_set_data_timeout(&brq.data, card);
761 777  
762 778 brq.data.sg = mq->sg;
... ... @@ -792,7 +808,8 @@
792 808 * until later as we need to wait for the card to leave
793 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 813 if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
797 814 /* Redo read one sector at a time */
798 815 printk(KERN_WARNING "%s: retrying using single "
... ... @@ -803,6 +820,13 @@
803 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 830 if (brq.cmd.error) {
807 831 printk(KERN_ERR "%s: error %d sending read/write "
808 832 "command, response %#x, card status %#x\n",
... ... @@ -1014,8 +1038,6 @@
1014 1038 md->disk->queue = md->queue.queue;
1015 1039 md->disk->driverfs_dev = parent;
1016 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 1043 * As discussed on lkml, GENHD_FL_REMOVABLE should:
... ... @@ -1034,6 +1056,19 @@
1034 1056  
1035 1057 blk_queue_logical_block_size(md->queue.queue, 512);
1036 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 1072 return md;
1038 1073  
1039 1074 err_putdisk:
... ... @@ -1189,6 +1224,21 @@
1189 1224 MMC_FIXUP("SEM08G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
1190 1225 MMC_FIXUP("SEM16G", 0x2, 0x100, add_quirk, MMC_QUIRK_INAND_CMD38),
1191 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 1242 END_FIXUP
1193 1243 };
1194 1244  
include/linux/mmc/card.h
... ... @@ -171,6 +171,7 @@
171 171 #define MMC_QUIRK_NONSTD_FUNC_IF (1<<4) /* SDIO card has nonstd function interfaces */
172 172 #define MMC_QUIRK_DISABLE_CD (1<<5) /* disconnect CD/DAT[3] resistor */
173 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 176 unsigned int erase_size; /* erase size in sectors */
176 177 unsigned int erase_shift; /* if erase unit is power 2 */
include/linux/mmc/core.h
... ... @@ -120,6 +120,7 @@
120 120 };
121 121  
122 122 struct mmc_request {
  123 + struct mmc_command *sbc; /* SET_BLOCK_COUNT for multiblock */
123 124 struct mmc_command *cmd;
124 125 struct mmc_data *data;
125 126 struct mmc_command *stop;
include/linux/mmc/host.h
... ... @@ -210,6 +210,7 @@
210 210 #define MMC_CAP_MAX_CURRENT_400 (1 << 27) /* Host max current limit is 400mA */
211 211 #define MMC_CAP_MAX_CURRENT_600 (1 << 28) /* Host max current limit is 600mA */
212 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 215 mmc_pm_flag_t pm_caps; /* supported pm features */
215 216  
... ... @@ -365,6 +366,11 @@
365 366 static inline int mmc_card_wake_sdio_irq(struct mmc_host *host)
366 367 {
367 368 return host->pm_flags & MMC_PM_WAKE_SDIO_IRQ;
  369 +}
  370 +
  371 +static inline int mmc_host_cmd23(struct mmc_host *host)
  372 +{
  373 + return host->caps & MMC_CAP_CMD23;
368 374 }
369 375 #endif
include/linux/mmc/mmc.h
... ... @@ -83,6 +83,12 @@
83 83 #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
84 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 93 * MMC_SWITCH argument format:
88 94 *