]>
Commit | Line | Data |
---|---|---|
c5d2b9f4 DW |
1 | Asynchronous Transfers/Transforms API |
2 | ||
3 | 1 INTRODUCTION | |
4 | ||
5 | 2 GENEALOGY | |
6 | ||
7 | 3 USAGE | |
8 | 3.1 General format of the API | |
9 | 3.2 Supported operations | |
10 | 3.3 Descriptor management | |
11 | 3.4 When does the operation execute? | |
12 | 3.5 When does the operation complete? | |
13 | 3.6 Constraints | |
14 | 3.7 Example | |
15 | ||
28405d8d | 16 | 4 DMAENGINE DRIVER DEVELOPER NOTES |
c5d2b9f4 | 17 | 4.1 Conformance points |
28405d8d | 18 | 4.2 "My application needs exclusive control of hardware channels" |
c5d2b9f4 DW |
19 | |
20 | 5 SOURCE | |
21 | ||
22 | --- | |
23 | ||
24 | 1 INTRODUCTION | |
25 | ||
26 | The async_tx API provides methods for describing a chain of asynchronous | |
27 | bulk memory transfers/transforms with support for inter-transactional | |
28 | dependencies. It is implemented as a dmaengine client that smooths over | |
29 | the details of different hardware offload engine implementations. Code | |
30 | that is written to the API can optimize for asynchronous operation and | |
31 | the API will fit the chain of operations to the available offload | |
32 | resources. | |
33 | ||
34 | 2 GENEALOGY | |
35 | ||
36 | The API was initially designed to offload the memory copy and | |
37 | xor-parity-calculations of the md-raid5 driver using the offload engines | |
38 | present in the Intel(R) Xscale series of I/O processors. It also built | |
39 | on the 'dmaengine' layer developed for offloading memory copies in the | |
40 | network stack using Intel(R) I/OAT engines. The following design | |
41 | features surfaced as a result: | |
42 | 1/ implicit synchronous path: users of the API do not need to know if | |
43 | the platform they are running on has offload capabilities. The | |
44 | operation will be offloaded when an engine is available and carried out | |
45 | in software otherwise. | |
46 | 2/ cross channel dependency chains: the API allows a chain of dependent | |
47 | operations to be submitted, like xor->copy->xor in the raid5 case. The | |
48 | API automatically handles cases where the transition from one operation | |
49 | to another implies a hardware channel switch. | |
50 | 3/ dmaengine extensions to support multiple clients and operation types | |
51 | beyond 'memcpy' | |
52 | ||
53 | 3 USAGE | |
54 | ||
55 | 3.1 General format of the API: | |
56 | struct dma_async_tx_descriptor * | |
57 | async_<operation>(<op specific parameters>, | |
58 | enum async_tx_flags flags, | |
59 | struct dma_async_tx_descriptor *dependency, | |
60 | dma_async_tx_callback callback_routine, | |
61 | void *callback_parameter); | |
62 | ||
63 | 3.2 Supported operations: | |
099f53cb DW |
64 | memcpy - memory copy between a source and a destination buffer |
65 | memset - fill a destination buffer with a byte value | |
66 | xor - xor a series of source buffers and write the result to a | |
67 | destination buffer | |
68 | xor_val - xor a series of source buffers and set a flag if the | |
69 | result is zero. The implementation attempts to prevent | |
70 | writes to memory | |
c5d2b9f4 DW |
71 | |
72 | 3.3 Descriptor management: | |
73 | The return value is non-NULL and points to a 'descriptor' when the operation | |
74 | has been queued to execute asynchronously. Descriptors are recycled | |
75 | resources, under control of the offload engine driver, to be reused as | |
76 | operations complete. When an application needs to submit a chain of | |
77 | operations it must guarantee that the descriptor is not automatically recycled | |
78 | before the dependency is submitted. This requires that all descriptors be | |
79 | acknowledged by the application before the offload engine driver is allowed to | |
80 | recycle (or free) the descriptor. A descriptor can be acked by one of the | |
81 | following methods: | |
82 | 1/ setting the ASYNC_TX_ACK flag if no child operations are to be submitted | |
83 | 2/ setting the ASYNC_TX_DEP_ACK flag to acknowledge the parent | |
84 | descriptor of a new operation. | |
85 | 3/ calling async_tx_ack() on the descriptor. | |
86 | ||
87 | 3.4 When does the operation execute? | |
88 | Operations do not immediately issue after return from the | |
89 | async_<operation> call. Offload engine drivers batch operations to | |
90 | improve performance by reducing the number of mmio cycles needed to | |
91 | manage the channel. Once a driver-specific threshold is met the driver | |
92 | automatically issues pending operations. An application can force this | |
93 | event by calling async_tx_issue_pending_all(). This operates on all | |
94 | channels since the application has no knowledge of channel to operation | |
95 | mapping. | |
96 | ||
97 | 3.5 When does the operation complete? | |
98 | There are two methods for an application to learn about the completion | |
99 | of an operation. | |
100 | 1/ Call dma_wait_for_async_tx(). This call causes the CPU to spin while | |
101 | it polls for the completion of the operation. It handles dependency | |
102 | chains and issuing pending operations. | |
103 | 2/ Specify a completion callback. The callback routine runs in tasklet | |
104 | context if the offload engine driver supports interrupts, or it is | |
105 | called in application context if the operation is carried out | |
106 | synchronously in software. The callback can be set in the call to | |
107 | async_<operation>, or when the application needs to submit a chain of | |
108 | unknown length it can use the async_trigger_callback() routine to set a | |
109 | completion interrupt/callback at the end of the chain. | |
110 | ||
111 | 3.6 Constraints: | |
112 | 1/ Calls to async_<operation> are not permitted in IRQ context. Other | |
113 | contexts are permitted provided constraint #2 is not violated. | |
114 | 2/ Completion callback routines cannot submit new operations. This | |
115 | results in recursion in the synchronous case and spin_locks being | |
116 | acquired twice in the asynchronous case. | |
117 | ||
118 | 3.7 Example: | |
119 | Perform a xor->copy->xor operation where each operation depends on the | |
120 | result from the previous operation: | |
121 | ||
122 | void complete_xor_copy_xor(void *param) | |
123 | { | |
124 | printk("complete\n"); | |
125 | } | |
126 | ||
127 | int run_xor_copy_xor(struct page **xor_srcs, | |
128 | int xor_src_cnt, | |
129 | struct page *xor_dest, | |
130 | size_t xor_len, | |
131 | struct page *copy_src, | |
132 | struct page *copy_dest, | |
133 | size_t copy_len) | |
134 | { | |
135 | struct dma_async_tx_descriptor *tx; | |
136 | ||
137 | tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len, | |
138 | ASYNC_TX_XOR_DROP_DST, NULL, NULL, NULL); | |
139 | tx = async_memcpy(copy_dest, copy_src, 0, 0, copy_len, | |
140 | ASYNC_TX_DEP_ACK, tx, NULL, NULL); | |
141 | tx = async_xor(xor_dest, xor_srcs, 0, xor_src_cnt, xor_len, | |
142 | ASYNC_TX_XOR_DROP_DST | ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, | |
143 | tx, complete_xor_copy_xor, NULL); | |
144 | ||
145 | async_tx_issue_pending_all(); | |
146 | } | |
147 | ||
148 | See include/linux/async_tx.h for more information on the flags. See the | |
149 | ops_run_* and ops_complete_* routines in drivers/md/raid5.c for more | |
150 | implementation examples. | |
151 | ||
152 | 4 DRIVER DEVELOPMENT NOTES | |
28405d8d | 153 | |
c5d2b9f4 DW |
154 | 4.1 Conformance points: |
155 | There are a few conformance points required in dmaengine drivers to | |
156 | accommodate assumptions made by applications using the async_tx API: | |
157 | 1/ Completion callbacks are expected to happen in tasklet context | |
158 | 2/ dma_async_tx_descriptor fields are never manipulated in IRQ context | |
159 | 3/ Use async_tx_run_dependencies() in the descriptor clean up path to | |
160 | handle submission of dependent operations | |
161 | ||
28405d8d DW |
162 | 4.2 "My application needs exclusive control of hardware channels" |
163 | Primarily this requirement arises from cases where a DMA engine driver | |
164 | is being used to support device-to-memory operations. A channel that is | |
165 | performing these operations cannot, for many platform specific reasons, | |
166 | be shared. For these cases the dma_request_channel() interface is | |
167 | provided. | |
168 | ||
169 | The interface is: | |
170 | struct dma_chan *dma_request_channel(dma_cap_mask_t mask, | |
171 | dma_filter_fn filter_fn, | |
172 | void *filter_param); | |
173 | ||
174 | Where dma_filter_fn is defined as: | |
175 | typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); | |
176 | ||
177 | When the optional 'filter_fn' parameter is set to NULL | |
178 | dma_request_channel simply returns the first channel that satisfies the | |
179 | capability mask. Otherwise, when the mask parameter is insufficient for | |
180 | specifying the necessary channel, the filter_fn routine can be used to | |
181 | disposition the available channels in the system. The filter_fn routine | |
182 | is called once for each free channel in the system. Upon seeing a | |
183 | suitable channel filter_fn returns DMA_ACK which flags that channel to | |
184 | be the return value from dma_request_channel. A channel allocated via | |
185 | this interface is exclusive to the caller, until dma_release_channel() | |
186 | is called. | |
187 | ||
188 | The DMA_PRIVATE capability flag is used to tag dma devices that should | |
189 | not be used by the general-purpose allocator. It can be set at | |
190 | initialization time if it is known that a channel will always be | |
191 | private. Alternatively, it is set when dma_request_channel() finds an | |
192 | unused "public" channel. | |
193 | ||
194 | A couple caveats to note when implementing a driver and consumer: | |
195 | 1/ Once a channel has been privately allocated it will no longer be | |
196 | considered by the general-purpose allocator even after a call to | |
197 | dma_release_channel(). | |
198 | 2/ Since capabilities are specified at the device level a dma_device | |
199 | with multiple channels will either have all channels public, or all | |
200 | channels private. | |
c5d2b9f4 DW |
201 | |
202 | 5 SOURCE | |
28405d8d DW |
203 | |
204 | include/linux/dmaengine.h: core header file for DMA drivers and api users | |
c5d2b9f4 DW |
205 | drivers/dma/dmaengine.c: offload engine channel management routines |
206 | drivers/dma/: location for offload engine drivers | |
207 | include/linux/async_tx.h: core header file for the async_tx api | |
208 | crypto/async_tx/async_tx.c: async_tx interface to dmaengine and common code | |
209 | crypto/async_tx/async_memcpy.c: copy offload | |
210 | crypto/async_tx/async_memset.c: memory fill offload | |
211 | crypto/async_tx/async_xor.c: xor and xor zero sum offload |