Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: atmel-aes - sync the buf used in DMA or CPU

The input buffer and output buffer are mapped for DMA transfer
in Atmel AES driver. But they are also be used by CPU when
the requested crypt length is not bigger than the threshold
value 16. The buffers will be cached in cache line when CPU
accessed them. When DMA uses the buffers again, the memory
can happened to be flushed by cache while DMA starts transfer.

So using API dma_sync_single_for_device and dma_sync_single_for_cpu
in DMA to ensure DMA coherence and CPU always access the correct
value. This fix the issue that the encrypted result periodically goes
wrong when doing performance test with OpenSSH.

Signed-off-by: Leilei Zhao <leilei.zhao@atmel.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Leilei Zhao and committed by
Herbert Xu
289b2623 8a10eb8d

+12 -4
+12 -4
drivers/crypto/atmel-aes.c
··· 315 315 316 316 dd->dma_size = length; 317 317 318 - if (!(dd->flags & AES_FLAGS_FAST)) { 319 - dma_sync_single_for_device(dd->dev, dma_addr_in, length, 320 - DMA_TO_DEVICE); 321 - } 318 + dma_sync_single_for_device(dd->dev, dma_addr_in, length, 319 + DMA_TO_DEVICE); 320 + dma_sync_single_for_device(dd->dev, dma_addr_out, length, 321 + DMA_FROM_DEVICE); 322 322 323 323 if (dd->flags & AES_FLAGS_CFB8) { 324 324 dd->dma_lch_in.dma_conf.dst_addr_width = ··· 391 391 { 392 392 dd->flags &= ~AES_FLAGS_DMA; 393 393 394 + dma_sync_single_for_cpu(dd->dev, dd->dma_addr_in, 395 + dd->dma_size, DMA_TO_DEVICE); 396 + dma_sync_single_for_cpu(dd->dev, dd->dma_addr_out, 397 + dd->dma_size, DMA_FROM_DEVICE); 398 + 394 399 /* use cache buffers */ 395 400 dd->nb_in_sg = atmel_aes_sg_length(dd->req, dd->in_sg); 396 401 if (!dd->nb_in_sg) ··· 464 459 dd->flags |= AES_FLAGS_FAST; 465 460 466 461 } else { 462 + dma_sync_single_for_cpu(dd->dev, dd->dma_addr_in, 463 + dd->dma_size, DMA_TO_DEVICE); 464 + 467 465 /* use cache buffers */ 468 466 count = atmel_aes_sg_copy(&dd->in_sg, &dd->in_offset, 469 467 dd->buf_in, dd->buflen, dd->total, 0);