diff options
author | Jonas Bonn <jonas@southpole.se> | 2012-04-15 21:09:25 +0200 |
---|---|---|
committer | Jonas Bonn <jonas@southpole.se> | 2012-05-08 11:43:51 +0200 |
commit | 7b903e6c021a5462e26ea7a8f014fa60b6782bdb (patch) | |
tree | 47bf29fa57bff2cd3940beeeace93e1da1d5cee6 /arch/openrisc/kernel | |
parent | b0e026f4dc118752382fa926431b4512a8042e09 (diff) |
openrisc: provide dma_map_ops
This switches OpenRISC over to fully using the generic dma-mapping
framework. This was almost already the case as the architecture's
implementation was essentially a copy of the generic header.
This also brings this architecture in line with the recent changes
to dma_map_ops (adding attributes to ops->alloc).
Signed-off-by: Jonas Bonn <jonas@southpole.se>
Diffstat (limited to 'arch/openrisc/kernel')
-rw-r--r-- | arch/openrisc/kernel/dma.c | 109 |
1 files changed, 73 insertions, 36 deletions
diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c index f1c8ee2895d0..0b77ddb1ee07 100644 --- a/arch/openrisc/kernel/dma.c +++ b/arch/openrisc/kernel/dma.c @@ -21,13 +21,16 @@ #include <linux/dma-mapping.h> #include <linux/dma-debug.h> +#include <linux/export.h> +#include <linux/dma-attrs.h> #include <asm/cpuinfo.h> #include <asm/spr_defs.h> #include <asm/tlbflush.h> -static int page_set_nocache(pte_t *pte, unsigned long addr, - unsigned long next, struct mm_walk *walk) +static int +page_set_nocache(pte_t *pte, unsigned long addr, + unsigned long next, struct mm_walk *walk) { unsigned long cl; @@ -46,8 +49,9 @@ static int page_set_nocache(pte_t *pte, unsigned long addr, return 0; } -static int page_clear_nocache(pte_t *pte, unsigned long addr, - unsigned long next, struct mm_walk *walk) +static int +page_clear_nocache(pte_t *pte, unsigned long addr, + unsigned long next, struct mm_walk *walk) { pte_val(*pte) &= ~_PAGE_CI; @@ -67,9 +71,19 @@ static int page_clear_nocache(pte_t *pte, unsigned long addr, * cache-inhibit bit on those pages, and makes sure that the pages are * flushed out of the cache before they are used. * + * If the NON_CONSISTENT attribute is set, then this function just + * returns "normal", cachable memory. + * + * There are additional flags WEAK_ORDERING and WRITE_COMBINE to take + * into consideration here, too. All current known implementations of + * the OR1K support only strongly ordered memory accesses, so that flag + * is being ignored for now; uncached but write-combined memory is a + * missing feature of the OR1K. */ -void *or1k_dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp) +static void * +or1k_dma_alloc(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, + struct dma_attrs *attrs) { unsigned long va; void *page; @@ -87,20 +101,23 @@ void *or1k_dma_alloc_coherent(struct device *dev, size_t size, va = (unsigned long)page; - /* - * We need to iterate through the pages, clearing the dcache for - * them and setting the cache-inhibit bit. - */ - if (walk_page_range(va, va + size, &walk)) { - free_pages_exact(page, size); - return NULL; + if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) { + /* + * We need to iterate through the pages, clearing the dcache for + * them and setting the cache-inhibit bit. + */ + if (walk_page_range(va, va + size, &walk)) { + free_pages_exact(page, size); + return NULL; + } } return (void *)va; } -void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr, - dma_addr_t dma_handle) +static void +or1k_dma_free(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle, struct dma_attrs *attrs) { unsigned long va = (unsigned long)vaddr; struct mm_walk walk = { @@ -108,16 +125,19 @@ void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr, .mm = &init_mm }; - /* walk_page_range shouldn't be able to fail here */ - WARN_ON(walk_page_range(va, va + size, &walk)); + if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) { + /* walk_page_range shouldn't be able to fail here */ + WARN_ON(walk_page_range(va, va + size, &walk)); + } free_pages_exact(vaddr, size); } -dma_addr_t or1k_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir, - struct dma_attrs *attrs) +static dma_addr_t +or1k_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs) { unsigned long cl; dma_addr_t addr = page_to_phys(page) + offset; @@ -147,16 +167,18 @@ dma_addr_t or1k_map_page(struct device *dev, struct page *page, return addr; } -void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction dir, - struct dma_attrs *attrs) +static void +or1k_unmap_page(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction dir, + struct dma_attrs *attrs) { /* Nothing special to do here... */ } -int or1k_map_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir, - struct dma_attrs *attrs) +static int +or1k_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs) { struct scatterlist *s; int i; @@ -169,9 +191,10 @@ int or1k_map_sg(struct device *dev, struct scatterlist *sg, return nents; } -void or1k_unmap_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir, - struct dma_attrs *attrs) +static void +or1k_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs) { struct scatterlist *s; int i; @@ -181,9 +204,10 @@ void or1k_unmap_sg(struct device *dev, struct scatterlist *sg, } } -void or1k_sync_single_for_cpu(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) +static void +or1k_sync_single_for_cpu(struct device *dev, + dma_addr_t dma_handle, size_t size, + enum dma_data_direction dir) { unsigned long cl; dma_addr_t addr = dma_handle; @@ -193,9 +217,10 @@ void or1k_sync_single_for_cpu(struct device *dev, mtspr(SPR_DCBIR, cl); } -void or1k_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) +static void +or1k_sync_single_for_device(struct device *dev, + dma_addr_t dma_handle, size_t size, + enum dma_data_direction dir) { unsigned long cl; dma_addr_t addr = dma_handle; @@ -205,6 +230,18 @@ void or1k_sync_single_for_device(struct device *dev, mtspr(SPR_DCBFR, cl); } +struct dma_map_ops or1k_dma_map_ops = { + .alloc = or1k_dma_alloc, + .free = or1k_dma_free, + .map_page = or1k_map_page, + .unmap_page = or1k_unmap_page, + .map_sg = or1k_map_sg, + .unmap_sg = or1k_unmap_sg, + .sync_single_for_cpu = or1k_sync_single_for_cpu, + .sync_single_for_device = or1k_sync_single_for_device, +}; +EXPORT_SYMBOL(or1k_dma_map_ops); + /* Number of entries preallocated for DMA-API debugging */ #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) |