aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2007-11-11 03:07:06 -0500
committerPaul Mundt <lethal@linux-sh.org>2008-01-27 23:18:44 -0500
commit8a7bcf0dd0d49fe8b0071adef0dfe8610abdffaa (patch)
treee8f0875c391fa2c2d96746112d841c8ca48d1307 /arch/sh/mm
parentb613881ead41c8fc2e1413aeb6ef8f021f00c1e7 (diff)
sh: Add SH-5 support to the consistent DMA impl.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm')
-rw-r--r--arch/sh/mm/consistent.c46
1 files changed, 28 insertions, 18 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 @@
1/* 1/*
2 * arch/sh/mm/consistent.c 2 * arch/sh/mm/consistent.c
3 * 3 *
4 * Copyright (C) 2004 Paul Mundt 4 * Copyright (C) 2004 - 2007 Paul Mundt
5 * 5 *
6 * This file is subject to the terms and conditions of the GNU General Public 6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive 7 * License. See the file "COPYING" in the main directory of this archive
@@ -16,7 +16,7 @@
16void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle) 16void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
17{ 17{
18 struct page *page, *end, *free; 18 struct page *page, *end, *free;
19 void *ret; 19 void *ret, *vp;
20 int order; 20 int order;
21 21
22 size = PAGE_ALIGN(size); 22 size = PAGE_ALIGN(size);
@@ -28,13 +28,20 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
28 split_page(page, order); 28 split_page(page, order);
29 29
30 ret = page_address(page); 30 ret = page_address(page);
31 memset(ret, 0, size);
32 *handle = virt_to_phys(ret); 31 *handle = virt_to_phys(ret);
33 32
33 vp = ioremap_nocache(*handle, size);
34 if (!vp) {
35 free_pages((unsigned long)ret, order);
36 return NULL;
37 }
38
39 memset(vp, 0, size);
40
34 /* 41 /*
35 * We must flush the cache before we pass it on to the device 42 * We must flush the cache before we pass it on to the device
36 */ 43 */
37 __flush_purge_region(ret, size); 44 dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL);
38 45
39 page = virt_to_page(ret); 46 page = virt_to_page(ret);
40 free = page + (size >> PAGE_SHIFT); 47 free = page + (size >> PAGE_SHIFT);
@@ -47,24 +54,31 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
47 } 54 }
48 } 55 }
49 56
50 return P2SEGADDR(ret); 57 return vp;
51} 58}
59EXPORT_SYMBOL(consistent_alloc);
52 60
53void consistent_free(void *vaddr, size_t size) 61void consistent_free(void *vaddr, size_t size, dma_addr_t dma_handle)
54{ 62{
55 unsigned long addr = P1SEGADDR((unsigned long)vaddr); 63 struct page *page;
56 struct page *page=virt_to_page(addr); 64 unsigned long addr;
57 int num_pages=(size+PAGE_SIZE-1) >> PAGE_SHIFT;
58 int i;
59 65
60 for(i=0;i<num_pages;i++) { 66 addr = (unsigned long)phys_to_virt((unsigned long)dma_handle);
61 __free_page((page+i)); 67 page = virt_to_page(addr);
62 } 68
69 free_pages(addr, get_order(size));
70
71 iounmap(vaddr);
63} 72}
73EXPORT_SYMBOL(consistent_free);
64 74
65void consistent_sync(void *vaddr, size_t size, int direction) 75void consistent_sync(void *vaddr, size_t size, int direction)
66{ 76{
67 void * p1addr = (void*) P1SEGADDR((unsigned long)vaddr); 77#ifdef CONFIG_CPU_SH5
78 void *p1addr = vaddr;
79#else
80 void *p1addr = (void*) P1SEGADDR((unsigned long)vaddr);
81#endif
68 82
69 switch (direction) { 83 switch (direction) {
70 case DMA_FROM_DEVICE: /* invalidate only */ 84 case DMA_FROM_DEVICE: /* invalidate only */
@@ -80,8 +94,4 @@ void consistent_sync(void *vaddr, size_t size, int direction)
80 BUG(); 94 BUG();
81 } 95 }
82} 96}
83
84EXPORT_SYMBOL(consistent_alloc);
85EXPORT_SYMBOL(consistent_free);
86EXPORT_SYMBOL(consistent_sync); 97EXPORT_SYMBOL(consistent_sync);
87