From a34a517ac96c6910a3a0aab9513035bfbed0020c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 20 Jan 2016 15:01:29 -0800 Subject: avr32: convert to dma_map_ops Signed-off-by: Christoph Hellwig Cc: Haavard Skinnemoen Cc: Hans-Christian Egtvedt Cc: Christian Borntraeger Cc: Joerg Roedel Cc: Sebastian Ott Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/avr32/mm/dma-coherent.c | 115 ++++++++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 35 deletions(-) (limited to 'arch/avr32/mm/dma-coherent.c') diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c index 50cdb5b10f0f..92cf1fb2b3e6 100644 --- a/arch/avr32/mm/dma-coherent.c +++ b/arch/avr32/mm/dma-coherent.c @@ -9,9 +9,14 @@ #include #include #include +#include +#include +#include -#include +#include #include +#include +#include void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction) { @@ -93,60 +98,100 @@ static void __dma_free(struct device *dev, size_t size, __free_page(page++); } -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t gfp) +static void *avr32_dma_alloc(struct device *dev, size_t size, + dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) { struct page *page; - void *ret = NULL; + dma_addr_t phys; page = __dma_alloc(dev, size, handle, gfp); - if (page) - ret = phys_to_uncached(page_to_phys(page)); + if (!page) + return NULL; + phys = page_to_phys(page); - return ret; + if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) { + /* Now, map the page into P3 with write-combining turned on */ + *handle = phys; + return __ioremap(phys, size, _PAGE_BUFFER); + } else { + return phys_to_uncached(phys); + } } -EXPORT_SYMBOL(dma_alloc_coherent); -void dma_free_coherent(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t handle) +static void avr32_dma_free(struct device *dev, size_t size, + void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs) { - void *addr = phys_to_cached(uncached_to_phys(cpu_addr)); struct page *page; - pr_debug("dma_free_coherent addr %p (phys %08lx) size %u\n", - cpu_addr, (unsigned long)handle, (unsigned)size); - BUG_ON(!virt_addr_valid(addr)); - page = virt_to_page(addr); + if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) { + iounmap(cpu_addr); + + page = phys_to_page(handle); + } else { + void *addr = phys_to_cached(uncached_to_phys(cpu_addr)); + + pr_debug("avr32_dma_free addr %p (phys %08lx) size %u\n", + cpu_addr, (unsigned long)handle, (unsigned)size); + + BUG_ON(!virt_addr_valid(addr)); + page = virt_to_page(addr); + } + __dma_free(dev, size, page, handle); } -EXPORT_SYMBOL(dma_free_coherent); -void *dma_alloc_writecombine(struct device *dev, size_t size, - dma_addr_t *handle, gfp_t gfp) +static dma_addr_t avr32_dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction, struct dma_attrs *attrs) { - struct page *page; - dma_addr_t phys; + void *cpu_addr = page_address(page) + offset; - page = __dma_alloc(dev, size, handle, gfp); - if (!page) - return NULL; + dma_cache_sync(dev, cpu_addr, size, direction); + return virt_to_bus(cpu_addr); +} - phys = page_to_phys(page); - *handle = phys; +static int avr32_dma_map_sg(struct device *dev, struct scatterlist *sglist, + int nents, enum dma_data_direction direction, + struct dma_attrs *attrs) +{ + int i; + struct scatterlist *sg; + + for_each_sg(sglist, sg, nents, i) { + char *virt; - /* Now, map the page into P3 with write-combining turned on */ - return __ioremap(phys, size, _PAGE_BUFFER); + sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset; + virt = sg_virt(sg); + dma_cache_sync(dev, virt, sg->length, direction); + } + + return nents; } -EXPORT_SYMBOL(dma_alloc_writecombine); -void dma_free_writecombine(struct device *dev, size_t size, - void *cpu_addr, dma_addr_t handle) +static void avr32_dma_sync_single_for_device(struct device *dev, + dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) { - struct page *page; + dma_cache_sync(dev, bus_to_virt(dma_handle), size, direction); +} - iounmap(cpu_addr); +static void avr32_dma_sync_sg_for_device(struct device *dev, + struct scatterlist *sglist, int nents, + enum dma_data_direction direction) +{ + int i; + struct scatterlist *sg; - page = phys_to_page(handle); - __dma_free(dev, size, page, handle); + for_each_sg(sglist, sg, nents, i) + dma_cache_sync(dev, sg_virt(sg), sg->length, direction); } -EXPORT_SYMBOL(dma_free_writecombine); + +struct dma_map_ops avr32_dma_ops = { + .alloc = avr32_dma_alloc, + .free = avr32_dma_free, + .map_page = avr32_dma_map_page, + .map_sg = avr32_dma_map_sg, + .sync_single_for_device = avr32_dma_sync_single_for_device, + .sync_sg_for_device = avr32_dma_sync_sg_for_device, +}; +EXPORT_SYMBOL(avr32_dma_ops); -- cgit v1.2.3