Commit 7476bd79fc019dd9a8361de6696627a4eae3ef05
1 parent
3bbdd49872
Exists in
master
and in
16 other branches
async_pq: convert to dmaengine_unmap_data
Use the generic unmap object to unmap dma buffers. Cc: Vinod Koul <vinod.koul@intel.com> Cc: Tomasz Figa <t.figa@samsung.com> Cc: Dave Jiang <dave.jiang@intel.com> Reported-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> [bzolnier: keep temporary dma_dest array in do_async_gen_syndrome()] Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Showing 2 changed files with 69 additions and 53 deletions Side-by-side Diff
crypto/async_tx/async_pq.c
... | ... | @@ -46,50 +46,26 @@ |
46 | 46 | * do_async_gen_syndrome - asynchronously calculate P and/or Q |
47 | 47 | */ |
48 | 48 | static __async_inline struct dma_async_tx_descriptor * |
49 | -do_async_gen_syndrome(struct dma_chan *chan, struct page **blocks, | |
50 | - const unsigned char *scfs, unsigned int offset, int disks, | |
51 | - size_t len, dma_addr_t *dma_src, | |
49 | +do_async_gen_syndrome(struct dma_chan *chan, | |
50 | + const unsigned char *scfs, int disks, | |
51 | + struct dmaengine_unmap_data *unmap, | |
52 | + enum dma_ctrl_flags dma_flags, | |
52 | 53 | struct async_submit_ctl *submit) |
53 | 54 | { |
54 | 55 | struct dma_async_tx_descriptor *tx = NULL; |
55 | 56 | struct dma_device *dma = chan->device; |
56 | - enum dma_ctrl_flags dma_flags = 0; | |
57 | 57 | enum async_tx_flags flags_orig = submit->flags; |
58 | 58 | dma_async_tx_callback cb_fn_orig = submit->cb_fn; |
59 | 59 | dma_async_tx_callback cb_param_orig = submit->cb_param; |
60 | 60 | int src_cnt = disks - 2; |
61 | - unsigned char coefs[src_cnt]; | |
62 | 61 | unsigned short pq_src_cnt; |
63 | 62 | dma_addr_t dma_dest[2]; |
64 | 63 | int src_off = 0; |
65 | - int idx; | |
66 | - int i; | |
67 | 64 | |
68 | - /* DMAs use destinations as sources, so use BIDIRECTIONAL mapping */ | |
69 | - if (P(blocks, disks)) | |
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; | |
65 | + dma_flags |= DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UNMAP; | |
66 | + if (submit->flags & ASYNC_TX_FENCE) | |
67 | + dma_flags |= DMA_PREP_FENCE; | |
79 | 68 | |
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 | - | |
93 | 69 | while (src_cnt > 0) { |
94 | 70 | submit->flags = flags_orig; |
95 | 71 | pq_src_cnt = min(src_cnt, dma_maxpq(dma, dma_flags)); |
96 | 72 | |
97 | 73 | |
98 | 74 | |
99 | 75 | |
100 | 76 | |
101 | 77 | |
... | ... | @@ -100,28 +76,25 @@ |
100 | 76 | if (src_cnt > pq_src_cnt) { |
101 | 77 | submit->flags &= ~ASYNC_TX_ACK; |
102 | 78 | submit->flags |= ASYNC_TX_FENCE; |
103 | - dma_flags |= DMA_COMPL_SKIP_DEST_UNMAP; | |
104 | 79 | submit->cb_fn = NULL; |
105 | 80 | submit->cb_param = NULL; |
106 | 81 | } else { |
107 | - dma_flags &= ~DMA_COMPL_SKIP_DEST_UNMAP; | |
108 | 82 | submit->cb_fn = cb_fn_orig; |
109 | 83 | submit->cb_param = cb_param_orig; |
110 | 84 | if (cb_fn_orig) |
111 | 85 | dma_flags |= DMA_PREP_INTERRUPT; |
112 | 86 | } |
113 | - if (submit->flags & ASYNC_TX_FENCE) | |
114 | - dma_flags |= DMA_PREP_FENCE; | |
115 | 87 | |
116 | - /* Since we have clobbered the src_list we are committed | |
117 | - * to doing this asynchronously. Drivers force forward | |
118 | - * progress in case they can not provide a descriptor | |
88 | + /* Drivers force forward progress in case they can not provide | |
89 | + * a descriptor | |
119 | 90 | */ |
120 | 91 | for (;;) { |
92 | + dma_dest[0] = unmap->addr[disks - 2]; | |
93 | + dma_dest[1] = unmap->addr[disks - 1]; | |
121 | 94 | tx = dma->device_prep_dma_pq(chan, dma_dest, |
122 | - &dma_src[src_off], | |
95 | + &unmap->addr[src_off], | |
123 | 96 | pq_src_cnt, |
124 | - &coefs[src_off], len, | |
97 | + &scfs[src_off], unmap->len, | |
125 | 98 | dma_flags); |
126 | 99 | if (likely(tx)) |
127 | 100 | break; |
... | ... | @@ -129,6 +102,7 @@ |
129 | 102 | dma_async_issue_pending(chan); |
130 | 103 | } |
131 | 104 | |
105 | + dma_set_unmap(tx, unmap); | |
132 | 106 | async_tx_submit(chan, tx, submit); |
133 | 107 | submit->depend_tx = tx; |
134 | 108 | |
... | ... | @@ -188,10 +162,6 @@ |
188 | 162 | * set to NULL those buffers will be replaced with the raid6_zero_page |
189 | 163 | * in the synchronous path and omitted in the hardware-asynchronous |
190 | 164 | * path. |
191 | - * | |
192 | - * 'blocks' note: if submit->scribble is NULL then the contents of | |
193 | - * 'blocks' may be overwritten to perform address conversions | |
194 | - * (dma_map_page() or page_address()). | |
195 | 165 | */ |
196 | 166 | struct dma_async_tx_descriptor * |
197 | 167 | async_gen_syndrome(struct page **blocks, unsigned int offset, int disks, |
198 | 168 | |
199 | 169 | |
200 | 170 | |
201 | 171 | |
202 | 172 | |
... | ... | @@ -202,25 +172,68 @@ |
202 | 172 | &P(blocks, disks), 2, |
203 | 173 | blocks, src_cnt, len); |
204 | 174 | struct dma_device *device = chan ? chan->device : NULL; |
205 | - dma_addr_t *dma_src = NULL; | |
175 | + struct dmaengine_unmap_data *unmap = NULL; | |
206 | 176 | |
207 | 177 | BUG_ON(disks > 255 || !(P(blocks, disks) || Q(blocks, disks))); |
208 | 178 | |
209 | - if (submit->scribble) | |
210 | - dma_src = submit->scribble; | |
211 | - else if (sizeof(dma_addr_t) <= sizeof(struct page *)) | |
212 | - dma_src = (dma_addr_t *) blocks; | |
179 | + if (device) | |
180 | + unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOIO); | |
213 | 181 | |
214 | - if (dma_src && device && | |
182 | + if (unmap && | |
215 | 183 | (src_cnt <= dma_maxpq(device, 0) || |
216 | 184 | dma_maxpq(device, DMA_PREP_CONTINUE) > 0) && |
217 | 185 | is_dma_pq_aligned(device, offset, 0, len)) { |
186 | + struct dma_async_tx_descriptor *tx; | |
187 | + enum dma_ctrl_flags dma_flags = 0; | |
188 | + unsigned char coefs[src_cnt]; | |
189 | + int i, j; | |
190 | + | |
218 | 191 | /* run the p+q asynchronously */ |
219 | 192 | pr_debug("%s: (async) disks: %d len: %zu\n", |
220 | 193 | __func__, disks, len); |
221 | - return do_async_gen_syndrome(chan, blocks, raid6_gfexp, offset, | |
222 | - disks, len, dma_src, submit); | |
194 | + | |
195 | + /* convert source addresses being careful to collapse 'empty' | |
196 | + * sources and update the coefficients accordingly | |
197 | + */ | |
198 | + unmap->len = len; | |
199 | + for (i = 0, j = 0; i < src_cnt; i++) { | |
200 | + if (blocks[i] == NULL) | |
201 | + continue; | |
202 | + unmap->addr[j] = dma_map_page(device->dev, blocks[i], offset, | |
203 | + len, DMA_TO_DEVICE); | |
204 | + coefs[j] = raid6_gfexp[i]; | |
205 | + unmap->to_cnt++; | |
206 | + j++; | |
207 | + } | |
208 | + | |
209 | + /* | |
210 | + * DMAs use destinations as sources, | |
211 | + * so use BIDIRECTIONAL mapping | |
212 | + */ | |
213 | + unmap->bidi_cnt++; | |
214 | + if (P(blocks, disks)) | |
215 | + unmap->addr[j++] = dma_map_page(device->dev, P(blocks, disks), | |
216 | + offset, len, DMA_BIDIRECTIONAL); | |
217 | + else { | |
218 | + unmap->addr[j++] = 0; | |
219 | + dma_flags |= DMA_PREP_PQ_DISABLE_P; | |
220 | + } | |
221 | + | |
222 | + unmap->bidi_cnt++; | |
223 | + if (Q(blocks, disks)) | |
224 | + unmap->addr[j++] = dma_map_page(device->dev, Q(blocks, disks), | |
225 | + offset, len, DMA_BIDIRECTIONAL); | |
226 | + else { | |
227 | + unmap->addr[j++] = 0; | |
228 | + dma_flags |= DMA_PREP_PQ_DISABLE_Q; | |
229 | + } | |
230 | + | |
231 | + tx = do_async_gen_syndrome(chan, coefs, j, unmap, dma_flags, submit); | |
232 | + dmaengine_unmap_put(unmap); | |
233 | + return tx; | |
223 | 234 | } |
235 | + | |
236 | + dmaengine_unmap_put(unmap); | |
224 | 237 | |
225 | 238 | /* run the pq synchronously */ |
226 | 239 | pr_debug("%s: (sync) disks: %d len: %zu\n", __func__, disks, len); |
drivers/dma/dmaengine.c
... | ... | @@ -953,9 +953,12 @@ |
953 | 953 | dma_unmap_page(dev, unmap->addr[i], unmap->len, |
954 | 954 | DMA_FROM_DEVICE); |
955 | 955 | cnt += unmap->bidi_cnt; |
956 | - for (; i < cnt; i++) | |
956 | + for (; i < cnt; i++) { | |
957 | + if (unmap->addr[i] == 0) | |
958 | + continue; | |
957 | 959 | dma_unmap_page(dev, unmap->addr[i], unmap->len, |
958 | 960 | DMA_BIDIRECTIONAL); |
961 | + } | |
959 | 962 | mempool_free(unmap, __get_unmap_pool(cnt)->pool); |
960 | 963 | } |
961 | 964 |