The default implementation simply takes care of invalidating/flushing
caches around CPU accesses. It takes care of both the exporter and
the importers, which forces us to overload the default
::[un]map_dma_buf() implementation provided by drm_gem.c to store the
sgt.

v5:
- New patch

Signed-off-by: Boris Brezillon <[email protected]>
---
 drivers/gpu/drm/drm_gem_shmem_helper.c | 114 +++++++++++++++++++++++++
 include/drm/drm_gem_shmem_helper.h     |  10 +++
 2 files changed, 124 insertions(+)

diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c 
b/drivers/gpu/drm/drm_gem_shmem_helper.c
index dc94a27710e5..e49c75739c20 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -893,6 +893,120 @@ struct drm_gem_object 
*drm_gem_shmem_prime_import_no_map(struct drm_device *dev,
 }
 EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_no_map);
 
+/**
+ * drm_gem_shmem_prime_unmap_dma_buf - Default unmap_dma_buf() for exported 
buffers
+ * @attach: attachment
+ * @sgt: SG table to unmap
+ * @dir: type of access done by this attachment
+ *
+ * Default implementation for dma_buf_ops::map_dma_buf(). This is just a 
wrapper
+ * around drm_gem_map_dma_buf() that lets us set the dma_buf_attachment::priv
+ * to the sgt so that drm_gem_shmem_prime_{begin,end}_cpu_access() can sync
+ * around CPU accesses.
+ */
+struct sg_table *
+drm_gem_shmem_prime_map_dma_buf(struct dma_buf_attachment *attach,
+                               enum dma_data_direction dir)
+{
+       struct sg_table *sgt = drm_gem_map_dma_buf(attach, dir);
+
+       if (!IS_ERR(sgt))
+               attach->priv = sgt;
+
+       return sgt;
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_map_dma_buf);
+
+/**
+ * drm_gem_shmem_prime_unmap_dma_buf - Default unmap_dma_buf() for exported 
buffers
+ * @attach: attachment
+ * @sgt: SG table to unmap
+ * @dir: type of access done by this attachment
+ *
+ * Default implementation for dma_buf_ops::unmap_dma_buf(). This is just a 
wrapper
+ * around drm_gem_unmap_dma_buf() that lets us reset the 
dma_buf_attachment::priv
+ * field so that drm_gem_shmem_prime_{begin,end}_cpu_access() don't consider it
+ * as a mapped attachment to sync against.
+ */
+void drm_gem_shmem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
+                                      struct sg_table *sgt,
+                                      enum dma_data_direction dir)
+{
+       attach->priv = NULL;
+       drm_gem_unmap_dma_buf(attach, sgt, dir);
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_unmap_dma_buf);
+
+/**
+ * drm_gem_shmem_prime_begin_cpu_access - Default end_cpu_access() for 
exported buffers
+ * @dma_buf: The exported DMA buffer this acts on
+ * @dir: direction of the access
+ *
+ * Default implementation for dma_buf_ops::begin_cpu_access(). This only takes 
care of
+ * cache maintenance.
+ */
+int drm_gem_shmem_prime_begin_cpu_access(struct dma_buf *dma_buf,
+                                        enum dma_data_direction dir)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->dev;
+       struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+       struct dma_buf_attachment *attach;
+
+       dma_resv_lock(obj->resv, NULL);
+       if (shmem->sgt)
+               dma_sync_sgtable_for_cpu(dev->dev, shmem->sgt, dir);
+
+       if (shmem->vaddr)
+               invalidate_kernel_vmap_range(shmem->vaddr, shmem->base.size);
+
+       list_for_each_entry(attach, &dma_buf->attachments, node) {
+               struct sg_table *sgt = attach->priv;
+
+               if (sgt)
+                       dma_sync_sgtable_for_cpu(attach->dev, sgt, dir);
+       }
+       dma_resv_unlock(obj->resv);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_begin_cpu_access);
+
+/**
+ * drm_gem_shmem_prime_end_cpu_access - Default end_cpu_access() for exported 
buffers
+ * @dma_buf: The exported DMA buffer this acts on
+ * @dir: direction of the access
+ *
+ * Default implementation for dma_buf_ops::end_cpu_access(). This only takes 
care of
+ * cache maintenance.
+ */
+int drm_gem_shmem_prime_end_cpu_access(struct dma_buf *dma_buf,
+                                      enum dma_data_direction dir)
+{
+       struct drm_gem_object *obj = dma_buf->priv;
+       struct drm_device *dev = obj->dev;
+       struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+       struct dma_buf_attachment *attach;
+
+       dma_resv_lock(obj->resv, NULL);
+       list_for_each_entry(attach, &dma_buf->attachments, node) {
+               struct sg_table *sgt = attach->priv;
+
+               if (sgt)
+                       dma_sync_sgtable_for_device(attach->dev, sgt, dir);
+       }
+
+       if (shmem->vaddr)
+               flush_kernel_vmap_range(shmem->vaddr, shmem->base.size);
+
+       if (shmem->sgt)
+               dma_sync_sgtable_for_device(dev->dev, shmem->sgt, dir);
+
+       dma_resv_unlock(obj->resv);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_end_cpu_access);
+
 MODULE_DESCRIPTION("DRM SHMEM memory-management helpers");
 MODULE_IMPORT_NS("DMA_BUF");
 MODULE_LICENSE("GPL v2");
diff --git a/include/drm/drm_gem_shmem_helper.h 
b/include/drm/drm_gem_shmem_helper.h
index 589f7bfe7506..075275d6b2fd 100644
--- a/include/drm/drm_gem_shmem_helper.h
+++ b/include/drm/drm_gem_shmem_helper.h
@@ -291,6 +291,16 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, 
struct drm_device *dev,
                              struct drm_mode_create_dumb *args);
 struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device 
*dev,
                                                         struct dma_buf *buf);
+struct sg_table *
+drm_gem_shmem_prime_map_dma_buf(struct dma_buf_attachment *attach,
+                               enum dma_data_direction dir);
+void drm_gem_shmem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
+                                      struct sg_table *sgt,
+                                      enum dma_data_direction dir);
+int drm_gem_shmem_prime_begin_cpu_access(struct dma_buf *dma_buf,
+                                        enum dma_data_direction dir);
+int drm_gem_shmem_prime_end_cpu_access(struct dma_buf *dma_buf,
+                                      enum dma_data_direction dir);
 
 /**
  * DRM_GEM_SHMEM_DRIVER_OPS - Default shmem GEM operations
-- 
2.51.0

Reply via email to