aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_gem.c
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2011-08-10 09:09:07 -0400
committerDave Airlie <airlied@redhat.com>2011-08-30 06:06:06 -0400
commit75ef8b3b9c0b76eb5a16cd838cb99a7deecceb85 (patch)
tree1d6a3762bbc157fe3fc65982f42452c97d539d4f /drivers/gpu/drm/drm_gem.c
parent302a8e8b06d312dcb3b718dfeb42aa912b5f426b (diff)
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.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 186d62eb063b..396e60ce8114 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -285,6 +285,94 @@ again:
285} 285}
286EXPORT_SYMBOL(drm_gem_handle_create); 286EXPORT_SYMBOL(drm_gem_handle_create);
287 287
288
289/**
290 * drm_gem_free_mmap_offset - release a fake mmap offset for an object
291 * @obj: obj in question
292 *
293 * This routine frees fake offsets allocated by drm_gem_create_mmap_offset().
294 */
295void
296drm_gem_free_mmap_offset(struct drm_gem_object *obj)
297{
298 struct drm_device *dev = obj->dev;
299 struct drm_gem_mm *mm = dev->mm_private;
300 struct drm_map_list *list = &obj->map_list;
301
302 drm_ht_remove_item(&mm->offset_hash, &list->hash);
303 drm_mm_put_block(list->file_offset_node);
304 kfree(list->map);
305 list->map = NULL;
306}
307EXPORT_SYMBOL(drm_gem_free_mmap_offset);
308
309/**
310 * drm_gem_create_mmap_offset - create a fake mmap offset for an object
311 * @obj: obj in question
312 *
313 * GEM memory mapping works by handing back to userspace a fake mmap offset
314 * it can use in a subsequent mmap(2) call. The DRM core code then looks
315 * up the object based on the offset and sets up the various memory mapping
316 * structures.
317 *
318 * This routine allocates and attaches a fake offset for @obj.
319 */
320int
321drm_gem_create_mmap_offset(struct drm_gem_object *obj)
322{
323 struct drm_device *dev = obj->dev;
324 struct drm_gem_mm *mm = dev->mm_private;
325 struct drm_map_list *list;
326 struct drm_local_map *map;
327 int ret = 0;
328
329 /* Set the object up for mmap'ing */
330 list = &obj->map_list;
331 list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
332 if (!list->map)
333 return -ENOMEM;
334
335 map = list->map;
336 map->type = _DRM_GEM;
337 map->size = obj->size;
338 map->handle = obj;
339
340 /* Get a DRM GEM mmap offset allocated... */
341 list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
342 obj->size / PAGE_SIZE, 0, 0);
343
344 if (!list->file_offset_node) {
345 DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
346 ret = -ENOSPC;
347 goto out_free_list;
348 }
349
350 list->file_offset_node = drm_mm_get_block(list->file_offset_node,
351 obj->size / PAGE_SIZE, 0);
352 if (!list->file_offset_node) {
353 ret = -ENOMEM;
354 goto out_free_list;
355 }
356
357 list->hash.key = list->file_offset_node->start;
358 ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
359 if (ret) {
360 DRM_ERROR("failed to add to map hash\n");
361 goto out_free_mm;
362 }
363
364 return 0;
365
366out_free_mm:
367 drm_mm_put_block(list->file_offset_node);
368out_free_list:
369 kfree(list->map);
370 list->map = NULL;
371
372 return ret;
373}
374EXPORT_SYMBOL(drm_gem_create_mmap_offset);
375
288/** Returns a reference to the object named by the handle. */ 376/** Returns a reference to the object named by the handle. */
289struct drm_gem_object * 377struct drm_gem_object *
290drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, 378drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,