]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mmc: sdhci-of-esdhc: set DMA snooping based on DMA coherence
authorRussell King <rmk+kernel@armlinux.org.uk>
Sun, 22 Sep 2019 10:26:58 +0000 (11:26 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Fri, 27 Sep 2019 18:30:13 +0000 (20:30 +0200)
We must not unconditionally set the DMA snoop bit; if the DMA API is
assuming that the device is not DMA coherent, and the device snoops the
CPU caches, the device can see stale cache lines brought in by
speculative prefetch.

This leads to the device seeing stale data, potentially resulting in
corrupted data transfers.  Commonly, this results in a descriptor fetch
error such as:

mmc0: ADMA error
mmc0: sdhci: ============ SDHCI REGISTER DUMP ===========
mmc0: sdhci: Sys addr:  0x00000000 | Version:  0x00002202
mmc0: sdhci: Blk size:  0x00000008 | Blk cnt:  0x00000001
mmc0: sdhci: Argument:  0x00000000 | Trn mode: 0x00000013
mmc0: sdhci: Present:   0x01f50008 | Host ctl: 0x00000038
mmc0: sdhci: Power:     0x00000003 | Blk gap:  0x00000000
mmc0: sdhci: Wake-up:   0x00000000 | Clock:    0x000040d8
mmc0: sdhci: Timeout:   0x00000003 | Int stat: 0x00000001
mmc0: sdhci: Int enab:  0x037f108f | Sig enab: 0x037f108b
mmc0: sdhci: ACmd stat: 0x00000000 | Slot int: 0x00002202
mmc0: sdhci: Caps:      0x35fa0000 | Caps_1:   0x0000af00
mmc0: sdhci: Cmd:       0x0000333a | Max curr: 0x00000000
mmc0: sdhci: Resp[0]:   0x00000920 | Resp[1]:  0x001d8a33
mmc0: sdhci: Resp[2]:   0x325b5900 | Resp[3]:  0x3f400e00
mmc0: sdhci: Host ctl2: 0x00000000
mmc0: sdhci: ADMA Err:  0x00000009 | ADMA Ptr: 0x000000236d43820c
mmc0: sdhci: ============================================
mmc0: error -5 whilst initialising SD card

but can lead to other errors, and potentially direct the SDHCI
controller to read/write data to other memory locations (e.g. if a valid
descriptor is visible to the device in a stale cache line.)

Fix this by ensuring that the DMA snoop bit corresponds with the
behaviour of the DMA API.  Since the driver currently only supports DT,
use of_dma_is_coherent().  Note that device_get_dma_attr() can not be
used as that risks re-introducing this bug if/when the driver is
converted to ACPI.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci-of-esdhc.c

index 3271c2d766296c28b4174a1981b95dd83e08f382..1d1953dfc54b12136082a9c59bf242665526cfd4 100644 (file)
@@ -495,7 +495,12 @@ static int esdhc_of_enable_dma(struct sdhci_host *host)
                dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
 
        value = sdhci_readl(host, ESDHC_DMA_SYSCTL);
-       value |= ESDHC_DMA_SNOOP;
+
+       if (of_dma_is_coherent(dev->of_node))
+               value |= ESDHC_DMA_SNOOP;
+       else
+               value &= ~ESDHC_DMA_SNOOP;
+
        sdhci_writel(host, value, ESDHC_DMA_SYSCTL);
        return 0;
 }