diff mbox series

drm/syncobj: Add better overview documentation for syncobj (v2)

Message ID 20190806161905.30769-1-jason@jlekstrand.net (mailing list archive)
State New, archived
Headers show
Series drm/syncobj: Add better overview documentation for syncobj (v2) | expand

Commit Message

Jason Ekstrand Aug. 6, 2019, 4:19 p.m. UTC
This patch only brings the syncobj documentation up-to-date for the
original form of syncobj.  It does not contain any information about the
design of timeline syncobjs.

v2: Incorporate feedback from Lionel and Christian:
 - Mention actual ioctl and flag names
 - Better language around reference counting
 - Misc. language cleanups

Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
---
 drivers/gpu/drm/drm_syncobj.c | 98 +++++++++++++++++++++++++++++++----
 1 file changed, 87 insertions(+), 11 deletions(-)

Comments

Lionel Landwerlin Aug. 7, 2019, 2:06 p.m. UTC | #1
On 06/08/2019 19:19, Jason Ekstrand wrote:
> This patch only brings the syncobj documentation up-to-date for the
> original form of syncobj.  It does not contain any information about the
> design of timeline syncobjs.
>
> v2: Incorporate feedback from Lionel and Christian:
>   - Mention actual ioctl and flag names
>   - Better language around reference counting
>   - Misc. language cleanups
>
> Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>

> ---
>   drivers/gpu/drm/drm_syncobj.c | 98 +++++++++++++++++++++++++++++++----
>   1 file changed, 87 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
> index 1438dcb3ebb1..4b5c7b0ed714 100644
> --- a/drivers/gpu/drm/drm_syncobj.c
> +++ b/drivers/gpu/drm/drm_syncobj.c
> @@ -29,21 +29,97 @@
>   /**
>    * DOC: Overview
>    *
> - * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are
> - * persistent objects that contain an optional fence. The fence can be updated
> - * with a new fence, or be NULL.
> + * DRM synchronisation objects (syncobj, see struct &drm_syncobj) provide a
> + * container for a synchronization primitive which can be used by userspace
> + * to explicitly synchronize GPU commands, can be shared between userspace
> + * processes, and can be shared between different DRM drivers.
> + * Their primary use-case is to implement Vulkan fences and semaphores.
> + * The syncobj userspace API provides ioctls for several operations:
>    *
> - * syncobj's can be waited upon, where it will wait for the underlying
> - * fence.
> + *  - Creation and destruction of syncobjs
> + *  - Import and export of syncobjs to/from a syncobj file descriptor
> + *  - Import and export a syncobj's underlying fence to/from a sync file
> + *  - Reset a syncobj (set its fence to NULL)
> + *  - Signal a syncobj (set a trivially signaled fence)
> + *  - Wait for a syncobj's fence to appear and be signaled
>    *
> - * syncobj's can be export to fd's and back, these fd's are opaque and
> - * have no other use case, except passing the syncobj between processes.
> + * At it's core, a syncobj is simply a wrapper around a pointer to a struct
> + * &dma_fence which may be NULL.
> + * When a syncobj is first created, its pointer is either NULL or a pointer
> + * to an already signaled fence depending on whether the
> + * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to
> + * &DRM_IOCTL_SYNCOBJ_CREATE.
> + * When GPU work which signals a syncobj is enqueued in a DRM driver,
> + * the syncobj fence is replaced with a fence which will be signaled by the
> + * completion of that work.
> + * When GPU work which waits on a syncobj is enqueued in a DRM driver, the
> + * driver retrieves syncobj's current fence at the time the work is enqueued
> + * waits on that fence before submitting the work to hardware.
> + * If the syncobj's fence is NULL, the enqueue operation is expected to fail.
> + * All manipulation of the syncobjs's fence happens in terms of the current
> + * fence at the time the ioctl is called by userspace regardless of whether
> + * that operation is an immediate host-side operation (signal or reset) or
> + * or an operation which is enqueued in some driver queue.
> + * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used to
> + * manipulate a syncobj from the host by resetting its pointer to NULL or
> + * setting its pointer to a fence which is already signaled.
>    *
> - * Their primary use-case is to implement Vulkan fences and semaphores.
>    *
> - * syncobj have a kref reference count, but also have an optional file.
> - * The file is only created once the syncobj is exported.
> - * The file takes a reference on the kref.
> + * Host-side wait on syncobjs
> + * --------------------------
> + *
> + * &DRM_IOCTL_SYNCOBJ_WAIT takes an array of syncobj handles and does a
> + * host-side wait on all of the syncobj fences simultaneously.
> + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL is set, the wait ioctl will wait on
> + * all of the syncobj fences to be signaled before it returns.
> + * Otherwise, it returns once at least one syncobj fence has been signaled
> + * and the index of a signaled fence is written back to the client.
> + *
> + * Unlike the enqueued GPU work dependencies which fail if they see a NULL
> + * fence in a syncobj, if &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is set,
> + * the host-side wait will first wait for the syncobj to receive a non-NULL
> + * fence and then wait on that fence.
> + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is not set and any one of the
> + * syncobjs in the array has a NULL fence, -EINVAL will be returned.
> + * Assuming the syncobj starts off with a NULL fence, this allows a client
> + * to do a host wait in one thread (or process) which waits on GPU work
> + * submitted in another thread (or process) without having to manually
> + * synchronize between the two.
> + * This requirement is inherited from the Vulkan fence API.
> + *
> + *
> + * Import/export of syncobjs
> + * -------------------------
> + *
> + * &DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE and &DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD
> + * provide two mechanisms for import/export of syncobjs.
> + *
> + * The first lets the client import or export an entire syncobj to a file
> + * descriptor.
> + * These fd's are opaque and have no other use case, except passing the
> + * syncobj between processes.
> + * All exported file descriptors and any syncobj handles created as a
> + * result of importing those file descriptors own a reference to the
> + * same underlying struct &drm_syncobj and the syncobj can be used
> + * persistently across all the processes with which it is shared.
> + * The syncobj is freed only once the last reference is dropped.
> + * Unlike dma-buf, importing a syncobj creates a new handle (with its own
> + * reference) for every import instead of de-duplicating.
> + * The primary use-case of this persistent import/export is for shared
> + * Vulkan fences and semaphores.
> + *
> + * The second import/export mechanism, which is indicated by
> + * &DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE or
> + * &DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE lets the client
> + * import/export the syncobj's current fence from/to a &sync_file.
> + * When a syncobj is exported to a sync file, that sync file wraps the
> + * sycnobj's fence at the time of export and any later signal or reset
> + * operations on the syncobj will not affect the exported sync file.
> + * When a sync file is imported into a syncobj, the syncobj's fence is set
> + * to the fence wrapped by that sync file.
> + * Because sync files are immutable, resetting or signaling the syncobj
> + * will not affect any sync files whose fences have been imported into the
> + * syncobj.
>    */
>   
>   #include <linux/anon_inodes.h>
Jason Ekstrand Aug. 8, 2019, 4:47 a.m. UTC | #2
Christan, any thoughts on v2?

--Jason


On August 7, 2019 09:06:47 Lionel Landwerlin 
<lionel.g.landwerlin@intel.com> wrote:

> On 06/08/2019 19:19, Jason Ekstrand wrote:
>> This patch only brings the syncobj documentation up-to-date for the
>> original form of syncobj.  It does not contain any information about the
>> design of timeline syncobjs.
>>
>> v2: Incorporate feedback from Lionel and Christian:
>>   - Mention actual ioctl and flag names
>>   - Better language around reference counting
>>   - Misc. language cleanups
>>
>> Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
>
> Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
>
>> ---
>>   drivers/gpu/drm/drm_syncobj.c | 98 +++++++++++++++++++++++++++++++----
>>   1 file changed, 87 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
>> index 1438dcb3ebb1..4b5c7b0ed714 100644
>> --- a/drivers/gpu/drm/drm_syncobj.c
>> +++ b/drivers/gpu/drm/drm_syncobj.c
>> @@ -29,21 +29,97 @@
>>   /**
>>    * DOC: Overview
>>    *
>> - * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are
>> - * persistent objects that contain an optional fence. The fence can be updated
>> - * with a new fence, or be NULL.
>> + * DRM synchronisation objects (syncobj, see struct &drm_syncobj) provide a
>> + * container for a synchronization primitive which can be used by userspace
>> + * to explicitly synchronize GPU commands, can be shared between userspace
>> + * processes, and can be shared between different DRM drivers.
>> + * Their primary use-case is to implement Vulkan fences and semaphores.
>> + * The syncobj userspace API provides ioctls for several operations:
>>    *
>> - * syncobj's can be waited upon, where it will wait for the underlying
>> - * fence.
>> + *  - Creation and destruction of syncobjs
>> + *  - Import and export of syncobjs to/from a syncobj file descriptor
>> + *  - Import and export a syncobj's underlying fence to/from a sync file
>> + *  - Reset a syncobj (set its fence to NULL)
>> + *  - Signal a syncobj (set a trivially signaled fence)
>> + *  - Wait for a syncobj's fence to appear and be signaled
>>    *
>> - * syncobj's can be export to fd's and back, these fd's are opaque and
>> - * have no other use case, except passing the syncobj between processes.
>> + * At it's core, a syncobj is simply a wrapper around a pointer to a struct
>> + * &dma_fence which may be NULL.
>> + * When a syncobj is first created, its pointer is either NULL or a pointer
>> + * to an already signaled fence depending on whether the
>> + * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to
>> + * &DRM_IOCTL_SYNCOBJ_CREATE.
>> + * When GPU work which signals a syncobj is enqueued in a DRM driver,
>> + * the syncobj fence is replaced with a fence which will be signaled by the
>> + * completion of that work.
>> + * When GPU work which waits on a syncobj is enqueued in a DRM driver, the
>> + * driver retrieves syncobj's current fence at the time the work is enqueued
>> + * waits on that fence before submitting the work to hardware.
>> + * If the syncobj's fence is NULL, the enqueue operation is expected to fail.
>> + * All manipulation of the syncobjs's fence happens in terms of the current
>> + * fence at the time the ioctl is called by userspace regardless of whether
>> + * that operation is an immediate host-side operation (signal or reset) or
>> + * or an operation which is enqueued in some driver queue.
>> + * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used to
>> + * manipulate a syncobj from the host by resetting its pointer to NULL or
>> + * setting its pointer to a fence which is already signaled.
>>    *
>> - * Their primary use-case is to implement Vulkan fences and semaphores.
>>    *
>> - * syncobj have a kref reference count, but also have an optional file.
>> - * The file is only created once the syncobj is exported.
>> - * The file takes a reference on the kref.
>> + * Host-side wait on syncobjs
>> + * --------------------------
>> + *
>> + * &DRM_IOCTL_SYNCOBJ_WAIT takes an array of syncobj handles and does a
>> + * host-side wait on all of the syncobj fences simultaneously.
>> + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL is set, the wait ioctl will wait on
>> + * all of the syncobj fences to be signaled before it returns.
>> + * Otherwise, it returns once at least one syncobj fence has been signaled
>> + * and the index of a signaled fence is written back to the client.
>> + *
>> + * Unlike the enqueued GPU work dependencies which fail if they see a NULL
>> + * fence in a syncobj, if &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is set,
>> + * the host-side wait will first wait for the syncobj to receive a non-NULL
>> + * fence and then wait on that fence.
>> + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is not set and any one of the
>> + * syncobjs in the array has a NULL fence, -EINVAL will be returned.
>> + * Assuming the syncobj starts off with a NULL fence, this allows a client
>> + * to do a host wait in one thread (or process) which waits on GPU work
>> + * submitted in another thread (or process) without having to manually
>> + * synchronize between the two.
>> + * This requirement is inherited from the Vulkan fence API.
>> + *
>> + *
>> + * Import/export of syncobjs
>> + * -------------------------
>> + *
>> + * &DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE and &DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD
>> + * provide two mechanisms for import/export of syncobjs.
>> + *
>> + * The first lets the client import or export an entire syncobj to a file
>> + * descriptor.
>> + * These fd's are opaque and have no other use case, except passing the
>> + * syncobj between processes.
>> + * All exported file descriptors and any syncobj handles created as a
>> + * result of importing those file descriptors own a reference to the
>> + * same underlying struct &drm_syncobj and the syncobj can be used
>> + * persistently across all the processes with which it is shared.
>> + * The syncobj is freed only once the last reference is dropped.
>> + * Unlike dma-buf, importing a syncobj creates a new handle (with its own
>> + * reference) for every import instead of de-duplicating.
>> + * The primary use-case of this persistent import/export is for shared
>> + * Vulkan fences and semaphores.
>> + *
>> + * The second import/export mechanism, which is indicated by
>> + * &DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE or
>> + * &DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE lets the client
>> + * import/export the syncobj's current fence from/to a &sync_file.
>> + * When a syncobj is exported to a sync file, that sync file wraps the
>> + * sycnobj's fence at the time of export and any later signal or reset
>> + * operations on the syncobj will not affect the exported sync file.
>> + * When a sync file is imported into a syncobj, the syncobj's fence is set
>> + * to the fence wrapped by that sync file.
>> + * Because sync files are immutable, resetting or signaling the syncobj
>> + * will not affect any sync files whose fences have been imported into the
>> + * syncobj.
>>    */
>>
>>   #include <linux/anon_inodes.h>
Christian König Aug. 8, 2019, 7:25 a.m. UTC | #3
Hi Jason,

this mail also somehow ended up to be rejected by our spam filter and 
I'm not sure why :(

Anyway, feel free to add my Acked-by. From the technical point I would 
give an r-b as well, but I'm not a native speaker of English.

Cheers,
Christian.

Am 08.08.19 um 06:47 schrieb Jason Ekstrand:
> Christan, any thoughts on v2?
>
> --Jason
>
>
> On August 7, 2019 09:06:47 Lionel Landwerlin 
> <lionel.g.landwerlin@intel.com> wrote:
>
>> On 06/08/2019 19:19, Jason Ekstrand wrote:
>>> This patch only brings the syncobj documentation up-to-date for the
>>> original form of syncobj.  It does not contain any information about 
>>> the
>>> design of timeline syncobjs.
>>>
>>> v2: Incorporate feedback from Lionel and Christian:
>>>   - Mention actual ioctl and flag names
>>>   - Better language around reference counting
>>>   - Misc. language cleanups
>>>
>>> Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
>>
>> Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
>>
>>> ---
>>>   drivers/gpu/drm/drm_syncobj.c | 98 
>>> +++++++++++++++++++++++++++++++----
>>>   1 file changed, 87 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/drm_syncobj.c 
>>> b/drivers/gpu/drm/drm_syncobj.c
>>> index 1438dcb3ebb1..4b5c7b0ed714 100644
>>> --- a/drivers/gpu/drm/drm_syncobj.c
>>> +++ b/drivers/gpu/drm/drm_syncobj.c
>>> @@ -29,21 +29,97 @@
>>>   /**
>>>    * DOC: Overview
>>>    *
>>> - * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are
>>> - * persistent objects that contain an optional fence. The Ok,fence 
>>> can be updated
>>> - * with a new fence, or be NULL.
>>> + * DRM synchronisation objects (syncobj, see struct &drm_syncobj) 
>>> provide a
>>> + * container for a synchronization primitive which can be used by 
>>> userspace
>>> + * to explicitly synchronize GPU commands, can be shared between 
>>> userspace
>>> + * processes, and can be shared between different DRM drivers.
>>> + * Their primary use-case is to implement Vulkan fences and 
>>> semaphores.
>>> + * The syncobj userspace API provides ioctls for several operations:
>>>    *
>>> - * syncobj's can be waited upon, where it will wait for the underlying
>>> - * fence.
>>> + *  - Creation and destruction of syncobjs
>>> + *  - Import and export of syncobjs to/from a syncobj file descriptor
>>> + *  - Import and export a syncobj's underlying fence to/from a sync 
>>> file
>>> + *  - Reset a syncobj (set its fence to NULL)
>>> + *  - Signal a syncobj (set a trivially signaled fence)
>>> + *  - Wait for a syncobj's fence to appear and be signaled
>>>    *
>>> - * syncobj's can be export to fd's and back, these fd's are opaque and
>>> - * have no other use case, except passing the syncobj between 
>>> processes.
>>> + * At it's core, a syncobj is simply a wrapper around a pointer to 
>>> a struct
>>> + * &dma_fence which may be NULL.
>>> + * When a syncobj is first created, its pointer is either NULL or a 
>>> pointer
>>> + * to an already signaled fence depending on whether the
>>> + * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to
>>> + * &DRM_IOCTL_SYNCOBJ_CREATE.
>>> + * When GPU work which signals a syncobj is enqueued in a DRM driver,
>>> + * the syncobj fence is replaced with a fence which will be 
>>> signaled by the
>>> + * completion of that work.
>>> + * When GPU work which waits on a syncobj is enqueued in a DRM 
>>> driver, the
>>> + * driver retrieves syncobj's current fence at the time the work is 
>>> enqueued
>>> + * waits on that fence before submitting the work to hardware.
>>> + * If the syncobj's fence is NULL, the enqueue operation is 
>>> expected to fail.
>>> + * All manipulation of the syncobjs's fence happens in terms of the 
>>> current
>>> + * fence at the time the ioctl is called by userspace regardless of 
>>> whether
>>> + * that operation is an immediate host-side operation (signal or 
>>> reset) or
>>> + * or an operation which is enqueued in some driver queue.
>>> + * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be 
>>> used to
>>> + * manipulate a syncobj from the host by resetting its pointer to 
>>> NULL or
>>> + * setting its pointer to a fence which is already signaled.
>>>    *
>>> - * Their primary use-case is to implement Vulkan fences and 
>>> semaphores.
>>>    *
>>> - * syncobj have a kref reference count, but also have an optional 
>>> file.
>>> - * The file is only created once the syncobj is exported.
>>> - * The file takes a reference on the kref.
>>> + * Host-side wait on syncobjs
>>> + * --------------------------
>>> + *
>>> + * &DRM_IOCTL_SYNCOBJ_WAIT takes an array of syncobj handles and 
>>> does a
>>> + * host-side wait on all of the syncobj fences simultaneously.
>>> + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL is set, the wait ioctl will 
>>> wait on
>>> + * all of the syncobj fences to be signaled before it returns.
>>> + * Otherwise, it returns once at least one syncobj fence has been 
>>> signaled
>>> + * and the index of a signaled fence is written back to the client.
>>> + *
>>> + * Unlike the enqueued GPU work dependencies which fail if they see 
>>> a NULL
>>> + * fence in a syncobj, if &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT 
>>> is set,
>>> + * the host-side wait will first wait for the syncobj to receive a 
>>> non-NULL
>>> + * fence and then wait on that fence.
>>> + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is not set and any 
>>> one of the
>>> + * syncobjs in the array has a NULL fence, -EINVAL will be returned.
>>> + * Assuming the syncobj starts off with a NULL fence, this allows a 
>>> client
>>> + * to do a host wait in one thread (or process) which waits on GPU 
>>> work
>>> + * submitted in another thread (or process) without having to manually
>>> + * synchronize between the two.
>>> + * This requirement is inherited from the Vulkan fence API.
>>> + *
>>> + *
>>> + * Import/export of syncobjs
>>> + * -------------------------
>>> + *
>>> + * &DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE and &DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD
>>> + * provide two mechanisms for import/export of syncobjs.
>>> + *
>>> + * The first lets the client import or export an entire syncobj to 
>>> a file
>>> + * descriptor.
>>> + * These fd's are opaque and have no other use case, except passing 
>>> the
>>> + * syncobj between processes.
>>> + * All exported file descriptors and any syncobj handles created as a
>>> + * result of importing those file descriptors own a reference to the
>>> + * same underlying struct &drm_syncobj and the syncobj can be used
>>> + * persistently across all the processes with which it is shared.
>>> + * The syncobj is freed only once the last reference is dropped.
>>> + * Unlike dma-buf, importing a syncobj creates a new handle (with 
>>> its own
>>> + * reference) for every import instead of de-duplicating.
>>> + * The primary use-case of this persistent import/export is for shared
>>> + * Vulkan fences and semaphores.
>>> + *
>>> + * The second import/export mechanism, which is indicated by
>>> + * &DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE or
>>> + * &DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE lets the client
>>> + * import/export the syncobj's current fence from/to a &sync_file.
>>> + * When a syncobj is exported to a sync file, that sync file wraps the
>>> + * sycnobj's fence at the time of export and any later signal or reset
>>> + * operations on the syncobj will not affect the exported sync file.
>>> + * When a sync file is imported into a syncobj, the syncobj's fence 
>>> is set
>>> + * to the fence wrapped by that sync file.
>>> + * Because sync files are immutable, resetting or signaling the 
>>> syncobj
>>> + * will not affect any sync files whose fences have been imported 
>>> into the
>>> + * syncobj.
>>>    */
>>>
>>>   #include <linux/anon_inodes.h>
>
>
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 1438dcb3ebb1..4b5c7b0ed714 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -29,21 +29,97 @@ 
 /**
  * DOC: Overview
  *
- * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are
- * persistent objects that contain an optional fence. The fence can be updated
- * with a new fence, or be NULL.
+ * DRM synchronisation objects (syncobj, see struct &drm_syncobj) provide a
+ * container for a synchronization primitive which can be used by userspace
+ * to explicitly synchronize GPU commands, can be shared between userspace
+ * processes, and can be shared between different DRM drivers.
+ * Their primary use-case is to implement Vulkan fences and semaphores.
+ * The syncobj userspace API provides ioctls for several operations:
  *
- * syncobj's can be waited upon, where it will wait for the underlying
- * fence.
+ *  - Creation and destruction of syncobjs
+ *  - Import and export of syncobjs to/from a syncobj file descriptor
+ *  - Import and export a syncobj's underlying fence to/from a sync file
+ *  - Reset a syncobj (set its fence to NULL)
+ *  - Signal a syncobj (set a trivially signaled fence)
+ *  - Wait for a syncobj's fence to appear and be signaled
  *
- * syncobj's can be export to fd's and back, these fd's are opaque and
- * have no other use case, except passing the syncobj between processes.
+ * At it's core, a syncobj is simply a wrapper around a pointer to a struct
+ * &dma_fence which may be NULL.
+ * When a syncobj is first created, its pointer is either NULL or a pointer
+ * to an already signaled fence depending on whether the
+ * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to
+ * &DRM_IOCTL_SYNCOBJ_CREATE.
+ * When GPU work which signals a syncobj is enqueued in a DRM driver,
+ * the syncobj fence is replaced with a fence which will be signaled by the
+ * completion of that work.
+ * When GPU work which waits on a syncobj is enqueued in a DRM driver, the
+ * driver retrieves syncobj's current fence at the time the work is enqueued
+ * waits on that fence before submitting the work to hardware.
+ * If the syncobj's fence is NULL, the enqueue operation is expected to fail.
+ * All manipulation of the syncobjs's fence happens in terms of the current
+ * fence at the time the ioctl is called by userspace regardless of whether
+ * that operation is an immediate host-side operation (signal or reset) or
+ * or an operation which is enqueued in some driver queue.
+ * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used to
+ * manipulate a syncobj from the host by resetting its pointer to NULL or
+ * setting its pointer to a fence which is already signaled.
  *
- * Their primary use-case is to implement Vulkan fences and semaphores.
  *
- * syncobj have a kref reference count, but also have an optional file.
- * The file is only created once the syncobj is exported.
- * The file takes a reference on the kref.
+ * Host-side wait on syncobjs
+ * --------------------------
+ *
+ * &DRM_IOCTL_SYNCOBJ_WAIT takes an array of syncobj handles and does a
+ * host-side wait on all of the syncobj fences simultaneously.
+ * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL is set, the wait ioctl will wait on
+ * all of the syncobj fences to be signaled before it returns.
+ * Otherwise, it returns once at least one syncobj fence has been signaled
+ * and the index of a signaled fence is written back to the client.
+ *
+ * Unlike the enqueued GPU work dependencies which fail if they see a NULL
+ * fence in a syncobj, if &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is set,
+ * the host-side wait will first wait for the syncobj to receive a non-NULL
+ * fence and then wait on that fence.
+ * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is not set and any one of the
+ * syncobjs in the array has a NULL fence, -EINVAL will be returned.
+ * Assuming the syncobj starts off with a NULL fence, this allows a client
+ * to do a host wait in one thread (or process) which waits on GPU work
+ * submitted in another thread (or process) without having to manually
+ * synchronize between the two.
+ * This requirement is inherited from the Vulkan fence API.
+ *
+ *
+ * Import/export of syncobjs
+ * -------------------------
+ *
+ * &DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE and &DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD
+ * provide two mechanisms for import/export of syncobjs.
+ *
+ * The first lets the client import or export an entire syncobj to a file
+ * descriptor.
+ * These fd's are opaque and have no other use case, except passing the
+ * syncobj between processes.
+ * All exported file descriptors and any syncobj handles created as a
+ * result of importing those file descriptors own a reference to the
+ * same underlying struct &drm_syncobj and the syncobj can be used
+ * persistently across all the processes with which it is shared.
+ * The syncobj is freed only once the last reference is dropped.
+ * Unlike dma-buf, importing a syncobj creates a new handle (with its own
+ * reference) for every import instead of de-duplicating.
+ * The primary use-case of this persistent import/export is for shared
+ * Vulkan fences and semaphores.
+ *
+ * The second import/export mechanism, which is indicated by
+ * &DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE or
+ * &DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE lets the client
+ * import/export the syncobj's current fence from/to a &sync_file.
+ * When a syncobj is exported to a sync file, that sync file wraps the
+ * sycnobj's fence at the time of export and any later signal or reset
+ * operations on the syncobj will not affect the exported sync file.
+ * When a sync file is imported into a syncobj, the syncobj's fence is set
+ * to the fence wrapped by that sync file.
+ * Because sync files are immutable, resetting or signaling the syncobj
+ * will not affect any sync files whose fences have been imported into the
+ * syncobj.
  */
 
 #include <linux/anon_inodes.h>