mbox series

[v4,00/21] Move all drivers to a common dma-buf locking convention

Message ID 20220831153757.97381-1-dmitry.osipenko@collabora.com
Headers show
Series Move all drivers to a common dma-buf locking convention | expand

Message

Dmitry Osipenko Aug. 31, 2022, 3:37 p.m. UTC
Hello,

This series moves all drivers to a dynamic dma-buf locking specification.

Comments

Christian König Sept. 1, 2022, 6:43 a.m. UTC | #1
Am 31.08.22 um 17:37 schrieb Dmitry Osipenko:
> Prepare Armada driver to the common dynamic dma-buf locking convention
> by starting to use the unlocked versions of dma-buf API functions.
>
> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>

Acked-by: Christian König <christian.koenig@amd.com>

> ---
>   drivers/gpu/drm/armada/armada_gem.c | 8 ++++----
>   1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
> index 5430265ad458..26d10065d534 100644
> --- a/drivers/gpu/drm/armada/armada_gem.c
> +++ b/drivers/gpu/drm/armada/armada_gem.c
> @@ -66,8 +66,8 @@ void armada_gem_free_object(struct drm_gem_object *obj)
>   	if (dobj->obj.import_attach) {
>   		/* We only ever display imported data */
>   		if (dobj->sgt)
> -			dma_buf_unmap_attachment(dobj->obj.import_attach,
> -						 dobj->sgt, DMA_TO_DEVICE);
> +			dma_buf_unmap_attachment_unlocked(dobj->obj.import_attach,
> +							  dobj->sgt, DMA_TO_DEVICE);
>   		drm_prime_gem_destroy(&dobj->obj, NULL);
>   	}
>   
> @@ -539,8 +539,8 @@ int armada_gem_map_import(struct armada_gem_object *dobj)
>   {
>   	int ret;
>   
> -	dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
> -					   DMA_TO_DEVICE);
> +	dobj->sgt = dma_buf_map_attachment_unlocked(dobj->obj.import_attach,
> +						    DMA_TO_DEVICE);
>   	if (IS_ERR(dobj->sgt)) {
>   		ret = PTR_ERR(dobj->sgt);
>   		dobj->sgt = NULL;
Christian König Sept. 1, 2022, 6:45 a.m. UTC | #2
Am 31.08.22 um 17:37 schrieb Dmitry Osipenko:
> Prepare OMAP DRM driver to the common dynamic dma-buf locking convention
> by starting to use the unlocked versions of dma-buf API functions.
>
> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>

Acked-by: Christian König <christian.koenig@amd.com>

> ---
>   drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> index 393f82e26927..8e194dbc9506 100644
> --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
> @@ -125,7 +125,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
>   
>   	get_dma_buf(dma_buf);
>   
> -	sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
> +	sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
>   	if (IS_ERR(sgt)) {
>   		ret = PTR_ERR(sgt);
>   		goto fail_detach;
> @@ -142,7 +142,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
>   	return obj;
>   
>   fail_unmap:
> -	dma_buf_unmap_attachment(attach, sgt, DMA_TO_DEVICE);
> +	dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_TO_DEVICE);
>   fail_detach:
>   	dma_buf_detach(dma_buf, attach);
>   	dma_buf_put(dma_buf);
Christian König Sept. 1, 2022, 7:04 a.m. UTC | #3
Am 31.08.22 um 17:37 schrieb Dmitry Osipenko:
> Prepare gntdev driver to the common dynamic dma-buf locking convention
> by starting to use the unlocked versions of dma-buf API functions.
>
> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>

Acked-by: Christian König <christian.koenig@amd.com>

> ---
>   drivers/xen/gntdev-dmabuf.c | 8 ++++----
>   1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
> index 940e5e9e8a54..4440e626b797 100644
> --- a/drivers/xen/gntdev-dmabuf.c
> +++ b/drivers/xen/gntdev-dmabuf.c
> @@ -600,7 +600,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev,
>   
>   	gntdev_dmabuf->u.imp.attach = attach;
>   
> -	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
> +	sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
>   	if (IS_ERR(sgt)) {
>   		ret = ERR_CAST(sgt);
>   		goto fail_detach;
> @@ -658,7 +658,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev,
>   fail_end_access:
>   	dmabuf_imp_end_foreign_access(gntdev_dmabuf->u.imp.refs, count);
>   fail_unmap:
> -	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
> +	dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
>   fail_detach:
>   	dma_buf_detach(dma_buf, attach);
>   fail_free_obj:
> @@ -708,8 +708,8 @@ static int dmabuf_imp_release(struct gntdev_dmabuf_priv *priv, u32 fd)
>   	attach = gntdev_dmabuf->u.imp.attach;
>   
>   	if (gntdev_dmabuf->u.imp.sgt)
> -		dma_buf_unmap_attachment(attach, gntdev_dmabuf->u.imp.sgt,
> -					 DMA_BIDIRECTIONAL);
> +		dma_buf_unmap_attachment_unlocked(attach, gntdev_dmabuf->u.imp.sgt,
> +						  DMA_BIDIRECTIONAL);
>   	dma_buf = attach->dmabuf;
>   	dma_buf_detach(attach->dmabuf, attach);
>   	dma_buf_put(dma_buf);
Christian König Sept. 1, 2022, 7:05 a.m. UTC | #4
Am 31.08.22 um 17:37 schrieb Dmitry Osipenko:
> Prepare Tegra video decoder driver to the common dynamic dma-buf
> locking convention by starting to use the unlocked versions of dma-buf
> API functions.
>
> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>

Acked-by: Christian König <christian.koenig@amd.com>

> ---
>   drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
> index 69c346148070..1c5b94989aec 100644
> --- a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
> +++ b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
> @@ -38,7 +38,7 @@ static void tegra_vde_release_entry(struct tegra_vde_cache_entry *entry)
>   	if (entry->vde->domain)
>   		tegra_vde_iommu_unmap(entry->vde, entry->iova);
>   
> -	dma_buf_unmap_attachment(entry->a, entry->sgt, entry->dma_dir);
> +	dma_buf_unmap_attachment_unlocked(entry->a, entry->sgt, entry->dma_dir);
>   	dma_buf_detach(dmabuf, entry->a);
>   	dma_buf_put(dmabuf);
>   
> @@ -102,7 +102,7 @@ int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
>   		goto err_unlock;
>   	}
>   
> -	sgt = dma_buf_map_attachment(attachment, dma_dir);
> +	sgt = dma_buf_map_attachment_unlocked(attachment, dma_dir);
>   	if (IS_ERR(sgt)) {
>   		dev_err(dev, "Failed to get dmabufs sg_table\n");
>   		err = PTR_ERR(sgt);
> @@ -152,7 +152,7 @@ int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde,
>   err_free:
>   	kfree(entry);
>   err_unmap:
> -	dma_buf_unmap_attachment(attachment, sgt, dma_dir);
> +	dma_buf_unmap_attachment_unlocked(attachment, sgt, dma_dir);
>   err_detach:
>   	dma_buf_detach(dmabuf, attachment);
>   err_unlock:
Christian König Sept. 1, 2022, 7:16 a.m. UTC | #5
Am 31.08.22 um 17:37 schrieb Dmitry Osipenko:
> Add documentation for the dynamic locking convention. The documentation
> tells dma-buf API users when they should take the reservation lock and
> when not.
>
> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>

Reviewed-by: Christian König <christian.koenig@amd.com>

> ---
>   Documentation/driver-api/dma-buf.rst |  6 +++
>   drivers/dma-buf/dma-buf.c            | 64 ++++++++++++++++++++++++++++
>   2 files changed, 70 insertions(+)
>
> diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
> index 36a76cbe9095..622b8156d212 100644
> --- a/Documentation/driver-api/dma-buf.rst
> +++ b/Documentation/driver-api/dma-buf.rst
> @@ -119,6 +119,12 @@ DMA Buffer ioctls
>   
>   .. kernel-doc:: include/uapi/linux/dma-buf.h
>   
> +DMA-BUF locking convention
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +.. kernel-doc:: drivers/dma-buf/dma-buf.c
> +   :doc: locking convention
> +
>   Kernel Functions and Structures Reference
>   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>   
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index d9130486cb8f..97ce884fad76 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -794,6 +794,70 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach,
>   	return sg_table;
>   }
>   
> +/**
> + * DOC: locking convention
> + *
> + * In order to avoid deadlock situations between dma-buf exports and importers,
> + * all dma-buf API users must follow the common dma-buf locking convention.
> + *
> + * Convention for importers
> + *
> + * 1. Importers must hold the dma-buf reservation lock when calling these
> + *    functions:
> + *
> + *     - dma_buf_pin()
> + *     - dma_buf_unpin()
> + *     - dma_buf_map_attachment()
> + *     - dma_buf_unmap_attachment()
> + *     - dma_buf_vmap()
> + *     - dma_buf_vunmap()
> + *
> + * 2. Importers must not hold the dma-buf reservation lock when calling these
> + *    functions:
> + *
> + *     - dma_buf_attach()
> + *     - dma_buf_dynamic_attach()
> + *     - dma_buf_detach()
> + *     - dma_buf_export(
> + *     - dma_buf_fd()
> + *     - dma_buf_get()
> + *     - dma_buf_put()
> + *     - dma_buf_mmap()
> + *     - dma_buf_begin_cpu_access()
> + *     - dma_buf_end_cpu_access()
> + *     - dma_buf_map_attachment_unlocked()
> + *     - dma_buf_unmap_attachment_unlocked()
> + *     - dma_buf_vmap_unlocked()
> + *     - dma_buf_vunmap_unlocked()
> + *
> + * Convention for exporters
> + *
> + * 1. These &dma_buf_ops callbacks are invoked with unlocked dma-buf
> + *    reservation and exporter can take the lock:
> + *
> + *     - &dma_buf_ops.attach()
> + *     - &dma_buf_ops.detach()
> + *     - &dma_buf_ops.release()
> + *     - &dma_buf_ops.begin_cpu_access()
> + *     - &dma_buf_ops.end_cpu_access()
> + *
> + * 2. These &dma_buf_ops callbacks are invoked with locked dma-buf
> + *    reservation and exporter can't take the lock:
> + *
> + *     - &dma_buf_ops.pin()
> + *     - &dma_buf_ops.unpin()
> + *     - &dma_buf_ops.map_dma_buf()
> + *     - &dma_buf_ops.unmap_dma_buf()
> + *     - &dma_buf_ops.mmap()
> + *     - &dma_buf_ops.vmap()
> + *     - &dma_buf_ops.vunmap()
> + *
> + * 3. Exporters must hold the dma-buf reservation lock when calling these
> + *    functions:
> + *
> + *     - dma_buf_move_notify()
> + */
> +
>   /**
>    * dma_buf_dynamic_attach - Add the device to dma_buf's attachments list
>    * @dmabuf:		[in]	buffer to attach device to.
Christian König Sept. 1, 2022, 7:49 a.m. UTC | #6
Hi Dmitry,

I've gone over this multiple times now and while it is still possible 
that we missed something I think that this should land now.

The whole topic is just to complicated that we can 100% sure guarantee 
that there isn't anything wrong with the locking, but lockdep and driver 
testing should allow us to quickly find remaining issues.

Do you have commit rights to drm-misc-next or should I push it?

Thanks,
Christian.

Am 31.08.22 um 17:37 schrieb Dmitry Osipenko:
> Hello,
>
> This series moves all drivers to a dynamic dma-buf locking specification.
>  From now on all dma-buf importers are made responsible for holding
> dma-buf's reservation lock around all operations performed over dma-bufs
> in accordance to the locking specification. This allows us to utilize
> reservation lock more broadly around kernel without fearing of a potential
> deadlocks.
>
> This patchset passes all i915 selftests. It was also tested using VirtIO,
> Panfrost, Lima, Tegra, udmabuf, AMDGPU and Nouveau drivers. I tested cases
> of display+GPU, display+V4L and GPU+V4L dma-buf sharing (where appropriate),
> which covers majority of kernel drivers since rest of the drivers share
> same or similar code paths.
>
> Changelog:
>
> v4: - Added dma_buf_mmap() to the "locking convention" documentation,
>        which was missed by accident in v3.
>
>      - Added acks from Christian König, Tomasz Figa and Hans Verkuil that
>        they gave to couple v3 patches.
>
>      - Dropped the "_unlocked" postfix from function names that don't have
>        the locked variant, as was requested by Christian König.
>
>      - Factored out the per-driver preparations into separate patches
>        to ease reviewing of the changes, which is now doable without the
>        global dma-buf functions renaming.
>
>      - Factored out the dynamic locking convention enforcements into separate
>        patches which add the final dma_resv_assert_held(dmabuf->resv) to the
>        dma-buf API functions.
>
> v3: - Factored out dma_buf_mmap_unlocked() and attachment functions
>        into aseparate patches, like was suggested by Christian König.
>
>      - Corrected and factored out dma-buf locking documentation into
>        a separate patch, like was suggested by Christian König.
>
>      - Intel driver dropped the reservation locking fews days ago from
>        its BO-release code path, but we need that locking for the imported
>        GEMs because in the end that code path unmaps the imported GEM.
>        So I added back the locking needed by the imported GEMs, updating
>        the "dma-buf attachment locking specification" patch appropriately.
>
>      - Tested Nouveau+Intel dma-buf import/export combo.
>
>      - Tested udmabuf import to i915/Nouveau/AMDGPU.
>
>      - Fixed few places in Etnaviv, Panfrost and Lima drivers that I missed
>        to switch to locked dma-buf vmapping in the drm/gem: Take reservation
>        lock for vmap/vunmap operations" patch. In a result invalidated the
>        Christian's r-b that he gave to v2.
>
>      - Added locked dma-buf vmap/vunmap functions that are needed for fixing
>        vmappping of Etnaviv, Panfrost and Lima drivers mentioned above.
>        I actually had this change stashed for the drm-shmem shrinker patchset,
>        but then realized that it's already needed by the dma-buf patches.
>        Also improved my tests to better cover these code paths.
>
> v2: - Changed locking specification to avoid problems with a cross-driver
>        ww locking, like was suggested by Christian König. Now the attach/detach
>        callbacks are invoked without the held lock and exporter should take the
>        lock.
>
>      - Added "locking convention" documentation that explains which dma-buf
>        functions and callbacks are locked/unlocked for importers and exporters,
>        which was requested by Christian König.
>
>      - Added ack from Tomasz Figa to the V4L patches that he gave to v1.
>
> Dmitry Osipenko (21):
>    dma-buf: Add unlocked variant of vmapping functions
>    dma-buf: Add unlocked variant of attachment-mapping functions
>    drm/gem: Take reservation lock for vmap/vunmap operations
>    drm/prime: Prepare to dynamic dma-buf locking specification
>    drm/armada: Prepare to dynamic dma-buf locking specification
>    drm/i915: Prepare to dynamic dma-buf locking specification
>    drm/omapdrm: Prepare to dynamic dma-buf locking specification
>    drm/tegra: Prepare to dynamic dma-buf locking specification
>    drm/etnaviv: Prepare to dynamic dma-buf locking specification
>    RDMA/umem: Prepare to dynamic dma-buf locking specification
>    misc: fastrpc: Prepare to dynamic dma-buf locking specification
>    xen/gntdev: Prepare to dynamic dma-buf locking specification
>    media: videobuf2: Prepare to dynamic dma-buf locking specification
>    media: tegra-vde: Prepare to dynamic dma-buf locking specification
>    dma-buf: Move dma_buf_vmap() to dynamic locking specification
>    dma-buf: Move dma_buf_attach() to dynamic locking specification
>    dma-buf: Move dma_buf_map_attachment() to dynamic locking
>      specification
>    dma-buf: Move dma_buf_mmap() to dynamic locking specification
>    dma-buf: Document dynamic locking convention
>    media: videobuf2: Stop using internal dma-buf lock
>    dma-buf: Remove obsoleted internal lock
>
>   Documentation/driver-api/dma-buf.rst          |   6 +
>   drivers/dma-buf/dma-buf.c                     | 211 +++++++++++++++---
>   drivers/gpu/drm/armada/armada_gem.c           |   8 +-
>   drivers/gpu/drm/drm_client.c                  |   4 +-
>   drivers/gpu/drm/drm_gem.c                     |  24 ++
>   drivers/gpu/drm/drm_gem_dma_helper.c          |   6 +-
>   drivers/gpu/drm/drm_gem_framebuffer_helper.c  |   6 +-
>   drivers/gpu/drm/drm_gem_ttm_helper.c          |   9 +-
>   drivers/gpu/drm/drm_prime.c                   |   6 +-
>   drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c   |   2 +-
>   drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    |   2 +-
>   drivers/gpu/drm/i915/gem/i915_gem_object.c    |  12 +
>   .../drm/i915/gem/selftests/i915_gem_dmabuf.c  |  16 +-
>   drivers/gpu/drm/lima/lima_sched.c             |   4 +-
>   drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c     |   4 +-
>   drivers/gpu/drm/panfrost/panfrost_dump.c      |   4 +-
>   drivers/gpu/drm/panfrost/panfrost_perfcnt.c   |   6 +-
>   drivers/gpu/drm/qxl/qxl_object.c              |  17 +-
>   drivers/gpu/drm/qxl/qxl_prime.c               |   4 +-
>   drivers/gpu/drm/tegra/gem.c                   |  17 +-
>   drivers/infiniband/core/umem_dmabuf.c         |   7 +-
>   .../common/videobuf2/videobuf2-dma-contig.c   |  22 +-
>   .../media/common/videobuf2/videobuf2-dma-sg.c |  19 +-
>   .../common/videobuf2/videobuf2-vmalloc.c      |  17 +-
>   .../platform/nvidia/tegra-vde/dmabuf-cache.c  |   6 +-
>   drivers/misc/fastrpc.c                        |   6 +-
>   drivers/xen/gntdev-dmabuf.c                   |   8 +-
>   include/drm/drm_gem.h                         |   3 +
>   include/linux/dma-buf.h                       |  17 +-
>   29 files changed, 318 insertions(+), 155 deletions(-)
>
Dmitry Osipenko Sept. 1, 2022, 10:47 a.m. UTC | #7
Hello Christian,

On 9/1/22 10:49, Christian König wrote:
> Hi Dmitry,
> 
> I've gone over this multiple times now and while it is still possible
> that we missed something I think that this should land now.

Thank you very much for the review!

> The whole topic is just to complicated that we can 100% sure guarantee
> that there isn't anything wrong with the locking, but lockdep and driver
> testing should allow us to quickly find remaining issues.

At least the most popular drivers should be okay. If anyone will find
issue introduced by this series, then indeed shouldn't be a problem to
fix it later on.

> Do you have commit rights to drm-misc-next or should I push it?

I got the drm-misc commit right two weeks ago, haven't pushed anything
there yet. Please let me try to do the push. I'll let you know if any
kind of help will be needed from you.

I'll wait for more acks/r-bs and then do the push.