diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arc/include/asm/dma-mapping.h | 205 | ||||
-rw-r--r-- | arch/arc/include/asm/dma.h | 14 | ||||
-rw-r--r-- | arch/arc/include/asm/io.h | 103 | ||||
-rw-r--r-- | arch/arc/mm/dma.c | 94 | ||||
-rw-r--r-- | arch/arc/mm/ioremap.c | 67 | ||||
-rw-r--r-- | arch/arc/plat-arcfpga/include/plat/dma_addr.h | 45 |
6 files changed, 528 insertions, 0 deletions
diff --git a/arch/arc/include/asm/dma-mapping.h b/arch/arc/include/asm/dma-mapping.h new file mode 100644 index 000000000000..7fd150e97eb2 --- /dev/null +++ b/arch/arc/include/asm/dma-mapping.h | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * DMA Mapping glue for ARC | ||
3 | * | ||
4 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef ASM_ARC_DMA_MAPPING_H | ||
12 | #define ASM_ARC_DMA_MAPPING_H | ||
13 | |||
14 | #include <asm-generic/dma-coherent.h> | ||
15 | #include <asm/cacheflush.h> | ||
16 | #include <plat/dma_addr.h> | ||
17 | |||
18 | void *dma_alloc_noncoherent(struct device *dev, size_t size, | ||
19 | dma_addr_t *dma_handle, gfp_t gfp); | ||
20 | |||
21 | void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, | ||
22 | dma_addr_t dma_handle); | ||
23 | |||
24 | void *dma_alloc_coherent(struct device *dev, size_t size, | ||
25 | dma_addr_t *dma_handle, gfp_t gfp); | ||
26 | |||
27 | void dma_free_coherent(struct device *dev, size_t size, void *kvaddr, | ||
28 | dma_addr_t dma_handle); | ||
29 | |||
30 | /* drivers/base/dma-mapping.c */ | ||
31 | extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, | ||
32 | void *cpu_addr, dma_addr_t dma_addr, size_t size); | ||
33 | extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, | ||
34 | void *cpu_addr, dma_addr_t dma_addr, | ||
35 | size_t size); | ||
36 | |||
37 | #define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) | ||
38 | #define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) | ||
39 | |||
40 | /* | ||
41 | * streaming DMA Mapping API... | ||
42 | * CPU accesses page via normal paddr, thus needs to explicitly made | ||
43 | * consistent before each use | ||
44 | */ | ||
45 | |||
46 | static inline void __inline_dma_cache_sync(unsigned long paddr, size_t size, | ||
47 | enum dma_data_direction dir) | ||
48 | { | ||
49 | switch (dir) { | ||
50 | case DMA_FROM_DEVICE: | ||
51 | dma_cache_inv(paddr, size); | ||
52 | break; | ||
53 | case DMA_TO_DEVICE: | ||
54 | dma_cache_wback(paddr, size); | ||
55 | break; | ||
56 | case DMA_BIDIRECTIONAL: | ||
57 | dma_cache_wback_inv(paddr, size); | ||
58 | break; | ||
59 | default: | ||
60 | pr_err("Invalid DMA dir [%d] for OP @ %lx\n", dir, paddr); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void __arc_dma_cache_sync(unsigned long paddr, size_t size, | ||
65 | enum dma_data_direction dir); | ||
66 | |||
67 | #define _dma_cache_sync(addr, sz, dir) \ | ||
68 | do { \ | ||
69 | if (__builtin_constant_p(dir)) \ | ||
70 | __inline_dma_cache_sync(addr, sz, dir); \ | ||
71 | else \ | ||
72 | __arc_dma_cache_sync(addr, sz, dir); \ | ||
73 | } \ | ||
74 | while (0); | ||
75 | |||
76 | static inline dma_addr_t | ||
77 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | ||
78 | enum dma_data_direction dir) | ||
79 | { | ||
80 | _dma_cache_sync((unsigned long)cpu_addr, size, dir); | ||
81 | return plat_kernel_addr_to_dma(dev, cpu_addr); | ||
82 | } | ||
83 | |||
84 | static inline void | ||
85 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
86 | size_t size, enum dma_data_direction dir) | ||
87 | { | ||
88 | } | ||
89 | |||
90 | static inline dma_addr_t | ||
91 | dma_map_page(struct device *dev, struct page *page, | ||
92 | unsigned long offset, size_t size, | ||
93 | enum dma_data_direction dir) | ||
94 | { | ||
95 | unsigned long paddr = page_to_phys(page) + offset; | ||
96 | return dma_map_single(dev, (void *)paddr, size, dir); | ||
97 | } | ||
98 | |||
99 | static inline void | ||
100 | dma_unmap_page(struct device *dev, dma_addr_t dma_handle, | ||
101 | size_t size, enum dma_data_direction dir) | ||
102 | { | ||
103 | } | ||
104 | |||
105 | static inline int | ||
106 | dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
107 | int nents, enum dma_data_direction dir) | ||
108 | { | ||
109 | struct scatterlist *s; | ||
110 | int i; | ||
111 | |||
112 | for_each_sg(sg, s, nents, i) | ||
113 | sg->dma_address = dma_map_page(dev, sg_page(s), s->offset, | ||
114 | s->length, dir); | ||
115 | |||
116 | return nents; | ||
117 | } | ||
118 | |||
119 | static inline void | ||
120 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
121 | int nents, enum dma_data_direction dir) | ||
122 | { | ||
123 | struct scatterlist *s; | ||
124 | int i; | ||
125 | |||
126 | for_each_sg(sg, s, nents, i) | ||
127 | dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); | ||
128 | } | ||
129 | |||
130 | static inline void | ||
131 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
132 | size_t size, enum dma_data_direction dir) | ||
133 | { | ||
134 | _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle), size, | ||
135 | DMA_FROM_DEVICE); | ||
136 | } | ||
137 | |||
138 | static inline void | ||
139 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, | ||
140 | size_t size, enum dma_data_direction dir) | ||
141 | { | ||
142 | _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle), size, | ||
143 | DMA_TO_DEVICE); | ||
144 | } | ||
145 | |||
146 | static inline void | ||
147 | dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
148 | unsigned long offset, size_t size, | ||
149 | enum dma_data_direction direction) | ||
150 | { | ||
151 | _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle) + offset, | ||
152 | size, DMA_FROM_DEVICE); | ||
153 | } | ||
154 | |||
155 | static inline void | ||
156 | dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, | ||
157 | unsigned long offset, size_t size, | ||
158 | enum dma_data_direction direction) | ||
159 | { | ||
160 | _dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle) + offset, | ||
161 | size, DMA_TO_DEVICE); | ||
162 | } | ||
163 | |||
164 | static inline void | ||
165 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, | ||
166 | enum dma_data_direction dir) | ||
167 | { | ||
168 | int i; | ||
169 | |||
170 | for (i = 0; i < nelems; i++, sg++) | ||
171 | _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir); | ||
172 | } | ||
173 | |||
174 | static inline void | ||
175 | dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, | ||
176 | enum dma_data_direction dir) | ||
177 | { | ||
178 | int i; | ||
179 | |||
180 | for (i = 0; i < nelems; i++, sg++) | ||
181 | _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir); | ||
182 | } | ||
183 | |||
184 | static inline int dma_supported(struct device *dev, u64 dma_mask) | ||
185 | { | ||
186 | /* Support 32 bit DMA mask exclusively */ | ||
187 | return dma_mask == DMA_BIT_MASK(32); | ||
188 | } | ||
189 | |||
190 | static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
191 | { | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | ||
196 | { | ||
197 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | ||
198 | return -EIO; | ||
199 | |||
200 | *dev->dma_mask = dma_mask; | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | #endif | ||
diff --git a/arch/arc/include/asm/dma.h b/arch/arc/include/asm/dma.h new file mode 100644 index 000000000000..ca7c45181de9 --- /dev/null +++ b/arch/arc/include/asm/dma.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef ASM_ARC_DMA_H | ||
10 | #define ASM_ARC_DMA_H | ||
11 | |||
12 | #define MAX_DMA_ADDRESS 0xC0000000 | ||
13 | |||
14 | #endif | ||
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h new file mode 100644 index 000000000000..d20051bbbf02 --- /dev/null +++ b/arch/arc/include/asm/io.h | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _ASM_ARC_IO_H | ||
10 | #define _ASM_ARC_IO_H | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | #include <asm/byteorder.h> | ||
14 | #include <asm/page.h> | ||
15 | |||
16 | #define PCI_IOBASE ((void __iomem *)0) | ||
17 | |||
18 | extern void __iomem *ioremap(unsigned long physaddr, unsigned long size); | ||
19 | extern void iounmap(const void __iomem *addr); | ||
20 | |||
21 | #define ioremap_nocache(phy, sz) ioremap(phy, sz) | ||
22 | #define ioremap_wc(phy, sz) ioremap(phy, sz) | ||
23 | |||
24 | /* Change struct page to physical address */ | ||
25 | #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) | ||
26 | |||
27 | #define __raw_readb __raw_readb | ||
28 | static inline u8 __raw_readb(const volatile void __iomem *addr) | ||
29 | { | ||
30 | u8 b; | ||
31 | |||
32 | __asm__ __volatile__( | ||
33 | " ldb%U1 %0, %1 \n" | ||
34 | : "=r" (b) | ||
35 | : "m" (*(volatile u8 __force *)addr) | ||
36 | : "memory"); | ||
37 | |||
38 | return b; | ||
39 | } | ||
40 | |||
41 | #define __raw_readw __raw_readw | ||
42 | static inline u16 __raw_readw(const volatile void __iomem *addr) | ||
43 | { | ||
44 | u16 s; | ||
45 | |||
46 | __asm__ __volatile__( | ||
47 | " ldw%U1 %0, %1 \n" | ||
48 | : "=r" (s) | ||
49 | : "m" (*(volatile u16 __force *)addr) | ||
50 | : "memory"); | ||
51 | |||
52 | return s; | ||
53 | } | ||
54 | |||
55 | #define __raw_readl __raw_readl | ||
56 | static inline u32 __raw_readl(const volatile void __iomem *addr) | ||
57 | { | ||
58 | u32 w; | ||
59 | |||
60 | __asm__ __volatile__( | ||
61 | " ld%U1 %0, %1 \n" | ||
62 | : "=r" (w) | ||
63 | : "m" (*(volatile u32 __force *)addr) | ||
64 | : "memory"); | ||
65 | |||
66 | return w; | ||
67 | } | ||
68 | |||
69 | #define __raw_writeb __raw_writeb | ||
70 | static inline void __raw_writeb(u8 b, volatile void __iomem *addr) | ||
71 | { | ||
72 | __asm__ __volatile__( | ||
73 | " stb%U1 %0, %1 \n" | ||
74 | : | ||
75 | : "r" (b), "m" (*(volatile u8 __force *)addr) | ||
76 | : "memory"); | ||
77 | } | ||
78 | |||
79 | #define __raw_writew __raw_writew | ||
80 | static inline void __raw_writew(u16 s, volatile void __iomem *addr) | ||
81 | { | ||
82 | __asm__ __volatile__( | ||
83 | " stw%U1 %0, %1 \n" | ||
84 | : | ||
85 | : "r" (s), "m" (*(volatile u16 __force *)addr) | ||
86 | : "memory"); | ||
87 | |||
88 | } | ||
89 | |||
90 | #define __raw_writel __raw_writel | ||
91 | static inline void __raw_writel(u32 w, volatile void __iomem *addr) | ||
92 | { | ||
93 | __asm__ __volatile__( | ||
94 | " st%U1 %0, %1 \n" | ||
95 | : | ||
96 | : "r" (w), "m" (*(volatile u32 __force *)addr) | ||
97 | : "memory"); | ||
98 | |||
99 | } | ||
100 | |||
101 | #include <asm-generic/io.h> | ||
102 | |||
103 | #endif /* _ASM_ARC_IO_H */ | ||
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c new file mode 100644 index 000000000000..12cc6485b218 --- /dev/null +++ b/arch/arc/mm/dma.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * DMA Coherent API Notes | ||
11 | * | ||
12 | * I/O is inherently non-coherent on ARC. So a coherent DMA buffer is | ||
13 | * implemented by accessintg it using a kernel virtual address, with | ||
14 | * Cache bit off in the TLB entry. | ||
15 | * | ||
16 | * The default DMA address == Phy address which is 0x8000_0000 based. | ||
17 | * A platform/device can make it zero based, by over-riding | ||
18 | * plat_{dma,kernel}_addr_to_{kernel,dma} | ||
19 | */ | ||
20 | |||
21 | #include <linux/dma-mapping.h> | ||
22 | #include <linux/dma-debug.h> | ||
23 | #include <linux/export.h> | ||
24 | #include <asm/cacheflush.h> | ||
25 | |||
26 | /* | ||
27 | * Helpers for Coherent DMA API. | ||
28 | */ | ||
29 | void *dma_alloc_noncoherent(struct device *dev, size_t size, | ||
30 | dma_addr_t *dma_handle, gfp_t gfp) | ||
31 | { | ||
32 | void *paddr; | ||
33 | |||
34 | /* This is linear addr (0x8000_0000 based) */ | ||
35 | paddr = alloc_pages_exact(size, gfp); | ||
36 | if (!paddr) | ||
37 | return NULL; | ||
38 | |||
39 | /* This is bus address, platform dependent */ | ||
40 | *dma_handle = plat_kernel_addr_to_dma(dev, paddr); | ||
41 | |||
42 | return paddr; | ||
43 | } | ||
44 | EXPORT_SYMBOL(dma_alloc_noncoherent); | ||
45 | |||
46 | void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, | ||
47 | dma_addr_t dma_handle) | ||
48 | { | ||
49 | free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle), | ||
50 | size); | ||
51 | } | ||
52 | EXPORT_SYMBOL(dma_free_noncoherent); | ||
53 | |||
54 | void *dma_alloc_coherent(struct device *dev, size_t size, | ||
55 | dma_addr_t *dma_handle, gfp_t gfp) | ||
56 | { | ||
57 | void *paddr, *kvaddr; | ||
58 | |||
59 | /* This is linear addr (0x8000_0000 based) */ | ||
60 | paddr = alloc_pages_exact(size, gfp); | ||
61 | if (!paddr) | ||
62 | return NULL; | ||
63 | |||
64 | /* This is kernel Virtual address (0x7000_0000 based) */ | ||
65 | kvaddr = ioremap_nocache((unsigned long)paddr, size); | ||
66 | if (kvaddr != NULL) | ||
67 | memset(kvaddr, 0, size); | ||
68 | |||
69 | /* This is bus address, platform dependent */ | ||
70 | *dma_handle = plat_kernel_addr_to_dma(dev, paddr); | ||
71 | |||
72 | return kvaddr; | ||
73 | } | ||
74 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
75 | |||
76 | void dma_free_coherent(struct device *dev, size_t size, void *kvaddr, | ||
77 | dma_addr_t dma_handle) | ||
78 | { | ||
79 | iounmap((void __force __iomem *)kvaddr); | ||
80 | |||
81 | free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle), | ||
82 | size); | ||
83 | } | ||
84 | EXPORT_SYMBOL(dma_free_coherent); | ||
85 | |||
86 | /* | ||
87 | * Helper for streaming DMA... | ||
88 | */ | ||
89 | void __arc_dma_cache_sync(unsigned long paddr, size_t size, | ||
90 | enum dma_data_direction dir) | ||
91 | { | ||
92 | __inline_dma_cache_sync(paddr, size, dir); | ||
93 | } | ||
94 | EXPORT_SYMBOL(__arc_dma_cache_sync); | ||
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c new file mode 100644 index 000000000000..52518b6d0f28 --- /dev/null +++ b/arch/arc/mm/ioremap.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/vmalloc.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <asm/cache.h> | ||
16 | |||
17 | void __iomem *ioremap(unsigned long paddr, unsigned long size) | ||
18 | { | ||
19 | unsigned long vaddr; | ||
20 | struct vm_struct *area; | ||
21 | unsigned long off, end; | ||
22 | const pgprot_t prot = PAGE_KERNEL_NO_CACHE; | ||
23 | |||
24 | /* Don't allow wraparound or zero size */ | ||
25 | end = paddr + size - 1; | ||
26 | if (!size || (end < paddr)) | ||
27 | return NULL; | ||
28 | |||
29 | /* If the region is h/w uncached, nothing special needed */ | ||
30 | if (paddr >= ARC_UNCACHED_ADDR_SPACE) | ||
31 | return (void __iomem *)paddr; | ||
32 | |||
33 | /* An early platform driver might end up here */ | ||
34 | if (!slab_is_available()) | ||
35 | return NULL; | ||
36 | |||
37 | /* Mappings have to be page-aligned, page-sized */ | ||
38 | off = paddr & ~PAGE_MASK; | ||
39 | paddr &= PAGE_MASK; | ||
40 | size = PAGE_ALIGN(end + 1) - paddr; | ||
41 | |||
42 | /* | ||
43 | * Ok, go for it.. | ||
44 | */ | ||
45 | area = get_vm_area(size, VM_IOREMAP); | ||
46 | if (!area) | ||
47 | return NULL; | ||
48 | |||
49 | area->phys_addr = paddr; | ||
50 | vaddr = (unsigned long)area->addr; | ||
51 | if (ioremap_page_range(vaddr, vaddr + size, paddr, prot)) { | ||
52 | vfree(area->addr); | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | return (void __iomem *)(off + (char __iomem *)vaddr); | ||
57 | } | ||
58 | EXPORT_SYMBOL(ioremap); | ||
59 | |||
60 | void iounmap(const void __iomem *addr) | ||
61 | { | ||
62 | if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE) | ||
63 | return; | ||
64 | |||
65 | vfree((void *)(PAGE_MASK & (unsigned long __force)addr)); | ||
66 | } | ||
67 | EXPORT_SYMBOL(iounmap); | ||
diff --git a/arch/arc/plat-arcfpga/include/plat/dma_addr.h b/arch/arc/plat-arcfpga/include/plat/dma_addr.h new file mode 100644 index 000000000000..0e963431b729 --- /dev/null +++ b/arch/arc/plat-arcfpga/include/plat/dma_addr.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * vineetg: Feb 2009 | ||
9 | * -For AA4 board, kernel to DMA address APIs | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * kernel addresses are 0x800_000 based, while Bus addr are 0 based | ||
14 | */ | ||
15 | |||
16 | #ifndef __PLAT_DMA_ADDR_H | ||
17 | #define __PLAT_DMA_ADDR_H | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | |||
21 | static inline unsigned long plat_dma_addr_to_kernel(struct device *dev, | ||
22 | dma_addr_t dma_addr) | ||
23 | { | ||
24 | return dma_addr + PAGE_OFFSET; | ||
25 | } | ||
26 | |||
27 | static inline dma_addr_t plat_kernel_addr_to_dma(struct device *dev, void *ptr) | ||
28 | { | ||
29 | unsigned long addr = (unsigned long)ptr; | ||
30 | /* | ||
31 | * To Catch buggy drivers which can call DMA map API with kernel vaddr | ||
32 | * i.e. for buffers alloc via vmalloc or ioremap which are not | ||
33 | * gaurnateed to be PHY contiguous and hence unfit for DMA anyways. | ||
34 | * On ARC kernel virtual address is 0x7000_0000 to 0x7FFF_FFFF, so | ||
35 | * ideally we want to check this range here, but our implementation is | ||
36 | * better as it checks for even worse user virtual address as well. | ||
37 | */ | ||
38 | if (likely(addr >= PAGE_OFFSET)) | ||
39 | return addr - PAGE_OFFSET; | ||
40 | |||
41 | BUG(); | ||
42 | return addr; | ||
43 | } | ||
44 | |||
45 | #endif | ||