aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@uclinux.org>2012-05-02 03:06:22 -0400
committerGreg Ungerer <gerg@uclinux.org>2012-05-20 07:22:56 -0400
commit5641686c234ffe5fbcb1728ac45016761b318839 (patch)
tree86e7db78f80f455be6855edc2048e142411f2a78 /arch/m68k
parent1744bd921cd1037f0415574e0f8a3611984ecc7c (diff)
m68k: merge the MMU and non-MMU versions of the arch dma code
The majority of the m68k architecture dma code is the same, so merge the current separated files dma_no.c and dma_mm.c back into a single dma.c The main alloc and free routines are a little different, so we keep a single #ifdef based on CONFIG_MMU for them. All the other support functions are now identical. Signed-off-by: Greg Ungerer <gerg@uclinux.org> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/kernel/dma.c165
-rw-r--r--arch/m68k/kernel/dma_mm.c131
-rw-r--r--arch/m68k/kernel/dma_no.c75
3 files changed, 162 insertions, 209 deletions
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index 90e8cb726c8c..f6daf6e15d2e 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -1,5 +1,164 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file COPYING in the main directory of this archive
4 * for more details.
5 */
6
7#undef DEBUG
8
9#include <linux/dma-mapping.h>
10#include <linux/device.h>
11#include <linux/kernel.h>
12#include <linux/scatterlist.h>
13#include <linux/slab.h>
14#include <linux/vmalloc.h>
15#include <linux/export.h>
16
17#include <asm/pgalloc.h>
18
1#ifdef CONFIG_MMU 19#ifdef CONFIG_MMU
2#include "dma_mm.c" 20
21void *dma_alloc_coherent(struct device *dev, size_t size,
22 dma_addr_t *handle, gfp_t flag)
23{
24 struct page *page, **map;
25 pgprot_t pgprot;
26 void *addr;
27 int i, order;
28
29 pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
30
31 size = PAGE_ALIGN(size);
32 order = get_order(size);
33
34 page = alloc_pages(flag, order);
35 if (!page)
36 return NULL;
37
38 *handle = page_to_phys(page);
39 map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
40 if (!map) {
41 __free_pages(page, order);
42 return NULL;
43 }
44 split_page(page, order);
45
46 order = 1 << order;
47 size >>= PAGE_SHIFT;
48 map[0] = page;
49 for (i = 1; i < size; i++)
50 map[i] = page + i;
51 for (; i < order; i++)
52 __free_page(page + i);
53 pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
54 if (CPU_IS_040_OR_060)
55 pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
56 else
57 pgprot_val(pgprot) |= _PAGE_NOCACHE030;
58 addr = vmap(map, size, VM_MAP, pgprot);
59 kfree(map);
60
61 return addr;
62}
63
64void dma_free_coherent(struct device *dev, size_t size,
65 void *addr, dma_addr_t handle)
66{
67 pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
68 vfree(addr);
69}
70
3#else 71#else
4#include "dma_no.c" 72
5#endif 73#include <asm/cacheflush.h>
74
75void *dma_alloc_coherent(struct device *dev, size_t size,
76 dma_addr_t *dma_handle, gfp_t gfp)
77{
78 void *ret;
79 /* ignore region specifiers */
80 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
81
82 if (dev == NULL || (*dev->dma_mask < 0xffffffff))
83 gfp |= GFP_DMA;
84 ret = (void *)__get_free_pages(gfp, get_order(size));
85
86 if (ret != NULL) {
87 memset(ret, 0, size);
88 *dma_handle = virt_to_phys(ret);
89 }
90 return ret;
91}
92
93void dma_free_coherent(struct device *dev, size_t size,
94 void *vaddr, dma_addr_t dma_handle)
95{
96 free_pages((unsigned long)vaddr, get_order(size));
97}
98
99#endif /* CONFIG_MMU */
100
101EXPORT_SYMBOL(dma_alloc_coherent);
102EXPORT_SYMBOL(dma_free_coherent);
103
104void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
105 size_t size, enum dma_data_direction dir)
106{
107 switch (dir) {
108 case DMA_TO_DEVICE:
109 cache_push(handle, size);
110 break;
111 case DMA_FROM_DEVICE:
112 cache_clear(handle, size);
113 break;
114 default:
115 if (printk_ratelimit())
116 printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
117 break;
118 }
119}
120EXPORT_SYMBOL(dma_sync_single_for_device);
121
122void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
123 enum dma_data_direction dir)
124{
125 int i;
126
127 for (i = 0; i < nents; sg++, i++)
128 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
129}
130EXPORT_SYMBOL(dma_sync_sg_for_device);
131
132dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
133 enum dma_data_direction dir)
134{
135 dma_addr_t handle = virt_to_bus(addr);
136
137 dma_sync_single_for_device(dev, handle, size, dir);
138 return handle;
139}
140EXPORT_SYMBOL(dma_map_single);
141
142dma_addr_t dma_map_page(struct device *dev, struct page *page,
143 unsigned long offset, size_t size,
144 enum dma_data_direction dir)
145{
146 dma_addr_t handle = page_to_phys(page) + offset;
147
148 dma_sync_single_for_device(dev, handle, size, dir);
149 return handle;
150}
151EXPORT_SYMBOL(dma_map_page);
152
153int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
154 enum dma_data_direction dir)
155{
156 int i;
157
158 for (i = 0; i < nents; sg++, i++) {
159 sg->dma_address = sg_phys(sg);
160 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
161 }
162 return nents;
163}
164EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/kernel/dma_mm.c b/arch/m68k/kernel/dma_mm.c
deleted file mode 100644
index a3c471b523f2..000000000000
--- a/arch/m68k/kernel/dma_mm.c
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file COPYING in the main directory of this archive
4 * for more details.
5 */
6
7#undef DEBUG
8
9#include <linux/dma-mapping.h>
10#include <linux/device.h>
11#include <linux/kernel.h>
12#include <linux/scatterlist.h>
13#include <linux/slab.h>
14#include <linux/vmalloc.h>
15#include <linux/export.h>
16
17#include <asm/pgalloc.h>
18
19void *dma_alloc_coherent(struct device *dev, size_t size,
20 dma_addr_t *handle, gfp_t flag)
21{
22 struct page *page, **map;
23 pgprot_t pgprot;
24 void *addr;
25 int i, order;
26
27 pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
28
29 size = PAGE_ALIGN(size);
30 order = get_order(size);
31
32 page = alloc_pages(flag, order);
33 if (!page)
34 return NULL;
35
36 *handle = page_to_phys(page);
37 map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
38 if (!map) {
39 __free_pages(page, order);
40 return NULL;
41 }
42 split_page(page, order);
43
44 order = 1 << order;
45 size >>= PAGE_SHIFT;
46 map[0] = page;
47 for (i = 1; i < size; i++)
48 map[i] = page + i;
49 for (; i < order; i++)
50 __free_page(page + i);
51 pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
52 if (CPU_IS_040_OR_060)
53 pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
54 else
55 pgprot_val(pgprot) |= _PAGE_NOCACHE030;
56 addr = vmap(map, size, VM_MAP, pgprot);
57 kfree(map);
58
59 return addr;
60}
61EXPORT_SYMBOL(dma_alloc_coherent);
62
63void dma_free_coherent(struct device *dev, size_t size,
64 void *addr, dma_addr_t handle)
65{
66 pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
67 vfree(addr);
68}
69EXPORT_SYMBOL(dma_free_coherent);
70
71void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
72 size_t size, enum dma_data_direction dir)
73{
74 switch (dir) {
75 case DMA_TO_DEVICE:
76 cache_push(handle, size);
77 break;
78 case DMA_FROM_DEVICE:
79 cache_clear(handle, size);
80 break;
81 default:
82 if (printk_ratelimit())
83 printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
84 break;
85 }
86}
87EXPORT_SYMBOL(dma_sync_single_for_device);
88
89void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
90 enum dma_data_direction dir)
91{
92 int i;
93
94 for (i = 0; i < nents; sg++, i++)
95 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
96}
97EXPORT_SYMBOL(dma_sync_sg_for_device);
98
99dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
100 enum dma_data_direction dir)
101{
102 dma_addr_t handle = virt_to_bus(addr);
103
104 dma_sync_single_for_device(dev, handle, size, dir);
105 return handle;
106}
107EXPORT_SYMBOL(dma_map_single);
108
109dma_addr_t dma_map_page(struct device *dev, struct page *page,
110 unsigned long offset, size_t size,
111 enum dma_data_direction dir)
112{
113 dma_addr_t handle = page_to_phys(page) + offset;
114
115 dma_sync_single_for_device(dev, handle, size, dir);
116 return handle;
117}
118EXPORT_SYMBOL(dma_map_page);
119
120int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
121 enum dma_data_direction dir)
122{
123 int i;
124
125 for (i = 0; i < nents; sg++, i++) {
126 sg->dma_address = sg_phys(sg);
127 dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
128 }
129 return nents;
130}
131EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/kernel/dma_no.c b/arch/m68k/kernel/dma_no.c
deleted file mode 100644
index f1dc3fc71bc2..000000000000
--- a/arch/m68k/kernel/dma_no.c
+++ /dev/null
@@ -1,75 +0,0 @@
1/*
2 * Dynamic DMA mapping support.
3 *
4 * We never have any address translations to worry about, so this
5 * is just alloc/free.
6 */
7
8#include <linux/types.h>
9#include <linux/gfp.h>
10#include <linux/mm.h>
11#include <linux/device.h>
12#include <linux/dma-mapping.h>
13#include <linux/export.h>
14#include <asm/cacheflush.h>
15
16void *dma_alloc_coherent(struct device *dev, size_t size,
17 dma_addr_t *dma_handle, gfp_t gfp)
18{
19 void *ret;
20 /* ignore region specifiers */
21 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
22
23 if (dev == NULL || (*dev->dma_mask < 0xffffffff))
24 gfp |= GFP_DMA;
25 ret = (void *)__get_free_pages(gfp, get_order(size));
26
27 if (ret != NULL) {
28 memset(ret, 0, size);
29 *dma_handle = virt_to_phys(ret);
30 }
31 return ret;
32}
33
34void dma_free_coherent(struct device *dev, size_t size,
35 void *vaddr, dma_addr_t dma_handle)
36{
37 free_pages((unsigned long)vaddr, get_order(size));
38}
39
40void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
41 size_t size, enum dma_data_direction dir)
42{
43 switch (dir) {
44 case DMA_TO_DEVICE:
45 flush_dcache_range(handle, size);
46 break;
47 case DMA_FROM_DEVICE:
48 /* Should be clear already */
49 break;
50 default:
51 if (printk_ratelimit())
52 printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
53 break;
54 }
55}
56
57EXPORT_SYMBOL(dma_sync_single_for_device);
58dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
59 enum dma_data_direction dir)
60{
61 dma_addr_t handle = virt_to_phys(addr);
62 flush_dcache_range(handle, size);
63 return handle;
64}
65EXPORT_SYMBOL(dma_map_single);
66
67dma_addr_t dma_map_page(struct device *dev, struct page *page,
68 unsigned long offset, size_t size,
69 enum dma_data_direction dir)
70{
71 dma_addr_t handle = page_to_phys(page) + offset;
72 dma_sync_single_for_device(dev, handle, size, dir);
73 return handle;
74}
75EXPORT_SYMBOL(dma_map_page);