[PATCH] dma-buf, drm, ion: Propagate error code from dma_buf_start_cpu_access()
Daniel Vetter
daniel at ffwll.ch
Sat Mar 19 10:09:36 UTC 2016
On Fri, Mar 18, 2016 at 08:02:39PM +0000, Chris Wilson wrote:
> Drivers, especially i915.ko, can fail during the initial migration of a
> dma-buf for CPU access. However, the error code from the driver was not
> being propagated back to ioctl and so userspace was blissfully ignorant
> of the failure. Rendering corruption ensues.
>
> Whilst fixing the ioctl to return the error code from
> dma_buf_start_cpu_access(), also do the same for
> dma_buf_end_cpu_access(). For most drivers, dma_buf_end_cpu_access()
> cannot fail. i915.ko however, as most drivers would, wants to avoid being
> uninterruptible (as would be required to guarrantee no failure when
> flushing the buffer to the device). As userspace already has to handle
> errors from the SYNC_IOCTL, take advantage of this to be able to restart
> the syscall across signals.
>
> This fixes a coherency issue for i915.ko as well as reducing the
> uninterruptible hold upon its BKL, the struct_mutex.
>
> Fixes commit c11e391da2a8fe973c3c2398452000bed505851e
> Author: Daniel Vetter <daniel.vetter at ffwll.ch>
> Date: Thu Feb 11 20:04:51 2016 -0200
>
> dma-buf: Add ioctls to allow userspace to flush
>
> Testcase: igt/gem_concurrent_blit/*dmabuf*interruptible
> Testcase: igt/prime_mmap_coherency/ioctl-errors
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Tiago Vignatti <tiago.vignatti at intel.com>
> Cc: Stéphane Marchesin <marcheu at chromium.org>
> Cc: David Herrmann <dh.herrmann at gmail.com>
> Cc: Sumit Semwal <sumit.semwal at linaro.org>
> Cc: Daniel Vetter <daniel.vetter at intel.com>
> CC: linux-media at vger.kernel.org
> Cc: dri-devel at lists.freedesktop.org
> Cc: linaro-mm-sig at lists.linaro.org
> Cc: intel-gfx at lists.freedesktop.org
> Cc: devel at driverdev.osuosl.org
Applied to drm-misc, I'll send a pull to Dave the next few days if no one
screams.
-Daniel
> ---
> drivers/dma-buf/dma-buf.c | 17 +++++++++++------
> drivers/gpu/drm/i915/i915_gem_dmabuf.c | 15 +++++----------
> drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 5 +++--
> drivers/gpu/drm/udl/udl_fb.c | 4 ++--
> drivers/staging/android/ion/ion.c | 6 ++++--
> include/linux/dma-buf.h | 6 +++---
> 6 files changed, 28 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index 9810d1df0691..774a60f4309a 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -259,6 +259,7 @@ static long dma_buf_ioctl(struct file *file,
> struct dma_buf *dmabuf;
> struct dma_buf_sync sync;
> enum dma_data_direction direction;
> + int ret;
>
> dmabuf = file->private_data;
>
> @@ -285,11 +286,11 @@ static long dma_buf_ioctl(struct file *file,
> }
>
> if (sync.flags & DMA_BUF_SYNC_END)
> - dma_buf_end_cpu_access(dmabuf, direction);
> + ret = dma_buf_end_cpu_access(dmabuf, direction);
> else
> - dma_buf_begin_cpu_access(dmabuf, direction);
> + ret = dma_buf_begin_cpu_access(dmabuf, direction);
>
> - return 0;
> + return ret;
> default:
> return -ENOTTY;
> }
> @@ -613,13 +614,17 @@ EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
> *
> * This call must always succeed.
> */
> -void dma_buf_end_cpu_access(struct dma_buf *dmabuf,
> - enum dma_data_direction direction)
> +int dma_buf_end_cpu_access(struct dma_buf *dmabuf,
> + enum dma_data_direction direction)
> {
> + int ret = 0;
> +
> WARN_ON(!dmabuf);
>
> if (dmabuf->ops->end_cpu_access)
> - dmabuf->ops->end_cpu_access(dmabuf, direction);
> + ret = dmabuf->ops->end_cpu_access(dmabuf, direction);
> +
> + return ret;
> }
> EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access);
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> index 1f3eef6fb345..0506016e18e0 100644
> --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
> @@ -228,25 +228,20 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_dire
> return ret;
> }
>
> -static void i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
> +static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
> {
> struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
> struct drm_device *dev = obj->base.dev;
> - struct drm_i915_private *dev_priv = to_i915(dev);
> - bool was_interruptible;
> int ret;
>
> - mutex_lock(&dev->struct_mutex);
> - was_interruptible = dev_priv->mm.interruptible;
> - dev_priv->mm.interruptible = false;
> + ret = i915_mutex_lock_interruptible(dev);
> + if (ret)
> + return ret;
>
> ret = i915_gem_object_set_to_gtt_domain(obj, false);
> -
> - dev_priv->mm.interruptible = was_interruptible;
> mutex_unlock(&dev->struct_mutex);
>
> - if (unlikely(ret))
> - DRM_ERROR("unable to flush buffer following CPU access; rendering may be corrupt\n");
> + return ret;
> }
>
> static const struct dma_buf_ops i915_dmabuf_ops = {
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> index 3cf8aab23a39..af267c35d813 100644
> --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> @@ -97,11 +97,12 @@ static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer,
> return omap_gem_get_pages(obj, &pages, true);
> }
>
> -static void omap_gem_dmabuf_end_cpu_access(struct dma_buf *buffer,
> - enum dma_data_direction dir)
> +static int omap_gem_dmabuf_end_cpu_access(struct dma_buf *buffer,
> + enum dma_data_direction dir)
> {
> struct drm_gem_object *obj = buffer->priv;
> omap_gem_put_pages(obj);
> + return 0;
> }
>
>
> diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
> index c427499133d6..33239a2b264a 100644
> --- a/drivers/gpu/drm/udl/udl_fb.c
> +++ b/drivers/gpu/drm/udl/udl_fb.c
> @@ -423,8 +423,8 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
> }
>
> if (ufb->obj->base.import_attach) {
> - dma_buf_end_cpu_access(ufb->obj->base.import_attach->dmabuf,
> - DMA_FROM_DEVICE);
> + ret = dma_buf_end_cpu_access(ufb->obj->base.import_attach->dmabuf,
> + DMA_FROM_DEVICE);
> }
>
> unlock:
> diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
> index 0754a37c9674..49436b4510f4 100644
> --- a/drivers/staging/android/ion/ion.c
> +++ b/drivers/staging/android/ion/ion.c
> @@ -1075,14 +1075,16 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
> return PTR_ERR_OR_ZERO(vaddr);
> }
>
> -static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
> - enum dma_data_direction direction)
> +static int ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
> + enum dma_data_direction direction)
> {
> struct ion_buffer *buffer = dmabuf->priv;
>
> mutex_lock(&buffer->lock);
> ion_buffer_kmap_put(buffer);
> mutex_unlock(&buffer->lock);
> +
> + return 0;
> }
>
> static struct dma_buf_ops dma_buf_ops = {
> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> index 532108ea0c1c..3fe90d494edb 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -94,7 +94,7 @@ struct dma_buf_ops {
> void (*release)(struct dma_buf *);
>
> int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction);
> - void (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);
> + int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);
> void *(*kmap_atomic)(struct dma_buf *, unsigned long);
> void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *);
> void *(*kmap)(struct dma_buf *, unsigned long);
> @@ -224,8 +224,8 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
> enum dma_data_direction);
> int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
> enum dma_data_direction dir);
> -void dma_buf_end_cpu_access(struct dma_buf *dma_buf,
> - enum dma_data_direction dir);
> +int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
> + enum dma_data_direction dir);
> void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long);
> void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *);
> void *dma_buf_kmap(struct dma_buf *, unsigned long);
> --
> 2.8.0.rc3
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list