aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_gem.c
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-07-24 15:07:52 -0400
committerDave Airlie <airlied@gmail.com>2013-07-25 06:47:06 -0400
commit0de23977cfeb5b357ec884ba15417ae118ff9e9b (patch)
treebad8f04fc993b778020f6a2f7e9e7d2be8deb293 /drivers/gpu/drm/drm_gem.c
parentfe3078fa5c367186c94a6652581ffbe9ccea4640 (diff)
drm/gem: convert to new unified vma manager
Use the new vma manager instead of the old hashtable. Also convert all drivers to use the new convenience helpers. This drops all the (map_list.hash.key << PAGE_SHIFT) non-sense. Locking and access-management is exactly the same as before with an additional lock inside of the vma-manager, which strictly wouldn't be needed for gem. v2: - rebase on drm-next - init nodes via drm_vma_node_reset() in drm_gem.c v3: - fix tegra v4: - remove duplicate if (drm_vma_node_has_offset()) checks - inline now trivial drm_vma_node_offset_addr() calls v5: - skip node-reset on gem-init due to kzalloc() - do not allow mapping gem-objects with offsets (backwards compat) - remove unneccessary casts Cc: Inki Dae <inki.dae@samsung.com> Cc: Rob Clark <robdclark@gmail.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Acked-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
-rw-r--r--drivers/gpu/drm/drm_gem.c89
1 files changed, 15 insertions, 74 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 1ad9e7ec0119..3613b50b5c26 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -37,6 +37,7 @@
37#include <linux/shmem_fs.h> 37#include <linux/shmem_fs.h>
38#include <linux/dma-buf.h> 38#include <linux/dma-buf.h>
39#include <drm/drmP.h> 39#include <drm/drmP.h>
40#include <drm/drm_vma_manager.h>
40 41
41/** @file drm_gem.c 42/** @file drm_gem.c
42 * 43 *
@@ -102,14 +103,9 @@ drm_gem_init(struct drm_device *dev)
102 } 103 }
103 104
104 dev->mm_private = mm; 105 dev->mm_private = mm;
105 106 drm_vma_offset_manager_init(&mm->vma_manager,
106 if (drm_ht_create(&mm->offset_hash, 12)) { 107 DRM_FILE_PAGE_OFFSET_START,
107 kfree(mm); 108 DRM_FILE_PAGE_OFFSET_SIZE);
108 return -ENOMEM;
109 }
110
111 drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
112 DRM_FILE_PAGE_OFFSET_SIZE);
113 109
114 return 0; 110 return 0;
115} 111}
@@ -119,8 +115,7 @@ drm_gem_destroy(struct drm_device *dev)
119{ 115{
120 struct drm_gem_mm *mm = dev->mm_private; 116 struct drm_gem_mm *mm = dev->mm_private;
121 117
122 drm_mm_takedown(&mm->offset_manager); 118 drm_vma_offset_manager_destroy(&mm->vma_manager);
123 drm_ht_remove(&mm->offset_hash);
124 kfree(mm); 119 kfree(mm);
125 dev->mm_private = NULL; 120 dev->mm_private = NULL;
126} 121}
@@ -302,12 +297,8 @@ drm_gem_free_mmap_offset(struct drm_gem_object *obj)
302{ 297{
303 struct drm_device *dev = obj->dev; 298 struct drm_device *dev = obj->dev;
304 struct drm_gem_mm *mm = dev->mm_private; 299 struct drm_gem_mm *mm = dev->mm_private;
305 struct drm_map_list *list = &obj->map_list;
306 300
307 drm_ht_remove_item(&mm->offset_hash, &list->hash); 301 drm_vma_offset_remove(&mm->vma_manager, &obj->vma_node);
308 drm_mm_put_block(list->file_offset_node);
309 kfree(list->map);
310 list->map = NULL;
311} 302}
312EXPORT_SYMBOL(drm_gem_free_mmap_offset); 303EXPORT_SYMBOL(drm_gem_free_mmap_offset);
313 304
@@ -327,54 +318,9 @@ drm_gem_create_mmap_offset(struct drm_gem_object *obj)
327{ 318{
328 struct drm_device *dev = obj->dev; 319 struct drm_device *dev = obj->dev;
329 struct drm_gem_mm *mm = dev->mm_private; 320 struct drm_gem_mm *mm = dev->mm_private;
330 struct drm_map_list *list;
331 struct drm_local_map *map;
332 int ret;
333
334 /* Set the object up for mmap'ing */
335 list = &obj->map_list;
336 list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
337 if (!list->map)
338 return -ENOMEM;
339
340 map = list->map;
341 map->type = _DRM_GEM;
342 map->size = obj->size;
343 map->handle = obj;
344
345 /* Get a DRM GEM mmap offset allocated... */
346 list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
347 obj->size / PAGE_SIZE, 0, false);
348
349 if (!list->file_offset_node) {
350 DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
351 ret = -ENOSPC;
352 goto out_free_list;
353 }
354 321
355 list->file_offset_node = drm_mm_get_block(list->file_offset_node, 322 return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
356 obj->size / PAGE_SIZE, 0); 323 obj->size / PAGE_SIZE);
357 if (!list->file_offset_node) {
358 ret = -ENOMEM;
359 goto out_free_list;
360 }
361
362 list->hash.key = list->file_offset_node->start;
363 ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
364 if (ret) {
365 DRM_ERROR("failed to add to map hash\n");
366 goto out_free_mm;
367 }
368
369 return 0;
370
371out_free_mm:
372 drm_mm_put_block(list->file_offset_node);
373out_free_list:
374 kfree(list->map);
375 list->map = NULL;
376
377 return ret;
378} 324}
379EXPORT_SYMBOL(drm_gem_create_mmap_offset); 325EXPORT_SYMBOL(drm_gem_create_mmap_offset);
380 326
@@ -703,8 +649,8 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
703 struct drm_file *priv = filp->private_data; 649 struct drm_file *priv = filp->private_data;
704 struct drm_device *dev = priv->minor->dev; 650 struct drm_device *dev = priv->minor->dev;
705 struct drm_gem_mm *mm = dev->mm_private; 651 struct drm_gem_mm *mm = dev->mm_private;
706 struct drm_local_map *map = NULL; 652 struct drm_gem_object *obj;
707 struct drm_hash_item *hash; 653 struct drm_vma_offset_node *node;
708 int ret = 0; 654 int ret = 0;
709 655
710 if (drm_device_is_unplugged(dev)) 656 if (drm_device_is_unplugged(dev))
@@ -712,21 +658,16 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
712 658
713 mutex_lock(&dev->struct_mutex); 659 mutex_lock(&dev->struct_mutex);
714 660
715 if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) { 661 node = drm_vma_offset_exact_lookup(&mm->vma_manager, vma->vm_pgoff,
662 vma_pages(vma));
663 if (!node) {
716 mutex_unlock(&dev->struct_mutex); 664 mutex_unlock(&dev->struct_mutex);
717 return drm_mmap(filp, vma); 665 return drm_mmap(filp, vma);
718 } 666 }
719 667
720 map = drm_hash_entry(hash, struct drm_map_list, hash)->map; 668 obj = container_of(node, struct drm_gem_object, vma_node);
721 if (!map || 669 ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node), vma);
722 ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
723 ret = -EPERM;
724 goto out_unlock;
725 }
726
727 ret = drm_gem_mmap_obj(map->handle, map->size, vma);
728 670
729out_unlock:
730 mutex_unlock(&dev->struct_mutex); 671 mutex_unlock(&dev->struct_mutex);
731 672
732 return ret; 673 return ret;