Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: atmel: fix corrupted data issue on SAM9 family SoCs

This patch disables the use of the DMA for data transfer and forces the
use of PIO transfers instead as a quick fixup to solve the cache aliasing
issue on ARM9 based cores, which embeds a VIVT data cache.

Indeed in the case of VIVT data caches, it is not safe to call dma_map_*()
functions to map buffers for DMA transfers when those buffers have been
allocated by vmalloc() or from any DMA-unsafe area.

Further patches may propose a better solution based on the use of a bounce
buffer at the SPI sub-system level but such solution needs more time to be
discussed. Then the use of DMA transfers could be enabled again to improve
the performances but before that, this patch already solves the issue.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@microchip.com>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org

authored by

Cyrille Pitchen and committed by
Mark Brown
7094576c 2ea659a9

+23 -1
+23 -1
drivers/spi/spi-atmel.c
··· 269 269 bool is_spi2; 270 270 bool has_wdrbt; 271 271 bool has_dma_support; 272 + bool has_pdc_support; 272 273 }; 273 274 274 275 /* ··· 1427 1426 1428 1427 as->caps.is_spi2 = version > 0x121; 1429 1428 as->caps.has_wdrbt = version >= 0x210; 1429 + #ifdef CONFIG_SOC_SAM_V4_V5 1430 + /* 1431 + * Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf() 1432 + * since this later function tries to map buffers with dma_map_sg() 1433 + * even if they have not been allocated inside DMA-safe areas. 1434 + * On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for 1435 + * those ARM cores, the data cache follows the PIPT model. 1436 + * Also the L2 cache controller of SAMA5D2 uses the PIPT model too. 1437 + * In case of PIPT caches, there cannot be cache aliases. 1438 + * However on ARM9 cores, the data cache follows the VIVT model, hence 1439 + * the cache aliases issue can occur when buffers are allocated from 1440 + * DMA-unsafe areas, by vmalloc() for instance, where cache coherency is 1441 + * not taken into account or at least not handled completely (cache 1442 + * lines of aliases are not invalidated). 1443 + * This is not a theorical issue: it was reproduced when trying to mount 1444 + * a UBI file-system on a at91sam9g35ek board. 1445 + */ 1446 + as->caps.has_dma_support = false; 1447 + #else 1430 1448 as->caps.has_dma_support = version >= 0x212; 1449 + #endif 1450 + as->caps.has_pdc_support = version < 0x212; 1431 1451 } 1432 1452 1433 1453 /*-------------------------------------------------------------------------*/ ··· 1589 1567 } else if (ret == -EPROBE_DEFER) { 1590 1568 return ret; 1591 1569 } 1592 - } else { 1570 + } else if (as->caps.has_pdc_support) { 1593 1571 as->use_pdc = true; 1594 1572 } 1595 1573