summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
authorAdrian Hunter2017-03-20 18:50:38 +0100
committerUlf Hansson2017-04-24 21:41:30 +0200
commit2a85ef25bee6910f4de510c5b574c81e87f38b05 (patch)
treece33855b6720114173acfede1bbb36900c03a75d /drivers/mmc/host/sdhci.c
parentmmc: sdhci: Do not use spin lock in set_ios paths (diff)
downloadkernel-qcow2-linux-2a85ef25bee6910f4de510c5b574c81e87f38b05.tar.gz
kernel-qcow2-linux-2a85ef25bee6910f4de510c5b574c81e87f38b05.tar.xz
kernel-qcow2-linux-2a85ef25bee6910f4de510c5b574c81e87f38b05.zip
mmc: sdhci: Reduce spin lock usage in sdhci_execute_tuning
Tuning execution is already synchronized with respect to other host operations by upper layers "claiming" the host, which also takes care of runtime pm. There can be no requests in progress. Retain the spin lock usage only for ensuring that sending tuning commands is synchronized with respect to the interrupt handler. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Tested-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c36
1 files changed, 14 insertions, 22 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 5c2b35dd1c45..cfb6d3a23aef 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1993,8 +1993,7 @@ static void sdhci_reset_tuning(struct sdhci_host *host)
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
}
-static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode,
- unsigned long flags)
+static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
{
sdhci_reset_tuning(host);
@@ -2003,9 +2002,7 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode,
sdhci_end_tuning(host);
- spin_unlock_irqrestore(&host->lock, flags);
mmc_abort_tuning(host->mmc, opcode);
- spin_lock_irqsave(&host->lock, flags);
}
/*
@@ -2015,12 +2012,14 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode,
* interrupt setup is different to other commands and there is no timeout
* interrupt so special handling is needed.
*/
-static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode,
- unsigned long flags)
+static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
{
struct mmc_host *mmc = host->mmc;
struct mmc_command cmd = {};
struct mmc_request mrq = {};
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
cmd.opcode = opcode;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -2054,17 +2053,16 @@ static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode,
host->tuning_done = 0;
+ mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
/* Wait for Buffer Read Ready interrupt */
wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1),
msecs_to_jiffies(50));
- spin_lock_irqsave(&host->lock, flags);
}
-static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode,
- unsigned long flags)
+static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
{
int i;
@@ -2075,12 +2073,12 @@ static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode,
for (i = 0; i < MAX_TUNING_LOOP; i++) {
u16 ctrl;
- sdhci_send_tuning(host, opcode, flags);
+ sdhci_send_tuning(host, opcode);
if (!host->tuning_done) {
pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
mmc_hostname(host->mmc));
- sdhci_abort_tuning(host, opcode, flags);
+ sdhci_abort_tuning(host, opcode);
return;
}
@@ -2105,12 +2103,9 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host = mmc_priv(mmc);
int err = 0;
- unsigned long flags;
unsigned int tuning_count = 0;
bool hs400_tuning;
- spin_lock_irqsave(&host->lock, flags);
-
hs400_tuning = host->flags & SDHCI_HS400_TUNING;
if (host->tuning_mode == SDHCI_TUNING_MODE_1)
@@ -2127,7 +2122,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
/* HS400 tuning is done in HS200 mode */
case MMC_TIMING_MMC_HS400:
err = -EINVAL;
- goto out_unlock;
+ goto out;
case MMC_TIMING_MMC_HS200:
/*
@@ -2148,26 +2143,23 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
/* FALLTHROUGH */
default:
- goto out_unlock;
+ goto out;
}
if (host->ops->platform_execute_tuning) {
- spin_unlock_irqrestore(&host->lock, flags);
err = host->ops->platform_execute_tuning(host, opcode);
- spin_lock_irqsave(&host->lock, flags);
- goto out_unlock;
+ goto out;
}
host->mmc->retune_period = tuning_count;
sdhci_start_tuning(host);
- __sdhci_execute_tuning(host, opcode, flags);
+ __sdhci_execute_tuning(host, opcode);
sdhci_end_tuning(host);
-out_unlock:
+out:
host->flags &= ~SDHCI_HS400_TUNING;
- spin_unlock_irqrestore(&host->lock, flags);
return err;
}