diff options
| -rw-r--r-- | arch/arm/mm/cache-v6.S | 10 | ||||
| -rw-r--r-- | arch/arm/mm/cache-v7.S | 10 | ||||
| -rw-r--r-- | arch/arm/mm/dma-mapping.c | 68 |
3 files changed, 42 insertions, 46 deletions
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index a11934e53fbd..9d89c67a1cc3 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S | |||
| @@ -271,10 +271,9 @@ ENTRY(v6_dma_flush_range) | |||
| 271 | */ | 271 | */ |
| 272 | ENTRY(v6_dma_map_area) | 272 | ENTRY(v6_dma_map_area) |
| 273 | add r1, r1, r0 | 273 | add r1, r1, r0 |
| 274 | cmp r2, #DMA_TO_DEVICE | 274 | teq r2, #DMA_FROM_DEVICE |
| 275 | beq v6_dma_clean_range | 275 | beq v6_dma_inv_range |
| 276 | bcs v6_dma_inv_range | 276 | b v6_dma_clean_range |
| 277 | b v6_dma_flush_range | ||
| 278 | ENDPROC(v6_dma_map_area) | 277 | ENDPROC(v6_dma_map_area) |
| 279 | 278 | ||
| 280 | /* | 279 | /* |
| @@ -284,6 +283,9 @@ ENDPROC(v6_dma_map_area) | |||
| 284 | * - dir - DMA direction | 283 | * - dir - DMA direction |
| 285 | */ | 284 | */ |
| 286 | ENTRY(v6_dma_unmap_area) | 285 | ENTRY(v6_dma_unmap_area) |
| 286 | add r1, r1, r0 | ||
| 287 | teq r2, #DMA_TO_DEVICE | ||
| 288 | bne v6_dma_inv_range | ||
| 287 | mov pc, lr | 289 | mov pc, lr |
| 288 | ENDPROC(v6_dma_unmap_area) | 290 | ENDPROC(v6_dma_unmap_area) |
| 289 | 291 | ||
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index b1cd0fd91207..bcd64f265870 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S | |||
| @@ -279,10 +279,9 @@ ENDPROC(v7_dma_flush_range) | |||
| 279 | */ | 279 | */ |
| 280 | ENTRY(v7_dma_map_area) | 280 | ENTRY(v7_dma_map_area) |
| 281 | add r1, r1, r0 | 281 | add r1, r1, r0 |
| 282 | cmp r2, #DMA_TO_DEVICE | 282 | teq r2, #DMA_FROM_DEVICE |
| 283 | beq v7_dma_clean_range | 283 | beq v7_dma_inv_range |
| 284 | bcs v7_dma_inv_range | 284 | b v7_dma_clean_range |
| 285 | b v7_dma_flush_range | ||
| 286 | ENDPROC(v7_dma_map_area) | 285 | ENDPROC(v7_dma_map_area) |
| 287 | 286 | ||
| 288 | /* | 287 | /* |
| @@ -292,6 +291,9 @@ ENDPROC(v7_dma_map_area) | |||
| 292 | * - dir - DMA direction | 291 | * - dir - DMA direction |
| 293 | */ | 292 | */ |
| 294 | ENTRY(v7_dma_unmap_area) | 293 | ENTRY(v7_dma_unmap_area) |
| 294 | add r1, r1, r0 | ||
| 295 | teq r2, #DMA_TO_DEVICE | ||
| 296 | bne v7_dma_inv_range | ||
| 295 | mov pc, lr | 297 | mov pc, lr |
| 296 | ENDPROC(v7_dma_unmap_area) | 298 | ENDPROC(v7_dma_unmap_area) |
| 297 | 299 | ||
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index efa8efa33f5e..64daef2173bd 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
| @@ -404,34 +404,22 @@ EXPORT_SYMBOL(dma_free_coherent); | |||
| 404 | * platforms with CONFIG_DMABOUNCE. | 404 | * platforms with CONFIG_DMABOUNCE. |
| 405 | * Use the driver DMA support - see dma-mapping.h (dma_sync_*) | 405 | * Use the driver DMA support - see dma-mapping.h (dma_sync_*) |
| 406 | */ | 406 | */ |
| 407 | static void dma_cache_maint(const void *start, size_t size, int direction) | ||
| 408 | { | ||
| 409 | void (*outer_op)(unsigned long, unsigned long); | ||
| 410 | |||
| 411 | switch (direction) { | ||
| 412 | case DMA_FROM_DEVICE: /* invalidate only */ | ||
| 413 | outer_op = outer_inv_range; | ||
| 414 | break; | ||
| 415 | case DMA_TO_DEVICE: /* writeback only */ | ||
| 416 | outer_op = outer_clean_range; | ||
| 417 | break; | ||
| 418 | case DMA_BIDIRECTIONAL: /* writeback and invalidate */ | ||
| 419 | outer_op = outer_flush_range; | ||
| 420 | break; | ||
| 421 | default: | ||
| 422 | BUG(); | ||
| 423 | } | ||
| 424 | |||
| 425 | outer_op(__pa(start), __pa(start) + size); | ||
| 426 | } | ||
| 427 | |||
| 428 | void ___dma_single_cpu_to_dev(const void *kaddr, size_t size, | 407 | void ___dma_single_cpu_to_dev(const void *kaddr, size_t size, |
| 429 | enum dma_data_direction dir) | 408 | enum dma_data_direction dir) |
| 430 | { | 409 | { |
| 410 | unsigned long paddr; | ||
| 411 | |||
| 431 | BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1)); | 412 | BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1)); |
| 432 | 413 | ||
| 433 | dmac_map_area(kaddr, size, dir); | 414 | dmac_map_area(kaddr, size, dir); |
| 434 | dma_cache_maint(kaddr, size, dir); | 415 | |
| 416 | paddr = __pa(kaddr); | ||
| 417 | if (dir == DMA_FROM_DEVICE) { | ||
| 418 | outer_inv_range(paddr, paddr + size); | ||
| 419 | } else { | ||
| 420 | outer_clean_range(paddr, paddr + size); | ||
| 421 | } | ||
| 422 | /* FIXME: non-speculating: flush on bidirectional mappings? */ | ||
| 435 | } | 423 | } |
| 436 | EXPORT_SYMBOL(___dma_single_cpu_to_dev); | 424 | EXPORT_SYMBOL(___dma_single_cpu_to_dev); |
| 437 | 425 | ||
| @@ -440,6 +428,13 @@ void ___dma_single_dev_to_cpu(const void *kaddr, size_t size, | |||
| 440 | { | 428 | { |
| 441 | BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1)); | 429 | BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1)); |
| 442 | 430 | ||
| 431 | /* FIXME: non-speculating: not required */ | ||
| 432 | /* don't bother invalidating if DMA to device */ | ||
| 433 | if (dir != DMA_TO_DEVICE) { | ||
| 434 | unsigned long paddr = __pa(kaddr); | ||
| 435 | outer_inv_range(paddr, paddr + size); | ||
| 436 | } | ||
| 437 | |||
| 443 | dmac_unmap_area(kaddr, size, dir); | 438 | dmac_unmap_area(kaddr, size, dir); |
| 444 | } | 439 | } |
| 445 | EXPORT_SYMBOL(___dma_single_dev_to_cpu); | 440 | EXPORT_SYMBOL(___dma_single_dev_to_cpu); |
| @@ -487,32 +482,29 @@ void ___dma_page_cpu_to_dev(struct page *page, unsigned long off, | |||
| 487 | size_t size, enum dma_data_direction dir) | 482 | size_t size, enum dma_data_direction dir) |
| 488 | { | 483 | { |
| 489 | unsigned long paddr; | 484 | unsigned long paddr; |
| 490 | void (*outer_op)(unsigned long, unsigned long); | ||
| 491 | |||
| 492 | switch (direction) { | ||
| 493 | case DMA_FROM_DEVICE: /* invalidate only */ | ||
| 494 | outer_op = outer_inv_range; | ||
| 495 | break; | ||
| 496 | case DMA_TO_DEVICE: /* writeback only */ | ||
| 497 | outer_op = outer_clean_range; | ||
| 498 | break; | ||
| 499 | case DMA_BIDIRECTIONAL: /* writeback and invalidate */ | ||
| 500 | outer_op = outer_flush_range; | ||
| 501 | break; | ||
| 502 | default: | ||
| 503 | BUG(); | ||
| 504 | } | ||
| 505 | 485 | ||
| 506 | dma_cache_maint_page(page, off, size, dir, dmac_map_area); | 486 | dma_cache_maint_page(page, off, size, dir, dmac_map_area); |
| 507 | 487 | ||
| 508 | paddr = page_to_phys(page) + off; | 488 | paddr = page_to_phys(page) + off; |
| 509 | outer_op(paddr, paddr + size); | 489 | if (dir == DMA_FROM_DEVICE) { |
| 490 | outer_inv_range(paddr, paddr + size); | ||
| 491 | } else { | ||
| 492 | outer_clean_range(paddr, paddr + size); | ||
| 493 | } | ||
| 494 | /* FIXME: non-speculating: flush on bidirectional mappings? */ | ||
| 510 | } | 495 | } |
| 511 | EXPORT_SYMBOL(___dma_page_cpu_to_dev); | 496 | EXPORT_SYMBOL(___dma_page_cpu_to_dev); |
| 512 | 497 | ||
| 513 | void ___dma_page_dev_to_cpu(struct page *page, unsigned long off, | 498 | void ___dma_page_dev_to_cpu(struct page *page, unsigned long off, |
| 514 | size_t size, enum dma_data_direction dir) | 499 | size_t size, enum dma_data_direction dir) |
| 515 | { | 500 | { |
| 501 | unsigned long paddr = page_to_phys(page) + off; | ||
| 502 | |||
| 503 | /* FIXME: non-speculating: not required */ | ||
| 504 | /* don't bother invalidating if DMA to device */ | ||
| 505 | if (dir != DMA_TO_DEVICE) | ||
| 506 | outer_inv_range(paddr, paddr + size); | ||
| 507 | |||
| 516 | dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); | 508 | dma_cache_maint_page(page, off, size, dir, dmac_unmap_area); |
| 517 | } | 509 | } |
| 518 | EXPORT_SYMBOL(___dma_page_dev_to_cpu); | 510 | EXPORT_SYMBOL(___dma_page_dev_to_cpu); |
