FAILED: patch "[PATCH] drm/prime: Take a ref on the drm_dev when exporting a dma_buf" failed to apply to 4.8-stable tree
Subsystems (8)
[email protected]
maintainerThe patch below does not apply to the 4.8-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
a4fce9cb782ad340ee5576a38e934e5e75832dc6Mon Sep 17 00:00:00 2001
From: Chris Wilson <[email protected]>
Date: Wed, 5 Oct 2016 13:21:44 +0100
Subject: [PATCH] drm/prime: Take a ref on the drm_dev when exporting a dma_buf
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
dma_buf may live a long time, longer than the last direct user of the driver. We already hold a reference to the owner module (that prevents the object code from disappearing), but there is no reference to the drm_dev - so the pointers to the driver backend themselves may vanish.
v2: Resist temptation to fix the bug in armada_gem.c not setting the correct flags on the exported dma-buf (it should pass the flags through and not be arbitrarily setting O_RDWR).
Use a common wrapper for exporting the dmabuf and acquiring the reference to the drm_device.
Testcase: igt/vgem_basic/unload
drivers/gpu/drm/armada/armada_gem.c +1 -1
@@ -547,7 +547,7 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, exp_info.flags =O_RDWR ; exp_info.priv = obj; -return dma_buf_export (&exp_info); +return drm_gem_dmabuf_export (dev, &exp_info); } struct drm_gem_object *
drivers/gpu/drm/drm_prime.c +29 -1
@@ -284,18 +284,46 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, }/** +* drm_gem_dmabuf_export - dma_buf export implementation for GEM +* @dma_buf: buffer to be exported +* +* This wraps dma_buf_export() for use by generic GEM drivers that are using +* drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take +* a reference to the drm_device which is released by drm_gem_dmabuf_release(). +* +* Returns the new dmabuf. +*/ +struct dma_buf *drm_gem_dmabuf_export (struct drm_device *dev, +struct dma_buf_export_info *exp_info) +{ +struct dma_buf *dma_buf; + + dma_buf =dma_buf_export (exp_info); +if (!IS_ERR (dma_buf)) +drm_dev_ref (dev); + +return dma_buf; +} +EXPORT_SYMBOL (drm_gem_dmabuf_export); + +/** * 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. +* drm_gem_dmabuf_release() should be used in conjunction with +* drm_gem_dmabuf_export(). */ void drm_gem_dmabuf_release (struct dma_buf *dma_buf) {struct drm_gem_object *obj = dma_buf->priv; +struct drm_device *dev = obj->dev;/* drop the reference on the export fd holds */ drm_gem_object_unreference_unlocked (obj); + +drm_dev_unref (dev); }EXPORT_SYMBOL (drm_gem_dmabuf_release);
@@ -412,7 +440,7 @@ struct dma_buf *drm_gem_prime_export(struct drm_device *dev,if (dev->driver->gem_prime_res_obj) exp_info.resv = dev->driver->gem_prime_res_obj (obj); -return dma_buf_export (&exp_info); +return drm_gem_dmabuf_export (dev, &exp_info); }EXPORT_SYMBOL (drm_gem_prime_export);
drivers/gpu/drm/i915/i915_gem_dmabuf.c +1 -1
@@ -283,7 +283,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,return ERR_PTR (ret); } - dma_buf =dma_buf_export (&exp_info); + dma_buf =drm_gem_dmabuf_export (dev, &exp_info);if (IS_ERR (dma_buf))return dma_buf;
drivers/gpu/drm/tegra/gem.c +1 -1
@@ -613,7 +613,7 @@ struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, exp_info.flags = flags; exp_info.priv = gem; -return dma_buf_export (&exp_info); +return drm_gem_dmabuf_export (drm, &exp_info); } struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
drivers/gpu/drm/udl/udl_dmabuf.c +1 -1
@@ -209,7 +209,7 @@ struct dma_buf *udl_gem_prime_export(struct drm_device *dev, exp_info.flags = flags; exp_info.priv = obj; -return dma_buf_export (&exp_info); +return drm_gem_dmabuf_export (dev, &exp_info); } static int udl_prime_create(struct drm_device *dev,
include/drm/drmP.h +4 -0
@@ -1011,6 +1011,8 @@ static inline int drm_debugfs_remove_files(const struct drm_info_list *files, }#endif +struct dma_buf_export_info ; +extern struct dma_buf *drm_gem_prime_export (struct drm_device *dev,struct drm_gem_object *obj,int flags);
@@ -1021,6 +1023,8 @@ extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf);extern 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);extern void drm_gem_dmabuf_release (struct dma_buf *dma_buf); extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,