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. Testcase: igt/vgem_basic/unload Suggested-by: Daniel Vetter <daniel.vetter@xxxxxxxx> Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Petri Latvala <petri.latvala@xxxxxxxxx> Cc: Daniel Vetter <daniel.vetter@xxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx Tested-by: Petri Latvala <petri.latvala@xxxxxxxxx> --- drivers/gpu/drm/armada/armada_gem.c | 9 +++++++-- drivers/gpu/drm/drm_prime.c | 10 +++++++++- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 1 + drivers/gpu/drm/tegra/gem.c | 7 ++++++- drivers/gpu/drm/udl/udl_dmabuf.c | 7 ++++++- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index cb8f0347b934..bdd3af043827 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -541,13 +541,18 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct dma_buf *dma_buf; exp_info.ops = &armada_gem_prime_dmabuf_ops; exp_info.size = obj->size; - exp_info.flags = O_RDWR; + exp_info.flags = flags; exp_info.priv = obj; - return dma_buf_export(&exp_info); + dma_buf = dma_buf_export(&exp_info); + if (!IS_ERR(dma_buf)) + drm_dev_ref(dev); + + return dma_buf; } struct drm_gem_object * diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 80907b34d857..5081f187d9e3 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -293,9 +293,12 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, 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); @@ -408,11 +411,16 @@ struct dma_buf *drm_gem_prime_export(struct drm_device *dev, .flags = flags, .priv = obj, }; + struct dma_buf *dma_buf; if (dev->driver->gem_prime_res_obj) exp_info.resv = dev->driver->gem_prime_res_obj(obj); - return dma_buf_export(&exp_info); + dma_buf = dma_buf_export(&exp_info); + if (!IS_ERR(dma_buf)) + drm_dev_ref(dev); + + return dma_buf; } EXPORT_SYMBOL(drm_gem_prime_export); diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 10265bb35604..b58b2e63add1 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -288,6 +288,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, return dma_buf; export_fences(obj, dma_buf); + drm_dev_ref(obj->base.dev); return dma_buf; } diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index aa60d9909ea2..aaae8b6ba668 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -607,13 +607,18 @@ struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct dma_buf *dma_buf; exp_info.ops = &tegra_gem_prime_dmabuf_ops; exp_info.size = gem->size; exp_info.flags = flags; exp_info.priv = gem; - return dma_buf_export(&exp_info); + dma_buf = dma_buf_export(&exp_info); + if (!IS_ERR(dma_buf)) + drm_dev_ref(drm); + + return dma_buf; } struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, diff --git a/drivers/gpu/drm/udl/udl_dmabuf.c b/drivers/gpu/drm/udl/udl_dmabuf.c index e2243edd1ce3..249cc1072112 100644 --- a/drivers/gpu/drm/udl/udl_dmabuf.c +++ b/drivers/gpu/drm/udl/udl_dmabuf.c @@ -203,13 +203,18 @@ struct dma_buf *udl_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct dma_buf *dma_buf; exp_info.ops = &udl_dmabuf_ops; exp_info.size = obj->size; exp_info.flags = flags; exp_info.priv = obj; - return dma_buf_export(&exp_info); + dma_buf = dma_buf_export(&exp_info); + if (!IS_ERR(dma_buf)) + drm_dev_ref(dev); + + return dma_buf; } static int udl_prime_create(struct drm_device *dev, -- 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html