|
@@ -37,6 +37,7 @@
|
|
|
#include <linux/shmem_fs.h>
|
|
|
#include <linux/dma-buf.h>
|
|
|
#include <drm/drmP.h>
|
|
|
+#include <drm/drm_vma_manager.h>
|
|
|
|
|
|
/** @file drm_gem.c
|
|
|
*
|
|
@@ -102,14 +103,9 @@ drm_gem_init(struct drm_device *dev)
|
|
|
}
|
|
|
|
|
|
dev->mm_private = mm;
|
|
|
-
|
|
|
- if (drm_ht_create(&mm->offset_hash, 12)) {
|
|
|
- kfree(mm);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
|
|
|
- DRM_FILE_PAGE_OFFSET_SIZE);
|
|
|
+ drm_vma_offset_manager_init(&mm->vma_manager,
|
|
|
+ DRM_FILE_PAGE_OFFSET_START,
|
|
|
+ DRM_FILE_PAGE_OFFSET_SIZE);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -119,8 +115,7 @@ drm_gem_destroy(struct drm_device *dev)
|
|
|
{
|
|
|
struct drm_gem_mm *mm = dev->mm_private;
|
|
|
|
|
|
- drm_mm_takedown(&mm->offset_manager);
|
|
|
- drm_ht_remove(&mm->offset_hash);
|
|
|
+ drm_vma_offset_manager_destroy(&mm->vma_manager);
|
|
|
kfree(mm);
|
|
|
dev->mm_private = NULL;
|
|
|
}
|
|
@@ -302,12 +297,8 @@ 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;
|
|
|
+ drm_vma_offset_remove(&mm->vma_manager, &obj->vma_node);
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_gem_free_mmap_offset);
|
|
|
|
|
@@ -327,54 +318,9 @@ 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;
|
|
|
-
|
|
|
- /* 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, false);
|
|
|
-
|
|
|
- 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;
|
|
|
+ return drm_vma_offset_add(&mm->vma_manager, &obj->vma_node,
|
|
|
+ obj->size / PAGE_SIZE);
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_gem_create_mmap_offset);
|
|
|
|
|
@@ -703,8 +649,8 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
|
|
struct drm_file *priv = filp->private_data;
|
|
|
struct drm_device *dev = priv->minor->dev;
|
|
|
struct drm_gem_mm *mm = dev->mm_private;
|
|
|
- struct drm_local_map *map = NULL;
|
|
|
- struct drm_hash_item *hash;
|
|
|
+ struct drm_gem_object *obj;
|
|
|
+ struct drm_vma_offset_node *node;
|
|
|
int ret = 0;
|
|
|
|
|
|
if (drm_device_is_unplugged(dev))
|
|
@@ -712,21 +658,16 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
|
- if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) {
|
|
|
+ node = drm_vma_offset_exact_lookup(&mm->vma_manager, vma->vm_pgoff,
|
|
|
+ vma_pages(vma));
|
|
|
+ if (!node) {
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
return drm_mmap(filp, vma);
|
|
|
}
|
|
|
|
|
|
- map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
|
|
|
- if (!map ||
|
|
|
- ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) {
|
|
|
- ret = -EPERM;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
- ret = drm_gem_mmap_obj(map->handle, map->size, vma);
|
|
|
+ obj = container_of(node, struct drm_gem_object, vma_node);
|
|
|
+ ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node), vma);
|
|
|
|
|
|
-out_unlock:
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
|
|
return ret;
|