The dma-buf subsystem provides the framework for sharing buffers for
hardware (DMA) access across multiple device drivers and subsystems, and
for synchronizing asynchronous hardware access.
As an example, it is used extensively by the DRM subsystem to exchange
buffers between processes, contexts, library APIs within the same
process, and also to exchange buffers with other subsystems such as
V4L2.
This document describes the way in which kernel subsystems can use and
interact with the three main primitives offered by dma-buf:
Shared DMA Buffers
This document serves as a guide to device-driver writers on what is the dma-buf
buffer sharing API, how to use it for exporting and using shared buffers.
Any device driver which wishes to be a part of DMA buffer sharing, can do so as
either the ‘exporter’ of buffers, or the ‘user’ or ‘importer’ of buffers.
Say a driver A wants to use buffers created by driver B, then we call B as the
exporter, and A as buffer-user/importer.
The exporter
implements and manages operations in struct dma_buf_ops for the buffer,
allows other users to share the buffer by using dma_buf sharing APIs,
manages the details of buffer allocation, wrapped in a struct
dma_buf,
decides about the actual backing storage where this allocation happens,
and takes care of any migration of scatterlist - for all (shared) users of
this buffer.
The buffer-user
is one of (many) sharing users of the buffer.
doesn’t need to worry about how the buffer is allocated, or where.
and needs a mechanism to get access to the scatterlist that makes up this
buffer in memory, mapped into its own address space, so it can access the
same area of memory. This interface is provided by struct
dma_buf_attachment.
Any exporters or users of the dma-buf buffer sharing framework must have a
‘select DMA_SHARED_BUFFER’ in their respective Kconfigs.
Userspace Interface Notes
Mostly a DMA buffer file descriptor is simply an opaque object for userspace,
and hence the generic interface exposed is very minimal. There’s a few things to
consider though:
Since kernel 3.12 the dma-buf FD supports the llseek system call, but only
with offset=0 and whence=SEEK_END|SEEK_SET. SEEK_SET is supported to allow
the usual size discover pattern size = SEEK_END(0); SEEK_SET(0). Every other
llseek operation will report -EINVAL.
If llseek on dma-buf FDs isn’t supported the kernel will report -ESPIPE for all
cases. Userspace can use this to detect support for discovering the dma-buf
size using llseek.
In order to avoid fd leaks on exec, the FD_CLOEXEC flag must be set
on the file descriptor. This is not just a resource leak, but a
potential security hole. It could give the newly exec’d application
access to buffers, via the leaked fd, to which it should otherwise
not be permitted access.
The problem with doing this via a separate fcntl() call, versus doing it
atomically when the fd is created, is that this is inherently racy in a
multi-threaded app[3]. The issue is made worse when it is library code
opening/creating the file descriptor, as the application may not even be
aware of the fd’s.
To avoid this problem, userspace must have a way to request O_CLOEXEC
flag be set when the dma-buf fd is created. So any API provided by
the exporting driver to create a dmabuf fd must provide a way to let
userspace control setting of O_CLOEXEC flag passed in to dma_buf_fd().
Memory mapping the contents of the DMA buffer is also supported. See the
discussion below on CPU Access to DMA Buffer Objects for the full details.
The DMA buffer FD is also pollable, see Implicit Fence Poll Support below for
details.
The DMA buffer FD also supports a few dma-buf-specific ioctls, see
DMA Buffer ioctls below for details.
Basic Operation and Device DMA Access
For device DMA access to a shared DMA buffer the usual sequence of operations
is fairly simple:
The exporter defines his exporter instance using
DEFINE_DMA_BUF_EXPORT_INFO() and calls dma_buf_export() to wrap a private
buffer object into a dma_buf. It then exports that dma_buf to userspace
as a file descriptor by calling dma_buf_fd().
Userspace passes this file-descriptors to all drivers it wants this buffer
to share with: First the file descriptor is converted to a dma_buf using
dma_buf_get(). Then the buffer is attached to the device using
dma_buf_attach().
Up to this stage the exporter is still free to migrate or reallocate the
backing storage.
Once the buffer is attached to all devices userspace can initiate DMA
access to the shared buffer. In the kernel this is done by calling
dma_buf_map_attachment() and dma_buf_unmap_attachment().
Once a driver is done with a shared buffer it needs to call
dma_buf_detach() (after cleaning up any mappings) and then release the
reference acquired with dma_buf_get() by calling dma_buf_put().
For the detailed semantics exporters are expected to implement see
dma_buf_ops.
CPU Access to DMA Buffer Objects
There are multiple reasons for supporting CPU access to a dma buffer object:
Fallback operations in the kernel, for example when a device is connected
over USB and the kernel needs to shuffle the data around first before
sending it away. Cache coherency is handled by bracketing any transactions
with calls to dma_buf_begin_cpu_access() and dma_buf_end_cpu_access()
access.
Since for most kernel internal dma-buf accesses need the entire buffer, a
vmap interface is introduced. Note that on very old 32-bit architectures
vmalloc space might be limited and result in vmap calls failing.
Interfaces:
void *dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map)
The vmap call can fail if there is no vmap support in the exporter, or if
it runs out of vmalloc space. Note that the dma-buf layer keeps a reference
count for all vmap access and calls down into the exporter’s vmap function
only when no vmapping exists, and only unmaps it once. Protection against
concurrent vmap/vunmap calls is provided by taking the dma_buf.lock mutex.
For full compatibility on the importer side with existing userspace
interfaces, which might already support mmap’ing buffers. This is needed in
many processing pipelines (e.g. feeding a software rendered image into a
hardware pipeline, thumbnail creation, snapshots, ...). Also, Android’s ION
framework already supported this and for DMA buffer file descriptors to
replace ION buffers mmap support was needed.
There is no special interfaces, userspace simply calls mmap on the dma-buf
fd. But like for CPU access there’s a need to bracket the actual access,
which is handled by the ioctl (DMA_BUF_IOCTL_SYNC). Note that
DMA_BUF_IOCTL_SYNC can fail with -EAGAIN or -EINTR, in which case it must
be restarted.
Some systems might need some sort of cache coherency management e.g. when
CPU and GPU domains are being accessed through dma-buf at the same time.
To circumvent this problem there are begin/end coherency markers, that
forward directly to existing dma-buf device drivers vfunc hooks. Userspace
can make use of those markers through the DMA_BUF_IOCTL_SYNC ioctl. The
sequence would be used like following:
mmap dma-buf fd
for each drawing/upload cycle in CPU 1. SYNC_START ioctl, 2. read/write
to mmap area 3. SYNC_END ioctl. This can be repeated as often as you
want (with the new data being consumed by say the GPU or the scanout
device)
munmap once you don’t need the buffer any more
For correctness and optimal performance, it is always required to use
SYNC_START and SYNC_END before and after, respectively, when accessing the
mapped address. Userspace cannot rely on coherent access, even when there
are systems where it just works without calling these ioctls.
And as a CPU fallback in userspace processing pipelines.
Similar to the motivation for kernel cpu access it is again important that
the userspace code of a given importing subsystem can use the same
interfaces with a imported dma-buf buffer object as with a native buffer
object. This is especially important for drm where the userspace part of
contemporary OpenGL, X, and other drivers is huge, and reworking them to
use a different way to mmap a buffer rather invasive.
The assumption in the current dma-buf interfaces is that redirecting the
initial mmap is all that’s needed. A survey of some of the existing
subsystems shows that no driver seems to do any nefarious thing like
syncing up with outstanding asynchronous processing on the device or
allocating special resources at fault time. So hopefully this is good
enough, since adding interfaces to intercept pagefaults and allow pte
shootdowns would increase the complexity quite a bit.
Interface:
int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *, unsigned long);
If the importing subsystem simply provides a special-purpose mmap call to
set up a mapping in userspace, calling do_mmap with dma_buf.file will
equally achieve that for a dma-buf object.
Implicit Fence Poll Support
To support cross-device and cross-driver synchronization of buffer access
implicit fences (represented internally in the kernel with struct dma_fence)
can be attached to a dma_buf. The glue for that and a few related things are
provided in the dma_resv structure.
Userspace can query the state of these implicitly tracked fences using poll()
and related system calls:
Checking for EPOLLIN, i.e. read access, can be use to query the state of the
most recent write or exclusive fence.
Checking for EPOLLOUT, i.e. write access, can be used to query the state of
all attached fences, shared and exclusive ones.
Note that this only signals the completion of the respective fences, i.e. the
DMA transfers are complete. Cache flushing and any other necessary
preparations before CPU access can begin still need to happen.
As an alternative to poll(), the set of fences on DMA buffer can be
exported as a sync_file using dma_buf_sync_file_export.
DMA-BUF statistics
/sys/kernel/debug/dma_buf/bufinfo provides an overview of every DMA-BUF
in the system. However, since debugfs is not safe to be mounted in
production, procfs and sysfs can be used to gather DMA-BUF statistics on
production systems.
The /proc/<pid>/fdinfo/<fd> files in procfs can be used to gather
information about DMA-BUF fds. Detailed documentation about the interface
is present in The /proc Filesystem.
Unfortunately, the existing procfs interfaces can only provide information
about the DMA-BUFs for which processes hold fds or have the buffers mmapped
into their address space. This necessitated the creation of the DMA-BUF sysfs
statistics interface to provide per-buffer information on production systems.
The interface at /sys/kernel/dmabuf/buffers exposes information about
every DMA-BUF when CONFIG_DMABUF_SYSFS_STATS is enabled.
The following stats are exposed by the interface:
The information in the interface can also be used to derive per-exporter
statistics. The data from the interface can be gathered on error conditions
or other important events to provide a snapshot of DMA-BUF usage.
It can also be collected periodically by telemetry to monitor various metrics.
Detailed documentation about the interface is present in
Documentation/ABI/testing/sysfs-kernel-dmabuf-buffers.
DMA Buffer ioctls
-
struct dma_buf_sync
Synchronize with CPU access.
Definition:
struct dma_buf_sync {
__u64 flags;
};
Members
flagsSet of access flags
- DMA_BUF_SYNC_START:
Indicates the start of a map access session.
- DMA_BUF_SYNC_END:
Indicates the end of a map access session.
- DMA_BUF_SYNC_READ:
Indicates that the mapped DMA buffer will be read by the
client via the CPU map.
- DMA_BUF_SYNC_WRITE:
Indicates that the mapped DMA buffer will be written by the
client via the CPU map.
- DMA_BUF_SYNC_RW:
An alias for DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE.
Description
When a DMA buffer is accessed from the CPU via mmap, it is not always
possible to guarantee coherency between the CPU-visible map and underlying
memory. To manage coherency, DMA_BUF_IOCTL_SYNC must be used to bracket
any CPU access to give the kernel the chance to shuffle memory around if
needed.
Prior to accessing the map, the client must call DMA_BUF_IOCTL_SYNC
with DMA_BUF_SYNC_START and the appropriate read/write flags. Once the
access is complete, the client should call DMA_BUF_IOCTL_SYNC with
DMA_BUF_SYNC_END and the same read/write flags.
The synchronization provided via DMA_BUF_IOCTL_SYNC only provides cache
coherency. It does not prevent other processes or devices from
accessing the memory at the same time. If synchronization with a GPU or
other device driver is required, it is the client’s responsibility to
wait for buffer to be ready for reading or writing before calling this
ioctl with DMA_BUF_SYNC_START. Likewise, the client must ensure that
follow-up work is not submitted to GPU or other device driver until
after this ioctl has been called with DMA_BUF_SYNC_END?
If the driver or API with which the client is interacting uses implicit
synchronization, waiting for prior work to complete can be done via
poll() on the DMA buffer file descriptor. If the driver or API requires
explicit synchronization, the client may have to wait on a sync_file or
other synchronization primitive outside the scope of the DMA buffer API.
-
struct dma_buf_export_sync_file
Get a sync_file from a dma-buf
Definition:
struct dma_buf_export_sync_file {
__u32 flags;
__s32 fd;
};
Members
flagsRead/write flags
Must be DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, or both.
If DMA_BUF_SYNC_READ is set and DMA_BUF_SYNC_WRITE is not set,
the returned sync file waits on any writers of the dma-buf to
complete. Waiting on the returned sync file is equivalent to
poll() with POLLIN.
If DMA_BUF_SYNC_WRITE is set, the returned sync file waits on
any users of the dma-buf (read or write) to complete. Waiting
on the returned sync file is equivalent to poll() with POLLOUT.
If both DMA_BUF_SYNC_WRITE and DMA_BUF_SYNC_READ are set, this
is equivalent to just DMA_BUF_SYNC_WRITE.
fdReturned sync file descriptor
Description
Userspace can perform a DMA_BUF_IOCTL_EXPORT_SYNC_FILE to retrieve the
current set of fences on a dma-buf file descriptor as a sync_file. CPU
waits via poll() or other driver-specific mechanisms typically wait on
whatever fences are on the dma-buf at the time the wait begins. This
is similar except that it takes a snapshot of the current fences on the
dma-buf for waiting later instead of waiting immediately. This is
useful for modern graphics APIs such as Vulkan which assume an explicit
synchronization model but still need to inter-operate with dma-buf.
The intended usage pattern is the following:
Export a sync_file with flags corresponding to the expected GPU usage
via DMA_BUF_IOCTL_EXPORT_SYNC_FILE.
Submit rendering work which uses the dma-buf. The work should wait on
the exported sync file before rendering and produce another sync_file
when complete.
Import the rendering-complete sync_file into the dma-buf with flags
corresponding to the GPU usage via DMA_BUF_IOCTL_IMPORT_SYNC_FILE.
Unlike doing implicit synchronization via a GPU kernel driver’s exec ioctl,
the above is not a single atomic operation. If userspace wants to ensure
ordering via these fences, it is the respnosibility of userspace to use
locks or other mechanisms to ensure that no other context adds fences or
submits work between steps 1 and 3 above.
-
struct dma_buf_import_sync_file
Insert a sync_file into a dma-buf
Definition:
struct dma_buf_import_sync_file {
__u32 flags;
__s32 fd;
};
Members
flagsRead/write flags
Must be DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE, or both.
If DMA_BUF_SYNC_READ is set and DMA_BUF_SYNC_WRITE is not set,
this inserts the sync_file as a read-only fence. Any subsequent
implicitly synchronized writes to this dma-buf will wait on this
fence but reads will not.
If DMA_BUF_SYNC_WRITE is set, this inserts the sync_file as a
write fence. All subsequent implicitly synchronized access to
this dma-buf will wait on this fence.
fdSync file descriptor
Description
Userspace can perform a DMA_BUF_IOCTL_IMPORT_SYNC_FILE to insert a
sync_file into a dma-buf for the purposes of implicit synchronization
with other dma-buf consumers. This allows clients using explicitly
synchronized APIs such as Vulkan to inter-op with dma-buf consumers
which expect implicit synchronization such as OpenGL or most media
drivers/video.
DMA-BUF 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
Importers must hold the dma-buf reservation lock when calling these
functions:
Importers must not hold the dma-buf reservation lock when calling these
functions:
Convention for exporters
These dma_buf_ops callbacks are invoked with unlocked dma-buf
reservation and exporter can take the lock:
These dma_buf_ops callbacks are invoked with locked dma-buf
reservation and exporter can’t take the lock:
Exporters must hold the dma-buf reservation lock when calling these
functions:
Kernel Functions and Structures Reference
-
struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
Creates a new dma_buf, and associates an anon file with this buffer, so it can be exported. Also connect the allocator specific data and ops to the buffer. Additionally, provide a name string for exporter; useful in debugging.
Parameters
const struct dma_buf_export_info *exp_info[in] holds all the export related information provided
by the exporter. see struct dma_buf_export_info
for further details.
Description
Returns, on success, a newly created struct dma_buf object, which wraps the
supplied private data and operations for struct dma_buf_ops. On either
missing ops, or error in allocating struct dma_buf, will return negative
error.
For most cases the easiest way to create exp_info is through the
DEFINE_DMA_BUF_EXPORT_INFO macro.
-
int dma_buf_fd(struct dma_buf *dmabuf, int flags)
returns a file descriptor for the given struct dma_buf
Parameters
struct dma_buf *dmabuf[in] pointer to dma_buf for which fd is required.
int flags[in] flags to give to fd
Description
On success, returns an associated ‘fd’. Else, returns error.
-
struct dma_buf *dma_buf_get(int fd)
returns the struct dma_buf related to an fd
Parameters
int fd[in] fd associated with the struct dma_buf to be returned
Description
On success, returns the struct dma_buf associated with an fd; uses
file’s refcounting done by fget to increase refcount. returns ERR_PTR
otherwise.
-
void dma_buf_put(struct dma_buf *dmabuf)
decreases refcount of the buffer
Parameters
struct dma_buf *dmabuf[in] buffer to reduce refcount of
Description
Uses file’s refcounting done implicitly by fput().
If, as a result of this call, the refcount becomes 0, the ‘release’ file
operation related to this fd is called. It calls dma_buf_ops.release vfunc
in turn, and frees the memory allocated for dmabuf when exported.
-
struct dma_buf_attachment *dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev, const struct dma_buf_attach_ops *importer_ops, void *importer_priv)
Add the device to dma_buf’s attachments list
Parameters
struct dma_buf *dmabuf[in] buffer to attach device to.
struct device *dev[in] device to be attached.
const struct dma_buf_attach_ops *importer_ops[in] importer operations for the attachment
void *importer_priv[in] importer private pointer for the attachment
Description
Returns struct dma_buf_attachment pointer for this attachment. Attachments
must be cleaned up by calling dma_buf_detach().
Optionally this calls dma_buf_ops.attach to allow device-specific attach
functionality.
A pointer to newly created dma_buf_attachment on success, or a negative
error code wrapped into a pointer on failure.
Note that this can fail if the backing storage of dmabuf is in a place not
accessible to dev, and cannot be moved to a more suitable place. This is
indicated with the error code -EBUSY.
Return
-
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, struct device *dev)
Wrapper for dma_buf_dynamic_attach
Parameters
struct dma_buf *dmabuf[in] buffer to attach device to.
struct device *dev[in] device to be attached.
Description
Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
mapping.
-
void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
Remove the given attachment from dmabuf’s attachments list
Parameters
struct dma_buf *dmabuf[in] buffer to detach from.
struct dma_buf_attachment *attach[in] attachment to be detached; is free’d after this call.
Description
Clean up a device attachment obtained by calling dma_buf_attach().
Optionally this calls dma_buf_ops.detach for device-specific detach.
-
int dma_buf_pin(struct dma_buf_attachment *attach)
Lock down the DMA-buf
Parameters
struct dma_buf_attachment *attach[in] attachment which should be pinned
Description
Only dynamic importers (who set up attach with dma_buf_dynamic_attach()) may
call this, and only for limited use cases like scanout and not for temporary
pin operations. It is not permitted to allow userspace to pin arbitrary
amounts of buffers through this interface.
Buffers must be unpinned by calling dma_buf_unpin().
Return
0 on success, negative error code on failure.
-
void dma_buf_unpin(struct dma_buf_attachment *attach)
Unpin a DMA-buf
Parameters
struct dma_buf_attachment *attach[in] attachment which should be unpinned
Description
This unpins a buffer pinned by dma_buf_pin() and allows the exporter to move
any mapping of attach again and inform the importer through
dma_buf_attach_ops.move_notify.
-
struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, enum dma_data_direction direction)
Returns the scatterlist table of the attachment; mapped into _device_ address space. Is a wrapper for map_dma_buf() of the dma_buf_ops.
Parameters
struct dma_buf_attachment *attach[in] attachment whose scatterlist is to be returned
enum dma_data_direction direction[in] direction of DMA transfer
Description
Returns sg_table containing the scatterlist to be returned; returns ERR_PTR
on error. May return -EINTR if it is interrupted by a signal.
On success, the DMA addresses and lengths in the returned scatterlist are
PAGE_SIZE aligned.
A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that
the underlying backing storage is pinned for as long as a mapping exists,
therefore users/importers should not hold onto a mapping for undue amounts of
time.
Important: Dynamic importers must wait for the exclusive fence of the struct
dma_resv attached to the DMA-BUF first.
-
struct sg_table *dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach, enum dma_data_direction direction)
Returns the scatterlist table of the attachment; mapped into _device_ address space. Is a wrapper for map_dma_buf() of the dma_buf_ops.
Parameters
struct dma_buf_attachment *attach[in] attachment whose scatterlist is to be returned
enum dma_data_direction direction[in] direction of DMA transfer
Description
Unlocked variant of dma_buf_map_attachment().
-
void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, struct sg_table *sg_table, enum dma_data_direction direction)
unmaps and decreases usecount of the buffer;might deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of dma_buf_ops.
Parameters
struct dma_buf_attachment *attach[in] attachment to unmap buffer from
struct sg_table *sg_table[in] scatterlist info of the buffer to unmap
enum dma_data_direction direction[in] direction of DMA transfer
Description
This unmaps a DMA mapping for attached obtained by dma_buf_map_attachment().
-
void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach, struct sg_table *sg_table, enum dma_data_direction direction)
unmaps and decreases usecount of the buffer;might deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of dma_buf_ops.
Parameters
struct dma_buf_attachment *attach[in] attachment to unmap buffer from
struct sg_table *sg_table[in] scatterlist info of the buffer to unmap
enum dma_data_direction direction[in] direction of DMA transfer
Description
Unlocked variant of dma_buf_unmap_attachment().
-
void dma_buf_move_notify(struct dma_buf *dmabuf)
notify attachments that DMA-buf is moving
Parameters
struct dma_buf *dmabuf[in] buffer which is moving
Description
Informs all attachments that they need to destroy and recreate all their
mappings.
-
int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction)
Must be called before accessing a dma_buf from the cpu in the kernel context. Calls begin_cpu_access to allow exporter-specific preparations. Coherency is only guaranteed in the specified range for the specified access direction.
Parameters
struct dma_buf *dmabuf[in] buffer to prepare cpu access for.
enum dma_data_direction direction[in] direction of access.
Description
After the cpu access is complete the caller should call
dma_buf_end_cpu_access(). Only when cpu access is bracketed by both calls is
it guaranteed to be coherent with other DMA access.
This function will also wait for any DMA transactions tracked through
implicit synchronization in dma_buf.resv. For DMA transactions with explicit
synchronization this function will only ensure cache coherency, callers must
ensure synchronization with such DMA transactions on their own.
Can return negative error values, returns 0 on success.
-
int dma_buf_end_cpu_access(struct dma_buf *dmabuf, enum dma_data_direction direction)
Must be called after accessing a dma_buf from the cpu in the kernel context. Calls end_cpu_access to allow exporter-specific actions. Coherency is only guaranteed in the specified range for the specified access direction.
Parameters
struct dma_buf *dmabuf[in] buffer to complete cpu access for.
enum dma_data_direction direction[in] direction of access.
Description
This terminates CPU access started with dma_buf_begin_cpu_access().
Can return negative error values, returns 0 on success.
-
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, unsigned long pgoff)
Setup up a userspace mmap with the given vma
Parameters
struct dma_buf *dmabuf[in] buffer that should back the vma
struct vm_area_struct *vma[in] vma for the mmap
unsigned long pgoff[in] offset in pages where this mmap should start within the
dma-buf buffer.
Description
This function adjusts the passed in vma so that it points at the file of the
dma_buf operation. It also adjusts the starting pgoff and does bounds
checking on the size of the vma. Then it calls the exporters mmap function to
set up the mapping.
Can return negative error values, returns 0 on success.
-
int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
Create virtual mapping for the buffer object into kernel address space. Same restrictions as for vmap and friends apply.
Parameters
struct dma_buf *dmabuf[in] buffer to vmap
struct iosys_map *map[out] returns the vmap pointer
Description
This call may fail due to lack of virtual mapping address space.
These calls are optional in drivers. The intended use for them
is for mapping objects linear in kernel space for high use objects.
To ensure coherency users must call dma_buf_begin_cpu_access() and
dma_buf_end_cpu_access() around any cpu access performed through this
mapping.
Returns 0 on success, or a negative errno code otherwise.
-
int dma_buf_vmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
Create virtual mapping for the buffer object into kernel address space. Same restrictions as for vmap and friends apply.
Parameters
struct dma_buf *dmabuf[in] buffer to vmap
struct iosys_map *map[out] returns the vmap pointer
Description
Unlocked version of dma_buf_vmap()
Returns 0 on success, or a negative errno code otherwise.
-
void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map)
Unmap a vmap obtained by dma_buf_vmap.
Parameters
struct dma_buf *dmabuf[in] buffer to vunmap
struct iosys_map *map[in] vmap pointer to vunmap
-
void dma_buf_vunmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
Unmap a vmap obtained by dma_buf_vmap.
Parameters
struct dma_buf *dmabuf[in] buffer to vunmap
struct iosys_map *map[in] vmap pointer to vunmap
-
struct dma_buf_ops
operations possible on struct dma_buf
Definition:
struct dma_buf_ops {
int (*attach)(struct dma_buf *, struct dma_buf_attachment *);
void (*detach)(struct dma_buf *, struct dma_buf_attachment *);
int (*pin)(struct dma_buf_attachment *attach);
void (*unpin)(struct dma_buf_attachment *attach);
struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *, enum dma_data_direction);
void (*unmap_dma_buf)(struct dma_buf_attachment *,struct sg_table *, enum dma_data_direction);
void (*release)(struct dma_buf *);
int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction);
int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction);
int (*mmap)(struct dma_buf *, struct vm_area_struct *vma);
int (*vmap)(struct dma_buf *dmabuf, struct iosys_map *map);
void (*vunmap)(struct dma_buf *dmabuf, struct iosys_map *map);
};
Members
attachThis is called from dma_buf_attach() to make sure that a given
dma_buf_attachment.dev can access the provided dma_buf. Exporters
which support buffer objects in special locations like VRAM or
device-specific carveout areas should check whether the buffer could
be move to system memory (or directly accessed by the provided
device), and otherwise need to fail the attach operation.
The exporter should also in general check whether the current
allocation fulfills the DMA constraints of the new device. If this
is not the case, and the allocation cannot be moved, it should also
fail the attach operation.
Any exporter-private housekeeping data can be stored in the
dma_buf_attachment.priv pointer.
This callback is optional.
Returns:
0 on success, negative error code on failure. It might return -EBUSY
to signal that backing storage is already allocated and incompatible
with the requirements of requesting device.
detachThis is called by dma_buf_detach() to release a dma_buf_attachment.
Provided so that exporters can clean up any housekeeping for an
dma_buf_attachment.
This callback is optional.
pinThis is called by dma_buf_pin() and lets the exporter know that the
DMA-buf can’t be moved any more. Ideally, the exporter should
pin the buffer so that it is generally accessible by all
devices.
This is called with the dmabuf.resv object locked and is mutual
exclusive with cache_sgt_mapping.
This is called automatically for non-dynamic importers from
dma_buf_attach().
Note that similar to non-dynamic exporters in their map_dma_buf
callback the driver must guarantee that the memory is available for
use and cleared of any old data by the time this function returns.
Drivers which pipeline their buffer moves internally must wait for
all moves and clears to complete.
Returns:
0 on success, negative error code on failure.
unpinThis is called by dma_buf_unpin() and lets the exporter know that the
DMA-buf can be moved again.
This is called with the dmabuf->resv object locked and is mutual
exclusive with cache_sgt_mapping.
This callback is optional.
map_dma_bufThis is called by dma_buf_map_attachment() and is used to map a
shared dma_buf into device address space, and it is mandatory. It
can only be called if attach has been called successfully.
This call may sleep, e.g. when the backing storage first needs to be
allocated, or moved to a location suitable for all currently attached
devices.
Note that any specific buffer attributes required for this function
should get added to device_dma_parameters accessible via
device.dma_params from the dma_buf_attachment. The attach callback
should also check these constraints.
If this is being called for the first time, the exporter can now
choose to scan through the list of attachments for this buffer,
collate the requirements of the attached devices, and choose an
appropriate backing storage for the buffer.
Based on enum dma_data_direction, it might be possible to have
multiple users accessing at the same time (for reading, maybe), or
any other kind of sharing that the exporter might wish to make
available to buffer-users.
This is always called with the dmabuf->resv object locked when
the dynamic_mapping flag is true.
Note that for non-dynamic exporters the driver must guarantee that
that the memory is available for use and cleared of any old data by
the time this function returns. Drivers which pipeline their buffer
moves internally must wait for all moves and clears to complete.
Dynamic exporters do not need to follow this rule: For non-dynamic
importers the buffer is already pinned through pin, which has the
same requirements. Dynamic importers otoh are required to obey the
dma_resv fences.
Returns:
A sg_table scatter list of the backing storage of the DMA buffer,
already mapped into the device address space of the device attached
with the provided dma_buf_attachment. The addresses and lengths in
the scatter list are PAGE_SIZE aligned.
On failure, returns a negative error value wrapped into a pointer.
May also return -EINTR when a signal was received while being
blocked.
Note that exporters should not try to cache the scatter list, or
return the same one for multiple calls. Caching is done either by the
DMA-BUF code (for non-dynamic importers) or the importer. Ownership
of the scatter list is transferred to the caller, and returned by
unmap_dma_buf.
unmap_dma_bufThis is called by dma_buf_unmap_attachment() and should unmap and
release the sg_table allocated in map_dma_buf, and it is mandatory.
For static dma_buf handling this might also unpin the backing
storage if this is the last mapping of the DMA buffer.
releaseCalled after the last dma_buf_put to release the dma_buf, and
mandatory.
begin_cpu_accessThis is called from dma_buf_begin_cpu_access() and allows the
exporter to ensure that the memory is actually coherent for cpu
access. The exporter also needs to ensure that cpu access is coherent
for the access direction. The direction can be used by the exporter
to optimize the cache flushing, i.e. access with a different
direction (read instead of write) might return stale or even bogus
data (e.g. when the exporter needs to copy the data to temporary
storage).
Note that this is both called through the DMA_BUF_IOCTL_SYNC IOCTL
command for userspace mappings established through mmap, and also
for kernel mappings established with vmap.
This callback is optional.
Returns:
0 on success or a negative error code on failure. This can for
example fail when the backing storage can’t be allocated. Can also
return -ERESTARTSYS or -EINTR when the call has been interrupted and
needs to be restarted.
end_cpu_accessThis is called from dma_buf_end_cpu_access() when the importer is
done accessing the CPU. The exporter can use this to flush caches and
undo anything else done in begin_cpu_access.
This callback is optional.
Returns:
0 on success or a negative error code on failure. Can return
-ERESTARTSYS or -EINTR when the call has been interrupted and needs
to be restarted.
mmapThis callback is used by the dma_buf_mmap() function
Note that the mapping needs to be incoherent, userspace is expected
to bracket CPU access using the DMA_BUF_IOCTL_SYNC interface.
Because dma-buf buffers have invariant size over their lifetime, the
dma-buf core checks whether a vma is too large and rejects such
mappings. The exporter hence does not need to duplicate this check.
Drivers do not need to check this themselves.
If an exporter needs to manually flush caches and hence needs to fake
coherency for mmap support, it needs to be able to zap all the ptes
pointing at the backing storage. Now linux mm needs a struct
address_space associated with the struct file stored in vma->vm_file
to do that with the function unmap_mapping_range. But the dma_buf
framework only backs every dma_buf fd with the anon_file struct file,
i.e. all dma_bufs share the same file.
Hence exporters need to setup their own file (and address_space)
association by setting vma->vm_file and adjusting vma->vm_pgoff in
the dma_buf mmap callback. In the specific case of a gem driver the
exporter could use the shmem file already provided by gem (and set
vm_pgoff = 0). Exporters can then zap ptes by unmapping the
corresponding range of the struct address_space associated with their
own file.
This callback is optional.
Returns:
0 on success or a negative error code on failure.
vmap[optional] creates a virtual mapping for the buffer into kernel
address space. Same restrictions as for vmap and friends apply.
vunmap[optional] unmaps a vmap from the buffer
-
struct dma_buf
shared buffer object
Definition:
struct dma_buf {
size_t size;
struct file *file;
struct list_head attachments;
const struct dma_buf_ops *ops;
unsigned vmapping_counter;
struct iosys_map vmap_ptr;
const char *exp_name;
const char *name;
spinlock_t name_lock;
struct module *owner;
struct list_head list_node;
void *priv;
struct dma_resv *resv;
wait_queue_head_t poll;
struct dma_buf_poll_cb_t {
struct dma_fence_cb cb;
wait_queue_head_t *poll;
__poll_t active;
} cb_in, cb_out;
#ifdef CONFIG_DMABUF_SYSFS_STATS;
struct dma_buf_sysfs_entry {
struct kobject kobj;
struct dma_buf *dmabuf;
} *sysfs_entry;
#endif;
};
Members
sizeSize of the buffer; invariant over the lifetime of the buffer.
fileFile pointer used for sharing buffers across, and for refcounting.
See dma_buf_get() and dma_buf_put().
attachmentsList of dma_buf_attachment that denotes all devices attached,
protected by dma_resv lock resv.
opsdma_buf_ops associated with this buffer object.
vmapping_counterUsed internally to refcnt the vmaps returned by dma_buf_vmap().
Protected by lock.
vmap_ptrThe current vmap ptr if vmapping_counter > 0. Protected by lock.
exp_nameName of the exporter; useful for debugging. Must not be NULL
nameUserspace-provided name. Default value is NULL. If not NULL,
length cannot be longer than DMA_BUF_NAME_LEN, including NIL
char. Useful for accounting and debugging. Read/Write accesses
are protected by name_lock
See the IOCTLs DMA_BUF_SET_NAME or DMA_BUF_SET_NAME_A/B
name_lockSpinlock to protect name access for read access.
ownerPointer to exporter module; used for refcounting when exporter is a
kernel module.
list_nodenode for dma_buf accounting and debugging.
privexporter specific private data for this buffer object.
resvReservation object linked to this dma-buf.
IMPLICIT SYNCHRONIZATION RULES:
Drivers which support implicit synchronization of buffer access as
e.g. exposed in Implicit Fence Poll Support must follow the
below rules.
Drivers must add a read fence through dma_resv_add_fence() with the
DMA_RESV_USAGE_READ flag for anything the userspace API considers a
read access. This highly depends upon the API and window system.
Similarly drivers must add a write fence through
dma_resv_add_fence() with the DMA_RESV_USAGE_WRITE flag for
anything the userspace API considers write access.
Drivers may just always add a write fence, since that only
causes unnecessary synchronization, but no correctness issues.
Some drivers only expose a synchronous userspace API with no
pipelining across drivers. These do not set any fences for their
access. An example here is v4l.
Driver should use dma_resv_usage_rw() when retrieving fences as
dependency for implicit synchronization.
DYNAMIC IMPORTER RULES:
Dynamic importers, see dma_buf_attachment_is_dynamic(), have
additional constraints on how they set up fences:
Dynamic importers must obey the write fences and wait for them to
signal before allowing access to the buffer’s underlying storage
through the device.
Dynamic importers should set fences for any access that they can’t
disable immediately from their dma_buf_attach_ops.move_notify
callback.
IMPORTANT:
All drivers and memory management related functions must obey the
struct dma_resv rules, specifically the rules for updating and
obeying fences. See enum dma_resv_usage for further descriptions.
pollfor userspace poll support
cb_infor userspace poll support
cb_outfor userspace poll support
sysfs_entryFor exposing information about this buffer in sysfs. See also
DMA-BUF statistics for the uapi this enables.
Description
This represents a shared buffer, created by calling dma_buf_export(). The
userspace representation is a normal file descriptor, which can be created by
calling dma_buf_fd().
Shared dma buffers are reference counted using dma_buf_put() and
get_dma_buf().
Device DMA access is handled by the separate struct dma_buf_attachment.
-
struct dma_buf_attach_ops
importer operations for an attachment
Definition:
struct dma_buf_attach_ops {
bool allow_peer2peer;
void (*move_notify)(struct dma_buf_attachment *attach);
};
Members
allow_peer2peerIf this is set to true the importer must be able to handle peer
resources without struct pages.
move_notify[optional] notification that the DMA-buf is moving
If this callback is provided the framework can avoid pinning the
backing store while mappings exists.
This callback is called with the lock of the reservation object
associated with the dma_buf held and the mapping function must be
called with this lock held as well. This makes sure that no mapping
is created concurrently with an ongoing move operation.
Mappings stay valid and are not directly affected by this callback.
But the DMA-buf can now be in a different physical location, so all
mappings should be destroyed and re-created as soon as possible.
New mappings can be created after this callback returns, and will
point to the new location of the DMA-buf.
Description
Attachment operations implemented by the importer.
-
struct dma_buf_attachment
holds device-buffer attachment data
Definition:
struct dma_buf_attachment {
struct dma_buf *dmabuf;
struct device *dev;
struct list_head node;
bool peer2peer;
const struct dma_buf_attach_ops *importer_ops;
void *importer_priv;
void *priv;
};
Members
dmabufbuffer for this attachment.
devdevice attached to the buffer.
nodelist of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
peer2peertrue if the importer can handle peer resources without pages.
importer_opsimporter operations for this attachment, if provided
dma_buf_map/unmap_attachment() must be called with the dma_resv lock held.
importer_privimporter specific attachment data.
privexporter specific attachment data.
Description
This structure holds the attachment information between the dma_buf buffer
and its user device(s). The list contains one attachment struct per device
attached to the buffer.
An attachment is created by calling dma_buf_attach(), and released again by
calling dma_buf_detach(). The DMA mapping itself needed to initiate a
transfer is created by dma_buf_map_attachment() and freed again by calling
dma_buf_unmap_attachment().
-
struct dma_buf_export_info
holds information needed to export a dma_buf
Definition:
struct dma_buf_export_info {
const char *exp_name;
struct module *owner;
const struct dma_buf_ops *ops;
size_t size;
int flags;
struct dma_resv *resv;
void *priv;
};
Members
exp_namename of the exporter - useful for debugging.
ownerpointer to exporter module - used for refcounting kernel module
opsAttach allocator-defined dma buf ops to the new buffer
sizeSize of the buffer - invariant over the lifetime of the buffer
flagsmode flags for the file
resvreservation-object, NULL to allocate default one
privAttach private data of allocator to this buffer
Description
This structure holds the information required to export the buffer. Used
with dma_buf_export() only.
-
struct dma_buf_phys_vec
describe continuous chunk of memory
Definition:
struct dma_buf_phys_vec {
phys_addr_t paddr;
size_t len;
};
Members
paddrphysical address of that chunk
lenLength of this chunk
-
DEFINE_DMA_BUF_EXPORT_INFO
DEFINE_DMA_BUF_EXPORT_INFO (name)
helper macro for exporters
Parameters
nameexport-info name
Description
DEFINE_DMA_BUF_EXPORT_INFO macro defines the struct dma_buf_export_info,
zeroes it out and pre-populates exp_name in it.
-
void get_dma_buf(struct dma_buf *dmabuf)
convenience wrapper for get_file.
Parameters
struct dma_buf *dmabuf[in] pointer to dma_buf
Description
Increments the reference count on the dma-buf, needed in case of drivers
that either need to create additional references to the dmabuf on the
kernel side. For example, an exporter that needs to keep a dmabuf ptr
so that subsequent exports don’t create a new dmabuf.
-
bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
check if a DMA-buf uses dynamic mappings.
Parameters
struct dma_buf *dmabufthe DMA-buf to check
Description
Returns true if a DMA-buf exporter wants to be called with the dma_resv
locked for the map/unmap callbacks, false if it doesn’t wants to be called
with the lock held.
Reservation Objects
The reservation object provides a mechanism to manage a container of
dma_fence object associated with a resource. A reservation object
can have any number of fences attaches to it. Each fence carries an usage
parameter determining how the operation represented by the fence is using the
resource. The RCU mechanism is used to protect read access to fences from
locked write-side updates.
See struct dma_resv for more details.
-
void dma_resv_init(struct dma_resv *obj)
initialize a reservation object
Parameters
struct dma_resv *objthe reservation object
-
void dma_resv_fini(struct dma_resv *obj)
destroys a reservation object
Parameters
struct dma_resv *objthe reservation object
-
int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
Reserve space to add fences to a dma_resv object.
Parameters
struct dma_resv *objreservation object
unsigned int num_fencesnumber of fences we want to add
Description
Should be called before dma_resv_add_fence(). Must be called with obj
locked through dma_resv_lock().
Note that the preallocated slots need to be re-reserved if obj is unlocked
at any time before calling dma_resv_add_fence(). This is validated when
CONFIG_DEBUG_MUTEXES is enabled.
RETURNS
Zero for success, or -errno
-
void dma_resv_reset_max_fences(struct dma_resv *obj)
reset fences for debugging
Parameters
struct dma_resv *objthe dma_resv object to reset
Description
Reset the number of pre-reserved fence slots to test that drivers do
correct slot allocation using dma_resv_reserve_fences(). See also
dma_resv_list.max_fences.
-
void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence, enum dma_resv_usage usage)
Add a fence to the dma_resv obj
-
void dma_resv_replace_fences(struct dma_resv *obj, uint64_t context, struct dma_fence *replacement, enum dma_resv_usage usage)
replace fences in the dma_resv obj
Parameters
struct dma_resv *objthe reservation object
uint64_t contextthe context of the fences to replace
struct dma_fence *replacementthe new fence to use instead
enum dma_resv_usage usagehow the new fence is used, see enum dma_resv_usage
Description
Replace fences with a specified context with a new fence. Only valid if the
operation represented by the original fence has no longer access to the
resources represented by the dma_resv object when the new fence completes.
And example for using this is replacing a preemption fence with a page table
update fence which makes the resource inaccessible.
-
struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor)
first fence in an unlocked dma_resv obj.
Parameters
struct dma_resv_iter *cursorthe cursor with the current position
Description
Subsequent fences are iterated with dma_resv_iter_next_unlocked().
Beware that the iterator can be restarted. Code which accumulates statistics
or similar needs to check for this with dma_resv_iter_is_restarted(). For
this reason prefer the locked dma_resv_iter_first() whenever possible.
Returns the first fence from an unlocked dma_resv obj.
-
struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
next fence in an unlocked dma_resv obj.
Parameters
struct dma_resv_iter *cursorthe cursor with the current position
Description
Beware that the iterator can be restarted. Code which accumulates statistics
or similar needs to check for this with dma_resv_iter_is_restarted(). For
this reason prefer the locked dma_resv_iter_next() whenever possible.
Returns the next fence from an unlocked dma_resv obj.
-
struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor)
first fence from a locked dma_resv object
Parameters
struct dma_resv_iter *cursorcursor to record the current position
Description
Subsequent fences are iterated with dma_resv_iter_next_unlocked().
Return the first fence in the dma_resv object while holding the
dma_resv.lock.
-
struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor)
next fence from a locked dma_resv object
Parameters
struct dma_resv_iter *cursorcursor to record the current position
Description
Return the next fences from the dma_resv object while holding the
dma_resv.lock.
-
int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
Copy all fences from src to dst.
Parameters
struct dma_resv *dstthe destination reservation object
struct dma_resv *srcthe source reservation object
Description
Copy all fences from src to dst. dst-lock must be held.
-
int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage, unsigned int *num_fences, struct dma_fence ***fences)
Get an object’s fences fences without update side lock held
Parameters
struct dma_resv *objthe reservation object
enum dma_resv_usage usagecontrols which fences to include, see enum dma_resv_usage.
unsigned int *num_fencesthe number of fences returned
struct dma_fence ***fencesthe array of fence ptrs returned (array is krealloc’d to the
required size, and must be freed by caller)
Description
Retrieve all fences from the reservation object.
Returns either zero or -ENOMEM.
-
int dma_resv_get_singleton(struct dma_resv *obj, enum dma_resv_usage usage, struct dma_fence **fence)
Get a single fence for all the fences
Parameters
struct dma_resv *objthe reservation object
enum dma_resv_usage usagecontrols which fences to include, see enum dma_resv_usage.
struct dma_fence **fencethe resulting fence
Description
Get a single fence representing all the fences inside the resv object.
Returns either 0 for success or -ENOMEM.
Warning: This can’t be used like this when adding the fence back to the resv
object since that can lead to stack corruption when finalizing the
dma_fence_array.
Returns 0 on success and negative error values on failure.
-
long dma_resv_wait_timeout(struct dma_resv *obj, enum dma_resv_usage usage, bool intr, unsigned long timeout)
Wait on reservation’s objects fences
Parameters
struct dma_resv *objthe reservation object
enum dma_resv_usage usagecontrols which fences to include, see enum dma_resv_usage.
bool intrif true, do interruptible wait
unsigned long timeouttimeout value in jiffies or zero to return immediately
Description
Callers are not required to hold specific locks, but maybe hold
dma_resv_lock() already
RETURNS
Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
greater than zero on success.
-
void dma_resv_set_deadline(struct dma_resv *obj, enum dma_resv_usage usage, ktime_t deadline)
Set a deadline on reservation’s objects fences
Parameters
struct dma_resv *objthe reservation object
enum dma_resv_usage usagecontrols which fences to include, see enum dma_resv_usage.
ktime_t deadlinethe requested deadline (MONOTONIC)
Description
May be called without holding the dma_resv lock. Sets deadline on
all fences filtered by usage.
-
bool dma_resv_test_signaled(struct dma_resv *obj, enum dma_resv_usage usage)
Test if a reservation object’s fences have been signaled.
Parameters
struct dma_resv *objthe reservation object
enum dma_resv_usage usagecontrols which fences to include, see enum dma_resv_usage.
Description
Callers are not required to hold specific locks, but maybe hold
dma_resv_lock() already.
RETURNS
True if all fences signaled, else false.
-
void dma_resv_describe(struct dma_resv *obj, struct seq_file *seq)
Dump description of the resv object into seq_file
Parameters
struct dma_resv *objthe reservation object
struct seq_file *seqthe seq_file to dump the description into
Description
Dump a textual description of the fences inside an dma_resv object into the
seq_file.
-
enum dma_resv_usage
how the fences from a dma_resv obj are used
Constants
DMA_RESV_USAGE_KERNELFor in kernel memory management only.
This should only be used for things like copying or clearing memory
with a DMA hardware engine for the purpose of kernel memory
management.
Drivers always must wait for those fences before accessing the
resource protected by the dma_resv object. The only exception for
that is when the resource is known to be locked down in place by
pinning it previously.
DMA_RESV_USAGE_WRITEImplicit write synchronization.
This should only be used for userspace command submissions which add
an implicit write dependency.
DMA_RESV_USAGE_READImplicit read synchronization.
This should only be used for userspace command submissions which add
an implicit read dependency.
DMA_RESV_USAGE_BOOKKEEPNo implicit sync.
This should be used by submissions which don’t want to participate in
any implicit synchronization.
The most common cases are preemption fences, page table updates, TLB
flushes as well as explicitly synced user submissions.
Explicitly synced user submissions can be promoted to
DMA_RESV_USAGE_READ or DMA_RESV_USAGE_WRITE as needed using
dma_buf_import_sync_file() when implicit synchronization should
become necessary after initial adding of the fence.
Description
This enum describes the different use cases for a dma_resv object and
controls which fences are returned when queried.
An important fact is that there is the order KERNEL<WRITE<READ<BOOKKEEP and
when the dma_resv object is asked for fences for one use case the fences
for the lower use case are returned as well.
For example when asking for WRITE fences then the KERNEL fences are returned
as well. Similar when asked for READ fences then both WRITE and KERNEL
fences are returned as well.
Already used fences can be promoted in the sense that a fence with
DMA_RESV_USAGE_BOOKKEEP could become DMA_RESV_USAGE_READ by adding it again
with this usage. But fences can never be degraded in the sense that a fence
with DMA_RESV_USAGE_WRITE could become DMA_RESV_USAGE_READ.
-
enum dma_resv_usage dma_resv_usage_rw(bool write)
helper for implicit sync
Parameters
bool writetrue if we create a new implicit sync write
Description
This returns the implicit synchronization usage for write or read accesses,
see enum dma_resv_usage and dma_buf.resv.
-
struct dma_resv
a reservation object manages fences for a buffer
Definition:
struct dma_resv {
struct ww_mutex lock;
struct dma_resv_list __rcu *fences;
};
Members
lockUpdate side lock. Don’t use directly, instead use the wrapper
functions like dma_resv_lock() and dma_resv_unlock().
Drivers which use the reservation object to manage memory dynamically
also use this lock to protect buffer object state like placement,
allocation policies or throughout command submission.
fencesArray of fences which where added to the dma_resv object
A new fence is added by calling dma_resv_add_fence(). Since this
often needs to be done past the point of no return in command
submission it cannot fail, and therefore sufficient slots need to be
reserved by calling dma_resv_reserve_fences().
Description
This is a container for dma_fence objects which needs to handle multiple use
cases.
One use is to synchronize cross-driver access to a struct dma_buf, either for
dynamic buffer management or just to handle implicit synchronization between
different users of the buffer in userspace. See dma_buf.resv for a more
in-depth discussion.
The other major use is to manage access and locking within a driver in a
buffer based memory manager. struct ttm_buffer_object is the canonical
example here, since this is where reservation objects originated from. But
use in drivers is spreading and some drivers also manage struct
drm_gem_object with the same scheme.
-
struct dma_resv_iter
current position into the dma_resv fences
Definition:
struct dma_resv_iter {
struct dma_resv *obj;
enum dma_resv_usage usage;
struct dma_fence *fence;
enum dma_resv_usage fence_usage;
unsigned int index;
struct dma_resv_list *fences;
unsigned int num_fences;
bool is_restarted;
};
Members
objThe dma_resv object we iterate over
usageReturn fences with this usage or lower.
fencethe currently handled fence
fence_usagethe usage of the current fence
indexindex into the shared fences
fencesthe shared fences; private, MUST not dereference
num_fencesnumber of fences
is_restartedtrue if this is the first returned fence
Description
Don’t touch this directly in the driver, use the accessor function instead.
IMPORTANT
When using the lockless iterators like dma_resv_iter_next_unlocked() or
dma_resv_for_each_fence_unlocked() beware that the iterator can be restarted.
Code which accumulates statistics or similar needs to check for this with
dma_resv_iter_is_restarted().
-
void dma_resv_iter_begin(struct dma_resv_iter *cursor, struct dma_resv *obj, enum dma_resv_usage usage)
initialize a dma_resv_iter object
Parameters
struct dma_resv_iter *cursorThe dma_resv_iter object to initialize
struct dma_resv *objThe dma_resv object which we want to iterate over
enum dma_resv_usage usagecontrols which fences to include, see enum dma_resv_usage.
-
void dma_resv_iter_end(struct dma_resv_iter *cursor)
cleanup a dma_resv_iter object
Parameters
struct dma_resv_iter *cursorthe dma_resv_iter object which should be cleaned up
Description
Make sure that the reference to the fence in the cursor is properly
dropped.
-
enum dma_resv_usage dma_resv_iter_usage(struct dma_resv_iter *cursor)
Return the usage of the current fence
Parameters
struct dma_resv_iter *cursorthe cursor of the current position
Description
Returns the usage of the currently processed fence.
-
bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor)
test if this is the first fence after a restart
Parameters
struct dma_resv_iter *cursorthe cursor with the current position
Description
Return true if this is the first fence in an iteration after a restart.
-
dma_resv_for_each_fence_unlocked
dma_resv_for_each_fence_unlocked (cursor, fence)
-
dma_resv_for_each_fence
dma_resv_for_each_fence (cursor, obj, usage, fence)
Parameters
cursora struct dma_resv_iter pointer
obja dma_resv object pointer
usagecontrols which fences to return
fencethe current fence
Description
Iterate over the fences in a struct dma_resv object while holding the
dma_resv.lock. all_fences controls if the shared fences are returned as
well. The cursor initialisation is part of the iterator and the fence stays
valid as long as the lock is held and so no extra reference to the fence is
taken.
-
int dma_resv_lock(struct dma_resv *obj, struct ww_acquire_ctx *ctx)
lock the reservation object
Parameters
struct dma_resv *objthe reservation object
struct ww_acquire_ctx *ctxthe locking context
Description
Locks the reservation object for exclusive access and modification. Note,
that the lock is only against other writers, readers will run concurrently
with a writer under RCU. The seqlock is used to notify readers if they
overlap with a writer.
As the reservation object may be locked by multiple parties in an
undefined order, a #ww_acquire_ctx is passed to unwind if a cycle
is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
object may be locked by itself by passing NULL as ctx.
When a die situation is indicated by returning -EDEADLK all locks held by
ctx must be unlocked and then dma_resv_lock_slow() called on obj.
Unlocked by calling dma_resv_unlock().
See also dma_resv_lock_interruptible() for the interruptible variant.
-
int dma_resv_lock_interruptible(struct dma_resv *obj, struct ww_acquire_ctx *ctx)
lock the reservation object
Parameters
struct dma_resv *objthe reservation object
struct ww_acquire_ctx *ctxthe locking context
Description
Locks the reservation object interruptible for exclusive access and
modification. Note, that the lock is only against other writers, readers
will run concurrently with a writer under RCU. The seqlock is used to
notify readers if they overlap with a writer.
As the reservation object may be locked by multiple parties in an
undefined order, a #ww_acquire_ctx is passed to unwind if a cycle
is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation
object may be locked by itself by passing NULL as ctx.
When a die situation is indicated by returning -EDEADLK all locks held by
ctx must be unlocked and then dma_resv_lock_slow_interruptible() called on
obj.
Unlocked by calling dma_resv_unlock().
-
void dma_resv_lock_slow(struct dma_resv *obj, struct ww_acquire_ctx *ctx)
slowpath lock the reservation object
Parameters
struct dma_resv *objthe reservation object
struct ww_acquire_ctx *ctxthe locking context
Description
Acquires the reservation object after a die case. This function
will sleep until the lock becomes available. See dma_resv_lock() as
well.
See also dma_resv_lock_slow_interruptible() for the interruptible variant.
-
int dma_resv_lock_slow_interruptible(struct dma_resv *obj, struct ww_acquire_ctx *ctx)
slowpath lock the reservation object, interruptible
Parameters
struct dma_resv *objthe reservation object
struct ww_acquire_ctx *ctxthe locking context
Description
Acquires the reservation object interruptible after a die case. This function
will sleep until the lock becomes available. See
dma_resv_lock_interruptible() as well.
-
bool dma_resv_trylock(struct dma_resv *obj)
trylock the reservation object
Parameters
struct dma_resv *objthe reservation object
Description
Tries to lock the reservation object for exclusive access and modification.
Note, that the lock is only against other writers, readers will run
concurrently with a writer under RCU. The seqlock is used to notify readers
if they overlap with a writer.
Also note that since no context is provided, no deadlock protection is
possible, which is also not needed for a trylock.
Returns true if the lock was acquired, false otherwise.
-
bool dma_resv_is_locked(struct dma_resv *obj)
is the reservation object locked
Parameters
struct dma_resv *objthe reservation object
Description
Returns true if the mutex is locked, false if unlocked.
-
struct ww_acquire_ctx *dma_resv_locking_ctx(struct dma_resv *obj)
returns the context used to lock the object
Parameters
struct dma_resv *objthe reservation object
Description
Returns the context used to lock a reservation object or NULL if no context
was used or the object is not locked at all.
WARNING: This interface is pretty horrible, but TTM needs it because it
doesn’t pass the struct ww_acquire_ctx around in some very long callchains.
Everyone else just uses it to check whether they’re holding a reservation or
not.
-
void dma_resv_unlock(struct dma_resv *obj)
unlock the reservation object
Parameters
struct dma_resv *objthe reservation object
Description
Unlocks the reservation object following exclusive access.
DMA Fences
DMA fences, represented by struct dma_fence, are the kernel internal
synchronization primitive for DMA operations like GPU rendering, video
encoding/decoding, or displaying buffers on a screen.
A fence is initialized using dma_fence_init() and completed using
dma_fence_signal(). Fences are associated with a context, allocated through
dma_fence_context_alloc(), and all fences on the same context are
fully ordered.
Since the purposes of fences is to facilitate cross-device and
cross-application synchronization, there’s multiple ways to use one:
Individual fences can be exposed as a sync_file, accessed as a file
descriptor from userspace, created by calling sync_file_create(). This is
called explicit fencing, since userspace passes around explicit
synchronization points.
Some subsystems also have their own explicit fencing primitives, like
drm_syncobj. Compared to sync_file, a drm_syncobj allows the underlying
fence to be updated.
Then there’s also implicit fencing, where the synchronization points are
implicitly passed around as part of shared dma_buf instances. Such
implicit fences are stored in struct dma_resv through the
dma_buf.resv pointer.
DMA Fence Cross-Driver Contract
Since dma_fence provide a cross driver contract, all drivers must follow the
same rules:
Fences must complete in a reasonable time. Fences which represent kernels
and shaders submitted by userspace, which could run forever, must be backed
up by timeout and gpu hang recovery code. Minimally that code must prevent
further command submission and force complete all in-flight fences, e.g.
when the driver or hardware do not support gpu reset, or if the gpu reset
failed for some reason. Ideally the driver supports gpu recovery which only
affects the offending userspace context, and no other userspace
submissions.
Drivers may have different ideas of what completion within a reasonable
time means. Some hang recovery code uses a fixed timeout, others a mix
between observing forward progress and increasingly strict timeouts.
Drivers should not try to second guess timeout handling of fences from
other drivers.
To ensure there’s no deadlocks of dma_fence_wait() against other locks
drivers should annotate all code required to reach dma_fence_signal(),
which completes the fences, with dma_fence_begin_signalling() and
dma_fence_end_signalling().
Drivers are allowed to call dma_fence_wait() while holding dma_resv_lock().
This means any code required for fence completion cannot acquire a
dma_resv lock. Note that this also pulls in the entire established
locking hierarchy around dma_resv_lock() and dma_resv_unlock().
Drivers are allowed to call dma_fence_wait() from their shrinker
callbacks. This means any code required for fence completion cannot
allocate memory with GFP_KERNEL.
Drivers are allowed to call dma_fence_wait() from their mmu_notifier
respectively mmu_interval_notifier callbacks. This means any code required
for fence completion cannot allocate memory with GFP_NOFS or GFP_NOIO.
Only GFP_ATOMIC is permissible, which might fail.
Note that only GPU drivers have a reasonable excuse for both requiring
mmu_interval_notifier and shrinker callbacks at the same time as having to
track asynchronous compute work using dma_fence. No driver outside of
drivers/gpu should ever call dma_fence_wait() in such contexts.
DMA Fence Signalling Annotations
Proving correctness of all the kernel code around dma_fence through code
review and testing is tricky for a few reasons:
It is a cross-driver contract, and therefore all drivers must follow the
same rules for lock nesting order, calling contexts for various functions
and anything else significant for in-kernel interfaces. But it is also
impossible to test all drivers in a single machine, hence brute-force N vs.
N testing of all combinations is impossible. Even just limiting to the
possible combinations is infeasible.
There is an enormous amount of driver code involved. For render drivers
there’s the tail of command submission, after fences are published,
scheduler code, interrupt and workers to process job completion,
and timeout, gpu reset and gpu hang recovery code. Plus for integration
with core mm with have mmu_notifier, respectively mmu_interval_notifier,
and shrinker. For modesetting drivers there’s the commit tail functions
between when fences for an atomic modeset are published, and when the
corresponding vblank completes, including any interrupt processing and
related workers. Auditing all that code, across all drivers, is not
feasible.
Due to how many other subsystems are involved and the locking hierarchies
this pulls in there is extremely thin wiggle-room for driver-specific
differences. dma_fence interacts with almost all of the core memory
handling through page fault handlers via dma_resv, dma_resv_lock() and
dma_resv_unlock(). On the other side it also interacts through all
allocation sites through mmu_notifier and shrinker.
Furthermore lockdep does not handle cross-release dependencies, which means
any deadlocks between dma_fence_wait() and dma_fence_signal() can’t be caught
at runtime with some quick testing. The simplest example is one thread
waiting on a dma_fence while holding a lock:
lock(A);
dma_fence_wait(B);
unlock(A);
while the other thread is stuck trying to acquire the same lock, which
prevents it from signalling the fence the previous thread is stuck waiting
on:
lock(A);
unlock(A);
dma_fence_signal(B);
By manually annotating all code relevant to signalling a dma_fence we can
teach lockdep about these dependencies, which also helps with the validation
headache since now lockdep can check all the rules for us:
cookie = dma_fence_begin_signalling();
lock(A);
unlock(A);
dma_fence_signal(B);
dma_fence_end_signalling(cookie);
For using dma_fence_begin_signalling() and dma_fence_end_signalling() to
annotate critical sections the following rules need to be observed:
All code necessary to complete a dma_fence must be annotated, from the
point where a fence is accessible to other threads, to the point where
dma_fence_signal() is called. Un-annotated code can contain deadlock issues,
and due to the very strict rules and many corner cases it is infeasible to
catch these just with review or normal stress testing.
struct dma_resv deserves a special note, since the readers are only
protected by rcu. This means the signalling critical section starts as soon
as the new fences are installed, even before dma_resv_unlock() is called.
The only exception are fast paths and opportunistic signalling code, which
calls dma_fence_signal() purely as an optimization, but is not required to
guarantee completion of a dma_fence. The usual example is a wait IOCTL
which calls dma_fence_signal(), while the mandatory completion path goes
through a hardware interrupt and possible job completion worker.
To aid composability of code, the annotations can be freely nested, as long
as the overall locking hierarchy is consistent. The annotations also work
both in interrupt and process context. Due to implementation details this
requires that callers pass an opaque cookie from
dma_fence_begin_signalling() to dma_fence_end_signalling().
Validation against the cross driver contract is implemented by priming
lockdep with the relevant hierarchy at boot-up. This means even just
testing with a single device is enough to validate a driver, at least as
far as deadlocks with dma_fence_wait() against dma_fence_signal() are
concerned.
DMA Fence Deadline Hints
In an ideal world, it would be possible to pipeline a workload sufficiently
that a utilization based device frequency governor could arrive at a minimum
frequency that meets the requirements of the use-case, in order to minimize
power consumption. But in the real world there are many workloads which
defy this ideal. For example, but not limited to:
Workloads that ping-pong between device and CPU, with alternating periods
of CPU waiting for device, and device waiting on CPU. This can result in
devfreq and cpufreq seeing idle time in their respective domains and in
result reduce frequency.
Workloads that interact with a periodic time based deadline, such as double
buffered GPU rendering vs vblank sync’d page flipping. In this scenario,
missing a vblank deadline results in an increase in idle time on the GPU
(since it has to wait an additional vblank period), sending a signal to
the GPU’s devfreq to reduce frequency, when in fact the opposite is what is
needed.
To this end, deadline hint(s) can be set on a dma_fence via dma_fence_set_deadline
(or indirectly via userspace facing ioctls like sync_set_deadline).
The deadline hint provides a way for the waiting driver, or userspace, to
convey an appropriate sense of urgency to the signaling driver.
A deadline hint is given in absolute ktime (CLOCK_MONOTONIC for userspace
facing APIs). The time could either be some point in the future (such as
the vblank based deadline for page-flipping, or the start of a compositor’s
composition cycle), or the current time to indicate an immediate deadline
hint (Ie. forward progress cannot be made until this fence is signaled).
Multiple deadlines may be set on a given fence, even in parallel. See the
documentation for dma_fence_ops.set_deadline.
The deadline hint is just that, a hint. The driver that created the fence
may react by increasing frequency, making different scheduling choices, etc.
Or doing nothing at all.
DMA Fences Functions Reference
-
struct dma_fence *dma_fence_get_stub(void)
return a signaled fence
Parameters
voidno arguments
Description
Return a stub fence which is already signaled. The fence’s
timestamp corresponds to the first time after boot this
function is called.
-
struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp)
return a private, signaled fence
Parameters
ktime_t timestamptimestamp when the fence was signaled
Description
Return a newly allocated and signaled stub fence.
-
u64 dma_fence_context_alloc(unsigned num)
allocate an array of fence contexts
Parameters
unsigned numamount of contexts to allocate
Description
This function will return the first index of the number of fence contexts
allocated. The fence context is used for setting dma_fence.context to a
unique number by passing the context to dma_fence_init().
-
bool dma_fence_begin_signalling(void)
begin a critical DMA fence signalling section
-
void dma_fence_end_signalling(bool cookie)
end a critical DMA fence signalling section
-
int dma_fence_signal_timestamp_locked(struct dma_fence *fence, ktime_t timestamp)
signal completion of a fence
Parameters
struct dma_fence *fencethe fence to signal
ktime_t timestampfence signal timestamp in kernel’s CLOCK_MONOTONIC time domain
Description
Signal completion for software callbacks on a fence, this will unblock
dma_fence_wait() calls and run all the callbacks added with
dma_fence_add_callback(). Can be called multiple times, but since a fence
can only go from the unsignaled to the signaled state and not back, it will
only be effective the first time. Set the timestamp provided as the fence
signal timestamp.
Unlike dma_fence_signal_timestamp(), this function must be called with
dma_fence.lock held.
Returns 0 on success and a negative error value when fence has been
signalled already.
-
int dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp)
signal completion of a fence
Parameters
struct dma_fence *fencethe fence to signal
ktime_t timestampfence signal timestamp in kernel’s CLOCK_MONOTONIC time domain
Description
Signal completion for software callbacks on a fence, this will unblock
dma_fence_wait() calls and run all the callbacks added with
dma_fence_add_callback(). Can be called multiple times, but since a fence
can only go from the unsignaled to the signaled state and not back, it will
only be effective the first time. Set the timestamp provided as the fence
signal timestamp.
Returns 0 on success and a negative error value when fence has been
signalled already.
-
int dma_fence_signal_locked(struct dma_fence *fence)
signal completion of a fence
Parameters
struct dma_fence *fencethe fence to signal
Description
Signal completion for software callbacks on a fence, this will unblock
dma_fence_wait() calls and run all the callbacks added with
dma_fence_add_callback(). Can be called multiple times, but since a fence
can only go from the unsignaled to the signaled state and not back, it will
only be effective the first time.
Unlike dma_fence_signal(), this function must be called with dma_fence.lock
held.
Returns 0 on success and a negative error value when fence has been
signalled already.
-
int dma_fence_signal(struct dma_fence *fence)
signal completion of a fence
Parameters
struct dma_fence *fencethe fence to signal
Description
Signal completion for software callbacks on a fence, this will unblock
dma_fence_wait() calls and run all the callbacks added with
dma_fence_add_callback(). Can be called multiple times, but since a fence
can only go from the unsignaled to the signaled state and not back, it will
only be effective the first time.
Returns 0 on success and a negative error value when fence has been
signalled already.
-
signed long dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
sleep until the fence gets signaled or until timeout elapses
Parameters
struct dma_fence *fencethe fence to wait on
bool intrif true, do an interruptible wait
signed long timeouttimeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
Description
Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
remaining timeout in jiffies on success. Other error values may be
returned on custom implementations.
Performs a synchronous wait on this fence. It is assumed the caller
directly or indirectly (buf-mgr between reservation and committing)
holds a reference to the fence, otherwise the fence might be
freed before return, resulting in undefined behavior.
See also dma_fence_wait() and dma_fence_wait_any_timeout().
-
void dma_fence_release(struct kref *kref)
default release function for fences
-
void dma_fence_free(struct dma_fence *fence)
default release function for dma_fence.
-
void dma_fence_enable_sw_signaling(struct dma_fence *fence)
enable signaling on fence
Parameters
struct dma_fence *fencethe fence to enable
Description
This will request for sw signaling to be enabled, to make the fence
complete as soon as possible. This calls dma_fence_ops.enable_signaling
internally.
-
int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb, dma_fence_func_t func)
add a callback to be called when the fence is signaled
Parameters
struct dma_fence *fencethe fence to wait on
struct dma_fence_cb *cbthe callback to register
dma_fence_func_t functhe function to call
Description
Add a software callback to the fence. The caller should keep a reference to
the fence.
cb will be initialized by dma_fence_add_callback(), no initialization
by the caller is required. Any number of callbacks can be registered
to a fence, but a callback can only be registered to one fence at a time.
If fence is already signaled, this function will return -ENOENT (and
not call the callback).
Note that the callback can be called from an atomic context or irq context.
Returns 0 in case of success, -ENOENT if the fence is already signaled
and -EINVAL in case of error.
-
int dma_fence_get_status(struct dma_fence *fence)
returns the status upon completion
Parameters
struct dma_fence *fencethe dma_fence to query
Description
This wraps dma_fence_get_status_locked() to return the error status
condition on a signaled fence. See dma_fence_get_status_locked() for more
details.
Returns 0 if the fence has not yet been signaled, 1 if the fence has
been signaled without an error condition, or a negative error code
if the fence has been completed in err.
-
bool dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *cb)
remove a callback from the signaling list
Parameters
struct dma_fence *fencethe fence to wait on
struct dma_fence_cb *cbthe callback to remove
Description
Remove a previously queued callback from the fence. This function returns
true if the callback is successfully removed, or false if the fence has
already been signaled.
WARNING:
Cancelling a callback should only be done if you really know what you’re
doing, since deadlocks and race conditions could occur all too easily. For
this reason, it should only ever be done on hardware lockup recovery,
with a reference held to the fence.
Behaviour is undefined if cb has not been added to fence using
dma_fence_add_callback() beforehand.
-
signed long dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout)
default sleep until the fence gets signaled or until timeout elapses
Parameters
struct dma_fence *fencethe fence to wait on
bool intrif true, do an interruptible wait
signed long timeouttimeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
Description
Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
remaining timeout in jiffies on success. If timeout is zero the value one is
returned if the fence is already signaled for consistency with other
functions taking a jiffies timeout.
-
signed long dma_fence_wait_any_timeout(struct dma_fence **fences, uint32_t count, bool intr, signed long timeout, uint32_t *idx)
sleep until any fence gets signaled or until timeout elapses
Parameters
struct dma_fence **fencesarray of fences to wait on
uint32_t countnumber of fences to wait on
bool intrif true, do an interruptible wait
signed long timeouttimeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
uint32_t *idxused to store the first signaled fence index, meaningful only on
positive return
Description
Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if
interrupted, 0 if the wait timed out, or the remaining timeout in jiffies
on success.
Synchronous waits for the first fence in the array to be signaled. The
caller needs to hold a reference to all fences in the array, otherwise a
fence might be freed before return, resulting in undefined behavior.
See also dma_fence_wait() and dma_fence_wait_timeout().
-
void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
set desired fence-wait deadline hint
Parameters
struct dma_fence *fencethe fence that is to be waited on
ktime_t deadlinethe time by which the waiter hopes for the fence to be
signaled
Description
Give the fence signaler a hint about an upcoming deadline, such as
vblank, by which point the waiter would prefer the fence to be
signaled by. This is intended to give feedback to the fence signaler
to aid in power management decisions, such as boosting GPU frequency
if a periodic vblank deadline is approaching but the fence is not
yet signaled..
-
void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq)
Dump fence description into seq_file
Parameters
struct dma_fence *fencethe fence to describe
struct seq_file *seqthe seq_file to put the textual description into
Description
Dump a textual description of the fence and it’s state into the seq_file.
-
void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, spinlock_t *lock, u64 context, u64 seqno)
Initialize a custom fence.
Parameters
struct dma_fence *fencethe fence to initialize
const struct dma_fence_ops *opsthe dma_fence_ops for operations on this fence
spinlock_t *lockthe irqsafe spinlock to use for locking this fence
u64 contextthe execution context this fence is run on
u64 seqnoa linear increasing sequence number for this context
Description
Initializes an allocated fence, the caller doesn’t have to keep its
refcount after committing with this fence, but it will need to hold a
refcount again if dma_fence_ops.enable_signaling gets called.
context and seqno are used for easy comparison between fences, allowing
to check which fence is later by simply using dma_fence_later().
-
void dma_fence_init64(struct dma_fence *fence, const struct dma_fence_ops *ops, spinlock_t *lock, u64 context, u64 seqno)
Initialize a custom fence with 64-bit seqno support.
Parameters
struct dma_fence *fencethe fence to initialize
const struct dma_fence_ops *opsthe dma_fence_ops for operations on this fence
spinlock_t *lockthe irqsafe spinlock to use for locking this fence
u64 contextthe execution context this fence is run on
u64 seqnoa linear increasing sequence number for this context
Description
Initializes an allocated fence, the caller doesn’t have to keep its
refcount after committing with this fence, but it will need to hold a
refcount again if dma_fence_ops.enable_signaling gets called.
Context and seqno are used for easy comparison between fences, allowing
to check which fence is later by simply using