diff options
author | Dave Airlie <airlied@redhat.com> | 2008-11-28 07:22:24 +0300 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-12-29 10:47:22 +0300 |
commit | 7c1c2871a6a3a114853ec6836e9035ac1c0c7f7a (patch) | |
tree | 1b5debcc86ff20bd5e11b42ea5c52da42214e376 /drivers/gpu/drm/drm_bufs.c | |
parent | e7f7ab45ebcb54fd5f814ea15ea079e079662f67 (diff) | |
download | linux-7c1c2871a6a3a114853ec6836e9035ac1c0c7f7a.tar.xz |
drm: move to kref per-master structures.
This is step one towards having multiple masters sharing a drm
device in order to get fast-user-switching to work.
It splits out the information associated with the drm master
into a separate kref counted structure, and allocates this when
a master opens the device node. It also allows the current master
to abdicate (say while VT switched), and a new master to take over
the hardware.
It moves the Intel and radeon drivers to using the sarea from
within the new master structures.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_bufs.c')
-rw-r--r-- | drivers/gpu/drm/drm_bufs.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index bde64b84166e..dc3ce3e0a0a4 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, { struct drm_map_list *entry; list_for_each_entry(entry, &dev->maplist, head) { - if (entry->map && map->type == entry->map->type && + if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) && ((entry->map->offset == map->offset) || - (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) { + ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) { return entry; } } @@ -210,12 +210,12 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, map->offset = (unsigned long)map->handle; if (map->flags & _DRM_CONTAINS_LOCK) { /* Prevent a 2nd X Server from creating a 2nd lock */ - if (dev->lock.hw_lock != NULL) { + if (dev->primary->master->lock.hw_lock != NULL) { vfree(map->handle); drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EBUSY; } - dev->sigdata.lock = dev->lock.hw_lock = map->handle; /* Pointer to lock */ + dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle; /* Pointer to lock */ } break; case _DRM_AGP: { @@ -319,6 +319,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, list->user_token = list->hash.key << PAGE_SHIFT; mutex_unlock(&dev->struct_mutex); + list->master = dev->primary->master; *maplist = list; return 0; } @@ -345,7 +346,7 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data, struct drm_map_list *maplist; int err; - if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP)) + if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM)) return -EPERM; err = drm_addmap_core(dev, map->offset, map->size, map->type, @@ -380,10 +381,12 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) struct drm_map_list *r_list = NULL, *list_t; drm_dma_handle_t dmah; int found = 0; + struct drm_master *master; /* Find the list entry for the map and remove it */ list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { if (r_list->map == map) { + master = r_list->master; list_del(&r_list->head); drm_ht_remove_key(&dev->map_hash, r_list->user_token >> PAGE_SHIFT); @@ -409,6 +412,13 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) break; case _DRM_SHM: vfree(map->handle); + if (master) { + if (dev->sigdata.lock == master->lock.hw_lock) + dev->sigdata.lock = NULL; + master->lock.hw_lock = NULL; /* SHM removed */ + master->lock.file_priv = NULL; + wake_up_interruptible(&master->lock.lock_queue); + } break; case _DRM_AGP: case _DRM_SCATTER_GATHER: |