diff options
author | Rob Clark <rob@ti.com> | 2011-08-10 09:09:07 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-08-30 06:06:06 -0400 |
commit | 75ef8b3b9c0b76eb5a16cd838cb99a7deecceb85 (patch) | |
tree | 1d6a3762bbc157fe3fc65982f42452c97d539d4f | |
parent | 302a8e8b06d312dcb3b718dfeb42aa912b5f426b (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>
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 88 | ||||
-rw-r--r-- | include/drm/drmP.h | 3 |
2 files changed, 91 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 | } |
286 | EXPORT_SYMBOL(drm_gem_handle_create); | 286 | EXPORT_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 | */ | ||
295 | void | ||
296 | drm_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 | } | ||
307 | EXPORT_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 | */ | ||
320 | int | ||
321 | drm_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 | |||
366 | out_free_mm: | ||
367 | drm_mm_put_block(list->file_offset_node); | ||
368 | out_free_list: | ||
369 | kfree(list->map); | ||
370 | list->map = NULL; | ||
371 | |||
372 | return ret; | ||
373 | } | ||
374 | EXPORT_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. */ |
289 | struct drm_gem_object * | 377 | struct drm_gem_object * |
290 | drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, | 378 | drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 9b7c2bb4bb44..43538b643560 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -1624,6 +1624,9 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) | |||
1624 | drm_gem_object_unreference_unlocked(obj); | 1624 | drm_gem_object_unreference_unlocked(obj); |
1625 | } | 1625 | } |
1626 | 1626 | ||
1627 | void drm_gem_free_mmap_offset(struct drm_gem_object *obj); | ||
1628 | int drm_gem_create_mmap_offset(struct drm_gem_object *obj); | ||
1629 | |||
1627 | struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, | 1630 | struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, |
1628 | struct drm_file *filp, | 1631 | struct drm_file *filp, |
1629 | u32 handle); | 1632 | u32 handle); |