| DMAengine controller documentation | |
| ================================== | |
| Hardware Introduction | |
| +++++++++++++++++++++ | |
| Most of the Slave DMA controllers have the same general principles of | |
| operations. | |
| They have a given number of channels to use for the DMA transfers, and | |
| a given number of requests lines. | |
| Requests and channels are pretty much orthogonal. Channels can be used | |
| to serve several to any requests. To simplify, channels are the | |
| entities that will be doing the copy, and requests what endpoints are | |
| involved. | |
| The request lines actually correspond to physical lines going from the | |
| DMA-eligible devices to the controller itself. Whenever the device | |
| will want to start a transfer, it will assert a DMA request (DRQ) by | |
| asserting that request line. | |
| A very simple DMA controller would only take into account a single | |
| parameter: the transfer size. At each clock cycle, it would transfer a | |
| byte of data from one buffer to another, until the transfer size has | |
| been reached. | |
| That wouldn't work well in the real world, since slave devices might | |
| require a specific number of bits to be transferred in a single | |
| cycle. For example, we may want to transfer as much data as the | |
| physical bus allows to maximize performances when doing a simple | |
| memory copy operation, but our audio device could have a narrower FIFO | |
| that requires data to be written exactly 16 or 24 bits at a time. This | |
| is why most if not all of the DMA controllers can adjust this, using a | |
| parameter called the transfer width. | |
| Moreover, some DMA controllers, whenever the RAM is used as a source | |
| or destination, can group the reads or writes in memory into a buffer, | |
| so instead of having a lot of small memory accesses, which is not | |
| really efficient, you'll get several bigger transfers. This is done | |
| using a parameter called the burst size, that defines how many single | |
| reads/writes it's allowed to do without the controller splitting the | |
| transfer into smaller sub-transfers. | |
| Our theoretical DMA controller would then only be able to do transfers | |
| that involve a single contiguous block of data. However, some of the | |
| transfers we usually have are not, and want to copy data from | |
| non-contiguous buffers to a contiguous buffer, which is called | |
| scatter-gather. | |
| DMAEngine, at least for mem2dev transfers, require support for | |
| scatter-gather. So we're left with two cases here: either we have a | |
| quite simple DMA controller that doesn't support it, and we'll have to | |
| implement it in software, or we have a more advanced DMA controller, | |
| that implements in hardware scatter-gather. | |
| The latter are usually programmed using a collection of chunks to | |
| transfer, and whenever the transfer is started, the controller will go | |
| over that collection, doing whatever we programmed there. | |
| This collection is usually either a table or a linked list. You will | |
| then push either the address of the table and its number of elements, | |
| or the first item of the list to one channel of the DMA controller, | |
| and whenever a DRQ will be asserted, it will go through the collection | |
| to know where to fetch the data from. | |
| Either way, the format of this collection is completely dependent on | |
| your hardware. Each DMA controller will require a different structure, | |
| but all of them will require, for every chunk, at least the source and | |
| destination addresses, whether it should increment these addresses or | |
| not and the three parameters we saw earlier: the burst size, the | |
| transfer width and the transfer size. | |
| The one last thing is that usually, slave devices won't issue DRQ by | |
| default, and you have to enable this in your slave device driver first | |
| whenever you're willing to use DMA. | |
| These were just the general memory-to-memory (also called mem2mem) or | |
| memory-to-device (mem2dev) kind of transfers. Most devices often | |
| support other kind of transfers or memory operations that dmaengine | |
| support and will be detailed later in this document. | |
| DMA Support in Linux | |
| ++++++++++++++++++++ | |
| Historically, DMA controller drivers have been implemented using the | |
| async TX API, to offload operations such as memory copy, XOR, | |
| cryptography, etc., basically any memory to memory operation. | |
| Over time, the need for memory to device transfers arose, and | |
| dmaengine was extended. Nowadays, the async TX API is written as a | |
| layer on top of dmaengine, and acts as a client. Still, dmaengine | |
| accommodates that API in some cases, and made some design choices to | |
| ensure that it stayed compatible. | |
| For more information on the Async TX API, please look the relevant | |
| documentation file in Documentation/crypto/async-tx-api.txt. | |
| DMAEngine Registration | |
| ++++++++++++++++++++++ | |
| struct dma_device Initialization | |
| -------------------------------- | |
| Just like any other kernel framework, the whole DMAEngine registration | |
| relies on the driver filling a structure and registering against the | |
| framework. In our case, that structure is dma_device. | |
| The first thing you need to do in your driver is to allocate this | |
| structure. Any of the usual memory allocators will do, but you'll also | |
| need to initialize a few fields in there: | |
| * channels: should be initialized as a list using the | |
| INIT_LIST_HEAD macro for example | |
| * src_addr_widths: | |
| - should contain a bitmask of the supported source transfer width | |
| * dst_addr_widths: | |
| - should contain a bitmask of the supported destination transfer | |
| width | |
| * directions: | |
| - should contain a bitmask of the supported slave directions | |
| (i.e. excluding mem2mem transfers) | |
| * residue_granularity: | |
| - Granularity of the transfer residue reported to dma_set_residue. | |
| - This can be either: | |
| + Descriptor | |
| -> Your device doesn't support any kind of residue | |
| reporting. The framework will only know that a particular | |
| transaction descriptor is done. | |
| + Segment | |
| -> Your device is able to report which chunks have been | |
| transferred | |
| + Burst | |
| -> Your device is able to report which burst have been | |
| transferred | |
| * dev: should hold the pointer to the struct device associated | |
| to your current driver instance. | |
| Supported transaction types | |
| --------------------------- | |
| The next thing you need is to set which transaction types your device | |
| (and driver) supports. | |
| Our dma_device structure has a field called cap_mask that holds the | |
| various types of transaction supported, and you need to modify this | |
| mask using the dma_cap_set function, with various flags depending on | |
| transaction types you support as an argument. | |
| All those capabilities are defined in the dma_transaction_type enum, | |
| in include/linux/dmaengine.h | |
| Currently, the types available are: | |
| * DMA_MEMCPY | |
| - The device is able to do memory to memory copies | |
| * DMA_XOR | |
| - The device is able to perform XOR operations on memory areas | |
| - Used to accelerate XOR intensive tasks, such as RAID5 | |
| * DMA_XOR_VAL | |
| - The device is able to perform parity check using the XOR | |
| algorithm against a memory buffer. | |
| * DMA_PQ | |
| - The device is able to perform RAID6 P+Q computations, P being a | |
| simple XOR, and Q being a Reed-Solomon algorithm. | |
| * DMA_PQ_VAL | |
| - The device is able to perform parity check using RAID6 P+Q | |
| algorithm against a memory buffer. | |
| * DMA_INTERRUPT | |
| - The device is able to trigger a dummy transfer that will | |
| generate periodic interrupts | |
| - Used by the client drivers to register a callback that will be | |
| called on a regular basis through the DMA controller interrupt | |
| * DMA_PRIVATE | |
| - The devices only supports slave transfers, and as such isn't | |
| available for async transfers. | |
| * DMA_ASYNC_TX | |
| - Must not be set by the device, and will be set by the framework | |
| if needed | |
| - /* TODO: What is it about? */ | |
| * DMA_SLAVE | |
| - The device can handle device to memory transfers, including | |
| scatter-gather transfers. | |
| - While in the mem2mem case we were having two distinct types to | |
| deal with a single chunk to copy or a collection of them, here, | |
| we just have a single transaction type that is supposed to | |
| handle both. | |
| - If you want to transfer a single contiguous memory buffer, | |
| simply build a scatter list with only one item. | |
| * DMA_CYCLIC | |
| - The device can handle cyclic transfers. | |
| - A cyclic transfer is a transfer where the chunk collection will | |
| loop over itself, with the last item pointing to the first. | |
| - It's usually used for audio transfers, where you want to operate | |
| on a single ring buffer that you will fill with your audio data. | |
| * DMA_INTERLEAVE | |
| - The device supports interleaved transfer. | |
| - These transfers can transfer data from a non-contiguous buffer | |
| to a non-contiguous buffer, opposed to DMA_SLAVE that can | |
| transfer data from a non-contiguous data set to a continuous | |
| destination buffer. | |
| - It's usually used for 2d content transfers, in which case you | |
| want to transfer a portion of uncompressed data directly to the | |
| display to print it | |
| These various types will also affect how the source and destination | |
| addresses change over time. | |
| Addresses pointing to RAM are typically incremented (or decremented) | |
| after each transfer. In case of a ring buffer, they may loop | |
| (DMA_CYCLIC). Addresses pointing to a device's register (e.g. a FIFO) | |
| are typically fixed. | |
| Device operations | |
| ----------------- | |
| Our dma_device structure also requires a few function pointers in | |
| order to implement the actual logic, now that we described what | |
| operations we were able to perform. | |
| The functions that we have to fill in there, and hence have to | |
| implement, obviously depend on the transaction types you reported as | |
| supported. | |
| * device_alloc_chan_resources | |
| * device_free_chan_resources | |
| - These functions will be called whenever a driver will call | |
| dma_request_channel or dma_release_channel for the first/last | |
| time on the channel associated to that driver. | |
| - They are in charge of allocating/freeing all the needed | |
| resources in order for that channel to be useful for your | |
| driver. | |
| - These functions can sleep. | |
| * device_prep_dma_* | |
| - These functions are matching the capabilities you registered | |
| previously. | |
| - These functions all take the buffer or the scatterlist relevant | |
| for the transfer being prepared, and should create a hardware | |
| descriptor or a list of hardware descriptors from it | |
| - These functions can be called from an interrupt context | |
| - Any allocation you might do should be using the GFP_NOWAIT | |
| flag, in order not to potentially sleep, but without depleting | |
| the emergency pool either. | |
| - Drivers should try to pre-allocate any memory they might need | |
| during the transfer setup at probe time to avoid putting to | |
| much pressure on the nowait allocator. | |
| - It should return a unique instance of the | |
| dma_async_tx_descriptor structure, that further represents this | |
| particular transfer. | |
| - This structure can be initialized using the function | |
| dma_async_tx_descriptor_init. | |
| - You'll also need to set two fields in this structure: | |
| + flags: | |
| TODO: Can it be modified by the driver itself, or | |
| should it be always the flags passed in the arguments | |
| + tx_submit: A pointer to a function you have to implement, | |
| that is supposed to push the current | |
| transaction descriptor to a pending queue, waiting | |
| for issue_pending to be called. | |
| - In this structure the function pointer callback_result can be | |
| initialized in order for the submitter to be notified that a | |
| transaction has completed. In the earlier code the function pointer | |
| callback has been used. However it does not provide any status to the | |
| transaction and will be deprecated. The result structure defined as | |
| dmaengine_result that is passed in to callback_result has two fields: | |
| + result: This provides the transfer result defined by | |
| dmaengine_tx_result. Either success or some error | |
| condition. | |
| + residue: Provides the residue bytes of the transfer for those that | |
| support residue. | |
| * device_issue_pending | |
| - Takes the first transaction descriptor in the pending queue, | |
| and starts the transfer. Whenever that transfer is done, it | |
| should move to the next transaction in the list. | |
| - This function can be called in an interrupt context | |
| * device_tx_status | |
| - Should report the bytes left to go over on the given channel | |
| - Should only care about the transaction descriptor passed as | |
| argument, not the currently active one on a given channel | |
| - The tx_state argument might be NULL | |
| - Should use dma_set_residue to report it | |
| - In the case of a cyclic transfer, it should only take into | |
| account the current period. | |
| - This function can be called in an interrupt context. | |
| * device_config | |
| - Reconfigures the channel with the configuration given as | |
| argument | |
| - This command should NOT perform synchronously, or on any | |
| currently queued transfers, but only on subsequent ones | |
| - In this case, the function will receive a dma_slave_config | |
| structure pointer as an argument, that will detail which | |
| configuration to use. | |
| - Even though that structure contains a direction field, this | |
| field is deprecated in favor of the direction argument given to | |
| the prep_* functions | |
| - This call is mandatory for slave operations only. This should NOT be | |
| set or expected to be set for memcpy operations. | |
| If a driver support both, it should use this call for slave | |
| operations only and not for memcpy ones. | |
| * device_pause | |
| - Pauses a transfer on the channel | |
| - This command should operate synchronously on the channel, | |
| pausing right away the work of the given channel | |
| * device_resume | |
| - Resumes a transfer on the channel | |
| - This command should operate synchronously on the channel, | |
| resuming right away the work of the given channel | |
| * device_terminate_all | |
| - Aborts all the pending and ongoing transfers on the channel | |
| - For aborted transfers the complete callback should not be called | |
| - Can be called from atomic context or from within a complete | |
| callback of a descriptor. Must not sleep. Drivers must be able | |
| to handle this correctly. | |
| - Termination may be asynchronous. The driver does not have to | |
| wait until the currently active transfer has completely stopped. | |
| See device_synchronize. | |
| * device_synchronize | |
| - Must synchronize the termination of a channel to the current | |
| context. | |
| - Must make sure that memory for previously submitted | |
| descriptors is no longer accessed by the DMA controller. | |
| - Must make sure that all complete callbacks for previously | |
| submitted descriptors have finished running and none are | |
| scheduled to run. | |
| - May sleep. | |
| Misc notes (stuff that should be documented, but don't really know | |
| where to put them) | |
| ------------------------------------------------------------------ | |
| * dma_run_dependencies | |
| - Should be called at the end of an async TX transfer, and can be | |
| ignored in the slave transfers case. | |
| - Makes sure that dependent operations are run before marking it | |
| as complete. | |
| * dma_cookie_t | |
| - it's a DMA transaction ID that will increment over time. | |
| - Not really relevant any more since the introduction of virt-dma | |
| that abstracts it away. | |
| * DMA_CTRL_ACK | |
| - If clear, the descriptor cannot be reused by provider until the | |
| client acknowledges receipt, i.e. has has a chance to establish any | |
| dependency chains | |
| - This can be acked by invoking async_tx_ack() | |
| - If set, does not mean descriptor can be reused | |
| * DMA_CTRL_REUSE | |
| - If set, the descriptor can be reused after being completed. It should | |
| not be freed by provider if this flag is set. | |
| - The descriptor should be prepared for reuse by invoking | |
| dmaengine_desc_set_reuse() which will set DMA_CTRL_REUSE. | |
| - dmaengine_desc_set_reuse() will succeed only when channel support | |
| reusable descriptor as exhibited by capabilities | |
| - As a consequence, if a device driver wants to skip the dma_map_sg() and | |
| dma_unmap_sg() in between 2 transfers, because the DMA'd data wasn't used, | |
| it can resubmit the transfer right after its completion. | |
| - Descriptor can be freed in few ways | |
| - Clearing DMA_CTRL_REUSE by invoking dmaengine_desc_clear_reuse() | |
| and submitting for last txn | |
| - Explicitly invoking dmaengine_desc_free(), this can succeed only | |
| when DMA_CTRL_REUSE is already set | |
| - Terminating the channel | |
| * DMA_PREP_CMD | |
| - If set, the client driver tells DMA controller that passed data in DMA | |
| API is command data. | |
| - Interpretation of command data is DMA controller specific. It can be | |
| used for issuing commands to other peripherals/register reads/register | |
| writes for which the descriptor should be in different format from | |
| normal data descriptors. | |
| General Design Notes | |
| -------------------- | |
| Most of the DMAEngine drivers you'll see are based on a similar design | |
| that handles the end of transfer interrupts in the handler, but defer | |
| most work to a tasklet, including the start of a new transfer whenever | |
| the previous transfer ended. | |
| This is a rather inefficient design though, because the inter-transfer | |
| latency will be not only the interrupt latency, but also the | |
| scheduling latency of the tasklet, which will leave the channel idle | |
| in between, which will slow down the global transfer rate. | |
| You should avoid this kind of practice, and instead of electing a new | |
| transfer in your tasklet, move that part to the interrupt handler in | |
| order to have a shorter idle window (that we can't really avoid | |
| anyway). | |
| Glossary | |
| -------- | |
| Burst: A number of consecutive read or write operations | |
| that can be queued to buffers before being flushed to | |
| memory. | |
| Chunk: A contiguous collection of bursts | |
| Transfer: A collection of chunks (be it contiguous or not) |