On 26 November 2015 at 13:00, Adrian Hunter <[email protected]> wrote:
> SDHCI has built-in DMA called ADMA2. ADMA2 uses a descriptor
> table to define DMA scatter-gather. Each desciptor can specify
> a data length up to 65536 bytes, however the length field is
> only 16-bits so zero means 65536. Consequently, putting zero
> when the size is zero must not be allowed. This patch fixes
> one case where zero data length could be set inadvertently.
>
> The problem happens because unaligned data gets split and the
> code did not consider that the remaining aligned portion might
> be zero length. That case really only happens for SDIO because
> SD and eMMC cards transfer blocks that are invariably sector-
> aligned. For SDIO, access to function registers is done by
> data transfer (CMD53) when the register is bigger than 1 byte.
> Generally registers are 4 bytes but 2-byte registers are possible.
> So DMA of 4 bytes or less can happen. When 32-bit DMA is used,
> the data alignment must be 4, so 4-byte transfers won't casue a
> problem, but a 2-byte transfer could. However with the introduction
> of 64-bit DMA, the data alignment for 64-bit DMA was made 8 bytes,
> so all 4-byte transfers not on 8-byte boundaries get "split" into
> a 4-byte chunk and a 0-byte chunk, thereby hitting the bug.
>
> In fact, a closer look at the SDHCI specs indicates that only the
> descriptor table requires 8-byte alignment for 64-bit DMA. That
> will be dealt with in a separate patch, but the potential for a
> 2-byte access remains, so this fix is needed anyway.
>
> Signed-off-by: Adrian Hunter <[email protected]>
> Cc: [email protected] # v3.19+
I updated the prefix of the commit msg header, /s/sdhc/sdhci
Kind regards
Uffe
> ---
> drivers/mmc/host/sdhci.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 5f8b0766428c..6ac5db8e86ab 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -540,9 +540,12 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
>
> BUG_ON(len > 65536);
>
> - /* tran, valid */
> - sdhci_adma_write_desc(host, desc, addr, len,
> ADMA2_TRAN_VALID);
> - desc += host->desc_sz;
> + if (len) {
> + /* tran, valid */
> + sdhci_adma_write_desc(host, desc, addr, len,
> + ADMA2_TRAN_VALID);
> + desc += host->desc_sz;
> + }
>
> /*
> * If this triggers then we have a calculation bug
> --
> 1.9.1
>
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html