diff options
Diffstat (limited to 'drivers/gpu/nvgpu/include')
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/kmem.h | 223 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/kmem_linux.h | 123 |
2 files changed, 324 insertions, 22 deletions
diff --git a/drivers/gpu/nvgpu/include/nvgpu/kmem.h b/drivers/gpu/nvgpu/include/nvgpu/kmem.h index c08e40a6..59192525 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/kmem.h +++ b/drivers/gpu/nvgpu/include/nvgpu/kmem.h | |||
@@ -14,18 +14,21 @@ | |||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef NVGPU_KMEM_H | 17 | #ifndef __NVGPU_KMEM_H__ |
18 | #define NVGPU_KMEM_H | 18 | #define __NVGPU_KMEM_H__ |
19 | 19 | ||
20 | #include <linux/mm.h> | 20 | /* |
21 | #include <linux/slab.h> | 21 | * Incase this isn't defined already. |
22 | #include <linux/vmalloc.h> | 22 | */ |
23 | 23 | #ifndef _THIS_IP_ | |
24 | #include <asm/page.h> | 24 | #define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) |
25 | #endif | ||
25 | 26 | ||
26 | struct gk20a; | 27 | struct gk20a; |
27 | 28 | ||
28 | /* | 29 | /** |
30 | * DOC: Kmem cache support | ||
31 | * | ||
29 | * In Linux there is support for the notion of a kmem_cache. It gives better | 32 | * In Linux there is support for the notion of a kmem_cache. It gives better |
30 | * memory usage characteristics for lots of allocations of the same size. Think | 33 | * memory usage characteristics for lots of allocations of the same size. Think |
31 | * structs that get allocated over and over. Normal kmalloc() type routines | 34 | * structs that get allocated over and over. Normal kmalloc() type routines |
@@ -37,26 +40,200 @@ struct gk20a; | |||
37 | */ | 40 | */ |
38 | struct nvgpu_kmem_cache; | 41 | struct nvgpu_kmem_cache; |
39 | 42 | ||
43 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
44 | /* | ||
45 | * Uncomment this if you want to enable stack traces in the memory profiling. | ||
46 | * Since this is a fairly high overhead operation and is only necessary for | ||
47 | * debugging actual bugs it's left here for developers to enable. | ||
48 | */ | ||
49 | /* #define __NVGPU_SAVE_KALLOC_STACK_TRACES */ | ||
50 | |||
51 | /* | ||
52 | * Defined per-OS. | ||
53 | */ | ||
54 | struct nvgpu_mem_alloc_tracker; | ||
55 | #endif | ||
56 | |||
57 | |||
58 | /** | ||
59 | * nvgpu_kmem_cache_create - create an nvgpu kernel memory cache. | ||
60 | * | ||
61 | * @g The GPU driver struct using this cache. | ||
62 | * @size Size of the object allocated by the cache. | ||
63 | * | ||
64 | * This cache can be used to allocate objects of size @size. Common usage would | ||
65 | * be for a struct that gets allocated a lot. In that case @size should be | ||
66 | * sizeof(struct my_struct). | ||
67 | * | ||
68 | * A given implementation of this need not do anything special. The allocation | ||
69 | * routines can simply be passed on to nvgpu_kzalloc() if desired so packing | ||
70 | * and alignment of the structs cannot be assumed. | ||
71 | */ | ||
40 | struct nvgpu_kmem_cache *nvgpu_kmem_cache_create(struct gk20a *g, size_t size); | 72 | struct nvgpu_kmem_cache *nvgpu_kmem_cache_create(struct gk20a *g, size_t size); |
73 | |||
74 | /** | ||
75 | * nvgpu_kmem_cache_destroy - destroy a cache created by | ||
76 | * nvgpu_kmem_cache_create(). | ||
77 | * | ||
78 | * @cache The cache to destroy. | ||
79 | */ | ||
41 | void nvgpu_kmem_cache_destroy(struct nvgpu_kmem_cache *cache); | 80 | void nvgpu_kmem_cache_destroy(struct nvgpu_kmem_cache *cache); |
42 | 81 | ||
82 | /** | ||
83 | * nvgpu_kmem_cache_alloc - Allocate an object from the cache | ||
84 | * | ||
85 | * @cache The cache to alloc from. | ||
86 | */ | ||
43 | void *nvgpu_kmem_cache_alloc(struct nvgpu_kmem_cache *cache); | 87 | void *nvgpu_kmem_cache_alloc(struct nvgpu_kmem_cache *cache); |
88 | |||
89 | /** | ||
90 | * nvgpu_kmem_cache_free - Free an object back to a cache | ||
91 | * | ||
92 | * @cache The cache to return the object to. | ||
93 | * @ptr Pointer to the object to free. | ||
94 | */ | ||
44 | void nvgpu_kmem_cache_free(struct nvgpu_kmem_cache *cache, void *ptr); | 95 | void nvgpu_kmem_cache_free(struct nvgpu_kmem_cache *cache, void *ptr); |
45 | 96 | ||
46 | static inline void *__nvgpu_big_alloc(size_t size, bool clear) | 97 | /** |
98 | * nvgpu_kmalloc - Allocate from the kernel's allocator. | ||
99 | * | ||
100 | * @g: Current GPU. | ||
101 | * @size: Size of the allocation. | ||
102 | * | ||
103 | * Allocate a chunk of system memory from the kernel. Allocations larger than 1 | ||
104 | * page may fail even when there may appear to be enough memory. | ||
105 | * | ||
106 | * This function may sleep so cannot be used in IRQs. | ||
107 | */ | ||
108 | #define nvgpu_kmalloc(g, size) __nvgpu_kmalloc(g, size, _THIS_IP_) | ||
109 | |||
110 | /** | ||
111 | * nvgpu_kzalloc - Allocate from the kernel's allocator. | ||
112 | * | ||
113 | * @g: Current GPU. | ||
114 | * @size: Size of the allocation. | ||
115 | * | ||
116 | * Identical to nvgpu_kalloc() except the memory will be zeroed before being | ||
117 | * returned. | ||
118 | */ | ||
119 | #define nvgpu_kzalloc(g, size) __nvgpu_kzalloc(g, size, _THIS_IP_) | ||
120 | |||
121 | /** | ||
122 | * nvgpu_kcalloc - Allocate from the kernel's allocator. | ||
123 | * | ||
124 | * @g: Current GPU. | ||
125 | * @n: Number of objects. | ||
126 | * @size: Size of each object. | ||
127 | * | ||
128 | * Identical to nvgpu_kalloc() except the size of the memory chunk returned is | ||
129 | * @n * @size. | ||
130 | */ | ||
131 | #define nvgpu_kcalloc(g, n, size) __nvgpu_kcalloc(g, n, size, _THIS_IP_) | ||
132 | |||
133 | /** | ||
134 | * nvgpu_vmalloc - Allocate memory and return a map to it. | ||
135 | * | ||
136 | * @g: Current GPU. | ||
137 | * @size: Size of the allocation. | ||
138 | * | ||
139 | * Allocate some memory and return a pointer to a virtual memory mapping of | ||
140 | * that memory in the kernel's virtual address space. The underlying physical | ||
141 | * memory is not guaranteed to be contiguous (and indeed likely isn't). This | ||
142 | * allows for much larger allocations to be done without worrying about as much | ||
143 | * about physical memory fragmentation. | ||
144 | * | ||
145 | * This function may sleep. | ||
146 | */ | ||
147 | #define nvgpu_vmalloc(g, size) __nvgpu_vmalloc(g, size, _THIS_IP_) | ||
148 | |||
149 | /** | ||
150 | * nvgpu_vzalloc - Allocate memory and return a map to it. | ||
151 | * | ||
152 | * @g: Current GPU. | ||
153 | * @size: Size of the allocation. | ||
154 | * | ||
155 | * Identical to nvgpu_vmalloc() except this will return zero'ed memory. | ||
156 | */ | ||
157 | #define nvgpu_vzalloc(g, size) __nvgpu_vzalloc(g, size, _THIS_IP_) | ||
158 | |||
159 | /** | ||
160 | * nvgpu_kfree - Frees an alloc from nvgpu_kmalloc, nvgpu_kzalloc, | ||
161 | * nvgpu_kcalloc. | ||
162 | * | ||
163 | * @g: Current GPU. | ||
164 | * @addr: Address of object to free. | ||
165 | */ | ||
166 | #define nvgpu_kfree(g, addr) __nvgpu_kfree(g, addr) | ||
167 | |||
168 | /** | ||
169 | * nvgpu_vfree - Frees an alloc from nvgpu_vmalloc, nvgpu_vzalloc. | ||
170 | * | ||
171 | * @g: Current GPU. | ||
172 | * @addr: Address of object to free. | ||
173 | */ | ||
174 | #define nvgpu_vfree(g, addr) __nvgpu_vfree(g, addr) | ||
175 | |||
176 | #define kmem_dbg(fmt, args...) \ | ||
177 | gk20a_dbg(gpu_dbg_kmem, fmt, ##args) | ||
178 | |||
179 | /** | ||
180 | * nvgpu_kmem_init - Initialize the kmem tracking stuff. | ||
181 | * | ||
182 | *@g: The driver to init. | ||
183 | * | ||
184 | * Returns non-zero on failure. | ||
185 | */ | ||
186 | int nvgpu_kmem_init(struct gk20a *g); | ||
187 | |||
188 | /** | ||
189 | * nvgpu_kmem_fini - Finalize the kmem tracking code | ||
190 | * | ||
191 | * @g - The GPU. | ||
192 | * @flags - Flags that control operation of this finalization. | ||
193 | * | ||
194 | * Cleanup resources used by nvgpu_kmem. Available flags for cleanup are: | ||
195 | * | ||
196 | * %NVGPU_KMEM_FINI_DO_NOTHING | ||
197 | * %NVGPU_KMEM_FINI_FORCE_CLEANUP | ||
198 | * %NVGPU_KMEM_FINI_DUMP_ALLOCS | ||
199 | * %NVGPU_KMEM_FINI_WARN | ||
200 | * %NVGPU_KMEM_FINI_BUG | ||
201 | * | ||
202 | * %NVGPU_KMEM_FINI_DO_NOTHING will be overridden by anything else specified. | ||
203 | * Put another way don't just add %NVGPU_KMEM_FINI_DO_NOTHING and expect that | ||
204 | * to suppress other flags from doing anything. | ||
205 | */ | ||
206 | void nvgpu_kmem_fini(struct gk20a *g, int flags); | ||
207 | |||
208 | /* | ||
209 | * These will simply be ignored if CONFIG_NVGPU_TRACK_MEM_USAGE is not defined. | ||
210 | */ | ||
211 | #define NVGPU_KMEM_FINI_DO_NOTHING 0 | ||
212 | #define NVGPU_KMEM_FINI_FORCE_CLEANUP (1 << 0) | ||
213 | #define NVGPU_KMEM_FINI_DUMP_ALLOCS (1 << 1) | ||
214 | #define NVGPU_KMEM_FINI_WARN (1 << 2) | ||
215 | #define NVGPU_KMEM_FINI_BUG (1 << 3) | ||
216 | |||
217 | /* | ||
218 | * When there's other implementations make sure they are included instead of | ||
219 | * Linux when not compiling on Linux! | ||
220 | */ | ||
221 | #include <nvgpu/kmem_linux.h> | ||
222 | |||
223 | static inline void *__nvgpu_big_alloc(struct gk20a *g, size_t size, bool clear) | ||
47 | { | 224 | { |
48 | void *p; | 225 | void *p; |
49 | 226 | ||
50 | if (size > PAGE_SIZE) { | 227 | if (size > PAGE_SIZE) { |
51 | if (clear) | 228 | if (clear) |
52 | p = vzalloc(size); | 229 | p = nvgpu_vzalloc(g, size); |
53 | else | 230 | else |
54 | p = vmalloc(size); | 231 | p = nvgpu_vmalloc(g, size); |
55 | } else { | 232 | } else { |
56 | if (clear) | 233 | if (clear) |
57 | p = kzalloc(size, GFP_KERNEL); | 234 | p = nvgpu_kzalloc(g, size); |
58 | else | 235 | else |
59 | p = kmalloc(size, GFP_KERNEL); | 236 | p = nvgpu_kmalloc(g, size); |
60 | } | 237 | } |
61 | 238 | ||
62 | return p; | 239 | return p; |
@@ -65,6 +242,7 @@ static inline void *__nvgpu_big_alloc(size_t size, bool clear) | |||
65 | /** | 242 | /** |
66 | * nvgpu_big_malloc - Pick virtual or physical alloc based on @size | 243 | * nvgpu_big_malloc - Pick virtual or physical alloc based on @size |
67 | * | 244 | * |
245 | * @g - The GPU. | ||
68 | * @size - Size of the allocation. | 246 | * @size - Size of the allocation. |
69 | * | 247 | * |
70 | * On some platforms (i.e Linux) it is possible to allocate memory directly | 248 | * On some platforms (i.e Linux) it is possible to allocate memory directly |
@@ -83,30 +261,31 @@ static inline void *__nvgpu_big_alloc(size_t size, bool clear) | |||
83 | * Returns a pointer to a virtual address range that the kernel can access or | 261 | * Returns a pointer to a virtual address range that the kernel can access or |
84 | * %NULL on failure. | 262 | * %NULL on failure. |
85 | */ | 263 | */ |
86 | static inline void *nvgpu_big_malloc(size_t size) | 264 | static inline void *nvgpu_big_malloc(struct gk20a *g, size_t size) |
87 | { | 265 | { |
88 | return __nvgpu_big_alloc(size, false); | 266 | return __nvgpu_big_alloc(g, size, false); |
89 | } | 267 | } |
90 | 268 | ||
91 | /** | 269 | /** |
92 | * nvgpu_big_malloc - Pick virtual or physical alloc based on @size | 270 | * nvgpu_big_malloc - Pick virtual or physical alloc based on @size |
93 | * | 271 | * |
272 | * @g - The GPU. | ||
94 | * @size - Size of the allocation. | 273 | * @size - Size of the allocation. |
95 | * | 274 | * |
96 | * Zeroed memory version of nvgpu_big_malloc(). | 275 | * Zeroed memory version of nvgpu_big_malloc(). |
97 | */ | 276 | */ |
98 | static inline void *nvgpu_big_zalloc(size_t size) | 277 | static inline void *nvgpu_big_zalloc(struct gk20a *g, size_t size) |
99 | { | 278 | { |
100 | return __nvgpu_big_alloc(size, true); | 279 | return __nvgpu_big_alloc(g, size, true); |
101 | } | 280 | } |
102 | 281 | ||
103 | /** | 282 | /** |
104 | * nvgpu_big_free - Free and alloc from nvgpu_big_zalloc() or | 283 | * nvgpu_big_free - Free and alloc from nvgpu_big_zalloc() or |
105 | * nvgpu_big_malloc(). | 284 | * nvgpu_big_malloc(). |
106 | * | 285 | * @g - The GPU. |
107 | * @p - A pointer allocated by nvgpu_big_zalloc() or nvgpu_big_malloc(). | 286 | * @p - A pointer allocated by nvgpu_big_zalloc() or nvgpu_big_malloc(). |
108 | */ | 287 | */ |
109 | static inline void nvgpu_big_free(void *p) | 288 | static inline void nvgpu_big_free(struct gk20a *g, void *p) |
110 | { | 289 | { |
111 | /* | 290 | /* |
112 | * This will have to be fixed eventually. Allocs that use | 291 | * This will have to be fixed eventually. Allocs that use |
@@ -114,9 +293,9 @@ static inline void nvgpu_big_free(void *p) | |||
114 | * when freeing. | 293 | * when freeing. |
115 | */ | 294 | */ |
116 | if (virt_addr_valid(p)) | 295 | if (virt_addr_valid(p)) |
117 | kfree(p); | 296 | nvgpu_kfree(g, p); |
118 | else | 297 | else |
119 | vfree(p); | 298 | nvgpu_vfree(g, p); |
120 | } | 299 | } |
121 | 300 | ||
122 | #endif | 301 | #endif /* __NVGPU_KMEM_H__ */ |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/kmem_linux.h b/drivers/gpu/nvgpu/include/nvgpu/kmem_linux.h new file mode 100644 index 00000000..d1cd27f3 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/kmem_linux.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __NVGPU_KMEM_LINUX_H__ | ||
18 | #define __NVGPU_KMEM_LINUX_H__ | ||
19 | |||
20 | #include <linux/mm.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/vmalloc.h> | ||
23 | |||
24 | #include <asm/page.h> | ||
25 | |||
26 | struct gk20a; | ||
27 | struct device; | ||
28 | |||
29 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
30 | void *__nvgpu_track_vmalloc(struct gk20a *g, unsigned long size, | ||
31 | unsigned long ip); | ||
32 | void *__nvgpu_track_vzalloc(struct gk20a *g, unsigned long size, | ||
33 | unsigned long ip); | ||
34 | void *__nvgpu_track_kmalloc(struct gk20a *g, size_t size, unsigned long ip); | ||
35 | void *__nvgpu_track_kzalloc(struct gk20a *g, size_t size, unsigned long ip); | ||
36 | void *__nvgpu_track_kcalloc(struct gk20a *g, size_t n, size_t size, | ||
37 | unsigned long ip); | ||
38 | void __nvgpu_track_vfree(struct gk20a *g, void *addr); | ||
39 | void __nvgpu_track_kfree(struct gk20a *g, void *addr); | ||
40 | |||
41 | void nvgpu_kmem_debugfs_init(struct device *dev); | ||
42 | #else | ||
43 | static inline void nvgpu_kmem_debugfs_init(struct device *dev) | ||
44 | { | ||
45 | } | ||
46 | #endif | ||
47 | |||
48 | /** | ||
49 | * DOC: Linux pass through kmem implementation. | ||
50 | * | ||
51 | * These are the Linux implementations of the various kmem functions defined by | ||
52 | * nvgpu. This should not be included directly - instead include <nvgpu/kmem.h>. | ||
53 | */ | ||
54 | |||
55 | static inline void *__nvgpu_kmalloc(struct gk20a *g, unsigned long size, | ||
56 | unsigned long ip) | ||
57 | { | ||
58 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
59 | return __nvgpu_track_vmalloc(g, size, ip); | ||
60 | #else | ||
61 | return kmalloc(size, GFP_KERNEL); | ||
62 | #endif | ||
63 | } | ||
64 | |||
65 | static inline void *__nvgpu_kzalloc(struct gk20a *g, size_t size, | ||
66 | unsigned long ip) | ||
67 | { | ||
68 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
69 | return __nvgpu_track_kzalloc(g, size, ip); | ||
70 | #else | ||
71 | return kzalloc(size, GFP_KERNEL); | ||
72 | #endif | ||
73 | } | ||
74 | |||
75 | static inline void *__nvgpu_kcalloc(struct gk20a *g, size_t n, size_t size, | ||
76 | unsigned long ip) | ||
77 | { | ||
78 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
79 | return __nvgpu_track_kcalloc(g, n, size, ip); | ||
80 | #else | ||
81 | return kcalloc(n, size, GFP_KERNEL); | ||
82 | #endif | ||
83 | } | ||
84 | |||
85 | static inline void *__nvgpu_vmalloc(struct gk20a *g, unsigned long size, | ||
86 | unsigned long ip) | ||
87 | { | ||
88 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
89 | return __nvgpu_track_vmalloc(g, size, ip); | ||
90 | #else | ||
91 | return vmalloc(size); | ||
92 | #endif | ||
93 | } | ||
94 | |||
95 | static inline void *__nvgpu_vzalloc(struct gk20a *g, unsigned long size, | ||
96 | unsigned long ip) | ||
97 | { | ||
98 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
99 | return __nvgpu_track_vzalloc(g, size, ip); | ||
100 | #else | ||
101 | return vzalloc(size); | ||
102 | #endif | ||
103 | } | ||
104 | |||
105 | static inline void __nvgpu_kfree(struct gk20a *g, void *addr) | ||
106 | { | ||
107 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
108 | __nvgpu_track_kfree(g, addr); | ||
109 | #else | ||
110 | kfree(addr); | ||
111 | #endif | ||
112 | } | ||
113 | |||
114 | static inline void __nvgpu_vfree(struct gk20a *g, void *addr) | ||
115 | { | ||
116 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
117 | __nvgpu_track_vfree(g, addr); | ||
118 | #else | ||
119 | vfree(addr); | ||
120 | #endif | ||
121 | } | ||
122 | |||
123 | #endif | ||