aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorRussell King2016-01-26 13:41:14 +0000
committerUlf Hansson2016-02-29 11:03:23 +0100
commitdf953925a504d3c7a2a8814143a044c14d6660c0 (patch)
treed219cf02c35b15ee481775653deff44d4d6b1387 /drivers/mmc
parenta0eaf0f93f0630ac09519e27c84f88c8e41c6f8b (diff)
mmc: sdhci: consolidate the DMA/ADMA size/address quicks
Rather than scanning the scatterlist multiple times for each quirk, scan it once, checking for each possible quirk. This should be cheaper due to the length and offset members commonly sharing the same cache line than scanning the scatterlist multiple times. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Tested-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/sdhci.c48
1 files changed, 16 insertions, 32 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5119904dc6bf..2bd6bc1aca28 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -731,22 +731,35 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
/*
* FIXME: This doesn't account for merging when mapping the
* scatterlist.
+ *
+ * The assumption here being that alignment and lengths are
+ * the same after DMA mapping to device address space.
*/
if (host->flags & SDHCI_REQ_USE_DMA) {
struct scatterlist *sg;
- unsigned int length_mask;
+ unsigned int length_mask, offset_mask;
int i;
length_mask = 0;
+ offset_mask = 0;
if (host->flags & SDHCI_USE_ADMA) {
- if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE)
+ if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE) {
length_mask = 3;
+ /*
+ * As we use up to 3 byte chunks to work
+ * around alignment problems, we need to
+ * check the offset as well.
+ */
+ offset_mask = 3;
+ }
} else {
if (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE)
length_mask = 3;
+ if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR)
+ offset_mask = 3;
}
- if (unlikely(length_mask)) {
+ if (unlikely(length_mask | offset_mask)) {
for_each_sg(data->sg, sg, data->sg_len, i) {
if (sg->length & length_mask) {
DBG("Reverting to PIO because of transfer size (%d)\n",
@@ -754,35 +767,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
host->flags &= ~SDHCI_REQ_USE_DMA;
break;
}
- }
- }
- }
-
- /*
- * The assumption here being that alignment is the same after
- * translation to device address space.
- */
- if (host->flags & SDHCI_REQ_USE_DMA) {
- struct scatterlist *sg;
- unsigned int offset_mask;
- int i;
-
- offset_mask = 0;
- if (host->flags & SDHCI_USE_ADMA) {
- /*
- * As we use 3 byte chunks to work around
- * alignment problems, we need to check this
- * quirk.
- */
- if (host->quirks & SDHCI_QUIRK_32BIT_ADMA_SIZE)
- offset_mask = 3;
- } else {
- if (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR)
- offset_mask = 3;
- }
-
- if (unlikely(offset_mask)) {
- for_each_sg(data->sg, sg, data->sg_len, i) {
if (sg->offset & offset_mask) {
DBG("Reverting to PIO because of bad alignment\n");
host->flags &= ~SDHCI_REQ_USE_DMA;