aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_bufs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/drm_bufs.c')
-rw-r--r--drivers/char/drm/drm_bufs.c75
1 files changed, 66 insertions, 9 deletions
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index a6828cc14e58..c11345856ffe 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -57,7 +57,8 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
57 list_for_each(list, &dev->maplist->head) { 57 list_for_each(list, &dev->maplist->head) {
58 drm_map_list_t *entry = list_entry(list, drm_map_list_t, head); 58 drm_map_list_t *entry = list_entry(list, drm_map_list_t, head);
59 if (entry->map && map->type == entry->map->type && 59 if (entry->map && map->type == entry->map->type &&
60 entry->map->offset == map->offset) { 60 ((entry->map->offset == map->offset) ||
61 (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
61 return entry; 62 return entry;
62 } 63 }
63 } 64 }
@@ -180,8 +181,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
180 if (map->type == _DRM_REGISTERS) 181 if (map->type == _DRM_REGISTERS)
181 map->handle = ioremap(map->offset, map->size); 182 map->handle = ioremap(map->offset, map->size);
182 break; 183 break;
183
184 case _DRM_SHM: 184 case _DRM_SHM:
185 list = drm_find_matching_map(dev, map);
186 if (list != NULL) {
187 if(list->map->size != map->size) {
188 DRM_DEBUG("Matching maps of type %d with "
189 "mismatched sizes, (%ld vs %ld)\n",
190 map->type, map->size, list->map->size);
191 list->map->size = map->size;
192 }
193
194 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
195 *maplist = list;
196 return 0;
197 }
185 map->handle = vmalloc_user(map->size); 198 map->handle = vmalloc_user(map->size);
186 DRM_DEBUG("%lu %d %p\n", 199 DRM_DEBUG("%lu %d %p\n",
187 map->size, drm_order(map->size), map->handle); 200 map->size, drm_order(map->size), map->handle);
@@ -200,15 +213,45 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
200 dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ 213 dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */
201 } 214 }
202 break; 215 break;
203 case _DRM_AGP: 216 case _DRM_AGP: {
204 if (drm_core_has_AGP(dev)) { 217 drm_agp_mem_t *entry;
218 int valid = 0;
219
220 if (!drm_core_has_AGP(dev)) {
221 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
222 return -EINVAL;
223 }
205#ifdef __alpha__ 224#ifdef __alpha__
206 map->offset += dev->hose->mem_space->start; 225 map->offset += dev->hose->mem_space->start;
207#endif 226#endif
208 map->offset += dev->agp->base; 227 /* Note: dev->agp->base may actually be 0 when the DRM
209 map->mtrr = dev->agp->agp_mtrr; /* for getmap */ 228 * is not in control of AGP space. But if user space is
229 * it should already have added the AGP base itself.
230 */
231 map->offset += dev->agp->base;
232 map->mtrr = dev->agp->agp_mtrr; /* for getmap */
233
234 /* This assumes the DRM is in total control of AGP space.
235 * It's not always the case as AGP can be in the control
236 * of user space (i.e. i810 driver). So this loop will get
237 * skipped and we double check that dev->agp->memory is
238 * actually set as well as being invalid before EPERM'ing
239 */
240 for (entry = dev->agp->memory; entry; entry = entry->next) {
241 if ((map->offset >= entry->bound) &&
242 (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
243 valid = 1;
244 break;
245 }
210 } 246 }
247 if (dev->agp->memory && !valid) {
248 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
249 return -EPERM;
250 }
251 DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size);
252
211 break; 253 break;
254 }
212 case _DRM_SCATTER_GATHER: 255 case _DRM_SCATTER_GATHER:
213 if (!dev->sg) { 256 if (!dev->sg) {
214 drm_free(map, sizeof(*map), DRM_MEM_MAPS); 257 drm_free(map, sizeof(*map), DRM_MEM_MAPS);
@@ -267,7 +310,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
267 310
268 *maplist = list; 311 *maplist = list;
269 return 0; 312 return 0;
270} 313 }
271 314
272int drm_addmap(drm_device_t * dev, unsigned int offset, 315int drm_addmap(drm_device_t * dev, unsigned int offset,
273 unsigned int size, drm_map_type_t type, 316 unsigned int size, drm_map_type_t type,
@@ -519,6 +562,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
519{ 562{
520 drm_device_dma_t *dma = dev->dma; 563 drm_device_dma_t *dma = dev->dma;
521 drm_buf_entry_t *entry; 564 drm_buf_entry_t *entry;
565 drm_agp_mem_t *agp_entry;
522 drm_buf_t *buf; 566 drm_buf_t *buf;
523 unsigned long offset; 567 unsigned long offset;
524 unsigned long agp_offset; 568 unsigned long agp_offset;
@@ -529,7 +573,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
529 int page_order; 573 int page_order;
530 int total; 574 int total;
531 int byte_count; 575 int byte_count;
532 int i; 576 int i, valid;
533 drm_buf_t **temp_buflist; 577 drm_buf_t **temp_buflist;
534 578
535 if (!dma) 579 if (!dma)
@@ -560,6 +604,19 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
560 if (dev->queue_count) 604 if (dev->queue_count)
561 return -EBUSY; /* Not while in use */ 605 return -EBUSY; /* Not while in use */
562 606
607 /* Make sure buffers are located in AGP memory that we own */
608 valid = 0;
609 for (agp_entry = dev->agp->memory; agp_entry; agp_entry = agp_entry->next) {
610 if ((agp_offset >= agp_entry->bound) &&
611 (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
612 valid = 1;
613 break;
614 }
615 }
616 if (dev->agp->memory && !valid) {
617 DRM_DEBUG("zone invalid\n");
618 return -EINVAL;
619 }
563 spin_lock(&dev->count_lock); 620 spin_lock(&dev->count_lock);
564 if (dev->buf_use) { 621 if (dev->buf_use) {
565 spin_unlock(&dev->count_lock); 622 spin_unlock(&dev->count_lock);