sh: Add SH-5 support to the consistent DMA impl.
authorPaul Mundt <lethal@linux-sh.org>
Sun, 11 Nov 2007 08:07:06 +0000 (17:07 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 28 Jan 2008 04:18:44 +0000 (13:18 +0900)
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/mm/consistent.c
include/asm-sh/dma-mapping.h

index e220c29..65ad300 100644 (file)
@@ -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);
-
index fcea067..20ae762 100644 (file)
@@ -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)