AnsweredAssumed Answered

Why does i.mx53 mxc_dma SDMA transfer keep going after I disable it?

Question asked by Ned Konz on Apr 10, 2013
Latest reply on Feb 24, 2014 by Yixing Kong

I'm using the mxc_dma functions to do large, recurring DMA transfers (up to 512K bytes in length) from a 16-bit wide FPGA device on the EIM in the i.mx53.

 

I'm using the latest on the imx_2.6.35_maintain branch from the FSL linux-2.6-imx.git repository.

 

The problem I'm having is that my DMA callback routine keeps getting called after the data should all have been transferred.

 

First I call mxc_dma_disable() to disable the channel.

Here's the 16 buffers I request using mxc_dma_config(dma_channel, req, 16, MXC_DMA_MODE_READ):

 

 

[  431.740287] req[0]: src_addr=0xf2000000 dst_addr=0x71f80000 num_of_bytes=32768

[  431.770668] req[1]: src_addr=0xf2000000 dst_addr=0x71f88000 num_of_bytes=32768

[  431.779915] req[2]: src_addr=0xf2000000 dst_addr=0x71f90000 num_of_bytes=32768

[  431.800661] req[3]: src_addr=0xf2000000 dst_addr=0x71f98000 num_of_bytes=32768

[  431.809910] req[4]: src_addr=0xf2000000 dst_addr=0x71fa0000 num_of_bytes=32768

[  431.840658] req[5]: src_addr=0xf2000000 dst_addr=0x71fa8000 num_of_bytes=32768

[  431.849906] req[6]: src_addr=0xf2000000 dst_addr=0x71fb0000 num_of_bytes=32768

[  431.872501] req[7]: src_addr=0xf2000000 dst_addr=0x71fb8000 num_of_bytes=32768

[  431.888411] req[8]: src_addr=0xf2000000 dst_addr=0x71fc0000 num_of_bytes=32768

[  431.908045] req[9]: src_addr=0xf2000000 dst_addr=0x71fc8000 num_of_bytes=32768

[  431.921424] req[10]: src_addr=0xf2000000 dst_addr=0x71fd0000 num_of_bytes=32768

[  431.932638] req[11]: src_addr=0xf2000000 dst_addr=0x71fd8000 num_of_bytes=32768

[  431.947103] req[12]: src_addr=0xf2000000 dst_addr=0x71fe0000 num_of_bytes=32768

[  431.958613] req[13]: src_addr=0xf2000000 dst_addr=0x71fe8000 num_of_bytes=32768

[  431.983398] req[14]: src_addr=0xf2000000 dst_addr=0x71ff0000 num_of_bytes=32768

[  432.003369] req[15]: src_addr=0xf2000000 dst_addr=0x71ff8000 num_of_bytes=32768

 

Then I call mxc_dma_callback_set(), and mxc_dma_enable().

 

In the callback, I check for the error_status, and update my remaining count, then print a debug message:

 

[  432.026618] dma_done_callback count=32768 remaining=491520

[  432.034276] dma_done_callback count=32768 remaining=458752

[  432.041906] dma_done_callback count=32768 remaining=425984

[  432.049443] dma_done_callback count=32768 remaining=393216

[  432.057022] dma_done_callback count=32768 remaining=360448

[  432.064600] dma_done_callback count=32768 remaining=327680

[  432.072174] dma_done_callback count=32768 remaining=294912

[  432.079705] dma_done_callback count=32768 remaining=262144

[  432.087275] dma_done_callback count=32768 remaining=229376

[  432.094836] dma_done_callback count=32768 remaining=196608

[  432.102397] dma_done_callback count=32768 remaining=163840

[  432.109916] dma_done_callback count=32768 remaining=131072

[  432.117473] dma_done_callback count=32768 remaining=98304

[  432.124946] dma_done_callback count=32768 remaining=65536

[  432.132422] dma_done_callback count=32768 remaining=32768

[  432.139911] dma_done_callback count=32768 remaining=0

[  432.147023] DMA complete

 

Now all the bytes I've wanted to have transferred should have been transferred.

I diagnose this, and then call mxc_dma_disable() on the channel.

Every time you see a "DMA complete" message, mxc_dma_disable() was called.

 

However, the callbacks keep coming. I call mxc_dma_disable() on each of them, but it doesn't help:

 

[  432.151811] dma_done_callback count=32768 remaining=-32768

[  432.159314] DMA complete

[  432.163966] dma_done_callback count=32768 remaining=-65536

[  432.171515] DMA complete

[  432.176085] dma_done_callback count=32768 remaining=-98304

[  432.183627] DMA complete

[  432.188197] dma_done_callback count=32768 remaining=-131072

[  432.195821] DMA complete

[  432.200392] dma_done_callback count=32768 remaining=-163840

[  432.208017] DMA complete

[  432.212627] dma_done_callback count=32768 remaining=-196608

[  432.220208] DMA complete

[  432.224818] dma_done_callback count=32768 remaining=-229376

[  432.232444] DMA complete

[  432.237015] dma_done_callback count=32768 remaining=-262144

[  432.244639] DMA complete

[  432.249209] dma_done_callback count=32768 remaining=-294912

[  432.256831] DMA complete

[  432.261443] dma_done_callback count=32768 remaining=-327680

[  432.269024] DMA complete

[  432.273634] dma_done_callback count=32768 remaining=-360448

[  432.281260] DMA complete

[  432.285831] dma_done_callback count=32768 remaining=-393216

[  432.293453] DMA complete

[  432.298024] dma_done_callback count=32768 remaining=-425984

[  432.305648] DMA complete

[  432.310218] dma_done_callback count=32768 remaining=-458752

[  432.317840] DMA complete

[  432.322453] dma_done_callback count=32768 remaining=-491520

[  432.330033] DMA complete

[  432.334641] dma_done_callback count=32768 remaining=-524288

[  432.342267] DMA complete

[  432.346837] dma_done_callback count=32768 remaining=-557056

[  432.354474] DMA complete

[  432.359047] dma_done_callback count=32768 remaining=-589824

[  432.366670] DMA complete

[  432.371285] dma_done_callback count=32768 remaining=-622592

[  432.378866] DMA complete

[  432.383474] dma_done_callback count=32768 remaining=-655360

[  432.391102] DMA complete

[  432.395671] dma_done_callback count=32768 remaining=-688128

[  432.403296] DMA complete

[  432.407865] dma_done_callback count=32768 remaining=-720896

[  432.415487] DMA complete

[  432.420055] dma_done_callback count=32768 remaining=-753664

[  432.427677] DMA complete

[  432.432289] dma_done_callback count=32768 remaining=-786432

[  432.439871] DMA complete

[  432.444477] dma_done_callback count=32768 remaining=-819200

[  432.452104] DMA complete

[  432.456675] dma_done_callback count=32768 remaining=-851968

[  432.464302] DMA complete

[  432.468873] dma_done_callback count=32768 remaining=-884736

[  432.476496] DMA complete

[  432.481110] dma_done_callback count=32768 remaining=-917504

[  432.488692] DMA complete

[  432.493300] dma_done_callback count=32768 remaining=-950272

[  432.500924] DMA complete

[  432.505494] dma_done_callback count=32768 remaining=-983040

[  432.513118] DMA complete

[  432.517688] dma_done_callback count=32768 remaining=-1015808

[  432.525399] DMA complete

[  432.529970] dma_done_callback count=32768 remaining=-1048576

[  432.537679] DMA complete

 

eventually, the completion is noticed by another part of my driver:

[  432.548644] DMA took 520 msec

 

Every transfer with a given transfer size does not necessarily get the same number of extra callbacks.

The count isn't always 32K, either (see below).

 

The same thing happens with fewer buffers (this was a 64K transfer):

 

[  140.417783] req[0]: src_addr=0xf2000000 dst_addr=0x71f80000 num_of_bytes=32768

[  140.427689] req[1]: src_addr=0xf2000000 dst_addr=0x71f88000 num_of_bytes=32768

[  140.441628] dma_done_callback count=32768 remaining=32768

[  140.449152] dma_done_callback count=32768 remaining=0

[  140.456219] DMA complete

[  140.461215] dma_done_callback count=8 remaining=-8

[  140.468012] DMA complete

[  140.472571] dma_done_callback count=32768 remaining=-32776

[  140.480062] DMA complete

[  140.484622] dma_done_callback count=32768 remaining=-65544

[  140.492113] DMA complete

[  140.496671] dma_done_callback count=32768 remaining=-98312

[  140.504162] DMA complete

[  140.508778] dma_done_callback count=32768 remaining=-131080

[  140.516359] DMA complete

[  140.520920] dma_done_callback count=32768 remaining=-163848

[  140.528497] DMA complete

[  140.533055] dma_done_callback count=32768 remaining=-196616

[  140.540633] DMA complete

[  140.552313] DMA took 110 msec

 

 

Changing the chunk size from 32K to 4K didn't help; it would get to 256K/512K of the transfer and hang.

 

Does anyone have an idea why this may be happening?

Outcomes