spi: au1550_spi full duplex dma fix

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. Tested with mmc-spi.

Signed-off-by: Jan Nikitenko <jan.nikitenko@gmail.com>
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>

authored by Jan Nikitenko and committed by Linus Torvalds 4e253d23 6a010b56

+16 -10
+16 -10
drivers/spi/au1550_spi.c
··· 369 369 dma_rx_addr = t->rx_dma; 370 370 371 371 /* 372 - * check if buffers are already dma mapped, map them otherwise 372 + * check if buffers are already dma mapped, map them otherwise: 373 + * - first map the TX buffer, so cache data gets written to memory 374 + * - then map the RX buffer, so that cache entries (with 375 + * soon-to-be-stale data) get removed 373 376 * use rx buffer in place of tx if tx buffer was not provided 374 377 * use temp rx buffer (preallocated or realloc to fit) for rx dma 375 378 */ 379 + if (t->tx_buf) { 380 + if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */ 381 + dma_tx_addr = dma_map_single(hw->dev, 382 + (void *)t->tx_buf, 383 + t->len, DMA_TO_DEVICE); 384 + if (dma_mapping_error(hw->dev, dma_tx_addr)) 385 + dev_err(hw->dev, "tx dma map error\n"); 386 + } 387 + } 388 + 376 389 if (t->rx_buf) { 377 390 if (t->rx_dma == 0) { /* if DMA_ADDR_INVALID, map it */ 378 391 dma_rx_addr = dma_map_single(hw->dev, ··· 409 396 dma_sync_single_for_device(hw->dev, dma_rx_addr, 410 397 t->len, DMA_FROM_DEVICE); 411 398 } 412 - if (t->tx_buf) { 413 - if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */ 414 - dma_tx_addr = dma_map_single(hw->dev, 415 - (void *)t->tx_buf, 416 - t->len, DMA_TO_DEVICE); 417 - if (dma_mapping_error(hw->dev, dma_tx_addr)) 418 - dev_err(hw->dev, "tx dma map error\n"); 419 - } 420 - } else { 399 + 400 + if (!t->tx_buf) { 421 401 dma_sync_single_for_device(hw->dev, dma_rx_addr, 422 402 t->len, DMA_BIDIRECTIONAL); 423 403 hw->tx = hw->rx;