diff options
author | Christoph Hellwig <hch@lst.de> | 2018-09-11 09:55:28 +0300 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2018-09-20 10:01:16 +0300 |
commit | 58b0440663ec11372befb8ead0ee7099d8878590 (patch) | |
tree | c613ed22ad229e6612d8c71888d2bb8139163ea8 /arch/mips/mm | |
parent | bc3ec75de5452db59b683487867ba562b950708a (diff) | |
download | linux-58b0440663ec11372befb8ead0ee7099d8878590.tar.xz |
dma-mapping: consolidate the dma mmap implementations
The only functional differences (modulo a few missing fixes in the arch
code) is that architectures without coherent caches need a hook to
convert a virtual or dma address into a pfn, given that we don't have
the kernel linear mapping available for the otherwise easy virt_to_page
call. As a side effect we can support mmap of the per-device coherent
area even on architectures not providing the callback, and we make
previous dangerous default methods dma_common_mmap actually save for
non-coherent architectures by rejecting it without the right helper.
In addition to that we need a hook so that some architectures can
override the protection bits when mmaping a dma coherent allocations.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Paul Burton <paul.burton@mips.com> # MIPS parts
Diffstat (limited to 'arch/mips/mm')
-rw-r--r-- | arch/mips/mm/dma-noncoherent.c | 32 |
1 files changed, 9 insertions, 23 deletions
diff --git a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c index b01b9a3e424f..e6c9485cadcf 100644 --- a/arch/mips/mm/dma-noncoherent.c +++ b/arch/mips/mm/dma-noncoherent.c @@ -66,33 +66,19 @@ void arch_dma_free(struct device *dev, size_t size, void *cpu_addr, dma_direct_free_pages(dev, size, cpu_addr, dma_addr, attrs); } -int arch_dma_mmap(struct device *dev, struct vm_area_struct *vma, - void *cpu_addr, dma_addr_t dma_addr, size_t size, - unsigned long attrs) +long arch_dma_coherent_to_pfn(struct device *dev, void *cpu_addr, + dma_addr_t dma_addr) { - unsigned long user_count = vma_pages(vma); - unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; unsigned long addr = CAC_ADDR((unsigned long)cpu_addr); - unsigned long off = vma->vm_pgoff; - unsigned long pfn = page_to_pfn(virt_to_page((void *)addr)); - int ret = -ENXIO; + return page_to_pfn(virt_to_page((void *)addr)); +} +pgprot_t arch_dma_mmap_pgprot(struct device *dev, pgprot_t prot, + unsigned long attrs) +{ if (attrs & DMA_ATTR_WRITE_COMBINE) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - else - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) - return ret; - - if (off < count && user_count <= (count - off)) { - ret = remap_pfn_range(vma, vma->vm_start, - pfn + off, - user_count << PAGE_SHIFT, - vma->vm_page_prot); - } - - return ret; + return pgprot_writecombine(prot); + return pgprot_noncached(prot); } static inline void dma_sync_virt(void *addr, size_t size, |