diff options
Diffstat (limited to 'drivers/gpu/drm/drm_bufs.c')
-rw-r--r-- | drivers/gpu/drm/drm_bufs.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index bde64b84166e..72c667f9bee1 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c | |||
@@ -54,9 +54,9 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, | |||
54 | { | 54 | { |
55 | struct drm_map_list *entry; | 55 | struct drm_map_list *entry; |
56 | list_for_each_entry(entry, &dev->maplist, head) { | 56 | list_for_each_entry(entry, &dev->maplist, head) { |
57 | if (entry->map && map->type == entry->map->type && | 57 | if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) && |
58 | ((entry->map->offset == map->offset) || | 58 | ((entry->map->offset == map->offset) || |
59 | (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) { | 59 | ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) { |
60 | return entry; | 60 | return entry; |
61 | } | 61 | } |
62 | } | 62 | } |
@@ -210,12 +210,12 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | |||
210 | map->offset = (unsigned long)map->handle; | 210 | map->offset = (unsigned long)map->handle; |
211 | if (map->flags & _DRM_CONTAINS_LOCK) { | 211 | if (map->flags & _DRM_CONTAINS_LOCK) { |
212 | /* Prevent a 2nd X Server from creating a 2nd lock */ | 212 | /* Prevent a 2nd X Server from creating a 2nd lock */ |
213 | if (dev->lock.hw_lock != NULL) { | 213 | if (dev->primary->master->lock.hw_lock != NULL) { |
214 | vfree(map->handle); | 214 | vfree(map->handle); |
215 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 215 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
216 | return -EBUSY; | 216 | return -EBUSY; |
217 | } | 217 | } |
218 | dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ | 218 | dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle; /* Pointer to lock */ |
219 | } | 219 | } |
220 | break; | 220 | break; |
221 | case _DRM_AGP: { | 221 | case _DRM_AGP: { |
@@ -262,6 +262,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | |||
262 | DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size); | 262 | DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size); |
263 | 263 | ||
264 | break; | 264 | break; |
265 | case _DRM_GEM: | ||
266 | DRM_ERROR("tried to rmmap GEM object\n"); | ||
267 | break; | ||
265 | } | 268 | } |
266 | case _DRM_SCATTER_GATHER: | 269 | case _DRM_SCATTER_GATHER: |
267 | if (!dev->sg) { | 270 | if (!dev->sg) { |
@@ -319,6 +322,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, | |||
319 | list->user_token = list->hash.key << PAGE_SHIFT; | 322 | list->user_token = list->hash.key << PAGE_SHIFT; |
320 | mutex_unlock(&dev->struct_mutex); | 323 | mutex_unlock(&dev->struct_mutex); |
321 | 324 | ||
325 | list->master = dev->primary->master; | ||
322 | *maplist = list; | 326 | *maplist = list; |
323 | return 0; | 327 | return 0; |
324 | } | 328 | } |
@@ -345,7 +349,7 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data, | |||
345 | struct drm_map_list *maplist; | 349 | struct drm_map_list *maplist; |
346 | int err; | 350 | int err; |
347 | 351 | ||
348 | if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP)) | 352 | if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM)) |
349 | return -EPERM; | 353 | return -EPERM; |
350 | 354 | ||
351 | err = drm_addmap_core(dev, map->offset, map->size, map->type, | 355 | err = drm_addmap_core(dev, map->offset, map->size, map->type, |
@@ -380,10 +384,12 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) | |||
380 | struct drm_map_list *r_list = NULL, *list_t; | 384 | struct drm_map_list *r_list = NULL, *list_t; |
381 | drm_dma_handle_t dmah; | 385 | drm_dma_handle_t dmah; |
382 | int found = 0; | 386 | int found = 0; |
387 | struct drm_master *master; | ||
383 | 388 | ||
384 | /* Find the list entry for the map and remove it */ | 389 | /* Find the list entry for the map and remove it */ |
385 | list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { | 390 | list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { |
386 | if (r_list->map == map) { | 391 | if (r_list->map == map) { |
392 | master = r_list->master; | ||
387 | list_del(&r_list->head); | 393 | list_del(&r_list->head); |
388 | drm_ht_remove_key(&dev->map_hash, | 394 | drm_ht_remove_key(&dev->map_hash, |
389 | r_list->user_token >> PAGE_SHIFT); | 395 | r_list->user_token >> PAGE_SHIFT); |
@@ -409,6 +415,13 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) | |||
409 | break; | 415 | break; |
410 | case _DRM_SHM: | 416 | case _DRM_SHM: |
411 | vfree(map->handle); | 417 | vfree(map->handle); |
418 | if (master) { | ||
419 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
420 | dev->sigdata.lock = NULL; | ||
421 | master->lock.hw_lock = NULL; /* SHM removed */ | ||
422 | master->lock.file_priv = NULL; | ||
423 | wake_up_interruptible(&master->lock.lock_queue); | ||
424 | } | ||
412 | break; | 425 | break; |
413 | case _DRM_AGP: | 426 | case _DRM_AGP: |
414 | case _DRM_SCATTER_GATHER: | 427 | case _DRM_SCATTER_GATHER: |
@@ -419,11 +432,15 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) | |||
419 | dmah.size = map->size; | 432 | dmah.size = map->size; |
420 | __drm_pci_free(dev, &dmah); | 433 | __drm_pci_free(dev, &dmah); |
421 | break; | 434 | break; |
435 | case _DRM_GEM: | ||
436 | DRM_ERROR("tried to rmmap GEM object\n"); | ||
437 | break; | ||
422 | } | 438 | } |
423 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 439 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
424 | 440 | ||
425 | return 0; | 441 | return 0; |
426 | } | 442 | } |
443 | EXPORT_SYMBOL(drm_rmmap_locked); | ||
427 | 444 | ||
428 | int drm_rmmap(struct drm_device *dev, drm_local_map_t *map) | 445 | int drm_rmmap(struct drm_device *dev, drm_local_map_t *map) |
429 | { | 446 | { |