diff options
author | Dan Williams <dan.j.williams@intel.com> | 2007-09-21 13:27:04 -0700 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2007-09-24 10:26:26 -0700 |
commit | 89bc5d05aa8a7b9a1c664fd4e481e3b43d4b9427 (patch) | |
tree | 30df1dfac3834a8a11b4da61b1d1c2c012e2d30e /crypto/async_tx/async_tx.c | |
parent | 7385c71768c9642dad17c090ff294eb9e7db5e1a (diff) | |
download | linux-crypto-89bc5d05aa8a7b9a1c664fd4e481e3b43d4b9427.tar.gz linux-crypto-89bc5d05aa8a7b9a1c664fd4e481e3b43d4b9427.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>
Diffstat (limited to 'crypto/async_tx/async_tx.c')
-rw-r--r-- | crypto/async_tx/async_tx.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c index 03500714..bc18cbb8 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)); |