2020-02-28 11:52:10

by Veerabhadrarao Badiganti

[permalink] [raw]
Subject: [PATCH] mmc: sdhci-msm: Disable CQE during SDHC reset

When SDHC gets reset (E.g. in suspend/resume 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.

Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
---
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..d7ba3b2 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)
+ 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,
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc., is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


2020-03-04 11:55:43

by Veerabhadrarao Badiganti

[permalink] [raw]
Subject: [PATCH V2] mmc: sdhci-msm: Disable CQE during SDHC reset

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.

Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
---
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,
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc., is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2020-03-04 12:29:52

by Adrian Hunter

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

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?

>
> Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
> ---
> 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,
>

2020-03-04 13:12:02

by Veerabhadrarao Badiganti

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

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.

>> Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
>> ---
>> 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,
>>

2020-03-04 14:12:27

by Adrian Hunter

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

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?

>
>>> Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
>>> ---
>>> 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,
>>>

2020-03-04 16:51:51

by Veerabhadrarao Badiganti

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


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 <[email protected]>
>>>> ---
>>>> 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,
>>>>

2020-03-05 09:01:17

by Adrian Hunter

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

On 4/03/20 6:50 pm, Veerabhadrarao Badiganti wrote:
>
> 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
>

OK, cqhci_suspend does the right thing, but it is not an
appropriate function for this. I suggest introducing
cqhci_deactivate() as below.

From: Adrian Hunter <[email protected]>
Date: Thu, 5 Mar 2020 10:42:09 +0200
Subject: [PATCH] mmc: cqhci: Add cqhci_deactivate()

Host controllers can reset CQHCI either directly or as a consequence of
host controller reset. Add cqhci_deactivate() which puts the CQHCI
driver into a state that is consistent with that.

Signed-off-by: Adrian Hunter <[email protected]>
---
drivers/mmc/host/cqhci.c | 6 +++---
drivers/mmc/host/cqhci.h | 5 ++++-
2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c
index e2ea2c4b6b94..d8d024a1682b 100644
--- a/drivers/mmc/host/cqhci.c
+++ b/drivers/mmc/host/cqhci.c
@@ -298,16 +298,16 @@ static void __cqhci_disable(struct cqhci_host *cq_host)
cq_host->activated = false;
}

-int cqhci_suspend(struct mmc_host *mmc)
+int cqhci_deactivate(struct mmc_host *mmc)
{
struct cqhci_host *cq_host = mmc->cqe_private;

- if (cq_host->enabled)
+ if (cq_host->enabled && cq_host->activated)
__cqhci_disable(cq_host);

return 0;
}
-EXPORT_SYMBOL(cqhci_suspend);
+EXPORT_SYMBOL(cqhci_deactivate);

int cqhci_resume(struct mmc_host *mmc)
{
diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
index def76e9b5cac..8648846a0213 100644
--- a/drivers/mmc/host/cqhci.h
+++ b/drivers/mmc/host/cqhci.h
@@ -230,7 +230,10 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error,
int data_error);
int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, bool dma64);
struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev);
-int cqhci_suspend(struct mmc_host *mmc);
+static inline int cqhci_suspend(struct mmc_host *mmc)
+{
+ return cqhci_deactivate(mmc);
+}
int cqhci_resume(struct mmc_host *mmc);

#endif
--
2.17.1


Also, it would be more logical to deactivate prior to the reset i.e.

+ if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL))
+ cqhci_deactivate(host->mmc);
+ sdhci_reset(host, mask);


Also, other drivers using cqhci, should probably do this too, although
some of them do not reset cqhci with sdhci so perhaps do not need to.

>>>>> Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
>>>>> ---
>>>>> 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,
>>>>>

2020-03-06 10:15:06

by Veerabhadrarao Badiganti

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


On 3/5/2020 2:29 PM, Adrian Hunter wrote:
> On 4/03/20 6:50 pm, Veerabhadrarao Badiganti wrote:
>> 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
>>
> OK, cqhci_suspend does the right thing, but it is not an
> appropriate function for this. I suggest introducing
> cqhci_deactivate() as below.
>
> From: Adrian Hunter <[email protected]>
> Date: Thu, 5 Mar 2020 10:42:09 +0200
> Subject: [PATCH] mmc: cqhci: Add cqhci_deactivate()
>
> Host controllers can reset CQHCI either directly or as a consequence of
> host controller reset. Add cqhci_deactivate() which puts the CQHCI
> driver into a state that is consistent with that.
>
> Signed-off-by: Adrian Hunter <[email protected]>
> ---
> drivers/mmc/host/cqhci.c | 6 +++---
> drivers/mmc/host/cqhci.h | 5 ++++-
> 2 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c
> index e2ea2c4b6b94..d8d024a1682b 100644
> --- a/drivers/mmc/host/cqhci.c
> +++ b/drivers/mmc/host/cqhci.c
> @@ -298,16 +298,16 @@ static void __cqhci_disable(struct cqhci_host *cq_host)
> cq_host->activated = false;
> }
>
> -int cqhci_suspend(struct mmc_host *mmc)
> +int cqhci_deactivate(struct mmc_host *mmc)
> {
> struct cqhci_host *cq_host = mmc->cqe_private;
>
> - if (cq_host->enabled)
> + if (cq_host->enabled && cq_host->activated)
> __cqhci_disable(cq_host);
>
> return 0;
> }
> -EXPORT_SYMBOL(cqhci_suspend);
> +EXPORT_SYMBOL(cqhci_deactivate);
>
> int cqhci_resume(struct mmc_host *mmc)
> {
> diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
> index def76e9b5cac..8648846a0213 100644
> --- a/drivers/mmc/host/cqhci.h
> +++ b/drivers/mmc/host/cqhci.h
> @@ -230,7 +230,10 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error,
> int data_error);
> int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, bool dma64);
> struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev);
> -int cqhci_suspend(struct mmc_host *mmc);
> +static inline int cqhci_suspend(struct mmc_host *mmc)
> +{
> + return cqhci_deactivate(mmc);
> +}
> int cqhci_resume(struct mmc_host *mmc);
>
> #endif

Thanks Adrian for the suggestion. Will post this change and my updated fix.

Thanks

Veera

2020-03-06 14:10:09

by Veerabhadrarao Badiganti

[permalink] [raw]
Subject: [PATCH V3 0/2] Deactivate CQE during SDHC reset

Host controllers can reset CQHCI either directly or as a consequence
of host controller reset. In the later case, driver should deactivate
CQHCI just before reset to puts the CQHCI driver into a state that is
consistent with that h/w state.

Changes sicne V2:
- Added support cqhci_deactivate()
- Use cqhci_deactivate() instead of cqhci_disable().
- Deactivate CQCHI just before SDHC reset.

Changes since V1:
- Disable CQE only when SDHC undergoes s/w reset for all.

Adrian Hunter (1):
mmc: cqhci: Add cqhci_deactivate()

Veerabhadrarao Badiganti (1):
mmc: sdhci-msm: Deactivate CQE during SDHC reset

drivers/mmc/host/cqhci.c | 6 +++---
drivers/mmc/host/cqhci.h | 6 +++++-
drivers/mmc/host/sdhci-msm.c | 9 ++++++++-
3 files changed, 16 insertions(+), 5 deletions(-)

--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc., is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2020-03-06 14:10:38

by Veerabhadrarao Badiganti

[permalink] [raw]
Subject: [PATCH V3 1/2] mmc: cqhci: Add cqhci_deactivate()

From: Adrian Hunter <[email protected]>

Host controllers can reset CQHCI either directly or as a consequence of
host controller reset. Add cqhci_deactivate() which puts the CQHCI
driver into a state that is consistent with that.

Signed-off-by: Adrian Hunter <[email protected]>
Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
---
drivers/mmc/host/cqhci.c | 6 +++---
drivers/mmc/host/cqhci.h | 6 +++++-
2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c
index e24b8ff..c2239ee 100644
--- a/drivers/mmc/host/cqhci.c
+++ b/drivers/mmc/host/cqhci.c
@@ -298,16 +298,16 @@ static void __cqhci_disable(struct cqhci_host *cq_host)
cq_host->activated = false;
}

-int cqhci_suspend(struct mmc_host *mmc)
+int cqhci_deactivate(struct mmc_host *mmc)
{
struct cqhci_host *cq_host = mmc->cqe_private;

- if (cq_host->enabled)
+ if (cq_host->enabled && cq_host->activated)
__cqhci_disable(cq_host);

return 0;
}
-EXPORT_SYMBOL(cqhci_suspend);
+EXPORT_SYMBOL(cqhci_deactivate);

int cqhci_resume(struct mmc_host *mmc)
{
diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
index def76e9..4377001 100644
--- a/drivers/mmc/host/cqhci.h
+++ b/drivers/mmc/host/cqhci.h
@@ -230,7 +230,11 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error,
int data_error);
int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, bool dma64);
struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev);
-int cqhci_suspend(struct mmc_host *mmc);
+int cqhci_deactivate(struct mmc_host *mmc);
+static inline int cqhci_suspend(struct mmc_host *mmc)
+{
+ return cqhci_deactivate(mmc);
+}
int cqhci_resume(struct mmc_host *mmc);

#endif
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc., is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2020-03-06 14:11:19

by Veerabhadrarao Badiganti

[permalink] [raw]
Subject: [PATCH V3 2/2] mmc: sdhci-msm: Deactivate CQE during SDHC reset

When SDHC gets reset (E.g. in runtime 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 deactivate CQE just before SDHC reset.

Signed-off-by: Veerabhadrarao Badiganti <[email protected]>
---
Changes sicne V2:
- Use cqhci_deactivate() instead of cqhci_disable().
- Deactivate CQCHI just before SDHC reset.

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..09ff731 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)
+{
+ if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL))
+ cqhci_deactivate(host->mmc);
+ sdhci_reset(host, mask);
+}
+
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,
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc., is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

2020-03-06 14:13:46

by Adrian Hunter

[permalink] [raw]
Subject: Re: [PATCH V3 2/2] mmc: sdhci-msm: Deactivate CQE during SDHC reset

On 6/03/20 4:08 pm, Veerabhadrarao Badiganti wrote:
> When SDHC gets reset (E.g. in runtime 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 deactivate CQE just before SDHC reset.
>
> Signed-off-by: Veerabhadrarao Badiganti <[email protected]>

Acked-by: Adrian Hunter <[email protected]>

> ---
> Changes sicne V2:
> - Use cqhci_deactivate() instead of cqhci_disable().
> - Deactivate CQCHI just before SDHC reset.
>
> 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..09ff731 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)
> +{
> + if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL))
> + cqhci_deactivate(host->mmc);
> + sdhci_reset(host, mask);
> +}
> +
> 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,
>

2020-03-11 15:35:52

by Ulf Hansson

[permalink] [raw]
Subject: Re: [PATCH V3 0/2] Deactivate CQE during SDHC reset

On Fri, 6 Mar 2020 at 15:09, Veerabhadrarao Badiganti
<[email protected]> wrote:
>
> Host controllers can reset CQHCI either directly or as a consequence
> of host controller reset. In the later case, driver should deactivate
> CQHCI just before reset to puts the CQHCI driver into a state that is
> consistent with that h/w state.
>
> Changes sicne V2:
> - Added support cqhci_deactivate()
> - Use cqhci_deactivate() instead of cqhci_disable().
> - Deactivate CQCHI just before SDHC reset.
>
> Changes since V1:
> - Disable CQE only when SDHC undergoes s/w reset for all.
>
> Adrian Hunter (1):
> mmc: cqhci: Add cqhci_deactivate()
>
> Veerabhadrarao Badiganti (1):
> mmc: sdhci-msm: Deactivate CQE during SDHC reset
>
> drivers/mmc/host/cqhci.c | 6 +++---
> drivers/mmc/host/cqhci.h | 6 +++++-
> drivers/mmc/host/sdhci-msm.c | 9 ++++++++-
> 3 files changed, 16 insertions(+), 5 deletions(-)

Applied for next, thanks!

Kind regards
Uffe