diff options
author | Alex Waterman <alexw@nvidia.com> | 2016-06-24 17:12:24 -0400 |
---|---|---|
committer | Alex Waterman <alexw@nvidia.com> | 2016-07-19 14:21:46 -0400 |
commit | b6569319c772d84087a0a1a6d7146bdcae8e9aab (patch) | |
tree | 16e7bae422279925301d9116b1e7f4d8aa656483 /drivers/gpu/nvgpu/gk20a/gk20a_allocator.c | |
parent | f4b77e465648e87b19a7df4bb2a121ac8ac1b851 (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.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a_allocator.c | 500 |
1 files changed, 329 insertions, 171 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c index d3a9202b..f2164768 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.c | |||
@@ -17,43 +17,58 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/seq_file.h> | ||
21 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
22 | #include <linux/debugfs.h> | ||
23 | 21 | ||
24 | #include "platform_gk20a.h" | 22 | #include "platform_gk20a.h" |
25 | #include "gk20a_allocator.h" | 23 | #include "gk20a_allocator.h" |
26 | 24 | ||
27 | #include "mm_gk20a.h" | 25 | #include "mm_gk20a.h" |
28 | 26 | ||
29 | static struct dentry *balloc_debugfs_root; | 27 | static struct dentry *gk20a_alloc_debugfs_root; |
30 | 28 | ||
31 | static struct kmem_cache *buddy_cache; /* slab cache for meta data. */ | 29 | static struct kmem_cache *buddy_cache; /* slab cache for meta data. */ |
32 | 30 | ||
33 | static u32 balloc_tracing_on; | 31 | u32 gk20a_alloc_tracing_on; |
34 | 32 | ||
35 | #define balloc_trace_func() \ | 33 | #define gk20a_alloc_trace_func() \ |
36 | do { \ | 34 | do { \ |
37 | if (balloc_tracing_on) \ | 35 | if (gk20a_alloc_tracing_on) \ |
38 | trace_printk("%s\n", __func__); \ | 36 | trace_printk("%s\n", __func__); \ |
39 | } while (0) | 37 | } while (0) |
40 | 38 | ||
41 | #define balloc_trace_func_done() \ | 39 | #define gk20a_alloc_trace_func_done() \ |
42 | do { \ | 40 | do { \ |
43 | if (balloc_tracing_on) \ | 41 | if (gk20a_alloc_tracing_on) \ |
44 | trace_printk("%s_done\n", __func__); \ | 42 | trace_printk("%s_done\n", __func__); \ |
45 | } while (0) | 43 | } while (0) |
46 | 44 | ||
47 | 45 | /* | |
48 | static void balloc_init_alloc_debug(struct gk20a_allocator *a); | 46 | * Buddy allocator implementation. |
49 | static void balloc_print_stats(struct gk20a_allocator *a, struct seq_file *s, | 47 | */ |
50 | int lock); | 48 | static u64 gk20a_buddy_alloc(struct gk20a_allocator *__a, u64 len); |
51 | static struct gk20a_buddy *balloc_free_buddy(struct gk20a_allocator *a, | 49 | static void gk20a_buddy_free(struct gk20a_allocator *__a, u64 addr); |
50 | static u64 gk20a_buddy_alloc_fixed(struct gk20a_allocator *__a, | ||
51 | u64 base, u64 len); | ||
52 | static u64 gk20a_buddy_alloc_base(struct gk20a_allocator *a); | ||
53 | static u64 gk20a_buddy_alloc_length(struct gk20a_allocator *a); | ||
54 | static u64 gk20a_buddy_alloc_end(struct gk20a_allocator *a); | ||
55 | static int gk20a_buddy_alloc_inited(struct gk20a_allocator *a); | ||
56 | |||
57 | static void gk20a_buddy_allocator_destroy(struct gk20a_allocator *__a); | ||
58 | static void gk20a_buddy_print_stats(struct gk20a_allocator *__a, | ||
59 | struct seq_file *s, int lock); | ||
60 | |||
61 | /* Some other buddy allocator functions. */ | ||
62 | static struct gk20a_buddy *balloc_free_buddy(struct gk20a_buddy_allocator *a, | ||
52 | u64 addr); | 63 | u64 addr); |
53 | static void balloc_coalesce(struct gk20a_allocator *a, struct gk20a_buddy *b); | 64 | static void balloc_coalesce(struct gk20a_buddy_allocator *a, |
54 | static void __balloc_do_free_fixed(struct gk20a_allocator *a, | 65 | struct gk20a_buddy *b); |
66 | static void __balloc_do_free_fixed(struct gk20a_buddy_allocator *a, | ||
55 | struct gk20a_fixed_alloc *falloc); | 67 | struct gk20a_fixed_alloc *falloc); |
56 | 68 | ||
69 | /* Debugging. */ | ||
70 | static void gk20a_init_alloc_debug(struct gk20a_allocator *a); | ||
71 | |||
57 | /* | 72 | /* |
58 | * This function is not present in older kernel's list.h code. | 73 | * This function is not present in older kernel's list.h code. |
59 | */ | 74 | */ |
@@ -62,6 +77,23 @@ static void __balloc_do_free_fixed(struct gk20a_allocator *a, | |||
62 | list_entry((ptr)->prev, type, member) | 77 | list_entry((ptr)->prev, type, member) |
63 | #endif | 78 | #endif |
64 | 79 | ||
80 | static const struct gk20a_allocator_ops buddy_ops = { | ||
81 | .alloc = gk20a_buddy_alloc, | ||
82 | .free = gk20a_buddy_free, | ||
83 | |||
84 | .alloc_fixed = gk20a_buddy_alloc_fixed, | ||
85 | /* .free_fixed not needed. */ | ||
86 | |||
87 | .base = gk20a_buddy_alloc_base, | ||
88 | .length = gk20a_buddy_alloc_length, | ||
89 | .end = gk20a_buddy_alloc_end, | ||
90 | .inited = gk20a_buddy_alloc_inited, | ||
91 | |||
92 | .fini = gk20a_buddy_allocator_destroy, | ||
93 | |||
94 | .print_stats = gk20a_buddy_print_stats, | ||
95 | }; | ||
96 | |||
65 | /* | 97 | /* |
66 | * GPU buddy allocator for various address spaces. | 98 | * GPU buddy allocator for various address spaces. |
67 | * | 99 | * |
@@ -80,13 +112,95 @@ static void __balloc_do_free_fixed(struct gk20a_allocator *a, | |||
80 | * easily PDE aligned so this hasn't been a problem. | 112 | * easily PDE aligned so this hasn't been a problem. |
81 | */ | 113 | */ |
82 | 114 | ||
115 | static u64 gk20a_buddy_alloc_length(struct gk20a_allocator *a) | ||
116 | { | ||
117 | struct gk20a_buddy_allocator *ba = a->priv; | ||
118 | |||
119 | return ba->length; | ||
120 | } | ||
121 | |||
122 | static u64 gk20a_buddy_alloc_base(struct gk20a_allocator *a) | ||
123 | { | ||
124 | struct gk20a_buddy_allocator *ba = a->priv; | ||
125 | |||
126 | return ba->start; | ||
127 | } | ||
128 | |||
129 | static int gk20a_buddy_alloc_inited(struct gk20a_allocator *a) | ||
130 | { | ||
131 | struct gk20a_buddy_allocator *ba = a->priv; | ||
132 | |||
133 | return ba->inited; | ||
134 | } | ||
135 | static u64 gk20a_buddy_alloc_end(struct gk20a_allocator *a) | ||
136 | { | ||
137 | struct gk20a_buddy_allocator *ba = a->priv; | ||
138 | |||
139 | return ba->end; | ||
140 | } | ||
141 | |||
142 | u64 gk20a_alloc_length(struct gk20a_allocator *a) | ||
143 | { | ||
144 | return a->ops->length(a); | ||
145 | } | ||
146 | |||
147 | u64 gk20a_alloc_base(struct gk20a_allocator *a) | ||
148 | { | ||
149 | return a->ops->base(a); | ||
150 | } | ||
151 | |||
152 | u64 gk20a_alloc_initialized(struct gk20a_allocator *a) | ||
153 | { | ||
154 | if (!a->ops) | ||
155 | return 0; | ||
156 | |||
157 | return a->ops->inited(a); | ||
158 | } | ||
159 | |||
160 | u64 gk20a_alloc_end(struct gk20a_allocator *a) | ||
161 | { | ||
162 | return a->ops->end(a); | ||
163 | } | ||
164 | |||
165 | u64 gk20a_alloc(struct gk20a_allocator *a, u64 len) | ||
166 | { | ||
167 | return a->ops->alloc(a, len); | ||
168 | } | ||
169 | |||
170 | void gk20a_free(struct gk20a_allocator *a, u64 addr) | ||
171 | { | ||
172 | a->ops->free(a, addr); | ||
173 | } | ||
174 | |||
175 | u64 gk20a_alloc_fixed(struct gk20a_allocator *a, u64 base, u64 len) | ||
176 | { | ||
177 | return a->ops->alloc_fixed(a, base, len); | ||
178 | } | ||
179 | |||
180 | void gk20a_free_fixed(struct gk20a_allocator *a, u64 base, u64 len) | ||
181 | { | ||
182 | /* | ||
183 | * If this operation is not defined for the allocator then just do | ||
184 | * nothing. The alternative would be to fall back on the regular | ||
185 | * free but that may be harmful in unexpected ways. | ||
186 | */ | ||
187 | if (a->ops->free_fixed) | ||
188 | a->ops->free_fixed(a, base, len); | ||
189 | } | ||
190 | |||
191 | void gk20a_alloc_destroy(struct gk20a_allocator *a) | ||
192 | { | ||
193 | a->ops->fini(a); | ||
194 | memset(a, 0, sizeof(*a)); | ||
195 | } | ||
196 | |||
83 | /* | 197 | /* |
84 | * Pick a suitable maximum order for this allocator. | 198 | * Pick a suitable maximum order for this allocator. |
85 | * | 199 | * |
86 | * Hueristic: Just guessing that the best max order is the largest single | 200 | * Hueristic: Just guessing that the best max order is the largest single |
87 | * block that will fit in the address space. | 201 | * block that will fit in the address space. |
88 | */ | 202 | */ |
89 | static void balloc_compute_max_order(struct gk20a_allocator *a) | 203 | static void balloc_compute_max_order(struct gk20a_buddy_allocator *a) |
90 | { | 204 | { |
91 | u64 true_max_order = ilog2(a->blks); | 205 | u64 true_max_order = ilog2(a->blks); |
92 | 206 | ||
@@ -105,9 +219,10 @@ static void balloc_compute_max_order(struct gk20a_allocator *a) | |||
105 | * Since we can only allocate in chucks of a->blk_size we need to trim off | 219 | * Since we can only allocate in chucks of a->blk_size we need to trim off |
106 | * any excess data that is not aligned to a->blk_size. | 220 | * any excess data that is not aligned to a->blk_size. |
107 | */ | 221 | */ |
108 | static void balloc_allocator_align(struct gk20a_allocator *a) | 222 | static void balloc_allocator_align(struct gk20a_buddy_allocator *a) |
109 | { | 223 | { |
110 | a->start = ALIGN(a->base, a->blk_size); | 224 | a->start = ALIGN(a->base, a->blk_size); |
225 | WARN_ON(a->start != a->base); | ||
111 | a->end = (a->base + a->length) & ~(a->blk_size - 1); | 226 | a->end = (a->base + a->length) & ~(a->blk_size - 1); |
112 | a->count = a->end - a->start; | 227 | a->count = a->end - a->start; |
113 | a->blks = a->count >> a->blk_shift; | 228 | a->blks = a->count >> a->blk_shift; |
@@ -116,7 +231,7 @@ static void balloc_allocator_align(struct gk20a_allocator *a) | |||
116 | /* | 231 | /* |
117 | * Pass NULL for parent if you want a top level buddy. | 232 | * Pass NULL for parent if you want a top level buddy. |
118 | */ | 233 | */ |
119 | static struct gk20a_buddy *balloc_new_buddy(struct gk20a_allocator *a, | 234 | static struct gk20a_buddy *balloc_new_buddy(struct gk20a_buddy_allocator *a, |
120 | struct gk20a_buddy *parent, | 235 | struct gk20a_buddy *parent, |
121 | u64 start, u64 order) | 236 | u64 start, u64 order) |
122 | { | 237 | { |
@@ -136,13 +251,14 @@ static struct gk20a_buddy *balloc_new_buddy(struct gk20a_allocator *a, | |||
136 | return new_buddy; | 251 | return new_buddy; |
137 | } | 252 | } |
138 | 253 | ||
139 | static void __balloc_buddy_list_add(struct gk20a_allocator *a, | 254 | static void __balloc_buddy_list_add(struct gk20a_buddy_allocator *a, |
140 | struct gk20a_buddy *b, | 255 | struct gk20a_buddy *b, |
141 | struct list_head *list) | 256 | struct list_head *list) |
142 | { | 257 | { |
143 | if (buddy_is_in_list(b)) { | 258 | if (buddy_is_in_list(b)) { |
144 | balloc_dbg(a, "Oops: adding added buddy (%llu:0x%llx)\n", | 259 | alloc_dbg(balloc_owner(a), |
145 | b->order, b->start); | 260 | "Oops: adding added buddy (%llu:0x%llx)\n", |
261 | b->order, b->start); | ||
146 | BUG(); | 262 | BUG(); |
147 | } | 263 | } |
148 | 264 | ||
@@ -160,12 +276,13 @@ static void __balloc_buddy_list_add(struct gk20a_allocator *a, | |||
160 | buddy_set_in_list(b); | 276 | buddy_set_in_list(b); |
161 | } | 277 | } |
162 | 278 | ||
163 | static void __balloc_buddy_list_rem(struct gk20a_allocator *a, | 279 | static void __balloc_buddy_list_rem(struct gk20a_buddy_allocator *a, |
164 | struct gk20a_buddy *b) | 280 | struct gk20a_buddy *b) |
165 | { | 281 | { |
166 | if (!buddy_is_in_list(b)) { | 282 | if (!buddy_is_in_list(b)) { |
167 | balloc_dbg(a, "Oops: removing removed buddy (%llu:0x%llx)\n", | 283 | alloc_dbg(balloc_owner(a), |
168 | b->order, b->start); | 284 | "Oops: removing removed buddy (%llu:0x%llx)\n", |
285 | b->order, b->start); | ||
169 | BUG(); | 286 | BUG(); |
170 | } | 287 | } |
171 | 288 | ||
@@ -177,19 +294,21 @@ static void __balloc_buddy_list_rem(struct gk20a_allocator *a, | |||
177 | * Add a buddy to one of the buddy lists and deal with the necessary | 294 | * Add a buddy to one of the buddy lists and deal with the necessary |
178 | * book keeping. Adds the buddy to the list specified by the buddy's order. | 295 | * book keeping. Adds the buddy to the list specified by the buddy's order. |
179 | */ | 296 | */ |
180 | static void balloc_blist_add(struct gk20a_allocator *a, struct gk20a_buddy *b) | 297 | static void balloc_blist_add(struct gk20a_buddy_allocator *a, |
298 | struct gk20a_buddy *b) | ||
181 | { | 299 | { |
182 | __balloc_buddy_list_add(a, b, balloc_get_order_list(a, b->order)); | 300 | __balloc_buddy_list_add(a, b, balloc_get_order_list(a, b->order)); |
183 | a->buddy_list_len[b->order]++; | 301 | a->buddy_list_len[b->order]++; |
184 | } | 302 | } |
185 | 303 | ||
186 | static void balloc_blist_rem(struct gk20a_allocator *a, struct gk20a_buddy *b) | 304 | static void balloc_blist_rem(struct gk20a_buddy_allocator *a, |
305 | struct gk20a_buddy *b) | ||
187 | { | 306 | { |
188 | __balloc_buddy_list_rem(a, b); | 307 | __balloc_buddy_list_rem(a, b); |
189 | a->buddy_list_len[b->order]--; | 308 | a->buddy_list_len[b->order]--; |
190 | } | 309 | } |
191 | 310 | ||
192 | static u64 balloc_get_order(struct gk20a_allocator *a, u64 len) | 311 | static u64 balloc_get_order(struct gk20a_buddy_allocator *a, u64 len) |
193 | { | 312 | { |
194 | if (len == 0) | 313 | if (len == 0) |
195 | return 0; | 314 | return 0; |
@@ -200,7 +319,8 @@ static u64 balloc_get_order(struct gk20a_allocator *a, u64 len) | |||
200 | return fls(len); | 319 | return fls(len); |
201 | } | 320 | } |
202 | 321 | ||
203 | static u64 __balloc_max_order_in(struct gk20a_allocator *a, u64 start, u64 end) | 322 | static u64 __balloc_max_order_in(struct gk20a_buddy_allocator *a, |
323 | u64 start, u64 end) | ||
204 | { | 324 | { |
205 | u64 size = (end - start) >> a->blk_shift; | 325 | u64 size = (end - start) >> a->blk_shift; |
206 | 326 | ||
@@ -213,7 +333,7 @@ static u64 __balloc_max_order_in(struct gk20a_allocator *a, u64 start, u64 end) | |||
213 | /* | 333 | /* |
214 | * Initialize the buddy lists. | 334 | * Initialize the buddy lists. |
215 | */ | 335 | */ |
216 | static int balloc_init_lists(struct gk20a_allocator *a) | 336 | static int balloc_init_lists(struct gk20a_buddy_allocator *a) |
217 | { | 337 | { |
218 | int i; | 338 | int i; |
219 | u64 bstart, bend, order; | 339 | u64 bstart, bend, order; |
@@ -253,6 +373,26 @@ cleanup: | |||
253 | } | 373 | } |
254 | 374 | ||
255 | /* | 375 | /* |
376 | * Handle the common init stuff for a gk20a_allocator. | ||
377 | */ | ||
378 | static int __gk20a_alloc_common_init(struct gk20a_allocator *a, | ||
379 | const char *name, void *priv, | ||
380 | const struct gk20a_allocator_ops *ops) | ||
381 | { | ||
382 | if (!ops) | ||
383 | return -EINVAL; | ||
384 | |||
385 | a->ops = ops; | ||
386 | a->priv = priv; | ||
387 | |||
388 | mutex_init(&a->lock); | ||
389 | |||
390 | strlcpy(a->name, name, sizeof(a->name)); | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | /* | ||
256 | * Initialize a buddy allocator. Returns 0 on success. This allocator does | 396 | * Initialize a buddy allocator. Returns 0 on success. This allocator does |
257 | * not necessarily manage bytes. It manages distinct ranges of resources. This | 397 | * not necessarily manage bytes. It manages distinct ranges of resources. This |
258 | * allows the allocator to work for things like comp_tags, semaphores, etc. | 398 | * allows the allocator to work for things like comp_tags, semaphores, etc. |
@@ -270,20 +410,40 @@ cleanup: | |||
270 | * will try and pick a reasonable max order. | 410 | * will try and pick a reasonable max order. |
271 | * @flags: Extra flags necessary. See GPU_BALLOC_*. | 411 | * @flags: Extra flags necessary. See GPU_BALLOC_*. |
272 | */ | 412 | */ |
273 | int __gk20a_allocator_init(struct gk20a_allocator *a, | 413 | int __gk20a_buddy_allocator_init(struct gk20a_allocator *__a, |
274 | struct vm_gk20a *vm, const char *name, | 414 | struct vm_gk20a *vm, const char *name, |
275 | u64 base, u64 size, u64 blk_size, u64 max_order, | 415 | u64 base, u64 size, u64 blk_size, |
276 | u64 flags) | 416 | u64 max_order, u64 flags) |
277 | { | 417 | { |
278 | int err; | 418 | int err; |
419 | struct gk20a_buddy_allocator *a; | ||
420 | |||
421 | /* blk_size must be greater than 0 and a power of 2. */ | ||
422 | if (blk_size == 0) | ||
423 | return -EINVAL; | ||
424 | if (blk_size & (blk_size - 1)) | ||
425 | return -EINVAL; | ||
279 | 426 | ||
280 | memset(a, 0, sizeof(struct gk20a_allocator)); | 427 | if (max_order > GPU_BALLOC_MAX_ORDER) |
281 | strncpy(a->name, name, 32); | 428 | return -EINVAL; |
429 | |||
430 | /* If this is to manage a GVA space we need a VM. */ | ||
431 | if (flags & GPU_BALLOC_GVA_SPACE && !vm) | ||
432 | return -EINVAL; | ||
433 | |||
434 | a = kzalloc(sizeof(struct gk20a_buddy_allocator), GFP_KERNEL); | ||
435 | if (!a) | ||
436 | return -ENOMEM; | ||
437 | |||
438 | err = __gk20a_alloc_common_init(__a, name, a, &buddy_ops); | ||
439 | if (err) | ||
440 | goto fail; | ||
282 | 441 | ||
283 | a->base = base; | 442 | a->base = base; |
284 | a->length = size; | 443 | a->length = size; |
285 | a->blk_size = blk_size; | 444 | a->blk_size = blk_size; |
286 | a->blk_shift = __ffs(blk_size); | 445 | a->blk_shift = __ffs(blk_size); |
446 | a->owner = __a; | ||
287 | 447 | ||
288 | /* | 448 | /* |
289 | * If base is 0 then modfy base to be the size of one block so that we | 449 | * If base is 0 then modfy base to be the size of one block so that we |
@@ -294,19 +454,6 @@ int __gk20a_allocator_init(struct gk20a_allocator *a, | |||
294 | a->length -= a->blk_size; | 454 | a->length -= a->blk_size; |
295 | } | 455 | } |
296 | 456 | ||
297 | /* blk_size must be greater than 0 and a power of 2. */ | ||
298 | if (blk_size == 0) | ||
299 | return -EINVAL; | ||
300 | if (blk_size & (blk_size - 1)) | ||
301 | return -EINVAL; | ||
302 | |||
303 | if (max_order > GPU_BALLOC_MAX_ORDER) | ||
304 | return -EINVAL; | ||
305 | |||
306 | /* If this is to manage a GVA space we need a VM. */ | ||
307 | if (flags & GPU_BALLOC_GVA_SPACE && !vm) | ||
308 | return -EINVAL; | ||
309 | |||
310 | a->vm = vm; | 457 | a->vm = vm; |
311 | if (flags & GPU_BALLOC_GVA_SPACE) | 458 | if (flags & GPU_BALLOC_GVA_SPACE) |
312 | a->pte_blk_order = balloc_get_order(a, vm->big_page_size << 10); | 459 | a->pte_blk_order = balloc_get_order(a, vm->big_page_size << 10); |
@@ -320,49 +467,55 @@ int __gk20a_allocator_init(struct gk20a_allocator *a, | |||
320 | /* Shared buddy kmem_cache for all allocators. */ | 467 | /* Shared buddy kmem_cache for all allocators. */ |
321 | if (!buddy_cache) | 468 | if (!buddy_cache) |
322 | buddy_cache = KMEM_CACHE(gk20a_buddy, 0); | 469 | buddy_cache = KMEM_CACHE(gk20a_buddy, 0); |
323 | if (!buddy_cache) | 470 | if (!buddy_cache) { |
324 | return -ENOMEM; | 471 | err = -ENOMEM; |
472 | goto fail; | ||
473 | } | ||
325 | 474 | ||
326 | a->alloced_buddies = RB_ROOT; | 475 | a->alloced_buddies = RB_ROOT; |
476 | a->fixed_allocs = RB_ROOT; | ||
327 | err = balloc_init_lists(a); | 477 | err = balloc_init_lists(a); |
328 | if (err) | 478 | if (err) |
329 | return err; | 479 | goto fail; |
330 | |||
331 | mutex_init(&a->lock); | ||
332 | 480 | ||
333 | a->init = 1; | 481 | a->inited = 1; |
334 | 482 | ||
335 | balloc_init_alloc_debug(a); | 483 | gk20a_init_alloc_debug(__a); |
336 | balloc_dbg(a, "New allocator: base 0x%llx\n", a->base); | 484 | alloc_dbg(__a, "New allocator: base 0x%llx\n", a->base); |
337 | balloc_dbg(a, " size 0x%llx\n", a->length); | 485 | alloc_dbg(__a, " size 0x%llx\n", a->length); |
338 | balloc_dbg(a, " blk_size 0x%llx\n", a->blk_size); | 486 | alloc_dbg(__a, " blk_size 0x%llx\n", a->blk_size); |
339 | balloc_dbg(a, " max_order %llu\n", a->max_order); | 487 | alloc_dbg(__a, " max_order %llu\n", a->max_order); |
340 | balloc_dbg(a, " flags 0x%llx\n", a->flags); | 488 | alloc_dbg(__a, " flags 0x%llx\n", a->flags); |
341 | 489 | ||
342 | return 0; | 490 | return 0; |
491 | |||
492 | fail: | ||
493 | kfree(a); | ||
494 | return err; | ||
343 | } | 495 | } |
344 | 496 | ||
345 | int gk20a_allocator_init(struct gk20a_allocator *a, const char *name, | 497 | int gk20a_buddy_allocator_init(struct gk20a_allocator *a, const char *name, |
346 | u64 base, u64 size, u64 blk_size) | 498 | u64 base, u64 size, u64 blk_size, u64 flags) |
347 | { | 499 | { |
348 | return __gk20a_allocator_init(a, NULL, name, | 500 | return __gk20a_buddy_allocator_init(a, NULL, name, |
349 | base, size, blk_size, 0, 0); | 501 | base, size, blk_size, 0, 0); |
350 | } | 502 | } |
351 | 503 | ||
352 | /* | 504 | /* |
353 | * Clean up and destroy the passed allocator. | 505 | * Clean up and destroy the passed allocator. |
354 | */ | 506 | */ |
355 | void gk20a_allocator_destroy(struct gk20a_allocator *a) | 507 | static void gk20a_buddy_allocator_destroy(struct gk20a_allocator *__a) |
356 | { | 508 | { |
509 | int i; | ||
357 | struct rb_node *node; | 510 | struct rb_node *node; |
358 | struct gk20a_buddy *bud; | 511 | struct gk20a_buddy *bud; |
359 | struct gk20a_fixed_alloc *falloc; | 512 | struct gk20a_fixed_alloc *falloc; |
360 | int i; | 513 | struct gk20a_buddy_allocator *a = __a->priv; |
361 | 514 | ||
362 | balloc_lock(a); | 515 | alloc_lock(__a); |
363 | 516 | ||
364 | if (!IS_ERR_OR_NULL(a->debugfs_entry)) | 517 | if (!IS_ERR_OR_NULL(__a->debugfs_entry)) |
365 | debugfs_remove(a->debugfs_entry); | 518 | debugfs_remove(__a->debugfs_entry); |
366 | 519 | ||
367 | /* | 520 | /* |
368 | * Free the fixed allocs first. | 521 | * Free the fixed allocs first. |
@@ -415,16 +568,9 @@ void gk20a_allocator_destroy(struct gk20a_allocator *a) | |||
415 | } | 568 | } |
416 | } | 569 | } |
417 | 570 | ||
418 | a->init = 0; | 571 | kfree(a); |
419 | 572 | ||
420 | balloc_unlock(a); | 573 | alloc_unlock(__a); |
421 | |||
422 | /* | ||
423 | * We cant unlock an allocator after memsetting it. That wipes the | ||
424 | * state of the mutex. Hopefully no one uses the allocator after | ||
425 | * destroying it... | ||
426 | */ | ||
427 | memset(a, 0, sizeof(struct gk20a_allocator)); | ||
428 | } | 574 | } |
429 | 575 | ||
430 | /* | 576 | /* |
@@ -433,7 +579,8 @@ void gk20a_allocator_destroy(struct gk20a_allocator *a) | |||
433 | * | 579 | * |
434 | * @a must be locked. | 580 | * @a must be locked. |
435 | */ | 581 | */ |
436 | static void balloc_coalesce(struct gk20a_allocator *a, struct gk20a_buddy *b) | 582 | static void balloc_coalesce(struct gk20a_buddy_allocator *a, |
583 | struct gk20a_buddy *b) | ||
437 | { | 584 | { |
438 | struct gk20a_buddy *parent; | 585 | struct gk20a_buddy *parent; |
439 | 586 | ||
@@ -473,8 +620,8 @@ static void balloc_coalesce(struct gk20a_allocator *a, struct gk20a_buddy *b) | |||
473 | * | 620 | * |
474 | * @a must be locked. | 621 | * @a must be locked. |
475 | */ | 622 | */ |
476 | static int balloc_split_buddy(struct gk20a_allocator *a, struct gk20a_buddy *b, | 623 | static int balloc_split_buddy(struct gk20a_buddy_allocator *a, |
477 | int pte_size) | 624 | struct gk20a_buddy *b, int pte_size) |
478 | { | 625 | { |
479 | struct gk20a_buddy *left, *right; | 626 | struct gk20a_buddy *left, *right; |
480 | u64 half; | 627 | u64 half; |
@@ -521,7 +668,8 @@ static int balloc_split_buddy(struct gk20a_allocator *a, struct gk20a_buddy *b, | |||
521 | * | 668 | * |
522 | * @a must be locked. | 669 | * @a must be locked. |
523 | */ | 670 | */ |
524 | static void balloc_alloc_buddy(struct gk20a_allocator *a, struct gk20a_buddy *b) | 671 | static void balloc_alloc_buddy(struct gk20a_buddy_allocator *a, |
672 | struct gk20a_buddy *b) | ||
525 | { | 673 | { |
526 | struct rb_node **new = &(a->alloced_buddies.rb_node); | 674 | struct rb_node **new = &(a->alloced_buddies.rb_node); |
527 | struct rb_node *parent = NULL; | 675 | struct rb_node *parent = NULL; |
@@ -552,7 +700,7 @@ static void balloc_alloc_buddy(struct gk20a_allocator *a, struct gk20a_buddy *b) | |||
552 | * | 700 | * |
553 | * @a must be locked. | 701 | * @a must be locked. |
554 | */ | 702 | */ |
555 | static struct gk20a_buddy *balloc_free_buddy(struct gk20a_allocator *a, | 703 | static struct gk20a_buddy *balloc_free_buddy(struct gk20a_buddy_allocator *a, |
556 | u64 addr) | 704 | u64 addr) |
557 | { | 705 | { |
558 | struct rb_node *node = a->alloced_buddies.rb_node; | 706 | struct rb_node *node = a->alloced_buddies.rb_node; |
@@ -582,7 +730,7 @@ static struct gk20a_buddy *balloc_free_buddy(struct gk20a_allocator *a, | |||
582 | /* | 730 | /* |
583 | * Find a suitable buddy for the given order and PTE type (big or little). | 731 | * Find a suitable buddy for the given order and PTE type (big or little). |
584 | */ | 732 | */ |
585 | static struct gk20a_buddy *__balloc_find_buddy(struct gk20a_allocator *a, | 733 | static struct gk20a_buddy *__balloc_find_buddy(struct gk20a_buddy_allocator *a, |
586 | u64 order, int pte_size) | 734 | u64 order, int pte_size) |
587 | { | 735 | { |
588 | struct gk20a_buddy *bud; | 736 | struct gk20a_buddy *bud; |
@@ -615,7 +763,8 @@ static struct gk20a_buddy *__balloc_find_buddy(struct gk20a_allocator *a, | |||
615 | * | 763 | * |
616 | * @a must be locked. | 764 | * @a must be locked. |
617 | */ | 765 | */ |
618 | static u64 __balloc_do_alloc(struct gk20a_allocator *a, u64 order, int pte_size) | 766 | static u64 __balloc_do_alloc(struct gk20a_buddy_allocator *a, |
767 | u64 order, int pte_size) | ||
619 | { | 768 | { |
620 | u64 split_order; | 769 | u64 split_order; |
621 | struct gk20a_buddy *bud = NULL; | 770 | struct gk20a_buddy *bud = NULL; |
@@ -644,21 +793,22 @@ static u64 __balloc_do_alloc(struct gk20a_allocator *a, u64 order, int pte_size) | |||
644 | /* | 793 | /* |
645 | * Allocate memory from the passed allocator. | 794 | * Allocate memory from the passed allocator. |
646 | */ | 795 | */ |
647 | u64 gk20a_balloc(struct gk20a_allocator *a, u64 len) | 796 | static u64 gk20a_buddy_alloc(struct gk20a_allocator *__a, u64 len) |
648 | { | 797 | { |
649 | u64 order, addr; | 798 | u64 order, addr; |
650 | int pte_size; | 799 | int pte_size; |
800 | struct gk20a_buddy_allocator *a = __a->priv; | ||
651 | 801 | ||
652 | balloc_trace_func(); | 802 | gk20a_alloc_trace_func(); |
653 | 803 | ||
654 | balloc_lock(a); | 804 | alloc_lock(__a); |
655 | 805 | ||
656 | order = balloc_get_order(a, len); | 806 | order = balloc_get_order(a, len); |
657 | 807 | ||
658 | if (order > a->max_order) { | 808 | if (order > a->max_order) { |
659 | balloc_unlock(a); | 809 | alloc_unlock(__a); |
660 | balloc_dbg(a, "Alloc fail\n"); | 810 | alloc_dbg(balloc_owner(a), "Alloc fail\n"); |
661 | balloc_trace_func_done(); | 811 | gk20a_alloc_trace_func_done(); |
662 | return 0; | 812 | return 0; |
663 | } | 813 | } |
664 | 814 | ||
@@ -681,18 +831,19 @@ u64 gk20a_balloc(struct gk20a_allocator *a, u64 len) | |||
681 | if (addr) { | 831 | if (addr) { |
682 | a->bytes_alloced += len; | 832 | a->bytes_alloced += len; |
683 | a->bytes_alloced_real += balloc_order_to_len(a, order); | 833 | a->bytes_alloced_real += balloc_order_to_len(a, order); |
684 | balloc_dbg(a, "Alloc 0x%-10llx %3lld:0x%-10llx pte_size=%s\n", | 834 | alloc_dbg(balloc_owner(a), |
685 | addr, order, len, | 835 | "Alloc 0x%-10llx %3lld:0x%-10llx pte_size=%s\n", |
836 | addr, order, len, | ||
686 | pte_size == gmmu_page_size_big ? "big" : | 837 | pte_size == gmmu_page_size_big ? "big" : |
687 | pte_size == gmmu_page_size_small ? "small" : | 838 | pte_size == gmmu_page_size_small ? "small" : |
688 | "NA/any"); | 839 | "NA/any"); |
689 | } else { | 840 | } else { |
690 | balloc_dbg(a, "Alloc failed: no mem!\n"); | 841 | alloc_dbg(balloc_owner(a), "Alloc failed: no mem!\n"); |
691 | } | 842 | } |
692 | 843 | ||
693 | balloc_unlock(a); | 844 | alloc_unlock(__a); |
694 | 845 | ||
695 | balloc_trace_func_done(); | 846 | gk20a_alloc_trace_func_done(); |
696 | return addr; | 847 | return addr; |
697 | } | 848 | } |
698 | 849 | ||
@@ -703,7 +854,8 @@ u64 gk20a_balloc(struct gk20a_allocator *a, u64 len) | |||
703 | * TODO: Right now this uses the unoptimal approach of going through all | 854 | * TODO: Right now this uses the unoptimal approach of going through all |
704 | * outstanding allocations and checking their base/ends. This could be better. | 855 | * outstanding allocations and checking their base/ends. This could be better. |
705 | */ | 856 | */ |
706 | static int balloc_is_range_free(struct gk20a_allocator *a, u64 base, u64 end) | 857 | static int balloc_is_range_free(struct gk20a_buddy_allocator *a, |
858 | u64 base, u64 end) | ||
707 | { | 859 | { |
708 | struct rb_node *node; | 860 | struct rb_node *node; |
709 | struct gk20a_buddy *bud; | 861 | struct gk20a_buddy *bud; |
@@ -728,7 +880,7 @@ static int balloc_is_range_free(struct gk20a_allocator *a, u64 base, u64 end) | |||
728 | return 1; | 880 | return 1; |
729 | } | 881 | } |
730 | 882 | ||
731 | static void balloc_alloc_fixed(struct gk20a_allocator *a, | 883 | static void balloc_alloc_fixed(struct gk20a_buddy_allocator *a, |
732 | struct gk20a_fixed_alloc *f) | 884 | struct gk20a_fixed_alloc *f) |
733 | { | 885 | { |
734 | struct rb_node **new = &(a->fixed_allocs.rb_node); | 886 | struct rb_node **new = &(a->fixed_allocs.rb_node); |
@@ -758,8 +910,8 @@ static void balloc_alloc_fixed(struct gk20a_allocator *a, | |||
758 | * | 910 | * |
759 | * @a must be locked. | 911 | * @a must be locked. |
760 | */ | 912 | */ |
761 | static struct gk20a_fixed_alloc *balloc_free_fixed(struct gk20a_allocator *a, | 913 | static struct gk20a_fixed_alloc *balloc_free_fixed( |
762 | u64 addr) | 914 | struct gk20a_buddy_allocator *a, u64 addr) |
763 | { | 915 | { |
764 | struct rb_node *node = a->fixed_allocs.rb_node; | 916 | struct rb_node *node = a->fixed_allocs.rb_node; |
765 | struct gk20a_fixed_alloc *falloc; | 917 | struct gk20a_fixed_alloc *falloc; |
@@ -788,7 +940,7 @@ static struct gk20a_fixed_alloc *balloc_free_fixed(struct gk20a_allocator *a, | |||
788 | * Find the parent range - doesn't necessarily need the parent to actually exist | 940 | * Find the parent range - doesn't necessarily need the parent to actually exist |
789 | * as a buddy. Finding an existing parent comes later... | 941 | * as a buddy. Finding an existing parent comes later... |
790 | */ | 942 | */ |
791 | static void __balloc_get_parent_range(struct gk20a_allocator *a, | 943 | static void __balloc_get_parent_range(struct gk20a_buddy_allocator *a, |
792 | u64 base, u64 order, | 944 | u64 base, u64 order, |
793 | u64 *pbase, u64 *porder) | 945 | u64 *pbase, u64 *porder) |
794 | { | 946 | { |
@@ -808,8 +960,8 @@ static void __balloc_get_parent_range(struct gk20a_allocator *a, | |||
808 | * Makes a buddy at the passed address. This will make all parent buddies | 960 | * Makes a buddy at the passed address. This will make all parent buddies |
809 | * necessary for this buddy to exist as well. | 961 | * necessary for this buddy to exist as well. |
810 | */ | 962 | */ |
811 | static struct gk20a_buddy *__balloc_make_fixed_buddy(struct gk20a_allocator *a, | 963 | static struct gk20a_buddy *__balloc_make_fixed_buddy( |
812 | u64 base, u64 order) | 964 | struct gk20a_buddy_allocator *a, u64 base, u64 order) |
813 | { | 965 | { |
814 | struct gk20a_buddy *bud = NULL; | 966 | struct gk20a_buddy *bud = NULL; |
815 | struct list_head *order_list; | 967 | struct list_head *order_list; |
@@ -843,7 +995,7 @@ static struct gk20a_buddy *__balloc_make_fixed_buddy(struct gk20a_allocator *a, | |||
843 | } | 995 | } |
844 | 996 | ||
845 | if (cur_order > a->max_order) { | 997 | if (cur_order > a->max_order) { |
846 | balloc_dbg(a, "No buddy for range ???\n"); | 998 | alloc_dbg(balloc_owner(a), "No buddy for range ???\n"); |
847 | return NULL; | 999 | return NULL; |
848 | } | 1000 | } |
849 | 1001 | ||
@@ -864,7 +1016,7 @@ static struct gk20a_buddy *__balloc_make_fixed_buddy(struct gk20a_allocator *a, | |||
864 | return bud; | 1016 | return bud; |
865 | } | 1017 | } |
866 | 1018 | ||
867 | static u64 __balloc_do_alloc_fixed(struct gk20a_allocator *a, | 1019 | static u64 __balloc_do_alloc_fixed(struct gk20a_buddy_allocator *a, |
868 | struct gk20a_fixed_alloc *falloc, | 1020 | struct gk20a_fixed_alloc *falloc, |
869 | u64 base, u64 len) | 1021 | u64 base, u64 len) |
870 | { | 1022 | { |
@@ -880,7 +1032,8 @@ static u64 __balloc_do_alloc_fixed(struct gk20a_allocator *a, | |||
880 | __fls(len >> a->blk_shift)); | 1032 | __fls(len >> a->blk_shift)); |
881 | 1033 | ||
882 | if (align_order > a->max_order) { | 1034 | if (align_order > a->max_order) { |
883 | balloc_dbg(a, "Align order too big: %llu > %llu\n", | 1035 | alloc_dbg(balloc_owner(a), |
1036 | "Align order too big: %llu > %llu\n", | ||
884 | align_order, a->max_order); | 1037 | align_order, a->max_order); |
885 | return 0; | 1038 | return 0; |
886 | } | 1039 | } |
@@ -898,7 +1051,8 @@ static u64 __balloc_do_alloc_fixed(struct gk20a_allocator *a, | |||
898 | balloc_base_unshift(a, inc_base), | 1051 | balloc_base_unshift(a, inc_base), |
899 | align_order); | 1052 | align_order); |
900 | if (!bud) { | 1053 | if (!bud) { |
901 | balloc_dbg(a, "Fixed buddy failed: {0x%llx, %llu}!\n", | 1054 | alloc_dbg(balloc_owner(a), |
1055 | "Fixed buddy failed: {0x%llx, %llu}!\n", | ||
902 | balloc_base_unshift(a, inc_base), | 1056 | balloc_base_unshift(a, inc_base), |
903 | align_order); | 1057 | align_order); |
904 | goto err_and_cleanup; | 1058 | goto err_and_cleanup; |
@@ -943,13 +1097,15 @@ err_and_cleanup: | |||
943 | * | 1097 | * |
944 | * Please do not use this function unless _absolutely_ necessary. | 1098 | * Please do not use this function unless _absolutely_ necessary. |
945 | */ | 1099 | */ |
946 | u64 gk20a_balloc_fixed(struct gk20a_allocator *a, u64 base, u64 len) | 1100 | static u64 gk20a_buddy_alloc_fixed(struct gk20a_allocator *__a, |
1101 | u64 base, u64 len) | ||
947 | { | 1102 | { |
948 | struct gk20a_fixed_alloc *falloc = NULL; | ||
949 | struct gk20a_buddy *bud; | ||
950 | u64 ret, real_bytes = 0; | 1103 | u64 ret, real_bytes = 0; |
1104 | struct gk20a_buddy *bud; | ||
1105 | struct gk20a_fixed_alloc *falloc = NULL; | ||
1106 | struct gk20a_buddy_allocator *a = __a->priv; | ||
951 | 1107 | ||
952 | balloc_trace_func(); | 1108 | gk20a_alloc_trace_func(); |
953 | 1109 | ||
954 | /* If base isn't aligned to an order 0 block, fail. */ | 1110 | /* If base isn't aligned to an order 0 block, fail. */ |
955 | if (base & (a->blk_size - 1)) | 1111 | if (base & (a->blk_size - 1)) |
@@ -966,16 +1122,18 @@ u64 gk20a_balloc_fixed(struct gk20a_allocator *a, u64 base, u64 len) | |||
966 | falloc->start = base; | 1122 | falloc->start = base; |
967 | falloc->end = base + len; | 1123 | falloc->end = base + len; |
968 | 1124 | ||
969 | balloc_lock(a); | 1125 | alloc_lock(__a); |
970 | if (!balloc_is_range_free(a, base, base + len)) { | 1126 | if (!balloc_is_range_free(a, base, base + len)) { |
971 | balloc_dbg(a, "Range not free: 0x%llx -> 0x%llx\n", | 1127 | alloc_dbg(balloc_owner(a), |
1128 | "Range not free: 0x%llx -> 0x%llx\n", | ||
972 | base, base + len); | 1129 | base, base + len); |
973 | goto fail_unlock; | 1130 | goto fail_unlock; |
974 | } | 1131 | } |
975 | 1132 | ||
976 | ret = __balloc_do_alloc_fixed(a, falloc, base, len); | 1133 | ret = __balloc_do_alloc_fixed(a, falloc, base, len); |
977 | if (!ret) { | 1134 | if (!ret) { |
978 | balloc_dbg(a, "Alloc-fixed failed ?? 0x%llx -> 0x%llx\n", | 1135 | alloc_dbg(balloc_owner(a), |
1136 | "Alloc-fixed failed ?? 0x%llx -> 0x%llx\n", | ||
979 | base, base + len); | 1137 | base, base + len); |
980 | goto fail_unlock; | 1138 | goto fail_unlock; |
981 | } | 1139 | } |
@@ -988,21 +1146,21 @@ u64 gk20a_balloc_fixed(struct gk20a_allocator *a, u64 base, u64 len) | |||
988 | a->bytes_alloced += len; | 1146 | a->bytes_alloced += len; |
989 | a->bytes_alloced_real += real_bytes; | 1147 | a->bytes_alloced_real += real_bytes; |
990 | 1148 | ||
991 | balloc_unlock(a); | 1149 | alloc_unlock(__a); |
992 | balloc_dbg(a, "Alloc (fixed) 0x%llx\n", base); | 1150 | alloc_dbg(balloc_owner(a), "Alloc (fixed) 0x%llx\n", base); |
993 | 1151 | ||
994 | balloc_trace_func_done(); | 1152 | gk20a_alloc_trace_func_done(); |
995 | return base; | 1153 | return base; |
996 | 1154 | ||
997 | fail_unlock: | 1155 | fail_unlock: |
998 | balloc_unlock(a); | 1156 | alloc_unlock(__a); |
999 | fail: | 1157 | fail: |
1000 | kfree(falloc); | 1158 | kfree(falloc); |
1001 | balloc_trace_func_done(); | 1159 | gk20a_alloc_trace_func_done(); |
1002 | return 0; | 1160 | return 0; |
1003 | } | 1161 | } |
1004 | 1162 | ||
1005 | static void __balloc_do_free_fixed(struct gk20a_allocator *a, | 1163 | static void __balloc_do_free_fixed(struct gk20a_buddy_allocator *a, |
1006 | struct gk20a_fixed_alloc *falloc) | 1164 | struct gk20a_fixed_alloc *falloc) |
1007 | { | 1165 | { |
1008 | struct gk20a_buddy *bud; | 1166 | struct gk20a_buddy *bud; |
@@ -1029,19 +1187,20 @@ static void __balloc_do_free_fixed(struct gk20a_allocator *a, | |||
1029 | /* | 1187 | /* |
1030 | * Free the passed allocation. | 1188 | * Free the passed allocation. |
1031 | */ | 1189 | */ |
1032 | void gk20a_bfree(struct gk20a_allocator *a, u64 addr) | 1190 | static void gk20a_buddy_free(struct gk20a_allocator *__a, u64 addr) |
1033 | { | 1191 | { |
1034 | struct gk20a_buddy *bud; | 1192 | struct gk20a_buddy *bud; |
1035 | struct gk20a_fixed_alloc *falloc; | 1193 | struct gk20a_fixed_alloc *falloc; |
1194 | struct gk20a_buddy_allocator *a = __a->priv; | ||
1036 | 1195 | ||
1037 | balloc_trace_func(); | 1196 | gk20a_alloc_trace_func(); |
1038 | 1197 | ||
1039 | if (!addr) { | 1198 | if (!addr) { |
1040 | balloc_trace_func_done(); | 1199 | gk20a_alloc_trace_func_done(); |
1041 | return; | 1200 | return; |
1042 | } | 1201 | } |
1043 | 1202 | ||
1044 | balloc_lock(a); | 1203 | alloc_lock(__a); |
1045 | 1204 | ||
1046 | /* | 1205 | /* |
1047 | * First see if this is a fixed alloc. If not fall back to a regular | 1206 | * First see if this is a fixed alloc. If not fall back to a regular |
@@ -1066,9 +1225,9 @@ void gk20a_bfree(struct gk20a_allocator *a, u64 addr) | |||
1066 | balloc_coalesce(a, bud); | 1225 | balloc_coalesce(a, bud); |
1067 | 1226 | ||
1068 | done: | 1227 | done: |
1069 | balloc_unlock(a); | 1228 | alloc_unlock(__a); |
1070 | balloc_dbg(a, "Free 0x%llx\n", addr); | 1229 | alloc_dbg(balloc_owner(a), "Free 0x%llx\n", addr); |
1071 | balloc_trace_func_done(); | 1230 | gk20a_alloc_trace_func_done(); |
1072 | return; | 1231 | return; |
1073 | } | 1232 | } |
1074 | 1233 | ||
@@ -1077,49 +1236,42 @@ done: | |||
1077 | * stats are printed to the kernel log. This lets this code be used for | 1236 | * stats are printed to the kernel log. This lets this code be used for |
1078 | * debugging purposes internal to the allocator. | 1237 | * debugging purposes internal to the allocator. |
1079 | */ | 1238 | */ |
1080 | static void balloc_print_stats(struct gk20a_allocator *a, struct seq_file *s, | 1239 | static void gk20a_buddy_print_stats(struct gk20a_allocator *__a, |
1081 | int lock) | 1240 | struct seq_file *s, int lock) |
1082 | { | 1241 | { |
1083 | #define __balloc_pstat(s, fmt, arg...) \ | ||
1084 | do { \ | ||
1085 | if (s) \ | ||
1086 | seq_printf(s, fmt, ##arg); \ | ||
1087 | else \ | ||
1088 | balloc_dbg(a, fmt, ##arg); \ | ||
1089 | } while (0) | ||
1090 | |||
1091 | int i; | 1242 | int i; |
1092 | struct rb_node *node; | 1243 | struct rb_node *node; |
1093 | struct gk20a_fixed_alloc *falloc; | 1244 | struct gk20a_fixed_alloc *falloc; |
1245 | struct gk20a_buddy_allocator *a = __a->priv; | ||
1094 | 1246 | ||
1095 | __balloc_pstat(s, "base = %llu, limit = %llu, blk_size = %llu\n", | 1247 | __alloc_pstat(s, __a, "base = %llu, limit = %llu, blk_size = %llu\n", |
1096 | a->base, a->length, a->blk_size); | 1248 | a->base, a->length, a->blk_size); |
1097 | __balloc_pstat(s, "Internal params:\n"); | 1249 | __alloc_pstat(s, __a, "Internal params:\n"); |
1098 | __balloc_pstat(s, " start = 0x%llx\n", a->start); | 1250 | __alloc_pstat(s, __a, " start = 0x%llx\n", a->start); |
1099 | __balloc_pstat(s, " end = 0x%llx\n", a->end); | 1251 | __alloc_pstat(s, __a, " end = 0x%llx\n", a->end); |
1100 | __balloc_pstat(s, " count = 0x%llx\n", a->count); | 1252 | __alloc_pstat(s, __a, " count = 0x%llx\n", a->count); |
1101 | __balloc_pstat(s, " blks = 0x%llx\n", a->blks); | 1253 | __alloc_pstat(s, __a, " blks = 0x%llx\n", a->blks); |
1102 | __balloc_pstat(s, " max_order = %llu\n", a->max_order); | 1254 | __alloc_pstat(s, __a, " max_order = %llu\n", a->max_order); |
1103 | 1255 | ||
1104 | __balloc_pstat(s, "Buddy blocks:\n"); | 1256 | __alloc_pstat(s, __a, "Buddy blocks:\n"); |
1105 | __balloc_pstat(s, " Order Free Alloced Split\n"); | 1257 | __alloc_pstat(s, __a, " Order Free Alloced Split\n"); |
1106 | __balloc_pstat(s, " ----- ---- ------- -----\n"); | 1258 | __alloc_pstat(s, __a, " ----- ---- ------- -----\n"); |
1107 | 1259 | ||
1108 | if (lock) | 1260 | if (lock) |
1109 | balloc_lock(a); | 1261 | alloc_lock(__a); |
1110 | for (i = a->max_order; i >= 0; i--) { | 1262 | for (i = a->max_order; i >= 0; i--) { |
1111 | if (a->buddy_list_len[i] == 0 && | 1263 | if (a->buddy_list_len[i] == 0 && |
1112 | a->buddy_list_alloced[i] == 0 && | 1264 | a->buddy_list_alloced[i] == 0 && |
1113 | a->buddy_list_split[i] == 0) | 1265 | a->buddy_list_split[i] == 0) |
1114 | continue; | 1266 | continue; |
1115 | 1267 | ||
1116 | __balloc_pstat(s, " %3d %-7llu %-9llu %llu\n", i, | 1268 | __alloc_pstat(s, __a, " %3d %-7llu %-9llu %llu\n", i, |
1117 | a->buddy_list_len[i], | 1269 | a->buddy_list_len[i], |
1118 | a->buddy_list_alloced[i], | 1270 | a->buddy_list_alloced[i], |
1119 | a->buddy_list_split[i]); | 1271 | a->buddy_list_split[i]); |
1120 | } | 1272 | } |
1121 | 1273 | ||
1122 | __balloc_pstat(s, "\n"); | 1274 | __alloc_pstat(s, __a, "\n"); |
1123 | 1275 | ||
1124 | for (node = rb_first(&a->fixed_allocs), i = 1; | 1276 | for (node = rb_first(&a->fixed_allocs), i = 1; |
1125 | node != NULL; | 1277 | node != NULL; |
@@ -1127,27 +1279,33 @@ static void balloc_print_stats(struct gk20a_allocator *a, struct seq_file *s, | |||
1127 | falloc = container_of(node, | 1279 | falloc = container_of(node, |
1128 | struct gk20a_fixed_alloc, alloced_entry); | 1280 | struct gk20a_fixed_alloc, alloced_entry); |
1129 | 1281 | ||
1130 | __balloc_pstat(s, "Fixed alloc (%d): [0x%llx -> 0x%llx]\n", | 1282 | __alloc_pstat(s, __a, "Fixed alloc (%d): [0x%llx -> 0x%llx]\n", |
1131 | i, falloc->start, falloc->end); | 1283 | i, falloc->start, falloc->end); |
1132 | } | 1284 | } |
1133 | 1285 | ||
1134 | __balloc_pstat(s, "\n"); | 1286 | __alloc_pstat(s, __a, "\n"); |
1135 | __balloc_pstat(s, "Bytes allocated: %llu\n", a->bytes_alloced); | 1287 | __alloc_pstat(s, __a, "Bytes allocated: %llu\n", |
1136 | __balloc_pstat(s, "Bytes allocated (real): %llu\n", | 1288 | a->bytes_alloced); |
1137 | a->bytes_alloced_real); | 1289 | __alloc_pstat(s, __a, "Bytes allocated (real): %llu\n", |
1138 | __balloc_pstat(s, "Bytes freed: %llu\n", a->bytes_freed); | 1290 | a->bytes_alloced_real); |
1291 | __alloc_pstat(s, __a, "Bytes freed: %llu\n", | ||
1292 | a->bytes_freed); | ||
1139 | 1293 | ||
1140 | if (lock) | 1294 | if (lock) |
1141 | balloc_unlock(a); | 1295 | alloc_unlock(__a); |
1296 | } | ||
1142 | 1297 | ||
1143 | #undef __balloc_pstats | 1298 | void gk20a_alloc_print_stats(struct gk20a_allocator *__a, |
1299 | struct seq_file *s, int lock) | ||
1300 | { | ||
1301 | __a->ops->print_stats(__a, s, lock); | ||
1144 | } | 1302 | } |
1145 | 1303 | ||
1146 | static int __alloc_show(struct seq_file *s, void *unused) | 1304 | static int __alloc_show(struct seq_file *s, void *unused) |
1147 | { | 1305 | { |
1148 | struct gk20a_allocator *a = s->private; | 1306 | struct gk20a_allocator *a = s->private; |
1149 | 1307 | ||
1150 | balloc_print_stats(a, s, 1); | 1308 | gk20a_alloc_print_stats(a, s, 1); |
1151 | 1309 | ||
1152 | return 0; | 1310 | return 0; |
1153 | } | 1311 | } |
@@ -1164,13 +1322,13 @@ static const struct file_operations __alloc_fops = { | |||
1164 | .release = single_release, | 1322 | .release = single_release, |
1165 | }; | 1323 | }; |
1166 | 1324 | ||
1167 | static void balloc_init_alloc_debug(struct gk20a_allocator *a) | 1325 | static void gk20a_init_alloc_debug(struct gk20a_allocator *a) |
1168 | { | 1326 | { |
1169 | if (!balloc_debugfs_root) | 1327 | if (!gk20a_alloc_debugfs_root) |
1170 | return; | 1328 | return; |
1171 | 1329 | ||
1172 | a->debugfs_entry = debugfs_create_file(a->name, S_IRUGO, | 1330 | a->debugfs_entry = debugfs_create_file(a->name, S_IRUGO, |
1173 | balloc_debugfs_root, | 1331 | gk20a_alloc_debugfs_root, |
1174 | a, &__alloc_fops); | 1332 | a, &__alloc_fops); |
1175 | } | 1333 | } |
1176 | 1334 | ||
@@ -1180,11 +1338,11 @@ void gk20a_alloc_debugfs_init(struct platform_device *pdev) | |||
1180 | struct gk20a_platform *platform = platform_get_drvdata(pdev); | 1338 | struct gk20a_platform *platform = platform_get_drvdata(pdev); |
1181 | struct dentry *gpu_root = platform->debugfs; | 1339 | struct dentry *gpu_root = platform->debugfs; |
1182 | 1340 | ||
1183 | balloc_debugfs_root = debugfs_create_dir("allocators", gpu_root); | 1341 | gk20a_alloc_debugfs_root = debugfs_create_dir("allocators", gpu_root); |
1184 | if (IS_ERR_OR_NULL(balloc_debugfs_root)) | 1342 | if (IS_ERR_OR_NULL(gk20a_alloc_debugfs_root)) |
1185 | return; | 1343 | return; |
1186 | 1344 | ||
1187 | debugfs_create_u32("tracing", 0664, balloc_debugfs_root, | 1345 | debugfs_create_u32("tracing", 0664, gk20a_alloc_debugfs_root, |
1188 | &balloc_tracing_on); | 1346 | &gk20a_alloc_tracing_on); |
1189 | } | 1347 | } |
1190 | #endif | 1348 | #endif |