aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/async_tx
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-07-17 20:59:55 -0400
committerDan Williams <dan.j.williams@intel.com>2008-07-17 20:59:55 -0400
commit669ab0b210f9bd15d94d4d6a49ae13366a85e4da (patch)
treeead561418e94def95c4d4b4512ae3c9a7888febe /crypto/async_tx
parent1e55db2d6bdef92abc981b68673564e63c80da4d (diff)
async_tx: fix handling of the "out of descriptor" condition in async_xor
Ensure forward progress is made when a dmaengine driver is unable to allocate an xor descriptor by breaking the dependency chain with async_tx_quisce() and issue any pending descriptors. Tested with iop-adma by setting device->max_xor = 2 to force multiple calls to device_prep_dma_xor for each call to async_xor and limiting the descriptor slot pool to 5. Discovered that the minimum descriptor pool size for iop-adma is 2 * iop_chan_xor_slot_cnt(device->max_xor) + 1. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'crypto/async_tx')
-rw-r--r--crypto/async_tx/async_xor.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 1fcf45ac81ec..19d16e452bcc 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -30,6 +30,24 @@
30#include <linux/raid/xor.h> 30#include <linux/raid/xor.h>
31#include <linux/async_tx.h> 31#include <linux/async_tx.h>
32 32
33/**
34 * async_tx_quiesce - ensure tx is complete and freeable upon return
35 * @tx - transaction to quiesce
36 */
37static void async_tx_quiesce(struct dma_async_tx_descriptor **tx)
38{
39 if (*tx) {
40 /* if ack is already set then we cannot be sure
41 * we are referring to the correct operation
42 */
43 BUG_ON(async_tx_test_ack(*tx));
44 if (dma_wait_for_async_tx(*tx) == DMA_ERROR)
45 panic("DMA_ERROR waiting for transaction\n");
46 async_tx_ack(*tx);
47 *tx = NULL;
48 }
49}
50
33/* do_async_xor - dma map the pages and perform the xor with an engine. 51/* do_async_xor - dma map the pages and perform the xor with an engine.
34 * This routine is marked __always_inline so it can be compiled away 52 * This routine is marked __always_inline so it can be compiled away
35 * when CONFIG_DMA_ENGINE=n 53 * when CONFIG_DMA_ENGINE=n
@@ -85,15 +103,17 @@ do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
85 tx = dma->device_prep_dma_xor(chan, dma_dest, &dma_src[src_off], 103 tx = dma->device_prep_dma_xor(chan, dma_dest, &dma_src[src_off],
86 xor_src_cnt, len, dma_flags); 104 xor_src_cnt, len, dma_flags);
87 105
88 if (unlikely(!tx && depend_tx)) 106 if (unlikely(!tx))
89 dma_wait_for_async_tx(depend_tx); 107 async_tx_quiesce(&depend_tx);
90 108
91 /* spin wait for the preceeding transactions to complete */ 109 /* spin wait for the preceeding transactions to complete */
92 while (unlikely(!tx)) 110 while (unlikely(!tx)) {
111 dma_async_issue_pending(chan);
93 tx = dma->device_prep_dma_xor(chan, dma_dest, 112 tx = dma->device_prep_dma_xor(chan, dma_dest,
94 &dma_src[src_off], 113 &dma_src[src_off],
95 xor_src_cnt, len, 114 xor_src_cnt, len,
96 dma_flags); 115 dma_flags);
116 }
97 117
98 async_tx_submit(chan, tx, async_flags, depend_tx, _cb_fn, 118 async_tx_submit(chan, tx, async_flags, depend_tx, _cb_fn,
99 _cb_param); 119 _cb_param);
@@ -267,11 +287,11 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
267 tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt, 287 tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt,
268 len, result, 288 len, result,
269 dma_prep_flags); 289 dma_prep_flags);
270 if (!tx) { 290 if (unlikely(!tx)) {
271 if (depend_tx) 291 async_tx_quiesce(&depend_tx);
272 dma_wait_for_async_tx(depend_tx);
273 292
274 while (!tx) 293 while (!tx)
294 dma_async_issue_pending(chan);
275 tx = device->device_prep_dma_zero_sum(chan, 295 tx = device->device_prep_dma_zero_sum(chan,
276 dma_src, src_cnt, len, result, 296 dma_src, src_cnt, len, result,
277 dma_prep_flags); 297 dma_prep_flags);