diff options
Diffstat (limited to 'include/linux/dmaengine.h')
-rw-r--r-- | include/linux/dmaengine.h | 179 |
1 files changed, 161 insertions, 18 deletions
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index ffefba81c818..2b9f2ac7ed60 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h | |||
@@ -48,19 +48,20 @@ enum dma_status { | |||
48 | 48 | ||
49 | /** | 49 | /** |
50 | * enum dma_transaction_type - DMA transaction types/indexes | 50 | * enum dma_transaction_type - DMA transaction types/indexes |
51 | * | ||
52 | * Note: The DMA_ASYNC_TX capability is not to be set by drivers. It is | ||
53 | * automatically set as dma devices are registered. | ||
51 | */ | 54 | */ |
52 | enum dma_transaction_type { | 55 | enum dma_transaction_type { |
53 | DMA_MEMCPY, | 56 | DMA_MEMCPY, |
54 | DMA_XOR, | 57 | DMA_XOR, |
55 | DMA_PQ_XOR, | 58 | DMA_PQ, |
56 | DMA_DUAL_XOR, | 59 | DMA_XOR_VAL, |
57 | DMA_PQ_UPDATE, | 60 | DMA_PQ_VAL, |
58 | DMA_ZERO_SUM, | ||
59 | DMA_PQ_ZERO_SUM, | ||
60 | DMA_MEMSET, | 61 | DMA_MEMSET, |
61 | DMA_MEMCPY_CRC32C, | ||
62 | DMA_INTERRUPT, | 62 | DMA_INTERRUPT, |
63 | DMA_PRIVATE, | 63 | DMA_PRIVATE, |
64 | DMA_ASYNC_TX, | ||
64 | DMA_SLAVE, | 65 | DMA_SLAVE, |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -70,18 +71,25 @@ enum dma_transaction_type { | |||
70 | 71 | ||
71 | /** | 72 | /** |
72 | * enum dma_ctrl_flags - DMA flags to augment operation preparation, | 73 | * enum dma_ctrl_flags - DMA flags to augment operation preparation, |
73 | * control completion, and communicate status. | 74 | * control completion, and communicate status. |
74 | * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of | 75 | * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of |
75 | * this transaction | 76 | * this transaction |
76 | * @DMA_CTRL_ACK - the descriptor cannot be reused until the client | 77 | * @DMA_CTRL_ACK - the descriptor cannot be reused until the client |
77 | * acknowledges receipt, i.e. has has a chance to establish any | 78 | * acknowledges receipt, i.e. has has a chance to establish any dependency |
78 | * dependency chains | 79 | * chains |
79 | * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s) | 80 | * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s) |
80 | * @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s) | 81 | * @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s) |
81 | * @DMA_COMPL_SRC_UNMAP_SINGLE - set to do the source dma-unmapping as single | 82 | * @DMA_COMPL_SRC_UNMAP_SINGLE - set to do the source dma-unmapping as single |
82 | * (if not set, do the source dma-unmapping as page) | 83 | * (if not set, do the source dma-unmapping as page) |
83 | * @DMA_COMPL_DEST_UNMAP_SINGLE - set to do the destination dma-unmapping as single | 84 | * @DMA_COMPL_DEST_UNMAP_SINGLE - set to do the destination dma-unmapping as single |
84 | * (if not set, do the destination dma-unmapping as page) | 85 | * (if not set, do the destination dma-unmapping as page) |
86 | * @DMA_PREP_PQ_DISABLE_P - prevent generation of P while generating Q | ||
87 | * @DMA_PREP_PQ_DISABLE_Q - prevent generation of Q while generating P | ||
88 | * @DMA_PREP_CONTINUE - indicate to a driver that it is reusing buffers as | ||
89 | * sources that were the result of a previous operation, in the case of a PQ | ||
90 | * operation it continues the calculation with new sources | ||
91 | * @DMA_PREP_FENCE - tell the driver that subsequent operations depend | ||
92 | * on the result of this operation | ||
85 | */ | 93 | */ |
86 | enum dma_ctrl_flags { | 94 | enum dma_ctrl_flags { |
87 | DMA_PREP_INTERRUPT = (1 << 0), | 95 | DMA_PREP_INTERRUPT = (1 << 0), |
@@ -90,9 +98,32 @@ enum dma_ctrl_flags { | |||
90 | DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3), | 98 | DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3), |
91 | DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4), | 99 | DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4), |
92 | DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5), | 100 | DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5), |
101 | DMA_PREP_PQ_DISABLE_P = (1 << 6), | ||
102 | DMA_PREP_PQ_DISABLE_Q = (1 << 7), | ||
103 | DMA_PREP_CONTINUE = (1 << 8), | ||
104 | DMA_PREP_FENCE = (1 << 9), | ||
93 | }; | 105 | }; |
94 | 106 | ||
95 | /** | 107 | /** |
108 | * enum sum_check_bits - bit position of pq_check_flags | ||
109 | */ | ||
110 | enum sum_check_bits { | ||
111 | SUM_CHECK_P = 0, | ||
112 | SUM_CHECK_Q = 1, | ||
113 | }; | ||
114 | |||
115 | /** | ||
116 | * enum pq_check_flags - result of async_{xor,pq}_zero_sum operations | ||
117 | * @SUM_CHECK_P_RESULT - 1 if xor zero sum error, 0 otherwise | ||
118 | * @SUM_CHECK_Q_RESULT - 1 if reed-solomon zero sum error, 0 otherwise | ||
119 | */ | ||
120 | enum sum_check_flags { | ||
121 | SUM_CHECK_P_RESULT = (1 << SUM_CHECK_P), | ||
122 | SUM_CHECK_Q_RESULT = (1 << SUM_CHECK_Q), | ||
123 | }; | ||
124 | |||
125 | |||
126 | /** | ||
96 | * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t. | 127 | * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t. |
97 | * See linux/cpumask.h | 128 | * See linux/cpumask.h |
98 | */ | 129 | */ |
@@ -180,8 +211,6 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param); | |||
180 | * @flags: flags to augment operation preparation, control completion, and | 211 | * @flags: flags to augment operation preparation, control completion, and |
181 | * communicate status | 212 | * communicate status |
182 | * @phys: physical address of the descriptor | 213 | * @phys: physical address of the descriptor |
183 | * @tx_list: driver common field for operations that require multiple | ||
184 | * descriptors | ||
185 | * @chan: target channel for this operation | 214 | * @chan: target channel for this operation |
186 | * @tx_submit: set the prepared descriptor(s) to be executed by the engine | 215 | * @tx_submit: set the prepared descriptor(s) to be executed by the engine |
187 | * @callback: routine to call after this operation is complete | 216 | * @callback: routine to call after this operation is complete |
@@ -195,7 +224,6 @@ struct dma_async_tx_descriptor { | |||
195 | dma_cookie_t cookie; | 224 | dma_cookie_t cookie; |
196 | enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */ | 225 | enum dma_ctrl_flags flags; /* not a 'long' to pack with cookie */ |
197 | dma_addr_t phys; | 226 | dma_addr_t phys; |
198 | struct list_head tx_list; | ||
199 | struct dma_chan *chan; | 227 | struct dma_chan *chan; |
200 | dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); | 228 | dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx); |
201 | dma_async_tx_callback callback; | 229 | dma_async_tx_callback callback; |
@@ -213,6 +241,11 @@ struct dma_async_tx_descriptor { | |||
213 | * @global_node: list_head for global dma_device_list | 241 | * @global_node: list_head for global dma_device_list |
214 | * @cap_mask: one or more dma_capability flags | 242 | * @cap_mask: one or more dma_capability flags |
215 | * @max_xor: maximum number of xor sources, 0 if no capability | 243 | * @max_xor: maximum number of xor sources, 0 if no capability |
244 | * @max_pq: maximum number of PQ sources and PQ-continue capability | ||
245 | * @copy_align: alignment shift for memcpy operations | ||
246 | * @xor_align: alignment shift for xor operations | ||
247 | * @pq_align: alignment shift for pq operations | ||
248 | * @fill_align: alignment shift for memset operations | ||
216 | * @dev_id: unique device ID | 249 | * @dev_id: unique device ID |
217 | * @dev: struct device reference for dma mapping api | 250 | * @dev: struct device reference for dma mapping api |
218 | * @device_alloc_chan_resources: allocate resources and return the | 251 | * @device_alloc_chan_resources: allocate resources and return the |
@@ -220,7 +253,9 @@ struct dma_async_tx_descriptor { | |||
220 | * @device_free_chan_resources: release DMA channel's resources | 253 | * @device_free_chan_resources: release DMA channel's resources |
221 | * @device_prep_dma_memcpy: prepares a memcpy operation | 254 | * @device_prep_dma_memcpy: prepares a memcpy operation |
222 | * @device_prep_dma_xor: prepares a xor operation | 255 | * @device_prep_dma_xor: prepares a xor operation |
223 | * @device_prep_dma_zero_sum: prepares a zero_sum operation | 256 | * @device_prep_dma_xor_val: prepares a xor validation operation |
257 | * @device_prep_dma_pq: prepares a pq operation | ||
258 | * @device_prep_dma_pq_val: prepares a pqzero_sum operation | ||
224 | * @device_prep_dma_memset: prepares a memset operation | 259 | * @device_prep_dma_memset: prepares a memset operation |
225 | * @device_prep_dma_interrupt: prepares an end of chain interrupt operation | 260 | * @device_prep_dma_interrupt: prepares an end of chain interrupt operation |
226 | * @device_prep_slave_sg: prepares a slave dma operation | 261 | * @device_prep_slave_sg: prepares a slave dma operation |
@@ -235,7 +270,13 @@ struct dma_device { | |||
235 | struct list_head channels; | 270 | struct list_head channels; |
236 | struct list_head global_node; | 271 | struct list_head global_node; |
237 | dma_cap_mask_t cap_mask; | 272 | dma_cap_mask_t cap_mask; |
238 | int max_xor; | 273 | unsigned short max_xor; |
274 | unsigned short max_pq; | ||
275 | u8 copy_align; | ||
276 | u8 xor_align; | ||
277 | u8 pq_align; | ||
278 | u8 fill_align; | ||
279 | #define DMA_HAS_PQ_CONTINUE (1 << 15) | ||
239 | 280 | ||
240 | int dev_id; | 281 | int dev_id; |
241 | struct device *dev; | 282 | struct device *dev; |
@@ -249,9 +290,17 @@ struct dma_device { | |||
249 | struct dma_async_tx_descriptor *(*device_prep_dma_xor)( | 290 | struct dma_async_tx_descriptor *(*device_prep_dma_xor)( |
250 | struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, | 291 | struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, |
251 | unsigned int src_cnt, size_t len, unsigned long flags); | 292 | unsigned int src_cnt, size_t len, unsigned long flags); |
252 | struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)( | 293 | struct dma_async_tx_descriptor *(*device_prep_dma_xor_val)( |
253 | struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, | 294 | struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt, |
254 | size_t len, u32 *result, unsigned long flags); | 295 | size_t len, enum sum_check_flags *result, unsigned long flags); |
296 | struct dma_async_tx_descriptor *(*device_prep_dma_pq)( | ||
297 | struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src, | ||
298 | unsigned int src_cnt, const unsigned char *scf, | ||
299 | size_t len, unsigned long flags); | ||
300 | struct dma_async_tx_descriptor *(*device_prep_dma_pq_val)( | ||
301 | struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src, | ||
302 | unsigned int src_cnt, const unsigned char *scf, size_t len, | ||
303 | enum sum_check_flags *pqres, unsigned long flags); | ||
255 | struct dma_async_tx_descriptor *(*device_prep_dma_memset)( | 304 | struct dma_async_tx_descriptor *(*device_prep_dma_memset)( |
256 | struct dma_chan *chan, dma_addr_t dest, int value, size_t len, | 305 | struct dma_chan *chan, dma_addr_t dest, int value, size_t len, |
257 | unsigned long flags); | 306 | unsigned long flags); |
@@ -270,6 +319,96 @@ struct dma_device { | |||
270 | void (*device_issue_pending)(struct dma_chan *chan); | 319 | void (*device_issue_pending)(struct dma_chan *chan); |
271 | }; | 320 | }; |
272 | 321 | ||
322 | static inline bool dmaengine_check_align(u8 align, size_t off1, size_t off2, size_t len) | ||
323 | { | ||
324 | size_t mask; | ||
325 | |||
326 | if (!align) | ||
327 | return true; | ||
328 | mask = (1 << align) - 1; | ||
329 | if (mask & (off1 | off2 | len)) | ||
330 | return false; | ||
331 | return true; | ||
332 | } | ||
333 | |||
334 | static inline bool is_dma_copy_aligned(struct dma_device *dev, size_t off1, | ||
335 | size_t off2, size_t len) | ||
336 | { | ||
337 | return dmaengine_check_align(dev->copy_align, off1, off2, len); | ||
338 | } | ||
339 | |||
340 | static inline bool is_dma_xor_aligned(struct dma_device *dev, size_t off1, | ||
341 | size_t off2, size_t len) | ||
342 | { | ||
343 | return dmaengine_check_align(dev->xor_align, off1, off2, len); | ||
344 | } | ||
345 | |||
346 | static inline bool is_dma_pq_aligned(struct dma_device *dev, size_t off1, | ||
347 | size_t off2, size_t len) | ||
348 | { | ||
349 | return dmaengine_check_align(dev->pq_align, off1, off2, len); | ||
350 | } | ||
351 | |||
352 | static inline bool is_dma_fill_aligned(struct dma_device *dev, size_t off1, | ||
353 | size_t off2, size_t len) | ||
354 | { | ||
355 | return dmaengine_check_align(dev->fill_align, off1, off2, len); | ||
356 | } | ||
357 | |||
358 | static inline void | ||
359 | dma_set_maxpq(struct dma_device *dma, int maxpq, int has_pq_continue) | ||
360 | { | ||
361 | dma->max_pq = maxpq; | ||
362 | if (has_pq_continue) | ||
363 | dma->max_pq |= DMA_HAS_PQ_CONTINUE; | ||
364 | } | ||
365 | |||
366 | static inline bool dmaf_continue(enum dma_ctrl_flags flags) | ||
367 | { | ||
368 | return (flags & DMA_PREP_CONTINUE) == DMA_PREP_CONTINUE; | ||
369 | } | ||
370 | |||
371 | static inline bool dmaf_p_disabled_continue(enum dma_ctrl_flags flags) | ||
372 | { | ||
373 | enum dma_ctrl_flags mask = DMA_PREP_CONTINUE | DMA_PREP_PQ_DISABLE_P; | ||
374 | |||
375 | return (flags & mask) == mask; | ||
376 | } | ||
377 | |||
378 | static inline bool dma_dev_has_pq_continue(struct dma_device *dma) | ||
379 | { | ||
380 | return (dma->max_pq & DMA_HAS_PQ_CONTINUE) == DMA_HAS_PQ_CONTINUE; | ||
381 | } | ||
382 | |||
383 | static unsigned short dma_dev_to_maxpq(struct dma_device *dma) | ||
384 | { | ||
385 | return dma->max_pq & ~DMA_HAS_PQ_CONTINUE; | ||
386 | } | ||
387 | |||
388 | /* dma_maxpq - reduce maxpq in the face of continued operations | ||
389 | * @dma - dma device with PQ capability | ||
390 | * @flags - to check if DMA_PREP_CONTINUE and DMA_PREP_PQ_DISABLE_P are set | ||
391 | * | ||
392 | * When an engine does not support native continuation we need 3 extra | ||
393 | * source slots to reuse P and Q with the following coefficients: | ||
394 | * 1/ {00} * P : remove P from Q', but use it as a source for P' | ||
395 | * 2/ {01} * Q : use Q to continue Q' calculation | ||
396 | * 3/ {00} * Q : subtract Q from P' to cancel (2) | ||
397 | * | ||
398 | * In the case where P is disabled we only need 1 extra source: | ||
399 | * 1/ {01} * Q : use Q to continue Q' calculation | ||
400 | */ | ||
401 | static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags) | ||
402 | { | ||
403 | if (dma_dev_has_pq_continue(dma) || !dmaf_continue(flags)) | ||
404 | return dma_dev_to_maxpq(dma); | ||
405 | else if (dmaf_p_disabled_continue(flags)) | ||
406 | return dma_dev_to_maxpq(dma) - 1; | ||
407 | else if (dmaf_continue(flags)) | ||
408 | return dma_dev_to_maxpq(dma) - 3; | ||
409 | BUG(); | ||
410 | } | ||
411 | |||
273 | /* --- public DMA engine API --- */ | 412 | /* --- public DMA engine API --- */ |
274 | 413 | ||
275 | #ifdef CONFIG_DMA_ENGINE | 414 | #ifdef CONFIG_DMA_ENGINE |
@@ -299,7 +438,11 @@ static inline void net_dmaengine_put(void) | |||
299 | #ifdef CONFIG_ASYNC_TX_DMA | 438 | #ifdef CONFIG_ASYNC_TX_DMA |
300 | #define async_dmaengine_get() dmaengine_get() | 439 | #define async_dmaengine_get() dmaengine_get() |
301 | #define async_dmaengine_put() dmaengine_put() | 440 | #define async_dmaengine_put() dmaengine_put() |
441 | #ifdef CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH | ||
442 | #define async_dma_find_channel(type) dma_find_channel(DMA_ASYNC_TX) | ||
443 | #else | ||
302 | #define async_dma_find_channel(type) dma_find_channel(type) | 444 | #define async_dma_find_channel(type) dma_find_channel(type) |
445 | #endif /* CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH */ | ||
303 | #else | 446 | #else |
304 | static inline void async_dmaengine_get(void) | 447 | static inline void async_dmaengine_get(void) |
305 | { | 448 | { |
@@ -312,7 +455,7 @@ async_dma_find_channel(enum dma_transaction_type type) | |||
312 | { | 455 | { |
313 | return NULL; | 456 | return NULL; |
314 | } | 457 | } |
315 | #endif | 458 | #endif /* CONFIG_ASYNC_TX_DMA */ |
316 | 459 | ||
317 | dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, | 460 | dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, |
318 | void *dest, void *src, size_t len); | 461 | void *dest, void *src, size_t len); |