aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sis/sis_mm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/sis/sis_mm.c')
-rw-r--r--drivers/gpu/drm/sis/sis_mm.c137
1 files changed, 65 insertions, 72 deletions
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
index 21d36df02a88..46cb2bce6cc5 100644
--- a/drivers/gpu/drm/sis/sis_mm.c
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -41,40 +41,18 @@
41#define AGP_TYPE 1 41#define AGP_TYPE 1
42 42
43 43
44struct sis_memblock {
45 struct drm_mm_node mm_node;
46 struct sis_memreq req;
47 struct list_head owner_list;
48};
49
44#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) 50#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
45/* fb management via fb device */ 51/* fb management via fb device */
46 52
47#define SIS_MM_ALIGN_SHIFT 0 53#define SIS_MM_ALIGN_SHIFT 0
48#define SIS_MM_ALIGN_MASK 0 54#define SIS_MM_ALIGN_MASK 0
49 55
50static void *sis_sman_mm_allocate(void *private, unsigned long size,
51 unsigned alignment)
52{
53 struct sis_memreq req;
54
55 req.size = size;
56 sis_malloc(&req);
57 if (req.size == 0)
58 return NULL;
59 else
60 return (void *)(unsigned long)~req.offset;
61}
62
63static void sis_sman_mm_free(void *private, void *ref)
64{
65 sis_free(~((unsigned long)ref));
66}
67
68static void sis_sman_mm_destroy(void *private)
69{
70 ;
71}
72
73static unsigned long sis_sman_mm_offset(void *private, void *ref)
74{
75 return ~((unsigned long)ref);
76}
77
78#else /* CONFIG_FB_SIS[_MODULE] */ 56#else /* CONFIG_FB_SIS[_MODULE] */
79 57
80#define SIS_MM_ALIGN_SHIFT 4 58#define SIS_MM_ALIGN_SHIFT 4
@@ -86,30 +64,11 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file
86{ 64{
87 drm_sis_private_t *dev_priv = dev->dev_private; 65 drm_sis_private_t *dev_priv = dev->dev_private;
88 drm_sis_fb_t *fb = data; 66 drm_sis_fb_t *fb = data;
89 int ret;
90 67
91 mutex_lock(&dev->struct_mutex); 68 mutex_lock(&dev->struct_mutex);
92#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) 69 /* Unconditionally init the drm_mm, even though we don't use it when the
93 { 70 * fb sis driver is available - make cleanup easier. */
94 struct drm_sman_mm sman_mm; 71 drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> SIS_MM_ALIGN_SHIFT);
95 sman_mm.private = (void *)0xFFFFFFFF;
96 sman_mm.allocate = sis_sman_mm_allocate;
97 sman_mm.free = sis_sman_mm_free;
98 sman_mm.destroy = sis_sman_mm_destroy;
99 sman_mm.offset = sis_sman_mm_offset;
100 ret =
101 drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
102 }
103#else
104 ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
105 fb->size >> SIS_MM_ALIGN_SHIFT);
106#endif
107
108 if (ret) {
109 DRM_ERROR("VRAM memory manager initialisation error\n");
110 mutex_unlock(&dev->struct_mutex);
111 return ret;
112 }
113 72
114 dev_priv->vram_initialized = 1; 73 dev_priv->vram_initialized = 1;
115 dev_priv->vram_offset = fb->offset; 74 dev_priv->vram_offset = fb->offset;
@@ -126,8 +85,9 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
126 drm_sis_private_t *dev_priv = dev->dev_private; 85 drm_sis_private_t *dev_priv = dev->dev_private;
127 drm_sis_mem_t *mem = data; 86 drm_sis_mem_t *mem = data;
128 int retval = 0, user_key; 87 int retval = 0, user_key;
129 struct drm_memblock_item *item; 88 struct sis_memblock *item;
130 struct sis_file_private *file_priv = file->driver_priv; 89 struct sis_file_private *file_priv = file->driver_priv;
90 unsigned long offset;
131 91
132 mutex_lock(&dev->struct_mutex); 92 mutex_lock(&dev->struct_mutex);
133 93
@@ -139,13 +99,35 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
139 return -EINVAL; 99 return -EINVAL;
140 } 100 }
141 101
142 mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; 102 item = kzalloc(sizeof(*item), GFP_KERNEL);
143 item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0, 0);
144 if (!item) { 103 if (!item) {
145 retval = -ENOMEM; 104 retval = -ENOMEM;
146 goto fail_alloc; 105 goto fail_alloc;
147 } 106 }
148 107
108 mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
109 if (pool == AGP_TYPE) {
110 retval = drm_mm_insert_node(&dev_priv->agp_mm,
111 &item->mm_node,
112 mem->size, 0);
113 offset = item->mm_node.start;
114 } else {
115#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
116 item->req.size = mem->size;
117 sis_malloc(&item->req);
118 if (item->req.size == 0)
119 retval = -ENOMEM;
120 offset = item->req.offset;
121#else
122 retval = drm_mm_insert_node(&dev_priv->vram_mm,
123 &item->mm_node,
124 mem->size, 0);
125 offset = item->mm_node.start;
126#endif
127 }
128 if (retval)
129 goto fail_alloc;
130
149again: 131again:
150 if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) { 132 if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) {
151 retval = -ENOMEM; 133 retval = -ENOMEM;
@@ -163,16 +145,16 @@ again:
163 145
164 mem->offset = ((pool == 0) ? 146 mem->offset = ((pool == 0) ?
165 dev_priv->vram_offset : dev_priv->agp_offset) + 147 dev_priv->vram_offset : dev_priv->agp_offset) +
166 (item->mm-> 148 (offset << SIS_MM_ALIGN_SHIFT);
167 offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
168 mem->free = user_key; 149 mem->free = user_key;
169 mem->size = mem->size << SIS_MM_ALIGN_SHIFT; 150 mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
170 151
171 return 0; 152 return 0;
172 153
173fail_idr: 154fail_idr:
174 drm_sman_free(item); 155 drm_mm_remove_node(&item->mm_node);
175fail_alloc: 156fail_alloc:
157 kfree(item);
176 mutex_unlock(&dev->struct_mutex); 158 mutex_unlock(&dev->struct_mutex);
177 159
178 mem->offset = 0; 160 mem->offset = 0;
@@ -189,7 +171,7 @@ static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *fil
189{ 171{
190 drm_sis_private_t *dev_priv = dev->dev_private; 172 drm_sis_private_t *dev_priv = dev->dev_private;
191 drm_sis_mem_t *mem = data; 173 drm_sis_mem_t *mem = data;
192 struct drm_memblock_item *obj; 174 struct sis_memblock *obj;
193 int ret; 175 int ret;
194 176
195 mutex_lock(&dev->struct_mutex); 177 mutex_lock(&dev->struct_mutex);
@@ -200,7 +182,14 @@ static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *fil
200 } 182 }
201 183
202 idr_remove(&dev_priv->object_idr, mem->free); 184 idr_remove(&dev_priv->object_idr, mem->free);
203 drm_sman_free(obj); 185 list_del(&obj->owner_list);
186 if (drm_mm_node_allocated(&obj->mm_node))
187 drm_mm_remove_node(&obj->mm_node);
188#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
189 else
190 sis_free(obj->req.offset);
191#endif
192 kfree(obj);
204 mutex_unlock(&dev->struct_mutex); 193 mutex_unlock(&dev->struct_mutex);
205 DRM_DEBUG("free = 0x%lx\n", mem->free); 194 DRM_DEBUG("free = 0x%lx\n", mem->free);
206 195
@@ -218,18 +207,10 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
218{ 207{
219 drm_sis_private_t *dev_priv = dev->dev_private; 208 drm_sis_private_t *dev_priv = dev->dev_private;
220 drm_sis_agp_t *agp = data; 209 drm_sis_agp_t *agp = data;
221 int ret;
222 dev_priv = dev->dev_private; 210 dev_priv = dev->dev_private;
223 211
224 mutex_lock(&dev->struct_mutex); 212 mutex_lock(&dev->struct_mutex);
225 ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0, 213 drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> SIS_MM_ALIGN_SHIFT);
226 agp->size >> SIS_MM_ALIGN_SHIFT);
227
228 if (ret) {
229 DRM_ERROR("AGP memory manager initialisation error\n");
230 mutex_unlock(&dev->struct_mutex);
231 return ret;
232 }
233 214
234 dev_priv->agp_initialized = 1; 215 dev_priv->agp_initialized = 1;
235 dev_priv->agp_offset = agp->offset; 216 dev_priv->agp_offset = agp->offset;
@@ -323,9 +304,14 @@ void sis_lastclose(struct drm_device *dev)
323 return; 304 return;
324 305
325 mutex_lock(&dev->struct_mutex); 306 mutex_lock(&dev->struct_mutex);
326 drm_sman_cleanup(&dev_priv->sman); 307 if (dev_priv->vram_initialized) {
327 dev_priv->vram_initialized = 0; 308 drm_mm_takedown(&dev_priv->vram_mm);
328 dev_priv->agp_initialized = 0; 309 dev_priv->vram_initialized = 0;
310 }
311 if (dev_priv->agp_initialized) {
312 drm_mm_takedown(&dev_priv->agp_mm);
313 dev_priv->agp_initialized = 0;
314 }
329 dev_priv->mmio = NULL; 315 dev_priv->mmio = NULL;
330 mutex_unlock(&dev->struct_mutex); 316 mutex_unlock(&dev->struct_mutex);
331} 317}
@@ -334,7 +320,7 @@ void sis_reclaim_buffers_locked(struct drm_device *dev,
334 struct drm_file *file) 320 struct drm_file *file)
335{ 321{
336 struct sis_file_private *file_priv = file->driver_priv; 322 struct sis_file_private *file_priv = file->driver_priv;
337 struct drm_memblock_item *entry, *next; 323 struct sis_memblock *entry, *next;
338 324
339 mutex_lock(&dev->struct_mutex); 325 mutex_lock(&dev->struct_mutex);
340 if (list_empty(&file_priv->obj_list)) { 326 if (list_empty(&file_priv->obj_list)) {
@@ -348,7 +334,14 @@ void sis_reclaim_buffers_locked(struct drm_device *dev,
348 334
349 list_for_each_entry_safe(entry, next, &file_priv->obj_list, 335 list_for_each_entry_safe(entry, next, &file_priv->obj_list,
350 owner_list) { 336 owner_list) {
351 drm_sman_free(entry); 337 list_del(&entry->owner_list);
338 if (drm_mm_node_allocated(&entry->mm_node))
339 drm_mm_remove_node(&entry->mm_node);
340#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
341 else
342 sis_free(entry->req.offset);
343#endif
344 kfree(entry);
352 } 345 }
353 mutex_unlock(&dev->struct_mutex); 346 mutex_unlock(&dev->struct_mutex);
354 return; 347 return;