diff options
-rw-r--r-- | arch/sh/mm/consistent.c | 46 | ||||
-rw-r--r-- | include/asm-sh/dma-mapping.h | 4 |
2 files changed, 30 insertions, 20 deletions
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index e220c29a3c00..65ad30031ad7 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -1,7 +1,7 @@ /* * arch/sh/mm/consistent.c * - * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004 - 2007 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -16,7 +16,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle) { struct page *page, *end, *free; - void *ret; + void *ret, *vp; int order; size = PAGE_ALIGN(size); @@ -28,13 +28,20 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle) split_page(page, order); ret = page_address(page); - memset(ret, 0, size); *handle = virt_to_phys(ret); + vp = ioremap_nocache(*handle, size); + if (!vp) { + free_pages((unsigned long)ret, order); + return NULL; + } + + memset(vp, 0, size); + /* * We must flush the cache before we pass it on to the device */ - __flush_purge_region(ret, size); + dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL); page = virt_to_page(ret); free = page + (size >> PAGE_SHIFT); @@ -47,24 +54,31 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle) } } - return P2SEGADDR(ret); + return vp; } +EXPORT_SYMBOL(consistent_alloc); -void consistent_free(void *vaddr, size_t size) +void consistent_free(void *vaddr, size_t size, dma_addr_t dma_handle) { - unsigned long addr = P1SEGADDR((unsigned long)vaddr); - struct page *page=virt_to_page(addr); - int num_pages=(size+PAGE_SIZE-1) >> PAGE_SHIFT; - int i; + struct page *page; + unsigned long addr; - for(i=0;i<num_pages;i++) { - __free_page((page+i)); - } + addr = (unsigned long)phys_to_virt((unsigned long)dma_handle); + page = virt_to_page(addr); + + free_pages(addr, get_order(size)); + + iounmap(vaddr); } +EXPORT_SYMBOL(consistent_free); void consistent_sync(void *vaddr, size_t size, int direction) { - void * p1addr = (void*) P1SEGADDR((unsigned long)vaddr); +#ifdef CONFIG_CPU_SH5 + void *p1addr = vaddr; +#else + void *p1addr = (void*) P1SEGADDR((unsigned long)vaddr); +#endif switch (direction) { case DMA_FROM_DEVICE: /* invalidate only */ @@ -80,8 +94,4 @@ void consistent_sync(void *vaddr, size_t size, int direction) BUG(); } } - -EXPORT_SYMBOL(consistent_alloc); -EXPORT_SYMBOL(consistent_free); EXPORT_SYMBOL(consistent_sync); - diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h index fcea067f7a9c..20ae762e5258 100644 --- a/include/asm-sh/dma-mapping.h +++ b/include/asm-sh/dma-mapping.h @@ -10,7 +10,7 @@ extern struct bus_type pci_bus_type; /* arch/sh/mm/consistent.c */ extern void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle); -extern void consistent_free(void *vaddr, size_t size); +extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle); extern void consistent_sync(void *vaddr, size_t size, int direction); #define dma_supported(dev, mask) (1) @@ -50,7 +50,7 @@ static inline void dma_free_coherent(struct device *dev, size_t size, return; } - consistent_free(vaddr, size); + consistent_free(vaddr, size, dma_handle); } #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) |