mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
docs: dma-api: document __dma_from_device_group_begin()/end()
Document the __dma_from_device_group_begin()/end() annotations. Message-ID: <01ea88055ded4d70cac70ba557680fd5fa7d9ff5.1767601130.git.mst@redhat.com> Acked-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Petr Tesarik <ptesarik@suse.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
ca085faabb
commit
1e8b5d8555
1 changed files with 52 additions and 0 deletions
|
|
@ -146,6 +146,58 @@ What about block I/O and networking buffers? The block I/O and
|
|||
networking subsystems make sure that the buffers they use are valid
|
||||
for you to DMA from/to.
|
||||
|
||||
__dma_from_device_group_begin/end annotations
|
||||
=============================================
|
||||
|
||||
As explained previously, when a structure contains a DMA_FROM_DEVICE /
|
||||
DMA_BIDIRECTIONAL buffer (device writes to memory) alongside fields that the
|
||||
CPU writes to, cache line sharing between the DMA buffer and CPU-written fields
|
||||
can cause data corruption on CPUs with DMA-incoherent caches.
|
||||
|
||||
The ``__dma_from_device_group_begin(GROUP)/__dma_from_device_group_end(GROUP)``
|
||||
macros ensure proper alignment to prevent this::
|
||||
|
||||
struct my_device {
|
||||
spinlock_t lock1;
|
||||
__dma_from_device_group_begin();
|
||||
char dma_buffer1[16];
|
||||
char dma_buffer2[16];
|
||||
__dma_from_device_group_end();
|
||||
spinlock_t lock2;
|
||||
};
|
||||
|
||||
To isolate a DMA buffer from adjacent fields, use
|
||||
``__dma_from_device_group_begin(GROUP)`` before the first DMA buffer
|
||||
field and ``__dma_from_device_group_end(GROUP)`` after the last DMA
|
||||
buffer field (with the same GROUP name). This protects both the head
|
||||
and tail of the buffer from cache line sharing.
|
||||
|
||||
The GROUP parameter is an optional identifier that names the DMA buffer group
|
||||
(in case you have several in the same structure)::
|
||||
|
||||
struct my_device {
|
||||
spinlock_t lock1;
|
||||
__dma_from_device_group_begin(buffer1);
|
||||
char dma_buffer1[16];
|
||||
__dma_from_device_group_end(buffer1);
|
||||
spinlock_t lock2;
|
||||
__dma_from_device_group_begin(buffer2);
|
||||
char dma_buffer2[16];
|
||||
__dma_from_device_group_end(buffer2);
|
||||
};
|
||||
|
||||
On cache-coherent platforms these macros expand to zero-length array markers.
|
||||
On non-coherent platforms, they also ensure the minimal DMA alignment, which
|
||||
can be as large as 128 bytes.
|
||||
|
||||
.. note::
|
||||
|
||||
It is allowed (though somewhat fragile) to include extra fields, not
|
||||
intended for DMA from the device, within the group (in order to pack the
|
||||
structure tightly) - but only as long as the CPU does not write these
|
||||
fields while any fields in the group are mapped for DMA_FROM_DEVICE or
|
||||
DMA_BIDIRECTIONAL.
|
||||
|
||||
DMA addressing capabilities
|
||||
===========================
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue