aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-08-19 11:54:26 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2016-08-19 12:13:35 -0400
commitcafaf14a5d8f152ed3c984ecd48dee6e824446bc (patch)
tree3053466d3791ede38d33e61f34b8541bae8d3a43
parent8678fdaf396c3aa3732b3d98ce2241633dbc26ba (diff)
io-mapping: Always create a struct to hold metadata about the io-mapping
Currently, we only allocate a structure to hold metadata if we need to allocate an ioremap for every access, such as on x86-32. However, it would be useful to store basic information about the io-mapping, such as its page protection, on all platforms. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: linux-mm@kvack.org Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20160819155428.1670-4-chris@chris-wilson.co.uk
-rw-r--r--include/linux/io-mapping.h92
1 files changed, 57 insertions, 35 deletions
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
index 645ad06b5d52..b4c4b5c4216d 100644
--- a/include/linux/io-mapping.h
+++ b/include/linux/io-mapping.h
@@ -31,16 +31,16 @@
31 * See Documentation/io-mapping.txt 31 * See Documentation/io-mapping.txt
32 */ 32 */
33 33
34#ifdef CONFIG_HAVE_ATOMIC_IOMAP
35
36#include <asm/iomap.h>
37
38struct io_mapping { 34struct io_mapping {
39 resource_size_t base; 35 resource_size_t base;
40 unsigned long size; 36 unsigned long size;
41 pgprot_t prot; 37 pgprot_t prot;
38 void __iomem *iomem;
42}; 39};
43 40
41#ifdef CONFIG_HAVE_ATOMIC_IOMAP
42
43#include <asm/iomap.h>
44/* 44/*
45 * For small address space machines, mapping large objects 45 * For small address space machines, mapping large objects
46 * into the kernel virtual space isn't practical. Where 46 * into the kernel virtual space isn't practical. Where
@@ -49,34 +49,25 @@ struct io_mapping {
49 */ 49 */
50 50
51static inline struct io_mapping * 51static inline struct io_mapping *
52io_mapping_create_wc(resource_size_t base, unsigned long size) 52io_mapping_init_wc(struct io_mapping *iomap,
53 resource_size_t base,
54 unsigned long size)
53{ 55{
54 struct io_mapping *iomap;
55 pgprot_t prot; 56 pgprot_t prot;
56 57
57 iomap = kmalloc(sizeof(*iomap), GFP_KERNEL);
58 if (!iomap)
59 goto out_err;
60
61 if (iomap_create_wc(base, size, &prot)) 58 if (iomap_create_wc(base, size, &prot))
62 goto out_free; 59 return NULL;
63 60
64 iomap->base = base; 61 iomap->base = base;
65 iomap->size = size; 62 iomap->size = size;
66 iomap->prot = prot; 63 iomap->prot = prot;
67 return iomap; 64 return iomap;
68
69out_free:
70 kfree(iomap);
71out_err:
72 return NULL;
73} 65}
74 66
75static inline void 67static inline void
76io_mapping_free(struct io_mapping *mapping) 68io_mapping_fini(struct io_mapping *mapping)
77{ 69{
78 iomap_free(mapping->base, mapping->size); 70 iomap_free(mapping->base, mapping->size);
79 kfree(mapping);
80} 71}
81 72
82/* Atomic map/unmap */ 73/* Atomic map/unmap */
@@ -121,21 +112,40 @@ io_mapping_unmap(void __iomem *vaddr)
121#else 112#else
122 113
123#include <linux/uaccess.h> 114#include <linux/uaccess.h>
124 115#include <asm/pgtable_types.h>
125/* this struct isn't actually defined anywhere */
126struct io_mapping;
127 116
128/* Create the io_mapping object*/ 117/* Create the io_mapping object*/
129static inline struct io_mapping * 118static inline struct io_mapping *
130io_mapping_create_wc(resource_size_t base, unsigned long size) 119io_mapping_init_wc(struct io_mapping *iomap,
120 resource_size_t base,
121 unsigned long size)
122{
123 iomap->base = base;
124 iomap->size = size;
125 iomap->iomem = ioremap_wc(base, size);
126 iomap->prot = pgprot_writecombine(PAGE_KERNEL_IO);
127
128 return iomap;
129}
130
131static inline void
132io_mapping_fini(struct io_mapping *mapping)
133{
134 iounmap(mapping->iomem);
135}
136
137/* Non-atomic map/unmap */
138static inline void __iomem *
139io_mapping_map_wc(struct io_mapping *mapping,
140 unsigned long offset,
141 unsigned long size)
131{ 142{
132 return (struct io_mapping __force *) ioremap_wc(base, size); 143 return mapping->iomem + offset;
133} 144}
134 145
135static inline void 146static inline void
136io_mapping_free(struct io_mapping *mapping) 147io_mapping_unmap(void __iomem *vaddr)
137{ 148{
138 iounmap((void __force __iomem *) mapping);
139} 149}
140 150
141/* Atomic map/unmap */ 151/* Atomic map/unmap */
@@ -145,30 +155,42 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping,
145{ 155{
146 preempt_disable(); 156 preempt_disable();
147 pagefault_disable(); 157 pagefault_disable();
148 return ((char __force __iomem *) mapping) + offset; 158 return io_mapping_map_wc(mapping, offset, PAGE_SIZE);
149} 159}
150 160
151static inline void 161static inline void
152io_mapping_unmap_atomic(void __iomem *vaddr) 162io_mapping_unmap_atomic(void __iomem *vaddr)
153{ 163{
164 io_mapping_unmap(vaddr);
154 pagefault_enable(); 165 pagefault_enable();
155 preempt_enable(); 166 preempt_enable();
156} 167}
157 168
158/* Non-atomic map/unmap */ 169#endif /* HAVE_ATOMIC_IOMAP */
159static inline void __iomem * 170
160io_mapping_map_wc(struct io_mapping *mapping, 171static inline struct io_mapping *
161 unsigned long offset, 172io_mapping_create_wc(resource_size_t base,
162 unsigned long size) 173 unsigned long size)
163{ 174{
164 return ((char __force __iomem *) mapping) + offset; 175 struct io_mapping *iomap;
176
177 iomap = kmalloc(sizeof(*iomap), GFP_KERNEL);
178 if (!iomap)
179 return NULL;
180
181 if (!io_mapping_init_wc(iomap, base, size)) {
182 kfree(iomap);
183 return NULL;
184 }
185
186 return iomap;
165} 187}
166 188
167static inline void 189static inline void
168io_mapping_unmap(void __iomem *vaddr) 190io_mapping_free(struct io_mapping *iomap)
169{ 191{
192 io_mapping_fini(iomap);
193 kfree(iomap);
170} 194}
171 195
172#endif /* HAVE_ATOMIC_IOMAP */
173
174#endif /* _LINUX_IO_MAPPING_H */ 196#endif /* _LINUX_IO_MAPPING_H */