Hi igor, all,
Thanks a lot for your reply.
It seems that we found root cause.
As the document you suggested:
sect.1.13.3 Data Address and Data Length Requirements p.15 SD specification
https://members.sdcard.org/downloads/pls/simplified_specs/archive/partA2_300.pdf
The i.MX host controller does NOT allow 64KB data size for each descriptor.
In Linux code, following quirk flag seems to be used for this spec.
(in sdhci.h)
/* Controller treats ADMA descriptors with length 0000h incorrectly */
#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30)
This quirk flag is set in sdhci-esdhc-imx.c.
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT
| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
| SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
.ops = &sdhci_esdhc_ops,
};
We are not so sure but in newer SD spec, length = 0 setting seems to be accepted, correct??
Anyway, if this quirk flag is set, the max_seg_size member in struct mmc_host is set to 65535 in sdhci.c.
/*
* Maximum segment size. Could be one segment with the maximum number
* of bytes. When doing hardware scatter/gather, each entry cannot
* be larger than 64 KiB though.
*/
if (host->flags & SDHCI_USE_ADMA) {
if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC)
mmc->max_seg_size = 65535;
else
mmc->max_seg_size = 65536;
} else {
mmc->max_seg_size = mmc->max_req_size;
}
max_seg_size member is used in mmc_io_rw_extended function in sdio_ops.c.
We are not so sure about following code but it seems that the transfer data is split by max_seg_size.
int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
{
struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
struct scatterlist sg, *sg_ptr;
struct sg_table sgtable;
unsigned int nents, left_size, i;
unsigned int seg_size = card->host->max_seg_size;
...
nents = (left_size - 1) / seg_size + 1;
if (nents > 1) {
if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))
return -ENOMEM;
data.sg = sgtable.sgl;
data.sg_len = nents;
for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
min(seg_size, left_size),
offset_in_page(buf + (i * seg_size)));
left_size = left_size - seg_size;
}
} else {
We supposed that for DMA transfer, such unaligned odd number is not OK, so we tested to change max_seg_size from 65535(0xFFFF) to 61440(0xF000).
After all, the ETIMEDOUT is not occurred and the transfer seems to become OK now.
So we assumed that wrong max_seq_size setting 65535 = 0xFFFF is the root cause.
We are not so professional about SD Host, but we think that i.MX SD Host cannot accept 64KB length data for each descriptor (SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC should be set), the max_seg_size should be set correct, and aligned value (like 0xF000) for i.MX system, we supposed.
We are not sure which code (sdhci.c or sdhci-esdhc-imx.c) should be fixed, but it's better to modify Linux SD host code to avoid similar issue.
What do you think?
Best Regards,
Yonezawa