12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- DMA Engine API Guide
- ====================
- Vinod Koul <vinod dot koul at intel.com>
- NOTE: For DMA Engine usage in async_tx please see:
- Documentation/crypto/async-tx-api.txt
- Below is a guide to device driver writers on how to use the Slave-DMA API of the
- DMA Engine. This is applicable only for slave DMA usage only.
- The slave DMA usage consists of following steps
- 1. Allocate a DMA slave channel
- 2. Set slave and controller specific parameters
- 3. Get a descriptor for transaction
- 4. Submit the transaction and wait for callback notification
- 1. Allocate a DMA slave channel
- Channel allocation is slightly different in the slave DMA context, client
- drivers typically need a channel from a particular DMA controller only and even
- in some cases a specific channel is desired. To request a channel
- dma_request_channel() API is used.
- Interface:
- struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
- dma_filter_fn filter_fn,
- void *filter_param);
- where dma_filter_fn is defined as:
- typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
- When the optional 'filter_fn' parameter is set to NULL dma_request_channel
- simply returns the first channel that satisfies the capability mask. Otherwise,
- when the mask parameter is insufficient for specifying the necessary channel,
- the filter_fn routine can be used to disposition the available channels in the
- system. The filter_fn routine is called once for each free channel in the
- system. Upon seeing a suitable channel filter_fn returns DMA_ACK which flags
- that channel to be the return value from dma_request_channel. A channel
- allocated via this interface is exclusive to the caller, until
- dma_release_channel() is called.
- 2. Set slave and controller specific parameters
- Next step is always to pass some specific information to the DMA driver. Most of
- the generic information which a slave DMA can use is in struct dma_slave_config.
- It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA
- burst lengths etc. If some DMA controllers have more parameters to be sent then
- they should try to embed struct dma_slave_config in their controller specific
- structure. That gives flexibility to client to pass more parameters, if
- required.
- Interface:
- int dmaengine_slave_config(struct dma_chan *chan,
- struct dma_slave_config *config)
- 3. Get a descriptor for transaction
- For slave usage the various modes of slave transfers supported by the
- DMA-engine are:
- slave_sg - DMA a list of scatter gather buffers from/to a peripheral
- dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the
- operation is explicitly stopped.
- The non NULL return of this transfer API represents a "descriptor" for the given
- transaction.
- Interface:
- struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)(
- struct dma_chan *chan,
- struct scatterlist *dst_sg, unsigned int dst_nents,
- struct scatterlist *src_sg, unsigned int src_nents,
- unsigned long flags);
- struct dma_async_tx_descriptor *(*chan->device->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);
- 4. Submit the transaction and wait for callback notification
- To schedule the transaction to be scheduled by dma device, the "descriptor"
- returned in above (3) needs to be submitted.
- To tell the dma driver that a transaction is ready to be serviced, the
- descriptor->submit() callback needs to be invoked. This chains the descriptor to
- the pending queue.
- The transactions in the pending queue can be activated by calling the
- issue_pending API. If channel is idle then the first transaction in queue is
- started and subsequent ones queued up.
- On completion of the DMA operation the next in queue is submitted and a tasklet
- triggered. The tasklet would then call the client driver completion callback
- routine for notification, if set.
- Interface:
- void dma_async_issue_pending(struct dma_chan *chan);
- ==============================================================================
- Additional usage notes for dma driver writers
- 1/ Although DMA engine specifies that completion callback routines cannot submit
- any new operations, but typically for slave DMA subsequent transaction may not
- be available for submit prior to callback routine being called. This requirement
- is not a requirement for DMA-slave devices. But they should take care to drop
- the spin-lock they might be holding before calling the callback routine
|