aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_mem.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-06-01 01:32:24 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-07-12 20:12:51 -0400
commitb833ac26f1f1c8e8d9149d83dbdd91432f2807d5 (patch)
tree2899ec81e2c41c6942d75d9039748c0a882ce321 /drivers/gpu/drm/nouveau/nouveau_mem.c
parentd17f395cdcec39033a481f96d75e8b3d3c41d43a (diff)
drm/nouveau: use drm_mm in preference to custom code doing the same thing
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_mem.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c176
1 files changed, 2 insertions, 174 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index fb6b791506b..4274281f45c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -35,162 +35,6 @@
35#include "drm_sarea.h" 35#include "drm_sarea.h"
36#include "nouveau_drv.h" 36#include "nouveau_drv.h"
37 37
38static struct mem_block *
39split_block(struct mem_block *p, uint64_t start, uint64_t size,
40 struct drm_file *file_priv)
41{
42 /* Maybe cut off the start of an existing block */
43 if (start > p->start) {
44 struct mem_block *newblock =
45 kmalloc(sizeof(*newblock), GFP_KERNEL);
46 if (!newblock)
47 goto out;
48 newblock->start = start;
49 newblock->size = p->size - (start - p->start);
50 newblock->file_priv = NULL;
51 newblock->next = p->next;
52 newblock->prev = p;
53 p->next->prev = newblock;
54 p->next = newblock;
55 p->size -= newblock->size;
56 p = newblock;
57 }
58
59 /* Maybe cut off the end of an existing block */
60 if (size < p->size) {
61 struct mem_block *newblock =
62 kmalloc(sizeof(*newblock), GFP_KERNEL);
63 if (!newblock)
64 goto out;
65 newblock->start = start + size;
66 newblock->size = p->size - size;
67 newblock->file_priv = NULL;
68 newblock->next = p->next;
69 newblock->prev = p;
70 p->next->prev = newblock;
71 p->next = newblock;
72 p->size = size;
73 }
74
75out:
76 /* Our block is in the middle */
77 p->file_priv = file_priv;
78 return p;
79}
80
81struct mem_block *
82nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size,
83 int align2, struct drm_file *file_priv, int tail)
84{
85 struct mem_block *p;
86 uint64_t mask = (1 << align2) - 1;
87
88 if (!heap)
89 return NULL;
90
91 if (tail) {
92 list_for_each_prev(p, heap) {
93 uint64_t start = ((p->start + p->size) - size) & ~mask;
94
95 if (p->file_priv == NULL && start >= p->start &&
96 start + size <= p->start + p->size)
97 return split_block(p, start, size, file_priv);
98 }
99 } else {
100 list_for_each(p, heap) {
101 uint64_t start = (p->start + mask) & ~mask;
102
103 if (p->file_priv == NULL &&
104 start + size <= p->start + p->size)
105 return split_block(p, start, size, file_priv);
106 }
107 }
108
109 return NULL;
110}
111
112void nouveau_mem_free_block(struct mem_block *p)
113{
114 p->file_priv = NULL;
115
116 /* Assumes a single contiguous range. Needs a special file_priv in
117 * 'heap' to stop it being subsumed.
118 */
119 if (p->next->file_priv == NULL) {
120 struct mem_block *q = p->next;
121 p->size += q->size;
122 p->next = q->next;
123 p->next->prev = p;
124 kfree(q);
125 }
126
127 if (p->prev->file_priv == NULL) {
128 struct mem_block *q = p->prev;
129 q->size += p->size;
130 q->next = p->next;
131 q->next->prev = q;
132 kfree(p);
133 }
134}
135
136/* Initialize. How to check for an uninitialized heap?
137 */
138int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start,
139 uint64_t size)
140{
141 struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
142
143 if (!blocks)
144 return -ENOMEM;
145
146 *heap = kmalloc(sizeof(**heap), GFP_KERNEL);
147 if (!*heap) {
148 kfree(blocks);
149 return -ENOMEM;
150 }
151
152 blocks->start = start;
153 blocks->size = size;
154 blocks->file_priv = NULL;
155 blocks->next = blocks->prev = *heap;
156
157 memset(*heap, 0, sizeof(**heap));
158 (*heap)->file_priv = (struct drm_file *) -1;
159 (*heap)->next = (*heap)->prev = blocks;
160 return 0;
161}
162
163/*
164 * Free all blocks associated with the releasing file_priv
165 */
166void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
167{
168 struct mem_block *p;
169
170 if (!heap || !heap->next)
171 return;
172
173 list_for_each(p, heap) {
174 if (p->file_priv == file_priv)
175 p->file_priv = NULL;
176 }
177
178 /* Assumes a single contiguous range. Needs a special file_priv in
179 * 'heap' to stop it being subsumed.
180 */
181 list_for_each(p, heap) {
182 while ((p->file_priv == NULL) &&
183 (p->next->file_priv == NULL) &&
184 (p->next != heap)) {
185 struct mem_block *q = p->next;
186 p->size += q->size;
187 p->next = q->next;
188 p->next->prev = p;
189 kfree(q);
190 }
191 }
192}
193
194/* 38/*
195 * NV10-NV40 tiling helpers 39 * NV10-NV40 tiling helpers
196 */ 40 */
@@ -421,24 +265,8 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
421/* 265/*
422 * Cleanup everything 266 * Cleanup everything
423 */ 267 */
424void nouveau_mem_takedown(struct mem_block **heap) 268void
425{ 269nouveau_mem_close(struct drm_device *dev)
426 struct mem_block *p;
427
428 if (!*heap)
429 return;
430
431 for (p = (*heap)->next; p != *heap;) {
432 struct mem_block *q = p;
433 p = p->next;
434 kfree(q);
435 }
436
437 kfree(*heap);
438 *heap = NULL;
439}
440
441void nouveau_mem_close(struct drm_device *dev)
442{ 270{
443 struct drm_nouveau_private *dev_priv = dev->dev_private; 271 struct drm_nouveau_private *dev_priv = dev->dev_private;
444 272