ARM: tegra: iovmm: Allow alloc_client to take struct device
[linux-2.6.git] / arch / arm / mach-tegra / include / mach / iovmm.h
1 /*
2  * arch/arm/mach-tegra/include/mach/iovmm.h
3  *
4  * Copyright (c) 2010-2012, NVIDIA Corporation.
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 as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed i the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/list.h>
22 #include <linux/platform_device.h>
23 #include <linux/miscdevice.h>
24 #include <linux/rbtree.h>
25 #include <linux/rwsem.h>
26 #include <linux/spinlock.h>
27 #include <linux/types.h>
28
29 #ifndef _MACH_TEGRA_IOVMM_H_
30 #define _MACH_TEGRA_IOVMM_H_
31
32 typedef u32 tegra_iovmm_addr_t;
33
34 struct tegra_iovmm_device_ops;
35
36 /*
37  * each I/O virtual memory manager unit should register a device with
38  * the iovmm system
39  */
40 struct tegra_iovmm_device {
41         struct tegra_iovmm_device_ops   *ops;
42         const char                      *name;
43         struct list_head                list;
44         int                             pgsize_bits;
45 };
46
47 /*
48  * tegra_iovmm_domain serves a purpose analagous to mm_struct as defined in
49  * <linux/mm_types.h> - it defines a virtual address space within which
50  * tegra_iovmm_areas can be created.
51  */
52 struct tegra_iovmm_domain {
53         atomic_t                clients;
54         atomic_t                locks;
55         spinlock_t              block_lock;  /* RB-tree for iovmm_area blocks */
56         unsigned long           flags;
57         wait_queue_head_t       delay_lock;  /* when lock_client fails */
58         struct rw_semaphore     map_lock;
59         struct rb_root          all_blocks;  /* ordered by address */
60         struct rb_root          free_blocks; /* ordered by size */
61         struct tegra_iovmm_device *dev;
62 };
63
64 /*
65  * tegra_iovmm_client is analagous to an individual task in the task group
66  * which owns an mm_struct.
67  */
68
69 struct iovmm_share_group;
70
71 struct tegra_iovmm_client {
72         const char                      *name;
73         unsigned long                   flags;
74         struct iovmm_share_group        *group;
75         struct tegra_iovmm_domain       *domain;
76         struct miscdevice               *misc_dev;
77         struct list_head                list;
78 };
79
80 /*
81  * tegra_iovmm_area serves a purpose analagous to vm_area_struct as defined
82  * in <linux/mm_types.h> - it defines a virtual memory area which can be
83  * mapped to physical memory by a client-provided mapping function. */
84
85 struct tegra_iovmm_area {
86         struct tegra_iovmm_domain       *domain;
87         tegra_iovmm_addr_t              iovm_start;
88         size_t                          iovm_length;
89         pgprot_t                        pgprot;
90         struct tegra_iovmm_area_ops     *ops;
91 };
92
93 struct tegra_iovmm_device_ops {
94         /* maps a VMA using the page residency functions provided by the VMA */
95         int (*map)(struct tegra_iovmm_domain *domain,
96                 struct tegra_iovmm_area *io_vma);
97         /* marks all PTEs in a VMA as invalid; decommits the virtual addres
98          * space (potentially freeing PDEs when decommit is true.) */
99         void (*unmap)(struct tegra_iovmm_domain *domain,
100                 struct tegra_iovmm_area *io_vma, bool decommit);
101         void (*map_pfn)(struct tegra_iovmm_domain *domain,
102                 struct tegra_iovmm_area *io_vma,
103                 unsigned long offs, unsigned long pfn);
104         /*
105          * ensures that a domain is resident in the hardware's mapping region
106          * so that it may be used by a client
107          */
108         int (*lock_domain)(struct tegra_iovmm_domain *domain,
109                 struct tegra_iovmm_client *client);
110         void (*unlock_domain)(struct tegra_iovmm_domain *domain,
111                 struct tegra_iovmm_client *client);
112         /*
113          * allocates a vmm_domain for the specified client; may return the same
114          * domain for multiple clients
115          */
116         struct tegra_iovmm_domain* (*alloc_domain)(
117                 struct tegra_iovmm_device *dev,
118                 struct tegra_iovmm_client *client);
119         void (*free_domain)(struct tegra_iovmm_domain *domain,
120                 struct tegra_iovmm_client *client);
121         int (*suspend)(struct tegra_iovmm_device *dev);
122         void (*resume)(struct tegra_iovmm_device *dev);
123 };
124
125 struct tegra_iovmm_area_ops {
126         /*
127          * ensures that the page of data starting at the specified offset
128          * from the start of the iovma is resident and pinned for use by
129          * DMA, returns the system pfn, or an invalid pfn if the
130          * operation fails.
131          */
132         unsigned long (*lock_makeresident)(struct tegra_iovmm_area *area,
133                 tegra_iovmm_addr_t offs);
134         /* called when the page is unmapped from the I/O VMA */
135         void (*release)(struct tegra_iovmm_area *area, tegra_iovmm_addr_t offs);
136 };
137
138 #ifdef CONFIG_TEGRA_IOVMM
139 /*
140  * called by clients to allocate an I/O VMM client mapping context which
141  * will be shared by all clients in the same share_group
142  */
143 struct tegra_iovmm_client *__tegra_iovmm_alloc_client(const char *name,
144         const char *share_group, struct miscdevice *misc_dev);
145
146 static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
147         struct device *dev, const char *share_group,
148         struct miscdevice *misc_dev)
149 {
150         return __tegra_iovmm_alloc_client(dev_name(dev), share_group, misc_dev);
151 }
152
153 size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client);
154
155 void tegra_iovmm_free_client(struct tegra_iovmm_client *client);
156
157 /*
158  * called by clients to ensure that their mapping context is resident
159  * before performing any DMA operations addressing I/O VMM regions.
160  * client_lock may return -EINTR.
161  */
162 int tegra_iovmm_client_lock(struct tegra_iovmm_client *client);
163 int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client);
164
165 /* called by clients after DMA operations are complete */
166 void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client);
167
168 /*
169  * called by clients to allocate a new iovmm_area and reserve I/O virtual
170  * address space for it. if ops is NULL, clients should subsequently call
171  * tegra_iovmm_vm_map_pages and/or tegra_iovmm_vm_insert_pfn to explicitly
172  * map the I/O virtual address to an OS-allocated page or physical address,
173  * respectively. VM operations may be called before this call returns
174  */
175 struct tegra_iovmm_area *tegra_iovmm_create_vm(
176         struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
177         size_t size, size_t align, pgprot_t pgprot, unsigned long iovm_start);
178
179 /*
180  * called by clients to "zap" an iovmm_area, and replace all mappings
181  * in it with invalid ones, without freeing the virtual address range
182  */
183 void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm);
184
185 /*
186  * after zapping a demand-loaded iovmm_area, the client should unzap it
187  * to allow the VMM device to remap the page range.
188  */
189 void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm);
190
191 /* called by clients to return an iovmm_area to the free pool for the domain */
192 void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm);
193
194 /* returns size of largest free iovm block */
195 size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client);
196
197 /*
198  * called by client software to map the page-aligned I/O address vaddr to
199  * a specific physical address pfn. I/O VMA should have been created with
200  * a NULL tegra_iovmm_area_ops structure.
201  */
202 void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
203         tegra_iovmm_addr_t vaddr, unsigned long pfn);
204
205 /*
206  * called by clients to return the iovmm_area containing addr, or NULL if
207  * addr has not been allocated. caller should call tegra_iovmm_area_put when
208  * finished using the returned pointer
209  */
210 struct tegra_iovmm_area *tegra_iovmm_find_area_get(
211         struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr);
212
213 struct tegra_iovmm_area *tegra_iovmm_area_get(struct tegra_iovmm_area *vm);
214 void tegra_iovmm_area_put(struct tegra_iovmm_area *vm);
215
216 /* called by drivers to initialize a tegra_iovmm_domain structure */
217 int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
218         struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
219         tegra_iovmm_addr_t end);
220
221 /* called by drivers to register an I/O VMM device with the system */
222 int tegra_iovmm_register(struct tegra_iovmm_device *dev);
223
224 /* called by drivers to remove an I/O VMM device from the system */
225 int tegra_iovmm_unregister(struct tegra_iovmm_device *dev);
226
227 #else /* CONFIG_TEGRA_IOVMM */
228
229 static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
230         const char *name, const char *share_group, struct miscdevice *misc_dev)
231 {
232         return NULL;
233 }
234
235 static inline size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client)
236 {
237         return 0;
238 }
239
240 static inline void tegra_iovmm_free_client(struct tegra_iovmm_client *client)
241 {
242 }
243
244 static inline int tegra_iovmm_client_lock(struct tegra_iovmm_client *client)
245 {
246         return 0;
247 }
248
249 static inline int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client)
250 {
251         return 0;
252 }
253
254 static inline void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client)
255 {
256 }
257
258 static inline struct tegra_iovmm_area *tegra_iovmm_create_vm(
259         struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
260         size_t size, size_t align, pgprot_t pgprot, unsigned long iovm_start)
261 {
262         return NULL;
263 }
264
265 static inline void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm)
266 {
267 }
268
269 static inline void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm)
270 {
271 }
272
273 static inline void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm)
274 {
275 }
276
277 static inline size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client)
278 {
279         return 0;
280 }
281
282 static inline void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
283         tegra_iovmm_addr_t vaddr, unsigned long pfn)
284 {
285 }
286
287 static inline struct tegra_iovmm_area *tegra_iovmm_find_area_get(
288         struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr)
289 {
290         return NULL;
291 }
292
293 static inline struct tegra_iovmm_area *tegra_iovmm_area_get(
294         struct tegra_iovmm_area *vm)
295 {
296         return NULL;
297 }
298
299 static inline void tegra_iovmm_area_put(struct tegra_iovmm_area *vm)
300 {
301 }
302
303 static inline int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
304         struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
305         tegra_iovmm_addr_t end)
306 {
307         return 0;
308 }
309
310 static inline int tegra_iovmm_register(struct tegra_iovmm_device *dev)
311 {
312         return 0;
313 }
314
315 static inline int tegra_iovmm_unregister(struct tegra_iovmm_device *dev)
316 {
317         return 0;
318 }
319
320 static inline int tegra_iovmm_suspend(void)
321 {
322         return 0;
323 }
324
325 static inline void tegra_iovmm_resume(void)
326 {
327 }
328
329 #endif /* CONFIG_TEGRA_IOVMM */
330 #endif /* _MACH_TEGRA_IOVMM_H_*/