Level: Intermediate
 
+Use struct dma_buf_map throughout codebase
+------------------------------------------
+
+Pointers to shared device memory are stored in struct dma_buf_map. Each
+instance knows whether it refers to system or I/O memory. Most of the DRM-wide
+interface have been converted to use struct dma_buf_map, but implementations
+often still use raw pointers.
+
+The task is to use struct dma_buf_map where it makes sense.
+
+* Memory managers should use struct dma_buf_map for dma-buf-imported buffers.
+* TTM might benefit from using struct dma_buf_map internally.
+* Framebuffer copying and blitting helpers should operate on struct dma_buf_map.
+
+Contact: Thomas Zimmermann <tzimmermann@suse.de>, Christian König, Daniel Vetter
+
+Level: Intermediate
+
 
 Core refactorings
 =================
 
        select FW_LOADER
         select DRM_KMS_HELPER
         select DRM_TTM
+       select DRM_TTM_HELPER
        select POWER_SUPPLY
        select HWMON
        select BACKLIGHT_CLASS_DEVICE
        select DRM_KMS_HELPER
        select DRM_SCHED
        select DRM_TTM
+       select DRM_TTM_HELPER
        select POWER_SUPPLY
        select HWMON
        select BACKLIGHT_CLASS_DEVICE
 
 #include <linux/dma-fence-array.h>
 #include <linux/pci-p2pdma.h>
 
-/**
- * amdgpu_gem_prime_vmap - &dma_buf_ops.vmap implementation
- * @obj: GEM BO
- *
- * Sets up an in-kernel virtual mapping of the BO's memory.
- *
- * Returns:
- * The virtual address of the mapping or an error pointer.
- */
-void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj)
-{
-       struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
-       int ret;
-
-       ret = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages,
-                         &bo->dma_buf_vmap);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return bo->dma_buf_vmap.virtual;
-}
-
-/**
- * amdgpu_gem_prime_vunmap - &dma_buf_ops.vunmap implementation
- * @obj: GEM BO
- * @vaddr: Virtual address (unused)
- *
- * Tears down the in-kernel virtual mapping of the BO's memory.
- */
-void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
-{
-       struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
-
-       ttm_bo_kunmap(&bo->dma_buf_vmap);
-}
-
 /**
  * amdgpu_gem_prime_mmap - &drm_driver.gem_prime_mmap implementation
  * @obj: GEM BO
 
                                            struct dma_buf *dma_buf);
 bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev,
                                      struct amdgpu_bo *bo);
-void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj);
-void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 int amdgpu_gem_prime_mmap(struct drm_gem_object *obj,
                          struct vm_area_struct *vma);
 
 
 
 #include <drm/amdgpu_drm.h>
 #include <drm/drm_debugfs.h>
+#include <drm/drm_gem_ttm_helper.h>
 
 #include "amdgpu.h"
 #include "amdgpu_display.h"
        .open = amdgpu_gem_object_open,
        .close = amdgpu_gem_object_close,
        .export = amdgpu_gem_prime_export,
-       .vmap = amdgpu_gem_prime_vmap,
-       .vunmap = amdgpu_gem_prime_vunmap,
+       .vmap = drm_gem_ttm_vmap,
+       .vunmap = drm_gem_ttm_vunmap,
 };
 
 /*
 
        struct amdgpu_bo                *parent;
        struct amdgpu_bo                *shadow;
 
-       struct ttm_bo_kmap_obj          dma_buf_vmap;
        struct amdgpu_mn                *mn;
 
 
 
 
        for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
                gbo = ast->cursor.gbo[i];
-               drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]);
+               drm_gem_vram_vunmap(gbo, &ast->cursor.map[i]);
                drm_gem_vram_unpin(gbo);
                drm_gem_vram_put(gbo);
        }
        struct drm_device *dev = &ast->base;
        size_t size, i;
        struct drm_gem_vram_object *gbo;
-       void __iomem *vaddr;
+       struct dma_buf_map map;
        int ret;
 
        size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
                        drm_gem_vram_put(gbo);
                        goto err_drm_gem_vram_put;
                }
-               vaddr = drm_gem_vram_vmap(gbo);
-               if (IS_ERR(vaddr)) {
-                       ret = PTR_ERR(vaddr);
+               ret = drm_gem_vram_vmap(gbo, &map);
+               if (ret) {
                        drm_gem_vram_unpin(gbo);
                        drm_gem_vram_put(gbo);
                        goto err_drm_gem_vram_put;
                }
 
                ast->cursor.gbo[i] = gbo;
-               ast->cursor.vaddr[i] = vaddr;
+               ast->cursor.map[i] = map;
        }
 
        return drmm_add_action_or_reset(dev, ast_cursor_release, NULL);
        while (i) {
                --i;
                gbo = ast->cursor.gbo[i];
-               drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]);
+               drm_gem_vram_vunmap(gbo, &ast->cursor.map[i]);
                drm_gem_vram_unpin(gbo);
                drm_gem_vram_put(gbo);
        }
 {
        struct drm_device *dev = &ast->base;
        struct drm_gem_vram_object *gbo;
+       struct dma_buf_map map;
        int ret;
        void *src;
        void __iomem *dst;
        ret = drm_gem_vram_pin(gbo, 0);
        if (ret)
                return ret;
-       src = drm_gem_vram_vmap(gbo);
-       if (IS_ERR(src)) {
-               ret = PTR_ERR(src);
+       ret = drm_gem_vram_vmap(gbo, &map);
+       if (ret)
                goto err_drm_gem_vram_unpin;
-       }
+       src = map.vaddr; /* TODO: Use mapping abstraction properly */
 
-       dst = ast->cursor.vaddr[ast->cursor.next_index];
+       dst = ast->cursor.map[ast->cursor.next_index].vaddr_iomem;
 
        /* do data transfer to cursor BO */
        update_cursor_image(dst, src, fb->width, fb->height);
 
-       drm_gem_vram_vunmap(gbo, src);
+       drm_gem_vram_vunmap(gbo, &map);
        drm_gem_vram_unpin(gbo);
 
        return 0;
        u8 __iomem *sig;
        u8 jreg;
 
-       dst = ast->cursor.vaddr[ast->cursor.next_index];
+       dst = ast->cursor.map[ast->cursor.next_index].vaddr;
 
        sig = dst + AST_HWC_SIZE;
        writel(x, sig + AST_HWC_SIGNATURE_X);
 
 #ifndef __AST_DRV_H__
 #define __AST_DRV_H__
 
-#include <linux/types.h>
-#include <linux/io.h>
+#include <linux/dma-buf-map.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
+#include <linux/io.h>
+#include <linux/types.h>
 
 #include <drm/drm_connector.h>
 #include <drm/drm_crtc.h>
 
        struct {
                struct drm_gem_vram_object *gbo[AST_DEFAULT_HWC_NUM];
-               void __iomem *vaddr[AST_DEFAULT_HWC_NUM];
+               struct dma_buf_map map[AST_DEFAULT_HWC_NUM];
                unsigned int next_index;
        } cursor;
 
 
 #include <linux/pagemap.h>
 #include <linux/shmem_fs.h>
 #include <linux/dma-buf.h>
+#include <linux/dma-buf-map.h>
 #include <linux/mem_encrypt.h>
 #include <linux/pagevec.h>
 
 
 void *drm_gem_vmap(struct drm_gem_object *obj)
 {
-       void *vaddr;
+       struct dma_buf_map map;
+       int ret;
 
-       if (obj->funcs->vmap)
-               vaddr = obj->funcs->vmap(obj);
-       else
-               vaddr = ERR_PTR(-EOPNOTSUPP);
+       if (!obj->funcs->vmap)
+               return ERR_PTR(-EOPNOTSUPP);
 
-       if (!vaddr)
-               vaddr = ERR_PTR(-ENOMEM);
+       ret = obj->funcs->vmap(obj, &map);
+       if (ret)
+               return ERR_PTR(ret);
+       else if (dma_buf_map_is_null(&map))
+               return ERR_PTR(-ENOMEM);
 
-       return vaddr;
+       return map.vaddr;
 }
 
 void drm_gem_vunmap(struct drm_gem_object *obj, void *vaddr)
 {
+       struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(vaddr);
+
        if (!vaddr)
                return;
 
        if (obj->funcs->vunmap)
-               obj->funcs->vunmap(obj, vaddr);
+               obj->funcs->vunmap(obj, &map);
 }
 
 /**
 
  * drm_gem_cma_prime_vmap - map a CMA GEM object into the kernel's virtual
  *     address space
  * @obj: GEM object
+ * @map: Returns the kernel virtual address of the CMA GEM object's backing
+ *       store.
  *
  * This function maps a buffer exported via DRM PRIME into the kernel's
  * virtual address space. Since the CMA buffers are already mapped into the
  * driver's &drm_gem_object_funcs.vmap callback.
  *
  * Returns:
- * The kernel virtual address of the CMA GEM object's backing store.
+ * 0 on success, or a negative error code otherwise.
  */
-void *drm_gem_cma_prime_vmap(struct drm_gem_object *obj)
+int drm_gem_cma_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
 
-       return cma_obj->vaddr;
+       dma_buf_map_set_vaddr(map, cma_obj->vaddr);
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vmap);
 
 
 }
 EXPORT_SYMBOL(drm_gem_shmem_unpin);
 
-static void *drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
+static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem, struct dma_buf_map *map)
 {
        struct drm_gem_object *obj = &shmem->base;
-       struct dma_buf_map map;
        int ret = 0;
 
-       if (shmem->vmap_use_count++ > 0)
-               return shmem->vaddr;
+       if (shmem->vmap_use_count++ > 0) {
+               dma_buf_map_set_vaddr(map, shmem->vaddr);
+               return 0;
+       }
 
        if (obj->import_attach) {
-               ret = dma_buf_vmap(obj->import_attach->dmabuf, &map);
-               if (!ret)
-                       shmem->vaddr = map.vaddr;
+               ret = dma_buf_vmap(obj->import_attach->dmabuf, map);
+               if (!ret) {
+                       if (WARN_ON(map->is_iomem)) {
+                               ret = -EIO;
+                               goto err_put_pages;
+                       }
+                       shmem->vaddr = map->vaddr;
+               }
        } else {
                pgprot_t prot = PAGE_KERNEL;
 
                                    VM_MAP, prot);
                if (!shmem->vaddr)
                        ret = -ENOMEM;
+               else
+                       dma_buf_map_set_vaddr(map, shmem->vaddr);
        }
 
        if (ret) {
                goto err_put_pages;
        }
 
-       return shmem->vaddr;
+       return 0;
 
 err_put_pages:
        if (!obj->import_attach)
 err_zero_use:
        shmem->vmap_use_count = 0;
 
-       return ERR_PTR(ret);
+       return ret;
 }
 
 /*
  * drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object
  * @shmem: shmem GEM object
+ * @map: Returns the kernel virtual address of the SHMEM GEM object's backing
+ *       store.
  *
  * This function makes sure that a contiguous kernel virtual address mapping
  * exists for the buffer backing the shmem GEM object.
  * Returns:
  * 0 on success or a negative error code on failure.
  */
-void *drm_gem_shmem_vmap(struct drm_gem_object *obj)
+int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
-       void *vaddr;
        int ret;
 
        ret = mutex_lock_interruptible(&shmem->vmap_lock);
        if (ret)
-               return ERR_PTR(ret);
-       vaddr = drm_gem_shmem_vmap_locked(shmem);
+               return ret;
+       ret = drm_gem_shmem_vmap_locked(shmem, map);
        mutex_unlock(&shmem->vmap_lock);
 
-       return vaddr;
+       return ret;
 }
 EXPORT_SYMBOL(drm_gem_shmem_vmap);
 
-static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem)
+static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
+                                       struct dma_buf_map *map)
 {
        struct drm_gem_object *obj = &shmem->base;
-       struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(shmem->vaddr);
 
        if (WARN_ON_ONCE(!shmem->vmap_use_count))
                return;
                return;
 
        if (obj->import_attach)
-               dma_buf_vunmap(obj->import_attach->dmabuf, &map);
+               dma_buf_vunmap(obj->import_attach->dmabuf, map);
        else
                vunmap(shmem->vaddr);
 
 /*
  * drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object
  * @shmem: shmem GEM object
+ * @map: Kernel virtual address where the SHMEM GEM object was mapped
  *
  * This function cleans up a kernel virtual address mapping acquired by
  * drm_gem_shmem_vmap(). The mapping is only removed when the use count drops to
  * also be called by drivers directly, in which case it will hide the
  * differences between dma-buf imported and natively allocated objects.
  */
-void drm_gem_shmem_vunmap(struct drm_gem_object *obj, void *vaddr)
+void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
 
        mutex_lock(&shmem->vmap_lock);
-       drm_gem_shmem_vunmap_locked(shmem);
+       drm_gem_shmem_vunmap_locked(shmem, map);
        mutex_unlock(&shmem->vmap_lock);
 }
 EXPORT_SYMBOL(drm_gem_shmem_vunmap);
 
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include <linux/dma-buf-map.h>
 #include <linux/module.h>
 
 #include <drm/drm_debugfs.h>
         * up; only release the GEM object.
         */
 
-       WARN_ON(gbo->kmap_use_count);
-       WARN_ON(gbo->kmap.virtual);
+       WARN_ON(gbo->vmap_use_count);
+       WARN_ON(dma_buf_map_is_set(&gbo->map));
 
        drm_gem_object_release(&gbo->bo.base);
 }
 }
 EXPORT_SYMBOL(drm_gem_vram_unpin);
 
-static void *drm_gem_vram_kmap_locked(struct drm_gem_vram_object *gbo)
+static int drm_gem_vram_kmap_locked(struct drm_gem_vram_object *gbo,
+                                   struct dma_buf_map *map)
 {
        int ret;
-       struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
-       bool is_iomem;
 
-       if (gbo->kmap_use_count > 0)
+       if (gbo->vmap_use_count > 0)
                goto out;
 
-       ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap);
+       ret = ttm_bo_vmap(&gbo->bo, &gbo->map);
        if (ret)
-               return ERR_PTR(ret);
+               return ret;
 
 out:
-       ++gbo->kmap_use_count;
-       return ttm_kmap_obj_virtual(kmap, &is_iomem);
+       ++gbo->vmap_use_count;
+       *map = gbo->map;
+
+       return 0;
 }
 
-static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo)
+static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo,
+                                      struct dma_buf_map *map)
 {
-       if (WARN_ON_ONCE(!gbo->kmap_use_count))
+       struct drm_device *dev = gbo->bo.base.dev;
+
+       if (drm_WARN_ON_ONCE(dev, !gbo->vmap_use_count))
                return;
-       if (--gbo->kmap_use_count > 0)
+
+       if (drm_WARN_ON_ONCE(dev, !dma_buf_map_is_equal(&gbo->map, map)))
+               return; /* BUG: map not mapped from this BO */
+
+       if (--gbo->vmap_use_count > 0)
                return;
 
        /*
 /**
  * drm_gem_vram_vmap() - Pins and maps a GEM VRAM object into kernel address
  *                       space
- * @gbo:       The GEM VRAM object to map
+ * @gbo: The GEM VRAM object to map
+ * @map: Returns the kernel virtual address of the VRAM GEM object's backing
+ *       store.
  *
  * The vmap function pins a GEM VRAM object to its current location, either
  * system or video memory, and maps its buffer into kernel address space.
  * unmap and unpin the GEM VRAM object.
  *
  * Returns:
- * The buffer's virtual address on success, or
- * an ERR_PTR()-encoded error code otherwise.
+ * 0 on success, or a negative error code otherwise.
  */
-void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo)
+int drm_gem_vram_vmap(struct drm_gem_vram_object *gbo, struct dma_buf_map *map)
 {
        int ret;
-       void *base;
 
        ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
        if (ret)
-               return ERR_PTR(ret);
+               return ret;
 
        ret = drm_gem_vram_pin_locked(gbo, 0);
        if (ret)
                goto err_ttm_bo_unreserve;
-       base = drm_gem_vram_kmap_locked(gbo);
-       if (IS_ERR(base)) {
-               ret = PTR_ERR(base);
+       ret = drm_gem_vram_kmap_locked(gbo, map);
+       if (ret)
                goto err_drm_gem_vram_unpin_locked;
-       }
 
        ttm_bo_unreserve(&gbo->bo);
 
-       return base;
+       return 0;
 
 err_drm_gem_vram_unpin_locked:
        drm_gem_vram_unpin_locked(gbo);
 err_ttm_bo_unreserve:
        ttm_bo_unreserve(&gbo->bo);
-       return ERR_PTR(ret);
+       return ret;
 }
 EXPORT_SYMBOL(drm_gem_vram_vmap);
 
 /**
  * drm_gem_vram_vunmap() - Unmaps and unpins a GEM VRAM object
- * @gbo:       The GEM VRAM object to unmap
- * @vaddr:     The mapping's base address as returned by drm_gem_vram_vmap()
+ * @gbo: The GEM VRAM object to unmap
+ * @map: Kernel virtual address where the VRAM GEM object was mapped
  *
  * A call to drm_gem_vram_vunmap() unmaps and unpins a GEM VRAM buffer. See
  * the documentation for drm_gem_vram_vmap() for more information.
  */
-void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr)
+void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, struct dma_buf_map *map)
 {
        int ret;
 
        if (WARN_ONCE(ret, "ttm_bo_reserve_failed(): ret=%d\n", ret))
                return;
 
-       drm_gem_vram_kunmap_locked(gbo);
+       drm_gem_vram_kunmap_locked(gbo, map);
        drm_gem_vram_unpin_locked(gbo);
 
        ttm_bo_unreserve(&gbo->bo);
                                               bool evict,
                                               struct ttm_resource *new_mem)
 {
-       struct ttm_bo_kmap_obj *kmap = &gbo->kmap;
+       struct ttm_buffer_object *bo = &gbo->bo;
+       struct drm_device *dev = bo->base.dev;
 
-       if (WARN_ON_ONCE(gbo->kmap_use_count))
+       if (drm_WARN_ON_ONCE(dev, gbo->vmap_use_count))
                return;
 
-       if (!kmap->virtual)
-               return;
-       ttm_bo_kunmap(kmap);
-       kmap->virtual = NULL;
+       ttm_bo_vunmap(bo, &gbo->map);
 }
 
 static int drm_gem_vram_bo_driver_move(struct drm_gem_vram_object *gbo,
 }
 
 /**
- * drm_gem_vram_object_vmap() - \
-       Implements &struct drm_gem_object_funcs.vmap
- * @gem:       The GEM object to map
+ * drm_gem_vram_object_vmap() -
+ *     Implements &struct drm_gem_object_funcs.vmap
+ * @gem: The GEM object to map
+ * @map: Returns the kernel virtual address of the VRAM GEM object's backing
+ *       store.
  *
  * Returns:
- * The buffers virtual address on success, or
- * NULL otherwise.
+ * 0 on success, or a negative error code otherwise.
  */
-static void *drm_gem_vram_object_vmap(struct drm_gem_object *gem)
+static int drm_gem_vram_object_vmap(struct drm_gem_object *gem, struct dma_buf_map *map)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
-       void *base;
 
-       base = drm_gem_vram_vmap(gbo);
-       if (IS_ERR(base))
-               return NULL;
-       return base;
+       return drm_gem_vram_vmap(gbo, map);
 }
 
 /**
- * drm_gem_vram_object_vunmap() - \
-       Implements &struct drm_gem_object_funcs.vunmap
- * @gem:       The GEM object to unmap
- * @vaddr:     The mapping's base address
+ * drm_gem_vram_object_vunmap() -
+ *     Implements &struct drm_gem_object_funcs.vunmap
+ * @gem: The GEM object to unmap
+ * @map: Kernel virtual address where the VRAM GEM object was mapped
  */
-static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem,
-                                      void *vaddr)
+static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem, struct dma_buf_map *map)
 {
        struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
 
-       drm_gem_vram_vunmap(gbo, vaddr);
+       drm_gem_vram_vunmap(gbo, map);
 }
 
 /*
 
 int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
 struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
-void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj);
+int etnaviv_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
 int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
                           struct vm_area_struct *vma);
 struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
 
        return drm_prime_pages_to_sg(obj->dev, etnaviv_obj->pages, npages);
 }
 
-void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj)
+int etnaviv_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
-       return etnaviv_gem_vmap(obj);
+       void *vaddr;
+
+       vaddr = etnaviv_gem_vmap(obj);
+       if (!vaddr)
+               return -ENOMEM;
+       dma_buf_map_set_vaddr(map, vaddr);
+
+       return 0;
 }
 
 int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
 
        return drm_gem_shmem_pin(obj);
 }
 
-static void *lima_gem_vmap(struct drm_gem_object *obj)
+static int lima_gem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct lima_bo *bo = to_lima_bo(obj);
 
        if (bo->heap_size)
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
 
-       return drm_gem_shmem_vmap(obj);
+       return drm_gem_shmem_vmap(obj, map);
 }
 
 static int lima_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
 
 // SPDX-License-Identifier: GPL-2.0 OR MIT
 /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
 
+#include <linux/dma-buf-map.h>
 #include <linux/kthread.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
        struct lima_dump_chunk_buffer *buffer_chunk;
        u32 size, task_size, mem_size;
        int i;
+       struct dma_buf_map map;
+       int ret;
 
        mutex_lock(&dev->error_task_list_lock);
 
                } else {
                        buffer_chunk->size = lima_bo_size(bo);
 
-                       data = drm_gem_shmem_vmap(&bo->base.base);
-                       if (IS_ERR_OR_NULL(data)) {
+                       ret = drm_gem_shmem_vmap(&bo->base.base, &map);
+                       if (ret) {
                                kvfree(et);
                                goto out;
                        }
 
-                       memcpy(buffer_chunk + 1, data, buffer_chunk->size);
+                       memcpy(buffer_chunk + 1, map.vaddr, buffer_chunk->size);
 
-                       drm_gem_shmem_vunmap(&bo->base.base, data);
+                       drm_gem_shmem_vunmap(&bo->base.base, &map);
                }
 
                buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size;
 
  */
 
 #include <linux/delay.h>
+#include <linux/dma-buf-map.h>
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_state_helper.h>
                      struct drm_rect *clip)
 {
        struct drm_device *dev = &mdev->base;
+       struct dma_buf_map map;
        void *vmap;
+       int ret;
 
-       vmap = drm_gem_shmem_vmap(fb->obj[0]);
-       if (drm_WARN_ON(dev, !vmap))
+       ret = drm_gem_shmem_vmap(fb->obj[0], &map);
+       if (drm_WARN_ON(dev, ret))
                return; /* BUG: SHMEM BO should always be vmapped */
+       vmap = map.vaddr; /* TODO: Use mapping abstraction properly */
 
        drm_fb_memcpy_dstclip(mdev->vram, vmap, fb, clip);
 
-       drm_gem_shmem_vunmap(fb->obj[0], vmap);
+       drm_gem_shmem_vunmap(fb->obj[0], &map);
 
        /* Always scanout image at VRAM offset 0 */
        mgag200_set_startadd(mdev, (u32)0);
 
        select FW_LOADER
        select DRM_KMS_HELPER
        select DRM_TTM
+       select DRM_TTM_HELPER
        select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT
        select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT
        select X86_PLATFORM_DEVICES if ACPI && X86
 
        unsigned mode;
 
        struct nouveau_drm_tile *tile;
-
-       struct ttm_bo_kmap_obj dma_buf_vmap;
 };
 
 static inline struct nouveau_bo *
 
  *
  */
 
+#include <drm/drm_gem_ttm_helper.h>
+
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
        .pin = nouveau_gem_prime_pin,
        .unpin = nouveau_gem_prime_unpin,
        .get_sg_table = nouveau_gem_prime_get_sg_table,
-       .vmap = nouveau_gem_prime_vmap,
-       .vunmap = nouveau_gem_prime_vunmap,
+       .vmap = drm_gem_ttm_vmap,
+       .vunmap = drm_gem_ttm_vunmap,
 };
 
 int
 
 extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *);
 extern struct drm_gem_object *nouveau_gem_prime_import_sg_table(
        struct drm_device *, struct dma_buf_attachment *, struct sg_table *);
-extern void *nouveau_gem_prime_vmap(struct drm_gem_object *);
-extern void nouveau_gem_prime_vunmap(struct drm_gem_object *, void *);
 
 #endif
 
        return drm_prime_pages_to_sg(obj->dev, nvbo->bo.ttm->pages, npages);
 }
 
-void *nouveau_gem_prime_vmap(struct drm_gem_object *obj)
-{
-       struct nouveau_bo *nvbo = nouveau_gem_object(obj);
-       int ret;
-
-       ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.num_pages,
-                         &nvbo->dma_buf_vmap);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return nvbo->dma_buf_vmap.virtual;
-}
-
-void nouveau_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
-{
-       struct nouveau_bo *nvbo = nouveau_gem_object(obj);
-
-       ttm_bo_kunmap(&nvbo->dma_buf_vmap);
-}
-
 struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
                                                         struct dma_buf_attachment *attach,
                                                         struct sg_table *sg)
 
 #include <drm/drm_gem_shmem_helper.h>
 #include <drm/panfrost_drm.h>
 #include <linux/completion.h>
+#include <linux/dma-buf-map.h>
 #include <linux/iopoll.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 {
        struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
+       struct dma_buf_map map;
        struct drm_gem_shmem_object *bo;
        u32 cfg, as;
        int ret;
                goto err_close_bo;
        }
 
-       perfcnt->buf = drm_gem_shmem_vmap(&bo->base);
-       if (IS_ERR(perfcnt->buf)) {
-               ret = PTR_ERR(perfcnt->buf);
+       ret = drm_gem_shmem_vmap(&bo->base, &map);
+       if (ret)
                goto err_put_mapping;
-       }
+       perfcnt->buf = map.vaddr;
 
        /*
         * Invalidate the cache and clear the counters to start from a fresh
        return 0;
 
 err_vunmap:
-       drm_gem_shmem_vunmap(&bo->base, perfcnt->buf);
+       drm_gem_shmem_vunmap(&bo->base, &map);
 err_put_mapping:
        panfrost_gem_mapping_put(perfcnt->mapping);
 err_close_bo:
 {
        struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
+       struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(perfcnt->buf);
 
        if (user != perfcnt->user)
                return -EINVAL;
                  GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF));
 
        perfcnt->user = NULL;
-       drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base.base, perfcnt->buf);
+       drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base.base, &map);
        perfcnt->buf = NULL;
        panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv);
        panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu);
 
 
 #include <linux/crc32.h>
 #include <linux/delay.h>
+#include <linux/dma-buf-map.h>
 
 #include <drm/drm_drv.h>
 #include <drm/drm_atomic.h>
        struct drm_gem_object *obj;
        struct qxl_bo *cursor_bo = NULL, *user_bo = NULL, *old_cursor_bo = NULL;
        int ret;
+       struct dma_buf_map user_map;
+       struct dma_buf_map cursor_map;
        void *user_ptr;
        int size = 64*64*4;
 
                user_bo = gem_to_qxl_bo(obj);
 
                /* pinning is done in the prepare/cleanup framevbuffer */
-               ret = qxl_bo_kmap(user_bo, &user_ptr);
+               ret = qxl_bo_kmap(user_bo, &user_map);
                if (ret)
                        goto out_free_release;
+               user_ptr = user_map.vaddr; /* TODO: Use mapping abstraction properly */
 
                ret = qxl_alloc_bo_reserved(qdev, release,
                                            sizeof(struct qxl_cursor) + size,
                if (ret)
                        goto out_unpin;
 
-               ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
+               ret = qxl_bo_kmap(cursor_bo, &cursor_map);
                if (ret)
                        goto out_backoff;
+               if (cursor_map.is_iomem) /* TODO: Use mapping abstraction properly */
+                       cursor = (struct qxl_cursor __force *)cursor_map.vaddr_iomem;
+               else
+                       cursor = (struct qxl_cursor *)cursor_map.vaddr;
 
                cursor->header.unique = 0;
                cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
 {
        int ret;
        struct drm_gem_object *gobj;
+       struct dma_buf_map map;
        int monitors_config_size = sizeof(struct qxl_monitors_config) +
                qxl_num_crtc * sizeof(struct qxl_head);
 
        if (ret)
                return ret;
 
-       qxl_bo_kmap(qdev->monitors_config_bo, NULL);
+       qxl_bo_kmap(qdev->monitors_config_bo, &map);
 
        qdev->monitors_config = qdev->monitors_config_bo->kptr;
        qdev->ram_header->monitors_config =
 
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/dma-buf-map.h>
+
 #include <drm/drm_fourcc.h>
 
 #include "qxl_drv.h"
                                              unsigned int num_clips,
                                              struct qxl_bo *clips_bo)
 {
+       struct dma_buf_map map;
        struct qxl_clip_rects *dev_clips;
        int ret;
 
-       ret = qxl_bo_kmap(clips_bo, (void **)&dev_clips);
-       if (ret) {
+       ret = qxl_bo_kmap(clips_bo, &map);
+       if (ret)
                return NULL;
-       }
+       dev_clips = map.vaddr; /* TODO: Use mapping abstraction properly */
+
        dev_clips->num_rects = num_clips;
        dev_clips->chunk.next_chunk = 0;
        dev_clips->chunk.prev_chunk = 0;
        int stride = fb->pitches[0];
        /* depth is not actually interesting, we don't mask with it */
        int depth = fb->format->cpp[0] * 8;
+       struct dma_buf_map surface_map;
        uint8_t *surface_base;
        struct qxl_release *release;
        struct qxl_bo *clips_bo;
        if (ret)
                goto out_release_backoff;
 
-       ret = qxl_bo_kmap(bo, (void **)&surface_base);
+       ret = qxl_bo_kmap(bo, &surface_map);
        if (ret)
                goto out_release_backoff;
+       surface_base = surface_map.vaddr; /* TODO: Use mapping abstraction properly */
 
        ret = qxl_image_init(qdev, release, dimage, surface_base,
                             left - dumb_shadow_offset,
 
  * Definitions taken from spice-protocol, plus kernel driver specific bits.
  */
 
+#include <linux/dma-buf-map.h>
 #include <linux/dma-fence.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
 
 #include "qxl_dev.h"
 
+struct dma_buf_map;
+
 #define DRIVER_AUTHOR          "Dave Airlie"
 
 #define DRIVER_NAME            "qxl"
        /* Protected by tbo.reserved */
        struct ttm_place                placements[3];
        struct ttm_placement            placement;
-       struct ttm_bo_kmap_obj          kmap;
+       struct dma_buf_map              map;
        void                            *kptr;
        unsigned int                    map_count;
        int                             type;
 void qxl_gem_object_close(struct drm_gem_object *obj,
                          struct drm_file *file_priv);
 void qxl_bo_force_delete(struct qxl_device *qdev);
-int qxl_bo_kmap(struct qxl_bo *bo, void **ptr);
 
 /* qxl_dumb.c */
 int qxl_mode_dumb_create(struct drm_file *file_priv,
 struct drm_gem_object *qxl_gem_prime_import_sg_table(
        struct drm_device *dev, struct dma_buf_attachment *attach,
        struct sg_table *sgt);
-void *qxl_gem_prime_vmap(struct drm_gem_object *obj);
-void qxl_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int qxl_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
+void qxl_gem_prime_vunmap(struct drm_gem_object *obj,
+                         struct dma_buf_map *map);
 int qxl_gem_prime_mmap(struct drm_gem_object *obj,
                                struct vm_area_struct *vma);
 
 
  *          Alon Levy
  */
 
+#include <linux/dma-buf-map.h>
+#include <linux/io-mapping.h>
+
 #include "qxl_drv.h"
 #include "qxl_object.h"
 
-#include <linux/io-mapping.h>
 static void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo)
 {
        struct qxl_bo *bo;
        return 0;
 }
 
-int qxl_bo_kmap(struct qxl_bo *bo, void **ptr)
+int qxl_bo_kmap(struct qxl_bo *bo, struct dma_buf_map *map)
 {
-       bool is_iomem;
        int r;
 
        if (bo->kptr) {
-               if (ptr)
-                       *ptr = bo->kptr;
                bo->map_count++;
-               return 0;
+               goto out;
        }
-       r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
+       r = ttm_bo_vmap(&bo->tbo, &bo->map);
        if (r)
                return r;
-       bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
-       if (ptr)
-               *ptr = bo->kptr;
        bo->map_count = 1;
+
+       /* TODO: Remove kptr in favor of map everywhere. */
+       if (bo->map.is_iomem)
+               bo->kptr = (void *)bo->map.vaddr_iomem;
+       else
+               bo->kptr = bo->map.vaddr;
+
+out:
+       *map = bo->map;
        return 0;
 }
 
        void *rptr;
        int ret;
        struct io_mapping *map;
+       struct dma_buf_map bo_map;
 
        if (bo->tbo.mem.mem_type == TTM_PL_VRAM)
                map = qdev->vram_mapping;
                return rptr;
        }
 
-       ret = qxl_bo_kmap(bo, &rptr);
+       ret = qxl_bo_kmap(bo, &bo_map);
        if (ret)
                return NULL;
+       rptr = bo_map.vaddr; /* TODO: Use mapping abstraction properly */
 
        rptr += page_offset * PAGE_SIZE;
        return rptr;
        if (bo->map_count > 0)
                return;
        bo->kptr = NULL;
-       ttm_bo_kunmap(&bo->kmap);
+       ttm_bo_vunmap(&bo->tbo, &bo->map);
 }
 
 void qxl_bo_kunmap_atomic_page(struct qxl_device *qdev,
 
                         bool kernel, bool pinned, u32 domain,
                         struct qxl_surface *surf,
                         struct qxl_bo **bo_ptr);
-extern int qxl_bo_kmap(struct qxl_bo *bo, void **ptr);
+extern int qxl_bo_kmap(struct qxl_bo *bo, struct dma_buf_map *map);
 extern void qxl_bo_kunmap(struct qxl_bo *bo);
 void *qxl_bo_kmap_atomic_page(struct qxl_device *qdev, struct qxl_bo *bo, int page_offset);
 void qxl_bo_kunmap_atomic_page(struct qxl_device *qdev, struct qxl_bo *bo, void *map);
 
        return ERR_PTR(-ENOSYS);
 }
 
-void *qxl_gem_prime_vmap(struct drm_gem_object *obj)
+int qxl_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct qxl_bo *bo = gem_to_qxl_bo(obj);
-       void *ptr;
        int ret;
 
-       ret = qxl_bo_kmap(bo, &ptr);
+       ret = qxl_bo_kmap(bo, map);
        if (ret < 0)
-               return ERR_PTR(ret);
+               return ret;
 
-       return ptr;
+       return 0;
 }
 
-void qxl_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+void qxl_gem_prime_vunmap(struct drm_gem_object *obj,
+                         struct dma_buf_map *map)
 {
        struct qxl_bo *bo = gem_to_qxl_bo(obj);
 
 
        /* Constant after initialization */
        struct radeon_device            *rdev;
 
-       struct ttm_bo_kmap_obj          dma_buf_vmap;
        pid_t                           pid;
 
 #ifdef CONFIG_MMU_NOTIFIER
 
 #include <drm/drm_debugfs.h>
 #include <drm/drm_device.h>
 #include <drm/drm_file.h>
+#include <drm/drm_gem_ttm_helper.h>
 #include <drm/radeon_drm.h>
 
 #include "radeon.h"
 struct sg_table *radeon_gem_prime_get_sg_table(struct drm_gem_object *obj);
 int radeon_gem_prime_pin(struct drm_gem_object *obj);
 void radeon_gem_prime_unpin(struct drm_gem_object *obj);
-void *radeon_gem_prime_vmap(struct drm_gem_object *obj);
-void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 
 static const struct drm_gem_object_funcs radeon_gem_object_funcs;
 
        .pin = radeon_gem_prime_pin,
        .unpin = radeon_gem_prime_unpin,
        .get_sg_table = radeon_gem_prime_get_sg_table,
-       .vmap = radeon_gem_prime_vmap,
-       .vunmap = radeon_gem_prime_vunmap,
+       .vmap = drm_gem_ttm_vmap,
+       .vunmap = drm_gem_ttm_vunmap,
 };
 
 /*
 
        return drm_prime_pages_to_sg(obj->dev, bo->tbo.ttm->pages, npages);
 }
 
-void *radeon_gem_prime_vmap(struct drm_gem_object *obj)
-{
-       struct radeon_bo *bo = gem_to_radeon_bo(obj);
-       int ret;
-
-       ret = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages,
-                         &bo->dma_buf_vmap);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return bo->dma_buf_vmap.virtual;
-}
-
-void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
-{
-       struct radeon_bo *bo = gem_to_radeon_bo(obj);
-
-       ttm_bo_kunmap(&bo->dma_buf_vmap);
-}
-
 struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev,
                                                        struct dma_buf_attachment *attach,
                                                        struct sg_table *sg)
 
        return ERR_PTR(ret);
 }
 
-void *rockchip_gem_prime_vmap(struct drm_gem_object *obj)
+int rockchip_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
 
-       if (rk_obj->pages)
-               return vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP,
-                           pgprot_writecombine(PAGE_KERNEL));
+       if (rk_obj->pages) {
+               void *vaddr = vmap(rk_obj->pages, rk_obj->num_pages, VM_MAP,
+                                 pgprot_writecombine(PAGE_KERNEL));
+               if (!vaddr)
+                       return -ENOMEM;
+               dma_buf_map_set_vaddr(map, vaddr);
+               return 0;
+       }
 
        if (rk_obj->dma_attrs & DMA_ATTR_NO_KERNEL_MAPPING)
-               return NULL;
+               return -ENOMEM;
+       dma_buf_map_set_vaddr(map, rk_obj->kvaddr);
 
-       return rk_obj->kvaddr;
+       return 0;
 }
 
-void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
 
        if (rk_obj->pages) {
-               vunmap(vaddr);
+               vunmap(map->vaddr);
                return;
        }
 
 
 rockchip_gem_prime_import_sg_table(struct drm_device *dev,
                                   struct dma_buf_attachment *attach,
                                   struct sg_table *sg);
-void *rockchip_gem_prime_vmap(struct drm_gem_object *obj);
-void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int rockchip_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
+void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map);
 
 /* drm driver mmap file operations */
 int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 
  */
 
 #include <linux/console.h>
+#include <linux/dma-buf-map.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 
                               struct drm_rect *rect)
 {
        struct cirrus_device *cirrus = to_cirrus(fb->dev);
+       struct dma_buf_map map;
        void *vmap;
        int idx, ret;
 
        if (!drm_dev_enter(&cirrus->dev, &idx))
                goto out;
 
-       ret = -ENOMEM;
-       vmap = drm_gem_shmem_vmap(fb->obj[0]);
-       if (!vmap)
+       ret = drm_gem_shmem_vmap(fb->obj[0], &map);
+       if (ret)
                goto out_dev_exit;
+       vmap = map.vaddr; /* TODO: Use mapping abstraction properly */
 
        if (cirrus->cpp == fb->format->cpp[0])
                drm_fb_memcpy_dstclip(cirrus->vram,
        else
                WARN_ON_ONCE("cpp mismatch");
 
-       drm_gem_shmem_vunmap(fb->obj[0], vmap);
+       drm_gem_shmem_vunmap(fb->obj[0], &map);
        ret = 0;
 
 out_dev_exit:
 
 {
        int block, dst_offset, len, remain, ret, x1, x2, y1, y2;
        struct drm_framebuffer *fb;
+       struct dma_buf_map map;
        void *vaddr;
        u8 *src;
 
        y1 = gm12u320->fb_update.rect.y1;
        y2 = gm12u320->fb_update.rect.y2;
 
-       vaddr = drm_gem_shmem_vmap(fb->obj[0]);
-       if (IS_ERR(vaddr)) {
-               GM12U320_ERR("failed to vmap fb: %ld\n", PTR_ERR(vaddr));
+       ret = drm_gem_shmem_vmap(fb->obj[0], &map);
+       if (ret) {
+               GM12U320_ERR("failed to vmap fb: %d\n", ret);
                goto put_fb;
        }
+       vaddr = map.vaddr; /* TODO: Use mapping abstraction properly */
 
        if (fb->obj[0]->import_attach) {
                ret = dma_buf_begin_cpu_access(
                        GM12U320_ERR("dma_buf_end_cpu_access err: %d\n", ret);
        }
 vunmap:
-       drm_gem_shmem_vunmap(fb->obj[0], vaddr);
+       drm_gem_shmem_vunmap(fb->obj[0], &map);
 put_fb:
        drm_framebuffer_put(fb);
        gm12u320->fb_update.fb = NULL;
 
        struct urb *urb;
        struct drm_rect clip;
        int log_bpp;
+       struct dma_buf_map map;
        void *vaddr;
 
        ret = udl_log_cpp(fb->format->cpp[0]);
                        return ret;
        }
 
-       vaddr = drm_gem_shmem_vmap(fb->obj[0]);
-       if (IS_ERR(vaddr)) {
+       ret = drm_gem_shmem_vmap(fb->obj[0], &map);
+       if (ret) {
                DRM_ERROR("failed to vmap fb\n");
                goto out_dma_buf_end_cpu_access;
        }
+       vaddr = map.vaddr; /* TODO: Use mapping abstraction properly */
 
        urb = udl_get_urb(dev);
        if (!urb)
        ret = 0;
 
 out_drm_gem_shmem_vunmap:
-       drm_gem_shmem_vunmap(fb->obj[0], vaddr);
+       drm_gem_shmem_vunmap(fb->obj[0], &map);
 out_dma_buf_end_cpu_access:
        if (import_attach) {
                tmp_ret = dma_buf_end_cpu_access(import_attach->dmabuf,
 
  *          Michael Thayer <michael.thayer@oracle.com,
  *          Hans de Goede <hdegoede@redhat.com>
  */
+
+#include <linux/dma-buf-map.h>
 #include <linux/export.h>
 
 #include <drm/drm_atomic.h>
        u32 height = plane->state->crtc_h;
        size_t data_size, mask_size;
        u32 flags;
+       struct dma_buf_map map;
+       int ret;
        u8 *src;
 
        /*
 
        vbox_crtc->cursor_enabled = true;
 
-       src = drm_gem_vram_vmap(gbo);
-       if (IS_ERR(src)) {
+       ret = drm_gem_vram_vmap(gbo, &map);
+       if (ret) {
                /*
                 * BUG: we should have pinned the BO in prepare_fb().
                 */
                DRM_WARN("Could not map cursor bo, skipping update\n");
                return;
        }
+       src = map.vaddr; /* TODO: Use mapping abstraction properly */
 
        /*
         * The mask must be calculated based on the alpha
        data_size = width * height * 4 + mask_size;
 
        copy_cursor_image(src, vbox->cursor_data, width, height, mask_size);
-       drm_gem_vram_vunmap(gbo, src);
+       drm_gem_vram_vunmap(gbo, &map);
 
        flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE |
                VBOX_MOUSE_POINTER_ALPHA;
 
        return drm_gem_cma_prime_mmap(obj, vma);
 }
 
-void *vc4_prime_vmap(struct drm_gem_object *obj)
+int vc4_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct vc4_bo *bo = to_vc4_bo(obj);
 
        if (bo->validated_shader) {
                DRM_DEBUG("mmaping of shader BOs not allowed.\n");
-               return ERR_PTR(-EINVAL);
+               return -EINVAL;
        }
 
-       return drm_gem_cma_prime_vmap(obj);
+       return drm_gem_cma_prime_vmap(obj, map);
 }
 
 struct drm_gem_object *
 
 struct drm_gem_object *vc4_prime_import_sg_table(struct drm_device *dev,
                                                 struct dma_buf_attachment *attach,
                                                 struct sg_table *sgt);
-void *vc4_prime_vmap(struct drm_gem_object *obj);
+int vc4_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
 int vc4_bo_cache_init(struct drm_device *dev);
 void vc4_bo_cache_destroy(struct drm_device *dev);
 int vc4_bo_inc_usecnt(struct vc4_bo *bo);
 
        return &obj->base;
 }
 
-static void *vgem_prime_vmap(struct drm_gem_object *obj)
+static int vgem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
        long n_pages = obj->size >> PAGE_SHIFT;
        struct page **pages;
+       void *vaddr;
 
        pages = vgem_pin_pages(bo);
        if (IS_ERR(pages))
-               return NULL;
+               return PTR_ERR(pages);
+
+       vaddr = vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL));
+       if (!vaddr)
+               return -ENOMEM;
+       dma_buf_map_set_vaddr(map, vaddr);
 
-       return vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL));
+       return 0;
 }
 
-static void vgem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+static void vgem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map)
 {
        struct drm_vgem_gem_object *bo = to_vgem_bo(obj);
 
-       vunmap(vaddr);
+       vunmap(map->vaddr);
        vgem_unpin_pages(bo);
 }
 
 
 // SPDX-License-Identifier: GPL-2.0+
 
+#include <linux/dma-buf-map.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
                           struct drm_plane_state *state)
 {
        struct drm_gem_object *gem_obj;
-       void *vaddr;
+       struct dma_buf_map map;
+       int ret;
 
        if (!state->fb)
                return 0;
 
        gem_obj = drm_gem_fb_get_obj(state->fb, 0);
-       vaddr = drm_gem_shmem_vmap(gem_obj);
-       if (IS_ERR(vaddr))
-               DRM_ERROR("vmap failed: %li\n", PTR_ERR(vaddr));
+       ret = drm_gem_shmem_vmap(gem_obj, &map);
+       if (ret)
+               DRM_ERROR("vmap failed: %d\n", ret);
 
        return drm_gem_fb_prepare_fb(plane, state);
 }
 {
        struct drm_gem_object *gem_obj;
        struct drm_gem_shmem_object *shmem_obj;
+       struct dma_buf_map map;
 
        if (!old_state->fb)
                return;
 
        gem_obj = drm_gem_fb_get_obj(old_state->fb, 0);
        shmem_obj = to_drm_gem_shmem_obj(drm_gem_fb_get_obj(old_state->fb, 0));
-       drm_gem_shmem_vunmap(gem_obj, shmem_obj->vaddr);
+       dma_buf_map_set_vaddr(&map, shmem_obj->vaddr);
+       drm_gem_shmem_vunmap(gem_obj, &map);
 }
 
 static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
 
 // SPDX-License-Identifier: GPL-2.0+
 
-#include "vkms_drv.h"
+#include <linux/dma-buf-map.h>
+
 #include <drm/drm_fourcc.h>
 #include <drm/drm_writeback.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_gem_shmem_helper.h>
 
+#include "vkms_drv.h"
+
 static const u32 vkms_wb_formats[] = {
        DRM_FORMAT_XRGB8888,
 };
                               struct drm_writeback_job *job)
 {
        struct drm_gem_object *gem_obj;
-       void *vaddr;
+       struct dma_buf_map map;
+       int ret;
 
        if (!job->fb)
                return 0;
 
        gem_obj = drm_gem_fb_get_obj(job->fb, 0);
-       vaddr = drm_gem_shmem_vmap(gem_obj);
-       if (IS_ERR(vaddr)) {
-               DRM_ERROR("vmap failed: %li\n", PTR_ERR(vaddr));
-               return PTR_ERR(vaddr);
+       ret = drm_gem_shmem_vmap(gem_obj, &map);
+       if (ret) {
+               DRM_ERROR("vmap failed: %d\n", ret);
+               return ret;
        }
 
-       job->priv = vaddr;
+       job->priv = map.vaddr;
 
        return 0;
 }
 {
        struct drm_gem_object *gem_obj;
        struct vkms_device *vkmsdev;
+       struct dma_buf_map map;
 
        if (!job->fb)
                return;
 
        gem_obj = drm_gem_fb_get_obj(job->fb, 0);
-       drm_gem_shmem_vunmap(gem_obj, job->priv);
+       dma_buf_map_set_vaddr(&map, job->priv);
+       drm_gem_shmem_vunmap(gem_obj, &map);
 
        vkmsdev = drm_device_to_vkms_device(gem_obj->dev);
        vkms_set_composer(&vkmsdev->output, false);
 
        return gem_mmap_obj(xen_obj, vma);
 }
 
-void *xen_drm_front_gem_prime_vmap(struct drm_gem_object *gem_obj)
+int xen_drm_front_gem_prime_vmap(struct drm_gem_object *gem_obj, struct dma_buf_map *map)
 {
        struct xen_gem_object *xen_obj = to_xen_gem_obj(gem_obj);
+       void *vaddr;
 
        if (!xen_obj->pages)
-               return NULL;
+               return -ENOMEM;
 
        /* Please see comment in gem_mmap_obj on mapping and attributes. */
-       return vmap(xen_obj->pages, xen_obj->num_pages,
-                   VM_MAP, PAGE_KERNEL);
+       vaddr = vmap(xen_obj->pages, xen_obj->num_pages,
+                    VM_MAP, PAGE_KERNEL);
+       if (!vaddr)
+               return -ENOMEM;
+       dma_buf_map_set_vaddr(map, vaddr);
+
+       return 0;
 }
 
 void xen_drm_front_gem_prime_vunmap(struct drm_gem_object *gem_obj,
-                                   void *vaddr)
+                                   struct dma_buf_map *map)
 {
-       vunmap(vaddr);
+       vunmap(map->vaddr);
 }
 
 int xen_drm_front_gem_prime_mmap(struct drm_gem_object *gem_obj,
 
 #define __XEN_DRM_FRONT_GEM_H
 
 struct dma_buf_attachment;
+struct dma_buf_map;
 struct drm_device;
 struct drm_gem_object;
 struct file;
 
 int xen_drm_front_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 
-void *xen_drm_front_gem_prime_vmap(struct drm_gem_object *gem_obj);
+int xen_drm_front_gem_prime_vmap(struct drm_gem_object *gem_obj,
+                                struct dma_buf_map *map);
 
 void xen_drm_front_gem_prime_vunmap(struct drm_gem_object *gem_obj,
-                                   void *vaddr);
+                                   struct dma_buf_map *map);
 
 int xen_drm_front_gem_prime_mmap(struct drm_gem_object *gem_obj,
                                 struct vm_area_struct *vma);
 
 
 #include <drm/drm_vma_manager.h>
 
+struct dma_buf_map;
 struct drm_gem_object;
 
 /**
         *
         * This callback is optional.
         */
-       void *(*vmap)(struct drm_gem_object *obj);
+       int (*vmap)(struct drm_gem_object *obj, struct dma_buf_map *map);
 
        /**
         * @vunmap:
         *
         * This callback is optional.
         */
-       void (*vunmap)(struct drm_gem_object *obj, void *vaddr);
+       void (*vunmap)(struct drm_gem_object *obj, struct dma_buf_map *map);
 
        /**
         * @mmap:
 
                                  struct sg_table *sgt);
 int drm_gem_cma_prime_mmap(struct drm_gem_object *obj,
                           struct vm_area_struct *vma);
-void *drm_gem_cma_prime_vmap(struct drm_gem_object *obj);
+int drm_gem_cma_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
 
 struct drm_gem_object *
 drm_gem_cma_create_object_default_funcs(struct drm_device *dev, size_t size);
 
 void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem);
 int drm_gem_shmem_pin(struct drm_gem_object *obj);
 void drm_gem_shmem_unpin(struct drm_gem_object *obj);
-void *drm_gem_shmem_vmap(struct drm_gem_object *obj);
-void drm_gem_shmem_vunmap(struct drm_gem_object *obj, void *vaddr);
+int drm_gem_shmem_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
+void drm_gem_shmem_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map);
 
 int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv);
 
 
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
 
+#include <linux/dma-buf-map.h>
 #include <linux/kernel.h> /* for container_of() */
 
 struct drm_mode_create_dumb;
 
 /**
  * struct drm_gem_vram_object - GEM object backed by VRAM
- * @gem:       GEM object
  * @bo:                TTM buffer object
- * @kmap:      Mapping information for @bo
+ * @map:       Mapping information for @bo
  * @placement: TTM placement information. Supported placements are \
        %TTM_PL_VRAM and %TTM_PL_SYSTEM
  * @placements:        TTM placement information.
  */
 struct drm_gem_vram_object {
        struct ttm_buffer_object bo;
-       struct ttm_bo_kmap_obj kmap;
+       struct dma_buf_map map;
 
        /**
-        * @kmap_use_count:
+        * @vmap_use_count:
         *
         * Reference count on the virtual address.
         * The address are un-mapped when the count reaches zero.
         */
-       unsigned int kmap_use_count;
+       unsigned int vmap_use_count;
 
        /* Supported placements are %TTM_PL_VRAM and %TTM_PL_SYSTEM */
        struct ttm_placement placement;
 s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo);
 int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag);
 int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo);
-void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo);
-void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr);
+int drm_gem_vram_vmap(struct drm_gem_vram_object *gbo, struct dma_buf_map *map);
+void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, struct dma_buf_map *map);
 
 int drm_gem_vram_fill_create_dumb(struct drm_file *file,
                                  struct drm_device *dev,