summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/include
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-01-11 18:00:54 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2017-03-03 13:34:48 -0500
commit707ea45e0f1d7a07885597777496b186dd5fb6f0 (patch)
tree9b48640703ccdf0108d731e66574370179a44b23 /drivers/gpu/nvgpu/include
parent3966efc2e58f1802411f44fd00967dde448f278d (diff)
gpu: nvgpu: kmem abstraction and tracking
Implement kmem abstraction and tracking in nvgpu. The abstraction helps move nvgpu's core code away from being Linux dependent and allows kmem allocation tracking to be done for Linux and any other OS supported by nvgpu. Bug 1799159 Bug 1823380 Change-Id: Ieaae4ca1bbd1d4db4a1546616ab8b9fc53a4079d Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1283828 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/include')
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/kmem.h223
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/kmem_linux.h123
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
26struct gk20a; 27struct 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 */
38struct nvgpu_kmem_cache; 41struct 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 */
54struct 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 */
40struct nvgpu_kmem_cache *nvgpu_kmem_cache_create(struct gk20a *g, size_t size); 72struct 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 */
41void nvgpu_kmem_cache_destroy(struct nvgpu_kmem_cache *cache); 80void 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 */
43void *nvgpu_kmem_cache_alloc(struct nvgpu_kmem_cache *cache); 87void *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 */
44void nvgpu_kmem_cache_free(struct nvgpu_kmem_cache *cache, void *ptr); 95void nvgpu_kmem_cache_free(struct nvgpu_kmem_cache *cache, void *ptr);
45 96
46static 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 */
186int 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 */
206void 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
223static 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 */
86static inline void *nvgpu_big_malloc(size_t size) 264static 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 */
98static inline void *nvgpu_big_zalloc(size_t size) 277static 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 */
109static inline void nvgpu_big_free(void *p) 288static 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
26struct gk20a;
27struct device;
28
29#ifdef CONFIG_NVGPU_TRACK_MEM_USAGE
30void *__nvgpu_track_vmalloc(struct gk20a *g, unsigned long size,
31 unsigned long ip);
32void *__nvgpu_track_vzalloc(struct gk20a *g, unsigned long size,
33 unsigned long ip);
34void *__nvgpu_track_kmalloc(struct gk20a *g, size_t size, unsigned long ip);
35void *__nvgpu_track_kzalloc(struct gk20a *g, size_t size, unsigned long ip);
36void *__nvgpu_track_kcalloc(struct gk20a *g, size_t n, size_t size,
37 unsigned long ip);
38void __nvgpu_track_vfree(struct gk20a *g, void *addr);
39void __nvgpu_track_kfree(struct gk20a *g, void *addr);
40
41void nvgpu_kmem_debugfs_init(struct device *dev);
42#else
43static 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
55static 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
65static 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
75static 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
85static 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
95static 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
105static 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
114static 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