aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/include/mach/iovmm.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/include/mach/iovmm.h')
-rw-r--r--arch/arm/mach-tegra/include/mach/iovmm.h323
1 files changed, 323 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/include/mach/iovmm.h b/arch/arm/mach-tegra/include/mach/iovmm.h
new file mode 100644
index 00000000000..fd83a326e12
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/iovmm.h
@@ -0,0 +1,323 @@
1/*
2 * arch/arm/mach-tegra/include/mach/iovmm.h
3 *
4 * Copyright (c) 2010-2011, 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
32typedef u32 tegra_iovmm_addr_t;
33
34struct tegra_iovmm_device_ops;
35
36/*
37 * each I/O virtual memory manager unit should register a device with
38 * the iovmm system
39 */
40struct 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 */
52struct 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
69struct iovmm_share_group;
70
71struct 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
85struct 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
93struct 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
125struct 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 */
143struct tegra_iovmm_client *tegra_iovmm_alloc_client(const char *name,
144 const char *share_group, struct miscdevice *misc_dev);
145
146size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client);
147
148void tegra_iovmm_free_client(struct tegra_iovmm_client *client);
149
150/*
151 * called by clients to ensure that their mapping context is resident
152 * before performing any DMA operations addressing I/O VMM regions.
153 * client_lock may return -EINTR.
154 */
155int tegra_iovmm_client_lock(struct tegra_iovmm_client *client);
156int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client);
157
158/* called by clients after DMA operations are complete */
159void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client);
160
161/*
162 * called by clients to allocate a new iovmm_area and reserve I/O virtual
163 * address space for it. if ops is NULL, clients should subsequently call
164 * tegra_iovmm_vm_map_pages and/or tegra_iovmm_vm_insert_pfn to explicitly
165 * map the I/O virtual address to an OS-allocated page or physical address,
166 * respectively. VM operations may be called before this call returns
167 */
168struct tegra_iovmm_area *tegra_iovmm_create_vm(
169 struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
170 size_t size, size_t align, pgprot_t pgprot, unsigned long iovm_start);
171
172/*
173 * called by clients to "zap" an iovmm_area, and replace all mappings
174 * in it with invalid ones, without freeing the virtual address range
175 */
176void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm);
177
178/*
179 * after zapping a demand-loaded iovmm_area, the client should unzap it
180 * to allow the VMM device to remap the page range.
181 */
182void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm);
183
184/* called by clients to return an iovmm_area to the free pool for the domain */
185void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm);
186
187/* returns size of largest free iovm block */
188size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client);
189
190/*
191 * called by client software to map the page-aligned I/O address vaddr to
192 * a specific physical address pfn. I/O VMA should have been created with
193 * a NULL tegra_iovmm_area_ops structure.
194 */
195void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
196 tegra_iovmm_addr_t vaddr, unsigned long pfn);
197
198/*
199 * called by clients to return the iovmm_area containing addr, or NULL if
200 * addr has not been allocated. caller should call tegra_iovmm_area_put when
201 * finished using the returned pointer
202 */
203struct tegra_iovmm_area *tegra_iovmm_find_area_get(
204 struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr);
205
206struct tegra_iovmm_area *tegra_iovmm_area_get(struct tegra_iovmm_area *vm);
207void tegra_iovmm_area_put(struct tegra_iovmm_area *vm);
208
209/* called by drivers to initialize a tegra_iovmm_domain structure */
210int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
211 struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
212 tegra_iovmm_addr_t end);
213
214/* called by drivers to register an I/O VMM device with the system */
215int tegra_iovmm_register(struct tegra_iovmm_device *dev);
216
217/* called by drivers to remove an I/O VMM device from the system */
218int tegra_iovmm_unregister(struct tegra_iovmm_device *dev);
219
220#else /* CONFIG_TEGRA_IOVMM */
221
222static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
223 const char *name, const char *share_group, struct miscdevice *misc_dev)
224{
225 return NULL;
226}
227
228static inline size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client)
229{
230 return 0;
231}
232
233static inline void tegra_iovmm_free_client(struct tegra_iovmm_client *client)
234{
235}
236
237static inline int tegra_iovmm_client_lock(struct tegra_iovmm_client *client)
238{
239 return 0;
240}
241
242static inline int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client)
243{
244 return 0;
245}
246
247static inline void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client)
248{
249}
250
251static inline struct tegra_iovmm_area *tegra_iovmm_create_vm(
252 struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops,
253 size_t size, size_t align, pgprot_t pgprot, unsigned long iovm_start)
254{
255 return NULL;
256}
257
258static inline void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm)
259{
260}
261
262static inline void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm)
263{
264}
265
266static inline void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm)
267{
268}
269
270static inline size_t tegra_iovmm_get_max_free(struct tegra_iovmm_client *client)
271{
272 return 0;
273}
274
275static inline void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area,
276 tegra_iovmm_addr_t vaddr, unsigned long pfn)
277{
278}
279
280static inline struct tegra_iovmm_area *tegra_iovmm_find_area_get(
281 struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr)
282{
283 return NULL;
284}
285
286static inline struct tegra_iovmm_area *tegra_iovmm_area_get(
287 struct tegra_iovmm_area *vm)
288{
289 return NULL;
290}
291
292static inline void tegra_iovmm_area_put(struct tegra_iovmm_area *vm)
293{
294}
295
296static inline int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain,
297 struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start,
298 tegra_iovmm_addr_t end)
299{
300 return 0;
301}
302
303static inline int tegra_iovmm_register(struct tegra_iovmm_device *dev)
304{
305 return 0;
306}
307
308static inline int tegra_iovmm_unregister(struct tegra_iovmm_device *dev)
309{
310 return 0;
311}
312
313static inline int tegra_iovmm_suspend(void)
314{
315 return 0;
316}
317
318static inline void tegra_iovmm_resume(void)
319{
320}
321
322#endif /* CONFIG_TEGRA_IOVMM */
323#endif /* _MACH_TEGRA_IOVMM_H_*/