diff options
| author | Rob Clark <rob@ti.com> | 2011-08-10 08:09:07 -0500 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2011-08-30 11:06:06 +0100 | 
| commit | 75ef8b3b9c0b76eb5a16cd838cb99a7deecceb85 (patch) | |
| tree | 1d6a3762bbc157fe3fc65982f42452c97d539d4f /drivers/gpu/drm/drm_gem.c | |
| parent | 302a8e8b06d312dcb3b718dfeb42aa912b5f426b (diff) | |
| download | olio-linux-3.10-75ef8b3b9c0b76eb5a16cd838cb99a7deecceb85.tar.xz olio-linux-3.10-75ef8b3b9c0b76eb5a16cd838cb99a7deecceb85.zip  | |
drm/gem: add functions for mmap offset creation
Signed-off-by: Rob Clark <rob@ti.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
| -rw-r--r-- | drivers/gpu/drm/drm_gem.c | 88 | 
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 186d62eb063..396e60ce811 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -285,6 +285,94 @@ again:  }  EXPORT_SYMBOL(drm_gem_handle_create); + +/** + * drm_gem_free_mmap_offset - release a fake mmap offset for an object + * @obj: obj in question + * + * This routine frees fake offsets allocated by drm_gem_create_mmap_offset(). + */ +void +drm_gem_free_mmap_offset(struct drm_gem_object *obj) +{ +	struct drm_device *dev = obj->dev; +	struct drm_gem_mm *mm = dev->mm_private; +	struct drm_map_list *list = &obj->map_list; + +	drm_ht_remove_item(&mm->offset_hash, &list->hash); +	drm_mm_put_block(list->file_offset_node); +	kfree(list->map); +	list->map = NULL; +} +EXPORT_SYMBOL(drm_gem_free_mmap_offset); + +/** + * drm_gem_create_mmap_offset - create a fake mmap offset for an object + * @obj: obj in question + * + * GEM memory mapping works by handing back to userspace a fake mmap offset + * it can use in a subsequent mmap(2) call.  The DRM core code then looks + * up the object based on the offset and sets up the various memory mapping + * structures. + * + * This routine allocates and attaches a fake offset for @obj. + */ +int +drm_gem_create_mmap_offset(struct drm_gem_object *obj) +{ +	struct drm_device *dev = obj->dev; +	struct drm_gem_mm *mm = dev->mm_private; +	struct drm_map_list *list; +	struct drm_local_map *map; +	int ret = 0; + +	/* Set the object up for mmap'ing */ +	list = &obj->map_list; +	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); +	if (!list->map) +		return -ENOMEM; + +	map = list->map; +	map->type = _DRM_GEM; +	map->size = obj->size; +	map->handle = obj; + +	/* Get a DRM GEM mmap offset allocated... */ +	list->file_offset_node = drm_mm_search_free(&mm->offset_manager, +			obj->size / PAGE_SIZE, 0, 0); + +	if (!list->file_offset_node) { +		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); +		ret = -ENOSPC; +		goto out_free_list; +	} + +	list->file_offset_node = drm_mm_get_block(list->file_offset_node, +			obj->size / PAGE_SIZE, 0); +	if (!list->file_offset_node) { +		ret = -ENOMEM; +		goto out_free_list; +	} + +	list->hash.key = list->file_offset_node->start; +	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); +	if (ret) { +		DRM_ERROR("failed to add to map hash\n"); +		goto out_free_mm; +	} + +	return 0; + +out_free_mm: +	drm_mm_put_block(list->file_offset_node); +out_free_list: +	kfree(list->map); +	list->map = NULL; + +	return ret; +} +EXPORT_SYMBOL(drm_gem_create_mmap_offset); +  /** Returns a reference to the object named by the handle. */  struct drm_gem_object *  drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,  |