08-16-2016 01:48 AM - edited 08-16-2016 10:23 AM
My experiments have shown, that to generate the interrupt (and call the completion callback), the AXI DMA must receive the tlast='1' during the transfer of particular dma_async_tx_descriptor.
It means, that if the AXI Stream data source transfers data in packets of dynamically changing length, I must allocate the descriptor for the maximum possible length of the packet, and after the callback is called, I should check the number of the really transferred bytes.
Unfortunately, I can't see any official method to do it.
There was a patch proposed adding the "transferred" field to the dma_async_tx_descriptor, however it was finally rejected, as it should be possible to check the number of not transferred bytes in the dma_tx_state structure accessible via dmaengine_tx_status. The final conclusion was, that the documentation should be updated to confirm, that the "residue" field in the "dma_tx_state" may be used to check the number of non-transferred bytes even after the transfer is completed.
However in the current Xilinx flavor of the Linux kernel, there is still information, that the residue field should be used only when the transfer is in the DMA_IN_PROGRESS or DMA_PAUSED state.
So the question is. How the driver should check the number of bytes transferred in a transfer described by the dma_async_tx_descriptor and finished by tlast='1' ?
With best regards,
08-16-2016 03:49 AM - edited 08-16-2016 04:24 AM
In the "AXI DMA Debug Guide" I have found the information (page 2):
If tlast occurrs before the number of bytes set in the length register, the SG engine updates the length
register with the actual number of bytes transferred and then starts working on the next descriptor as
the next packet is coming in.
There is even API defined to obtain the information about the actual number of transferred bytes:
The actual transfer length for receive could be smaller than the requested transfer length. The hardware sets the actual transfer length in the completed BD. The API to retrieve the actual transfer length is XAxiDma_GetActualLength().
However the above apply to non-Linux API.
Is there equivalent function to get the actual number of transferred bytes available for Linux driver?
I have checked the approach with "dmaengine_tx_status" described in the previous post, and it seems that after the transfer is completed, the "residue" field in the "tx_state" is set to 0 regardless of the number of actually transferred bytes.
08-16-2016 04:50 AM
08-17-2016 02:06 AM
I have tried to add the patch shown below, so that the residue is calculated even for completed transfer, but unfortunately it doesn't work. Probably at the moment when the callback is executed, the list of segments for the descriptor is already empty.
diff --git a/linux-xilinx-v2016.2/drivers/dma/xilinx/xilinx_dma.c b/linux-xilinx-v2016.2/drivers/dma/xilinx/xilinx_dma.c index 47c1641..99cb039 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -558,7 +558,7 @@ static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan, u32 residue = 0; ret = dma_cookie_status(dchan, cookie, txstate); - if (ret == DMA_COMPLETE || !txstate) + if (!txstate) return ret; desc = list_last_entry(&chan->active_list,
08-19-2016 05:09 AM
I discussed this before in a xilinx issue on github, but unfortunately all issues seem to have been taken offline.
warning: dead link: https://github.com/Xilinx/linux-xlnx/issues/20
I would have to search if I still have the patch that I proposed there.
08-21-2016 03:57 PM
I'd be glad to see your patches.
However it seems, that the problem is not Xilinx specific.
It is rather related to the whole dmaengine infrastructure.
08-26-2016 09:19 AM
11-01-2016 05:04 AM
Have you found answer for question about transfer length?
01-26-2018 12:59 PM
Has this really not been fixed yet? This severely limits the real-world use of the Linux AXI DMA driver.
01-31-2018 02:55 AM - edited 01-31-2018 11:58 AM
As I can see, in 2017.4 still the length is filled only when the status is not DMA_COMPLETE: https://github.com/Xilinx/linux-xlnx/blob/xilinx-v2017.4/drivers/dma/xilinx/xilinx_dma.c#L955
As a workaround, I have finally developed a solution based on DataMover controlled by FIFO.
It is described in
The presentation is available at
Sources of that particular DMA solution are available in https://github.com/wzab/Z-turn-examples/tree/master/axi_dma_prj2
02-27-2018 02:30 PM
I ran into this same issue with AXI DMA in streaming mode where the size of messages aren't known in advance.
I modified xilinx_dma.c to populate the residue field of xilinx_dma_chan when xilinx_dma_complete_descriptor() is called. Then, when xilinx_dma_tx_status is called, I return that value (or, in the event of non-complete DMA, the calculated result from adding up the remaining bytes in the active segments, as it was doing previously).
This seems to work well for my use case. Would this sort of a patch be more likely to be accepted since it only modifies xilinx_dma.c, rather than modifying the dma engine framework? Is this something that Xilinx is interested in?
02-28-2018 03:06 AM
02-28-2018 07:03 AM
Are you sure, that this solution works correctly for chained descriptors? I tried that approach, and experienced the problem that the engine was already initialized for the next transfer, and the information about the number of transferred bytes was already lost when my complete handler was executed.
I knew there was something I was missing. I don't see how this can work for chained descriptors or even multiple descriptors in flight.
I'm storing residue in the residue field of the xilinx_dma_chan struct in each call to xilinx_dma_complete_descriptor(). I believe that will catch every completed descriptor, but I'm only storing a single value - not one for each descriptor. That works fine when you don't start another transaction until you've called xilinx_dma_tx_status() to check the completion state (and retrieve residue) for the most recently completed one. But like you said, that's not going to happen if there's already another descriptor in flight.
I think in order to support chained descriptors I would need to store the residue of each completed descriptor. That's tricky because as far as I can tell, there's no persistent storage for descriptors other than what is accessed via cookie using dma_cookie_status(). And now that I'm looking into that mechanism, it doesn't have persistent storage either - it just does a <= comparison of the cookie itself to the current cookie, assuming that it's complete if the dma engine went on to the next one.