summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a_allocator.h')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_allocator.h177
1 files changed, 177 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
new file mode 100644
index 00000000..dba397e2
--- /dev/null
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_allocator.h
@@ -0,0 +1,177 @@
1/*
2 * gk20a allocator
3 *
4 * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef __NVHOST_ALLOCATOR_H__
20#define __NVHOST_ALLOCATOR_H__
21
22#include <linux/rbtree.h>
23#include <linux/rwsem.h>
24#include <linux/slab.h>
25
26/* #define ALLOCATOR_DEBUG */
27
28struct allocator_block;
29
30/* main struct */
31struct gk20a_allocator {
32
33 char name[32]; /* name for allocator */
34 struct rb_root rb_root; /* rb tree root for blocks */
35
36 u32 base; /* min value of this linear space */
37 u32 limit; /* max value = limit - 1 */
38 u32 align; /* alignment size, power of 2 */
39
40 struct gk20a_alloc_block *block_first; /* first block in list */
41 struct gk20a_alloc_block *block_recent; /* last visited block */
42
43 u32 first_free_addr; /* first free addr, non-contigous
44 allocation preferred start,
45 in order to pick up small holes */
46 u32 last_free_addr; /* last free addr, contiguous
47 allocation preferred start */
48 u32 cached_hole_size; /* max free hole size up to
49 last_free_addr */
50 u32 block_count; /* number of blocks */
51
52 struct rw_semaphore rw_sema; /* lock */
53 struct kmem_cache *block_cache; /* slab cache */
54
55 /* if enabled, constrain to [base, limit) */
56 struct {
57 bool enable;
58 u32 base;
59 u32 limit;
60 } constraint;
61
62 int (*alloc)(struct gk20a_allocator *allocator,
63 u32 *addr, u32 len);
64 int (*alloc_nc)(struct gk20a_allocator *allocator,
65 u32 *addr, u32 len,
66 struct gk20a_alloc_block **pblock);
67 int (*free)(struct gk20a_allocator *allocator,
68 u32 addr, u32 len);
69 void (*free_nc)(struct gk20a_allocator *allocator,
70 struct gk20a_alloc_block *block);
71
72 int (*constrain)(struct gk20a_allocator *a,
73 bool enable,
74 u32 base, u32 limit);
75};
76
77/* a block of linear space range [start, end) */
78struct gk20a_alloc_block {
79 struct gk20a_allocator *allocator; /* parent allocator */
80 struct rb_node rb; /* rb tree node */
81
82 u32 start; /* linear space range
83 [start, end) */
84 u32 end;
85
86 void *priv; /* backing structure for this
87 linear space block
88 page table, comp tag, etc */
89
90 struct gk20a_alloc_block *prev; /* prev block with lower address */
91 struct gk20a_alloc_block *next; /* next block with higher address */
92
93 bool nc_block;
94 struct gk20a_alloc_block *nc_prev; /* prev block for
95 non-contiguous allocation */
96 struct gk20a_alloc_block *nc_next; /* next block for
97 non-contiguous allocation */
98};
99
100int gk20a_allocator_init(struct gk20a_allocator *allocator,
101 const char *name, u32 base, u32 size, u32 align);
102void gk20a_allocator_destroy(struct gk20a_allocator *allocator);
103
104int gk20a_allocator_block_alloc(struct gk20a_allocator *allocator,
105 u32 *addr, u32 len);
106int gk20a_allocator_block_alloc_nc(struct gk20a_allocator *allocator,
107 u32 *addr, u32 len,
108 struct gk20a_alloc_block **pblock);
109
110int gk20a_allocator_block_free(struct gk20a_allocator *allocator,
111 u32 addr, u32 len);
112void gk20a_allocator_block_free_nc(struct gk20a_allocator *allocator,
113 struct gk20a_alloc_block *block);
114
115#if defined(ALLOCATOR_DEBUG)
116
117#define allocator_dbg(alloctor, format, arg...) \
118do { \
119 if (1) \
120 pr_debug("gk20a_allocator (%s) %s: " format "\n",\
121 alloctor->name, __func__, ##arg);\
122} while (0)
123
124static inline void
125gk20a_allocator_dump(struct gk20a_allocator *allocator) {
126 struct gk20a_alloc_block *block;
127 u32 count = 0;
128
129 down_read(&allocator->rw_sema);
130 for (block = allocator->block_first; block; block = block->next) {
131 allocator_dbg(allocator, "block %d - %d:%d, nc %d",
132 count++, block->start, block->end, block->nc_block);
133
134 if (block->prev)
135 BUG_ON(block->prev->end > block->start);
136 if (block->next)
137 BUG_ON(block->next->start < block->end);
138 }
139 allocator_dbg(allocator, "tracked count %d, actual count %d",
140 allocator->block_count, count);
141 allocator_dbg(allocator, "first block %d:%d",
142 allocator->block_first ? allocator->block_first->start : -1,
143 allocator->block_first ? allocator->block_first->end : -1);
144 allocator_dbg(allocator, "first free addr %d",
145 allocator->first_free_addr);
146 allocator_dbg(allocator, "last free addr %d",
147 allocator->last_free_addr);
148 allocator_dbg(allocator, "cached hole size %d",
149 allocator->cached_hole_size);
150 up_read(&allocator->rw_sema);
151
152 BUG_ON(count != allocator->block_count);
153}
154
155static inline void
156gk20a_allocator_dump_nc_list(
157 struct gk20a_allocator *allocator,
158 struct gk20a_alloc_block *block)
159{
160 down_read(&allocator->rw_sema);
161 while (block) {
162 pr_debug("non-contiguous block %d:%d\n",
163 block->start, block->end);
164 block = block->nc_next;
165 }
166 up_read(&allocator->rw_sema);
167}
168
169void gk20a_allocator_test(void);
170
171#else /* ALLOCATOR_DEBUG */
172
173#define allocator_dbg(format, arg...)
174
175#endif /* ALLOCATOR_DEBUG */
176
177#endif /*__NVHOST_ALLOCATOR_H__ */