[PATCH 8/8] amdgpu: use sync file for shared semaphores (v2)

Daniel Vetter daniel at ffwll.ch
Tue Apr 4 08:10:36 UTC 2017


On Tue, Apr 04, 2017 at 09:40:57AM +0200, Christian König wrote:
> Am 04.04.2017 um 06:27 schrieb Dave Airlie:
> > From: Dave Airlie <airlied at redhat.com>
> > 
> > This creates a new interface for amdgpu with ioctls to
> > create/destroy/import and export shared semaphores using
> > sem object backed by the sync_file code. The semaphores
> > are not installed as fd (except for export), but rather
> > like other driver internal objects in an idr. The idr
> > holds the initial reference on the sync file.
> > 
> > The command submission interface is enhanced with two new
> > chunks, one for semaphore waiting, one for semaphore signalling
> > and just takes a list of handles for each.
> > 
> > This is based on work originally done by David Zhou at AMD,
> > with input from Christian Konig on what things should look like.
> > 
> > NOTE: this interface addition needs a version bump to expose
> > it to userspace.
> > 
> > v1.1: keep file reference on import.
> > v2: move to using syncobjs
> > 
> > Signed-off-by: Dave Airlie <airlied at redhat.com>
> 
> Looks good to me in general, but one note below.
> 
> > ---
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c  | 86 ++++++++++++++++++++++++++++++++-
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c |  2 +-
> >   include/uapi/drm/amdgpu_drm.h           |  6 +++
> >   3 files changed, 92 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
> > index 4671432..4dd210b 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
> > @@ -27,6 +27,7 @@
> >   #include <linux/pagemap.h>
> >   #include <drm/drmP.h>
> >   #include <drm/amdgpu_drm.h>
> > +#include <drm/drm_syncobj.h>
> >   #include "amdgpu.h"
> >   #include "amdgpu_trace.h"
> > @@ -217,6 +218,8 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
> >   			break;
> >   		case AMDGPU_CHUNK_ID_DEPENDENCIES:
> > +		case AMDGPU_CHUNK_ID_SEM_WAIT:
> > +		case AMDGPU_CHUNK_ID_SEM_SIGNAL:
> >   			break;
> >   		default:
> > @@ -1009,6 +1012,44 @@ static int amdgpu_process_fence_dep(struct amdgpu_device *adev,
> >   	return 0;
> >   }
> > +static int amdgpu_sem_lookup_and_sync(struct amdgpu_device *adev,
> > +				      struct drm_file *file_private,
> > +				      struct amdgpu_sync *sync,
> > +				      uint32_t handle)
> > +{
> > +	int r;
> > +	struct dma_fence *old_fence;
> > +	r = drm_syncobj_swap_fences(file_private, handle, NULL, &old_fence);
> 
> What happens when we the CS fails later on? Would the semaphore then not
> contain the fence any more?

Atm rules are that you're not allowed to publish a dma_fence before you're
committed to executing whatever it represents (i.e. guaranteed to get
signalled).

Publish depends upon context, but can include: Install an fd for a type
fence sync_file, swap the sync_file in a sema type, assign it to the
reservation_object for implicit sync.

I guess we need to have drm_syncobj_lookup exported (or whatever it was),
keep a temporary pointer, and then swap it only at the end (with
sync_file_swap_fence or whatever it was).

-Daniel

> 
> Christian.
> 
> > +	if (r)
> > +		return r;
> > +
> > +	r = amdgpu_sync_fence(adev, sync, old_fence);
> > +	dma_fence_put(old_fence);
> > +
> > +	return r;
> > +}
> > +
> > +static int amdgpu_process_sem_wait_dep(struct amdgpu_device *adev,
> > +				       struct amdgpu_cs_parser *p,
> > +				       struct amdgpu_cs_chunk *chunk)
> > +{
> > +	unsigned num_deps;
> > +	int i, r;
> > +	struct drm_amdgpu_cs_chunk_sem *deps;
> > +
> > +	deps = (struct drm_amdgpu_cs_chunk_sem *)chunk->kdata;
> > +	num_deps = chunk->length_dw * 4 /
> > +		sizeof(struct drm_amdgpu_cs_chunk_sem);
> > +
> > +	for (i = 0; i < num_deps; ++i) {
> > +		r = amdgpu_sem_lookup_and_sync(adev, p->filp, &p->job->sync,
> > +					       deps[i].handle);
> > +		if (r)
> > +			return r;
> > +	}
> > +	return 0;
> > +}
> > +
> >   static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
> >   				  struct amdgpu_cs_parser *p)
> >   {
> > @@ -1023,12 +1064,55 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
> >   			r = amdgpu_process_fence_dep(adev, p, chunk);
> >   			if (r)
> >   				return r;
> > +		} else if (chunk->chunk_id == AMDGPU_CHUNK_ID_SEM_WAIT) {
> > +			r = amdgpu_process_sem_wait_dep(adev, p, chunk);
> > +			if (r)
> > +				return r;
> >   		}
> >   	}
> >   	return 0;
> >   }
> > +static int amdgpu_process_sem_signal_dep(struct amdgpu_cs_parser *p,
> > +					 struct amdgpu_cs_chunk *chunk,
> > +					 struct dma_fence *fence)
> > +{
> > +	unsigned num_deps;
> > +	int i, r;
> > +	struct drm_amdgpu_cs_chunk_sem *deps;
> > +
> > +	deps = (struct drm_amdgpu_cs_chunk_sem *)chunk->kdata;
> > +	num_deps = chunk->length_dw * 4 /
> > +		sizeof(struct drm_amdgpu_cs_chunk_sem);
> > +
> > +	for (i = 0; i < num_deps; ++i) {
> > +		r = drm_syncobj_replace_fence(p->filp, deps[i].handle,
> > +					      fence);
> > +		if (r)
> > +			return r;
> > +	}
> > +	return 0;
> > +}
> > +
> > +static int amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
> > +{
> > +	int i, r;
> > +
> > +	for (i = 0; i < p->nchunks; ++i) {
> > +		struct amdgpu_cs_chunk *chunk;
> > +
> > +		chunk = &p->chunks[i];
> > +
> > +		if (chunk->chunk_id == AMDGPU_CHUNK_ID_SEM_SIGNAL) {
> > +			r = amdgpu_process_sem_signal_dep(p, chunk, p->fence);
> > +			if (r)
> > +				return r;
> > +		}
> > +	}
> > +	return 0;
> > +}
> > +
> >   static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
> >   			    union drm_amdgpu_cs *cs)
> >   {
> > @@ -1056,7 +1140,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
> >   	trace_amdgpu_cs_ioctl(job);
> >   	amd_sched_entity_push_job(&job->base);
> > -	return 0;
> > +	return amdgpu_cs_post_dependencies(p);
> >   }
> >   int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > index b76cd69..e95951e 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> > @@ -683,7 +683,7 @@ static struct drm_driver kms_driver = {
> >   	.driver_features =
> >   	    DRIVER_USE_AGP |
> >   	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
> > -	    DRIVER_PRIME | DRIVER_RENDER | DRIVER_MODESET,
> > +	    DRIVER_PRIME | DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ,
> >   	.load = amdgpu_driver_load_kms,
> >   	.open = amdgpu_driver_open_kms,
> >   	.preclose = amdgpu_driver_preclose_kms,
> > diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
> > index 5797283..647c520 100644
> > --- a/include/uapi/drm/amdgpu_drm.h
> > +++ b/include/uapi/drm/amdgpu_drm.h
> > @@ -390,6 +390,8 @@ struct drm_amdgpu_gem_va {
> >   #define AMDGPU_CHUNK_ID_IB		0x01
> >   #define AMDGPU_CHUNK_ID_FENCE		0x02
> >   #define AMDGPU_CHUNK_ID_DEPENDENCIES	0x03
> > +#define AMDGPU_CHUNK_ID_SEM_WAIT        0x04
> > +#define AMDGPU_CHUNK_ID_SEM_SIGNAL      0x05
> >   struct drm_amdgpu_cs_chunk {
> >   	__u32		chunk_id;
> > @@ -454,6 +456,10 @@ struct drm_amdgpu_cs_chunk_fence {
> >   	__u32 offset;
> >   };
> > +struct drm_amdgpu_cs_chunk_sem {
> > +	__u32 handle;
> > +};
> > +
> >   struct drm_amdgpu_cs_chunk_data {
> >   	union {
> >   		struct drm_amdgpu_cs_chunk_ib		ib_data;
> 
> 
> _______________________________________________
> 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