aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/async_tx/async_pq.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/crypto/async_tx/async_pq.c b/crypto/async_tx/async_pq.c
index 8cdbf33bd046..4126b56fbc01 100644
--- a/crypto/async_tx/async_pq.c
+++ b/crypto/async_tx/async_pq.c
@@ -290,50 +290,60 @@ async_syndrome_val(struct page **blocks, unsigned int offset, int disks,
290 struct dma_async_tx_descriptor *tx; 290 struct dma_async_tx_descriptor *tx;
291 unsigned char coefs[disks-2]; 291 unsigned char coefs[disks-2];
292 enum dma_ctrl_flags dma_flags = submit->cb_fn ? DMA_PREP_INTERRUPT : 0; 292 enum dma_ctrl_flags dma_flags = submit->cb_fn ? DMA_PREP_INTERRUPT : 0;
293 dma_addr_t *dma_src = NULL; 293 struct dmaengine_unmap_data *unmap = NULL;
294 int src_cnt = 0;
295 294
296 BUG_ON(disks < 4); 295 BUG_ON(disks < 4);
297 296
298 if (submit->scribble) 297 if (device)
299 dma_src = submit->scribble; 298 unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOIO);
300 else if (sizeof(dma_addr_t) <= sizeof(struct page *))
301 dma_src = (dma_addr_t *) blocks;
302 299
303 if (dma_src && device && disks <= dma_maxpq(device, 0) && 300 if (unmap && disks <= dma_maxpq(device, 0) &&
304 is_dma_pq_aligned(device, offset, 0, len)) { 301 is_dma_pq_aligned(device, offset, 0, len)) {
305 struct device *dev = device->dev; 302 struct device *dev = device->dev;
306 dma_addr_t *pq = &dma_src[disks-2]; 303 dma_addr_t pq[2];
307 int i; 304 int i, j = 0, src_cnt = 0;
308 305
309 pr_debug("%s: (async) disks: %d len: %zu\n", 306 pr_debug("%s: (async) disks: %d len: %zu\n",
310 __func__, disks, len); 307 __func__, disks, len);
311 if (!P(blocks, disks)) 308
309 unmap->len = len;
310 for (i = 0; i < disks-2; i++)
311 if (likely(blocks[i])) {
312 unmap->addr[j] = dma_map_page(dev, blocks[i],
313 offset, len,
314 DMA_TO_DEVICE);
315 coefs[j] = raid6_gfexp[i];
316 unmap->to_cnt++;
317 src_cnt++;
318 j++;
319 }
320
321 if (!P(blocks, disks)) {
322 pq[0] = 0;
312 dma_flags |= DMA_PREP_PQ_DISABLE_P; 323 dma_flags |= DMA_PREP_PQ_DISABLE_P;
313 else 324 } else {
314 pq[0] = dma_map_page(dev, P(blocks, disks), 325 pq[0] = dma_map_page(dev, P(blocks, disks),
315 offset, len, 326 offset, len,
316 DMA_TO_DEVICE); 327 DMA_TO_DEVICE);
317 if (!Q(blocks, disks)) 328 unmap->addr[j++] = pq[0];
329 unmap->to_cnt++;
330 }
331 if (!Q(blocks, disks)) {
332 pq[1] = 0;
318 dma_flags |= DMA_PREP_PQ_DISABLE_Q; 333 dma_flags |= DMA_PREP_PQ_DISABLE_Q;
319 else 334 } else {
320 pq[1] = dma_map_page(dev, Q(blocks, disks), 335 pq[1] = dma_map_page(dev, Q(blocks, disks),
321 offset, len, 336 offset, len,
322 DMA_TO_DEVICE); 337 DMA_TO_DEVICE);
338 unmap->addr[j++] = pq[1];
339 unmap->to_cnt++;
340 }
323 341
324 if (submit->flags & ASYNC_TX_FENCE) 342 if (submit->flags & ASYNC_TX_FENCE)
325 dma_flags |= DMA_PREP_FENCE; 343 dma_flags |= DMA_PREP_FENCE;
326 for (i = 0; i < disks-2; i++)
327 if (likely(blocks[i])) {
328 dma_src[src_cnt] = dma_map_page(dev, blocks[i],
329 offset, len,
330 DMA_TO_DEVICE);
331 coefs[src_cnt] = raid6_gfexp[i];
332 src_cnt++;
333 }
334
335 for (;;) { 344 for (;;) {
336 tx = device->device_prep_dma_pq_val(chan, pq, dma_src, 345 tx = device->device_prep_dma_pq_val(chan, pq,
346 unmap->addr,
337 src_cnt, 347 src_cnt,
338 coefs, 348 coefs,
339 len, pqres, 349 len, pqres,
@@ -343,6 +353,8 @@ async_syndrome_val(struct page **blocks, unsigned int offset, int disks,
343 async_tx_quiesce(&submit->depend_tx); 353 async_tx_quiesce(&submit->depend_tx);
344 dma_async_issue_pending(chan); 354 dma_async_issue_pending(chan);
345 } 355 }
356
357 dma_set_unmap(tx, unmap);
346 async_tx_submit(chan, tx, submit); 358 async_tx_submit(chan, tx, submit);
347 359
348 return tx; 360 return tx;