diff options
author | Michael Hennerich <michael.hennerich@analog.com> | 2010-06-16 05:12:10 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-08-06 12:55:50 -0400 |
commit | d1401e1dc22606a91f577ad3dfd68ae7e60e0357 (patch) | |
tree | 6c59463c60fd4ada2b5d4974afaa30be7059c67f /arch/blackfin/kernel | |
parent | 502c8a0e07450ff886b80a11150a123bae92f3f7 (diff) |
Blackfin: fix DMA/cache bug when resuming from suspend to RAM
The dma_memcpy() function takes care of flushing different caches for us.
Normally this is what we want, but when resuming from mem, we don't yet
have caches enabled. If these functions happen to be placed into L1 mem
(which is what we're trying to relocate), then things aren't going to
work. So define a non-cache dma_memcpy() variant to utilize in situations
like this.
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/bfin_dma_5xx.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 26403d1c9e65..1e485dfdc9f2 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c | |||
@@ -450,7 +450,6 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size) | |||
450 | { | 450 | { |
451 | unsigned long dst = (unsigned long)pdst; | 451 | unsigned long dst = (unsigned long)pdst; |
452 | unsigned long src = (unsigned long)psrc; | 452 | unsigned long src = (unsigned long)psrc; |
453 | size_t bulk, rest; | ||
454 | 453 | ||
455 | if (bfin_addr_dcacheable(src)) | 454 | if (bfin_addr_dcacheable(src)) |
456 | blackfin_dcache_flush_range(src, src + size); | 455 | blackfin_dcache_flush_range(src, src + size); |
@@ -458,6 +457,22 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size) | |||
458 | if (bfin_addr_dcacheable(dst)) | 457 | if (bfin_addr_dcacheable(dst)) |
459 | blackfin_dcache_invalidate_range(dst, dst + size); | 458 | blackfin_dcache_invalidate_range(dst, dst + size); |
460 | 459 | ||
460 | return dma_memcpy_nocache(pdst, psrc, size); | ||
461 | } | ||
462 | EXPORT_SYMBOL(dma_memcpy); | ||
463 | |||
464 | /** | ||
465 | * dma_memcpy_nocache - DMA memcpy under mutex lock | ||
466 | * - No cache flush/invalidate | ||
467 | * | ||
468 | * Do not check arguments before starting the DMA memcpy. Break the transfer | ||
469 | * up into two pieces. The first transfer is in multiples of 64k and the | ||
470 | * second transfer is the piece smaller than 64k. | ||
471 | */ | ||
472 | void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size) | ||
473 | { | ||
474 | size_t bulk, rest; | ||
475 | |||
461 | bulk = size & ~0xffff; | 476 | bulk = size & ~0xffff; |
462 | rest = size - bulk; | 477 | rest = size - bulk; |
463 | if (bulk) | 478 | if (bulk) |
@@ -465,7 +480,7 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size) | |||
465 | _dma_memcpy(pdst + bulk, psrc + bulk, rest); | 480 | _dma_memcpy(pdst + bulk, psrc + bulk, rest); |
466 | return pdst; | 481 | return pdst; |
467 | } | 482 | } |
468 | EXPORT_SYMBOL(dma_memcpy); | 483 | EXPORT_SYMBOL(dma_memcpy_nocache); |
469 | 484 | ||
470 | /** | 485 | /** |
471 | * safe_dma_memcpy - DMA memcpy w/argument checking | 486 | * safe_dma_memcpy - DMA memcpy w/argument checking |