Re: [PATCH] mmc: SD tuning is broken for some controllers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 9 May 2014 17:34, Al Cooper <alcooperx@xxxxxxxxx> wrote:
> The SD Host Controller spec states that the SD Host Controller can
> request that the driver send up to 40 CMD19's while doing tuning
> and that the total time the card spends responding must be < 150ms.
> The sdhci_execute_tuning() function in sdhci.c that loops through
> sending the CMD19's has multiple bugs. First it sets a "timeout"
> variable to 150 and a loop counter variable to 40. It then decrements
> both variables by 1 at the end of each loop. It tries to handle
> violations of the count and time by doing a break when BOTH variables
> are equal to zero, which can never happen because they we set to
> different values and decremented by 1 at the same time. The timeout
> variable is not based on time at all and is totally useless.
> The routine also considers a loop counter of zero to be an error
> which means that any controller that requests the max of 40 CMD19s
> will cause tuning to fail and be disabled.
>
> I've fixed these issues by allowing up to 40 CMD19's and I've removed
> any attempt to handle the 150ms time limit. Removing timeout checking
> seems safe here because each CMD19 is timeout protected and the max
> loop counters insures we don't loop forever. Adding timeout checking
> would not be as simple as snapping the time at the loop start and
> checking for 150ms to pass because the loop queues the CMD19's and
> uses events to wait for completion so the time would include
> all the normal scheduler latencies.
>
> Signed-off-by: Al Cooper <alcooperx@xxxxxxxxx>

Thanks Al. This make sense to me.
Unless someone objects, I will include this in the next PR I send to Chris.

Kind regards
Ulf Hansson

> ---
>  drivers/mmc/host/sdhci.c | 24 +++++++++---------------
>  1 file changed, 9 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 9ddef47..a601c10 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1859,7 +1859,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>         u16 ctrl;
>         u32 ier;
>         int tuning_loop_counter = MAX_TUNING_LOOP;
> -       unsigned long timeout;
>         int err = 0;
>         bool requires_tuning_nonuhs = false;
>         unsigned long flags;
> @@ -1918,14 +1917,10 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>          * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
>          * of loops reaches 40 times or a timeout of 150ms occurs.
>          */
> -       timeout = 150;
>         do {
>                 struct mmc_command cmd = {0};
>                 struct mmc_request mrq = {NULL};
>
> -               if (!tuning_loop_counter && !timeout)
> -                       break;
> -
>                 cmd.opcode = opcode;
>                 cmd.arg = 0;
>                 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> @@ -1933,6 +1928,9 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>                 cmd.data = NULL;
>                 cmd.error = 0;
>
> +               if (tuning_loop_counter-- == 0)
> +                       break;
> +
>                 mrq.cmd = &cmd;
>                 host->mrq = &mrq;
>
> @@ -1990,8 +1988,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>                 host->tuning_done = 0;
>
>                 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> -               tuning_loop_counter--;
> -               timeout--;
>                 mdelay(1);
>         } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
>
> @@ -1999,17 +1995,15 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>          * The Host Driver has exhausted the maximum number of loops allowed,
>          * so use fixed sampling frequency.
>          */
> -       if (!tuning_loop_counter || !timeout) {
> +       if (tuning_loop_counter < 0) {
>                 ctrl &= ~SDHCI_CTRL_TUNED_CLK;
>                 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> +       }
> +       if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
> +               pr_info(DRIVER_NAME ": Tuning procedure"
> +                       " failed, falling back to fixed sampling"
> +                       " clock\n");
>                 err = -EIO;
> -       } else {
> -               if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
> -                       pr_info(DRIVER_NAME ": Tuning procedure"
> -                               " failed, falling back to fixed sampling"
> -                               " clock\n");
> -                       err = -EIO;
> -               }
>         }
>
>  out:
> --
> 1.9.0.138.g2de3478
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux