async_tx: fix dma_wait_for_async_tx
authorDan Williams <dan.j.williams@intel.com>
Fri, 21 Sep 2007 20:27:04 +0000 (13:27 -0700)
committerDan Williams <dan.j.williams@intel.com>
Mon, 24 Sep 2007 17:26:26 +0000 (10:26 -0700)
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>
crypto/async_tx/async_tx.c

index 035007145e780d2cedd3e38cbb1a34e39345d3c2..bc18cbb8ea79562ce05401a5734d8310cf2ea938 100644 (file)
@@ -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));