Skip to content

Commit 9c8ebd8

Browse files
pinchartlvinodkoul
authored andcommitted
dmaengine: Add support for repeating transactions
DMA engines used with displays perform 2D interleaved transfers to read framebuffers from memory and feed the data to the display engine. As the same framebuffer can be displayed for multiple frames, the DMA transactions need to be repeated until a new framebuffer replaces the current one. This feature is implemented natively by some DMA engines that have the ability to repeat transactions and switch to a new transaction at the end of a transfer without any race condition or frame loss. This patch implements support for this feature in the DMA engine API. A new DMA_PREP_REPEAT transaction flag allows DMA clients to instruct the DMA channel to repeat the transaction automatically until one or more new transactions are issued on the channel (or until all active DMA transfers are explicitly terminated with the dmaengine_terminate_*() functions). A new DMA_REPEAT transaction type is also added for DMA engine drivers to report their support of the DMA_PREP_REPEAT flag. A new DMA_PREP_LOAD_EOT transaction flag is also introduced (with a corresponding DMA_LOAD_EOT capability bit), as requested during the review of v4. The flag instructs the DMA channel that the transaction being queued should replace the active repeated transaction when the latter terminates (at End Of Transaction). Not setting the flag will result in the active repeated transaction to continue being repeated, and the new transaction being silently ignored. The DMA_PREP_REPEAT flag is currently supported for interleaved transactions only. Its usage can easily be extended to cover more transaction types simply by adding an appropriate check in the corresponding dmaengine_prep_*() function. Signed-off-by: Laurent Pinchart <[email protected]> Reviewed-by: Peter Ujfalusi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent ef9303f commit 9c8ebd8

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

Documentation/driver-api/dmaengine/client.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ The details of these operations are:
8686
- interleaved_dma: This is common to Slave as well as M2M clients. For slave
8787
address of devices' fifo could be already known to the driver.
8888
Various types of operations could be expressed by setting
89-
appropriate values to the 'dma_interleaved_template' members.
89+
appropriate values to the 'dma_interleaved_template' members. Cyclic
90+
interleaved DMA transfers are also possible if supported by the channel by
91+
setting the DMA_PREP_REPEAT transfer flag.
9092

9193
A non-NULL return of this transfer API represents a "descriptor" for
9294
the given transaction.

Documentation/driver-api/dmaengine/provider.rst

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,27 @@ Currently, the types available are:
239239
want to transfer a portion of uncompressed data directly to the
240240
display to print it
241241

242+
- DMA_REPEAT
243+
244+
- The device supports repeated transfers. A repeated transfer, indicated by
245+
the DMA_PREP_REPEAT transfer flag, is similar to a cyclic transfer in that
246+
it gets automatically repeated when it ends, but can additionally be
247+
replaced by the client.
248+
249+
- This feature is limited to interleaved transfers, this flag should thus not
250+
be set if the DMA_INTERLEAVE flag isn't set. This limitation is based on
251+
the current needs of DMA clients, support for additional transfer types
252+
should be added in the future if and when the need arises.
253+
254+
- DMA_LOAD_EOT
255+
256+
- The device supports replacing repeated transfers at end of transfer (EOT)
257+
by queuing a new transfer with the DMA_PREP_LOAD_EOT flag set.
258+
259+
- Support for replacing a currently running transfer at another point (such
260+
as end of burst instead of end of transfer) will be added in the future
261+
based on DMA clients needs, if and when the need arises.
262+
242263
These various types will also affect how the source and destination
243264
addresses change over time.
244265

@@ -531,6 +552,34 @@ DMA_CTRL_REUSE
531552
writes for which the descriptor should be in different format from
532553
normal data descriptors.
533554

555+
- DMA_PREP_REPEAT
556+
557+
- If set, the transfer will be automatically repeated when it ends until a
558+
new transfer is queued on the same channel with the DMA_PREP_LOAD_EOT flag.
559+
If the next transfer to be queued on the channel does not have the
560+
DMA_PREP_LOAD_EOT flag set, the current transfer will be repeated until the
561+
client terminates all transfers.
562+
563+
- This flag is only supported if the channel reports the DMA_REPEAT
564+
capability.
565+
566+
- DMA_PREP_LOAD_EOT
567+
568+
- If set, the transfer will replace the transfer currently being executed at
569+
the end of the transfer.
570+
571+
- This is the default behaviour for non-repeated transfers, specifying
572+
DMA_PREP_LOAD_EOT for non-repeated transfers will thus make no difference.
573+
574+
- When using repeated transfers, DMA clients will usually need to set the
575+
DMA_PREP_LOAD_EOT flag on all transfers, otherwise the channel will keep
576+
repeating the last repeated transfer and ignore the new transfers being
577+
queued. Failure to set DMA_PREP_LOAD_EOT will appear as if the channel was
578+
stuck on the previous transfer.
579+
580+
- This flag is only supported if the channel reports the DMA_LOAD_EOT
581+
capability.
582+
534583
General Design Notes
535584
====================
536585

include/linux/dmaengine.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ enum dma_transaction_type {
6161
DMA_SLAVE,
6262
DMA_CYCLIC,
6363
DMA_INTERLEAVE,
64+
DMA_REPEAT,
65+
DMA_LOAD_EOT,
6466
/* last transaction type for creation of the capabilities mask */
6567
DMA_TX_TYPE_END,
6668
};
@@ -176,6 +178,16 @@ struct dma_interleaved_template {
176178
* @DMA_PREP_CMD: tell the driver that the data passed to DMA API is command
177179
* data and the descriptor should be in different format from normal
178180
* data descriptors.
181+
* @DMA_PREP_REPEAT: tell the driver that the transaction shall be automatically
182+
* repeated when it ends until a transaction is issued on the same channel
183+
* with the DMA_PREP_LOAD_EOT flag set. This flag is only applicable to
184+
* interleaved transactions and is ignored for all other transaction types.
185+
* @DMA_PREP_LOAD_EOT: tell the driver that the transaction shall replace any
186+
* active repeated (as indicated by DMA_PREP_REPEAT) transaction when the
187+
* repeated transaction ends. Not setting this flag when the previously queued
188+
* transaction is marked with DMA_PREP_REPEAT will cause the new transaction
189+
* to never be processed and stay in the issued queue forever. The flag is
190+
* ignored if the previous transaction is not a repeated transaction.
179191
*/
180192
enum dma_ctrl_flags {
181193
DMA_PREP_INTERRUPT = (1 << 0),
@@ -186,6 +198,8 @@ enum dma_ctrl_flags {
186198
DMA_PREP_FENCE = (1 << 5),
187199
DMA_CTRL_REUSE = (1 << 6),
188200
DMA_PREP_CMD = (1 << 7),
201+
DMA_PREP_REPEAT = (1 << 8),
202+
DMA_PREP_LOAD_EOT = (1 << 9),
189203
};
190204

191205
/**
@@ -980,6 +994,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma(
980994
{
981995
if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma)
982996
return NULL;
997+
if (flags & DMA_PREP_REPEAT &&
998+
!test_bit(DMA_REPEAT, chan->device->cap_mask.bits))
999+
return NULL;
9831000

9841001
return chan->device->device_prep_interleaved_dma(chan, xt, flags);
9851002
}

0 commit comments

Comments
 (0)