From: Dave Airlie <airlied@xxxxxxxxxx> This is likely the simplest solution to the problem, and seems to work fine. When we export a dma_buf from a gem object, we keep track of it with the handle, we take a reference to the dma_buf. When we close the handle (i.e. userspace is finished with the buffer), we drop the reference to the dma_buf, and it gets collected. I'd like to refrain from too much in this patch as I'd like it to go to stable, so future cleanups should look at maybe reducing the obj storing two pointers etc. Signed-off-by: Dave Airlie <airlied@xxxxxxxxxx> --- drivers/gpu/drm/drm_gem.c | 2 +- drivers/gpu/drm/drm_prime.c | 34 ++++++++++++++++++++++++++++++---- include/drm/drmP.h | 1 + 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 24efae4..e221b7b 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -209,7 +209,7 @@ drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp) obj->import_attach->dmabuf); } if (obj->export_dma_buf) { - drm_prime_remove_imported_buf_handle(&filp->prime, + drm_prime_remove_exported_buf_handle(&filp->prime, obj->export_dma_buf); } } diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 7f12573..583d126 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -62,6 +62,8 @@ struct drm_prime_member { uint32_t handle; }; +static int drm_prime_add_exported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, 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) @@ -104,8 +106,8 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, /* if we've exported this buffer the cheat and add it to the import list * so we get the correct handle back */ - ret = drm_prime_add_imported_buf_handle(&file_priv->prime, - obj->export_dma_buf, handle); + ret = drm_prime_add_exported_buf_handle(&file_priv->prime, + obj->export_dma_buf, handle); if (ret) { drm_gem_object_unreference_unlocked(obj); mutex_unlock(&file_priv->prime.lock); @@ -307,7 +309,7 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) } EXPORT_SYMBOL(drm_prime_destroy_file_private); -int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) +static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) { struct drm_prime_member *member; @@ -320,6 +322,18 @@ int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv list_add(&member->entry, &prime_fpriv->head); return 0; } + +int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) +{ + return drm_prime_add_buf_handle(prime_fpriv, dma_buf, handle); +} + +static int drm_prime_add_exported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) +{ + /* take a reference to the buf handle for this case */ + get_dma_buf(dma_buf); + return drm_prime_add_buf_handle(prime_fpriv, dma_buf, handle); +} EXPORT_SYMBOL(drm_prime_add_imported_buf_handle); int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle) @@ -336,7 +350,7 @@ int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fp } EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle); -void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) +static void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) { struct drm_prime_member *member, *safe; @@ -349,4 +363,16 @@ void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_f } mutex_unlock(&prime_fpriv->lock); } + +void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) +{ + drm_prime_remove_buf_handle(prime_fpriv, dma_buf); +} EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle); + +void drm_prime_remove_exported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) +{ + drm_prime_remove_buf_handle(prime_fpriv, dma_buf); + dma_buf_put(dma_buf); +} +EXPORT_SYMBOL(drm_prime_remove_exported_buf_handle); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index fad21c9..6dcfa2e 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1562,6 +1562,7 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv); int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle); int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle); void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf); +void drm_prime_remove_exported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf); int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj); int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf, -- 1.8.0.2 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel