drm_gem_prime_export() and drm_gem_is_prime_exported_dma_buf() hardcode
drm_gem_prime_dmabuf_ops. Drivers with custom dma_buf_ops can't use them
and end up duplicating the export and self-import logic instead.

Add drm_gem_prime_export_with_ops() to export with driver-provided ops,
and an optional drm_driver.gem_prime_is_exporter() callback to let drivers
identify their own DMA-BUFs. Note that the callback must receive DMA-BUF,
so that the driver can check its ops before dereferencing dma_buf->priv.

Signed-off-by: Maíra Canal <[email protected]>
---
 drivers/gpu/drm/drm_prime.c | 47 +++++++++++++++++++++++++++++++++++----------
 include/drm/drm_drv.h       | 11 +++++++++++
 include/drm/drm_prime.h     |  4 ++++
 3 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index fe3436d1235d..4183def83cdd 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -905,22 +905,26 @@ unsigned long drm_prime_get_contiguous_size(struct 
sg_table *sgt)
 EXPORT_SYMBOL(drm_prime_get_contiguous_size);
 
 /**
- * drm_gem_prime_export - helper library implementation of the export callback
+ * drm_gem_prime_export_with_ops - export a GEM object with custom dma_buf_ops
  * @obj: GEM object to export
+ * @dma_buf_ops: &dma_buf_ops of the exported DMA-BUF
  * @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. It is used as the default in
- * drm_gem_prime_handle_to_fd().
+ * Same as drm_gem_prime_export(), but with driver-provided &dma_buf_ops.
+ * Drivers using this can implement &drm_driver.gem_prime_is_exporter for
+ * the PRIME import helpers to recognize their own buffers.
+ *
+ * Return: the exported DMA-BUF on success, or an ERR_PTR() on failure.
  */
-struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
-                                    int flags)
+struct dma_buf *drm_gem_prime_export_with_ops(struct drm_gem_object *obj,
+                                             const struct dma_buf_ops 
*dma_buf_ops,
+                                             int flags)
 {
        struct drm_device *dev = obj->dev;
        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,
+               .ops = dma_buf_ops,
                .size = obj->size,
                .flags = flags,
                .priv = obj,
@@ -929,24 +933,47 @@ struct dma_buf *drm_gem_prime_export(struct 
drm_gem_object *obj,
 
        return drm_gem_dmabuf_export(dev, &exp_info);
 }
+EXPORT_SYMBOL(drm_gem_prime_export_with_ops);
+
+/**
+ * drm_gem_prime_export - helper library implementation of the export callback
+ * @obj: GEM object to export
+ * @flags: flags like DRM_CLOEXEC and DRM_RDWR
+ *
+ * This is the implementation of the &drm_gem_object_funcs.export function for
+ * GEM drivers using the PRIME helpers. It is used as the default in
+ * drm_gem_prime_handle_to_fd().
+ *
+ * Return: the exported DMA-BUF on success, or an ERR_PTR() on failure.
+ */
+struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
+                                    int flags)
+{
+       return drm_gem_prime_export_with_ops(obj, &drm_gem_prime_dmabuf_ops, 
flags);
+}
 EXPORT_SYMBOL(drm_gem_prime_export);
 
 
 /**
- * drm_gem_is_prime_exported_dma_buf -
- * checks if the DMA-BUF was exported from a GEM object belonging to @dev.
+ * drm_gem_is_prime_exported_dma_buf - check if a DMA-BUF was exported by @dev
  * @dev: drm_device to check against
  * @dma_buf: dma-buf object to import
  *
+ * DMA-BUFs exported with custom &dma_buf_ops are recognized through
+ * &drm_driver.gem_prime_is_exporter.
+ *
  * Return: true if the DMA-BUF was exported from a GEM object belonging
  * to @dev, false otherwise.
  */
-
 bool drm_gem_is_prime_exported_dma_buf(struct drm_device *dev,
                                       struct dma_buf *dma_buf)
 {
        struct drm_gem_object *obj = dma_buf->priv;
 
+       if (dev->driver->gem_prime_is_exporter &&
+           dev->driver->gem_prime_is_exporter(dev, dma_buf))
+               return true;
+
        return (dma_buf->ops == &drm_gem_prime_dmabuf_ops) && (obj->dev == dev);
 }
 EXPORT_SYMBOL(drm_gem_is_prime_exported_dma_buf);
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index b23830494ed4..d613740a06d4 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -310,6 +310,17 @@ struct drm_driver {
         */
        struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
                                struct dma_buf *dma_buf);
+       /**
+        * @gem_prime_is_exporter:
+        *
+        * Returns true if @dma_buf was exported from a GEM object of @dev.
+        * Drivers exporting with a custom &dma_buf_ops can implement this
+        * hook to let the PRIME import helpers recognize their own buffers.
+        *
+        * This callback is optional.
+        */
+       bool (*gem_prime_is_exporter)(struct drm_device *dev,
+                                     struct dma_buf *dma_buf);
        /**
         * @gem_prime_import_sg_table:
         *
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
index f50f862f0d8b..9b704e3ca919 100644
--- a/include/drm/drm_prime.h
+++ b/include/drm/drm_prime.h
@@ -53,6 +53,7 @@ struct device;
 
 struct dma_buf_export_info;
 struct dma_buf;
+struct dma_buf_ops;
 struct dma_buf_attachment;
 struct iosys_map;
 
@@ -96,6 +97,9 @@ struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev,
                                       struct page **pages, unsigned int 
nr_pages);
 struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj,
                                     int flags);
+struct dma_buf *drm_gem_prime_export_with_ops(struct drm_gem_object *obj,
+                                             const struct dma_buf_ops 
*dma_buf_ops,
+                                             int flags);
 
 unsigned long drm_prime_get_contiguous_size(struct sg_table *sgt);
 

-- 
2.56.0

Reply via email to