All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: DRI Development <dri-devel@lists.freedesktop.org>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>,
	Intel Graphics Development <intel-gfx@lists.freedesktop.org>,
	Daniel Vetter <daniel.vetter@intel.com>
Subject: [PATCH 03/59] drm/prime: Update docs
Date: Fri, 14 Jun 2019 22:35:19 +0200	[thread overview]
Message-ID: <20190614203615.12639-4-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <20190614203615.12639-1-daniel.vetter@ffwll.ch>

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.vetter@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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2019-06-14 20:35 UTC|newest]

Thread overview: 215+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-14 20:35 [PATCH 00/59] prime doc polish and ... a few cleanups Daniel Vetter
2019-06-14 20:35 ` [PATCH 01/59] drm/todo: Improve drm_gem_object funcs todo Daniel Vetter
2019-06-14 20:44   ` Rob Herring
2019-06-14 22:53   ` Eric Anholt
2019-06-17 14:03     ` Daniel Vetter
2019-06-17  6:02   ` Gerd Hoffmann
2019-06-17 15:47   ` Noralf Trønnes
2019-06-17 16:29     ` Daniel Vetter
2019-06-17 16:54       ` Noralf Trønnes
2019-06-17 21:20         ` Daniel Vetter
2019-06-17 22:12           ` Noralf Trønnes
2019-06-18 14:02   ` [PATCH] drm/todo: Update drm_gem_object_funcs todo even more Daniel Vetter
2019-06-18 14:15     ` Noralf Trønnes
2019-06-18 18:25     ` Eric Engestrom
2019-06-20 12:52       ` Daniel Vetter
2019-06-27 12:15   ` [PATCH 01/59] drm/todo: Improve drm_gem_object funcs todo Thomas Zimmermann
2019-06-14 20:35 ` [PATCH 02/59] drm/gem: Unexport drm_gem_(un)pin/v(un)map Daniel Vetter
2019-06-14 20:35 ` Daniel Vetter [this message]
2019-06-15 11:41   ` [PATCH 03/59] drm/prime: Update docs Sam Ravnborg
2019-06-17 16:38     ` Daniel Vetter
2019-06-17 17:01       ` Sam Ravnborg
2019-06-17 17:47   ` Emil Velikov
2019-06-18  9:20   ` [PATCH 1/2] drm/prime: Shuffle functions Daniel Vetter
2019-06-18  9:20     ` [PATCH 2/2] drm/prime: Update docs Daniel Vetter
2019-06-19  9:03       ` Daniel Vetter
2019-06-19 10:21       ` Gerd Hoffmann
2019-06-19 10:50       ` Emil Velikov
2019-06-19 12:43       ` Noralf Trønnes
2019-06-20 12:44         ` Daniel Vetter
2019-06-20 12:46       ` [PATCH] " Daniel Vetter
2019-06-19 10:18     ` [PATCH 1/2] drm/prime: Shuffle functions Gerd Hoffmann
2019-06-19 10:47     ` Emil Velikov
2019-06-19 12:09     ` Noralf Trønnes
2019-06-14 20:35 ` [PATCH 04/59] drm/prime: Unconditionally set up the prime file private Daniel Vetter
2019-06-14 20:35 ` [PATCH 05/59] drm/prime: Make DRIVER_PRIME a no-op Daniel Vetter
2019-06-17 17:53   ` Emil Velikov
2019-06-14 20:35 ` [PATCH 06/59] drm/prime: Actually remove DRIVER_PRIME everywhere Daniel Vetter
2019-06-14 20:35 ` [PATCH 07/59] drm/arm/komeda: Remove DRIVER_HAVE_IRQ Daniel Vetter
2019-06-17  6:26   ` james qian wang (Arm Technology China)
2019-06-17 13:43     ` Daniel Vetter
2019-06-18  4:41       ` james qian wang (Arm Technology China)
2019-06-18  5:04         ` james qian wang (Arm Technology China)
2019-06-17 18:01     ` Emil Velikov
2019-06-19 10:11   ` Liviu Dudau
2019-06-14 20:35 ` [PATCH 08/59] drm/omapdrm: drop fb_debug_enter/leave Daniel Vetter
2019-06-14 20:35 ` [PATCH 10/59] drm/arc: Drop drm_gem_prime_export/import Daniel Vetter
2019-06-14 20:35 ` [PATCH 11/59] drm/arm: " Daniel Vetter
2019-06-17  3:22   ` james qian wang (Arm Technology China)
2019-06-19 10:11   ` Liviu Dudau
2019-06-14 20:35 ` [PATCH 12/59] drm/atmel: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-14 21:43   ` Sam Ravnborg
2019-06-14 21:43     ` Sam Ravnborg
2019-06-14 20:35 ` [PATCH 13/59] drm/etnaviv: " Daniel Vetter
2019-06-16  7:02   ` Christian Gmeiner
2019-06-25 16:12   ` Lucas Stach
2019-06-14 20:35 ` [PATCH 14/59] drm/exynos: Drop drm_gem_prime_export Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-14 20:35 ` [PATCH 15/59] drm/fsl-dcu: Drop drm_gem_prime_export/import Daniel Vetter
2019-06-17 13:58   ` Stefan Agner
2019-06-14 20:35 ` [PATCH 16/59] drm/hisilicon: " Daniel Vetter
2019-06-14 21:29   ` Sam Ravnborg
2019-06-14 20:35 ` [PATCH 17/59] drm/imx: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-14 20:35 ` [PATCH 18/59] drm/mcde: " Daniel Vetter
2019-06-15  8:31   ` Linus Walleij
2019-06-14 20:35 ` [PATCH 19/59] drm/mtk: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-17  1:51   ` CK Hu
2019-06-17  1:51     ` CK Hu
2019-06-14 20:35 ` [PATCH 20/59] drm/meson: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-18  9:48   ` Neil Armstrong
2019-06-18  9:48     ` Neil Armstrong
2019-06-18  9:48     ` Neil Armstrong
2019-06-14 20:35 ` [PATCH 21/59] drm/msm: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-14 20:35 ` [PATCH 22/59] drm/mxsfb: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-17 13:59   ` Stefan Agner
2019-06-17 13:59     ` Stefan Agner
2019-06-14 20:35 ` [PATCH 24/59] drm/pl111: " Daniel Vetter
2019-06-14 20:35 ` [PATCH 25/59] drm/qxl: " Daniel Vetter
2019-06-17  6:03   ` Gerd Hoffmann
2019-06-17  6:03   ` Gerd Hoffmann
2019-06-14 20:35 ` [PATCH 26/59] drm/rcar-du: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-18  7:35   ` Laurent Pinchart
2019-06-18  7:35     ` Laurent Pinchart
2019-06-14 20:35 ` [PATCH 27/59] drm/rockchip: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-15 22:36   ` Heiko Stuebner
2019-06-15 22:36     ` Heiko Stuebner
2019-06-14 20:35 ` [PATCH 28/59] drm/shmob: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-18  7:35   ` Laurent Pinchart
2019-06-18  7:35     ` Laurent Pinchart
2019-06-14 20:35 ` [PATCH 29/59] drm/sti: " Daniel Vetter
2019-06-20 15:08   ` Benjamin Gaignard
2019-06-14 20:35 ` [PATCH 30/59] drm/stm: " Daniel Vetter
2019-06-14 20:35   ` Daniel Vetter
2019-06-18  9:55   ` Philippe CORNU
2019-06-18  9:55     ` Philippe CORNU
2019-06-14 20:35 ` [PATCH 31/59] drm/tilcdc: " Daniel Vetter
2019-06-14 20:35 ` [PATCH 32/59] drm/tve2000: " Daniel Vetter
2019-06-15  8:34   ` Linus Walleij
2019-06-15  9:14     ` Daniel Vetter
2019-06-14 20:35 ` [PATCH 33/59] drm/vboxvideo: " Daniel Vetter
2019-06-14 20:35 ` [PATCH 34/59] drm/vc3: Drop drm_gem_prime_import Daniel Vetter
2019-06-14 20:35 ` [PATCH 35/59] drm/radeon: " Daniel Vetter
2019-06-14 20:35 ` [PATCH 36/59] drm/vgem: Drop drm_gem_prime_export Daniel Vetter
2019-06-14 20:35 ` [PATCH 37/59] drm/virtio: Drop drm_gem_prime_export/import Daniel Vetter
2019-06-17  6:03   ` Gerd Hoffmann
2019-06-17  6:03   ` Gerd Hoffmann
2019-06-14 20:35 ` [PATCH 38/59] drm/xen: " Daniel Vetter
2019-06-14 20:35   ` [Xen-devel] " Daniel Vetter
2019-06-18  5:05   ` Oleksandr Andrushchenko
2019-06-18  5:05     ` Oleksandr Andrushchenko
2019-06-14 20:35 ` [PATCH 39/59] drm/zte: " Daniel Vetter
2019-06-18 13:15   ` Shawn Guo
2019-06-14 20:35 ` [PATCH 40/59] drm/vram-helper: " Daniel Vetter
2019-06-17  6:03   ` Gerd Hoffmann
2019-06-17  8:24   ` Gerd Hoffmann
2019-06-17 13:59     ` Daniel Vetter
2019-06-18  4:49       ` Gerd Hoffmann
2019-06-18  7:59         ` Daniel Vetter
2019-06-19 11:21           ` Gerd Hoffmann
2019-06-19 11:31             ` Daniel Vetter
2019-06-27  8:27       ` Thomas Zimmermann
2019-06-27  9:59         ` Daniel Vetter
2019-06-14 20:35 ` [PATCH 41/59] drm/prime: automatically set gem_obj->resv on import Daniel Vetter
2019-06-14 20:35 ` [PATCH 42/59] drm/etnaviv: Drop resv argument from etnaviv_gem_new_impl Daniel Vetter
2019-06-25 16:10   ` Lucas Stach
2019-06-14 20:35 ` [PATCH 43/59] drm/lima: Drop resv argument from lima_bo_create_struct Daniel Vetter
2019-06-15 10:03   ` Qiang Yu
2019-06-14 20:36 ` [PATCH 44/59] drm/mediatek: Use drm_atomic_helper_wait_for_fences Daniel Vetter
2019-06-14 20:36   ` Daniel Vetter
2019-06-17  5:19   ` CK Hu
2019-06-17  5:19     ` CK Hu
2019-06-14 20:36 ` [PATCH 45/59] drm/msm: Drop robj from msm_gem_new_impl Daniel Vetter
2019-06-14 20:36   ` Daniel Vetter
2019-06-14 20:36 ` [PATCH 46/59] drm/panfrost: don't set gem_obj->resv for prime import anymore Daniel Vetter
2019-06-14 21:05   ` Rob Herring
2019-06-14 20:36 ` [PATCH 47/59] drm/vc4: Don set gem_obj->resv in " Daniel Vetter
2019-06-14 20:36 ` [PATCH 48/59] drm/vgem: Ditch attach trickery in the fence ioctl Daniel Vetter
2019-06-18 12:31   ` Chris Wilson
2019-06-18 13:18     ` Daniel Vetter
2019-06-14 20:36 ` [PATCH 49/59] drm/msm: Use drm_gem_fb_prepare_fb Daniel Vetter
2019-06-14 20:36   ` Daniel Vetter
2019-06-14 20:36 ` [PATCH 50/59] drm/vc4: " Daniel Vetter
     [not found] ` <20190614203615.12639-1-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
2019-06-14 20:35   ` [PATCH 06/59] drm/prime: Actually remove DRIVER_PRIME everywhere Daniel Vetter
2019-06-14 20:35     ` Daniel Vetter
2019-06-14 20:35     ` [Xen-devel] " Daniel Vetter
2019-06-14 20:35     ` Daniel Vetter
2019-06-14 20:35     ` Daniel Vetter
2019-06-14 21:36     ` Sam Ravnborg
2019-06-17 15:39     ` [PATCH] " Daniel Vetter
     [not found]     ` <20190614203615.12639-7-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
2019-06-14 21:36       ` [PATCH 06/59] " Sam Ravnborg
2019-06-14 21:36         ` Sam Ravnborg
2019-06-14 21:36         ` [Xen-devel] " Sam Ravnborg
2019-06-14 21:36         ` Sam Ravnborg
2019-06-14 21:36         ` Sam Ravnborg
2019-06-17 15:39       ` [PATCH] " Daniel Vetter
2019-06-17 15:39         ` Daniel Vetter
2019-06-17 15:39         ` [Xen-devel] " Daniel Vetter
2019-06-17 15:39         ` Daniel Vetter
2019-06-17 15:39         ` Daniel Vetter
2019-06-17 17:56     ` [PATCH 06/59] " Emil Velikov
2019-06-17 17:56       ` Emil Velikov
2019-06-17 17:56       ` [Xen-devel] " Emil Velikov
2019-06-17 17:56       ` Emil Velikov
2019-06-17 17:56       ` Emil Velikov
2019-06-14 20:35   ` [PATCH 09/59] drm/prime: Align gem_prime_export with obj_funcs.export Daniel Vetter
     [not found]     ` <20190614203615.12639-10-daniel.vetter-/w4YWyX8dFk@public.gmane.org>
2019-06-17  9:32       ` Koenig, Christian
2019-06-17  9:53       ` Thierry Reding
2019-06-21 10:37       ` Daniel Vetter
2019-06-14 20:35   ` [PATCH 23/59] drm/nouveau: Drop drm_gem_prime_export/import Daniel Vetter
2019-06-14 20:36   ` [PATCH 51/59] drm/radeon: Fill out gem_object->resv Daniel Vetter
2019-06-14 20:36 ` [PATCH 52/59] drm/nouveau: " Daniel Vetter
2019-06-14 20:36 ` [PATCH 53/59] drm/amdgpu: " Daniel Vetter
2019-06-14 20:36 ` [PATCH 54/59] drm/prime: Ditch gem_prime_res_obj hook Daniel Vetter
2019-06-14 20:36 ` [PATCH 55/59] drm/todo: remove gem_prime_import/export todo Daniel Vetter
2019-06-14 20:36 ` [PATCH 56/59] drm/todo: Update backlight todo Daniel Vetter
2019-06-14 21:46   ` Sam Ravnborg
2019-06-21 13:11   ` Daniel Thompson
2019-06-14 20:36 ` [PATCH 57/59] drm/todo: Update mmap todo Daniel Vetter
2019-06-14 20:36 ` [PATCH 58/59] drm/todo: Add new debugfs todo Daniel Vetter
2019-06-15  6:23   ` Greg Kroah-Hartman
2019-06-18 15:19   ` drm connectors, tegra, and the web they weave (was Re: [PATCH 58/59] drm/todo: Add new debugfs todo) Greg Kroah-Hartman
2019-06-18 15:25     ` Greg Kroah-Hartman
2019-06-18 17:32       ` Daniel Vetter
2019-06-18 18:01         ` Greg Kroah-Hartman
2019-06-18 21:46           ` Daniel Vetter
2019-06-20 14:50             ` Thierry Reding
2019-06-20 15:11         ` Thierry Reding
2019-06-18 15:37     ` Jon Hunter
2019-06-20 15:16       ` Thierry Reding
2019-06-20 14:57     ` Thierry Reding
2019-06-14 20:36 ` [PATCH 59/59] drm/doc: Document kapi doc expectations Daniel Vetter
2019-06-17  8:52   ` Jani Nikula
2019-06-14 21:02 ` ✗ Fi.CI.CHECKPATCH: warning for prime doc polish and ... a few cleanups Patchwork
2019-06-14 21:16 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-06-15  6:55 ` ✓ Fi.CI.BAT: success " Patchwork
2019-06-17 10:14 ` ✓ Fi.CI.IGT: " Patchwork
2019-06-17 18:21 ` [Intel-gfx] [PATCH 00/59] " Emil Velikov
2019-06-18 10:41   ` Emil Velikov
2019-06-17 18:28 ` ✗ Fi.CI.CHECKPATCH: warning for prime doc polish and ... a few cleanups (rev2) Patchwork
2019-06-17 18:42 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-06-17 18:49 ` ✓ Fi.CI.BAT: success " Patchwork
2019-06-18  8:20 ` ✓ Fi.CI.IGT: " Patchwork
2019-06-18  9:55 ` ✗ Fi.CI.BAT: failure for prime doc polish and ... a few cleanups (rev4) Patchwork
2019-06-18 14:48 ` ✗ Fi.CI.BAT: failure for prime doc polish and ... a few cleanups (rev5) Patchwork
2019-06-18 15:56 ` ✗ Fi.CI.BAT: failure for prime doc polish and ... a few cleanups (rev6) Patchwork
2019-06-20 17:17 ` ✗ Fi.CI.BAT: failure for prime doc polish and ... a few cleanups (rev7) Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190614203615.12639-4-daniel.vetter@ffwll.ch \
    --to=daniel.vetter@ffwll.ch \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.