crypto: atmel-{aes,sha} - Fix incorrect use of dmaengine_terminate_all()
authorTudor Ambarus <tudor.ambarus@microchip.com>
Fri, 13 Dec 2019 09:54:42 +0000 (09:54 +0000)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 20 Dec 2019 06:58:34 +0000 (14:58 +0800)
device_terminate_all() is used to abort all the pending and
ongoing transfers on the channel, it should be used just in the
error path.

Also, dmaengine_terminate_all() is deprecated and one should use
dmaengine_terminate_async() or dmaengine_terminate_sync(). The method
is not used in atomic context, use dmaengine_terminate_sync().

A secondary aspect of this patch is that it luckily avoids a deadlock
between atmel_aes and at_hdmac.c. While in tasklet with the lock held,
the dma controller invokes the client callback (dmaengine_terminate_all),
which tries to get the same lock. The at_hdmac fix would be to drop the
lock before invoking the client callback, a fix on at_hdmac will follow.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/atmel-aes.c
drivers/crypto/atmel-sha.c

index 47b20df3adfc9db9f2f8e99d623c84e811e275fe..c3f0e99d24b02fb96a26a7fd18bd83f935918c42 100644 (file)
@@ -857,27 +857,6 @@ static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd,
        return 0;
 }
 
-static void atmel_aes_dma_transfer_stop(struct atmel_aes_dev *dd,
-                                       enum dma_transfer_direction dir)
-{
-       struct atmel_aes_dma *dma;
-
-       switch (dir) {
-       case DMA_MEM_TO_DEV:
-               dma = &dd->src;
-               break;
-
-       case DMA_DEV_TO_MEM:
-               dma = &dd->dst;
-               break;
-
-       default:
-               return;
-       }
-
-       dmaengine_terminate_all(dma->chan);
-}
-
 static int atmel_aes_dma_start(struct atmel_aes_dev *dd,
                               struct scatterlist *src,
                               struct scatterlist *dst,
@@ -936,25 +915,18 @@ static int atmel_aes_dma_start(struct atmel_aes_dev *dd,
        return -EINPROGRESS;
 
 output_transfer_stop:
-       atmel_aes_dma_transfer_stop(dd, DMA_DEV_TO_MEM);
+       dmaengine_terminate_sync(dd->dst.chan);
 unmap:
        atmel_aes_unmap(dd);
 exit:
        return atmel_aes_complete(dd, err);
 }
 
-static void atmel_aes_dma_stop(struct atmel_aes_dev *dd)
-{
-       atmel_aes_dma_transfer_stop(dd, DMA_MEM_TO_DEV);
-       atmel_aes_dma_transfer_stop(dd, DMA_DEV_TO_MEM);
-       atmel_aes_unmap(dd);
-}
-
 static void atmel_aes_dma_callback(void *data)
 {
        struct atmel_aes_dev *dd = data;
 
-       atmel_aes_dma_stop(dd);
+       atmel_aes_unmap(dd);
        dd->is_async = true;
        (void)dd->resume(dd);
 }
index ebf500153700c6b18df88d205178ad60f2cfd845..7cf4ec9ed93a03516209bc295c85374a8ebaa9f8 100644 (file)
@@ -1429,7 +1429,6 @@ static void atmel_sha_dma_callback2(void *data)
        struct scatterlist *sg;
        int nents;
 
-       dmaengine_terminate_all(dma->chan);
        dma_unmap_sg(dd->dev, dma->sg, dma->nents, DMA_TO_DEVICE);
 
        sg = dma->sg;