aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2008-09-09 15:54:13 -0400
committerNicolas Pitre <nico@cam.org>2009-03-15 21:01:21 -0400
commit58edb515724f9e63e569536d01ac8d8f8ddb367a (patch)
tree627d3eafefd38b031e776b48d8d04d764912ec92
parent43377453af83b8ff8c1c731da1508bd6b84ebfea (diff)
[ARM] make page_to_dma() highmem aware
If a machine class has a custom __virt_to_bus() implementation then it must provide a __arch_page_to_dma() implementation as well which is _not_ based on page_address() to support highmem. This patch fixes existing __arch_page_to_dma() and provide a default implementation otherwise. The default implementation for highmem is based on __pfn_to_bus() which is defined only when no custom __virt_to_bus() is provided by the machine class. That leaves only ebsa110 and footbridge which cannot support highmem until they provide their own __arch_page_to_dma() implementation. But highmem support on those legacy platforms with limited memory is certainly not a priority. Signed-off-by: Nicolas Pitre <nico@marvell.com>
-rw-r--r--arch/arm/common/dmabounce.c7
-rw-r--r--arch/arm/include/asm/dma-mapping.h10
-rw-r--r--arch/arm/include/asm/memory.h1
-rw-r--r--arch/arm/mach-iop13xx/include/mach/memory.h5
-rw-r--r--arch/arm/mach-ks8695/include/mach/memory.h6
-rw-r--r--arch/arm/plat-omap/include/mach/memory.h8
6 files changed, 32 insertions, 5 deletions
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index f030f0775be7..734ac9135998 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -25,6 +25,7 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/slab.h> 27#include <linux/slab.h>
28#include <linux/page-flags.h>
28#include <linux/device.h> 29#include <linux/device.h>
29#include <linux/dma-mapping.h> 30#include <linux/dma-mapping.h>
30#include <linux/dmapool.h> 31#include <linux/dmapool.h>
@@ -349,6 +350,12 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
349 350
350 BUG_ON(!valid_dma_direction(dir)); 351 BUG_ON(!valid_dma_direction(dir));
351 352
353 if (PageHighMem(page)) {
354 dev_err(dev, "DMA buffer bouncing of HIGHMEM pages "
355 "is not supported\n");
356 return ~0;
357 }
358
352 return map_single(dev, page_address(page) + offset, size, dir); 359 return map_single(dev, page_address(page) + offset, size, dir);
353} 360}
354EXPORT_SYMBOL(dma_map_page); 361EXPORT_SYMBOL(dma_map_page);
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 59fa762e9c66..ff46dfa68a97 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -15,10 +15,20 @@
15 * must not be used by drivers. 15 * must not be used by drivers.
16 */ 16 */
17#ifndef __arch_page_to_dma 17#ifndef __arch_page_to_dma
18
19#if !defined(CONFIG_HIGHMEM)
18static inline dma_addr_t page_to_dma(struct device *dev, struct page *page) 20static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
19{ 21{
20 return (dma_addr_t)__virt_to_bus((unsigned long)page_address(page)); 22 return (dma_addr_t)__virt_to_bus((unsigned long)page_address(page));
21} 23}
24#elif defined(__pfn_to_bus)
25static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
26{
27 return (dma_addr_t)__pfn_to_bus(page_to_pfn(page));
28}
29#else
30#error "this machine class needs to define __arch_page_to_dma to use HIGHMEM"
31#endif
22 32
23static inline void *dma_to_virt(struct device *dev, dma_addr_t addr) 33static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
24{ 34{
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index ae472bc376d3..85763db87449 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -188,6 +188,7 @@ static inline void *phys_to_virt(unsigned long x)
188#ifndef __virt_to_bus 188#ifndef __virt_to_bus
189#define __virt_to_bus __virt_to_phys 189#define __virt_to_bus __virt_to_phys
190#define __bus_to_virt __phys_to_virt 190#define __bus_to_virt __phys_to_virt
191#define __pfn_to_bus(x) ((x) << PAGE_SHIFT)
191#endif 192#endif
192 193
193static inline __deprecated unsigned long virt_to_bus(void *x) 194static inline __deprecated unsigned long virt_to_bus(void *x)
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h
index e012bf13c955..42ae29b288a1 100644
--- a/arch/arm/mach-iop13xx/include/mach/memory.h
+++ b/arch/arm/mach-iop13xx/include/mach/memory.h
@@ -59,7 +59,10 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x)
59 }) 59 })
60 60
61#define __arch_page_to_dma(dev, page) \ 61#define __arch_page_to_dma(dev, page) \
62 __arch_virt_to_dma(dev, page_address(page)) 62 ({ \
63 /* __is_lbus_virt() can never be true for RAM pages */ \
64 (dma_addr_t)page_to_phys(page); \
65 })
63 66
64#endif /* CONFIG_ARCH_IOP13XX */ 67#endif /* CONFIG_ARCH_IOP13XX */
65#endif /* !ASSEMBLY */ 68#endif /* !ASSEMBLY */
diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h
index 6d5887cf5742..76e5308685a4 100644
--- a/arch/arm/mach-ks8695/include/mach/memory.h
+++ b/arch/arm/mach-ks8695/include/mach/memory.h
@@ -35,7 +35,11 @@ extern struct bus_type platform_bus_type;
35 __phys_to_virt(x) : __bus_to_virt(x)); }) 35 __phys_to_virt(x) : __bus_to_virt(x)); })
36#define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \ 36#define __arch_virt_to_dma(dev, x) ({ is_lbus_device(dev) ? \
37 (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); }) 37 (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
38#define __arch_page_to_dma(dev, x) __arch_virt_to_dma(dev, page_address(x)) 38#define __arch_page_to_dma(dev, x) \
39 ({ dma_addr_t __dma = page_to_phys(page); \
40 if (!is_lbus_device(dev)) \
41 __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
42 __dma; })
39 43
40#endif 44#endif
41 45
diff --git a/arch/arm/plat-omap/include/mach/memory.h b/arch/arm/plat-omap/include/mach/memory.h
index d6b5ca6c7da2..99ed564d9277 100644
--- a/arch/arm/plat-omap/include/mach/memory.h
+++ b/arch/arm/plat-omap/include/mach/memory.h
@@ -61,9 +61,11 @@
61#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET) 61#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
62#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0)) 62#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
63 63
64#define __arch_page_to_dma(dev, page) ({is_lbus_device(dev) ? \ 64#define __arch_page_to_dma(dev, page) \
65 (dma_addr_t)virt_to_lbus(page_address(page)) : \ 65 ({ dma_addr_t __dma = page_to_phys(page); \
66 (dma_addr_t)__virt_to_phys(page_address(page));}) 66 if (is_lbus_device(dev)) \
67 __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
68 __dma; })
67 69
68#define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \ 70#define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \
69 lbus_to_virt(addr) : \ 71 lbus_to_virt(addr) : \