diff options
author | Paul Walmsley <paul@pwsan.com> | 2011-10-06 16:50:33 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-10-27 09:10:57 -0400 |
commit | 2bf22b39823c1d173dda31111a4eb2ce36daaf39 (patch) | |
tree | 54575fedfd2b032c3113b55dea5e2fd5d0c7eb38 | |
parent | b6ad726e3fe69e1ff3c3b2ad272ba3e4c376cd6a (diff) |
mmc: core: add workaround for controllers with broken multiblock reads
Due to hardware bugs, some MMC host controllers don't support
multiple-block reads[1]. To resolve, add a new MMC capability flag,
MMC_CAP2_NO_MULTI_READ, which can be set by affected host controller
drivers. When this capability is set, all reads will be issued one
sector at a time.
1. See for example Advisory 2.1.1.128 "MMC: Multiple Block Read
Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
Revision F (October 2010) (SPRZ278F), available from
http://focus.ti.com/lit/er/sprz278f/sprz278f.pdf
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dave Hylands <dhylands@gmail.com>
Tested-by: Steve Sakoman <sakoman@gmail.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r-- | drivers/mmc/card/block.c | 21 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 1 |
2 files changed, 15 insertions, 7 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c0cb225bbb47..a1cb21f95302 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -1030,13 +1030,20 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, | |||
1030 | if (brq->data.blocks > card->host->max_blk_count) | 1030 | if (brq->data.blocks > card->host->max_blk_count) |
1031 | brq->data.blocks = card->host->max_blk_count; | 1031 | brq->data.blocks = card->host->max_blk_count; |
1032 | 1032 | ||
1033 | /* | 1033 | if (brq->data.blocks > 1) { |
1034 | * After a read error, we redo the request one sector at a time | 1034 | /* |
1035 | * in order to accurately determine which sectors can be read | 1035 | * After a read error, we redo the request one sector |
1036 | * successfully. | 1036 | * at a time in order to accurately determine which |
1037 | */ | 1037 | * sectors can be read successfully. |
1038 | if (disable_multi && brq->data.blocks > 1) | 1038 | */ |
1039 | brq->data.blocks = 1; | 1039 | if (disable_multi) |
1040 | brq->data.blocks = 1; | ||
1041 | |||
1042 | /* Some controllers can't do multiblock reads due to hw bugs */ | ||
1043 | if (card->host->caps2 & MMC_CAP2_NO_MULTI_READ && | ||
1044 | rq_data_dir(req) == READ) | ||
1045 | brq->data.blocks = 1; | ||
1046 | } | ||
1040 | 1047 | ||
1041 | if (brq->data.blocks > 1 || do_rel_wr) { | 1048 | if (brq->data.blocks > 1 || do_rel_wr) { |
1042 | /* SPI multiblock writes terminate using a special | 1049 | /* SPI multiblock writes terminate using a special |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 16e9338944e8..a3ac9c48e5de 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -241,6 +241,7 @@ struct mmc_host { | |||
241 | #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ | 241 | #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ |
242 | #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ | 242 | #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ |
243 | #define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */ | 243 | #define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */ |
244 | #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ | ||
244 | 245 | ||
245 | mmc_pm_flag_t pm_caps; /* supported pm features */ | 246 | mmc_pm_flag_t pm_caps; /* supported pm features */ |
246 | unsigned int power_notify_type; | 247 | unsigned int power_notify_type; |