summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2007-09-21 13:27:04 -0700
committerDan Williams <dan.j.williams@intel.com>2007-09-24 10:26:26 -0700
commit6247cdc2cd334dad0ea5428245a7d8f4b075f21e (patch)
tree275bfcdb142a92ea347d264b6b37b17c98d41733
parentc5d2b9f444b8d9f5ad7c5e583686c119ba3a9ba7 (diff)
downloadlinux-6247cdc2cd334dad0ea5428245a7d8f4b075f21e.tar.gz
linux-6247cdc2cd334dad0ea5428245a7d8f4b075f21e.tar.bz2
linux-6247cdc2cd334dad0ea5428245a7d8f4b075f21e.zip
async_tx: fix dma_wait_for_async_tx
Fix dma_wait_for_async_tx to not loop forever in the case where a dependency chain is longer than two entries. This condition will not happen with current in-kernel drivers, but fix it for future drivers. Found-by: Saeed Bishara <saeed.bishara@gmail.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--crypto/async_tx/async_tx.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index 035007145e78..bc18cbb8ea79 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -80,6 +80,7 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
{
enum dma_status status;
struct dma_async_tx_descriptor *iter;
+ struct dma_async_tx_descriptor *parent;
if (!tx)
return DMA_SUCCESS;
@@ -87,8 +88,15 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
/* poll through the dependency chain, return when tx is complete */
do {
iter = tx;
- while (iter->cookie == -EBUSY)
- iter = iter->parent;
+
+ /* find the root of the unsubmitted dependency chain */
+ while (iter->cookie == -EBUSY) {
+ parent = iter->parent;
+ if (parent && parent->cookie == -EBUSY)
+ iter = iter->parent;
+ else
+ break;
+ }
status = dma_sync_wait(iter->chan, iter->cookie);
} while (status == DMA_IN_PROGRESS || (iter != tx));