Re: [PATCH V2] mmc: sdhci-msm: Disable CQE during SDHC reset

From: Veerabhadrarao Badiganti
Date: Wed Mar 04 2020 - 11:51:18 EST



On 3/4/2020 7:40 PM, Adrian Hunter wrote:
On 4/03/20 3:10 pm, Veerabhadrarao Badiganti wrote:
Hi Adrian

On 3/4/2020 5:58 PM, Adrian Hunter wrote:
On 4/03/20 1:54 pm, Veerabhadrarao Badiganti wrote:
When SDHC gets reset (E.g. in suspend path), CQE also gets reset
and goes to disable state. But s/w state still points it as CQE
is in enabled state. Since s/w and h/w states goes out of sync,
it results in s/w request timeout for subsequent CQE requests.

To synchronize CQE s/w and h/w state during SDHC reset,
explicitly disable CQE after reset.
Shouldn't you be calling cqhci_suspend() / cqhci_resume() in the suspend and
resume paths?
This issue is seen during mmc runtime suspend. I can add it
sdhci_msm_runtime_suspend

but sdhci_msm runtime delay is aggressive, its 50ms. It may get invoked very
frequently.

So Im of the opinion that disabling CQE very often from platform runtime
suspend is overkill.
It doesn't look like sdhci-msm calls any sdhci.c pm ops, so how does SDHC
get reset?

With MMC_CAP_AGGRESSIVE_PM flag enabled, it getting called from mmc_runtime_suspend()

Below is the call stack()

ÂÂ sdhci_reset
 sdhci_do_reset
 sdhci_init
 sdhci_set_ios
 mmc_set_initial_state
 mmc_power_off
Â_mmc_suspend
 mmc_runtime_suspend

Signed-off-by: Veerabhadrarao Badiganti <vbadigan@xxxxxxxxxxxxxx>
---
Changes since V1:
ÂÂÂÂ- Disable CQE only when SDHC undergoes s/w reset for all.
---
 drivers/mmc/host/sdhci-msm.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 53b79ee..75929d3 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1823,6 +1823,13 @@ static void sdhci_msm_set_regulator_caps(struct
sdhci_msm_host *msm_host)
ÂÂÂÂÂ pr_debug("%s: supported caps: 0x%08x\n", mmc_hostname(mmc), caps);
 }
 +static void sdhci_msm_reset(struct sdhci_host *host, u8 mask)
+{
+ÂÂÂ sdhci_reset(host, mask);
+ÂÂÂ if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL))
+ÂÂÂÂÂÂÂ cqhci_suspend(host->mmc);
+}
+
 static const struct sdhci_msm_variant_ops mci_var_ops = {
ÂÂÂÂÂ .msm_readl_relaxed = sdhci_msm_mci_variant_readl_relaxed,
ÂÂÂÂÂ .msm_writel_relaxed = sdhci_msm_mci_variant_writel_relaxed,
@@ -1861,7 +1868,7 @@ static void sdhci_msm_set_regulator_caps(struct
sdhci_msm_host *msm_host)
 MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
  static const struct sdhci_ops sdhci_msm_ops = {
-ÂÂÂ .reset = sdhci_reset,
+ÂÂÂ .reset = sdhci_msm_reset,
ÂÂÂÂÂ .set_clock = sdhci_msm_set_clock,
ÂÂÂÂÂ .get_min_clock = sdhci_msm_get_min_clock,
ÂÂÂÂÂ .get_max_clock = sdhci_msm_get_max_clock,