aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/sis
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/gpu/drm/sis
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/gpu/drm/sis')
-rw-r--r--drivers/gpu/drm/sis/sis_drv.c75
-rw-r--r--drivers/gpu/drm/sis/sis_drv.h7
-rw-r--r--drivers/gpu/drm/sis/sis_mm.c222
3 files changed, 117 insertions, 187 deletions
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index 841065b998a..46d5be6e97e 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -25,13 +25,11 @@
25 * 25 *
26 */ 26 */
27 27
28#include <linux/module.h> 28#include "drmP.h"
29 29#include "sis_drm.h"
30#include <drm/drmP.h>
31#include <drm/sis_drm.h>
32#include "sis_drv.h" 30#include "sis_drv.h"
33 31
34#include <drm/drm_pciids.h> 32#include "drm_pciids.h"
35 33
36static struct pci_device_id pciidlist[] = { 34static struct pci_device_id pciidlist[] = {
37 sisdrv_PCI_IDS 35 sisdrv_PCI_IDS
@@ -40,80 +38,51 @@ static struct pci_device_id pciidlist[] = {
40static int sis_driver_load(struct drm_device *dev, unsigned long chipset) 38static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
41{ 39{
42 drm_sis_private_t *dev_priv; 40 drm_sis_private_t *dev_priv;
43 41 int ret;
44 pci_set_master(dev->pdev);
45 42
46 dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL); 43 dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL);
47 if (dev_priv == NULL) 44 if (dev_priv == NULL)
48 return -ENOMEM; 45 return -ENOMEM;
49 46
50 idr_init(&dev_priv->object_idr);
51 dev->dev_private = (void *)dev_priv; 47 dev->dev_private = (void *)dev_priv;
52 dev_priv->chipset = chipset; 48 dev_priv->chipset = chipset;
49 ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
50 if (ret)
51 kfree(dev_priv);
53 52
54 return 0; 53 return ret;
55} 54}
56 55
57static int sis_driver_unload(struct drm_device *dev) 56static int sis_driver_unload(struct drm_device *dev)
58{ 57{
59 drm_sis_private_t *dev_priv = dev->dev_private; 58 drm_sis_private_t *dev_priv = dev->dev_private;
60 59
61 idr_remove_all(&dev_priv->object_idr); 60 drm_sman_takedown(&dev_priv->sman);
62 idr_destroy(&dev_priv->object_idr);
63
64 kfree(dev_priv); 61 kfree(dev_priv);
65 62
66 return 0; 63 return 0;
67} 64}
68 65
69static const struct file_operations sis_driver_fops = {
70 .owner = THIS_MODULE,
71 .open = drm_open,
72 .release = drm_release,
73 .unlocked_ioctl = drm_ioctl,
74 .mmap = drm_mmap,
75 .poll = drm_poll,
76 .fasync = drm_fasync,
77#ifdef CONFIG_COMPAT
78 .compat_ioctl = drm_compat_ioctl,
79#endif
80 .llseek = noop_llseek,
81};
82
83static int sis_driver_open(struct drm_device *dev, struct drm_file *file)
84{
85 struct sis_file_private *file_priv;
86
87 DRM_DEBUG_DRIVER("\n");
88 file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
89 if (!file_priv)
90 return -ENOMEM;
91
92 file->driver_priv = file_priv;
93
94 INIT_LIST_HEAD(&file_priv->obj_list);
95
96 return 0;
97}
98
99void sis_driver_postclose(struct drm_device *dev, struct drm_file *file)
100{
101 struct sis_file_private *file_priv = file->driver_priv;
102
103 kfree(file_priv);
104}
105
106static struct drm_driver driver = { 66static struct drm_driver driver = {
107 .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, 67 .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
108 .load = sis_driver_load, 68 .load = sis_driver_load,
109 .unload = sis_driver_unload, 69 .unload = sis_driver_unload,
110 .open = sis_driver_open,
111 .preclose = sis_reclaim_buffers_locked,
112 .postclose = sis_driver_postclose,
113 .dma_quiescent = sis_idle, 70 .dma_quiescent = sis_idle,
71 .reclaim_buffers = NULL,
72 .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked,
114 .lastclose = sis_lastclose, 73 .lastclose = sis_lastclose,
115 .ioctls = sis_ioctls, 74 .ioctls = sis_ioctls,
116 .fops = &sis_driver_fops, 75 .fops = {
76 .owner = THIS_MODULE,
77 .open = drm_open,
78 .release = drm_release,
79 .unlocked_ioctl = drm_ioctl,
80 .mmap = drm_mmap,
81 .poll = drm_poll,
82 .fasync = drm_fasync,
83 .llseek = noop_llseek,
84 },
85
117 .name = DRIVER_NAME, 86 .name = DRIVER_NAME,
118 .desc = DRIVER_DESC, 87 .desc = DRIVER_DESC,
119 .date = DRIVER_DATE, 88 .date = DRIVER_DATE,
diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h
index 13b527bb83b..194303c177a 100644
--- a/drivers/gpu/drm/sis/sis_drv.h
+++ b/drivers/gpu/drm/sis/sis_drv.h
@@ -44,7 +44,7 @@ enum sis_family {
44 SIS_CHIP_315 = 1, 44 SIS_CHIP_315 = 1,
45}; 45};
46 46
47#include <drm/drm_mm.h> 47#include "drm_sman.h"
48 48
49 49
50#define SIS_BASE (dev_priv->mmio) 50#define SIS_BASE (dev_priv->mmio)
@@ -54,15 +54,12 @@ enum sis_family {
54typedef struct drm_sis_private { 54typedef struct drm_sis_private {
55 drm_local_map_t *mmio; 55 drm_local_map_t *mmio;
56 unsigned int idle_fault; 56 unsigned int idle_fault;
57 struct drm_sman sman;
57 unsigned int chipset; 58 unsigned int chipset;
58 int vram_initialized; 59 int vram_initialized;
59 int agp_initialized; 60 int agp_initialized;
60 unsigned long vram_offset; 61 unsigned long vram_offset;
61 unsigned long agp_offset; 62 unsigned long agp_offset;
62 struct drm_mm vram_mm;
63 struct drm_mm agp_mm;
64 /** Mapping of userspace keys to mm objects */
65 struct idr object_idr;
66} drm_sis_private_t; 63} drm_sis_private_t;
67 64
68extern int sis_idle(struct drm_device *dev); 65extern int sis_idle(struct drm_device *dev);
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
index 2b2f78c428a..7fe2b63412c 100644
--- a/drivers/gpu/drm/sis/sis_mm.c
+++ b/drivers/gpu/drm/sis/sis_mm.c
@@ -31,8 +31,8 @@
31 * Thomas Hellström <thomas-at-tungstengraphics-dot-com> 31 * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
32 */ 32 */
33 33
34#include <drm/drmP.h> 34#include "drmP.h"
35#include <drm/sis_drm.h> 35#include "sis_drm.h"
36#include "sis_drv.h" 36#include "sis_drv.h"
37 37
38#include <video/sisfb.h> 38#include <video/sisfb.h>
@@ -41,18 +41,40 @@
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
50#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE) 44#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
51/* fb management via fb device */ 45/* fb management via fb device */
52 46
53#define SIS_MM_ALIGN_SHIFT 0 47#define SIS_MM_ALIGN_SHIFT 0
54#define SIS_MM_ALIGN_MASK 0 48#define SIS_MM_ALIGN_MASK 0
55 49
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
56#else /* CONFIG_FB_SIS[_MODULE] */ 78#else /* CONFIG_FB_SIS[_MODULE] */
57 79
58#define SIS_MM_ALIGN_SHIFT 4 80#define SIS_MM_ALIGN_SHIFT 4
@@ -64,30 +86,47 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file
64{ 86{
65 drm_sis_private_t *dev_priv = dev->dev_private; 87 drm_sis_private_t *dev_priv = dev->dev_private;
66 drm_sis_fb_t *fb = data; 88 drm_sis_fb_t *fb = data;
89 int ret;
67 90
68 mutex_lock(&dev->struct_mutex); 91 mutex_lock(&dev->struct_mutex);
69 /* Unconditionally init the drm_mm, even though we don't use it when the 92#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
70 * fb sis driver is available - make cleanup easier. */ 93 {
71 drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> SIS_MM_ALIGN_SHIFT); 94 struct drm_sman_mm sman_mm;
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 }
72 113
73 dev_priv->vram_initialized = 1; 114 dev_priv->vram_initialized = 1;
74 dev_priv->vram_offset = fb->offset; 115 dev_priv->vram_offset = fb->offset;
75 116
76 mutex_unlock(&dev->struct_mutex); 117 mutex_unlock(&dev->struct_mutex);
77 DRM_DEBUG("offset = %lu, size = %lu\n", fb->offset, fb->size); 118 DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
78 119
79 return 0; 120 return 0;
80} 121}
81 122
82static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file, 123static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv,
83 void *data, int pool) 124 void *data, int pool)
84{ 125{
85 drm_sis_private_t *dev_priv = dev->dev_private; 126 drm_sis_private_t *dev_priv = dev->dev_private;
86 drm_sis_mem_t *mem = data; 127 drm_sis_mem_t *mem = data;
87 int retval = 0, user_key; 128 int retval = 0;
88 struct sis_memblock *item; 129 struct drm_memblock_item *item;
89 struct sis_file_private *file_priv = file->driver_priv;
90 unsigned long offset;
91 130
92 mutex_lock(&dev->struct_mutex); 131 mutex_lock(&dev->struct_mutex);
93 132
@@ -99,69 +138,26 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file,
99 return -EINVAL; 138 return -EINVAL;
100 } 139 }
101 140
102 item = kzalloc(sizeof(*item), GFP_KERNEL);
103 if (!item) {
104 retval = -ENOMEM;
105 goto fail_alloc;
106 }
107
108 mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; 141 mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
109 if (pool == AGP_TYPE) { 142 item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0,
110 retval = drm_mm_insert_node(&dev_priv->agp_mm, 143 (unsigned long)file_priv);
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 144
131again: 145 mutex_unlock(&dev->struct_mutex);
132 if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) { 146 if (item) {
147 mem->offset = ((pool == 0) ?
148 dev_priv->vram_offset : dev_priv->agp_offset) +
149 (item->mm->
150 offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
151 mem->free = item->user_hash.key;
152 mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
153 } else {
154 mem->offset = 0;
155 mem->size = 0;
156 mem->free = 0;
133 retval = -ENOMEM; 157 retval = -ENOMEM;
134 goto fail_idr;
135 } 158 }
136 159
137 retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key); 160 DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size,
138 if (retval == -EAGAIN)
139 goto again;
140 if (retval)
141 goto fail_idr;
142
143 list_add(&item->owner_list, &file_priv->obj_list);
144 mutex_unlock(&dev->struct_mutex);
145
146 mem->offset = ((pool == 0) ?
147 dev_priv->vram_offset : dev_priv->agp_offset) +
148 (offset << SIS_MM_ALIGN_SHIFT);
149 mem->free = user_key;
150 mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
151
152 return 0;
153
154fail_idr:
155 drm_mm_remove_node(&item->mm_node);
156fail_alloc:
157 kfree(item);
158 mutex_unlock(&dev->struct_mutex);
159
160 mem->offset = 0;
161 mem->size = 0;
162 mem->free = 0;
163
164 DRM_DEBUG("alloc %d, size = %ld, offset = %ld\n", pool, mem->size,
165 mem->offset); 161 mem->offset);
166 162
167 return retval; 163 return retval;
@@ -171,28 +167,14 @@ static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *fil
171{ 167{
172 drm_sis_private_t *dev_priv = dev->dev_private; 168 drm_sis_private_t *dev_priv = dev->dev_private;
173 drm_sis_mem_t *mem = data; 169 drm_sis_mem_t *mem = data;
174 struct sis_memblock *obj; 170 int ret;
175 171
176 mutex_lock(&dev->struct_mutex); 172 mutex_lock(&dev->struct_mutex);
177 obj = idr_find(&dev_priv->object_idr, mem->free); 173 ret = drm_sman_free_key(&dev_priv->sman, mem->free);
178 if (obj == NULL) {
179 mutex_unlock(&dev->struct_mutex);
180 return -EINVAL;
181 }
182
183 idr_remove(&dev_priv->object_idr, mem->free);
184 list_del(&obj->owner_list);
185 if (drm_mm_node_allocated(&obj->mm_node))
186 drm_mm_remove_node(&obj->mm_node);
187#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
188 else
189 sis_free(obj->req.offset);
190#endif
191 kfree(obj);
192 mutex_unlock(&dev->struct_mutex); 174 mutex_unlock(&dev->struct_mutex);
193 DRM_DEBUG("free = 0x%lx\n", mem->free); 175 DRM_DEBUG("free = 0x%lx\n", mem->free);
194 176
195 return 0; 177 return ret;
196} 178}
197 179
198static int sis_fb_alloc(struct drm_device *dev, void *data, 180static int sis_fb_alloc(struct drm_device *dev, void *data,
@@ -206,16 +188,24 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
206{ 188{
207 drm_sis_private_t *dev_priv = dev->dev_private; 189 drm_sis_private_t *dev_priv = dev->dev_private;
208 drm_sis_agp_t *agp = data; 190 drm_sis_agp_t *agp = data;
191 int ret;
209 dev_priv = dev->dev_private; 192 dev_priv = dev->dev_private;
210 193
211 mutex_lock(&dev->struct_mutex); 194 mutex_lock(&dev->struct_mutex);
212 drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> SIS_MM_ALIGN_SHIFT); 195 ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
196 agp->size >> SIS_MM_ALIGN_SHIFT);
197
198 if (ret) {
199 DRM_ERROR("AGP memory manager initialisation error\n");
200 mutex_unlock(&dev->struct_mutex);
201 return ret;
202 }
213 203
214 dev_priv->agp_initialized = 1; 204 dev_priv->agp_initialized = 1;
215 dev_priv->agp_offset = agp->offset; 205 dev_priv->agp_offset = agp->offset;
216 mutex_unlock(&dev->struct_mutex); 206 mutex_unlock(&dev->struct_mutex);
217 207
218 DRM_DEBUG("offset = %lu, size = %lu\n", agp->offset, agp->size); 208 DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
219 return 0; 209 return 0;
220} 210}
221 211
@@ -303,55 +293,29 @@ void sis_lastclose(struct drm_device *dev)
303 return; 293 return;
304 294
305 mutex_lock(&dev->struct_mutex); 295 mutex_lock(&dev->struct_mutex);
306 if (dev_priv->vram_initialized) { 296 drm_sman_cleanup(&dev_priv->sman);
307 drm_mm_takedown(&dev_priv->vram_mm); 297 dev_priv->vram_initialized = 0;
308 dev_priv->vram_initialized = 0; 298 dev_priv->agp_initialized = 0;
309 }
310 if (dev_priv->agp_initialized) {
311 drm_mm_takedown(&dev_priv->agp_mm);
312 dev_priv->agp_initialized = 0;
313 }
314 dev_priv->mmio = NULL; 299 dev_priv->mmio = NULL;
315 mutex_unlock(&dev->struct_mutex); 300 mutex_unlock(&dev->struct_mutex);
316} 301}
317 302
318void sis_reclaim_buffers_locked(struct drm_device *dev, 303void sis_reclaim_buffers_locked(struct drm_device *dev,
319 struct drm_file *file) 304 struct drm_file *file_priv)
320{ 305{
321 struct sis_file_private *file_priv = file->driver_priv; 306 drm_sis_private_t *dev_priv = dev->dev_private;
322 struct sis_memblock *entry, *next;
323
324 if (!(file->minor->master && file->master->lock.hw_lock))
325 return;
326
327 drm_idlelock_take(&file->master->lock);
328 307
329 mutex_lock(&dev->struct_mutex); 308 mutex_lock(&dev->struct_mutex);
330 if (list_empty(&file_priv->obj_list)) { 309 if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
331 mutex_unlock(&dev->struct_mutex); 310 mutex_unlock(&dev->struct_mutex);
332 drm_idlelock_release(&file->master->lock);
333
334 return; 311 return;
335 } 312 }
336 313
337 sis_idle(dev); 314 if (dev->driver->dma_quiescent)
315 dev->driver->dma_quiescent(dev);
338 316
339 317 drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
340 list_for_each_entry_safe(entry, next, &file_priv->obj_list,
341 owner_list) {
342 list_del(&entry->owner_list);
343 if (drm_mm_node_allocated(&entry->mm_node))
344 drm_mm_remove_node(&entry->mm_node);
345#if defined(CONFIG_FB_SIS) || defined(CONFIG_FB_SIS_MODULE)
346 else
347 sis_free(entry->req.offset);
348#endif
349 kfree(entry);
350 }
351 mutex_unlock(&dev->struct_mutex); 318 mutex_unlock(&dev->struct_mutex);
352
353 drm_idlelock_release(&file->master->lock);
354
355 return; 319 return;
356} 320}
357 321