aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/dma-swiotlb.c10
-rw-r--r--lib/swiotlb.c41
2 files changed, 23 insertions, 28 deletions
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index 68ccf11e4f19..41534ae2f589 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -24,16 +24,6 @@
24int swiotlb __read_mostly; 24int swiotlb __read_mostly;
25unsigned int ppc_swiotlb_enable; 25unsigned int ppc_swiotlb_enable;
26 26
27void *swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t addr)
28{
29 unsigned long pfn = PFN_DOWN(swiotlb_bus_to_phys(hwdev, addr));
30 void *pageaddr = page_address(pfn_to_page(pfn));
31
32 if (pageaddr != NULL)
33 return pageaddr + (addr % PAGE_SIZE);
34 return NULL;
35}
36
37dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr) 27dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
38{ 28{
39 return paddr + get_dma_direct_offset(hwdev); 29 return paddr + get_dma_direct_offset(hwdev);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index dc1cd1f5369e..cba3db809fbc 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -124,17 +124,13 @@ phys_addr_t __weak swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
124 return baddr; 124 return baddr;
125} 125}
126 126
127/* Note that this doesn't work with highmem page */
127static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, 128static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
128 volatile void *address) 129 volatile void *address)
129{ 130{
130 return swiotlb_phys_to_bus(hwdev, virt_to_phys(address)); 131 return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
131} 132}
132 133
133void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
134{
135 return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
136}
137
138int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev, 134int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
139 dma_addr_t addr, size_t size) 135 dma_addr_t addr, size_t size)
140{ 136{
@@ -307,9 +303,10 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t size)
307 return swiotlb_arch_address_needs_mapping(hwdev, addr, size); 303 return swiotlb_arch_address_needs_mapping(hwdev, addr, size);
308} 304}
309 305
310static int is_swiotlb_buffer(char *addr) 306static int is_swiotlb_buffer(phys_addr_t paddr)
311{ 307{
312 return addr >= io_tlb_start && addr < io_tlb_end; 308 return paddr >= virt_to_phys(io_tlb_start) &&
309 paddr < virt_to_phys(io_tlb_end);
313} 310}
314 311
315/* 312/*
@@ -582,11 +579,13 @@ EXPORT_SYMBOL(swiotlb_alloc_coherent);
582 579
583void 580void
584swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, 581swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
585 dma_addr_t dma_handle) 582 dma_addr_t dev_addr)
586{ 583{
584 phys_addr_t paddr = swiotlb_bus_to_phys(hwdev, dev_addr);
585
587 WARN_ON(irqs_disabled()); 586 WARN_ON(irqs_disabled());
588 if (!is_swiotlb_buffer(vaddr)) 587 if (!is_swiotlb_buffer(paddr))
589 free_pages((unsigned long) vaddr, get_order(size)); 588 free_pages((unsigned long)vaddr, get_order(size));
590 else 589 else
591 /* DMA_TO_DEVICE to avoid memcpy in unmap_single */ 590 /* DMA_TO_DEVICE to avoid memcpy in unmap_single */
592 do_unmap_single(hwdev, vaddr, size, DMA_TO_DEVICE); 591 do_unmap_single(hwdev, vaddr, size, DMA_TO_DEVICE);
@@ -671,19 +670,25 @@ EXPORT_SYMBOL_GPL(swiotlb_map_page);
671static void unmap_single(struct device *hwdev, dma_addr_t dev_addr, 670static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
672 size_t size, int dir) 671 size_t size, int dir)
673{ 672{
674 char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr); 673 phys_addr_t paddr = swiotlb_bus_to_phys(hwdev, dev_addr);
675 674
676 BUG_ON(dir == DMA_NONE); 675 BUG_ON(dir == DMA_NONE);
677 676
678 if (is_swiotlb_buffer(dma_addr)) { 677 if (is_swiotlb_buffer(paddr)) {
679 do_unmap_single(hwdev, dma_addr, size, dir); 678 do_unmap_single(hwdev, phys_to_virt(paddr), size, dir);
680 return; 679 return;
681 } 680 }
682 681
683 if (dir != DMA_FROM_DEVICE) 682 if (dir != DMA_FROM_DEVICE)
684 return; 683 return;
685 684
686 dma_mark_clean(dma_addr, size); 685 /*
686 * phys_to_virt doesn't work with hihgmem page but we could
687 * call dma_mark_clean() with hihgmem page here. However, we
688 * are fine since dma_mark_clean() is null on POWERPC. We can
689 * make dma_mark_clean() take a physical address if necessary.
690 */
691 dma_mark_clean(phys_to_virt(paddr), size);
687} 692}
688 693
689void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, 694void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
@@ -708,19 +713,19 @@ static void
708swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, 713swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
709 size_t size, int dir, int target) 714 size_t size, int dir, int target)
710{ 715{
711 char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr); 716 phys_addr_t paddr = swiotlb_bus_to_phys(hwdev, dev_addr);
712 717
713 BUG_ON(dir == DMA_NONE); 718 BUG_ON(dir == DMA_NONE);
714 719
715 if (is_swiotlb_buffer(dma_addr)) { 720 if (is_swiotlb_buffer(paddr)) {
716 sync_single(hwdev, dma_addr, size, dir, target); 721 sync_single(hwdev, phys_to_virt(paddr), size, dir, target);
717 return; 722 return;
718 } 723 }
719 724
720 if (dir != DMA_FROM_DEVICE) 725 if (dir != DMA_FROM_DEVICE)
721 return; 726 return;
722 727
723 dma_mark_clean(dma_addr, size); 728 dma_mark_clean(phys_to_virt(paddr), size);
724} 729}
725 730
726void 731void