aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/drmP.h36
-rw-r--r--drivers/char/drm/drm_bufs.c19
-rw-r--r--drivers/char/drm/drm_memory.c94
-rw-r--r--drivers/char/drm/drm_memory.h20
-rw-r--r--drivers/char/drm/drm_memory_debug.h70
-rw-r--r--drivers/char/drm/drm_mm.c183
-rw-r--r--drivers/char/drm/drm_pciids.h4
-rw-r--r--drivers/char/drm/drm_proc.c4
-rw-r--r--drivers/char/drm/drm_sman.c3
-rw-r--r--drivers/char/drm/drm_vm.c16
-rw-r--r--drivers/char/drm/i810_dma.c34
-rw-r--r--drivers/char/drm/i810_drv.h2
-rw-r--r--drivers/char/drm/i830_dma.c32
-rw-r--r--drivers/char/drm/i830_drv.h2
-rw-r--r--drivers/char/drm/via_dma.c9
-rw-r--r--drivers/char/drm/via_dmablit.c2
-rw-r--r--drivers/char/drm/via_drv.h11
-rw-r--r--drivers/char/drm/via_irq.c16
-rw-r--r--drivers/char/drm/via_map.c3
-rw-r--r--drivers/char/drm/via_verifier.c50
-rw-r--r--drivers/char/drm/via_verifier.h1
21 files changed, 304 insertions, 307 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 6dcdceb81203..85d99e21e188 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -532,11 +532,13 @@ typedef struct drm_mm_node {
532 int free; 532 int free;
533 unsigned long start; 533 unsigned long start;
534 unsigned long size; 534 unsigned long size;
535 struct drm_mm *mm;
535 void *private; 536 void *private;
536} drm_mm_node_t; 537} drm_mm_node_t;
537 538
538typedef struct drm_mm { 539typedef struct drm_mm {
539 drm_mm_node_t root_node; 540 struct list_head fl_entry;
541 struct list_head ml_entry;
540} drm_mm_t; 542} drm_mm_t;
541 543
542/** 544/**
@@ -843,9 +845,6 @@ extern void drm_mem_init(void);
843extern int drm_mem_info(char *buf, char **start, off_t offset, 845extern int drm_mem_info(char *buf, char **start, off_t offset,
844 int request, int *eof, void *data); 846 int request, int *eof, void *data);
845extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); 847extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
846extern void *drm_ioremap(unsigned long offset, unsigned long size,
847 drm_device_t * dev);
848extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev);
849 848
850extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type); 849extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
851extern int drm_free_agp(DRM_AGP_MEM * handle, int pages); 850extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
@@ -1053,33 +1052,18 @@ extern void drm_sysfs_device_remove(struct class_device *class_dev);
1053extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, 1052extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
1054 unsigned long size, 1053 unsigned long size,
1055 unsigned alignment); 1054 unsigned alignment);
1056extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur); 1055void drm_mm_put_block(drm_mm_node_t * cur);
1057extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, 1056extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size,
1058 unsigned alignment, int best_match); 1057 unsigned alignment, int best_match);
1059extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); 1058extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size);
1060extern void drm_mm_takedown(drm_mm_t *mm); 1059extern void drm_mm_takedown(drm_mm_t *mm);
1060extern int drm_mm_clean(drm_mm_t *mm);
1061extern unsigned long drm_mm_tail_space(drm_mm_t *mm);
1062extern int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size);
1063extern int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size);
1061 1064
1062/* Inline replacements for DRM_IOREMAP macros */ 1065extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
1063static __inline__ void drm_core_ioremap(struct drm_map *map, 1066extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
1064 struct drm_device *dev)
1065{
1066 map->handle = drm_ioremap(map->offset, map->size, dev);
1067}
1068
1069#if 0
1070static __inline__ void drm_core_ioremap_nocache(struct drm_map *map,
1071 struct drm_device *dev)
1072{
1073 map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
1074}
1075#endif /* 0 */
1076
1077static __inline__ void drm_core_ioremapfree(struct drm_map *map,
1078 struct drm_device *dev)
1079{
1080 if (map->handle && map->size)
1081 drm_ioremapfree(map->handle, map->size, dev);
1082}
1083 1067
1084static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, 1068static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
1085 unsigned int token) 1069 unsigned int token)
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 9f65f5697ba8..a6828cc14e58 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -79,14 +79,14 @@ static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash,
79 79
80 if (!use_hashed_handle) { 80 if (!use_hashed_handle) {
81 int ret; 81 int ret;
82 hash->key = user_token; 82 hash->key = user_token >> PAGE_SHIFT;
83 ret = drm_ht_insert_item(&dev->map_hash, hash); 83 ret = drm_ht_insert_item(&dev->map_hash, hash);
84 if (ret != -EINVAL) 84 if (ret != -EINVAL)
85 return ret; 85 return ret;
86 } 86 }
87 return drm_ht_just_insert_please(&dev->map_hash, hash, 87 return drm_ht_just_insert_please(&dev->map_hash, hash,
88 user_token, 32 - PAGE_SHIFT - 3, 88 user_token, 32 - PAGE_SHIFT - 3,
89 PAGE_SHIFT, DRM_MAP_HASH_OFFSET); 89 0, DRM_MAP_HASH_OFFSET >> PAGE_SHIFT);
90} 90}
91 91
92/** 92/**
@@ -178,11 +178,11 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
178 } 178 }
179 } 179 }
180 if (map->type == _DRM_REGISTERS) 180 if (map->type == _DRM_REGISTERS)
181 map->handle = drm_ioremap(map->offset, map->size, dev); 181 map->handle = ioremap(map->offset, map->size);
182 break; 182 break;
183 183
184 case _DRM_SHM: 184 case _DRM_SHM:
185 map->handle = vmalloc_32(map->size); 185 map->handle = vmalloc_user(map->size);
186 DRM_DEBUG("%lu %d %p\n", 186 DRM_DEBUG("%lu %d %p\n",
187 map->size, drm_order(map->size), map->handle); 187 map->size, drm_order(map->size), map->handle);
188 if (!map->handle) { 188 if (!map->handle) {
@@ -238,7 +238,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
238 list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); 238 list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
239 if (!list) { 239 if (!list) {
240 if (map->type == _DRM_REGISTERS) 240 if (map->type == _DRM_REGISTERS)
241 drm_ioremapfree(map->handle, map->size, dev); 241 iounmap(map->handle);
242 drm_free(map, sizeof(*map), DRM_MEM_MAPS); 242 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
243 return -EINVAL; 243 return -EINVAL;
244 } 244 }
@@ -255,14 +255,14 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
255 ret = drm_map_handle(dev, &list->hash, user_token, 0); 255 ret = drm_map_handle(dev, &list->hash, user_token, 0);
256 if (ret) { 256 if (ret) {
257 if (map->type == _DRM_REGISTERS) 257 if (map->type == _DRM_REGISTERS)
258 drm_ioremapfree(map->handle, map->size, dev); 258 iounmap(map->handle);
259 drm_free(map, sizeof(*map), DRM_MEM_MAPS); 259 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
260 drm_free(list, sizeof(*list), DRM_MEM_MAPS); 260 drm_free(list, sizeof(*list), DRM_MEM_MAPS);
261 mutex_unlock(&dev->struct_mutex); 261 mutex_unlock(&dev->struct_mutex);
262 return ret; 262 return ret;
263 } 263 }
264 264
265 list->user_token = list->hash.key; 265 list->user_token = list->hash.key << PAGE_SHIFT;
266 mutex_unlock(&dev->struct_mutex); 266 mutex_unlock(&dev->struct_mutex);
267 267
268 *maplist = list; 268 *maplist = list;
@@ -347,7 +347,8 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
347 347
348 if (r_list->map == map) { 348 if (r_list->map == map) {
349 list_del(list); 349 list_del(list);
350 drm_ht_remove_key(&dev->map_hash, r_list->user_token); 350 drm_ht_remove_key(&dev->map_hash,
351 r_list->user_token >> PAGE_SHIFT);
351 drm_free(list, sizeof(*list), DRM_MEM_MAPS); 352 drm_free(list, sizeof(*list), DRM_MEM_MAPS);
352 break; 353 break;
353 } 354 }
@@ -362,7 +363,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
362 363
363 switch (map->type) { 364 switch (map->type) {
364 case _DRM_REGISTERS: 365 case _DRM_REGISTERS:
365 drm_ioremapfree(map->handle, map->size, dev); 366 iounmap(map->handle);
366 /* FALLTHROUGH */ 367 /* FALLTHROUGH */
367 case _DRM_FRAME_BUFFER: 368 case _DRM_FRAME_BUFFER:
368 if (drm_core_has_MTRR(dev) && map->mtrr >= 0) { 369 if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 5681cae1d404..92a867082376 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -79,28 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
79} 79}
80 80
81#if __OS_HAS_AGP 81#if __OS_HAS_AGP
82/*
83 * Find the drm_map that covers the range [offset, offset+size).
84 */
85static drm_map_t *drm_lookup_map(unsigned long offset,
86 unsigned long size, drm_device_t * dev)
87{
88 struct list_head *list;
89 drm_map_list_t *r_list;
90 drm_map_t *map;
91
92 list_for_each(list, &dev->maplist->head) {
93 r_list = (drm_map_list_t *) list;
94 map = r_list->map;
95 if (!map)
96 continue;
97 if (map->offset <= offset
98 && (offset + size) <= (map->offset + map->size))
99 return map;
100 }
101 return NULL;
102}
103
104static void *agp_remap(unsigned long offset, unsigned long size, 82static void *agp_remap(unsigned long offset, unsigned long size,
105 drm_device_t * dev) 83 drm_device_t * dev)
106{ 84{
@@ -169,13 +147,6 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
169} 147}
170 148
171#else /* __OS_HAS_AGP */ 149#else /* __OS_HAS_AGP */
172
173static inline drm_map_t *drm_lookup_map(unsigned long offset,
174 unsigned long size, drm_device_t * dev)
175{
176 return NULL;
177}
178
179static inline void *agp_remap(unsigned long offset, unsigned long size, 150static inline void *agp_remap(unsigned long offset, unsigned long size,
180 drm_device_t * dev) 151 drm_device_t * dev)
181{ 152{
@@ -184,57 +155,28 @@ static inline void *agp_remap(unsigned long offset, unsigned long size,
184 155
185#endif /* agp */ 156#endif /* agp */
186 157
187void *drm_ioremap(unsigned long offset, unsigned long size, 158#endif /* debug_memory */
188 drm_device_t * dev)
189{
190 if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
191 drm_map_t *map = drm_lookup_map(offset, size, dev);
192
193 if (map && map->type == _DRM_AGP)
194 return agp_remap(offset, size, dev);
195 }
196 return ioremap(offset, size);
197}
198EXPORT_SYMBOL(drm_ioremap);
199 159
200#if 0 160void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
201void *drm_ioremap_nocache(unsigned long offset,
202 unsigned long size, drm_device_t * dev)
203{ 161{
204 if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) { 162 if (drm_core_has_AGP(dev) &&
205 drm_map_t *map = drm_lookup_map(offset, size, dev); 163 dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
206 164 map->handle = agp_remap(map->offset, map->size, dev);
207 if (map && map->type == _DRM_AGP) 165 else
208 return agp_remap(offset, size, dev); 166 map->handle = ioremap(map->offset, map->size);
209 }
210 return ioremap_nocache(offset, size);
211} 167}
212#endif /* 0 */ 168EXPORT_SYMBOL(drm_core_ioremap);
213 169
214void drm_ioremapfree(void *pt, unsigned long size, 170void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
215 drm_device_t * dev)
216{ 171{
217 /* 172 if (!map->handle || !map->size)
218 * This is a bit ugly. It would be much cleaner if the DRM API would use separate 173 return;
219 * routines for handling mappings in the AGP space. Hopefully this can be done in 174
220 * a future revision of the interface... 175 if (drm_core_has_AGP(dev) &&
221 */ 176 dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
222 if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture 177 vunmap(map->handle);
223 && ((unsigned long)pt >= VMALLOC_START 178 else
224 && (unsigned long)pt < VMALLOC_END)) { 179 iounmap(map->handle);
225 unsigned long offset;
226 drm_map_t *map;
227
228 offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
229 map = drm_lookup_map(offset, size, dev);
230 if (map && map->type == _DRM_AGP) {
231 vunmap(pt);
232 return;
233 }
234 }
235
236 iounmap(pt);
237} 180}
238EXPORT_SYMBOL(drm_ioremapfree); 181EXPORT_SYMBOL(drm_core_ioremapfree);
239 182
240#endif /* debug_memory */
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
index f1b97aff10cf..63e425b5ea82 100644
--- a/drivers/char/drm/drm_memory.h
+++ b/drivers/char/drm/drm_memory.h
@@ -56,26 +56,6 @@
56# endif 56# endif
57#endif 57#endif
58 58
59static inline unsigned long drm_follow_page(void *vaddr)
60{
61 pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
62 pud_t *pud = pud_offset(pgd, (unsigned long)vaddr);
63 pmd_t *pmd = pmd_offset(pud, (unsigned long)vaddr);
64 pte_t *ptep = pte_offset_kernel(pmd, (unsigned long)vaddr);
65 return pte_pfn(*ptep) << PAGE_SHIFT;
66}
67
68#else /* __OS_HAS_AGP */ 59#else /* __OS_HAS_AGP */
69 60
70static inline unsigned long drm_follow_page(void *vaddr)
71{
72 return 0;
73}
74
75#endif 61#endif
76
77void *drm_ioremap(unsigned long offset, unsigned long size,
78 drm_device_t * dev);
79
80void drm_ioremapfree(void *pt, unsigned long size,
81 drm_device_t * dev);
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index 74581af806e1..6463271deea8 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -205,76 +205,6 @@ void drm_free (void *pt, size_t size, int area) {
205 } 205 }
206} 206}
207 207
208void *drm_ioremap (unsigned long offset, unsigned long size,
209 drm_device_t * dev) {
210 void *pt;
211
212 if (!size) {
213 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
214 "Mapping 0 bytes at 0x%08lx\n", offset);
215 return NULL;
216 }
217
218 if (!(pt = drm_ioremap(offset, size, dev))) {
219 spin_lock(&drm_mem_lock);
220 ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;
221 spin_unlock(&drm_mem_lock);
222 return NULL;
223 }
224 spin_lock(&drm_mem_lock);
225 ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
226 drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
227 spin_unlock(&drm_mem_lock);
228 return pt;
229}
230
231#if 0
232void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
233 drm_device_t * dev) {
234 void *pt;
235
236 if (!size) {
237 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
238 "Mapping 0 bytes at 0x%08lx\n", offset);
239 return NULL;
240 }
241
242 if (!(pt = drm_ioremap_nocache(offset, size, dev))) {
243 spin_lock(&drm_mem_lock);
244 ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;
245 spin_unlock(&drm_mem_lock);
246 return NULL;
247 }
248 spin_lock(&drm_mem_lock);
249 ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
250 drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
251 spin_unlock(&drm_mem_lock);
252 return pt;
253}
254#endif /* 0 */
255
256void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) {
257 int alloc_count;
258 int free_count;
259
260 if (!pt)
261 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
262 "Attempt to free NULL pointer\n");
263 else
264 drm_ioremapfree(pt, size, dev);
265
266 spin_lock(&drm_mem_lock);
267 drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size;
268 free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count;
269 alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
270 spin_unlock(&drm_mem_lock);
271 if (free_count > alloc_count) {
272 DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
273 "Excess frees: %d frees, %d allocs\n",
274 free_count, alloc_count);
275 }
276}
277
278#if __OS_HAS_AGP 208#if __OS_HAS_AGP
279 209
280DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) { 210DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) {
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
index 617526bd5b0c..9b46b85027d0 100644
--- a/drivers/char/drm/drm_mm.c
+++ b/drivers/char/drm/drm_mm.c
@@ -42,36 +42,131 @@
42 */ 42 */
43 43
44#include "drmP.h" 44#include "drmP.h"
45#include <linux/slab.h>
46
47unsigned long drm_mm_tail_space(drm_mm_t *mm)
48{
49 struct list_head *tail_node;
50 drm_mm_node_t *entry;
51
52 tail_node = mm->ml_entry.prev;
53 entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
54 if (!entry->free)
55 return 0;
56
57 return entry->size;
58}
59
60int drm_mm_remove_space_from_tail(drm_mm_t *mm, unsigned long size)
61{
62 struct list_head *tail_node;
63 drm_mm_node_t *entry;
64
65 tail_node = mm->ml_entry.prev;
66 entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
67 if (!entry->free)
68 return -ENOMEM;
69
70 if (entry->size <= size)
71 return -ENOMEM;
72
73 entry->size -= size;
74 return 0;
75}
76
77
78static int drm_mm_create_tail_node(drm_mm_t *mm,
79 unsigned long start,
80 unsigned long size)
81{
82 drm_mm_node_t *child;
83
84 child = (drm_mm_node_t *)
85 drm_alloc(sizeof(*child), DRM_MEM_MM);
86 if (!child)
87 return -ENOMEM;
88
89 child->free = 1;
90 child->size = size;
91 child->start = start;
92 child->mm = mm;
93
94 list_add_tail(&child->ml_entry, &mm->ml_entry);
95 list_add_tail(&child->fl_entry, &mm->fl_entry);
96
97 return 0;
98}
99
100
101int drm_mm_add_space_to_tail(drm_mm_t *mm, unsigned long size)
102{
103 struct list_head *tail_node;
104 drm_mm_node_t *entry;
105
106 tail_node = mm->ml_entry.prev;
107 entry = list_entry(tail_node, drm_mm_node_t, ml_entry);
108 if (!entry->free) {
109 return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
110 }
111 entry->size += size;
112 return 0;
113}
114
115static drm_mm_node_t *drm_mm_split_at_start(drm_mm_node_t *parent,
116 unsigned long size)
117{
118 drm_mm_node_t *child;
119
120 child = (drm_mm_node_t *)
121 drm_alloc(sizeof(*child), DRM_MEM_MM);
122 if (!child)
123 return NULL;
124
125 INIT_LIST_HEAD(&child->fl_entry);
126
127 child->free = 0;
128 child->size = size;
129 child->start = parent->start;
130 child->mm = parent->mm;
131
132 list_add_tail(&child->ml_entry, &parent->ml_entry);
133 INIT_LIST_HEAD(&child->fl_entry);
134
135 parent->size -= size;
136 parent->start += size;
137 return child;
138}
139
140
45 141
46drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, 142drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
47 unsigned long size, unsigned alignment) 143 unsigned long size, unsigned alignment)
48{ 144{
49 145
146 drm_mm_node_t *align_splitoff = NULL;
50 drm_mm_node_t *child; 147 drm_mm_node_t *child;
148 unsigned tmp = 0;
51 149
52 if (alignment) 150 if (alignment)
53 size += alignment - 1; 151 tmp = parent->start % alignment;
152
153 if (tmp) {
154 align_splitoff = drm_mm_split_at_start(parent, alignment - tmp);
155 if (!align_splitoff)
156 return NULL;
157 }
54 158
55 if (parent->size == size) { 159 if (parent->size == size) {
56 list_del_init(&parent->fl_entry); 160 list_del_init(&parent->fl_entry);
57 parent->free = 0; 161 parent->free = 0;
58 return parent; 162 return parent;
59 } else { 163 } else {
60 child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); 164 child = drm_mm_split_at_start(parent, size);
61 if (!child) 165 }
62 return NULL;
63
64 INIT_LIST_HEAD(&child->ml_entry);
65 INIT_LIST_HEAD(&child->fl_entry);
66 166
67 child->free = 0; 167 if (align_splitoff)
68 child->size = size; 168 drm_mm_put_block(align_splitoff);
69 child->start = parent->start;
70 169
71 list_add_tail(&child->ml_entry, &parent->ml_entry);
72 parent->size -= size;
73 parent->start += size;
74 }
75 return child; 170 return child;
76} 171}
77 172
@@ -80,12 +175,12 @@ drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent,
80 * Otherwise add to the free stack. 175 * Otherwise add to the free stack.
81 */ 176 */
82 177
83void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) 178void drm_mm_put_block(drm_mm_node_t * cur)
84{ 179{
85 180
86 drm_mm_node_t *list_root = &mm->root_node; 181 drm_mm_t *mm = cur->mm;
87 struct list_head *cur_head = &cur->ml_entry; 182 struct list_head *cur_head = &cur->ml_entry;
88 struct list_head *root_head = &list_root->ml_entry; 183 struct list_head *root_head = &mm->ml_entry;
89 drm_mm_node_t *prev_node = NULL; 184 drm_mm_node_t *prev_node = NULL;
90 drm_mm_node_t *next_node; 185 drm_mm_node_t *next_node;
91 186
@@ -116,7 +211,7 @@ void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur)
116 } 211 }
117 if (!merged) { 212 if (!merged) {
118 cur->free = 1; 213 cur->free = 1;
119 list_add(&cur->fl_entry, &list_root->fl_entry); 214 list_add(&cur->fl_entry, &mm->fl_entry);
120 } else { 215 } else {
121 list_del(&cur->ml_entry); 216 list_del(&cur->ml_entry);
122 drm_free(cur, sizeof(*cur), DRM_MEM_MM); 217 drm_free(cur, sizeof(*cur), DRM_MEM_MM);
@@ -128,20 +223,30 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
128 unsigned alignment, int best_match) 223 unsigned alignment, int best_match)
129{ 224{
130 struct list_head *list; 225 struct list_head *list;
131 const struct list_head *free_stack = &mm->root_node.fl_entry; 226 const struct list_head *free_stack = &mm->fl_entry;
132 drm_mm_node_t *entry; 227 drm_mm_node_t *entry;
133 drm_mm_node_t *best; 228 drm_mm_node_t *best;
134 unsigned long best_size; 229 unsigned long best_size;
230 unsigned wasted;
135 231
136 best = NULL; 232 best = NULL;
137 best_size = ~0UL; 233 best_size = ~0UL;
138 234
139 if (alignment)
140 size += alignment - 1;
141
142 list_for_each(list, free_stack) { 235 list_for_each(list, free_stack) {
143 entry = list_entry(list, drm_mm_node_t, fl_entry); 236 entry = list_entry(list, drm_mm_node_t, fl_entry);
144 if (entry->size >= size) { 237 wasted = 0;
238
239 if (entry->size < size)
240 continue;
241
242 if (alignment) {
243 register unsigned tmp = entry->start % alignment;
244 if (tmp)
245 wasted += alignment - tmp;
246 }
247
248
249 if (entry->size >= size + wasted) {
145 if (!best_match) 250 if (!best_match)
146 return entry; 251 return entry;
147 if (size < best_size) { 252 if (size < best_size) {
@@ -154,40 +259,32 @@ drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm,
154 return best; 259 return best;
155} 260}
156 261
157int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) 262int drm_mm_clean(drm_mm_t * mm)
158{ 263{
159 drm_mm_node_t *child; 264 struct list_head *head = &mm->ml_entry;
160
161 INIT_LIST_HEAD(&mm->root_node.ml_entry);
162 INIT_LIST_HEAD(&mm->root_node.fl_entry);
163 child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM);
164 if (!child)
165 return -ENOMEM;
166
167 INIT_LIST_HEAD(&child->ml_entry);
168 INIT_LIST_HEAD(&child->fl_entry);
169 265
170 child->start = start; 266 return (head->next->next == head);
171 child->size = size; 267}
172 child->free = 1;
173 268
174 list_add(&child->fl_entry, &mm->root_node.fl_entry); 269int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size)
175 list_add(&child->ml_entry, &mm->root_node.ml_entry); 270{
271 INIT_LIST_HEAD(&mm->ml_entry);
272 INIT_LIST_HEAD(&mm->fl_entry);
176 273
177 return 0; 274 return drm_mm_create_tail_node(mm, start, size);
178} 275}
179 276
180EXPORT_SYMBOL(drm_mm_init); 277EXPORT_SYMBOL(drm_mm_init);
181 278
182void drm_mm_takedown(drm_mm_t * mm) 279void drm_mm_takedown(drm_mm_t * mm)
183{ 280{
184 struct list_head *bnode = mm->root_node.fl_entry.next; 281 struct list_head *bnode = mm->fl_entry.next;
185 drm_mm_node_t *entry; 282 drm_mm_node_t *entry;
186 283
187 entry = list_entry(bnode, drm_mm_node_t, fl_entry); 284 entry = list_entry(bnode, drm_mm_node_t, fl_entry);
188 285
189 if (entry->ml_entry.next != &mm->root_node.ml_entry || 286 if (entry->ml_entry.next != &mm->ml_entry ||
190 entry->fl_entry.next != &mm->root_node.fl_entry) { 287 entry->fl_entry.next != &mm->fl_entry) {
191 DRM_ERROR("Memory manager not clean. Delaying takedown\n"); 288 DRM_ERROR("Memory manager not clean. Delaying takedown\n");
192 return; 289 return;
193 } 290 }
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 09398d5fbd3f..ad54b845978b 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -226,12 +226,14 @@
226 {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 226 {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
227 {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ 227 {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
228 {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 228 {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
229 {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
229 {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 230 {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
230 {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 231 {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
231 {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 232 {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
232 {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 233 {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
233 {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 234 {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
234 {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 235 {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
236 {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \
235 {0, 0, 0} 237 {0, 0, 0}
236 238
237#define i810_PCI_IDS \ 239#define i810_PCI_IDS \
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 62d5fe15f046..7fd0da712142 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -500,7 +500,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
500 for (pt = dev->vmalist; pt; pt = pt->next) { 500 for (pt = dev->vmalist; pt; pt = pt->next) {
501 if (!(vma = pt->vma)) 501 if (!(vma = pt->vma))
502 continue; 502 continue;
503 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx", 503 DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
504 pt->pid, 504 pt->pid,
505 vma->vm_start, 505 vma->vm_start,
506 vma->vm_end, 506 vma->vm_end,
@@ -510,7 +510,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request,
510 vma->vm_flags & VM_MAYSHARE ? 's' : 'p', 510 vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
511 vma->vm_flags & VM_LOCKED ? 'l' : '-', 511 vma->vm_flags & VM_LOCKED ? 'l' : '-',
512 vma->vm_flags & VM_IO ? 'i' : '-', 512 vma->vm_flags & VM_IO ? 'i' : '-',
513 vma->vm_pgoff << PAGE_SHIFT); 513 vma->vm_pgoff);
514 514
515#if defined(__i386__) 515#if defined(__i386__)
516 pgprot = pgprot_val(vma->vm_page_prot); 516 pgprot = pgprot_val(vma->vm_page_prot);
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c
index 19c81d2e13d0..e15db6d6bea9 100644
--- a/drivers/char/drm/drm_sman.c
+++ b/drivers/char/drm/drm_sman.c
@@ -101,10 +101,9 @@ static void *drm_sman_mm_allocate(void *private, unsigned long size,
101 101
102static void drm_sman_mm_free(void *private, void *ref) 102static void drm_sman_mm_free(void *private, void *ref)
103{ 103{
104 drm_mm_t *mm = (drm_mm_t *) private;
105 drm_mm_node_t *node = (drm_mm_node_t *) ref; 104 drm_mm_node_t *node = (drm_mm_node_t *) ref;
106 105
107 drm_mm_put_block(mm, node); 106 drm_mm_put_block(node);
108} 107}
109 108
110static void drm_sman_mm_destroy(void *private) 109static void drm_sman_mm_destroy(void *private)
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index b9cfc077f6bc..54a632848955 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -70,7 +70,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
70 if (!dev->agp || !dev->agp->cant_use_aperture) 70 if (!dev->agp || !dev->agp->cant_use_aperture)
71 goto vm_nopage_error; 71 goto vm_nopage_error;
72 72
73 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) 73 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
74 goto vm_nopage_error; 74 goto vm_nopage_error;
75 75
76 r_list = drm_hash_entry(hash, drm_map_list_t, hash); 76 r_list = drm_hash_entry(hash, drm_map_list_t, hash);
@@ -227,7 +227,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
227 map->size); 227 map->size);
228 DRM_DEBUG("mtrr_del = %d\n", retcode); 228 DRM_DEBUG("mtrr_del = %d\n", retcode);
229 } 229 }
230 drm_ioremapfree(map->handle, map->size, dev); 230 iounmap(map->handle);
231 break; 231 break;
232 case _DRM_SHM: 232 case _DRM_SHM:
233 vfree(map->handle); 233 vfree(map->handle);
@@ -463,8 +463,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
463 lock_kernel(); 463 lock_kernel();
464 dev = priv->head->dev; 464 dev = priv->head->dev;
465 dma = dev->dma; 465 dma = dev->dma;
466 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", 466 DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
467 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); 467 vma->vm_start, vma->vm_end, vma->vm_pgoff);
468 468
469 /* Length must match exact page count */ 469 /* Length must match exact page count */
470 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { 470 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
@@ -537,8 +537,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
537 unsigned long offset = 0; 537 unsigned long offset = 0;
538 drm_hash_item_t *hash; 538 drm_hash_item_t *hash;
539 539
540 DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", 540 DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
541 vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); 541 vma->vm_start, vma->vm_end, vma->vm_pgoff);
542 542
543 if (!priv->authenticated) 543 if (!priv->authenticated)
544 return -EACCES; 544 return -EACCES;
@@ -547,7 +547,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
547 * the AGP mapped at physical address 0 547 * the AGP mapped at physical address 0
548 * --BenH. 548 * --BenH.
549 */ 549 */
550 if (!(vma->vm_pgoff << PAGE_SHIFT) 550 if (!vma->vm_pgoff
551#if __OS_HAS_AGP 551#if __OS_HAS_AGP
552 && (!dev->agp 552 && (!dev->agp
553 || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) 553 || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
@@ -555,7 +555,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
555 ) 555 )
556 return drm_mmap_dma(filp, vma); 556 return drm_mmap_dma(filp, vma);
557 557
558 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) { 558 if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) {
559 DRM_ERROR("Could not find map\n"); 559 DRM_ERROR("Could not find map\n");
560 return -EINVAL; 560 return -EINVAL;
561 } 561 }
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index fa2de70f7401..60cb4e45a75e 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -219,8 +219,7 @@ static int i810_dma_cleanup(drm_device_t * dev)
219 (drm_i810_private_t *) dev->dev_private; 219 (drm_i810_private_t *) dev->dev_private;
220 220
221 if (dev_priv->ring.virtual_start) { 221 if (dev_priv->ring.virtual_start) {
222 drm_ioremapfree((void *)dev_priv->ring.virtual_start, 222 drm_core_ioremapfree(&dev_priv->ring.map, dev);
223 dev_priv->ring.Size, dev);
224 } 223 }
225 if (dev_priv->hw_status_page) { 224 if (dev_priv->hw_status_page) {
226 pci_free_consistent(dev->pdev, PAGE_SIZE, 225 pci_free_consistent(dev->pdev, PAGE_SIZE,
@@ -236,9 +235,9 @@ static int i810_dma_cleanup(drm_device_t * dev)
236 for (i = 0; i < dma->buf_count; i++) { 235 for (i = 0; i < dma->buf_count; i++) {
237 drm_buf_t *buf = dma->buflist[i]; 236 drm_buf_t *buf = dma->buflist[i];
238 drm_i810_buf_priv_t *buf_priv = buf->dev_private; 237 drm_i810_buf_priv_t *buf_priv = buf->dev_private;
238
239 if (buf_priv->kernel_virtual && buf->total) 239 if (buf_priv->kernel_virtual && buf->total)
240 drm_ioremapfree(buf_priv->kernel_virtual, 240 drm_core_ioremapfree(&buf_priv->map, dev);
241 buf->total, dev);
242 } 241 }
243 } 242 }
244 return 0; 243 return 0;
@@ -311,8 +310,15 @@ static int i810_freelist_init(drm_device_t * dev, drm_i810_private_t * dev_priv)
311 310
312 *buf_priv->in_use = I810_BUF_FREE; 311 *buf_priv->in_use = I810_BUF_FREE;
313 312
314 buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 313 buf_priv->map.offset = buf->bus_address;
315 buf->total, dev); 314 buf_priv->map.size = buf->total;
315 buf_priv->map.type = _DRM_AGP;
316 buf_priv->map.flags = 0;
317 buf_priv->map.mtrr = 0;
318
319 drm_core_ioremap(&buf_priv->map, dev);
320 buf_priv->kernel_virtual = buf_priv->map.handle;
321
316 } 322 }
317 return 0; 323 return 0;
318} 324}
@@ -363,18 +369,24 @@ static int i810_dma_initialize(drm_device_t * dev,
363 dev_priv->ring.End = init->ring_end; 369 dev_priv->ring.End = init->ring_end;
364 dev_priv->ring.Size = init->ring_size; 370 dev_priv->ring.Size = init->ring_size;
365 371
366 dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 372 dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
367 init->ring_start, 373 dev_priv->ring.map.size = init->ring_size;
368 init->ring_size, dev); 374 dev_priv->ring.map.type = _DRM_AGP;
375 dev_priv->ring.map.flags = 0;
376 dev_priv->ring.map.mtrr = 0;
369 377
370 if (dev_priv->ring.virtual_start == NULL) { 378 drm_core_ioremap(&dev_priv->ring.map, dev);
379
380 if (dev_priv->ring.map.handle == NULL) {
371 dev->dev_private = (void *)dev_priv; 381 dev->dev_private = (void *)dev_priv;
372 i810_dma_cleanup(dev); 382 i810_dma_cleanup(dev);
373 DRM_ERROR("can not ioremap virtual address for" 383 DRM_ERROR("can not ioremap virtual address for"
374 " ring buffer\n"); 384 " ring buffer\n");
375 return -ENOMEM; 385 return DRM_ERR(ENOMEM);
376 } 386 }
377 387
388 dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
389
378 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; 390 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
379 391
380 dev_priv->w = init->w; 392 dev_priv->w = init->w;
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index e8cf3ff606f0..e6df49f4928a 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -61,6 +61,7 @@ typedef struct drm_i810_buf_priv {
61 int currently_mapped; 61 int currently_mapped;
62 void *virtual; 62 void *virtual;
63 void *kernel_virtual; 63 void *kernel_virtual;
64 drm_local_map_t map;
64} drm_i810_buf_priv_t; 65} drm_i810_buf_priv_t;
65 66
66typedef struct _drm_i810_ring_buffer { 67typedef struct _drm_i810_ring_buffer {
@@ -72,6 +73,7 @@ typedef struct _drm_i810_ring_buffer {
72 int head; 73 int head;
73 int tail; 74 int tail;
74 int space; 75 int space;
76 drm_local_map_t map;
75} drm_i810_ring_buffer_t; 77} drm_i810_ring_buffer_t;
76 78
77typedef struct drm_i810_private { 79typedef struct drm_i810_private {
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 4f0e5746ab33..95224455ec0c 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -223,8 +223,7 @@ static int i830_dma_cleanup(drm_device_t * dev)
223 (drm_i830_private_t *) dev->dev_private; 223 (drm_i830_private_t *) dev->dev_private;
224 224
225 if (dev_priv->ring.virtual_start) { 225 if (dev_priv->ring.virtual_start) {
226 drm_ioremapfree((void *)dev_priv->ring.virtual_start, 226 drm_core_ioremapfree(&dev_priv->ring.map, dev);
227 dev_priv->ring.Size, dev);
228 } 227 }
229 if (dev_priv->hw_status_page) { 228 if (dev_priv->hw_status_page) {
230 pci_free_consistent(dev->pdev, PAGE_SIZE, 229 pci_free_consistent(dev->pdev, PAGE_SIZE,
@@ -242,8 +241,7 @@ static int i830_dma_cleanup(drm_device_t * dev)
242 drm_buf_t *buf = dma->buflist[i]; 241 drm_buf_t *buf = dma->buflist[i];
243 drm_i830_buf_priv_t *buf_priv = buf->dev_private; 242 drm_i830_buf_priv_t *buf_priv = buf->dev_private;
244 if (buf_priv->kernel_virtual && buf->total) 243 if (buf_priv->kernel_virtual && buf->total)
245 drm_ioremapfree(buf_priv->kernel_virtual, 244 drm_core_ioremapfree(&buf_priv->map, dev);
246 buf->total, dev);
247 } 245 }
248 } 246 }
249 return 0; 247 return 0;
@@ -320,8 +318,14 @@ static int i830_freelist_init(drm_device_t * dev, drm_i830_private_t * dev_priv)
320 318
321 *buf_priv->in_use = I830_BUF_FREE; 319 *buf_priv->in_use = I830_BUF_FREE;
322 320
323 buf_priv->kernel_virtual = drm_ioremap(buf->bus_address, 321 buf_priv->map.offset = buf->bus_address;
324 buf->total, dev); 322 buf_priv->map.size = buf->total;
323 buf_priv->map.type = _DRM_AGP;
324 buf_priv->map.flags = 0;
325 buf_priv->map.mtrr = 0;
326
327 drm_core_ioremap(&buf_priv->map, dev);
328 buf_priv->kernel_virtual = buf_priv->map.handle;
325 } 329 }
326 return 0; 330 return 0;
327} 331}
@@ -373,18 +377,24 @@ static int i830_dma_initialize(drm_device_t * dev,
373 dev_priv->ring.End = init->ring_end; 377 dev_priv->ring.End = init->ring_end;
374 dev_priv->ring.Size = init->ring_size; 378 dev_priv->ring.Size = init->ring_size;
375 379
376 dev_priv->ring.virtual_start = drm_ioremap(dev->agp->base + 380 dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
377 init->ring_start, 381 dev_priv->ring.map.size = init->ring_size;
378 init->ring_size, dev); 382 dev_priv->ring.map.type = _DRM_AGP;
383 dev_priv->ring.map.flags = 0;
384 dev_priv->ring.map.mtrr = 0;
385
386 drm_core_ioremap(&dev_priv->ring.map, dev);
379 387
380 if (dev_priv->ring.virtual_start == NULL) { 388 if (dev_priv->ring.map.handle == NULL) {
381 dev->dev_private = (void *)dev_priv; 389 dev->dev_private = (void *)dev_priv;
382 i830_dma_cleanup(dev); 390 i830_dma_cleanup(dev);
383 DRM_ERROR("can not ioremap virtual address for" 391 DRM_ERROR("can not ioremap virtual address for"
384 " ring buffer\n"); 392 " ring buffer\n");
385 return -ENOMEM; 393 return DRM_ERR(ENOMEM);
386 } 394 }
387 395
396 dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
397
388 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; 398 dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
389 399
390 dev_priv->w = init->w; 400 dev_priv->w = init->w;
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index 85bc5be6f916..e91f94afb4bb 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -68,6 +68,7 @@ typedef struct drm_i830_buf_priv {
68 int currently_mapped; 68 int currently_mapped;
69 void __user *virtual; 69 void __user *virtual;
70 void *kernel_virtual; 70 void *kernel_virtual;
71 drm_local_map_t map;
71} drm_i830_buf_priv_t; 72} drm_i830_buf_priv_t;
72 73
73typedef struct _drm_i830_ring_buffer { 74typedef struct _drm_i830_ring_buffer {
@@ -79,6 +80,7 @@ typedef struct _drm_i830_ring_buffer {
79 int head; 80 int head;
80 int tail; 81 int tail;
81 int space; 82 int space;
83 drm_local_map_t map;
82} drm_i830_ring_buffer_t; 84} drm_i830_ring_buffer_t;
83 85
84typedef struct drm_i830_private { 86typedef struct drm_i830_private {
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index a691ae74129d..c0539c6299cf 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -190,6 +190,11 @@ static int via_initialize(drm_device_t * dev,
190 return DRM_ERR(EFAULT); 190 return DRM_ERR(EFAULT);
191 } 191 }
192 192
193 if (dev_priv->chipset == VIA_DX9_0) {
194 DRM_ERROR("AGP DMA is not supported on this chip\n");
195 return DRM_ERR(EINVAL);
196 }
197
193 dev_priv->ring.map.offset = dev->agp->base + init->offset; 198 dev_priv->ring.map.offset = dev->agp->base + init->offset;
194 dev_priv->ring.map.size = init->size; 199 dev_priv->ring.map.size = init->size;
195 dev_priv->ring.map.type = 0; 200 dev_priv->ring.map.type = 0;
@@ -480,6 +485,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
480 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); 485 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
481 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); 486 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
482 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); 487 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
488 VIA_READ(VIA_REG_TRANSPACE);
483 } 489 }
484 } 490 }
485 return paused; 491 return paused;
@@ -557,8 +563,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv)
557 563
558 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); 564 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
559 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); 565 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
560 566 DRM_WRITEMEMORYBARRIER();
561 VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); 567 VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
568 VIA_READ(VIA_REG_TRANSPACE);
562} 569}
563 570
564static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) 571static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 806f9ce5f47b..2054d5773717 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -218,7 +218,9 @@ via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)
218 VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); 218 VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
219 VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); 219 VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
220 VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); 220 VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
221 DRM_WRITEMEMORYBARRIER();
221 VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); 222 VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
223 VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04);
222} 224}
223 225
224/* 226/*
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index d21b5b75da0f..8b8778d4a423 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -29,10 +29,10 @@
29 29
30#define DRIVER_NAME "via" 30#define DRIVER_NAME "via"
31#define DRIVER_DESC "VIA Unichrome / Pro" 31#define DRIVER_DESC "VIA Unichrome / Pro"
32#define DRIVER_DATE "20060529" 32#define DRIVER_DATE "20061227"
33 33
34#define DRIVER_MAJOR 2 34#define DRIVER_MAJOR 2
35#define DRIVER_MINOR 10 35#define DRIVER_MINOR 11
36#define DRIVER_PATCHLEVEL 0 36#define DRIVER_PATCHLEVEL 0
37 37
38#include "via_verifier.h" 38#include "via_verifier.h"
@@ -79,7 +79,7 @@ typedef struct drm_via_private {
79 char pci_buf[VIA_PCI_BUF_SIZE]; 79 char pci_buf[VIA_PCI_BUF_SIZE];
80 const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE]; 80 const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
81 uint32_t num_fire_offsets; 81 uint32_t num_fire_offsets;
82 int pro_group_a; 82 int chipset;
83 drm_via_irq_t via_irqs[VIA_NUM_IRQS]; 83 drm_via_irq_t via_irqs[VIA_NUM_IRQS];
84 unsigned num_irqs; 84 unsigned num_irqs;
85 maskarray_t *irq_masks; 85 maskarray_t *irq_masks;
@@ -96,8 +96,9 @@ typedef struct drm_via_private {
96} drm_via_private_t; 96} drm_via_private_t;
97 97
98enum via_family { 98enum via_family {
99 VIA_OTHER = 0, 99 VIA_OTHER = 0, /* Baseline */
100 VIA_PRO_GROUP_A, 100 VIA_PRO_GROUP_A, /* Another video engine and DMA commands */
101 VIA_DX9_0 /* Same video as pro_group_a, but 3D is unsupported */
101}; 102};
102 103
103/* VIA MMIO register access */ 104/* VIA MMIO register access */
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index c33d068cde19..1ac5941ad237 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -258,12 +258,16 @@ void via_driver_irq_preinstall(drm_device_t * dev)
258 dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE; 258 dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
259 dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING; 259 dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
260 260
261 dev_priv->irq_masks = (dev_priv->pro_group_a) ? 261 if (dev_priv->chipset == VIA_PRO_GROUP_A ||
262 via_pro_group_a_irqs : via_unichrome_irqs; 262 dev_priv->chipset == VIA_DX9_0) {
263 dev_priv->num_irqs = (dev_priv->pro_group_a) ? 263 dev_priv->irq_masks = via_pro_group_a_irqs;
264 via_num_pro_group_a : via_num_unichrome; 264 dev_priv->num_irqs = via_num_pro_group_a;
265 dev_priv->irq_map = (dev_priv->pro_group_a) ? 265 dev_priv->irq_map = via_irqmap_pro_group_a;
266 via_irqmap_pro_group_a : via_irqmap_unichrome; 266 } else {
267 dev_priv->irq_masks = via_unichrome_irqs;
268 dev_priv->num_irqs = via_num_unichrome;
269 dev_priv->irq_map = via_irqmap_unichrome;
270 }
267 271
268 for (i = 0; i < dev_priv->num_irqs; ++i) { 272 for (i = 0; i < dev_priv->num_irqs; ++i) {
269 atomic_set(&cur_irq->irq_received, 0); 273 atomic_set(&cur_irq->irq_received, 0);
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index 782011e0a58d..4e3fc072aa3b 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -106,8 +106,7 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset)
106 106
107 dev->dev_private = (void *)dev_priv; 107 dev->dev_private = (void *)dev_priv;
108 108
109 if (chipset == VIA_PRO_GROUP_A) 109 dev_priv->chipset = chipset;
110 dev_priv->pro_group_a = 1;
111 110
112 ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); 111 ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
113 if (ret) { 112 if (ret) {
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
index 70c897c88766..2e7e08078287 100644
--- a/drivers/char/drm/via_verifier.c
+++ b/drivers/char/drm/via_verifier.c
@@ -306,6 +306,7 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
306 unsigned long lo = ~0, hi = 0, tmp; 306 unsigned long lo = ~0, hi = 0, tmp;
307 uint32_t *addr, *pitch, *height, tex; 307 uint32_t *addr, *pitch, *height, tex;
308 unsigned i; 308 unsigned i;
309 int npot;
309 310
310 if (end > 9) 311 if (end > 9)
311 end = 9; 312 end = 9;
@@ -316,12 +317,15 @@ static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
316 &(cur_seq->t_addr[tex = cur_seq->texture][start]); 317 &(cur_seq->t_addr[tex = cur_seq->texture][start]);
317 pitch = &(cur_seq->pitch[tex][start]); 318 pitch = &(cur_seq->pitch[tex][start]);
318 height = &(cur_seq->height[tex][start]); 319 height = &(cur_seq->height[tex][start]);
319 320 npot = cur_seq->tex_npot[tex];
320 for (i = start; i <= end; ++i) { 321 for (i = start; i <= end; ++i) {
321 tmp = *addr++; 322 tmp = *addr++;
322 if (tmp < lo) 323 if (tmp < lo)
323 lo = tmp; 324 lo = tmp;
324 tmp += (*height++ << *pitch++); 325 if (i == 0 && npot)
326 tmp += (*height++ * *pitch++);
327 else
328 tmp += (*height++ << *pitch++);
325 if (tmp > hi) 329 if (tmp > hi)
326 hi = tmp; 330 hi = tmp;
327 } 331 }
@@ -443,13 +447,21 @@ investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
443 return 0; 447 return 0;
444 case check_texture_addr3: 448 case check_texture_addr3:
445 cur_seq->unfinished = tex_address; 449 cur_seq->unfinished = tex_address;
446 tmp = ((cmd >> 24) - 0x2B); 450 tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
447 cur_seq->pitch[cur_seq->texture][tmp] = 451 if (tmp == 0 &&
448 (cmd & 0x00F00000) >> 20; 452 (cmd & HC_HTXnEnPit_MASK)) {
449 if (!tmp && (cmd & 0x000FFFFF)) { 453 cur_seq->pitch[cur_seq->texture][tmp] =
450 DRM_ERROR 454 (cmd & HC_HTXnLnPit_MASK);
451 ("Unimplemented texture level 0 pitch mode.\n"); 455 cur_seq->tex_npot[cur_seq->texture] = 1;
452 return 2; 456 } else {
457 cur_seq->pitch[cur_seq->texture][tmp] =
458 (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
459 cur_seq->tex_npot[cur_seq->texture] = 0;
460 if (cmd & 0x000FFFFF) {
461 DRM_ERROR
462 ("Unimplemented texture level 0 pitch mode.\n");
463 return 2;
464 }
453 } 465 }
454 return 0; 466 return 0;
455 case check_texture_addr4: 467 case check_texture_addr4:
@@ -961,7 +973,13 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size,
961 uint32_t cmd; 973 uint32_t cmd;
962 const uint32_t *buf_end = buf + (size >> 2); 974 const uint32_t *buf_end = buf + (size >> 2);
963 verifier_state_t state = state_command; 975 verifier_state_t state = state_command;
964 int pro_group_a = dev_priv->pro_group_a; 976 int cme_video;
977 int supported_3d;
978
979 cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
980 dev_priv->chipset == VIA_DX9_0);
981
982 supported_3d = dev_priv->chipset != VIA_DX9_0;
965 983
966 hc_state->dev = dev; 984 hc_state->dev = dev;
967 hc_state->unfinished = no_sequence; 985 hc_state->unfinished = no_sequence;
@@ -986,17 +1004,21 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size,
986 state = via_check_vheader6(&buf, buf_end); 1004 state = via_check_vheader6(&buf, buf_end);
987 break; 1005 break;
988 case state_command: 1006 case state_command:
989 if (HALCYON_HEADER2 == (cmd = *buf)) 1007 if ((HALCYON_HEADER2 == (cmd = *buf)) &&
1008 supported_3d)
990 state = state_header2; 1009 state = state_header2;
991 else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) 1010 else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
992 state = state_header1; 1011 state = state_header1;
993 else if (pro_group_a 1012 else if (cme_video
994 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5) 1013 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
995 state = state_vheader5; 1014 state = state_vheader5;
996 else if (pro_group_a 1015 else if (cme_video
997 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) 1016 && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
998 state = state_vheader6; 1017 state = state_vheader6;
999 else { 1018 else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
1019 DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
1020 state = state_error;
1021 } else {
1000 DRM_ERROR 1022 DRM_ERROR
1001 ("Invalid / Unimplemented DMA HEADER command. 0x%x\n", 1023 ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
1002 cmd); 1024 cmd);
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index 256590fcc22a..b77f59df0278 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -43,6 +43,7 @@ typedef struct {
43 uint32_t tex_level_lo[2]; 43 uint32_t tex_level_lo[2];
44 uint32_t tex_level_hi[2]; 44 uint32_t tex_level_hi[2];
45 uint32_t tex_palette_size[2]; 45 uint32_t tex_palette_size[2];
46 uint32_t tex_npot[2];
46 drm_via_sequence_t unfinished; 47 drm_via_sequence_t unfinished;
47 int agp_texture; 48 int agp_texture;
48 int multitex; 49 int multitex;