Hi Laurent, On 08/07/2020 23.19, Laurent Pinchart wrote: > 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@xxxxxxxxxxxxxxxx> > --- > Changes since v5: > > - Document the API in Documentation/driver-api/dmaengine/ > - Small improvements to documentation in header file Reviewed-by: Peter Ujfalusi <peter.ujfalusi@xxxxxx> > Changes since v4: > > - Add DMA_LOAD_EOT and DMA_PREP_LOAD_EOT flags > --- > Documentation/driver-api/dmaengine/client.rst | 4 +- > .../driver-api/dmaengine/provider.rst | 49 +++++++++++++++++++ > include/linux/dmaengine.h | 17 +++++++ > 3 files changed, 69 insertions(+), 1 deletion(-) > > diff --git a/Documentation/driver-api/dmaengine/client.rst b/Documentation/driver-api/dmaengine/client.rst > index 2104830a99ae..41938aa2bdeb 100644 > --- a/Documentation/driver-api/dmaengine/client.rst > +++ b/Documentation/driver-api/dmaengine/client.rst > @@ -86,7 +86,9 @@ The details of these operations are: > - interleaved_dma: This is common to Slave as well as M2M clients. For slave > address of devices' fifo could be already known to the driver. > Various types of operations could be expressed by setting > - appropriate values to the 'dma_interleaved_template' members. > + appropriate values to the 'dma_interleaved_template' members. Cyclic > + interleaved DMA transfers are also possible if supported by the channel by > + setting the DMA_PREP_REPEAT transfer flag. > > A non-NULL return of this transfer API represents a "descriptor" for > the given transaction. > diff --git a/Documentation/driver-api/dmaengine/provider.rst b/Documentation/driver-api/dmaengine/provider.rst > index 56e5833e8a07..f896acccdfee 100644 > --- a/Documentation/driver-api/dmaengine/provider.rst > +++ b/Documentation/driver-api/dmaengine/provider.rst > @@ -239,6 +239,27 @@ Currently, the types available are: > want to transfer a portion of uncompressed data directly to the > display to print it > > +- DMA_REPEAT > + > + - The device supports repeated transfers. A repeated transfer, indicated by > + the DMA_PREP_REPEAT transfer flag, is similar to a cyclic transfer in that > + it gets automatically repeated when it ends, but can additionally be > + replaced by the client. > + > + - This feature is limited to interleaved transfers, this flag should thus not > + be set if the DMA_INTERLEAVE flag isn't set. This limitation is based on > + the current needs of DMA clients, support for additional transfer types > + should be added in the future if and when the need arises. > + > +- DMA_LOAD_EOT > + > + - The device supports replacing repeated transfers at end of transfer (EOT) > + by queuing a new transfer with the DMA_PREP_LOAD_EOT flag set. > + > + - Support for replacing a currently running transfer at another point (such > + as end of burst instead of end of transfer) will be added in the future > + based on DMA clients needs, if and when the need arises. > + > These various types will also affect how the source and destination > addresses change over time. > > @@ -531,6 +552,34 @@ DMA_CTRL_REUSE > writes for which the descriptor should be in different format from > normal data descriptors. > > +- DMA_PREP_REPEAT > + > + - If set, the transfer will be automatically repeated when it ends until a > + new transfer is queued on the same channel with the DMA_PREP_LOAD_EOT flag. > + If the next transfer to be queued on the channel does not have the > + DMA_PREP_LOAD_EOT flag set, the current transfer will be repeated until the > + client terminates all transfers. > + > + - This flag is only supported if the channel reports the DMA_REPEAT > + capability. > + > +- DMA_PREP_LOAD_EOT > + > + - If set, the transfer will replace the transfer currently being executed at > + the end of the transfer. > + > + - This is the default behaviour for non-repeated transfers, specifying > + DMA_PREP_LOAD_EOT for non-repeated transfers will thus make no difference. > + > + - When using repeated transfers, DMA clients will usually need to set the > + DMA_PREP_LOAD_EOT flag on all transfers, otherwise the channel will keep > + repeating the last repeated transfer and ignore the new transfers being > + queued. Failure to set DMA_PREP_LOAD_EOT will appear as if the channel was > + stuck on the previous transfer. > + > + - This flag is only supported if the channel reports the DMA_LOAD_EOT > + capability. > + > General Design Notes > ==================== > > diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h > index e1c03339918f..328e3aca7f51 100644 > --- a/include/linux/dmaengine.h > +++ b/include/linux/dmaengine.h > @@ -61,6 +61,8 @@ enum dma_transaction_type { > DMA_SLAVE, > DMA_CYCLIC, > DMA_INTERLEAVE, > + DMA_REPEAT, > + DMA_LOAD_EOT, > /* last transaction type for creation of the capabilities mask */ > DMA_TX_TYPE_END, > }; > @@ -176,6 +178,16 @@ struct dma_interleaved_template { > * @DMA_PREP_CMD: tell the driver that the data passed to DMA API is command > * data and the descriptor should be in different format from normal > * data descriptors. > + * @DMA_PREP_REPEAT: tell the driver that the transaction shall be automatically > + * repeated when it ends until a transaction is issued on the same channel > + * with the DMA_PREP_LOAD_EOT flag set. This flag is only applicable to > + * interleaved transactions and is ignored for all other transaction types. > + * @DMA_PREP_LOAD_EOT: tell the driver that the transaction shall replace any > + * active repeated (as indicated by DMA_PREP_REPEAT) transaction when the > + * repeated transaction ends. Not setting this flag when the previously queued > + * transaction is marked with DMA_PREP_REPEAT will cause the new transaction > + * to never be processed and stay in the issued queue forever. The flag is > + * ignored if the previous transaction is not a repeated transaction. > */ > enum dma_ctrl_flags { > DMA_PREP_INTERRUPT = (1 << 0), > @@ -186,6 +198,8 @@ enum dma_ctrl_flags { > DMA_PREP_FENCE = (1 << 5), > DMA_CTRL_REUSE = (1 << 6), > DMA_PREP_CMD = (1 << 7), > + DMA_PREP_REPEAT = (1 << 8), > + DMA_PREP_LOAD_EOT = (1 << 9), > }; > > /** > @@ -980,6 +994,9 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_interleaved_dma( > { > if (!chan || !chan->device || !chan->device->device_prep_interleaved_dma) > return NULL; > + if (flags & DMA_PREP_REPEAT && > + !test_bit(DMA_REPEAT, chan->device->cap_mask.bits)) > + return NULL; > > return chan->device->device_prep_interleaved_dma(chan, xt, flags); > } > - Péter Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki