diff mbox

[2/3] mmc: mmc: do not use CMD13 to get status after speed mode switch

Message ID 1463647662-27426-3-git-send-email-chaotian.jing@mediatek.com (mailing list archive)
State New, archived
Headers show

Commit Message

Chaotian Jing (井朝天) May 19, 2016, 8:47 a.m. UTC
Per JEDEC spec, it is not recommended to use CMD13 to get card status
after speed mode switch. below are two reason about this:
1. CMD13 cannot be guaranteed due to the asynchronous operation.
Therefore it is not recommended to use CMD13 to check busy completion
of the timing change indication.
2. After switch to HS200, CMD13 will get response of 0x800, and even the
busy signal gets de-asserted, the response of CMD13 is aslo 0x800.

Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
---
 drivers/mmc/core/mmc.c | 112 ++++++++++++++++++++-----------------------------
 1 file changed, 45 insertions(+), 67 deletions(-)

Comments

Ulf Hansson June 21, 2016, 1:16 p.m. UTC | #1
On 19 May 2016 at 10:47, Chaotian Jing <chaotian.jing@mediatek.com> wrote:
> Per JEDEC spec, it is not recommended to use CMD13 to get card status
> after speed mode switch. below are two reason about this:
> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
> Therefore it is not recommended to use CMD13 to check busy completion
> of the timing change indication.
> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>
> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>

Thanks, applied for next! (With a minor change, see below)

[...]

>
>         /* Switch HS to HS200 */
>         val = EXT_CSD_TIMING_HS200 |
>               card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
>         err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
>                            val, card->ext_csd.generic_cmd6_time, true,
> -                          send_status, true);
> +                          false, true);

To keep consistency with other calls to __mmc_switch(), I change these lines to:

err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
                       val, card->ext_csd.generic_cmd6_time,
                       true, false, true);

>         if (err)
>                 goto out_err;
>
>         mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>
> -       if (!send_status) {
> -               err = mmc_switch_status(card);
> -               if (err)
> -                       goto out_err;
> -       }
> +       err = mmc_switch_status(card);
> +       if (err)
> +               goto out_err;
>
>         mmc_set_bus_speed(card);
>
> @@ -1243,7 +1227,6 @@ static void mmc_select_driver_type(struct mmc_card *card)
>  static int mmc_select_hs200(struct mmc_card *card)
>  {
>         struct mmc_host *host = card->host;
> -       bool send_status = true;
>         unsigned int old_timing;
>         int err = -EINVAL;
>         u8 val;
> @@ -1260,9 +1243,6 @@ static int mmc_select_hs200(struct mmc_card *card)
>
>         mmc_select_driver_type(card);
>
> -       if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
> -               send_status = false;
> -
>         /*
>          * Set the bus width(4 or 8) with host's support and
>          * switch to HS200 mode if bus width is set successfully.
> @@ -1274,20 +1254,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                                    EXT_CSD_HS_TIMING, val,
>                                    card->ext_csd.generic_cmd6_time,
> -                                  true, send_status, true);
> +                                  true, false, true);

[...]

Kind regards
Uffe
Bjorn Andersson July 15, 2016, 10:10 p.m. UTC | #2
On Thu, May 19, 2016 at 1:47 AM, Chaotian Jing
<chaotian.jing@mediatek.com> wrote:
> Per JEDEC spec, it is not recommended to use CMD13 to get card status
> after speed mode switch. below are two reason about this:
> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
> Therefore it is not recommended to use CMD13 to check busy completion
> of the timing change indication.
> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>
> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
> ---
>  drivers/mmc/core/mmc.c | 112 ++++++++++++++++++++-----------------------------
>  1 file changed, 45 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
[..]
> @@ -1274,20 +1254,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                                    EXT_CSD_HS_TIMING, val,
>                                    card->ext_csd.generic_cmd6_time,
> -                                  true, send_status, true);
> +                                  true, false, true);
>                 if (err)
>                         goto err;
>                 old_timing = host->ios.timing;
>                 mmc_set_timing(host, MMC_TIMING_MMC_HS200);
> -               if (!send_status) {
> -                       err = mmc_switch_status(card);
> -                       /*
> -                        * mmc_select_timing() assumes timing has not changed if
> -                        * it is a switch error.
> -                        */
> -                       if (err == -EBADMSG)
> -                               mmc_set_timing(host, old_timing);
> -               }
> +               err = mmc_switch_status(card);
> +               /*
> +                * mmc_select_timing() assumes timing has not changed if
> +                * it is a switch error.
> +                */
> +               if (err == -EBADMSG)
> +                       mmc_set_timing(host, old_timing);

Sorry for not spotting this earlier, but with the move of the call of
mmc_switch_status() to after mmc_set_timing() we get following error
with sdhci-msm:

mmc0: mmc_select_hs200 failed, error -110
mmc0: error -110 whilst initialising MMC card
mmc0: Reset 0x1 never completed.
sdhci: =========== REGISTER DUMP (mmc0)===========
sdhci: Sys addr: 0x00000000 | Version: 0x00002e02
sdhci: Blk size: 0x00004000 | Blk cnt: 0x00000000
sdhci: Argument: 0x00000000 | Trn mode: 0x00000000
sdhci: Present: 0x01f80000 | Host ctl: 0x00000000
sdhci: Power: 0x00000000 | Blk gap: 0x00000000
sdhci: Wake-up: 0x00000000 | Clock: 0x00000003
sdhci: Timeout: 0x00000000 | Int stat: 0x00000000
sdhci: Int enab: 0x00000000 | Sig enab: 0x00000000
sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
sdhci: Caps: 0x322dc8b2 | Caps_1: 0x00008007
sdhci: Cmd: 0x00000000 | Max curr: 0x00000000
sdhci: Host ctl2: 0x00000000
sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x0000000000000000
sdhci: ===========================================

But I if I understand the commit correctly this is the intention of
the patch (not the error, but the move).

Regards,
Bjorn

>         }
>  err:
>         if (err)
> --
> 1.8.1.1.dirty
>
Ulf Hansson July 18, 2016, 12:50 p.m. UTC | #3
On 16 July 2016 at 00:10, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
> On Thu, May 19, 2016 at 1:47 AM, Chaotian Jing
> <chaotian.jing@mediatek.com> wrote:
>> Per JEDEC spec, it is not recommended to use CMD13 to get card status
>> after speed mode switch. below are two reason about this:
>> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
>> Therefore it is not recommended to use CMD13 to check busy completion
>> of the timing change indication.
>> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
>> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>>
>> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
>> ---
>>  drivers/mmc/core/mmc.c | 112 ++++++++++++++++++++-----------------------------
>>  1 file changed, 45 insertions(+), 67 deletions(-)
>>
>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> [..]
>> @@ -1274,20 +1254,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>                                    EXT_CSD_HS_TIMING, val,
>>                                    card->ext_csd.generic_cmd6_time,
>> -                                  true, send_status, true);
>> +                                  true, false, true);
>>                 if (err)
>>                         goto err;
>>                 old_timing = host->ios.timing;
>>                 mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>> -               if (!send_status) {
>> -                       err = mmc_switch_status(card);
>> -                       /*
>> -                        * mmc_select_timing() assumes timing has not changed if
>> -                        * it is a switch error.
>> -                        */
>> -                       if (err == -EBADMSG)
>> -                               mmc_set_timing(host, old_timing);
>> -               }
>> +               err = mmc_switch_status(card);
>> +               /*
>> +                * mmc_select_timing() assumes timing has not changed if
>> +                * it is a switch error.
>> +                */
>> +               if (err == -EBADMSG)
>> +                       mmc_set_timing(host, old_timing);
>
> Sorry for not spotting this earlier, but with the move of the call of
> mmc_switch_status() to after mmc_set_timing() we get following error
> with sdhci-msm:

Thanks for reporting!

>
> mmc0: mmc_select_hs200 failed, error -110
> mmc0: error -110 whilst initialising MMC card
> mmc0: Reset 0x1 never completed.
> sdhci: =========== REGISTER DUMP (mmc0)===========
> sdhci: Sys addr: 0x00000000 | Version: 0x00002e02
> sdhci: Blk size: 0x00004000 | Blk cnt: 0x00000000
> sdhci: Argument: 0x00000000 | Trn mode: 0x00000000
> sdhci: Present: 0x01f80000 | Host ctl: 0x00000000
> sdhci: Power: 0x00000000 | Blk gap: 0x00000000
> sdhci: Wake-up: 0x00000000 | Clock: 0x00000003
> sdhci: Timeout: 0x00000000 | Int stat: 0x00000000
> sdhci: Int enab: 0x00000000 | Sig enab: 0x00000000
> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
> sdhci: Caps: 0x322dc8b2 | Caps_1: 0x00008007
> sdhci: Cmd: 0x00000000 | Max curr: 0x00000000
> sdhci: Host ctl2: 0x00000000
> sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x0000000000000000
> sdhci: ===========================================
>
> But I if I understand the commit correctly this is the intention of
> the patch (not the error, but the move).

I tried dropping this change from my next branch, but there are some
more changes on top that prevents a "clean" drop. It's certainly
doable, but perhaps we can try to narrow down the problem to see if
this could/should be fixed in the sdhci msm driver instead!?

I also noticed that below submitted change, which *isn't* applied for
next, might be related.
https://patchwork.kernel.org/patch/9197881/

>
> Regards,
> Bjorn
>
>>         }
>>  err:
>>         if (err)
>> --
>> 1.8.1.1.dirty
>>

Kind regards
Uffe
Georgi Djakov July 18, 2016, 1:38 p.m. UTC | #4
On 07/18/2016 03:50 PM, Ulf Hansson wrote:
> On 16 July 2016 at 00:10, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>> On Thu, May 19, 2016 at 1:47 AM, Chaotian Jing
>> <chaotian.jing@mediatek.com> wrote:
>>> Per JEDEC spec, it is not recommended to use CMD13 to get card status
>>> after speed mode switch. below are two reason about this:
>>> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
>>> Therefore it is not recommended to use CMD13 to check busy completion
>>> of the timing change indication.
>>> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
>>> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>>>
>>> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
>>> ---
>>>  drivers/mmc/core/mmc.c | 112 ++++++++++++++++++++-----------------------------
>>>  1 file changed, 45 insertions(+), 67 deletions(-)
>>>
>>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> [..]
>>> @@ -1274,20 +1254,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>>>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>>                                    EXT_CSD_HS_TIMING, val,
>>>                                    card->ext_csd.generic_cmd6_time,
>>> -                                  true, send_status, true);
>>> +                                  true, false, true);
>>>                 if (err)
>>>                         goto err;
>>>                 old_timing = host->ios.timing;
>>>                 mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>>> -               if (!send_status) {
>>> -                       err = mmc_switch_status(card);
>>> -                       /*
>>> -                        * mmc_select_timing() assumes timing has not changed if
>>> -                        * it is a switch error.
>>> -                        */
>>> -                       if (err == -EBADMSG)
>>> -                               mmc_set_timing(host, old_timing);
>>> -               }
>>> +               err = mmc_switch_status(card);
>>> +               /*
>>> +                * mmc_select_timing() assumes timing has not changed if
>>> +                * it is a switch error.
>>> +                */
>>> +               if (err == -EBADMSG)
>>> +                       mmc_set_timing(host, old_timing);
>>
>> Sorry for not spotting this earlier, but with the move of the call of
>> mmc_switch_status() to after mmc_set_timing() we get following error
>> with sdhci-msm:
> 
> Thanks for reporting!
> 
>>
>> mmc0: mmc_select_hs200 failed, error -110
>> mmc0: error -110 whilst initialising MMC card
>> mmc0: Reset 0x1 never completed.
>> sdhci: =========== REGISTER DUMP (mmc0)===========
>> sdhci: Sys addr: 0x00000000 | Version: 0x00002e02
>> sdhci: Blk size: 0x00004000 | Blk cnt: 0x00000000
>> sdhci: Argument: 0x00000000 | Trn mode: 0x00000000
>> sdhci: Present: 0x01f80000 | Host ctl: 0x00000000
>> sdhci: Power: 0x00000000 | Blk gap: 0x00000000
>> sdhci: Wake-up: 0x00000000 | Clock: 0x00000003
>> sdhci: Timeout: 0x00000000 | Int stat: 0x00000000
>> sdhci: Int enab: 0x00000000 | Sig enab: 0x00000000
>> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
>> sdhci: Caps: 0x322dc8b2 | Caps_1: 0x00008007
>> sdhci: Cmd: 0x00000000 | Max curr: 0x00000000
>> sdhci: Host ctl2: 0x00000000
>> sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x0000000000000000
>> sdhci: ===========================================
>>
>> But I if I understand the commit correctly this is the intention of
>> the patch (not the error, but the move).
> 
> I tried dropping this change from my next branch, but there are some
> more changes on top that prevents a "clean" drop. It's certainly
> doable, but perhaps we can try to narrow down the problem to see if
> this could/should be fixed in the sdhci msm driver instead!?

Yes, i am working on it. Seems that if we just ignore the -ETIMEDOUT
returned by mmc_switch_status() everything works as before. Currently
i am expecting more information about this controller specifics, in
order to understand if this could be fixed with a change in the driver
only.

> 
> I also noticed that below submitted change, which *isn't* applied for
> next, might be related.
> https://patchwork.kernel.org/patch/9197881/
> 

It is not related to this issue, but it is good to have when this is
resolved, otherwise we will see the dumpregs output (pr_err now),
when controller is initialized without a card in the SD slot.

Thanks,
Georgi
Ulf Hansson July 19, 2016, 9:31 a.m. UTC | #5
On 18 July 2016 at 15:38, Georgi Djakov <georgi.djakov@linaro.org> wrote:
> On 07/18/2016 03:50 PM, Ulf Hansson wrote:
>> On 16 July 2016 at 00:10, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>>> On Thu, May 19, 2016 at 1:47 AM, Chaotian Jing
>>> <chaotian.jing@mediatek.com> wrote:
>>>> Per JEDEC spec, it is not recommended to use CMD13 to get card status
>>>> after speed mode switch. below are two reason about this:
>>>> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
>>>> Therefore it is not recommended to use CMD13 to check busy completion
>>>> of the timing change indication.
>>>> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
>>>> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>>>>
>>>> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
>>>> ---
>>>>  drivers/mmc/core/mmc.c | 112 ++++++++++++++++++++-----------------------------
>>>>  1 file changed, 45 insertions(+), 67 deletions(-)
>>>>
>>>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>>> [..]
>>>> @@ -1274,20 +1254,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>>>>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>>>                                    EXT_CSD_HS_TIMING, val,
>>>>                                    card->ext_csd.generic_cmd6_time,
>>>> -                                  true, send_status, true);
>>>> +                                  true, false, true);
>>>>                 if (err)
>>>>                         goto err;
>>>>                 old_timing = host->ios.timing;
>>>>                 mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>>>> -               if (!send_status) {
>>>> -                       err = mmc_switch_status(card);
>>>> -                       /*
>>>> -                        * mmc_select_timing() assumes timing has not changed if
>>>> -                        * it is a switch error.
>>>> -                        */
>>>> -                       if (err == -EBADMSG)
>>>> -                               mmc_set_timing(host, old_timing);
>>>> -               }
>>>> +               err = mmc_switch_status(card);
>>>> +               /*
>>>> +                * mmc_select_timing() assumes timing has not changed if
>>>> +                * it is a switch error.
>>>> +                */
>>>> +               if (err == -EBADMSG)
>>>> +                       mmc_set_timing(host, old_timing);
>>>
>>> Sorry for not spotting this earlier, but with the move of the call of
>>> mmc_switch_status() to after mmc_set_timing() we get following error
>>> with sdhci-msm:
>>
>> Thanks for reporting!
>>
>>>
>>> mmc0: mmc_select_hs200 failed, error -110
>>> mmc0: error -110 whilst initialising MMC card
>>> mmc0: Reset 0x1 never completed.
>>> sdhci: =========== REGISTER DUMP (mmc0)===========
>>> sdhci: Sys addr: 0x00000000 | Version: 0x00002e02
>>> sdhci: Blk size: 0x00004000 | Blk cnt: 0x00000000
>>> sdhci: Argument: 0x00000000 | Trn mode: 0x00000000
>>> sdhci: Present: 0x01f80000 | Host ctl: 0x00000000
>>> sdhci: Power: 0x00000000 | Blk gap: 0x00000000
>>> sdhci: Wake-up: 0x00000000 | Clock: 0x00000003
>>> sdhci: Timeout: 0x00000000 | Int stat: 0x00000000
>>> sdhci: Int enab: 0x00000000 | Sig enab: 0x00000000
>>> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
>>> sdhci: Caps: 0x322dc8b2 | Caps_1: 0x00008007
>>> sdhci: Cmd: 0x00000000 | Max curr: 0x00000000
>>> sdhci: Host ctl2: 0x00000000
>>> sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x0000000000000000
>>> sdhci: ===========================================
>>>
>>> But I if I understand the commit correctly this is the intention of
>>> the patch (not the error, but the move).
>>
>> I tried dropping this change from my next branch, but there are some
>> more changes on top that prevents a "clean" drop. It's certainly
>> doable, but perhaps we can try to narrow down the problem to see if
>> this could/should be fixed in the sdhci msm driver instead!?
>
> Yes, i am working on it. Seems that if we just ignore the -ETIMEDOUT
> returned by mmc_switch_status() everything works as before. Currently
> i am expecting more information about this controller specifics, in
> order to understand if this could be fixed with a change in the driver
> only.

Thanks for looking into this!

>
>>
>> I also noticed that below submitted change, which *isn't* applied for
>> next, might be related.
>> https://patchwork.kernel.org/patch/9197881/
>>
>
> It is not related to this issue, but it is good to have when this is
> resolved, otherwise we will see the dumpregs output (pr_err now),
> when controller is initialized without a card in the SD slot.

Okay, thanks for clarifying. Although, I need an ack from Adrian
before I apply it.

>
> Thanks,
> Georgi

Kind regards
Uffe
Georgi Djakov July 19, 2016, 4:27 p.m. UTC | #6
On 07/19/2016 12:31 PM, Ulf Hansson wrote:
> On 18 July 2016 at 15:38, Georgi Djakov <georgi.djakov@linaro.org> wrote:
>> On 07/18/2016 03:50 PM, Ulf Hansson wrote:
>>> On 16 July 2016 at 00:10, Bjorn Andersson <bjorn.andersson@linaro.org> wrote:
>>>> On Thu, May 19, 2016 at 1:47 AM, Chaotian Jing
>>>> <chaotian.jing@mediatek.com> wrote:
>>>>> Per JEDEC spec, it is not recommended to use CMD13 to get card status
>>>>> after speed mode switch. below are two reason about this:
>>>>> 1. CMD13 cannot be guaranteed due to the asynchronous operation.
>>>>> Therefore it is not recommended to use CMD13 to check busy completion
>>>>> of the timing change indication.
>>>>> 2. After switch to HS200, CMD13 will get response of 0x800, and even the
>>>>> busy signal gets de-asserted, the response of CMD13 is aslo 0x800.
>>>>>
>>>>> Signed-off-by: Chaotian Jing <chaotian.jing@mediatek.com>
>>>>> ---
>>>>>  drivers/mmc/core/mmc.c | 112 ++++++++++++++++++++-----------------------------
>>>>>  1 file changed, 45 insertions(+), 67 deletions(-)
>>>>>
>>>>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>>>> [..]
>>>>> @@ -1274,20 +1254,18 @@ static int mmc_select_hs200(struct mmc_card *card)
>>>>>                 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>>>>                                    EXT_CSD_HS_TIMING, val,
>>>>>                                    card->ext_csd.generic_cmd6_time,
>>>>> -                                  true, send_status, true);
>>>>> +                                  true, false, true);
>>>>>                 if (err)
>>>>>                         goto err;
>>>>>                 old_timing = host->ios.timing;
>>>>>                 mmc_set_timing(host, MMC_TIMING_MMC_HS200);
>>>>> -               if (!send_status) {
>>>>> -                       err = mmc_switch_status(card);
>>>>> -                       /*
>>>>> -                        * mmc_select_timing() assumes timing has not changed if
>>>>> -                        * it is a switch error.
>>>>> -                        */
>>>>> -                       if (err == -EBADMSG)
>>>>> -                               mmc_set_timing(host, old_timing);
>>>>> -               }
>>>>> +               err = mmc_switch_status(card);
>>>>> +               /*
>>>>> +                * mmc_select_timing() assumes timing has not changed if
>>>>> +                * it is a switch error.
>>>>> +                */
>>>>> +               if (err == -EBADMSG)
>>>>> +                       mmc_set_timing(host, old_timing);
>>>>
>>>> Sorry for not spotting this earlier, but with the move of the call of
>>>> mmc_switch_status() to after mmc_set_timing() we get following error
>>>> with sdhci-msm:
>>>
>>> Thanks for reporting!
>>>
>>>>
>>>> mmc0: mmc_select_hs200 failed, error -110
>>>> mmc0: error -110 whilst initialising MMC card
>>>> mmc0: Reset 0x1 never completed.
>>>> sdhci: =========== REGISTER DUMP (mmc0)===========
>>>> sdhci: Sys addr: 0x00000000 | Version: 0x00002e02
>>>> sdhci: Blk size: 0x00004000 | Blk cnt: 0x00000000
>>>> sdhci: Argument: 0x00000000 | Trn mode: 0x00000000
>>>> sdhci: Present: 0x01f80000 | Host ctl: 0x00000000
>>>> sdhci: Power: 0x00000000 | Blk gap: 0x00000000
>>>> sdhci: Wake-up: 0x00000000 | Clock: 0x00000003
>>>> sdhci: Timeout: 0x00000000 | Int stat: 0x00000000
>>>> sdhci: Int enab: 0x00000000 | Sig enab: 0x00000000
>>>> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
>>>> sdhci: Caps: 0x322dc8b2 | Caps_1: 0x00008007
>>>> sdhci: Cmd: 0x00000000 | Max curr: 0x00000000
>>>> sdhci: Host ctl2: 0x00000000
>>>> sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x0000000000000000
>>>> sdhci: ===========================================
>>>>
>>>> But I if I understand the commit correctly this is the intention of
>>>> the patch (not the error, but the move).
>>>
>>> I tried dropping this change from my next branch, but there are some
>>> more changes on top that prevents a "clean" drop. It's certainly
>>> doable, but perhaps we can try to narrow down the problem to see if
>>> this could/should be fixed in the sdhci msm driver instead!?
>>
>> Yes, i am working on it. Seems that if we just ignore the -ETIMEDOUT
>> returned by mmc_switch_status() everything works as before. Currently
>> i am expecting more information about this controller specifics, in
>> order to understand if this could be fixed with a change in the driver
>> only.
> 
> Thanks for looking into this!
> 

Here is a partial fix, as it resolves the issue for the eMMC only.
https://patchwork.kernel.org/patch/9237679/
More investigation ongoing.

Thanks,
Georgi

>>
>>>
>>> I also noticed that below submitted change, which *isn't* applied for
>>> next, might be related.
>>> https://patchwork.kernel.org/patch/9197881/
>>>
>>
>> It is not related to this issue, but it is good to have when this is
>> resolved, otherwise we will see the dumpregs output (pr_err now),
>> when controller is initialized without a card in the SD slot.
> 
> Okay, thanks for clarifying. Although, I need an ack from Adrian
> before I apply it.
> 
>>
>> Thanks,
>> Georgi
> 
> Kind regards
> Uffe
>
diff mbox

Patch

diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 4dbe3df..97403a6 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -952,6 +952,19 @@  static int mmc_select_bus_width(struct mmc_card *card)
 	return err;
 }
 
+/* Caller must hold re-tuning */
+static int mmc_switch_status(struct mmc_card *card)
+{
+	u32 status;
+	int err;
+
+	err = mmc_send_status(card, &status);
+	if (err)
+		return err;
+
+	return mmc_switch_status_error(card->host, status);
+}
+
 /*
  * Switch to the high-speed mode
  */
@@ -962,9 +975,11 @@  static int mmc_select_hs(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
 			   card->ext_csd.generic_cmd6_time,
-			   true, true, true);
-	if (!err)
+			   true, false, true);
+	if (!err) {
 		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+		err = mmc_switch_status(card);
+	}
 
 	return err;
 }
@@ -1040,23 +1055,9 @@  static int mmc_select_hs_ddr(struct mmc_card *card)
 	return err;
 }
 
-/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
-{
-	u32 status;
-	int err;
-
-	err = mmc_send_status(card, &status);
-	if (err)
-		return err;
-
-	return mmc_switch_status_error(card->host, status);
-}
-
 static int mmc_select_hs400(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int max_dtr;
 	int err = 0;
 	u8 val;
@@ -1068,9 +1069,6 @@  static int mmc_select_hs400(struct mmc_card *card)
 	      host->ios.bus_width == MMC_BUS_WIDTH_8))
 		return 0;
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/* Reduce frequency to HS frequency */
 	max_dtr = card->ext_csd.hs_max_dtr;
 	mmc_set_clock(host, max_dtr);
@@ -1080,7 +1078,7 @@  static int mmc_select_hs400(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
 			   card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
 			mmc_hostname(host), err);
@@ -1090,11 +1088,9 @@  static int mmc_select_hs400(struct mmc_card *card)
 	/* Set host controller to HS timing */
 	mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch card to DDR */
 	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1113,7 +1109,7 @@  static int mmc_select_hs400(struct mmc_card *card)
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
 			   card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to hs400 failed, err:%d\n",
 			 mmc_hostname(host), err);
@@ -1124,11 +1120,9 @@  static int mmc_select_hs400(struct mmc_card *card)
 	mmc_set_timing(host, MMC_TIMING_MMC_HS400);
 	mmc_set_bus_speed(card);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	return 0;
 
@@ -1146,14 +1140,10 @@  int mmc_hs200_to_hs400(struct mmc_card *card)
 int mmc_hs400_to_hs200(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int max_dtr;
 	int err;
 	u8 val;
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/* Reduce frequency to HS */
 	max_dtr = card->ext_csd.hs_max_dtr;
 	mmc_set_clock(host, max_dtr);
@@ -1162,49 +1152,43 @@  int mmc_hs400_to_hs200(struct mmc_card *card)
 	val = EXT_CSD_TIMING_HS;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
 			   val, card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch HS DDR to HS */
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
 			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
-			   true, send_status, true);
+			   true, false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_HS);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	/* Switch HS to HS200 */
 	val = EXT_CSD_TIMING_HS200 |
 	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
 			   val, card->ext_csd.generic_cmd6_time, true,
-			   send_status, true);
+			   false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 
-	if (!send_status) {
-		err = mmc_switch_status(card);
-		if (err)
-			goto out_err;
-	}
+	err = mmc_switch_status(card);
+	if (err)
+		goto out_err;
 
 	mmc_set_bus_speed(card);
 
@@ -1243,7 +1227,6 @@  static void mmc_select_driver_type(struct mmc_card *card)
 static int mmc_select_hs200(struct mmc_card *card)
 {
 	struct mmc_host *host = card->host;
-	bool send_status = true;
 	unsigned int old_timing;
 	int err = -EINVAL;
 	u8 val;
@@ -1260,9 +1243,6 @@  static int mmc_select_hs200(struct mmc_card *card)
 
 	mmc_select_driver_type(card);
 
-	if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-		send_status = false;
-
 	/*
 	 * Set the bus width(4 or 8) with host's support and
 	 * switch to HS200 mode if bus width is set successfully.
@@ -1274,20 +1254,18 @@  static int mmc_select_hs200(struct mmc_card *card)
 		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				   EXT_CSD_HS_TIMING, val,
 				   card->ext_csd.generic_cmd6_time,
-				   true, send_status, true);
+				   true, false, true);
 		if (err)
 			goto err;
 		old_timing = host->ios.timing;
 		mmc_set_timing(host, MMC_TIMING_MMC_HS200);
-		if (!send_status) {
-			err = mmc_switch_status(card);
-			/*
-			 * mmc_select_timing() assumes timing has not changed if
-			 * it is a switch error.
-			 */
-			if (err == -EBADMSG)
-				mmc_set_timing(host, old_timing);
-		}
+		err = mmc_switch_status(card);
+		/*
+		 * mmc_select_timing() assumes timing has not changed if
+		 * it is a switch error.
+		 */
+		if (err == -EBADMSG)
+			mmc_set_timing(host, old_timing);
 	}
 err:
 	if (err)