diff options
Diffstat (limited to 'crypto/async_tx')
| -rw-r--r-- | crypto/async_tx/async_memcpy.c | 37 | ||||
| -rw-r--r-- | crypto/async_tx/async_pq.c | 174 | ||||
| -rw-r--r-- | crypto/async_tx/async_raid6_recov.c | 61 | ||||
| -rw-r--r-- | crypto/async_tx/async_tx.c | 4 | ||||
| -rw-r--r-- | crypto/async_tx/async_xor.c | 123 | ||||
| -rw-r--r-- | crypto/async_tx/raid6test.c | 10 |
6 files changed, 240 insertions, 169 deletions
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c index 9e62feffb374..f8c0b8dbeb75 100644 --- a/crypto/async_tx/async_memcpy.c +++ b/crypto/async_tx/async_memcpy.c | |||
| @@ -50,33 +50,36 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, | |||
| 50 | &dest, 1, &src, 1, len); | 50 | &dest, 1, &src, 1, len); |
| 51 | struct dma_device *device = chan ? chan->device : NULL; | 51 | struct dma_device *device = chan ? chan->device : NULL; |
| 52 | struct dma_async_tx_descriptor *tx = NULL; | 52 | struct dma_async_tx_descriptor *tx = NULL; |
| 53 | struct dmaengine_unmap_data *unmap = NULL; | ||
| 53 | 54 | ||
| 54 | if (device && is_dma_copy_aligned(device, src_offset, dest_offset, len)) { | 55 | if (device) |
| 55 | dma_addr_t dma_dest, dma_src; | 56 | unmap = dmaengine_get_unmap_data(device->dev, 2, GFP_NOIO); |
| 57 | |||
| 58 | if (unmap && is_dma_copy_aligned(device, src_offset, dest_offset, len)) { | ||
| 56 | unsigned long dma_prep_flags = 0; | 59 | unsigned long dma_prep_flags = 0; |
| 57 | 60 | ||
| 58 | if (submit->cb_fn) | 61 | if (submit->cb_fn) |
| 59 | dma_prep_flags |= DMA_PREP_INTERRUPT; | 62 | dma_prep_flags |= DMA_PREP_INTERRUPT; |
| 60 | if (submit->flags & ASYNC_TX_FENCE) | 63 | if (submit->flags & ASYNC_TX_FENCE) |
| 61 | dma_prep_flags |= DMA_PREP_FENCE; | 64 | dma_prep_flags |= DMA_PREP_FENCE; |
| 62 | dma_dest = dma_map_page(device->dev, dest, dest_offset, len, | 65 | |
| 63 | DMA_FROM_DEVICE); | 66 | unmap->to_cnt = 1; |
| 64 | 67 | unmap->addr[0] = dma_map_page(device->dev, src, src_offset, len, | |
| 65 | dma_src = dma_map_page(device->dev, src, src_offset, len, | 68 | DMA_TO_DEVICE); |
| 66 | DMA_TO_DEVICE); | 69 | unmap->from_cnt = 1; |
| 67 | 70 | unmap->addr[1] = dma_map_page(device->dev, dest, dest_offset, len, | |
| 68 | tx = device->device_prep_dma_memcpy(chan, dma_dest, dma_src, | 71 | DMA_FROM_DEVICE); |
| 69 | len, dma_prep_flags); | 72 | unmap->len = len; |
| 70 | if (!tx) { | 73 | |
| 71 | dma_unmap_page(device->dev, dma_dest, len, | 74 | tx = device->device_prep_dma_memcpy(chan, unmap->addr[1], |
| 72 | DMA_FROM_DEVICE); | 75 | unmap->addr[0], len, |
| 73 | dma_unmap_page(device->dev, dma_src, len, | 76 | dma_prep_flags); |
| 74 | DMA_TO_DEVICE); | ||
| 75 | } | ||
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | if (tx) { | 79 | if (tx) { |
| 79 | pr_debug("%s: (async) len: %zu\n", __func__, len); | 80 | pr_debug("%s: (async) len: %zu\n", __func__, len); |
| 81 | |||
| 82 | dma_set_unmap(tx, unmap); | ||
| 80 | async_tx_submit(chan, tx, submit); | 83 | async_tx_submit(chan, tx, submit); |
| 81 | } else { | 84 | } else { |
| 82 | void *dest_buf, *src_buf; | 85 | void *dest_buf, *src_buf; |
| @@ -96,6 +99,8 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset, | |||
| 96 | async_tx_sync_epilog(submit); | 99 | async_tx_sync_epilog(submit); |
| 97 | } | 100 | } |
| 98 | 101 | ||
| 102 | dmaengine_unmap_put(unmap); | ||
| 103 | |||
| 99 | return tx; | 104 | return tx; |
| 100 | } | 105 | } |
| 101 | EXPORT_SYMBOL_GPL(async_memcpy); | 106 | EXPORT_SYMBOL_GPL(async_memcpy); |
diff --git a/crypto/async_tx/async_pq.c b/crypto/async_tx/async_pq.c index 91d5d385899e..d05327caf69d 100644 --- a/crypto/async_tx/async_pq.c +++ b/crypto/async_tx/async_pq.c | |||
| @@ -46,49 +46,24 @@ static struct page *pq_scribble_page; | |||
| 46 | * do_async_gen_syndrome - asynchronously calculate P and/or Q | 46 | * do_async_gen_syndrome - asynchronously calculate P and/or Q |
| 47 | */ | 47 | */ |
| 48 | static __async_inline struct dma_async_tx_descriptor * | 48 | static __async_inline struct dma_async_tx_descriptor * |
| 49 | do_async_gen_syndrome(struct dma_chan *chan, struct page **blocks, | 49 | do_async_gen_syndrome(struct dma_chan *chan, |
| 50 | const unsigned char *scfs, unsigned int offset, int disks, | 50 | const unsigned char *scfs, int disks, |
| 51 | size_t len, dma_addr_t *dma_src, | 51 | struct dmaengine_unmap_data *unmap, |
| 52 | enum dma_ctrl_flags dma_flags, | ||
| 52 | struct async_submit_ctl *submit) | 53 | struct async_submit_ctl *submit) |
| 53 | { | 54 | { |
| 54 | struct dma_async_tx_descriptor *tx = NULL; | 55 | struct dma_async_tx_descriptor *tx = NULL; |
| 55 | struct dma_device *dma = chan->device; | 56 | struct dma_device *dma = chan->device; |
| 56 | enum dma_ctrl_flags dma_flags = 0; | ||
| 57 | enum async_tx_flags flags_orig = submit->flags; | 57 | enum async_tx_flags flags_orig = submit->flags; |
| 58 | dma_async_tx_callback cb_fn_orig = submit->cb_fn; | 58 | dma_async_tx_callback cb_fn_orig = submit->cb_fn; |
| 59 | dma_async_tx_callback cb_param_orig = submit->cb_param; | 59 | dma_async_tx_callback cb_param_orig = submit->cb_param; |
| 60 | int src_cnt = disks - 2; | 60 | int src_cnt = disks - 2; |
| 61 | unsigned char coefs[src_cnt]; | ||
| 62 | unsigned short pq_src_cnt; | 61 | unsigned short pq_src_cnt; |
| 63 | dma_addr_t dma_dest[2]; | 62 | dma_addr_t dma_dest[2]; |
| 64 | int src_off = 0; | 63 | int src_off = 0; |
| 65 | int idx; | ||
| 66 | int i; | ||
| 67 | 64 | ||
| 68 | /* DMAs use destinations as sources, so use BIDIRECTIONAL mapping */ | 65 | if (submit->flags & ASYNC_TX_FENCE) |
| 69 | if (P(blocks, disks)) | 66 | dma_flags |= DMA_PREP_FENCE; |
| 70 | dma_dest[0] = dma_map_page(dma->dev, P(blocks, disks), offset, | ||
| 71 | len, DMA_BIDIRECTIONAL); | ||
| 72 | else | ||
| 73 | dma_flags |= DMA_PREP_PQ_DISABLE_P; | ||
| 74 | if (Q(blocks, disks)) | ||
| 75 | dma_dest[1] = dma_map_page(dma->dev, Q(blocks, disks), offset, | ||
| 76 | len, DMA_BIDIRECTIONAL); | ||
| 77 | else | ||
| 78 | dma_flags |= DMA_PREP_PQ_DISABLE_Q; | ||
| 79 | |||
| 80 | /* convert source addresses being careful to collapse 'empty' | ||
| 81 | * sources and update the coefficients accordingly | ||
| 82 | */ | ||
| 83 | for (i = 0, idx = 0; i < src_cnt; i++) { | ||
| 84 | if (blocks[i] == NULL) | ||
| 85 | continue; | ||
| 86 | dma_src[idx] = dma_map_page(dma->dev, blocks[i], offset, len, | ||
| 87 | DMA_TO_DEVICE); | ||
| 88 | coefs[idx] = scfs[i]; | ||
| 89 | idx++; | ||
| 90 | } | ||
| 91 | src_cnt = idx; | ||
| 92 | 67 | ||
| 93 | while (src_cnt > 0) { | 68 | while (src_cnt > 0) { |
| 94 | submit->flags = flags_orig; | 69 | submit->flags = flags_orig; |
| @@ -100,28 +75,25 @@ do_async_gen_syndrome(struct dma_chan *chan, struct page **blocks, | |||
| 100 | if (src_cnt > pq_src_cnt) { | 75 | if (src_cnt > pq_src_cnt) { |
| 101 | submit->flags &= ~ASYNC_TX_ACK; | 76 | submit->flags &= ~ASYNC_TX_ACK; |
| 102 | submit->flags |= ASYNC_TX_FENCE; | 77 | submit->flags |= ASYNC_TX_FENCE; |
| 103 | dma_flags |= DMA_COMPL_SKIP_DEST_UNMAP; | ||
| 104 | submit->cb_fn = NULL; | 78 | submit->cb_fn = NULL; |
| 105 | submit->cb_param = NULL; | 79 | submit->cb_param = NULL; |
| 106 | } else { | 80 | } else { |
| 107 | dma_flags &= ~DMA_COMPL_SKIP_DEST_UNMAP; | ||
| 108 | submit->cb_fn = cb_fn_orig; | 81 | submit->cb_fn = cb_fn_orig; |
| 109 | submit->cb_param = cb_param_orig; | 82 | submit->cb_param = cb_param_orig; |
| 110 | if (cb_fn_orig) | 83 | if (cb_fn_orig) |
| 111 | dma_flags |= DMA_PREP_INTERRUPT; | 84 | dma_flags |= DMA_PREP_INTERRUPT; |
| 112 | } | 85 | } |
| 113 | if (submit->flags & ASYNC_TX_FENCE) | ||
| 114 | dma_flags |= DMA_PREP_FENCE; | ||
| 115 | 86 | ||
| 116 | /* Since we have clobbered the src_list we are committed | 87 | /* Drivers force forward progress in case they can not provide |
| 117 | * to doing this asynchronously. Drivers force forward | 88 | * a descriptor |
| 118 | * progress in case they can not provide a descriptor | ||
| 119 | */ | 89 | */ |
| 120 | for (;;) { | 90 | for (;;) { |
| 91 | dma_dest[0] = unmap->addr[disks - 2]; | ||
| 92 | dma_dest[1] = unmap->addr[disks - 1]; | ||
| 121 | tx = dma->device_prep_dma_pq(chan, dma_dest, | 93 | tx = dma->device_prep_dma_pq(chan, dma_dest, |
| 122 | &dma_src[src_off], | 94 | &unmap->addr[src_off], |
| 123 | pq_src_cnt, | 95 | pq_src_cnt, |
| 124 | &coefs[src_off], len, | 96 | &scfs[src_off], unmap->len, |
| 125 | dma_flags); | 97 | dma_flags); |
| 126 | if (likely(tx)) | 98 | if (likely(tx)) |
| 127 | break; | 99 | break; |
| @@ -129,6 +101,7 @@ do_async_gen_syndrome(struct dma_chan *chan, struct page **blocks, | |||
| 129 | dma_async_issue_pending(chan); | 101 | dma_async_issue_pending(chan); |
| 130 | } | ||
