Yes this is a bit a big patch, but since it's essentially a complete
rewrite of all the prime docs I didn't see how to better split it up.

Changes:
- Consistently point to drm_gem_object_funcs as the preferred hooks,
  where applicable.

- Reorder all the functions in drm_prime.[hc] into three groups: core,
  export helpers, import helpers.

- Document all the hooks in &drm_driver that lacked kerneldoc.

- Completely new overview section, which now also includes the cleaned
  up lifetime/reference counting subchapter. I also mentioned the weak
  references in there due to the lookup caches.

- Completely rewritten helper intro section, highlight the
  import/export related functionality.

- Polish for all the functions and more cross references.

I also sprinkled a bunch of todos all over.

Most important: 0 code changes in here. The cleanup motivated by
reading and improving all this will follow later on.

v2: Actually update the prime helper docs. Plus add a few FIXMEs that
I won't address right away in subsequent cleanup patches.

Signed-off-by: Daniel Vetter <daniel.vet...@intel.com>
---
 Documentation/gpu/drm-mm.rst |  40 +-
 drivers/gpu/drm/drm_prime.c  | 851 ++++++++++++++++++-----------------
 include/drm/drm_drv.h        | 104 ++++-
 include/drm/drm_gem.h        |  18 +-
 include/drm/drm_prime.h      |  42 +-
 5 files changed, 576 insertions(+), 479 deletions(-)

diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
index c8ebd4f66a6a..b664f054c259 100644
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -433,43 +433,11 @@ PRIME is the cross device buffer sharing framework in 
drm, originally
 created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME
 buffers are dma-buf based file descriptors.
 
-Overview and Driver Interface
------------------------------
+Overview and Lifetime Rules
+---------------------------
 
-Similar to GEM global names, PRIME file descriptors are also used to
-share buffer objects across processes. They offer additional security:
-as file descriptors must be explicitly sent over UNIX domain sockets to
-be shared between applications, they can't be guessed like the globally
-unique GEM names.
-
-Drivers that support the PRIME API must set the DRIVER_PRIME bit in the
-struct :c:type:`struct drm_driver <drm_driver>`
-driver_features field, and implement the prime_handle_to_fd and
-prime_fd_to_handle operations.
-
-int (\*prime_handle_to_fd)(struct drm_device \*dev, struct drm_file
-\*file_priv, uint32_t handle, uint32_t flags, int \*prime_fd); int
-(\*prime_fd_to_handle)(struct drm_device \*dev, struct drm_file
-\*file_priv, int prime_fd, uint32_t \*handle); Those two operations
-convert a handle to a PRIME file descriptor and vice versa. Drivers must
-use the kernel dma-buf buffer sharing framework to manage the PRIME file
-descriptors. Similar to the mode setting API PRIME is agnostic to the
-underlying buffer object manager, as long as handles are 32bit unsigned
-integers.
-
-While non-GEM drivers must implement the operations themselves, GEM
-drivers must use the :c:func:`drm_gem_prime_handle_to_fd()` and
-:c:func:`drm_gem_prime_fd_to_handle()` helper functions. Those
-helpers rely on the driver gem_prime_export and gem_prime_import
-operations to create a dma-buf instance from a GEM object (dma-buf
-exporter role) and to create a GEM object from a dma-buf instance
-(dma-buf importer role).
-
-struct dma_buf \* (\*gem_prime_export)(struct drm_device \*dev,
-struct drm_gem_object \*obj, int flags); struct drm_gem_object \*
-(\*gem_prime_import)(struct drm_device \*dev, struct dma_buf
-\*dma_buf); These two operations are mandatory for GEM drivers that
-support PRIME.
+.. kernel-doc:: drivers/gpu/drm/drm_prime.c
+   :doc: overview and lifetime rules
 
 PRIME Helper Functions
 ----------------------
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index d0c01318076b..f08159a8b03a 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -38,47 +38,53 @@
 
 #include "drm_internal.h"
 
-/*
- * DMA-BUF/GEM Object references and lifetime overview:
- *
- * On the export the dma_buf holds a reference to the exporting GEM
- * object. It takes this reference in handle_to_fd_ioctl, when it
- * first calls .prime_export and stores the exporting GEM object in
- * the dma_buf priv. This reference needs to be released when the
- * final reference to the &dma_buf itself is dropped and its
- * &dma_buf_ops.release function is called. For GEM-based drivers,
- * the dma_buf should be exported using drm_gem_dmabuf_export() and
- * then released by drm_gem_dmabuf_release().
- *
- * On the import the importing GEM object holds a reference to the
- * dma_buf (which in turn holds a ref to the exporting GEM object).
- * It takes that reference in the fd_to_handle ioctl.
- * It calls dma_buf_get, creates an attachment to it and stores the
- * attachment in the GEM object. When this attachment is destroyed
- * when the imported object is destroyed, we remove the attachment
- * and drop the reference to the dma_buf.
- *
- * When all the references to the &dma_buf are dropped, i.e. when
- * userspace has closed both handles to the imported GEM object (through the
- * FD_TO_HANDLE IOCTL) and closed the file descriptor of the exported
- * (through the HANDLE_TO_FD IOCTL) dma_buf, and all kernel-internal references
- * are also gone, then the dma_buf gets destroyed.  This can also happen as a
- * part of the clean up procedure in the drm_release() function if userspace
- * fails to properly clean up.  Note that both the kernel and userspace (by
- * keeeping the PRIME file descriptors open) can hold references onto a
- * &dma_buf.
- *
- * Thus the chain of references always flows in one direction
- * (avoiding loops): importing_gem -> dmabuf -> exporting_gem
- *
- * Self-importing: if userspace is using PRIME as a replacement for flink
- * then it will get a fd->handle request for a GEM object that it created.
- * Drivers should detect this situation and return back the gem object
- * from the dma-buf private.  Prime will do this automatically for drivers that
- * use the drm_gem_prime_{import,export} helpers.
- *
- * GEM struct &dma_buf_ops symbols are now exported. They can be resued by
- * drivers which implement GEM interface.
+/**
+ * DOC: overview and lifetime rules
+ *
+ * Similar to GEM global names, PRIME file descriptors are also used to share
+ * buffer objects across processes. They offer additional security: as file
+ * descriptors must be explicitly sent over UNIX domain sockets to be shared
+ * between applications, they can't be guessed like the globally unique GEM
+ * names.
+ *
+ * Drivers that support the PRIME API must set the DRIVER_PRIME bit in the
+ * &drm_driver.driver_features field, and implement the
+ * &drm_driver.prime_handle_to_fd and &drm_driver.prime_fd_to_handle 
operations.
+ * GEM based drivers must use drm_gem_prime_handle_to_fd() an
+ * drm_gem_prime_fd_to_handle() to implement these. For GEM based drivers the
+ * actual driver interfaces is provided through the 
&drm_gem_object_funcs.export
+ * and &drm_driver.gem_prime_import hooks.
+ *
+ * &dma_buf_ops implementations for GEM drivers are all individually exported
+ * for drivers which need to overwrite or reimplement some of them.
+ *
+ * Reference Counting for GEM Drivers
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * On the export the &dma_buf holds a reference to the exported buffer object,
+ * usually a &drm_gem_object. It takes this reference in the PRIME_HANDLE_TO_FD
+ * IOCTL, when it first calls &drm_gem_object_funcs.export
+ * and stores the exporting GEM object in the &dma_buf.priv field. This
+ * reference needs to be released when the final reference to the &dma_buf
+ * itself is dropped and its &dma_buf_ops.release function is called.  For
+ * GEM-based drivers, the &dma_buf should be exported using
+ * drm_gem_dmabuf_export() and then released by drm_gem_dmabuf_release().
+ *
+ * Thus the chain of references always flows in one direction, avoiding loops:
+ * importing GEM object -> dma-buf -> exported GEM bo. A further complication
+ * are the lookup caches for import and export. These are required to guarantee
+ * that any given object will always have only one uniqe userspace handle. This
+ * is required to allow userspace to detect duplicated imports, since some GEM
+ * drivers do fail command submissions if a given buffer object is listed more
+ * than once. These import and export caches in &drm_prime_file_private only
+ * retain a weak reference, which is cleaned up when the corresponding object 
is
+ * released.
+ *
+ * Self-importing: If userspace is using PRIME as a replacement for flink then
+ * it will get a fd->handle request for a GEM object that it created.  Drivers
+ * should detect this situation and return back the underlying object from the
+ * dma-buf private. For GEM based drivers this is handled in
+ * drm_gem_prime_import() already.
  */
 
 struct drm_prime_member {
@@ -181,42 +187,6 @@ static int drm_prime_lookup_buf_handle(struct 
drm_prime_file_private *prime_fpri
        return -ENOENT;
 }
 
-/**
- * drm_gem_map_attach - dma_buf attach implementation for GEM
- * @dma_buf: buffer to attach device to
- * @attach: buffer attachment data
- *
- * Calls &drm_driver.gem_prime_pin for device specific handling. This can be
- * used as the &dma_buf_ops.attach callback.
- *
- * Returns 0 on success, negative error code on failure.
- */
-int drm_gem_map_attach(struct dma_buf *dma_buf,
-                      struct dma_buf_attachment *attach)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
-
-       return drm_gem_pin(obj);
-}
-EXPORT_SYMBOL(drm_gem_map_attach);
-
-/**
- * drm_gem_map_detach - dma_buf detach implementation for GEM
- * @dma_buf: buffer to detach from
- * @attach: attachment to be detached
- *
- * Cleans up &dma_buf_attachment. This can be used as the &dma_buf_ops.detach
- * callback.
- */
-void drm_gem_map_detach(struct dma_buf *dma_buf,
-                       struct dma_buf_attachment *attach)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
-
-       drm_gem_unpin(obj);
-}
-EXPORT_SYMBOL(drm_gem_map_detach);
-
 void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private 
*prime_fpriv,
                                        struct dma_buf *dma_buf)
 {
@@ -242,67 +212,21 @@ void drm_prime_remove_buf_handle_locked(struct 
drm_prime_file_private *prime_fpr
        }
 }
 
-/**
- * drm_gem_map_dma_buf - map_dma_buf implementation for GEM
- * @attach: attachment whose scatterlist is to be returned
- * @dir: direction of DMA transfer
- *
- * Calls &drm_driver.gem_prime_get_sg_table and then maps the scatterlist. This
- * can be used as the &dma_buf_ops.map_dma_buf callback.
- *
- * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
- * on error. May return -EINTR if it is interrupted by a signal.
- */
-
-struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
-                                    enum dma_data_direction dir)
+void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
 {
-       struct drm_gem_object *obj = attach->dmabuf->priv;
-       struct sg_table *sgt;
-
-       if (WARN_ON(dir == DMA_NONE))
-               return ERR_PTR(-EINVAL);
-
-       if (obj->funcs)
-               sgt = obj->funcs->get_sg_table(obj);
-       else
-               sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
-
-       if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
-                             DMA_ATTR_SKIP_CPU_SYNC)) {
-               sg_free_table(sgt);
-               kfree(sgt);
-               sgt = ERR_PTR(-ENOMEM);
-       }
-
-       return sgt;
+       mutex_init(&prime_fpriv->lock);
+       prime_fpriv->dmabufs = RB_ROOT;
+       prime_fpriv->handles = RB_ROOT;
 }
-EXPORT_SYMBOL(drm_gem_map_dma_buf);
 
-/**
- * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM
- * @attach: attachment to unmap buffer from
- * @sgt: scatterlist info of the buffer to unmap
- * @dir: direction of DMA transfer
- *
- * This can be used as the &dma_buf_ops.unmap_dma_buf callback.
- */
-void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
-                          struct sg_table *sgt,
-                          enum dma_data_direction dir)
+void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
 {
-       if (!sgt)
-               return;
-
-       dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
-                          DMA_ATTR_SKIP_CPU_SYNC);
-       sg_free_table(sgt);
-       kfree(sgt);
+       /* by now drm_gem_release should've made sure the list is empty */
+       WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
 }
-EXPORT_SYMBOL(drm_gem_unmap_dma_buf);
 
 /**
- * drm_gem_dmabuf_export - dma_buf export implementation for GEM
+ * drm_gem_dmabuf_export - &dma_buf export implementation for GEM
  * @dev: parent device for the exported dmabuf
  * @exp_info: the export information used by dma_buf_export()
  *
@@ -330,11 +254,11 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device 
*dev,
 EXPORT_SYMBOL(drm_gem_dmabuf_export);
 
 /**
- * drm_gem_dmabuf_release - dma_buf release implementation for GEM
+ * drm_gem_dmabuf_release - &dma_buf release implementation for GEM
  * @dma_buf: buffer to be released
  *
  * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers
- * must use this in their dma_buf ops structure as the release callback.
+ * must use this in their &dma_buf_ops structure as the release callback.
  * drm_gem_dmabuf_release() should be used in conjunction with
  * drm_gem_dmabuf_export().
  */
@@ -351,128 +275,101 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
 EXPORT_SYMBOL(drm_gem_dmabuf_release);
 
 /**
- * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM
- * @dma_buf: buffer to be mapped
- *
- * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap
- * callback.
+ * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
+ * @dev: dev to export the buffer from
+ * @file_priv: drm file-private structure
+ * @prime_fd: fd id of the dma-buf which should be imported
+ * @handle: pointer to storage for the handle of the imported buffer object
  *
- * Returns the kernel virtual address.
+ * This is the PRIME import function which must be used mandatorily by GEM
+ * drivers to ensure correct lifetime management of the underlying GEM object.
+ * The actual importing of GEM object from the dma-buf is done through the
+ * &drm_driver.gem_import_export driver callback.
  */
-void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+                              struct drm_file *file_priv, int prime_fd,
+                              uint32_t *handle)
 {
-       struct drm_gem_object *obj = dma_buf->priv;
-       void *vaddr;
+       struct dma_buf *dma_buf;
+       struct drm_gem_object *obj;
+       int ret;
 
-       vaddr = drm_gem_vmap(obj);
-       if (IS_ERR(vaddr))
-               vaddr = NULL;
+       dma_buf = dma_buf_get(prime_fd);
+       if (IS_ERR(dma_buf))
+               return PTR_ERR(dma_buf);
 
-       return vaddr;
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
+       mutex_lock(&file_priv->prime.lock);
 
-/**
- * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM
- * @dma_buf: buffer to be unmapped
- * @vaddr: the virtual address of the buffer
- *
- * Releases a kernel virtual mapping. This can be used as the
- * &dma_buf_ops.vunmap callback.
- */
-void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
+       ret = drm_prime_lookup_buf_handle(&file_priv->prime,
+                       dma_buf, handle);
+       if (ret == 0)
+               goto out_put;
 
-       drm_gem_vunmap(obj, vaddr);
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
+       /* never seen this one, need to import */
+       mutex_lock(&dev->object_name_lock);
+       if (dev->driver->gem_prime_import)
+               obj = dev->driver->gem_prime_import(dev, dma_buf);
+       else
+               obj = drm_gem_prime_import(dev, dma_buf);
+       if (IS_ERR(obj)) {
+               ret = PTR_ERR(obj);
+               goto out_unlock;
+       }
 
-/**
- * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM
- * @dma_buf: buffer to be mapped
- * @vma: virtual address range
- *
- * Provides memory mapping for the buffer. This can be used as the
- * &dma_buf_ops.mmap callback.
- *
- * Returns 0 on success or a negative error code on failure.
- */
-int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
-{
-       struct drm_gem_object *obj = dma_buf->priv;
-       struct drm_device *dev = obj->dev;
+       if (obj->dma_buf) {
+               WARN_ON(obj->dma_buf != dma_buf);
+       } else {
+               obj->dma_buf = dma_buf;
+               get_dma_buf(dma_buf);
+       }
 
-       if (!dev->driver->gem_prime_mmap)
-               return -ENOSYS;
+       /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
+       ret = drm_gem_handle_create_tail(file_priv, obj, handle);
+       drm_gem_object_put_unlocked(obj);
+       if (ret)
+               goto out_put;
 
-       return dev->driver->gem_prime_mmap(obj, vma);
-}
-EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
+       ret = drm_prime_add_buf_handle(&file_priv->prime,
+                       dma_buf, *handle);
+       mutex_unlock(&file_priv->prime.lock);
+       if (ret)
+               goto fail;
 
-static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
-       .cache_sgt_mapping = true,
-       .attach = drm_gem_map_attach,
-       .detach = drm_gem_map_detach,
-       .map_dma_buf = drm_gem_map_dma_buf,
-       .unmap_dma_buf = drm_gem_unmap_dma_buf,
-       .release = drm_gem_dmabuf_release,
-       .mmap = drm_gem_dmabuf_mmap,
-       .vmap = drm_gem_dmabuf_vmap,
-       .vunmap = drm_gem_dmabuf_vunmap,
-};
+       dma_buf_put(dma_buf);
 
-/**
- * DOC: PRIME Helpers
- *
- * Drivers can implement @gem_prime_export and @gem_prime_import in terms of
- * simpler APIs by using the helper functions @drm_gem_prime_export and
- * @drm_gem_prime_import.  These functions implement dma-buf support in terms 
of
- * six lower-level driver callbacks:
- *
- * Export callbacks:
- *
- *  * @gem_prime_pin (optional): prepare a GEM object for exporting
- *  * @gem_prime_get_sg_table: provide a scatter/gather table of pinned pages
- *  * @gem_prime_vmap: vmap a buffer exported by your driver
- *  * @gem_prime_vunmap: vunmap a buffer exported by your driver
- *  * @gem_prime_mmap (optional): mmap a buffer exported by your driver
- *
- * Import callback:
- *
- *  * @gem_prime_import_sg_table (import): produce a GEM object from another
- *    driver's scatter/gather table
- */
+       return 0;
 
-/**
- * drm_gem_prime_export - helper library implementation of the export callback
- * @dev: drm_device to export from
- * @obj: GEM object to export
- * @flags: flags like DRM_CLOEXEC and DRM_RDWR
- *
- * This is the implementation of the gem_prime_export functions for GEM drivers
- * using the PRIME helpers.
- */
-struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-                                    struct drm_gem_object *obj,
-                                    int flags)
+fail:
+       /* hmm, if driver attached, we are relying on the free-object path
+        * to detach.. which seems ok..
+        */
+       drm_gem_handle_delete(file_priv, *handle);
+       dma_buf_put(dma_buf);
+       return ret;
+
+out_unlock:
+       mutex_unlock(&dev->object_name_lock);
+out_put:
+       mutex_unlock(&file_priv->prime.lock);
+       dma_buf_put(dma_buf);
+       return ret;
+}
+EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
+
+int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
 {
-       struct dma_buf_export_info exp_info = {
-               .exp_name = KBUILD_MODNAME, /* white lie for debug */
-               .owner = dev->driver->fops->owner,
-               .ops = &drm_gem_prime_dmabuf_ops,
-               .size = obj->size,
-               .flags = flags,
-               .priv = obj,
-               .resv = obj->resv,
-       };
+       struct drm_prime_handle *args = data;
 
-       if (dev->driver->gem_prime_res_obj)
-               exp_info.resv = dev->driver->gem_prime_res_obj(obj);
+       if (!drm_core_check_feature(dev, DRIVER_PRIME))
+               return -EOPNOTSUPP;
 
-       return drm_gem_dmabuf_export(dev, &exp_info);
+       if (!dev->driver->prime_fd_to_handle)
+               return -ENOSYS;
+
+       return dev->driver->prime_fd_to_handle(dev, file_priv,
+                       args->fd, &args->handle);
 }
-EXPORT_SYMBOL(drm_gem_prime_export);
 
 static struct dma_buf *export_and_register_object(struct drm_device *dev,
                                                  struct drm_gem_object *obj,
@@ -521,7 +418,7 @@ static struct dma_buf *export_and_register_object(struct 
drm_device *dev,
  * This is the PRIME export function which must be used mandatorily by GEM
  * drivers to ensure correct lifetime management of the underlying GEM object.
  * The actual exporting from GEM object to a dma-buf is done through the
- * gem_prime_export driver callback.
+ * &drm_driver.gem_prime_export driver callback.
  */
 int drm_gem_prime_handle_to_fd(struct drm_device *dev,
                               struct drm_file *file_priv, uint32_t handle,
@@ -610,6 +507,198 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
 
+int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       struct drm_prime_handle *args = data;
+
+       if (!drm_core_check_feature(dev, DRIVER_PRIME))
+               return -EOPNOTSUPP;
+
+       if (!dev->driver->prime_handle_to_fd)
+               return -ENOSYS;
+
+       /* check flags are valid */
+       if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR))
+               return -EINVAL;
+
+       return dev->driver->prime_handle_to_fd(dev, file_priv,
+                       args->handle, args->flags, &args->fd);
+}
+
+/**
+ * DOC: PRIME Helpers
+ *
+ * Drivers can implement &drm_gem_object_funcs.export and
+ * &drm_driver.gem_prime_import in terms of simpler APIs by using the helper
+ * functions drm_gem_prime_export() and drm_gem_prime_import().  These 
functions
+ * implement dma-buf support in terms of some lower-level helpers, which are
+ * again exported for drivers to use individually:
+ *
+ * Exporting buffers
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * Optional pinning of buffers is handled at dma-buf attach and detach time in
+ * drm_gem_map_attach() and drm_gem_map_detach(). Backing storage itself is
+ * handled by drm_gem_map_dma_buf() and drm_gem_unmap_dma_buf(), which relies 
on
+ * &drm_gem_object_funcs.get_sg_table.
+ *
+ * For kernel-internal access there's drm_gem_dmabuf_vmap() and
+ * drm_gem_dmabuf_vunmap(). Userspace mmap support is provided by
+ * drm_gem_dmabuf_mmap().
+ *
+ * Note that these export helpers can only be used if the underlying backing
+ * storage is fully coherent and either permanently pinned, or it is safe to 
pin
+ * it indefinitely.
+ *
+ * FIXME: The underlying helper functions are named rather inconsistently.
+ *
+ * Exporting buffers
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * Importing dma-bufs using drm_gem_prime_import() relies on
+ * &drm_driver.gem_prime_import_sg_table.
+ *
+ * Note that similarly to the export helpers this permanently pins the
+ * underlying backing storage. Which is ok for scanout, but is not the best
+ * option for sharing lots of buffers for rendering.
+ */
+
+/**
+ * drm_gem_map_attach - dma_buf attach implementation for GEM
+ * @dma_buf: buffer to attach device to
+ * @attach: buffer attachment data
+ *
+ * Calls &drm_gem_object_funcs.pin for device specific handling. This can be
+ * used as the &dma_buf_ops.attach callback. Must be used together with
+ * drm_gem_map_detach().
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+int drm_gem_map_attach(struct dma_buf *dma_buf,
+                      struct dma_buf_attachment *attach)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+
+       return drm_gem_pin(obj);
+}
+EXPORT_SYMBOL(drm_gem_map_attach);
+
+/**
+ * drm_gem_map_detach - dma_buf detach implementation for GEM
+ * @dma_buf: buffer to detach from
+ * @attach: attachment to be detached
+ *
+ * Calls &drm_gem_object_funcs.pin for device specific handling.  Cleans up
+ * &dma_buf_attachment from drm_gem_map_attach(). This can be used as the
+ * &dma_buf_ops.detach callback.
+ */
+void drm_gem_map_detach(struct dma_buf *dma_buf,
+                       struct dma_buf_attachment *attach)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+
+       drm_gem_unpin(obj);
+}
+EXPORT_SYMBOL(drm_gem_map_detach);
+
+/**
+ * drm_gem_map_dma_buf - map_dma_buf implementation for GEM
+ * @attach: attachment whose scatterlist is to be returned
+ * @dir: direction of DMA transfer
+ *
+ * Calls &drm_gem_object_funcs.get_sg_table and then maps the scatterlist. This
+ * can be used as the &dma_buf_ops.map_dma_buf callback. Should be used 
together
+ * with drm_gem_unmap_dma_buf().
+ *
+ * Returns:sg_table containing the scatterlist to be returned; returns ERR_PTR
+ * on error. May return -EINTR if it is interrupted by a signal.
+ */
+struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
+                                    enum dma_data_direction dir)
+{
+       struct drm_gem_object *obj = attach->dmabuf->priv;
+       struct sg_table *sgt;
+
+       if (WARN_ON(dir == DMA_NONE))
+               return ERR_PTR(-EINVAL);
+
+       if (obj->funcs)
+               sgt = obj->funcs->get_sg_table(obj);
+       else
+               sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
+
+       if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
+                             DMA_ATTR_SKIP_CPU_SYNC)) {
+               sg_free_table(sgt);
+               kfree(sgt);
+               sgt = ERR_PTR(-ENOMEM);
+       }
+
+       return sgt;
+}
+EXPORT_SYMBOL(drm_gem_map_dma_buf);
+
+/**
+ * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM
+ * @attach: attachment to unmap buffer from
+ * @sgt: scatterlist info of the buffer to unmap
+ * @dir: direction of DMA transfer
+ *
+ * This can be used as the &dma_buf_ops.unmap_dma_buf callback.
+ */
+void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
+                          struct sg_table *sgt,
+                          enum dma_data_direction dir)
+{
+       if (!sgt)
+               return;
+
+       dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
+                          DMA_ATTR_SKIP_CPU_SYNC);
+       sg_free_table(sgt);
+       kfree(sgt);
+}
+EXPORT_SYMBOL(drm_gem_unmap_dma_buf);
+
+/**
+ * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM
+ * @dma_buf: buffer to be mapped
+ *
+ * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap
+ * callback. Calls into &drm_gem_object_funcs.vmap for device specific 
handling.
+ *
+ * Returns the kernel virtual address.
+ */
+void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       void *vaddr;
+
+       vaddr = drm_gem_vmap(obj);
+       if (IS_ERR(vaddr))
+               vaddr = NULL;
+
+       return vaddr;
+}
+EXPORT_SYMBOL(drm_gem_dmabuf_vmap);
+
+/**
+ * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM
+ * @dma_buf: buffer to be unmapped
+ * @vaddr: the virtual address of the buffer
+ *
+ * Releases a kernel virtual mapping. This can be used as the
+ * &dma_buf_ops.vunmap callback. Calls into &drm_gem_object_funcs.vunmap for 
device specific handling.
+ */
+void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+
+       drm_gem_vunmap(obj, vaddr);
+}
+EXPORT_SYMBOL(drm_gem_dmabuf_vunmap);
+
 /**
  * drm_gem_prime_mmap - PRIME mmap function for GEM drivers
  * @obj: GEM object
@@ -656,15 +745,121 @@ int drm_gem_prime_mmap(struct drm_gem_object *obj, 
struct vm_area_struct *vma)
 }
 EXPORT_SYMBOL(drm_gem_prime_mmap);
 
+/**
+ * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM
+ * @dma_buf: buffer to be mapped
+ * @vma: virtual address range
+ *
+ * Provides memory mapping for the buffer. This can be used as the
+ * &dma_buf_ops.mmap callback. It just forwards to &drm_driver.gem_prime_mmap,
+ * which should be set to drm_gem_prime_mmap().
+ *
+ * FIXME: There's really no point to this wrapper, drivers which need anything
+ * else but drm_gem_prime_mmap can roll their own &dma_buf_ops.mmap callback.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->dev;
+
+       if (!dev->driver->gem_prime_mmap)
+               return -ENOSYS;
+
+       return dev->driver->gem_prime_mmap(obj, vma);
+}
+EXPORT_SYMBOL(drm_gem_dmabuf_mmap);
+
+static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
+       .cache_sgt_mapping = true,
+       .attach = drm_gem_map_attach,
+       .detach = drm_gem_map_detach,
+       .map_dma_buf = drm_gem_map_dma_buf,
+       .unmap_dma_buf = drm_gem_unmap_dma_buf,
+       .release = drm_gem_dmabuf_release,
+       .mmap = drm_gem_dmabuf_mmap,
+       .vmap = drm_gem_dmabuf_vmap,
+       .vunmap = drm_gem_dmabuf_vunmap,
+};
+
+/**
+ * drm_prime_pages_to_sg - converts a page array into an sg list
+ * @pages: pointer to the array of page pointers to convert
+ * @nr_pages: length of the page vector
+ *
+ * This helper creates an sg table object from a set of pages
+ * the driver is responsible for mapping the pages into the
+ * importers address space for use with dma_buf itself.
+ *
+ * This is useful for implementing &drm_gem_object_funcs.get_sg_table.
+ */
+struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int 
nr_pages)
+{
+       struct sg_table *sg = NULL;
+       int ret;
+
+       sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+       if (!sg) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
+                               nr_pages << PAGE_SHIFT, GFP_KERNEL);
+       if (ret)
+               goto out;
+
+       return sg;
+out:
+       kfree(sg);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(drm_prime_pages_to_sg);
+
+/**
+ * drm_gem_prime_export - helper library implementation of the export callback
+ * @dev: drm_device to export from
+ * @obj: GEM object to export
+ * @flags: flags like DRM_CLOEXEC and DRM_RDWR
+ *
+ * This is the implementation of the &drm_gem_object_funcs.export functions 
for GEM drivers
+ * using the PRIME helpers.
+ */
+struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
+                                    struct drm_gem_object *obj,
+                                    int flags)
+{
+       struct dma_buf_export_info exp_info = {
+               .exp_name = KBUILD_MODNAME, /* white lie for debug */
+               .owner = dev->driver->fops->owner,
+               .ops = &drm_gem_prime_dmabuf_ops,
+               .size = obj->size,
+               .flags = flags,
+               .priv = obj,
+               .resv = obj->resv,
+       };
+
+       if (dev->driver->gem_prime_res_obj)
+               exp_info.resv = dev->driver->gem_prime_res_obj(obj);
+
+       return drm_gem_dmabuf_export(dev, &exp_info);
+}
+EXPORT_SYMBOL(drm_gem_prime_export);
+
 /**
  * drm_gem_prime_import_dev - core implementation of the import callback
  * @dev: drm_device to import into
  * @dma_buf: dma-buf object to import
  * @attach_dev: struct device to dma_buf attach
  *
- * This is the core of drm_gem_prime_import. It's designed to be called by
- * drivers who want to use a different device structure than dev->dev for
- * attaching via dma_buf.
+ * This is the core of drm_gem_prime_import(). It's designed to be called by
+ * drivers who want to use a different device structure than &drm_device.dev 
for
+ * attaching via dma_buf. This function calls
+ * &drm_driver.gem_prime_import_sg_table internally.
+ *
+ * Drivers must arrange to call drm_prime_gem_destroy() from their
+ * &drm_gem_object_funcs.free hook when using this function.
  */
 struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
                                            struct dma_buf *dma_buf,
@@ -728,7 +923,11 @@ EXPORT_SYMBOL(drm_gem_prime_import_dev);
  * @dma_buf: dma-buf object to import
  *
  * This is the implementation of the gem_prime_import functions for GEM drivers
- * using the PRIME helpers.
+ * using the PRIME helpers. Drivers can use this as their
+ * &drm_driver.gem_prime_import implementation.
+ *
+ * Drivers must arrange to call drm_prime_gem_destroy() from their
+ * &drm_gem_object_funcs.free hook when using this function.
  */
 struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
                                            struct dma_buf *dma_buf)
@@ -737,154 +936,6 @@ struct drm_gem_object *drm_gem_prime_import(struct 
drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_prime_import);
 
-/**
- * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
- * @dev: dev to export the buffer from
- * @file_priv: drm file-private structure
- * @prime_fd: fd id of the dma-buf which should be imported
- * @handle: pointer to storage for the handle of the imported buffer object
- *
- * This is the PRIME import function which must be used mandatorily by GEM
- * drivers to ensure correct lifetime management of the underlying GEM object.
- * The actual importing of GEM object from the dma-buf is done through the
- * gem_import_export driver callback.
- */
-int drm_gem_prime_fd_to_handle(struct drm_device *dev,
-                              struct drm_file *file_priv, int prime_fd,
-                              uint32_t *handle)
-{
-       struct dma_buf *dma_buf;
-       struct drm_gem_object *obj;
-       int ret;
-
-       dma_buf = dma_buf_get(prime_fd);
-       if (IS_ERR(dma_buf))
-               return PTR_ERR(dma_buf);
-
-       mutex_lock(&file_priv->prime.lock);
-
-       ret = drm_prime_lookup_buf_handle(&file_priv->prime,
-                       dma_buf, handle);
-       if (ret == 0)
-               goto out_put;
-
-       /* never seen this one, need to import */
-       mutex_lock(&dev->object_name_lock);
-       if (dev->driver->gem_prime_import)
-               obj = dev->driver->gem_prime_import(dev, dma_buf);
-       else
-               obj = drm_gem_prime_import(dev, dma_buf);
-       if (IS_ERR(obj)) {
-               ret = PTR_ERR(obj);
-               goto out_unlock;
-       }
-
-       if (obj->dma_buf) {
-               WARN_ON(obj->dma_buf != dma_buf);
-       } else {
-               obj->dma_buf = dma_buf;
-               get_dma_buf(dma_buf);
-       }
-
-       /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
-       ret = drm_gem_handle_create_tail(file_priv, obj, handle);
-       drm_gem_object_put_unlocked(obj);
-       if (ret)
-               goto out_put;
-
-       ret = drm_prime_add_buf_handle(&file_priv->prime,
-                       dma_buf, *handle);
-       mutex_unlock(&file_priv->prime.lock);
-       if (ret)
-               goto fail;
-
-       dma_buf_put(dma_buf);
-
-       return 0;
-
-fail:
-       /* hmm, if driver attached, we are relying on the free-object path
-        * to detach.. which seems ok..
-        */
-       drm_gem_handle_delete(file_priv, *handle);
-       dma_buf_put(dma_buf);
-       return ret;
-
-out_unlock:
-       mutex_unlock(&dev->object_name_lock);
-out_put:
-       mutex_unlock(&file_priv->prime.lock);
-       dma_buf_put(dma_buf);
-       return ret;
-}
-EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
-
-int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv)
-{
-       struct drm_prime_handle *args = data;
-
-       if (!drm_core_check_feature(dev, DRIVER_PRIME))
-               return -EOPNOTSUPP;
-
-       if (!dev->driver->prime_handle_to_fd)
-               return -ENOSYS;
-
-       /* check flags are valid */
-       if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR))
-               return -EINVAL;
-
-       return dev->driver->prime_handle_to_fd(dev, file_priv,
-                       args->handle, args->flags, &args->fd);
-}
-
-int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv)
-{
-       struct drm_prime_handle *args = data;
-
-       if (!drm_core_check_feature(dev, DRIVER_PRIME))
-               return -EOPNOTSUPP;
-
-       if (!dev->driver->prime_fd_to_handle)
-               return -ENOSYS;
-
-       return dev->driver->prime_fd_to_handle(dev, file_priv,
-                       args->fd, &args->handle);
-}
-
-/**
- * drm_prime_pages_to_sg - converts a page array into an sg list
- * @pages: pointer to the array of page pointers to convert
- * @nr_pages: length of the page vector
- *
- * This helper creates an sg table object from a set of pages
- * the driver is responsible for mapping the pages into the
- * importers address space for use with dma_buf itself.
- */
-struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int 
nr_pages)
-{
-       struct sg_table *sg = NULL;
-       int ret;
-
-       sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
-       if (!sg) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
-                               nr_pages << PAGE_SHIFT, GFP_KERNEL);
-       if (ret)
-               goto out;
-
-       return sg;
-out:
-       kfree(sg);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL(drm_prime_pages_to_sg);
-
 /**
  * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
  * @sgt: scatter-gather table to convert
@@ -894,6 +945,9 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg);
  *
  * Exports an sg table into an array of pages and addresses. This is currently
  * required by the TTM driver in order to do correct fault handling.
+ *
+ * Drivers can use this in their &drm_driver.gem_prime_import_sg_table
+ * implementation.
  */
 int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
                                     dma_addr_t *addrs, int max_entries)
@@ -934,7 +988,7 @@ EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
  * @sg: the sg-table which was pinned at import time
  *
  * This is the cleanup functions which GEM drivers need to call when they use
- * @drm_gem_prime_import to import dma-bufs.
+ * drm_gem_prime_import() or drm_gem_prime_import_dev() to import dma-bufs.
  */
 void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
 {
@@ -949,16 +1003,3 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, 
struct sg_table *sg)
        dma_buf_put(dma_buf);
 }
 EXPORT_SYMBOL(drm_prime_gem_destroy);
-
-void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
-{
-       mutex_init(&prime_fpriv->lock);
-       prime_fpriv->dmabufs = RB_ROOT;
-       prime_fpriv->handles = RB_ROOT;
-}
-
-void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
-{
-       /* by now drm_gem_release should've made sure the list is empty */
-       WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
-}
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 5c4fc0ddc863..5e1ba16d19c6 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -505,21 +505,25 @@ struct drm_driver {
         * @gem_free_object: deconstructor for drm_gem_objects
         *
         * This is deprecated and should not be used by new drivers. Use
-        * @gem_free_object_unlocked instead.
+        * &drm_gem_object_funcs.free instead.
         */
        void (*gem_free_object) (struct drm_gem_object *obj);
 
        /**
         * @gem_free_object_unlocked: deconstructor for drm_gem_objects
         *
-        * This is for drivers which are not encumbered with 
&drm_device.struct_mutex
-        * legacy locking schemes. Use this hook instead of @gem_free_object.
+        * This is deprecated and should not be used by new drivers. Use
+        * &drm_gem_object_funcs.free instead.
+        * Compared to @gem_free_object this is not encumbered with
+        * &drm_device.struct_mutex legacy locking schemes.
         */
        void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
 
        /**
         * @gem_open_object:
         *
+        * This callback is deprecated in favour of &drm_gem_object_funcs.open.
+        *
         * Driver hook called upon gem handle creation
         */
        int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
@@ -527,6 +531,8 @@ struct drm_driver {
        /**
         * @gem_close_object:
         *
+        * This callback is deprecated in favour of &drm_gem_object_funcs.close.
+        *
         * Driver hook called upon gem handle release
         */
        void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
@@ -534,6 +540,9 @@ struct drm_driver {
        /**
         * @gem_print_info:
         *
+        * This callback is deprecated in favour of
+        * &drm_gem_object_funcs.print_info.
+        *
         * If driver subclasses struct &drm_gem_object, it can implement this
         * optional hook for printing additional driver specific info.
         *
@@ -548,56 +557,120 @@ struct drm_driver {
        /**
         * @gem_create_object: constructor for gem objects
         *
-        * Hook for allocating the GEM object struct, for use by core
-        * helpers.
+        * Hook for allocating the GEM object struct, for use by the CMA and
+        * SHMEM GEM helpers.
         */
        struct drm_gem_object *(*gem_create_object)(struct drm_device *dev,
                                                    size_t size);
-
-       /* prime: */
        /**
         * @prime_handle_to_fd:
         *
-        * export handle -> fd (see drm_gem_prime_handle_to_fd() helper)
+        * Main PRIME export function. Should be implented with
+        * drm_gem_prime_handle_to_fd() for GEM based drivers.
+        *
+        * For an in-depth discussion see :ref:`PRIME buffer sharing
+        * documentation <prime_buffer_sharing>`.
         */
        int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file 
*file_priv,
                                uint32_t handle, uint32_t flags, int *prime_fd);
        /**
         * @prime_fd_to_handle:
         *
-        * import fd -> handle (see drm_gem_prime_fd_to_handle() helper)
+        * Main PRIME import function. Should be implented with
+        * drm_gem_prime_fd_to_handle() for GEM based drivers.
+        *
+        * For an in-depth discussion see :ref:`PRIME buffer sharing
+        * documentation <prime_buffer_sharing>`.
         */
        int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file 
*file_priv,
                                int prime_fd, uint32_t *handle);
        /**
         * @gem_prime_export:
         *
-        * export GEM -> dmabuf
-        *
-        * This defaults to drm_gem_prime_export() if not set.
+        * Export hook for GEM drivers. Deprecated in favour of
+        * &drm_gem_object_funcs.export.
         */
        struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
                                struct drm_gem_object *obj, int flags);
        /**
         * @gem_prime_import:
         *
-        * import dmabuf -> GEM
+        * Import hook for GEM drivers.
         *
         * This defaults to drm_gem_prime_import() if not set.
         */
        struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
                                struct dma_buf *dma_buf);
+
+       /**
+        * @gem_prime_pin:
+        *
+        * Deprecated hook in favour of &drm_gem_object_funcs.pin.
+        */
        int (*gem_prime_pin)(struct drm_gem_object *obj);
+
+       /**
+        * @gem_prime_unpin:
+        *
+        * Deprecated hook in favour of &drm_gem_object_funcs.unpin.
+        */
        void (*gem_prime_unpin)(struct drm_gem_object *obj);
+
+
+       /**
+        * @gem_prime_get_sg_table:
+        *
+        * Deprecated hook in favour of &drm_gem_object_funcs.get_sg_table.
+        */
+       struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj);
+
+       /**
+        * @gem_prime_res_obj:
+        *
+        * Optional hook to look up the &reservation_object for an buffer when
+        * exporting it.
+        *
+        * FIXME: This hook is deprecated. User of this hook should be replaced
+        * by setting &drm_gem_object.resv instead.
+        */
        struct reservation_object * (*gem_prime_res_obj)(
                                struct drm_gem_object *obj);
-       struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj);
+
+       /**
+        * @gem_prime_import_sg_table:
+        *
+        * Optional hook used by the PRIME helper functions
+        * drm_gem_prime_import() respectively drm_gem_prime_import_dev().
+        */
        struct drm_gem_object *(*gem_prime_import_sg_table)(
                                struct drm_device *dev,
                                struct dma_buf_attachment *attach,
                                struct sg_table *sgt);
+       /**
+        * @gem_prime_vmap:
+        *
+        * Deprecated vmap hook for GEM drivers. Please use
+        * &drm_gem_object_funcs.vmap instead.
+        */
        void *(*gem_prime_vmap)(struct drm_gem_object *obj);
+
+       /**
+        * @gem_prime_vunmap:
+        *
+        * Deprecated vunmap hook for GEM drivers. Please use
+        * &drm_gem_object_funcs.vunmap instead.
+        */
        void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr);
+
+       /**
+        * @gem_prime_mmap:
+        *
+        * mmap hook for GEM drivers, used to implement dma-buf mmap in the
+        * PRIME helpers.
+        *
+        * FIXME: There's way too much duplication going on here, and also moved
+        * to &drm_gem_object_funcs.
+        */
        int (*gem_prime_mmap)(struct drm_gem_object *obj,
                                struct vm_area_struct *vma);
 
@@ -665,6 +738,9 @@ struct drm_driver {
 
        /**
         * @gem_vm_ops: Driver private ops for this object
+        *
+        * For GEM driver this is deprecated in favour of
+        * &drm_gem_object_funcs.vm_ops.
         */
        const struct vm_operations_struct *gem_vm_ops;
 
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index a9121fe66ea2..9af88238ee5c 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -101,7 +101,7 @@ struct drm_gem_object_funcs {
        /**
         * @pin:
         *
-        * Pin backing buffer in memory.
+        * Pin backing buffer in memory. Used by the drm_gem_map_attach helper.
         *
         * This callback is optional.
         */
@@ -110,7 +110,7 @@ struct drm_gem_object_funcs {
        /**
         * @unpin:
         *
-        * Unpin backing buffer.
+        * Unpin backing buffer. Used by the drm_gem_map_detach() helper.
         *
         * This callback is optional.
         */
@@ -120,16 +120,21 @@ struct drm_gem_object_funcs {
         * @get_sg_table:
         *
         * Returns a Scatter-Gather table representation of the buffer.
-        * Used when exporting a buffer.
+        * Used when exporting a buffer by the drm_gem_map_dma_buf() helper.
+        * Releasing is done by calling dma_unmap_sg_attrs() and sg_free_table()
+        * in drm_gem_unmap_buf(), therefore these helpers and this callback
+        * here cannot be used for sg tables pointing at driver private memory
+        * ranges.
         *
-        * This callback is mandatory if buffer export is supported.
+        * See also drm_prime_pages_to_sg().
         */
        struct sg_table *(*get_sg_table)(struct drm_gem_object *obj);
 
        /**
         * @vmap:
         *
-        * Returns a virtual address for the buffer.
+        * Returns a virtual address for the buffer. Used by the
+        * drm_gem_dmabuf_vmap() helper.
         *
         * This callback is optional.
         */
@@ -138,7 +143,8 @@ struct drm_gem_object_funcs {
        /**
         * @vunmap:
         *
-        * Releases the the address previously returned by @vmap.
+        * Releases the the address previously returned by @vmap. Used by the
+        * drm_gem_dmabuf_vunmap() helper.
         *
         * This callback is optional.
         */
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
index b03731a3f079..ee32b07f3eb0 100644
--- a/include/drm/drm_prime.h
+++ b/include/drm/drm_prime.h
@@ -42,7 +42,6 @@
  * This just contains the internal &struct dma_buf and handle caches for each
  * &struct drm_file used by the PRIME core code.
  */
-
 struct drm_prime_file_private {
 /* private: */
        struct mutex lock;
@@ -64,25 +63,18 @@ struct drm_file;
 
 struct device;
 
-struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
-                                    struct drm_gem_object *obj,
-                                    int flags);
+/* core prime functions */
+struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
+                                     struct dma_buf_export_info *exp_info);
+void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
+
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+                              struct drm_file *file_priv, int prime_fd, 
uint32_t *handle);
 int drm_gem_prime_handle_to_fd(struct drm_device *dev,
                               struct drm_file *file_priv, uint32_t handle, 
uint32_t flags,
                               int *prime_fd);
-int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
-struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
-                                           struct dma_buf *dma_buf);
-
-struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
-                                               struct dma_buf *dma_buf,
-                                               struct device *attach_dev);
 
-int drm_gem_prime_fd_to_handle(struct drm_device *dev,
-                              struct drm_file *file_priv, int prime_fd, 
uint32_t *handle);
-struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
-                                     struct dma_buf_export_info *exp_info);
-void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
+/* helper functions for exporting */
 int drm_gem_map_attach(struct dma_buf *dma_buf,
                       struct dma_buf_attachment *attach);
 void drm_gem_map_detach(struct dma_buf *dma_buf,
@@ -94,12 +86,26 @@ void drm_gem_unmap_dma_buf(struct dma_buf_attachment 
*attach,
                           enum dma_data_direction dir);
 void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf);
 void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr);
+
+int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
 int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma);
 
-int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
-                                    dma_addr_t *addrs, int max_pages);
 struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int 
nr_pages);
+struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
+                                    struct drm_gem_object *obj,
+                                    int flags);
+
+/* helper functions for importing */
+struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
+                                               struct dma_buf *dma_buf,
+                                               struct device *attach_dev);
+struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
+                                           struct dma_buf *dma_buf);
+
 void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
 
+int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
+                                    dma_addr_t *addrs, int max_pages);
+
 
 #endif /* __DRM_PRIME_H__ */
-- 
2.20.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to