mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 06:34:12 +08:00
spi_imx: full duplex dma corruption bugfix
Fix unsafe order in dma mapping operation: always flush data from the cache *BEFORE* invalidating it, to allow full duplex transfers where the same buffer may be used for both writes and reads. Signed-off-by: Andrea Paterniani <a.paterniani@swapp-eng.it> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b3b4dc8840
commit
3b45d6380c
@ -506,20 +506,6 @@ static int map_dma_buffers(struct driver_data *drv_data)
|
||||
if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
|
||||
return -1;
|
||||
|
||||
/* NULL rx means write-only transfer and no map needed
|
||||
since rx DMA will not be used */
|
||||
if (drv_data->rx) {
|
||||
buf = drv_data->rx;
|
||||
drv_data->rx_dma = dma_map_single(
|
||||
dev,
|
||||
buf,
|
||||
drv_data->len,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dev, drv_data->rx_dma))
|
||||
return -1;
|
||||
drv_data->rx_dma_needs_unmap = 1;
|
||||
}
|
||||
|
||||
if (drv_data->tx == NULL) {
|
||||
/* Read only message --> use drv_data->dummy_dma_buf for dummy
|
||||
writes to achive reads */
|
||||
@ -533,18 +519,31 @@ static int map_dma_buffers(struct driver_data *drv_data)
|
||||
buf,
|
||||
drv_data->tx_map_len,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(dev, drv_data->tx_dma)) {
|
||||
if (drv_data->rx_dma) {
|
||||
dma_unmap_single(dev,
|
||||
drv_data->rx_dma,
|
||||
drv_data->len,
|
||||
DMA_FROM_DEVICE);
|
||||
drv_data->rx_dma_needs_unmap = 0;
|
||||
}
|
||||
if (dma_mapping_error(dev, drv_data->tx_dma))
|
||||
return -1;
|
||||
}
|
||||
drv_data->tx_dma_needs_unmap = 1;
|
||||
|
||||
/* NULL rx means write-only transfer and no map needed
|
||||
* since rx DMA will not be used */
|
||||
if (drv_data->rx) {
|
||||
buf = drv_data->rx;
|
||||
drv_data->rx_dma = dma_map_single(dev,
|
||||
buf,
|
||||
drv_data->len,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dev, drv_data->rx_dma)) {
|
||||
if (drv_data->tx_dma) {
|
||||
dma_unmap_single(dev,
|
||||
drv_data->tx_dma,
|
||||
drv_data->tx_map_len,
|
||||
DMA_TO_DEVICE);
|
||||
drv_data->tx_dma_needs_unmap = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
drv_data->rx_dma_needs_unmap = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user