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.

Signed-off-by: David Herrmann <dh.herrmann at gmail.com>
---
 drivers/gpu/drm/drm_gem.c                  | 89 +++++-------------------------
 drivers/gpu/drm/drm_gem_cma_helper.c       |  9 +--
 drivers/gpu/drm/exynos/exynos_drm_gem.c    |  7 ++-
 drivers/gpu/drm/gma500/gem.c               |  8 +--
 drivers/gpu/drm/i915/i915_gem.c            |  9 +--
 drivers/gpu/drm/omapdrm/omap_gem.c         | 11 ++--
 drivers/gpu/drm/omapdrm/omap_gem_helpers.c | 49 +---------------
 drivers/gpu/drm/udl/udl_gem.c              |  6 +-
 include/drm/drmP.h                         |  7 +--
 include/drm/drm_vma_manager.h              |  1 -
 include/uapi/drm/drm.h                     |  2 +-
 11 files changed, 47 insertions(+), 151 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 88f0322..e1d0f67 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -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;
 }
@@ -306,12 +301,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);

@@ -331,54 +322,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);

@@ -660,9 +606,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_gem_object *obj;
-       struct drm_hash_item *hash;
+       struct drm_vma_offset_node *node;
        int ret = 0;

        if (drm_device_is_unplugged(dev))
@@ -670,25 +615,19 @@ 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);
+       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;
-       }
+       obj = container_of(node, struct drm_gem_object, vma_node);

        /* Check for valid size. */
-       if (map->size < vma->vm_end - vma->vm_start) {
+       if (node->vm_pages < vma_pages(vma)) {
                ret = -EINVAL;
                goto out_unlock;
        }

-       obj = map->handle;
        if (!obj->dev->driver->gem_vm_ops) {
                ret = -EINVAL;
                goto out_unlock;
@@ -696,7 +635,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct 
*vma)

        vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
        vma->vm_ops = obj->dev->driver->gem_vm_ops;
-       vma->vm_private_data = map->handle;
+       vma->vm_private_data = (void*)obj;
        vma->vm_page_prot =  
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));

        /* Take a ref for this mapping of the object, so that the fault
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c 
b/drivers/gpu/drm/drm_gem_cma_helper.c
index 0a7e011..905f4ec 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -26,10 +26,11 @@
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_vma_manager.h>

 static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
 {
-       return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
+       return (unsigned int)drm_vma_node_offset_addr(&obj->vma_node);
 }

 static void drm_gem_cma_buf_destroy(struct drm_device *drm,
@@ -140,7 +141,7 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
 {
        struct drm_gem_cma_object *cma_obj;

-       if (gem_obj->map_list.map)
+       if (drm_vma_node_has_offset(&gem_obj->vma_node))
                drm_gem_free_mmap_offset(gem_obj);

        drm_gem_object_release(gem_obj);
@@ -259,8 +260,8 @@ void drm_gem_cma_describe(struct drm_gem_cma_object 
*cma_obj, struct seq_file *m

        WARN_ON(!mutex_is_locked(&dev->struct_mutex));

-       if (obj->map_list.map)
-               off = (uint64_t)obj->map_list.hash.key;
+       if (drm_vma_node_has_offset(&obj->vma_node))
+               off = drm_vma_node_start(&obj->vma_node);

        seq_printf(m, "%2d (%2d) %08llx %08Zx %p %d",
                        obj->name, obj->refcount.refcount.counter,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c 
b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index cf4543f..59488ea 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -10,6 +10,7 @@
  */

 #include <drm/drmP.h>
+#include <drm/drm_vma_manager.h>

 #include <linux/shmem_fs.h>
 #include <drm/exynos_drm.h>
@@ -154,7 +155,7 @@ out:
        exynos_drm_fini_buf(obj->dev, buf);
        exynos_gem_obj->buffer = NULL;

-       if (obj->map_list.map)
+       if (drm_vma_node_has_offset(&obj->vma_node))
                drm_gem_free_mmap_offset(obj);

        /* release file pointer to gem object. */
@@ -721,13 +722,13 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file 
*file_priv,
                goto unlock;
        }

-       if (!obj->map_list.map) {
+       if (!drm_vma_node_has_offset(&obj->vma_node)) {
                ret = drm_gem_create_mmap_offset(obj);
                if (ret)
                        goto out;
        }

-       *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
+       *offset = drm_vma_node_offset_addr(&obj->vma_node);
        DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);

 out:
diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index eefd6cc..9fd0c9f 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -26,6 +26,7 @@
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include <drm/gma_drm.h>
+#include <drm/drm_vma_manager.h>
 #include "psb_drv.h"

 int psb_gem_init_object(struct drm_gem_object *obj)
@@ -38,7 +39,7 @@ void psb_gem_free_object(struct drm_gem_object *obj)
        struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);

        /* Remove the list map if one is present */
-       if (obj->map_list.map)
+       if (drm_vma_node_has_offset(&obj->vma_node))
                drm_gem_free_mmap_offset(obj);
        drm_gem_object_release(obj);

@@ -81,13 +82,12 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct 
drm_device *dev,
        /* What validation is needed here ? */

        /* Make it mmapable */
-       if (!obj->map_list.map) {
+       if (!drm_vma_node_has_offset(&obj->vma_node)) {
                ret = drm_gem_create_mmap_offset(obj);
                if (ret)
                        goto out;
        }
-       /* GEM should really work out the hash offsets for us */
-       *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
+       *offset = drm_vma_node_offset_addr(&obj->vma_node);
 out:
        drm_gem_object_unreference(obj);
 unlock:
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9e35daf..1617166 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -26,6 +26,7 @@
  */

 #include <drm/drmP.h>
+#include <drm/drm_vma_manager.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
@@ -1428,7 +1429,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)

        if (obj->base.dev->dev_mapping)
                unmap_mapping_range(obj->base.dev->dev_mapping,
-                                   
(loff_t)obj->base.map_list.hash.key<<PAGE_SHIFT,
+                                   
(loff_t)drm_vma_node_offset_addr(&obj->base.vma_node),
                                    obj->base.size, 1);

        obj->fault_mappable = false;
@@ -1486,7 +1487,7 @@ static int i915_gem_object_create_mmap_offset(struct 
drm_i915_gem_object *obj)
        struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
        int ret;

-       if (obj->base.map_list.map)
+       if (drm_vma_node_has_offset(&obj->base.vma_node))
                return 0;

        dev_priv->mm.shrinker_no_lock_stealing = true;
@@ -1517,7 +1518,7 @@ out:

 static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
 {
-       if (!obj->base.map_list.map)
+       if (!drm_vma_node_has_offset(&obj->base.vma_node))
                return;

        drm_gem_free_mmap_offset(&obj->base);
@@ -1558,7 +1559,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
        if (ret)
                goto out;

-       *offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
+       *offset = drm_vma_node_offset_addr(&obj->base.vma_node);

 out:
        drm_gem_object_unreference(&obj->base);
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c 
b/drivers/gpu/drm/omapdrm/omap_gem.c
index ebbdf41..0bcfdb9 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -20,6 +20,7 @@

 #include <linux/spinlock.h>
 #include <linux/shmem_fs.h>
+#include <drm/drm_vma_manager.h>

 #include "omap_drv.h"
 #include "omap_dmm_tiler.h"
@@ -311,7 +312,7 @@ static uint64_t mmap_offset(struct drm_gem_object *obj)

        WARN_ON(!mutex_is_locked(&dev->struct_mutex));

-       if (!obj->map_list.map) {
+       if (!drm_vma_node_has_offset(&obj->vma_node)) {
                /* Make it mmapable */
                size_t size = omap_gem_mmap_size(obj);
                int ret = _drm_gem_create_mmap_offset_size(obj, size);
@@ -322,7 +323,7 @@ static uint64_t mmap_offset(struct drm_gem_object *obj)
                }
        }

-       return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;
+       return drm_vma_node_offset_addr(&obj->vma_node);
 }

 uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
@@ -1001,8 +1002,8 @@ void omap_gem_describe(struct drm_gem_object *obj, struct 
seq_file *m)

        WARN_ON(!mutex_is_locked(&dev->struct_mutex));

-       if (obj->map_list.map)
-               off = (uint64_t)obj->map_list.hash.key;
+       if (drm_vma_node_has_offset(&obj->vma_node))
+               off = drm_vma_node_start(&obj->vma_node);

        seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
                        omap_obj->flags, obj->name, 
obj->refcount.refcount.counter,
@@ -1309,7 +1310,7 @@ void omap_gem_free_object(struct drm_gem_object *obj)

        list_del(&omap_obj->mm_list);

-       if (obj->map_list.map)
+       if (drm_vma_node_has_offset(&obj->vma_node))
                drm_gem_free_mmap_offset(obj);

        /* this means the object is still pinned.. which really should
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c 
b/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
index f9eb679..dbb1575 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_helpers.c
@@ -118,52 +118,7 @@ _drm_gem_create_mmap_offset_size(struct drm_gem_object 
*obj, size_t size)
 {
        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 = size;
-       map->handle = obj;
-
-       /* Get a DRM GEM mmap offset allocated... */
-       list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-                       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,
-                       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,
+                                 size / PAGE_SIZE);
 }
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index ef034fa..59aee8a 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -223,7 +223,7 @@ void udl_gem_free_object(struct drm_gem_object *gem_obj)
        if (obj->pages)
                udl_gem_put_pages(obj);

-       if (gem_obj->map_list.map)
+       if (drm_vma_node_has_offset(&gem_obj->vma_node))
                drm_gem_free_mmap_offset(gem_obj);
 }

@@ -247,13 +247,13 @@ int udl_gem_mmap(struct drm_file *file, struct drm_device 
*dev,
        ret = udl_gem_get_pages(gobj, GFP_KERNEL);
        if (ret)
                goto out;
-       if (!gobj->base.map_list.map) {
+       if (!drm_vma_node_has_offset(&gobj->base.vma_node)) {
                ret = drm_gem_create_mmap_offset(obj);
                if (ret)
                        goto out;
        }

-       *offset = (u64)gobj->base.map_list.hash.key << PAGE_SHIFT;
+       *offset = drm_vma_node_offset_addr(&gobj->base.vma_node);

 out:
        drm_gem_object_unreference(&gobj->base);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 63d17ee..79ea723 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -74,6 +74,7 @@
 #include <asm/pgalloc.h>
 #include <drm/drm.h>
 #include <drm/drm_sarea.h>
+#include <drm/drm_vma_manager.h>

 #include <linux/idr.h>

@@ -590,7 +591,6 @@ struct drm_map_list {
        struct drm_local_map *map;      /**< mapping */
        uint64_t user_token;
        struct drm_master *master;
-       struct drm_mm_node *file_offset_node;   /**< fake offset */
 };

 /**
@@ -625,8 +625,7 @@ struct drm_ati_pcigart_info {
  * GEM specific mm private for tracking GEM objects
  */
 struct drm_gem_mm {
-       struct drm_mm offset_manager;   /**< Offset mgmt for buffer objects */
-       struct drm_open_hash offset_hash; /**< User token hash table for maps */
+       struct drm_vma_offset_manager vma_manager;
 };

 /**
@@ -647,7 +646,7 @@ struct drm_gem_object {
        struct file *filp;

        /* Mapping info for this object */
-       struct drm_map_list map_list;
+       struct drm_vma_offset_node vma_node;

        /**
         * Size of the object, in bytes.  Immutable over the object's
diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h
index 8a1975c..4d6a734 100644
--- a/include/drm/drm_vma_manager.h
+++ b/include/drm/drm_vma_manager.h
@@ -23,7 +23,6 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */

-#include <drm/drmP.h>
 #include <drm/drm_mm.h>
 #include <linux/module.h>
 #include <linux/rbtree.h>
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 5a57be6..1d1c6f0 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -181,7 +181,7 @@ enum drm_map_type {
        _DRM_AGP = 3,             /**< AGP/GART */
        _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
        _DRM_CONSISTENT = 5,      /**< Consistent memory for PCI DMA */
-       _DRM_GEM = 6,             /**< GEM object */
+       _DRM_GEM = 6,             /**< GEM object (obsolete) */
 };

 /**
-- 
1.8.3.2

Reply via email to