Hi Eugen,

On 2023-03-13 15:58, Eugen Hristev wrote:
> From: Ziyuan Xu <xzy...@rock-chips.com>
> 
> Per dw_mmc databook, it's recommended to reset the host controller if
> some data-related error occurred.
> Implement a reset mechanism.
> 
> Signed-off-by: Ziyuan Xu <xzy...@rock-chips.com>
> Co-developed-by: Jason Zhu <jason....@rock-chips.com>
> Signed-off-by: Jason Zhu <jason....@rock-chips.com>
> [eugen.hris...@collabora.com: modified a bit the variables initialization]
> Signed-off-by: Eugen Hristev <eugen.hris...@collabora.com>
> ---
>  drivers/mmc/dw_mmc.c | 20 +++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
> index 5085a3b491da..7c302ee614f4 100644
> --- a/drivers/mmc/dw_mmc.c
> +++ b/drivers/mmc/dw_mmc.c
> @@ -138,7 +138,7 @@ static int dwmci_data_transfer(struct dwmci_host *host, 
> struct mmc_data *data)
>  {
>       struct mmc *mmc = host->mmc;
>       int ret = 0;
> -     u32 timeout, mask, size, i, len = 0;
> +     u32 timeout, reset_timeout = 100, status, ctrl, mask, size, i, len = 0;
>       u32 *buf = NULL;
>       ulong start = get_timer(0);
>       u32 fifo_depth = (((host->fifoth_val & RX_WMARK_MASK) >>
> @@ -159,6 +159,24 @@ static int dwmci_data_transfer(struct dwmci_host *host, 
> struct mmc_data *data)
>               /* Error during data transfer. */
>               if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
>                       debug("%s: DATA ERROR!\n", __func__);
> +
> +                     dwmci_wait_reset(host, DWMCI_RESET_ALL);
> +                     dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
> +                                  DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
> +
> +                     do {
> +                             status = dwmci_readl(host, DWMCI_CMD);
> +                             if (!reset_timeout)

It does not look like reset_timeout is modified and this has potential
to get stuck in an endless loop.

Regards,
Jonas

> +                                     break;
> +                             udelay(100);
> +                     } while (status & DWMCI_CMD_START);
> +
> +                     if (!host->fifo_mode) {
> +                             ctrl = dwmci_readl(host, DWMCI_BMOD);
> +                             ctrl |= DWMCI_BMOD_IDMAC_RESET;
> +                             dwmci_writel(host, DWMCI_BMOD, ctrl);
> +                     }
> +
>                       ret = -EINVAL;
>                       break;
>               }

Reply via email to