diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-06-01 01:32:24 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-07-12 20:12:51 -0400 |
commit | b833ac26f1f1c8e8d9149d83dbdd91432f2807d5 (patch) | |
tree | 2899ec81e2c41c6942d75d9039748c0a882ce321 /drivers/gpu/drm/nouveau/nouveau_mem.c | |
parent | d17f395cdcec39033a481f96d75e8b3d3c41d43a (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.c | 176 |
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 | ||
38 | static struct mem_block * | ||
39 | split_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 | |||
75 | out: | ||
76 | /* Our block is in the middle */ | ||
77 | p->file_priv = file_priv; | ||
78 | return p; | ||
79 | } | ||
80 | |||
81 | struct mem_block * | ||
82 | nouveau_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 | |||
112 | void 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 | */ | ||
138 | int 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 | */ | ||
166 | void 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 | */ |
424 | void nouveau_mem_takedown(struct mem_block **heap) | 268 | void |
425 | { | 269 | nouveau_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 | |||
441 | void 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 | ||