Showing results for 
Show  only  | Search instead for 
Did you mean: 
Registered: ‎08-24-2015

DMA issues on Xilinx Zynq for Mem to Mem Transfer




We're using the Zynq 7000 platform and trying to implement DMA using the DMAengine API to do Memory to Memory transfer. The code in our driver looks as following,


   dma_cap_set(DMA_MEMCPY, mask);
   dma_cap_set(DMA_PRIVATE, mask);

   rx_chan = dma_request_channel(mask, NULL, NULL);

   if (!rx_chan) {
    printk("\nZynqDmaDriver_ioctl: DMA Request Channel for Read failed");
    return -EIO;

   /* copy from user */
   cookie = dma_async_memcpy_buf_to_buf(rx_chan,
                    (void *)buffer_v_addr + dma_param->target_offset,
                    (void *)buffer_v_addr2 + dma_param->src_offset,


   /* to comply to debug checks */
   debug_dma_mapping_error(dev, buffer_p_addr);
   debug_dma_mapping_error(dev, buffer_p_addr2);
   while(dma_async_is_tx_complete(rx_chan, cookie, NULL, NULL) == DMA_IN_PROGRESS)
    dma_sync_wait(rx_chan, cookie);




Basically, we are trying to copy data from source memory (buffer_v_addr2 + offset) into destination memory (buffer_v_addr + offset). The two buffers (buffer_v_addr and buffer_v_addr2) were both allocated using dma_alloc_coherent() in the init function of the driver as below,


 buffer_v_addr = dma_alloc_coherent(dev, DMA_BUFFER_SIZE, &buffer_p_addr, GFP_KERNEL);
 buffer_v_addr2 = dma_alloc_coherent(dev, DMA_BUFFER_SIZE, &buffer_p_addr2, GFP_KERNEL);



In doing so and executing this code, we are getting the below error, 


WARNING: CPU: 0 PID: 0 at /opt/pkg/petalinux-v2014.2-final/components/linux-kernel/xlnx-3.14/lib/dma-debug.c:1140 check_unmap+0x73c/0x888()


dma-pl330 f8003000.ps7-dma: DMA-API: device driver failed to check map error[device address=0x0000000030068000] [size=4096 bytes] [mapped as page]


Modules linked in:

CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.14.2-xilinx #116

[<c0015658>] (unwind_backtrace) from [<c00119b4>] (show_stack+0x10/0x14)

[<c00119b4>] (show_stack) from [<c048ea18>] (dump_stack+0x8c/0xd0)

[<c048ea18>] (dump_stack) from [<c002295c>] (warn_slowpath_common+0x60/0x84)

[<c002295c>] (warn_slowpath_common) from [<c00229ac>] (warn_slowpath_fmt+0x2c/0x3c)

[<c00229ac>] (warn_slowpath_fmt) from [<c021844c>] (check_unmap+0x73c/0x888)

[<c021844c>] (check_unmap) from [<c021860c>] (debug_dma_unmap_page+0x74/0x80)

[<c021860c>] (debug_dma_unmap_page) from [<c023c82c>] (dmaengine_unmap+0x94/0x1bc)

[<c023c82c>] (dmaengine_unmap) from [<c023fab4>] (pl330_tasklet+0x448/0x510)

[<c023fab4>] (pl330_tasklet) from [<c002769c>] (tasklet_action+0x94/0xfc)

[<c002769c>] (tasklet_action) from [<c0026cc0>] (__do_softirq+0x120/0x278)

[<c0026cc0>] (__do_softirq) from [<c0027104>] (irq_exit+0x84/0xf4)

[<c0027104>] (irq_exit) from [<c000efa8>] (handle_IRQ+0x6c/0x90)

[<c000efa8>] (handle_IRQ) from [<c0008530>] (gic_handle_irq+0x3c/0x60)

[<c0008530>] (gic_handle_irq) from [<c0012444>] (__irq_svc+0x44/0x78)

Exception stack(0xc0da9f18 to 0xc0da9f60)

9f00:                                                       00000001 00000004

9f20: 00000000 c0db32b0 2ed84957 0000001b 00000000 eefd3448 2f1b232b 0000001b

9f40: c131c590 00000000 00000008 c0da9f60 c005ec48 c03987cc 20070013 ffffffff

[<c0012444>] (__irq_svc) from [<c03987cc>] (cpuidle_enter_state+0x54/0xe4)

[<c03987cc>] (cpuidle_enter_state) from [<c0398944>] (cpuidle_idle_call+0xe8/0x140)

[<c0398944>] (cpuidle_idle_call) from [<c000f2b0>] (arch_cpu_idle+0x8/0x3c)

[<c000f2b0>] (arch_cpu_idle) from [<c0068cec>] (cpu_startup_entry+0xc4/0x12c)

[<c0068cec>] (cpu_startup_entry) from [<c067bab4>] (start_kernel+0x324/0x380)

---[ end trace acc507b5e599e2b0 ]---

Mapped at:

[<c0218824>] debug_dma_map_page+0x48/0x12c

[<c023ca90>] dma_async_memcpy_pg_to_pg+0xc4/0x288

[<c023cca0>] dma_async_memcpy_buf_to_buf+0x4c/0x5c

[<c026664c>] ZynqDmaDriver_ioctl+0xb0/0x1c4

[<c00e3f54>] do_vfs_ioctl+0x55c/0x61c




As you can see in the code above, we added calls to debug_dma_mapping_error() to try checking for map error, however this still doesn't resolve the issue.


Would you have any suggestions on what we might be missing, or how to go about resolving the issue? Is the dma_async_memcpy_buf_to_buf() the correct API call to use for such Memory to Memory DMA transfer, or should we try another method?


Would appreciate any help!

Thanks in advance!



0 Kudos
0 Replies