summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorRadu Alexe <radu.alexe@nxp.com>2017-10-09 14:29:11 (GMT)
committerXie Xiaobo <xiaobo.xie@nxp.com>2017-10-12 03:37:27 (GMT)
commit445358482f0e9a1d30c8fd36c2eae581812e086d (patch)
tree215c897512cbdcb1583e5829da2ccc6f8f1e2e11 /drivers/dma
parent072da00ac095a99e27ad40c966a5044fb3798b78 (diff)
downloadlinux-445358482f0e9a1d30c8fd36c2eae581812e086d.tar.xz
dma: caam: fix desc error when data length is over 130815 bytes
The CAAM DMA shared descriptor states that if a buffer is large enough it is broken into chunks of maximum 65280 bytes (DMA_MAX_DATA_CHUNK) and for each chunk a transfer request is issued. The length of the chunk for each iteration should be therefore computed as min(DMA_MAX_DATA_CHUNK, data_rem_length), where data_rem_length is the length of the chunks that still remain to be send. Currently the logic of the shared descriptor is broken: on every iteration the chunk length is instead computed as max(max_chunk_size, data_rem_length). This produces an error for the first chunk when buffer data length is greater than max_chunk_size + max_allowed_chunk_size = 65280 + 65535 = 130815. Signed-off-by: Radu Alexe <radu.alexe@nxp.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/caam_dma.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/dma/caam_dma.c b/drivers/dma/caam_dma.c
index 0d837ad..cc9f9cf 100644
--- a/drivers/dma/caam_dma.c
+++ b/drivers/dma/caam_dma.c
@@ -25,6 +25,14 @@
#define DESC_DMA_MEMCPY_LEN ((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN) / \
CAAM_CMD_SZ)
+/* This is max chunk size of a DMA transfer. If a buffer is larger than this
+ * value it is internally broken into chunks of max CAAM_DMA_CHUNK_SIZE bytes
+ * and for each chunk a DMA transfer request is issued.
+ * This value is the largest number on 16 bits that is a multiple of 256 bytes
+ * (the largest configurable CAAM DMA burst size).
+ */
+#define CAAM_DMA_CHUNK_SIZE 65280
+
struct caam_dma_sh_desc {
u32 desc[DESC_DMA_MEMCPY_LEN] ____cacheline_aligned;
dma_addr_t desc_dma;
@@ -345,8 +353,11 @@ static void set_caam_dma_desc(u32 *desc)
/* dma shared descriptor */
init_sh_desc(desc, HDR_SHARE_NEVER | (1 << HDR_START_IDX_SHIFT));
- /* REG0 = SEQINLEN - 65472 */
- append_math_sub_imm_u32(desc, REG0, SEQINLEN, IMM, 65472);
+ /* REG1 = CAAM_DMA_CHUNK_SIZE */
+ append_math_add_imm_u32(desc, REG1, ZERO, IMM, CAAM_DMA_CHUNK_SIZE);
+
+ /* REG0 = SEQINLEN - CAAM_DMA_CHUNK_SIZE */
+ append_math_sub_imm_u32(desc, REG0, SEQINLEN, IMM, CAAM_DMA_CHUNK_SIZE);
/* if (REG0 > 0)
* jmp to LABEL1
@@ -354,17 +365,17 @@ static void set_caam_dma_desc(u32 *desc)
jmp_cmd = append_jump(desc, JUMP_TEST_INVALL | JUMP_COND_MATH_N |
JUMP_COND_MATH_Z);
- /* REG0 = SEQINLEN */
- append_math_sub(desc, REG0, SEQINLEN, ZERO, CAAM_CMD_SZ);
+ /* REG1 = SEQINLEN */
+ append_math_sub(desc, REG1, SEQINLEN, ZERO, CAAM_CMD_SZ);
/* LABEL1 */
set_jump_tgt_here(desc, jmp_cmd);
- /* VARSEQINLEN = REG0 */
- append_math_add(desc, VARSEQINLEN, REG0, ZERO, CAAM_CMD_SZ);
+ /* VARSEQINLEN = REG1 */
+ append_math_add(desc, VARSEQINLEN, REG1, ZERO, CAAM_CMD_SZ);
- /* VARSEQOUTLEN = REG0 */
- append_math_add(desc, VARSEQOUTLEN, REG0, ZERO, CAAM_CMD_SZ);
+ /* VARSEQOUTLEN = REG1 */
+ append_math_add(desc, VARSEQOUTLEN, REG1, ZERO, CAAM_CMD_SZ);
/* do FIFO STORE */
append_seq_fifo_store(desc, 0, FIFOST_TYPE_METADATA | LDST_VLF);