Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <laurent.pinchart@ideasonboard.com>
Reviewed-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Link: https://lore.kernel.org/r/20200717013337.24122-3-laurent.pinchart@ideasonboard.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Laurent Pinchart and committed by
Vinod Koul
9c8ebd8b ef9303fd

+69 -1
+3 -1
Documentation/driver-api/dmaengine/client.rst
··· 86 86 - interleaved_dma: This is common to Slave as well as M2M clients. For slave 87 87 address of devices' fifo could be already known to the driver. 88 88 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. 90 92 91 93 A non-NULL return of this transfer API represents a "descriptor" for 92 94 the given transaction.
+49
Documentation/driver-api/dmaengine/provider.rst
··· 239 239 want to transfer a portion of uncompressed data directly to the 240 240 display to print it 241 241 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 + 242 263 These various types will also affect how the source and destination 243 264 addresses change over time. 244 265 ··· 551 530 used for issuing commands to other peripherals/register reads/register 552 531 writes for which the descriptor should be in different format from 553 532 normal data descriptors. 533 + 534 + - DMA_PREP_REPEAT 535 + 536 + - If set, the transfer will be automatically repeated when it ends until a 537 + new transfer is queued on the same channel with the DMA_PREP_LOAD_EOT flag. 538 + If the next transfer to be queued on the channel does not have the 539 + DMA_PREP_LOAD_EOT flag set, the current transfer will be repeated until the 540 + client terminates all transfers. 541 + 542 + - This flag is only supported if the channel reports the DMA_REPEAT 543 + capability. 544 + 545 + - DMA_PREP_LOAD_EOT 546 + 547 + - If set, the transfer will replace the transfer currently being executed at 548 + the end of the transfer. 549 + 550 + - This is the default behaviour for non-repeated transfers, specifying 551 + DMA_PREP_LOAD_EOT for non-repeated transfers will thus make no difference. 552 + 553 + - When using repeated transfers, DMA clients will usually need to set the 554 + DMA_PREP_LOAD_EOT flag on all transfers, otherwise the channel will keep 555 + repeating the last repeated transfer and ignore the new transfers being 556 + queued. Failure to set DMA_PREP_LOAD_EOT will appear as if the channel was 557 + stuck on the previous transfer. 558 + 559 + - This flag is only supported if the channel reports the DMA_LOAD_EOT 560 + capability. 554 561 555 562 General Design Notes 556 563 ====================
+17
include/linux/dmaengine.h
··· 61 61 DMA_SLAVE, 62 62 DMA_CYCLIC, 63 63 DMA_INTERLEAVE, 64 + DMA_REPEAT, 65 + DMA_LOAD_EOT, 64 66 /* last transaction type for creation of the capabilities mask */ 65 67 DMA_TX_TYPE_END, 66 68 }; ··· 178 176 * @DMA_PREP_CMD: tell the driver that the data passed to DMA API is command 179 177 * data and the descriptor should be in different format from normal 180 178 * data descriptors. 179 + * @DMA_PREP_REPEAT: tell the driver that the transaction shall be automatically 180 + * repeated when it ends until a transaction is issued on the same channel 181 + * with the DMA_PREP_LOAD_EOT flag set. This flag is only applicable to 182 + * interleaved transactions and is ignored for all other transaction types. 183 + * @DMA_PREP_LOAD_EOT: tell the driver that the transaction shall replace any 184 + * active repeated (as indicated by DMA_PREP_REPEAT) transaction when the 185 + * repeated transaction ends. Not setting this flag when the previously queued 186 + * transaction is marked with DMA_PREP_REPEAT will cause the new transaction 187 + * to never be processed and stay in the issued queue forever. The flag is 188 + * ignored if the previous transaction is not a repeated transaction. 181 189 */ 182 190 enum dma_ctrl_flags { 183 191 DMA_PREP_INTERRUPT = (1 << 0), ··· 198 186 DMA_PREP_FENCE = (1 << 5), 199 187 DMA_CTRL_REUSE = (1 << 6), 200 188 DMA_PREP_CMD = (1 << 7), 189 + DMA_PREP_REPEAT = (1 << 8), 190 + DMA_PREP_LOAD_EOT = (1 << 9), 201 191 }; 202 192 203 193 /** ··· 993 979 unsigned long flags) 994 980 { 995 981 if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma) 982 + return NULL; 983 + if (flags & DMA_PREP_REPEAT && 984 + !test_bit(DMA_REPEAT, chan->device->cap_mask.bits)) 996 985 return NULL; 997 986 998 987 return chan->device->device_prep_interleaved_dma(chan, xt, flags);