AnsweredAssumed Answered

USB Data Mismatch

Question asked by Dooty Seyed Mohamed on Mar 20, 2014

Dear All,

 

Using iMx6x and software release LTIB 4.1.0 Version.

 

Test Setup:

========

iMx6x is the Host and its connected to USB based contoller device is the USB device side.

From Host Side, Linux CDC-ACM driver is used. This driver will communicate between USB host and USB based controller device.

 

Test Application:

============

A USB Loopback Test App is used:

 

On the Host side, controller device is opened and 1016 bytes of data (1 to 1016) are wrtten into it and the controller device will recieve it and then the received data is written back.

The Host side will receive those data. Finally received data's are compared with the transferred data's.

 

The above  process runs in a loop of count 10000000.

 

Issue:

=====

Issue occurs only in Multi-core selected in kernel not in Single-core.

 

The above process fails once in 500000 times(i.e the Received data is not same as transferred data)

 

To find where the issue resides, we used USB Analyzer on both Host and Device Endpoints.

We saw that whatever data Host Sends is exactly received by the Device side.

But we found that Host Side itself sends wrong data. As a result Device side also recives the same wrong data.

We found that the issue  is occurs on the cdc-acm driver.

Attached Error Log.

 

Reason:

======

We have been able to isolate the problem in CDC_ACM driver. It seems that the receive buffers of the cdc_acm driver contain stale data (data from a previous read ) about once in  every 500000 ... 8000000 counts.

we also found a work around for this problem, by calling a "dma_sync_single_for_device" on the buffer allocated by usb_alloc_coherent fixes this problem.

We investigate and find that "dma_sync_single_for_device" API flushes the cache. But Why buffer goes to cache memory, as "usb_alloc_coherent" API gives a un-cacheable buffer.

 

Investigate the issue:

================

In cdc-acm driver, to allocate DMA coherent memory usb_alloc_coherent is used.  But when checked through function flow, the usb_alloc_coherent wrapper calls the dma_pool_alloc API  which internally calls dma_alloc_coherent API.

 

The dma_alloc_coherent API will allocate DMA coherent memory if available and if failed to allocate DMA coherent memory, it allocates generic DMA memory without coherence.

 

On our investigation we have found that dma_mem condition is failing in the dma_alloc_from_coherent API, so the DMA generic memory region (non- coherent) is allocated by __dma_alloc API.

 

We also figured out why dma_mem condition is failing. we came to know dma_declare_coherent_memory API is not declared. 

This dma_declare_coherent_memory API will try to allocate memory from the coherent area.

This is the reason why "dma_mem"  condition returns NULL in dma_alloc_from_coherent API.

 

Can you provide us how the declaration (dma_declare_coherent_memory) can be done for USB device in linux kernel in order to allocate the memory from the coherent region successfully.

 

Looking forward to your reply.

 

Thanks in advance.

 

Regards,

Dooty.

Original Attachment has been moved to: error_log.txt.zip

Outcomes