This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
We have observed something that could be problematic in the way Davinci MMC Linux driver sets data timeout requested by Linux MMC core driver.
To give some context, we are working on an Omap-L138 based board on which we run Linux 3.1-rc4. On this system, we use an SDCard that has very high read/write busy time. For this reason, we have modified mmc_set_data_timeout() in drivers/mmc/core/core.c by adjusting data->timeout_ns/data->timeout_clks to obtain what we call software timeout. This modification has the following effects:
- Davinci MMC driver computes this software timeout as data->timeout_clks + convert_to_clks(data->timeout_ns) (see mmc_davinci_prepare_data() in drivers/mmc/host/davinci_mmc.c)
- this software timeout cannot be more than 0xFFFF
- this software timeout is then write to DAVINCI_MMCTOD register
As its is implemented in Davinci MMC driver, value in DAVINCI_MMCTOD only constitutes the lower bits of what we call the hardware timeout. The upper bits of this hardware timeout are found in TOD_25_16 bits of DAVINCI_MMCTOR register. Currently, TOD_25_16 bits contains fixed value 0x1F. This means that 0x1F FFFF is the maximum timeout that we can obtain with Davinci MMC driver code.
The problem is that hardware timeout (set in MMC controller by Davinci MMC driver) may not be equal to requested software timeout (set in Linux MMC core code, ie data->timeout_ns and data->timeout_clks).
In my opinion, this is really problematic especially when hardware timeout ends up being set less than requested software timeout. This situation may only be tolerate if the software timeout is bigger than the max possible hardware timeout which is 0x3FF FFFF (and not 0x1F FFFF as forced by Davinci MMC driver). To obtain the requested software timeout, the Davinci MMC driver must adjust both the value in DAVINCI_MMCTOD and in TOD_25_16 bits of DAVINCI_MMCTOR.
This situation is also present in Davinci MMC driver of Linux kernel 3.18.
What do you think about this observation? Do I miss something?
Regards,
Fabrice
Hi Fabrice,
Apologize for the delayed response on this.
To give some context, we are working on an Omap-L138 based board on which we run Linux 3.1-rc4. On this system, we use an SDCard that has very high read/write busy time. For this reason, we have modified mmc_set_data_timeout() in drivers/mmc/core/core.c by adjusting data->timeout_ns/data->timeout_clks to obtain what we call software timeout. This modification has the following effects:
Hi Titus,
Thanks for replying. Below, I am adding more information as requested.
What problem are you facing when you used the default hw timeout even though MMC was in high read/write busy ?
Regarding this question, here follows what I obtained from kernel log (this shows the issue with the default hw timeout):
mmcblk0: retrying using single block read
mmcblk0: error -110 transferring data, sector 7774080, nr 8, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 7774080
mmcblk0: timed out sending r/w cmd command, card status 0x400b00
mmcblk0: error -110 transferring data, sector 7774081, nr 7, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 7774081
mmcblk0: timed out sending r/w cmd command, card status 0x400b00
mmcblk0: error -110 transferring data, sector 7774082, nr 6, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 7774082
mmcblk0: timed out sending r/w cmd command, card status 0x400b00
mmcblk0: error -110 transferring data, sector 7774083, nr 5, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 7774083
mmcblk0: timed out sending r/w cmd command, card status 0x400b00
mmcblk0: error -110 transferring data, sector 7774084, nr 4, cmd response 0x900, card status 0x0
end_request: I/O error, dev mmcblk0, sector 7774084
mmcblk0: timed out sending r/w cmd command, card status 0x400b00
Also, have you increased the hardware timeout to maximum ?
Yes, I increased this timeout to its max value as you can see in the patch below. After that the card worked properly.
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 91a0a74..02fd8de 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -410,6 +410,29 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) data->timeout_ns = limit_us * 1000; data->timeout_clks = 0; } + + data->timeout_clks = 0xFFFF; + data->timeout_ns = 0; } /* * Some cards need very high timeouts if driven in SPI mode. diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 0076c74..1001bd1 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -351,7 +351,15 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, cmd_reg |= MMCCMD_PPLEN; /* set Command timeout */ - writel(0x1FFF, host->base + DAVINCI_MMCTOR); + writel(0x3FFFF, host->base + DAVINCI_MMCTOR); /* Enable interrupt (calculate here, defer until FIFO is stuffed). */ im_val = MMCST0_RSPDNE | MMCST0_CRCRS | MMCST0_TOUTRS; @@ -1197,7 +1205,15 @@ static void __init init_mmcsd_host(struct mmc_davinci_host *host) writel(0, host->base + DAVINCI_MMCCLK); writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK); - writel(0x1FFF, host->base + DAVINCI_MMCTOR); + writel(0x3FFFF, host->base + DAVINCI_MMCTOR); writel(0xFFFF, host->base + DAVINCI_MMCTOD); mmc_davinci_reset_ctrl(host, 0);
Could you attach the code changes if any to reproduce the issue at my end?
I did NO code changes for the issue to show up. The only changes that I did are those in the above patch.
Kind regards,
Fabrice