diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/gpu/drm/via/via_mm.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/gpu/drm/via/via_mm.c')
-rw-r--r-- | drivers/gpu/drm/via/via_mm.c | 152 |
1 files changed, 50 insertions, 102 deletions
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index 0d55432e02a..6cc2dadae3e 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c | |||
@@ -25,25 +25,29 @@ | |||
25 | * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> | 25 | * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <drm/drmP.h> | 28 | #include "drmP.h" |
29 | #include <drm/via_drm.h> | 29 | #include "via_drm.h" |
30 | #include "via_drv.h" | 30 | #include "via_drv.h" |
31 | #include "drm_sman.h" | ||
31 | 32 | ||
32 | #define VIA_MM_ALIGN_SHIFT 4 | 33 | #define VIA_MM_ALIGN_SHIFT 4 |
33 | #define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1) | 34 | #define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1) |
34 | 35 | ||
35 | struct via_memblock { | ||
36 | struct drm_mm_node mm_node; | ||
37 | struct list_head owner_list; | ||
38 | }; | ||
39 | |||
40 | int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) | 36 | int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) |
41 | { | 37 | { |
42 | drm_via_agp_t *agp = data; | 38 | drm_via_agp_t *agp = data; |
43 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 39 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
40 | int ret; | ||
44 | 41 | ||
45 | mutex_lock(&dev->struct_mutex); | 42 | mutex_lock(&dev->struct_mutex); |
46 | drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT); | 43 | ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0, |
44 | agp->size >> VIA_MM_ALIGN_SHIFT); | ||
45 | |||
46 | if (ret) { | ||
47 | DRM_ERROR("AGP memory manager initialisation error\n"); | ||
48 | mutex_unlock(&dev->struct_mutex); | ||
49 | return ret; | ||
50 | } | ||
47 | 51 | ||
48 | dev_priv->agp_initialized = 1; | 52 | dev_priv->agp_initialized = 1; |
49 | dev_priv->agp_offset = agp->offset; | 53 | dev_priv->agp_offset = agp->offset; |
@@ -57,9 +61,17 @@ int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
57 | { | 61 | { |
58 | drm_via_fb_t *fb = data; | 62 | drm_via_fb_t *fb = data; |
59 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 63 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
64 | int ret; | ||
60 | 65 | ||
61 | mutex_lock(&dev->struct_mutex); | 66 | mutex_lock(&dev->struct_mutex); |
62 | drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT); | 67 | ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0, |
68 | fb->size >> VIA_MM_ALIGN_SHIFT); | ||
69 | |||
70 | if (ret) { | ||
71 | DRM_ERROR("VRAM memory manager initialisation error\n"); | ||
72 | mutex_unlock(&dev->struct_mutex); | ||
73 | return ret; | ||
74 | } | ||
63 | 75 | ||
64 | dev_priv->vram_initialized = 1; | 76 | dev_priv->vram_initialized = 1; |
65 | dev_priv->vram_offset = fb->offset; | 77 | dev_priv->vram_offset = fb->offset; |
@@ -96,25 +108,19 @@ void via_lastclose(struct drm_device *dev) | |||
96 | return; | 108 | return; |
97 | 109 | ||
98 | mutex_lock(&dev->struct_mutex); | 110 | mutex_lock(&dev->struct_mutex); |
99 | if (dev_priv->vram_initialized) { | 111 | drm_sman_cleanup(&dev_priv->sman); |
100 | drm_mm_takedown(&dev_priv->vram_mm); | 112 | dev_priv->vram_initialized = 0; |
101 | dev_priv->vram_initialized = 0; | 113 | dev_priv->agp_initialized = 0; |
102 | } | ||
103 | if (dev_priv->agp_initialized) { | ||
104 | drm_mm_takedown(&dev_priv->agp_mm); | ||
105 | dev_priv->agp_initialized = 0; | ||
106 | } | ||
107 | mutex_unlock(&dev->struct_mutex); | 114 | mutex_unlock(&dev->struct_mutex); |
108 | } | 115 | } |
109 | 116 | ||
110 | int via_mem_alloc(struct drm_device *dev, void *data, | 117 | int via_mem_alloc(struct drm_device *dev, void *data, |
111 | struct drm_file *file) | 118 | struct drm_file *file_priv) |
112 | { | 119 | { |
113 | drm_via_mem_t *mem = data; | 120 | drm_via_mem_t *mem = data; |
114 | int retval = 0, user_key; | 121 | int retval = 0; |
115 | struct via_memblock *item; | 122 | struct drm_memblock_item *item; |
116 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 123 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
117 | struct via_file_private *file_priv = file->driver_priv; | ||
118 | unsigned long tmpSize; | 124 | unsigned long tmpSize; |
119 | 125 | ||
120 | if (mem->type > VIA_MEM_AGP) { | 126 | if (mem->type > VIA_MEM_AGP) { |
@@ -130,57 +136,24 @@ int via_mem_alloc(struct drm_device *dev, void *data, | |||
130 | return -EINVAL; | 136 | return -EINVAL; |
131 | } | 137 | } |
132 | 138 | ||
133 | item = kzalloc(sizeof(*item), GFP_KERNEL); | ||
134 | if (!item) { | ||
135 | retval = -ENOMEM; | ||
136 | goto fail_alloc; | ||
137 | } | ||
138 | |||
139 | tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; | 139 | tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; |
140 | if (mem->type == VIA_MEM_AGP) | 140 | item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, |
141 | retval = drm_mm_insert_node(&dev_priv->agp_mm, | 141 | (unsigned long)file_priv); |
142 | &item->mm_node, | 142 | mutex_unlock(&dev->struct_mutex); |
143 | tmpSize, 0); | 143 | if (item) { |
144 | else | 144 | mem->offset = ((mem->type == VIA_MEM_VIDEO) ? |
145 | retval = drm_mm_insert_node(&dev_priv->vram_mm, | 145 | dev_priv->vram_offset : dev_priv->agp_offset) + |
146 | &item->mm_node, | 146 | (item->mm-> |
147 | tmpSize, 0); | 147 | offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); |
148 | if (retval) | 148 | mem->index = item->user_hash.key; |
149 | goto fail_alloc; | 149 | } else { |
150 | 150 | mem->offset = 0; | |
151 | again: | 151 | mem->size = 0; |
152 | if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) { | 152 | mem->index = 0; |
153 | DRM_DEBUG("Video memory allocation failed\n"); | ||
153 | retval = -ENOMEM; | 154 | retval = -ENOMEM; |
154 | goto fail_idr; | ||
155 | } | 155 | } |
156 | 156 | ||
157 | retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key); | ||
158 | if (retval == -EAGAIN) | ||
159 | goto again; | ||
160 | if (retval) | ||
161 | goto fail_idr; | ||
162 | |||
163 | list_add(&item->owner_list, &file_priv->obj_list); | ||
164 | mutex_unlock(&dev->struct_mutex); | ||
165 | |||
166 | mem->offset = ((mem->type == VIA_MEM_VIDEO) ? | ||
167 | dev_priv->vram_offset : dev_priv->agp_offset) + | ||
168 | ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT); | ||
169 | mem->index = user_key; | ||
170 | |||
171 | return 0; | ||
172 | |||
173 | fail_idr: | ||
174 | drm_mm_remove_node(&item->mm_node); | ||
175 | fail_alloc: | ||
176 | kfree(item); | ||
177 | mutex_unlock(&dev->struct_mutex); | ||
178 | |||
179 | mem->offset = 0; | ||
180 | mem->size = 0; | ||
181 | mem->index = 0; | ||
182 | DRM_DEBUG("Video memory allocation failed\n"); | ||
183 | |||
184 | return retval; | 157 | return retval; |
185 | } | 158 | } |
186 | 159 | ||
@@ -188,57 +161,32 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) | |||
188 | { | 161 | { |
189 | drm_via_private_t *dev_priv = dev->dev_private; | 162 | drm_via_private_t *dev_priv = dev->dev_private; |
190 | drm_via_mem_t *mem = data; | 163 | drm_via_mem_t *mem = data; |
191 | struct via_memblock *obj; | 164 | int ret; |
192 | 165 | ||
193 | mutex_lock(&dev->struct_mutex); | 166 | mutex_lock(&dev->struct_mutex); |
194 | obj = idr_find(&dev_priv->object_idr, mem->index); | 167 | ret = drm_sman_free_key(&dev_priv->sman, mem->index); |
195 | if (obj == NULL) { | ||
196 | mutex_unlock(&dev->struct_mutex); | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
200 | idr_remove(&dev_priv->object_idr, mem->index); | ||
201 | list_del(&obj->owner_list); | ||
202 | drm_mm_remove_node(&obj->mm_node); | ||
203 | kfree(obj); | ||
204 | mutex_unlock(&dev->struct_mutex); | 168 | mutex_unlock(&dev->struct_mutex); |
205 | |||
206 | DRM_DEBUG("free = 0x%lx\n", mem->index); | 169 | DRM_DEBUG("free = 0x%lx\n", mem->index); |
207 | 170 | ||
208 | return 0; | 171 | return ret; |
209 | } | 172 | } |
210 | 173 | ||
211 | 174 | ||
212 | void via_reclaim_buffers_locked(struct drm_device *dev, | 175 | void via_reclaim_buffers_locked(struct drm_device *dev, |
213 | struct drm_file *file) | 176 | struct drm_file *file_priv) |
214 | { | 177 | { |
215 | struct via_file_private *file_priv = file->driver_priv; | 178 | drm_via_private_t *dev_priv = dev->dev_private; |
216 | struct via_memblock *entry, *next; | ||
217 | |||
218 | if (!(file->minor->master && file->master->lock.hw_lock)) | ||
219 | return; | ||
220 | |||
221 | drm_idlelock_take(&file->master->lock); | ||
222 | 179 | ||
223 | mutex_lock(&dev->struct_mutex); | 180 | mutex_lock(&dev->struct_mutex); |
224 | if (list_empty(&file_priv->obj_list)) { | 181 | if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) { |
225 | mutex_unlock(&dev->struct_mutex); | 182 | mutex_unlock(&dev->struct_mutex); |
226 | drm_idlelock_release(&file->master->lock); | ||
227 | |||
228 | return; | 183 | return; |
229 | } | 184 | } |
230 | 185 | ||
231 | via_driver_dma_quiescent(dev); | 186 | if (dev->driver->dma_quiescent) |
187 | dev->driver->dma_quiescent(dev); | ||
232 | 188 | ||
233 | list_for_each_entry_safe(entry, next, &file_priv->obj_list, | 189 | drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); |
234 | owner_list) { | ||
235 | list_del(&entry->owner_list); | ||
236 | drm_mm_remove_node(&entry->mm_node); | ||
237 | kfree(entry); | ||
238 | } | ||
239 | mutex_unlock(&dev->struct_mutex); | 190 | mutex_unlock(&dev->struct_mutex); |
240 | |||
241 | drm_idlelock_release(&file->master->lock); | ||
242 | |||
243 | return; | 191 | return; |
244 | } | 192 | } |