[PATCH 1/3] drm/etnaviv: submit support for in-fences

Gustavo Padovan gustavo at padovan.org
Wed Mar 8 14:37:48 UTC 2017


Hi Philipp,

2017-03-08 Philipp Zabel <p.zabel at pengutronix.de>:

> Loosely based on commit f0a42bb5423a ("drm/msm: submit support for
> in-fences"). Unfortunately, struct drm_etnaviv_gem_submit doesn't have
> a flags field yet, so we have to extend the structure and trust that
> drm_ioctl will clear the flags for us if an older userspace only submits
> part of the struct.
> 
> Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
> ---
>  drivers/gpu/drm/etnaviv/Kconfig              |  1 +
>  drivers/gpu/drm/etnaviv/etnaviv_gem.h        |  1 +
>  drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 34 +++++++++++++++++++++++++++-
>  drivers/gpu/drm/etnaviv/etnaviv_gpu.c        |  5 +++-
>  drivers/gpu/drm/etnaviv/etnaviv_gpu.h        |  2 +-
>  include/uapi/drm/etnaviv_drm.h               |  6 +++++
>  6 files changed, 46 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig
> index cc1731c5289c2..71cee4e9fefbb 100644
> --- a/drivers/gpu/drm/etnaviv/Kconfig
> +++ b/drivers/gpu/drm/etnaviv/Kconfig
> @@ -5,6 +5,7 @@ config DRM_ETNAVIV
>  	depends on ARCH_MXC || ARCH_DOVE || (ARM && COMPILE_TEST)
>  	depends on MMU
>  	select SHMEM
> +	select SYNC_FILE
>  	select TMPFS
>  	select IOMMU_API
>  	select IOMMU_SUPPORT
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
> index e63ff116a3b3d..120410d67eb5b 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
> @@ -107,6 +107,7 @@ struct etnaviv_gem_submit {
>  	u32 fence;
>  	unsigned int nr_bos;
>  	struct etnaviv_gem_submit_bo bos[0];
> +	u32 flags;
>  };
>  
>  int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
> index 726090d7a6ace..e67d83eac22dc 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
> @@ -15,6 +15,7 @@
>   */
>  
>  #include <linux/reservation.h>
> +#include <linux/sync_file.h>
>  #include "etnaviv_cmdbuf.h"
>  #include "etnaviv_drv.h"
>  #include "etnaviv_gpu.h"
> @@ -169,8 +170,10 @@ static int submit_fence_sync(const struct etnaviv_gem_submit *submit)
>  	for (i = 0; i < submit->nr_bos; i++) {
>  		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
>  		bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE;
> +		bool explicit = !(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);
>  
> -		ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write);
> +		ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write,
> +						 explicit);
>  		if (ret)
>  			break;
>  	}
> @@ -303,6 +306,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
>  	struct etnaviv_gem_submit *submit;
>  	struct etnaviv_cmdbuf *cmdbuf;
>  	struct etnaviv_gpu *gpu;
> +	struct dma_fence *in_fence = NULL;
>  	void *stream;
>  	int ret;
>  
> @@ -326,6 +330,11 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
>  		return -EINVAL;
>  	}
>  
> +	if (args->flags & ~ETNA_SUBMIT_FLAGS) {
> +		DRM_ERROR("invalid flags: 0x%x\n", args->flags);
> +		return -EINVAL;
> +	}
> +
>  	/*
>  	 * Copy the command submission and bo array to kernel space in
>  	 * one go, and do this outside of any locks.
> @@ -371,6 +380,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
>  		goto err_submit_cmds;
>  	}
>  
> +	submit->flags = args->flags;
> +
>  	ret = submit_lookup_objects(submit, file, bos, args->nr_bos);
>  	if (ret)
>  		goto err_submit_objects;
> @@ -385,6 +396,25 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
>  		goto err_submit_objects;
>  	}
>  
> +	if (args->flags & ETNA_SUBMIT_FENCE_FD_IN) {
> +		in_fence = sync_file_get_fence(args->fence_fd);
> +		if (!in_fence) {
> +			ret = -EINVAL;
> +			goto err_submit_objects;
> +		}
> +
> +		/* TODO if we get an array-fence due to userspace merging
> +		 * multiple fences, we need a way to determine if all the
> +		 * backing fences are from our own context..
> +		 */

All GPU drivers seem to have the same need on fence_array, so I think we
can create a fence array helper to inspect if it has a specific context
or not.

> +
> +		if (in_fence->context != gpu->fence_context) {
> +			ret = dma_fence_wait(in_fence, true);
> +			if (ret)
> +				goto err_submit_objects;

sync_file_get_fence() hold a fence ref, we need to release it here
always and not only in case of error.

> +		}
> +	}
> +
>  	ret = submit_fence_sync(submit);
>  	if (ret)
>  		goto err_submit_objects;
> @@ -419,6 +449,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
>  		flush_workqueue(priv->wq);
>  
>  err_submit_objects:
> +	if (in_fence)
> +		dma_fence_put(in_fence);
>  	submit_cleanup(submit);
>  
>  err_submit_cmds:
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> index 130d7d517a19a..51d52c72aef17 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> @@ -1064,7 +1064,7 @@ static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
>  }
>  
>  int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
> -	unsigned int context, bool exclusive)
> +	unsigned int context, bool exclusive, bool explicit)
>  {
>  	struct reservation_object *robj = etnaviv_obj->resv;
>  	struct reservation_object_list *fobj;
> @@ -1077,6 +1077,9 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
>  			return ret;
>  	}
>  
> +	if (explicit)
> +		return 0;
> +
>  	/*
>  	 * If we have any shared fences, then the exclusive fence
>  	 * should be ignored as it will already have been signalled.
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
> index 1c0606ea7d5e8..dc27c7a039060 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
> @@ -181,7 +181,7 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
>  #endif
>  
>  int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj,
> -	unsigned int context, bool exclusive);
> +	unsigned int context, bool exclusive, bool implicit);
>  
>  void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
>  int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
> diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h
> index 2584c1cca42f6..e9c388a1d8ebe 100644
> --- a/include/uapi/drm/etnaviv_drm.h
> +++ b/include/uapi/drm/etnaviv_drm.h
> @@ -154,6 +154,10 @@ struct drm_etnaviv_gem_submit_bo {
>   * one or more cmdstream buffers.  This allows for conditional execution
>   * (context-restore), and IB buffers needed for per tile/bin draw cmds.
>   */
> +#define ETNA_SUBMIT_NO_IMPLICIT         0x0001
> +#define ETNA_SUBMIT_FENCE_FD_IN         0x0002

ETNA_SUBMIT_NO_IMPLICIT and ETNA_SUBMIT_FENCE_FD_IN are the same, when
you send and fence_fd to the kernel you are requesting on explicit sync
thus I think the ETNA_SUBMIT_NO_IMPLICIT can be dropped and
ETNA_SUBMIT_FENCE_FD_IN would be the one to look at.

> +#define ETNA_SUBMIT_FLAGS		(ETNA_SUBMIT_NO_IMPLICIT | \
> +					 ETNA_SUBMIT_FENCE_FD_IN)
>  #define ETNA_PIPE_3D      0x00
>  #define ETNA_PIPE_2D      0x01
>  #define ETNA_PIPE_VG      0x02
> @@ -167,6 +171,8 @@ struct drm_etnaviv_gem_submit {
>  	__u64 bos;            /* in, ptr to array of submit_bo's */
>  	__u64 relocs;         /* in, ptr to array of submit_reloc's */
>  	__u64 stream;         /* in, ptr to cmdstream */
> +	__u32 flags;          /* in, mask of ETNA_SUBMIT_x */
> +	__s32 fence_fd;       /* in, fence fd (see ETNA_SUBMIT_FENCE_FD_IN) */
>  };
>  
>  /* The normal way to synchronize with the GPU is just to CPU_PREP on
> -- 
> 2.11.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the etnaviv mailing list