mmc: meson-gx: check for scatterlist size alignment in block mode
Enable SGDMA support for SD_IO_RW_EXTENDED and add proper check for scatterlist size alignment in block mode. According to documentation, in SDIO block mode meson-gx DMA could only handle buffers with sizes that are multiples of SDIO block size. Some SDIO drivers like brcmfmac use scatterlist API, but do not enforce proper scatterlist buffer size alignemnt, this looks like a root cause of non-working CMD53. Some minor style fixes. Signed-off-by: Dmitry Lebed <lebed.dmitry@gmail.com> Reviewed-by: Jerome Brunet <jbrunet@baylibre.com> Link: https://lore.kernel.org/r/20201218075312.67338-1-lebed.dmitry@gmail.com Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
0354ca6edd
commit
e085b51c74
@ -227,7 +227,6 @@ static void meson_mmc_get_transfer_mode(struct mmc_host *mmc,
|
|||||||
struct mmc_data *data = mrq->data;
|
struct mmc_data *data = mrq->data;
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
int i;
|
int i;
|
||||||
bool use_desc_chain_mode = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When Controller DMA cannot directly access DDR memory, disable
|
* When Controller DMA cannot directly access DDR memory, disable
|
||||||
@ -237,25 +236,33 @@ static void meson_mmc_get_transfer_mode(struct mmc_host *mmc,
|
|||||||
if (host->dram_access_quirk)
|
if (host->dram_access_quirk)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
if (data->blocks > 1) {
|
||||||
* Broken SDIO with AP6255-based WiFi on Khadas VIM Pro has been
|
/*
|
||||||
* reported. For some strange reason this occurs in descriptor
|
* In block mode DMA descriptor format, "length" field indicates
|
||||||
* chain mode only. So let's fall back to bounce buffer mode
|
* number of blocks and there is no way to pass DMA size that
|
||||||
* for command SD_IO_RW_EXTENDED.
|
* is not multiple of SDIO block size, making it impossible to
|
||||||
*/
|
* tie more than one memory buffer with single SDIO block.
|
||||||
if (mrq->cmd->opcode == SD_IO_RW_EXTENDED)
|
* Block mode sg buffer size should be aligned with SDIO block
|
||||||
return;
|
* size, otherwise chain mode could not be used.
|
||||||
|
*/
|
||||||
for_each_sg(data->sg, sg, data->sg_len, i)
|
for_each_sg(data->sg, sg, data->sg_len, i) {
|
||||||
/* check for 8 byte alignment */
|
if (sg->length % data->blksz) {
|
||||||
if (sg->offset & 7) {
|
WARN_ONCE(1, "unaligned sg len %u blksize %u\n",
|
||||||
WARN_ONCE(1, "unaligned scatterlist buffer\n");
|
sg->length, data->blksz);
|
||||||
use_desc_chain_mode = false;
|
return;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (use_desc_chain_mode)
|
for_each_sg(data->sg, sg, data->sg_len, i) {
|
||||||
data->host_cookie |= SD_EMMC_DESC_CHAIN_MODE;
|
/* check for 8 byte alignment */
|
||||||
|
if (sg->offset % 8) {
|
||||||
|
WARN_ONCE(1, "unaligned scatterlist buffer\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->host_cookie |= SD_EMMC_DESC_CHAIN_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool meson_mmc_desc_chain_mode(const struct mmc_data *data)
|
static inline bool meson_mmc_desc_chain_mode(const struct mmc_data *data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user