summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2016-06-24 17:12:24 -0400
committerAlex Waterman <alexw@nvidia.com>2016-07-19 14:21:46 -0400
commitb6569319c772d84087a0a1a6d7146bdcae8e9aab (patch)
tree16e7bae422279925301d9116b1e7f4d8aa656483 /drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
parentf4b77e465648e87b19a7df4bb2a121ac8ac1b851 (diff)
gpu: nvgpu: Support multiple types of allocators
Support multiple types of allocation backends. Currently there is only one allocator implementation available: a buddy allocator. Buddy allocators have certain limitations though. For one the allocator requires metadata to be allocated from the kernel's system memory. This causes a given buddy allocation to potentially sleep on a kmalloc() call. This patch has been created so that a new backend can be created which will avoid any dynamic system memory management routines from being called. Bug 1781897 Change-Id: I98d6c8402c049942f13fee69c6901a166f177f65 Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1172115 GVS: Gerrit_Virtual_Submit Reviewed-by: Konsta Holtta <kholtta@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a_allocator.h')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_allocator.h169
1 files changed, 134 insertions, 35 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
index e86e053b..74e23e6c 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
@@ -20,10 +20,49 @@
20#include <linux/list.h> 20#include <linux/list.h>
21#include <linux/rbtree.h> 21#include <linux/rbtree.h>
22#include <linux/debugfs.h> 22#include <linux/debugfs.h>
23#include <linux/seq_file.h>
23#include <linux/platform_device.h> 24#include <linux/platform_device.h>
24 25
25/* #define ALLOCATOR_DEBUG */ 26/* #define ALLOCATOR_DEBUG */
26 27
28struct gk20a_allocator;
29struct vm_gk20a;
30
31/*
32 * Operations for an allocator to implement.
33 */
34struct gk20a_allocator_ops {
35 u64 (*alloc)(struct gk20a_allocator *allocator, u64 len);
36 void (*free)(struct gk20a_allocator *allocator, u64 addr);
37
38 /*
39 * Special interface to allocate a memory region with a specific
40 * starting address. Yikes. Note: if free() works for freeing both
41 * regular and fixed allocations then free_fixed() does not need to
42 * be implemented. This behavior exists for legacy reasons and should
43 * not be propagated to new allocators.
44 */
45 u64 (*alloc_fixed)(struct gk20a_allocator *allocator,
46 u64 base, u64 len);
47 void (*free_fixed)(struct gk20a_allocator *allocator,
48 u64 base, u64 len);
49
50 /*
51 * Returns info about the allocator.
52 */
53 u64 (*base)(struct gk20a_allocator *allocator);
54 u64 (*length)(struct gk20a_allocator *allocator);
55 u64 (*end)(struct gk20a_allocator *allocator);
56 int (*inited)(struct gk20a_allocator *allocator);
57
58 /* Destructor. */
59 void (*fini)(struct gk20a_allocator *allocator);
60
61 /* Debugging. */
62 void (*print_stats)(struct gk20a_allocator *allocator,
63 struct seq_file *s, int lock);
64};
65
27/* 66/*
28 * Each buddy is an element in a binary tree. 67 * Each buddy is an element in a binary tree.
29 */ 68 */
@@ -97,8 +136,6 @@ struct gk20a_fixed_alloc {
97 u64 end; /* End address. */ 136 u64 end; /* End address. */
98}; 137};
99 138
100struct vm_gk20a;
101
102/* 139/*
103 * GPU buddy allocator for the various GPU address spaces. Each addressable unit 140 * GPU buddy allocator for the various GPU address spaces. Each addressable unit
104 * doesn't have to correspond to a byte. In some cases each unit is a more 141 * doesn't have to correspond to a byte. In some cases each unit is a more
@@ -109,12 +146,10 @@ struct vm_gk20a;
109 * 146 *
110 * order_size is the size of an order 0 buddy. 147 * order_size is the size of an order 0 buddy.
111 */ 148 */
112struct gk20a_allocator { 149struct gk20a_buddy_allocator {
113 150 struct gk20a_allocator *owner; /* Owner of this buddy allocator. */
114 struct vm_gk20a *vm; /* Parent VM - can be NULL. */ 151 struct vm_gk20a *vm; /* Parent VM - can be NULL. */
115 152
116 char name[32]; /* Name of allocator. */
117
118 u64 base; /* Base address of the space. */ 153 u64 base; /* Base address of the space. */
119 u64 length; /* Length of the space. */ 154 u64 length; /* Length of the space. */
120 u64 blk_size; /* Size of order 0 allocation. */ 155 u64 blk_size; /* Size of order 0 allocation. */
@@ -132,11 +167,6 @@ struct gk20a_allocator {
132 struct rb_root alloced_buddies; /* Outstanding allocations. */ 167 struct rb_root alloced_buddies; /* Outstanding allocations. */
133 struct rb_root fixed_allocs; /* Outstanding fixed allocations. */ 168 struct rb_root fixed_allocs; /* Outstanding fixed allocations. */
134 169
135 struct mutex lock; /* Protects buddy access. */
136
137#define GPU_BALLOC_GVA_SPACE 0x1
138 u64 flags;
139
140 /* 170 /*
141 * Impose an upper bound on the maximum order. 171 * Impose an upper bound on the maximum order.
142 */ 172 */
@@ -155,52 +185,121 @@ struct gk20a_allocator {
155 */ 185 */
156 u64 pte_blk_order; 186 u64 pte_blk_order;
157 187
158 struct dentry *debugfs_entry; 188 int inited;
189
190#define GPU_BALLOC_GVA_SPACE 0x1
191 u64 flags;
159 192
160 u64 bytes_alloced; 193 u64 bytes_alloced;
161 u64 bytes_alloced_real; 194 u64 bytes_alloced_real;
162 u64 bytes_freed; 195 u64 bytes_freed;
163}; 196};
164 197
165#define balloc_lock(a) mutex_lock(&(a)->lock) 198struct gk20a_allocator {
166#define balloc_unlock(a) mutex_unlock(&(a)->lock) 199 char name[32];
200 struct mutex lock;
167 201
168#define balloc_get_order_list(a, order) (&(a)->buddy_list[(order)]) 202 void *priv;
169#define balloc_order_to_len(a, order) ((1 << order) * (a)->blk_size) 203 const struct gk20a_allocator_ops *ops;
170#define balloc_base_shift(a, base) ((base) - (a)->start)
171#define balloc_base_unshift(a, base) ((base) + (a)->start)
172 204
173int gk20a_allocator_init(struct gk20a_allocator *allocator, 205 struct dentry *debugfs_entry;
174 const char *name, u64 base, u64 size, u64 order0); 206};
175int __gk20a_allocator_init(struct gk20a_allocator *allocator, 207
176 struct vm_gk20a *vm, const char *name, 208static inline void alloc_lock(struct gk20a_allocator *a)
177 u64 base, u64 size, u64 order0, 209{
178 u64 max_order, u64 flags); 210 mutex_lock(&a->lock);
179void gk20a_allocator_destroy(struct gk20a_allocator *allocator); 211}
212
213static inline void alloc_unlock(struct gk20a_allocator *a)
214{
215 mutex_unlock(&a->lock);
216}
217
218static inline struct gk20a_buddy_allocator *buddy_allocator(
219 struct gk20a_allocator *a)
220{
221 return (struct gk20a_buddy_allocator *)a->priv;
222}
223
224static inline struct list_head *balloc_get_order_list(
225 struct gk20a_buddy_allocator *a, int order)
226{
227 return &a->buddy_list[order];
228}
229
230static inline u64 balloc_order_to_len(struct gk20a_buddy_allocator *a,
231 int order)
232{
233 return (1 << order) * a->blk_size;
234}
235
236static inline u64 balloc_base_shift(struct gk20a_buddy_allocator *a,
237 u64 base)
238{
239 return base - a->start;
240}
241
242static inline u64 balloc_base_unshift(struct gk20a_buddy_allocator *a,
243 u64 base)
244{
245 return base + a->start;
246}
247
248static inline struct gk20a_allocator *balloc_owner(
249 struct gk20a_buddy_allocator *a)
250{
251 return a->owner;
252}
180 253
181/* 254/*
182 * Normal alloc/free operations for the buddy allocator. 255 * Buddy allocator specific initializers.
183 */ 256 */
184u64 gk20a_balloc(struct gk20a_allocator *allocator, u64 len); 257int __gk20a_buddy_allocator_init(struct gk20a_allocator *a,
185void gk20a_bfree(struct gk20a_allocator *allocator, u64 addr); 258 struct vm_gk20a *vm, const char *name,
259 u64 base, u64 size, u64 blk_size,
260 u64 max_order, u64 flags);
261int gk20a_buddy_allocator_init(struct gk20a_allocator *allocator,
262 const char *name, u64 base, u64 size,
263 u64 blk_size, u64 flags);
186 264
187/* 265/*
188 * Special interface to allocate a memory regions with a specific starting 266 * Allocator APIs.
189 * address. Yikes.
190 */ 267 */
191u64 gk20a_balloc_fixed(struct gk20a_allocator *allocator, u64 base, u64 len); 268u64 gk20a_alloc(struct gk20a_allocator *allocator, u64 len);
269void gk20a_free(struct gk20a_allocator *allocator, u64 addr);
270
271u64 gk20a_alloc_fixed(struct gk20a_allocator *allocator, u64 base, u64 len);
272void gk20a_free_fixed(struct gk20a_allocator *allocator, u64 base, u64 len);
273
274u64 gk20a_alloc_base(struct gk20a_allocator *a);
275u64 gk20a_alloc_length(struct gk20a_allocator *a);
276u64 gk20a_alloc_end(struct gk20a_allocator *a);
277u64 gk20a_alloc_initialized(struct gk20a_allocator *a);
278
279void gk20a_alloc_destroy(struct gk20a_allocator *allocator);
280
281void gk20a_alloc_print_stats(struct gk20a_allocator *a,
282 struct seq_file *s, int lock);
192 283
193/* 284/*
194 * Debugfs init. 285 * Debug stuff.
195 */ 286 */
196void gk20a_alloc_debugfs_init(struct platform_device *pdev); 287void gk20a_alloc_debugfs_init(struct platform_device *pdev);
197 288
289#define __alloc_pstat(seq, allocator, fmt, arg...) \
290 do { \
291 if (s) \
292 seq_printf(seq, fmt, ##arg); \
293 else \
294 alloc_dbg(allocator, fmt, ##arg); \
295 } while (0)
296
198#if defined(ALLOCATOR_DEBUG) 297#if defined(ALLOCATOR_DEBUG)
199#define balloc_dbg(alloctor, format, arg...) \ 298#define alloc_dbg(allocator, format, arg...) \
200 pr_info("%-25s %25s() " format, \ 299 pr_info("%-25s %25s() " format, \
201 alloctor->name, __func__, ##arg) 300 allocator->name, __func__, ##arg)
202#else 301#else
203#define balloc_dbg(allocator, format, arg...) 302#define alloc_dbg(allocator, format, arg...)
204#endif 303#endif
205 304
206#endif /* GK20A_ALLOCATOR_H */ 305#endif /* GK20A_ALLOCATOR_H */