Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[linux-drm-fsl-dcu.git] / crypto / async_tx / async_pq.c
index d05327caf69dbc18532478b122ea9834e67f1fd9..5d355e0c263339b5bd179ad61aad63c9b7efb3a3 100644 (file)
@@ -124,6 +124,7 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
 {
        void **srcs;
        int i;
+       int start = -1, stop = disks - 3;
 
        if (submit->scribble)
                srcs = submit->scribble;
@@ -134,10 +135,21 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
                if (blocks[i] == NULL) {
                        BUG_ON(i > disks - 3); /* P or Q can't be zero */
                        srcs[i] = (void*)raid6_empty_zero_page;
-               } else
+               } else {
                        srcs[i] = page_address(blocks[i]) + offset;
+                       if (i < disks - 2) {
+                               stop = i;
+                               if (start == -1)
+                                       start = i;
+                       }
+               }
        }
-       raid6_call.gen_syndrome(disks, len, srcs);
+       if (submit->flags & ASYNC_TX_PQ_XOR_DST) {
+               BUG_ON(!raid6_call.xor_syndrome);
+               if (start >= 0)
+                       raid6_call.xor_syndrome(disks, start, stop, len, srcs);
+       } else
+               raid6_call.gen_syndrome(disks, len, srcs);
        async_tx_sync_epilog(submit);
 }
 
@@ -178,7 +190,8 @@ async_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
        if (device)
                unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOIO);
 
-       if (unmap &&
+       /* XORing P/Q is only implemented in software */
+       if (unmap && !(submit->flags & ASYNC_TX_PQ_XOR_DST) &&
            (src_cnt <= dma_maxpq(device, 0) ||
             dma_maxpq(device, DMA_PREP_CONTINUE) > 0) &&
            is_dma_pq_aligned(device, offset, 0, len)) {