aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@hobbes.lan>2008-07-28 18:15:46 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-07-28 18:15:46 -0400
commit756f7bc6683916177e8176f8d3fa5f4c11c88afc (patch)
treecbe3ffc375950b016198fa61dea63bb449c59c93
parent979b1791e5b8f8b556faeec4c48339e7ed63af9f (diff)
parentcb28a1bbdb4790378e7366d6c9ee1d2340b84f92 (diff)
Merge branch 'core/generic-dma-coherent' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip into for-linus
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mm/consistent.c8
-rw-r--r--arch/cris/arch-v32/drivers/Kconfig1
-rw-r--r--arch/cris/arch-v32/drivers/pci/dma.c106
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sh/mm/consistent.c98
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/kernel/pci-dma.c122
-rw-r--r--include/asm-arm/dma-mapping.h2
-rw-r--r--include/asm-cris/dma-mapping.h2
-rw-r--r--include/asm-generic/dma-coherent.h32
-rw-r--r--include/asm-sh/dma-mapping.h1
-rw-r--r--include/asm-x86/dma-mapping.h22
-rw-r--r--init/Kconfig4
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/dma-coherent.c154
16 files changed, 217 insertions, 339 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c8f528284a94..652cd32a09c5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -17,6 +17,7 @@ config ARM
17 select HAVE_KRETPROBES if (HAVE_KPROBES) 17 select HAVE_KRETPROBES if (HAVE_KPROBES)
18 select HAVE_FTRACE if (!XIP_KERNEL) 18 select HAVE_FTRACE if (!XIP_KERNEL)
19 select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE) 19 select HAVE_DYNAMIC_FTRACE if (HAVE_FTRACE)
20 select HAVE_GENERIC_DMA_COHERENT
20 help 21 help
21 The ARM series is a line of low-power-consumption RISC chip designs 22 The ARM series is a line of low-power-consumption RISC chip designs
22 licensed by ARM Ltd and targeted at embedded applications and 23 licensed by ARM Ltd and targeted at embedded applications and
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 333a82a3717e..db7b3e38ef1d 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -274,6 +274,11 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
274void * 274void *
275dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) 275dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
276{ 276{
277 void *memory;
278
279 if (dma_alloc_from_coherent(dev, size, handle, &memory))
280 return memory;
281
277 if (arch_is_coherent()) { 282 if (arch_is_coherent()) {
278 void *virt; 283 void *virt;
279 284
@@ -362,6 +367,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
362 367
363 WARN_ON(irqs_disabled()); 368 WARN_ON(irqs_disabled());
364 369
370 if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
371 return;
372
365 if (arch_is_coherent()) { 373 if (arch_is_coherent()) {
366 kfree(cpu_addr); 374 kfree(cpu_addr);
367 return; 375 return;
diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
index 2a92cb1886ca..7a64fcef9d07 100644
--- a/arch/cris/arch-v32/drivers/Kconfig
+++ b/arch/cris/arch-v32/drivers/Kconfig
@@ -641,6 +641,7 @@ config PCI
641 bool 641 bool
642 depends on ETRAX_CARDBUS 642 depends on ETRAX_CARDBUS
643 default y 643 default y
644 select HAVE_GENERIC_DMA_COHERENT
644 645
645config ETRAX_IOP_FW_LOAD 646config ETRAX_IOP_FW_LOAD
646 tristate "IO-processor hotplug firmware loading support" 647 tristate "IO-processor hotplug firmware loading support"
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c
index e0364654fc44..fbe65954ee6c 100644
--- a/arch/cris/arch-v32/drivers/pci/dma.c
+++ b/arch/cris/arch-v32/drivers/pci/dma.c
@@ -15,35 +15,16 @@
15#include <linux/pci.h> 15#include <linux/pci.h>
16#include <asm/io.h> 16#include <asm/io.h>
17 17
18struct dma_coherent_mem {
19 void *virt_base;
20 u32 device_base;
21 int size;
22 int flags;
23 unsigned long *bitmap;
24};
25
26void *dma_alloc_coherent(struct device *dev, size_t size, 18void *dma_alloc_coherent(struct device *dev, size_t size,
27 dma_addr_t *dma_handle, gfp_t gfp) 19 dma_addr_t *dma_handle, gfp_t gfp)
28{ 20{
29 void *ret; 21 void *ret;
30 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
31 int order = get_order(size); 22 int order = get_order(size);
32 /* ignore region specifiers */ 23 /* ignore region specifiers */
33 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); 24 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
34 25
35 if (mem) { 26 if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
36 int page = bitmap_find_free_region(mem->bitmap, mem->size, 27 return ret;
37 order);
38 if (page >= 0) {
39 *dma_handle = mem->device_base + (page << PAGE_SHIFT);
40 ret = mem->virt_base + (page << PAGE_SHIFT);
41 memset(ret, 0, size);
42 return ret;
43 }
44 if (mem->flags & DMA_MEMORY_EXCLUSIVE)
45 return NULL;
46 }
47 28
48 if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) 29 if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
49 gfp |= GFP_DMA; 30 gfp |= GFP_DMA;
@@ -60,90 +41,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
60void dma_free_coherent(struct device *dev, size_t size, 41void dma_free_coherent(struct device *dev, size_t size,
61 void *vaddr, dma_addr_t dma_handle) 42 void *vaddr, dma_addr_t dma_handle)
62{ 43{
63 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
64 int order = get_order(size); 44 int order = get_order(size);
65 45
66 if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { 46 if (!dma_release_from_coherent(dev, order, vaddr))
67 int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
68
69 bitmap_release_region(mem->bitmap, page, order);
70 } else
71 free_pages((unsigned long)vaddr, order); 47 free_pages((unsigned long)vaddr, order);
72} 48}
73 49
74int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
75 dma_addr_t device_addr, size_t size, int flags)
76{
77 void __iomem *mem_base;
78 int pages = size >> PAGE_SHIFT;
79 int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
80
81 if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
82 goto out;
83 if (!size)
84 goto out;
85 if (dev->dma_mem)
86 goto out;
87
88 /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
89
90 mem_base = ioremap(bus_addr, size);
91 if (!mem_base)
92 goto out;
93
94 dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
95 if (!dev->dma_mem)
96 goto iounmap_out;
97 dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
98 if (!dev->dma_mem->bitmap)
99 goto free1_out;
100
101 dev->dma_mem->virt_base = mem_base;
102 dev->dma_mem->device_base = device_addr;
103 dev->dma_mem->size = pages;
104 dev->dma_mem->flags = flags;
105
106 if (flags & DMA_MEMORY_MAP)
107 return DMA_MEMORY_MAP;
108
109 return DMA_MEMORY_IO;
110
111 free1_out:
112 kfree(dev->dma_mem);
113 iounmap_out:
114 iounmap(mem_base);
115 out:
116 return 0;
117}
118EXPORT_SYMBOL(dma_declare_coherent_memory);
119
120void dma_release_declared_memory(struct device *dev)
121{
122 struct dma_coherent_mem *mem = dev->dma_mem;
123
124 if(!mem)
125 return;
126 dev->dma_mem = NULL;
127 iounmap(mem->virt_base);
128 kfree(mem->bitmap);
129 kfree(mem);
130}
131EXPORT_SYMBOL(dma_release_declared_memory);
132
133void *dma_mark_declared_memory_occupied(struct device *dev,
134 dma_addr_t device_addr, size_t size)
135{
136 struct dma_coherent_mem *mem = dev->dma_mem;
137 int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
138 int pos, err;
139
140 if (!mem)
141 return ERR_PTR(-EINVAL);
142
143 pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
144 err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
145 if (err != 0)
146 return ERR_PTR(err);
147 return mem->virt_base + (pos << PAGE_SHIFT);
148}
149EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 7bfb0d219d67..0b88dc462d73 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -11,6 +11,7 @@ config SUPERH
11 select HAVE_CLK 11 select HAVE_CLK
12 select HAVE_IDE 12 select HAVE_IDE
13 select HAVE_OPROFILE 13 select HAVE_OPROFILE
14 select HAVE_GENERIC_DMA_COHERENT
14 help 15 help
15 The SuperH is a RISC processor targeted for use in embedded systems 16 The SuperH is a RISC processor targeted for use in embedded systems
16 and consumer electronics; it was also used in the Sega Dreamcast 17 and consumer electronics; it was also used in the Sega Dreamcast
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index 8277982d0938..b2ce014401b5 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -28,21 +28,10 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
28 dma_addr_t *dma_handle, gfp_t gfp) 28 dma_addr_t *dma_handle, gfp_t gfp)
29{ 29{
30 void *ret, *ret_nocache; 30 void *ret, *ret_nocache;
31 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
32 int order = get_order(size); 31 int order = get_order(size);
33 32
34 if (mem) { 33 if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
35 int page = bitmap_find_free_region(mem->bitmap, mem->size, 34 return ret;
36 order);
37 if (page >= 0) {
38 *dma_handle = mem->device_base + (page << PAGE_SHIFT);
39 ret = mem->virt_base + (page << PAGE_SHIFT);
40 memset(ret, 0, size);
41 return ret;
42 }
43 if (mem->flags & DMA_MEMORY_EXCLUSIVE)
44 return NULL;
45 }
46 35
47 ret = (void *)__get_free_pages(gfp, order); 36 ret = (void *)__get_free_pages(gfp, order);
48 if (!ret) 37 if (!ret)
@@ -72,11 +61,7 @@ void dma_free_coherent(struct device *dev, size_t size,
72 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; 61 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
73 int order = get_order(size); 62 int order = get_order(size);
74 63
75 if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { 64 if (!dma_release_from_coherent(dev, order, vaddr)) {
76 int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
77
78 bitmap_release_region(mem->bitmap, page, order);
79 } else {
80 WARN_ON(irqs_disabled()); /* for portability */ 65 WARN_ON(irqs_disabled()); /* for portability */
81 BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE); 66 BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE);
82 free_pages((unsigned long)phys_to_virt(dma_handle), order); 67 free_pages((unsigned long)phys_to_virt(dma_handle), order);
@@ -85,83 +70,6 @@ void dma_free_coherent(struct device *dev, size_t size,
85} 70}
86EXPORT_SYMBOL(dma_free_coherent); 71EXPORT_SYMBOL(dma_free_coherent);
87 72
88int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
89 dma_addr_t device_addr, size_t size, int flags)
90{
91 void __iomem *mem_base = NULL;
92 int pages = size >> PAGE_SHIFT;
93 int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
94
95 if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
96 goto out;
97 if (!size)
98 goto out;
99 if (dev->dma_mem)
100 goto out;
101
102 /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
103
104 mem_base = ioremap_nocache(bus_addr, size);
105 if (!mem_base)
106 goto out;
107
108 dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
109 if (!dev->dma_mem)
110 goto out;
111 dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
112 if (!dev->dma_mem->bitmap)
113 goto free1_out;
114
115 dev->dma_mem->virt_base = mem_base;
116 dev->dma_mem->device_base = device_addr;
117 dev->dma_mem->size = pages;
118 dev->dma_mem->flags = flags;
119
120 if (flags & DMA_MEMORY_MAP)
121 return DMA_MEMORY_MAP;
122
123 return DMA_MEMORY_IO;
124
125 free1_out:
126 kfree(dev->dma_mem);
127 out:
128 if (mem_base)
129 iounmap(mem_base);
130 return 0;
131}
132EXPORT_SYMBOL(dma_declare_coherent_memory);
133
134void dma_release_declared_memory(struct device *dev)
135{
136 struct dma_coherent_mem *mem = dev->dma_mem;
137
138 if (!mem)
139 return;
140 dev->dma_mem = NULL;
141 iounmap(mem->virt_base);
142 kfree(mem->bitmap);
143 kfree(mem);
144}
145EXPORT_SYMBOL(dma_release_declared_memory);
146
147void *dma_mark_declared_memory_occupied(struct device *dev,
148 dma_addr_t device_addr, size_t size)
149{
150 struct dma_coherent_mem *mem = dev->dma_mem;
151 int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
152 int pos, err;
153
154 if (!mem)
155 return ERR_PTR(-EINVAL);
156
157 pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
158 err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
159 if (err != 0)
160 return ERR_PTR(err);
161 return mem->virt_base + (pos << PAGE_SHIFT);
162}
163EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
164
165void dma_cache_sync(struct device *dev, void *vaddr, size_t size, 73void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
166 enum dma_data_direction direction) 74 enum dma_data_direction direction)
167{ 75{
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b6fa2877b173..3d0f2b6a5a16 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -30,6 +30,7 @@ config X86
30 select HAVE_FTRACE 30 select HAVE_FTRACE
31 select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) 31 select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
32 select HAVE_ARCH_KGDB if !X86_VOYAGER 32 select HAVE_ARCH_KGDB if !X86_VOYAGER
33 select HAVE_GENERIC_DMA_COHERENT if X86_32
33 select HAVE_EFFICIENT_UNALIGNED_ACCESS 34 select HAVE_EFFICIENT_UNALIGNED_ACCESS
34 35
35config ARCH_DEFCONFIG 36config ARCH_DEFCONFIG
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 37544123896d..8dbffb846de9 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -192,124 +192,6 @@ static __init int iommu_setup(char *p)
192} 192}
193early_param("iommu", iommu_setup); 193early_param("iommu", iommu_setup);
194 194
195#ifdef CONFIG_X86_32
196int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
197 dma_addr_t device_addr, size_t size, int flags)
198{
199 void __iomem *mem_base = NULL;
200 int pages = size >> PAGE_SHIFT;
201 int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
202
203 if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
204 goto out;
205 if (!size)
206 goto out;
207 if (dev->dma_mem)
208 goto out;
209
210 /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
211
212 mem_base = ioremap(bus_addr, size);
213 if (!mem_base)
214 goto out;
215
216 dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
217 if (!dev->dma_mem)
218 goto out;
219 dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
220 if (!dev->dma_mem->bitmap)
221 goto free1_out;
222
223 dev->dma_mem->virt_base = mem_base;
224 dev->dma_mem->device_base = device_addr;
225 dev->dma_mem->size = pages;
226 dev->dma_mem->flags = flags;
227
228 if (flags & DMA_MEMORY_MAP)
229 return DMA_MEMORY_MAP;
230
231 return DMA_MEMORY_IO;
232
233 free1_out:
234 kfree(dev->dma_mem);
235 out:
236 if (mem_base)
237 iounmap(mem_base);
238 return 0;
239}
240EXPORT_SYMBOL(dma_declare_coherent_memory);
241
242void dma_release_declared_memory(struct device *dev)
243{
244 struct dma_coherent_mem *mem = dev->dma_mem;
245
246 if (!mem)
247 return;
248 dev->dma_mem = NULL;
249 iounmap(mem->virt_base);
250 kfree(mem->bitmap);
251 kfree(mem);
252}
253EXPORT_SYMBOL(dma_release_declared_memory);
254
255void *dma_mark_declared_memory_occupied(struct device *dev,
256 dma_addr_t device_addr, size_t size)
257{
258 struct dma_coherent_mem *mem = dev->dma_mem;
259 int pos, err;
260 int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
261
262 pages >>= PAGE_SHIFT;
263
264 if (!mem)
265 return ERR_PTR(-EINVAL);
266
267 pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
268 err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
269 if (err != 0)
270 return ERR_PTR(err);
271 return mem->virt_base + (pos << PAGE_SHIFT);
272}
273EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
274
275static int dma_alloc_from_coherent_mem(struct device *dev, ssize_t size,
276 dma_addr_t *dma_handle, void **ret)
277{
278 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
279 int order = get_order(size);
280
281 if (mem) {
282 int page = bitmap_find_free_region(mem->bitmap, mem->size,
283 order);
284 if (page >= 0) {
285 *dma_handle = mem->device_base + (page << PAGE_SHIFT);
286 *ret = mem->virt_base + (page << PAGE_SHIFT);
287 memset(*ret, 0, size);
288 }
289 if (mem->flags & DMA_MEMORY_EXCLUSIVE)
290 *ret = NULL;
291 }
292 return (mem != NULL);
293}
294
295static int dma_release_coherent(struct device *dev, int order, void *vaddr)
296{
297 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
298
299 if (mem && vaddr >= mem->virt_base && vaddr <
300 (mem->virt_base + (mem->size << PAGE_SHIFT))) {
301 int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
302
303 bitmap_release_region(mem->bitmap, page, order);
304 return 1;
305 }
306 return 0;
307}
308#else
309#define dma_alloc_from_coherent_mem(dev, size, handle, ret) (0)
310#define dma_release_coherent(dev, order, vaddr) (0)
311#endif /* CONFIG_X86_32 */
312
313int dma_supported(struct device *dev, u64 mask) 195int dma_supported(struct device *dev, u64 mask)
314{ 196{
315 struct dma_mapping_ops *ops = get_dma_ops(dev); 197 struct dma_mapping_ops *ops = get_dma_ops(dev);
@@ -379,7 +261,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
379 /* ignore region specifiers */ 261 /* ignore region specifiers */
380 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); 262 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
381 263
382 if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory)) 264 if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
383 return memory; 265 return memory;
384 266
385 if (!dev) { 267 if (!dev) {
@@ -484,7 +366,7 @@ void dma_free_coherent(struct device *dev, size_t size,
484 366
485 int order = get_order(size); 367 int order = get_order(size);
486 WARN_ON(irqs_disabled()); /* for portability */ 368 WARN_ON(irqs_disabled()); /* for portability */
487 if (dma_release_coherent(dev, order, vaddr)) 369 if (dma_release_from_coherent(dev, order, vaddr))
488 return; 370 return;
489 if (ops->unmap_single) 371 if (ops->unmap_single)
490 ops->unmap_single(dev, bus, size, 0); 372 ops->unmap_single(dev, bus, size, 0);
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index f41335ba6337..45329fca1b64 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -7,6 +7,8 @@
7 7
8#include <linux/scatterlist.h> 8#include <linux/scatterlist.h>
9 9
10#include <asm-generic/dma-coherent.h>
11
10/* 12/*
11 * DMA-consistent mapping functions. These allocate/free a region of 13 * DMA-consistent mapping functions. These allocate/free a region of
12 * uncached, unwrite-buffered mapped memory space for use with DMA 14 * uncached, unwrite-buffered mapped memory space for use with DMA
diff --git a/include/asm-cris/dma-mapping.h b/include/asm-cris/dma-mapping.h
index cb2fb25ff8d9..da8ef8e8f842 100644
--- a/include/asm-cris/dma-mapping.h
+++ b/include/asm-cris/dma-mapping.h
@@ -14,6 +14,8 @@
14#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) 14#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
15 15
16#ifdef CONFIG_PCI 16#ifdef CONFIG_PCI
17#include <asm-generic/dma-coherent.h>
18
17void *dma_alloc_coherent(struct device *dev, size_t size, 19void *dma_alloc_coherent(struct device *dev, size_t size,
18 dma_addr_t *dma_handle, gfp_t flag); 20 dma_addr_t *dma_handle, gfp_t flag);
19 21
diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h
new file mode 100644
index 000000000000..85a3ffaa0242
--- /dev/null
+++ b/include/asm-generic/dma-coherent.h
@@ -0,0 +1,32 @@
1#ifndef DMA_COHERENT_H
2#define DMA_COHERENT_H
3
4#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
5/*
6 * These two functions are only for dma allocator.
7 * Don't use them in device drivers.
8 */
9int dma_alloc_from_coherent(struct device *dev, ssize_t size,
10 dma_addr_t *dma_handle, void **ret);
11int dma_release_from_coherent(struct device *dev, int order, void *vaddr);
12
13/*
14 * Standard interface
15 */
16#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
17extern int
18dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
19 dma_addr_t device_addr, size_t size, int flags);
20
21extern void
22dma_release_declared_memory(struct device *dev);
23
24extern void *
25dma_mark_declared_memory_occupied(struct device *dev,
26 dma_addr_t device_addr, size_t size);
27#else
28#define dma_alloc_from_coherent(dev, size, handle, ret) (0)
29#define dma_release_from_coherent(dev, order, vaddr) (0)
30#endif
31
32#endif
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 6c0b8a2de143..627315ecdb52 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -5,6 +5,7 @@
5#include <linux/scatterlist.h> 5#include <linux/scatterlist.h>
6#include <asm/cacheflush.h> 6#include <asm/cacheflush.h>
7#include <asm/io.h> 7#include <asm/io.h>
8#include <asm-generic/dma-coherent.h>
8 9
9extern struct bus_type pci_bus_type; 10extern struct bus_type pci_bus_type;
10 11
diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h
index 0eaa9bf6011f..ad9cd6d49bfc 100644
--- a/include/asm-x86/dma-mapping.h
+++ b/include/asm-x86/dma-mapping.h
@@ -249,25 +249,5 @@ static inline int dma_get_cache_alignment(void)
249 249
250#define dma_is_consistent(d, h) (1) 250#define dma_is_consistent(d, h) (1)
251 251
252#ifdef CONFIG_X86_32 252#include <asm-generic/dma-coherent.h>
253# define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
254struct dma_coherent_mem {
255 void *virt_base;
256 u32 device_base;
257 int size;
258 int flags;
259 unsigned long *bitmap;
260};
261
262extern int
263dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
264 dma_addr_t device_addr, size_t size, int flags);
265
266extern void
267dma_release_declared_memory(struct device *dev);
268
269extern void *
270dma_mark_declared_memory_occupied(struct device *dev,
271 dma_addr_t device_addr, size_t size);
272#endif /* CONFIG_X86_32 */
273#endif 253#endif
diff --git a/init/Kconfig b/init/Kconfig
index 43d6989c275f..250e02c8f8f9 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -802,6 +802,10 @@ config PROC_PAGE_MONITOR
802 802
803endmenu # General setup 803endmenu # General setup
804 804
805config HAVE_GENERIC_DMA_COHERENT
806 bool
807 default n
808
805config SLABINFO 809config SLABINFO
806 bool 810 bool
807 depends on PROC_FS 811 depends on PROC_FS
diff --git a/kernel/Makefile b/kernel/Makefile
index 54f69837d35a..4e1d7df7c3e2 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -84,6 +84,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
84obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o 84obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
85obj-$(CONFIG_MARKERS) += marker.o 85obj-$(CONFIG_MARKERS) += marker.o
86obj-$(CONFIG_LATENCYTOP) += latencytop.o 86obj-$(CONFIG_LATENCYTOP) += latencytop.o
87obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
87obj-$(CONFIG_FTRACE) += trace/ 88obj-$(CONFIG_FTRACE) += trace/
88obj-$(CONFIG_TRACING) += trace/ 89obj-$(CONFIG_TRACING) += trace/
89obj-$(CONFIG_SMP) += sched_cpupri.o 90obj-$(CONFIG_SMP) += sched_cpupri.o
diff --git a/kernel/dma-coherent.c b/kernel/dma-coherent.c
new file mode 100644
index 000000000000..7517115a8cce
--- /dev/null
+++ b/kernel/dma-coherent.c
@@ -0,0 +1,154 @@
1/*
2 * Coherent per-device memory handling.
3 * Borrowed from i386
4 */
5#include <linux/kernel.h>
6#include <linux/dma-mapping.h>
7
8struct dma_coherent_mem {
9 void *virt_base;
10 u32 device_base;
11 int size;
12 int flags;
13 unsigned long *bitmap;
14};
15
16int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
17 dma_addr_t device_addr, size_t size, int flags)
18{
19 void __iomem *mem_base = NULL;
20 int pages = size >> PAGE_SHIFT;
21 int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
22
23 if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
24 goto out;
25 if (!size)
26 goto out;
27 if (dev->dma_mem)
28 goto out;
29
30 /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
31
32 mem_base = ioremap(bus_addr, size);
33 if (!mem_base)
34 goto out;
35
36 dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
37 if (!dev->dma_mem)
38 goto out;
39 dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
40 if (!dev->dma_mem->bitmap)
41 goto free1_out;
42
43 dev->dma_mem->virt_base = mem_base;
44 dev->dma_mem->device_base = device_addr;
45 dev->dma_mem->size = pages;
46 dev->dma_mem->flags = flags;
47
48 if (flags & DMA_MEMORY_MAP)
49 return DMA_MEMORY_MAP;
50
51 return DMA_MEMORY_IO;
52
53 free1_out:
54 kfree(dev->dma_mem);
55 out:
56 if (mem_base)
57 iounmap(mem_base);
58 return 0;
59}
60EXPORT_SYMBOL(dma_declare_coherent_memory);
61
62void dma_release_declared_memory(struct device *dev)
63{
64 struct dma_coherent_mem *mem = dev->dma_mem;
65
66 if (!mem)
67 return;
68 dev->dma_mem = NULL;
69 iounmap(mem->virt_base);
70 kfree(mem->bitmap);
71 kfree(mem);
72}
73EXPORT_SYMBOL(dma_release_declared_memory);
74
75void *dma_mark_declared_memory_occupied(struct device *dev,
76 dma_addr_t device_addr, size_t size)
77{
78 struct dma_coherent_mem *mem = dev->dma_mem;
79 int pos, err;
80 int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1);
81
82 pages >>= PAGE_SHIFT;
83
84 if (!mem)
85 return ERR_PTR(-EINVAL);
86
87 pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
88 err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
89 if (err != 0)
90 return ERR_PTR(err);
91 return mem->virt_base + (pos << PAGE_SHIFT);
92}
93EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
94
95/**
96 * Try to allocate memory from the per-device coherent area.
97 *
98 * @dev: device from which we allocate memory
99 * @size: size of requested memory area
100 * @dma_handle: This will be filled with the correct dma handle
101 * @ret: This pointer will be filled with the virtual address
102 * to allocated area.
103 *
104 * This function should be only called from per-arch %dma_alloc_coherent()
105 * to support allocation from per-device coherent memory pools.
106 *
107 * Returns 0 if dma_alloc_coherent should continue with allocating from
108 * generic memory areas, or !0 if dma_alloc_coherent should return %ret.
109 */
110int dma_alloc_from_coherent(struct device *dev, ssize_t size,
111 dma_addr_t *dma_handle, void **ret)
112{
113 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
114 int order = get_order(size);
115
116 if (mem) {
117 int page = bitmap_find_free_region(mem->bitmap, mem->size,
118 order);
119 if (page >= 0) {
120 *dma_handle = mem->device_base + (page << PAGE_SHIFT);
121 *ret = mem->virt_base + (page << PAGE_SHIFT);
122 memset(*ret, 0, size);
123 } else if (mem->flags & DMA_MEMORY_EXCLUSIVE)
124 *ret = NULL;
125 }
126 return (mem != NULL);
127}
128
129/**
130 * Try to free the memory allocated from per-device coherent memory pool.
131 * @dev: device from which the memory was allocated
132 * @order: the order of pages allocated
133 * @vaddr: virtual address of allocated pages
134 *
135 * This checks whether the memory was allocated from the per-device
136 * coherent memory pool and if so, releases that memory.
137 *
138 * Returns 1 if we correctly released the memory, or 0 if
139 * %dma_release_coherent() should proceed with releasing memory from
140 * generic pools.
141 */
142int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
143{
144 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
145
146 if (mem && vaddr >= mem->virt_base && vaddr <
147 (mem->virt_base + (mem->size << PAGE_SHIFT))) {
148 int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
149
150 bitmap_release_region(mem->bitmap, page, order);
151 return 1;
152 }
153 return 0;
154}