Commit 0e693789 authored by Tudor Ambarus's avatar Tudor Ambarus Committed by Herbert Xu
Browse files

crypto: atmel-{aes,sha} - Fix incorrect use of dmaengine_terminate_all()



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: default avatarTudor Ambarus <tudor.ambarus@microchip.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 7d07de2c
Loading
Loading
Loading
Loading
+2 −30
Original line number Diff line number Diff line
@@ -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);
}
+0 −1
Original line number Diff line number Diff line
@@ -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;