OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * arch/arm/mach-tegra/include/mach/iovmm.h |
| 3 * |
| 4 * Copyright (c) 2010, 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/rbtree.h> |
| 24 #include <linux/rwsem.h> |
| 25 #include <linux/spinlock.h> |
| 26 #include <linux/types.h> |
| 27 |
| 28 #ifndef _MACH_TEGRA_IOVMM_H_ |
| 29 #define _MACH_TEGRA_IOVMM_H_ |
| 30 |
| 31 #if defined(CONFIG_ARCH_TEGRA_1x_SOC) || defined(CONFIG_ARCH_TEGRA_2x_SOC) |
| 32 typedef u32 tegra_iovmm_addr_t; |
| 33 #else |
| 34 #error "Unsupported tegra architecture family" |
| 35 #endif |
| 36 |
| 37 struct tegra_iovmm_device_ops; |
| 38 |
| 39 /* each I/O virtual memory manager unit should register a device with |
| 40 * the iovmm system |
| 41 */ |
| 42 struct tegra_iovmm_device { |
| 43 struct tegra_iovmm_device_ops *ops; |
| 44 const char *name; |
| 45 struct list_head list; |
| 46 int pgsize_bits; |
| 47 }; |
| 48 |
| 49 /* tegra_iovmm_domain serves a purpose analagous to mm_struct as defined in |
| 50 * <linux/mm_types.h> - it defines a virtual address space within which |
| 51 * tegra_iovmm_areas can be created. |
| 52 */ |
| 53 struct tegra_iovmm_domain { |
| 54 atomic_t clients; |
| 55 atomic_t locks; |
| 56 spinlock_t block_lock; |
| 57 unsigned long flags; |
| 58 wait_queue_head_t delay_lock; /* when lock_client fails */ |
| 59 struct rw_semaphore map_lock; |
| 60 struct rb_root all_blocks; /* ordered by address */ |
| 61 struct rb_root free_blocks; /* ordered by size */ |
| 62 struct tegra_iovmm_device *dev; |
| 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 list_head list; |
| 77 }; |
| 78 |
| 79 /* tegra_iovmm_area serves a purpose analagous to vm_area_struct as defined |
| 80 * in <linux/mm_types.h> - it defines a virtual memory area which can be |
| 81 * mapped to physical memory by a client-provided mapping function. */ |
| 82 |
| 83 struct tegra_iovmm_area { |
| 84 struct tegra_iovmm_domain *domain; |
| 85 tegra_iovmm_addr_t iovm_start; |
| 86 tegra_iovmm_addr_t iovm_length; |
| 87 pgprot_t pgprot; |
| 88 struct tegra_iovmm_area_ops *ops; |
| 89 }; |
| 90 |
| 91 struct tegra_iovmm_device_ops { |
| 92 /* maps a VMA using the page residency functions provided by the VMA */ |
| 93 int (*map)(struct tegra_iovmm_device *dev, |
| 94 struct tegra_iovmm_area *io_vma); |
| 95 /* marks all PTEs in a VMA as invalid; decommits the virtual addres |
| 96 * space (potentially freeing PDEs when decommit is true.) */ |
| 97 void (*unmap)(struct tegra_iovmm_device *dev, |
| 98 struct tegra_iovmm_area *io_vma, bool decommit); |
| 99 void (*map_pfn)(struct tegra_iovmm_device *dev, |
| 100 struct tegra_iovmm_area *io_vma, |
| 101 tegra_iovmm_addr_t offs, unsigned long pfn); |
| 102 /* ensures that a domain is resident in the hardware's mapping region |
| 103 * so that it may be used by a client */ |
| 104 int (*lock_domain)(struct tegra_iovmm_device *dev, |
| 105 struct tegra_iovmm_domain *domain); |
| 106 void (*unlock_domain)(struct tegra_iovmm_device *dev, |
| 107 struct tegra_iovmm_domain *domain); |
| 108 /* allocates a vmm_domain for the specified client; may return the same |
| 109 * domain for multiple clients */ |
| 110 struct tegra_iovmm_domain* (*alloc_domain)( |
| 111 struct tegra_iovmm_device *dev, |
| 112 struct tegra_iovmm_client *client); |
| 113 void (*free_domain)(struct tegra_iovmm_device *dev, |
| 114 struct tegra_iovmm_domain *domain); |
| 115 }; |
| 116 |
| 117 struct tegra_iovmm_area_ops { |
| 118 /* ensures that the page of data starting at the specified offset |
| 119 * from the start of the iovma is resident and pinned for use by |
| 120 * DMA, returns the system pfn, or an invalid pfn if the |
| 121 * operation fails. */ |
| 122 unsigned long (*lock_makeresident)(struct tegra_iovmm_area *area, |
| 123 tegra_iovmm_addr_t offs); |
| 124 /* called when the page is unmapped from the I/O VMA */ |
| 125 void (*release)(struct tegra_iovmm_area *area, tegra_iovmm_addr_t offs); |
| 126 }; |
| 127 |
| 128 #ifdef CONFIG_TEGRA_IOVMM |
| 129 /* called by clients to allocate an I/O VMM client mapping context which |
| 130 * will be shared by all clients in the same share_group */ |
| 131 struct tegra_iovmm_client *tegra_iovmm_alloc_client(const char *name, |
| 132 const char *share_group); |
| 133 |
| 134 size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client); |
| 135 |
| 136 void tegra_iovmm_free_client(struct tegra_iovmm_client *client); |
| 137 |
| 138 /* called by clients to ensure that their mapping context is resident |
| 139 * before performing any DMA operations addressing I/O VMM regions. |
| 140 * client_lock may return -EINTR. */ |
| 141 int tegra_iovmm_client_lock(struct tegra_iovmm_client *client); |
| 142 int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client); |
| 143 |
| 144 /* called by clients after DMA operations are complete */ |
| 145 void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client); |
| 146 |
| 147 /* called by clients to allocate a new iovmm_area and reserve I/O virtual |
| 148 * address space for it. if ops is NULL, clients should subsequently call |
| 149 * tegra_iovmm_vm_map_pages and/or tegra_iovmm_vm_insert_pfn to explicitly |
| 150 * map the I/O virtual address to an OS-allocated page or physical address, |
| 151 * respectively. VM operations may be called before this call returns */ |
| 152 struct tegra_iovmm_area *tegra_iovmm_create_vm( |
| 153 struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops, |
| 154 unsigned long size, pgprot_t pgprot); |
| 155 |
| 156 /* called by clients to "zap" an iovmm_area, and replace all mappings |
| 157 * in it with invalid ones, without freeing the virtual address range */ |
| 158 void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm); |
| 159 |
| 160 /* after zapping a demand-loaded iovmm_area, the client should unzap it |
| 161 * to allow the VMM device to remap the page range. */ |
| 162 void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm); |
| 163 |
| 164 /* called by clients to return an iovmm_area to the free pool for the domain */ |
| 165 void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm); |
| 166 |
| 167 /* called by client software to map the page-aligned I/O address vaddr to |
| 168 * a specific physical address pfn. I/O VMA should have been created with |
| 169 * a NULL tegra_iovmm_area_ops structure. */ |
| 170 void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area, |
| 171 tegra_iovmm_addr_t vaddr, unsigned long pfn); |
| 172 |
| 173 /* called by clients to return the iovmm_area containing addr, or NULL if |
| 174 * addr has not been allocated. caller should call tegra_iovmm_put_area when |
| 175 * finished using the returned pointer */ |
| 176 struct tegra_iovmm_area *tegra_iovmm_find_area_get( |
| 177 struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr); |
| 178 |
| 179 struct tegra_iovmm_area *tegra_iovmm_area_get(struct tegra_iovmm_area *vm); |
| 180 void tegra_iovmm_area_put(struct tegra_iovmm_area *vm); |
| 181 |
| 182 /* called by drivers to initialize a tegra_iovmm_domain structure */ |
| 183 int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain, |
| 184 struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start, |
| 185 tegra_iovmm_addr_t end); |
| 186 |
| 187 /* called by drivers to register an I/O VMM device with the system */ |
| 188 int tegra_iovmm_register(struct tegra_iovmm_device *dev); |
| 189 |
| 190 /* called by drivers to remove an I/O VMM device from the system */ |
| 191 int tegra_iovmm_unregister(struct tegra_iovmm_device *dev); |
| 192 |
| 193 |
| 194 |
| 195 #else /* CONFIG_TEGRA_IOVMM */ |
| 196 |
| 197 static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client( |
| 198 const char *name, const char *share_group) |
| 199 { |
| 200 return NULL; |
| 201 } |
| 202 |
| 203 static inline size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client) |
| 204 { |
| 205 return 0; |
| 206 } |
| 207 |
| 208 static inline void tegra_iovmm_free_client(struct tegra_iovmm_client *client) |
| 209 {} |
| 210 |
| 211 static inline int tegra_iovmm_client_lock(struct tegra_iovmm_client *client) |
| 212 { |
| 213 return 0; |
| 214 } |
| 215 |
| 216 static inline int tegra_iovmm_client_trylock(struct tegra_iovmm_client *client) |
| 217 { |
| 218 return 0; |
| 219 } |
| 220 |
| 221 static inline void tegra_iovmm_client_unlock(struct tegra_iovmm_client *client) |
| 222 {} |
| 223 |
| 224 static inline struct tegra_iovmm_area *tegra_iovmm_create_vm( |
| 225 struct tegra_iovmm_client *client, struct tegra_iovmm_area_ops *ops, |
| 226 unsigned long size, pgprot_t pgprot) |
| 227 { |
| 228 return NULL; |
| 229 } |
| 230 |
| 231 static inline void tegra_iovmm_zap_vm(struct tegra_iovmm_area *vm) { } |
| 232 |
| 233 static inline void tegra_iovmm_unzap_vm(struct tegra_iovmm_area *vm) { } |
| 234 |
| 235 static inline void tegra_iovmm_free_vm(struct tegra_iovmm_area *vm) { } |
| 236 |
| 237 static inline void tegra_iovmm_vm_insert_pfn(struct tegra_iovmm_area *area, |
| 238 tegra_iovmm_addr_t vaddr, unsigned long pfn) { } |
| 239 |
| 240 static inline struct tegra_iovmm_area *tegra_iovmm_find_area_get( |
| 241 struct tegra_iovmm_client *client, tegra_iovmm_addr_t addr) |
| 242 { |
| 243 return NULL; |
| 244 } |
| 245 |
| 246 static inline struct tegra_iovmm_area *tegra_iovmm_area_get( |
| 247 struct tegra_iovmm_area *vm) |
| 248 { |
| 249 return NULL; |
| 250 } |
| 251 |
| 252 static inline void tegra_iovmm_area_put(struct tegra_iovmm_area *vm) { } |
| 253 |
| 254 static inline int tegra_iovmm_domain_init(struct tegra_iovmm_domain *domain, |
| 255 struct tegra_iovmm_device *dev, tegra_iovmm_addr_t start, |
| 256 tegra_iovmm_addr_t end) |
| 257 { |
| 258 return 0; |
| 259 } |
| 260 |
| 261 static inline int tegra_iovmm_register(struct tegra_iovmm_device *dev) |
| 262 { |
| 263 return 0; |
| 264 } |
| 265 |
| 266 static inline int tegra_iovmm_unregister(struct tegra_iovmm_device *dev) |
| 267 { |
| 268 return 0; |
| 269 } |
| 270 #endif /* CONFIG_TEGRA_IOVMM */ |
| 271 |
| 272 |
| 273 #endif |
OLD | NEW |