diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-10-05 08:21:44 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-10-05 09:30:32 -0400 |
commit | a4fce9cb782ad340ee5576a38e934e5e75832dc6 (patch) | |
tree | 528aa09d8be2f3fcbe72e3a8b972fc6e6711a68d /drivers/gpu | |
parent | 56a76c0123d6cb034975901c80fce2627338ef9e (diff) |
drm/prime: Take a ref on the drm_dev when exporting a dma_buf
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
Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: stable@vger.kernel.org
Tested-by: Petri Latvala <petri.latvala@intel.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20161005122145.1507-2-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/armada/armada_gem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_prime.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_dmabuf.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/udl/udl_dmabuf.c | 2 |
5 files changed, 33 insertions, 5 deletions
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index cb8f0347b934..a5e428d27d2f 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c | |||
@@ -547,7 +547,7 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, | |||
547 | exp_info.flags = O_RDWR; | 547 | exp_info.flags = O_RDWR; |
548 | exp_info.priv = obj; | 548 | exp_info.priv = obj; |
549 | 549 | ||
550 | return dma_buf_export(&exp_info); | 550 | return drm_gem_dmabuf_export(dev, &exp_info); |
551 | } | 551 | } |
552 | 552 | ||
553 | struct drm_gem_object * | 553 | struct drm_gem_object * |
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 80907b34d857..875df8d719fb 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
@@ -284,18 +284,46 @@ static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, | |||
284 | } | 284 | } |
285 | 285 | ||
286 | /** | 286 | /** |
287 | * drm_gem_dmabuf_export - dma_buf export implementation for GEM | ||
288 | * @dma_buf: buffer to be exported | ||
289 | * | ||
290 | * This wraps dma_buf_export() for use by generic GEM drivers that are using | ||
291 | * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take | ||
292 | * a reference to the drm_device which is released by drm_gem_dmabuf_release(). | ||
293 | * | ||
294 | * Returns the new dmabuf. | ||
295 | */ | ||
296 | struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, | ||
297 | struct dma_buf_export_info *exp_info) | ||
298 | { | ||
299 | struct dma_buf *dma_buf; | ||
300 | |||
301 | dma_buf = dma_buf_export(exp_info); | ||
302 | if (!IS_ERR(dma_buf)) | ||
303 | drm_dev_ref(dev); | ||
304 | |||
305 | return dma_buf; | ||
306 | } | ||
307 | EXPORT_SYMBOL(drm_gem_dmabuf_export); | ||
308 | |||
309 | /** | ||
287 | * drm_gem_dmabuf_release - dma_buf release implementation for GEM | 310 | * drm_gem_dmabuf_release - dma_buf release implementation for GEM |
288 | * @dma_buf: buffer to be released | 311 | * @dma_buf: buffer to be released |
289 | * | 312 | * |
290 | * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers | 313 | * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers |
291 | * must use this in their dma_buf ops structure as the release callback. | 314 | * must use this in their dma_buf ops structure as the release callback. |
315 | * drm_gem_dmabuf_release() should be used in conjunction with | ||
316 | * drm_gem_dmabuf_export(). | ||
292 | */ | 317 | */ |
293 | void drm_gem_dmabuf_release(struct dma_buf *dma_buf) | 318 | void drm_gem_dmabuf_release(struct dma_buf *dma_buf) |
294 | { | 319 | { |
295 | struct drm_gem_object *obj = dma_buf->priv; | 320 | struct drm_gem_object *obj = dma_buf->priv; |
321 | struct drm_device *dev = obj->dev; | ||
296 | 322 | ||
297 | /* drop the reference on the export fd holds */ | 323 | /* drop the reference on the export fd holds */ |
298 | drm_gem_object_unreference_unlocked(obj); | 324 | drm_gem_object_unreference_unlocked(obj); |
325 | |||
326 | drm_dev_unref(dev); | ||
299 | } | 327 | } |
300 | EXPORT_SYMBOL(drm_gem_dmabuf_release); | 328 | EXPORT_SYMBOL(drm_gem_dmabuf_release); |
301 | 329 | ||
@@ -412,7 +440,7 @@ struct dma_buf *drm_gem_prime_export(struct drm_device *dev, | |||
412 | if (dev->driver->gem_prime_res_obj) | 440 | if (dev->driver->gem_prime_res_obj) |
413 | exp_info.resv = dev->driver->gem_prime_res_obj(obj); | 441 | exp_info.resv = dev->driver->gem_prime_res_obj(obj); |
414 | 442 | ||
415 | return dma_buf_export(&exp_info); | 443 | return drm_gem_dmabuf_export(dev, &exp_info); |
416 | } | 444 | } |
417 | EXPORT_SYMBOL(drm_gem_prime_export); | 445 | EXPORT_SYMBOL(drm_gem_prime_export); |
418 | 446 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 10265bb35604..97c9d68b45df 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c | |||
@@ -283,7 +283,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, | |||
283 | return ERR_PTR(ret); | 283 | return ERR_PTR(ret); |
284 | } | 284 | } |
285 | 285 | ||
286 | dma_buf = dma_buf_export(&exp_info); | 286 | dma_buf = drm_gem_dmabuf_export(dev, &exp_info); |
287 | if (IS_ERR(dma_buf)) | 287 | if (IS_ERR(dma_buf)) |
288 | return dma_buf; | 288 | return dma_buf; |
289 | 289 | ||
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index aa60d9909ea2..95e622e31931 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c | |||
@@ -613,7 +613,7 @@ struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, | |||
613 | exp_info.flags = flags; | 613 | exp_info.flags = flags; |
614 | exp_info.priv = gem; | 614 | exp_info.priv = gem; |
615 | 615 | ||
616 | return dma_buf_export(&exp_info); | 616 | return drm_gem_dmabuf_export(drm, &exp_info); |
617 | } | 617 | } |
618 | 618 | ||
619 | struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, | 619 | 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..ac90ffdb5912 100644 --- a/drivers/gpu/drm/udl/udl_dmabuf.c +++ b/drivers/gpu/drm/udl/udl_dmabuf.c | |||
@@ -209,7 +209,7 @@ struct dma_buf *udl_gem_prime_export(struct drm_device *dev, | |||
209 | exp_info.flags = flags; | 209 | exp_info.flags = flags; |
210 | exp_info.priv = obj; | 210 | exp_info.priv = obj; |
211 | 211 | ||
212 | return dma_buf_export(&exp_info); | 212 | return drm_gem_dmabuf_export(dev, &exp_info); |
213 | } | 213 | } |
214 | 214 | ||
215 | static int udl_prime_create(struct drm_device *dev, | 215 | static int udl_prime_create(struct drm_device *dev, |