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
