lkml.org 
[lkml]   [2011]   [Jun]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [RFC] dmaengine: add new api for preparing simple slave transfer
From
Date
On Thu, 2011-06-09 at 17:32 +0100, Russell King - ARM Linux wrote:
> On Thu, Jun 09, 2011 at 09:31:56PM +0530, Raju, Sundaram wrote:
> > Here it is, with proper line wrapping;
>
> Thanks. This is much easier to reply to.
>
> > I believe that even though the dmaengine framework addresses and
> > supports most of the required use cases of a client driver to a DMA
> > controller, some extensions are required in it to make it still more
> > generic.
> >
> > Current framework contains two APIs to prepare for slave transfers:
> >
> > struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
> > struct dma_chan *chan, struct scatterlist *sgl,
> > unsigned int sg_len, enum dma_data_direction direction,
> > unsigned long flags);
> >
> > struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)(
> > struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
> > size_t period_len, enum dma_data_direction direction);
> >
> > and one control API.
> > int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
> > unsigned long arg);
> >
> > A simple single buffer transfer (i.e. non sg transfer) can be done only
> > as a trivial case of the device_prep_slave_sg API. The client driver is
> > expected to prepare a sg list and provide to the dmaengine API for that
> > single buffer also.
>
> We can avoid preparing a sg list in every driver which wants this by
> having dmaengine.h provide a helper for this case:
>
> static inline dma_async_tx_descriptor *dmaengine_prep_slave_single(
> struct dma_chan *chan, void *buf, size_t len,
> enum dma_data_direction dir, unsigned long flags)
> {
> struct scatterlist sg;
>
> sg_init_one(&sg, buf, len);
>
> return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags);
> }
That sounds good...

>
> I think also providing dmaengine_prep_slave_sg() and
> dmaengine_prep_dma_cyclic() as wrappers to hide the chan->device->blah
> bit would also be beneficial (and helps keep that detail out of the
> users of DMA engine.)
>
> > In a slave transfer, the client has to define all the buffer related
> > attributes and the peripheral related attributes.
>
> I'd argue that it is incorrect to have drivers specify the buffer
> related attributes - that makes the API unnecessarily complicated
> to use, requiring two calls (one to configure the channel, and one
> to prepare the transfer) each time it needs to be used.
>
> Not only that but the memory side of the transfer should be no business
> of the driver - the driver itself should only specify the attributes
> for the device being driven. The attributes for the memory side of the
> transfer should be a property of the DMA engine itself.
>
> I would like to see in the long term the dma_slave_config structure
> lose its 'direction' argument, and the rest of the parameters used to
> define the device side parameters only.
I am not sure why direction flag is required and can be done away with.
Both sg and cyclic API have a direction parameter and that should be
used. A channel can be used in any direction client wishes to.
>
> This will allow the channel to be configured once when its requested,
> and then the prepare call can configure the direction as required.
>
> > Now coming to the buffer related attributes, sg list is a nice way to
> > represent a disjoint buffer; all the offload engines in drivers/dma
> > create a descriptor for each of the contiguous chunk in the sg list
> > buffer and pass it to the controller.
>
> The sg list is the standard Linux way to describe scattered buffers.
>
> > But many a times a client may want to transfer from a single buffer to
> > the peripheral and most of the DMA controllers have the capability to
> > transfer data in chunks/frames directly at a stretch.
>
> So far, I've only seen DMA controllers which operate on a linked list of
> source, destination, length, attributes, and next entry pointer.
>
> > All the attributes of a buffer, which are required for the transfer
> > can be programmed in single descriptor and submitted to the
> > DMA controller.
>
> I'm not sure that this is useful - in order to make use of the data, the
> data would have to be copied in between the descriptors - and doesn't that
> rather negate the point of DMA if you have to memcpy() the data around?
>
> Isn't it far more efficient to have DMA place the data exactly where it's
> required in memory right from the start without any memcpy() operations?
>
> Can you explain where and how you would use something like this:
>
> > -------------------------------------------------------------------
> > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame 0
> > -------------------------------------------------------------------
> > | Inter Frame Gap |
> > -------------------------------------------------------------------
> > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame 1
> > -------------------------------------------------------------------
> > | Inter Frame Gap |
> > -------------------------------------------------------------------
> > | ........ |
> > -------------------------------------------------------------------
> > | Inter Frame Gap |
> > -------------------------------------------------------------------
> > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame m
> > -------------------------------------------------------------------
>
> Can you also explain what a chunk contains, what a frame contains,
> how they're different and how they're processed? Where does the
> data to be transferred to the device live?
>
> Also, bear in mind that in Linux, we try hard to avoid allocating
> buffers larger than one page at a time - as soon as we get to multiple
> contiguous page buffers, allocations can start failing because of
> memory fragmentation. This is why we much prefer scatterlists over
> single contiguous buffers for DMA.


--
~Vinod



\
 
 \ /
  Last update: 2011-06-10 08:51    [from the cache]
©2003-2011 Jasper Spaans