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); |
