This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MUSB controller hang when simultaneous RX and TX in DM368



We are facing MUSB controller hang when there is simultaneous RX and TX transfers. The MUSB controller will not hang when we disable the MUSB DMA. Is there a known issue on this is DM368/5 . 

Also I saw the TI document for DM365 where they claim MUSB hangs for audio playback and in CDC/RNDIS mode.

There are few links which claim there is such issue in MUSB controller,

e2e.ti.com/.../30198

  • This issue seems to solved after taking care of data corruption in DMA RX channel.
  • For the record,

    The DMA is not releasing the memory, by not clearing CPPI_OWN_SET, though interrupt occurs for RX and ARM9 proceeds to update the Buffer descriptors. ARM9, when trying to update buffer descriptor, checks if CPPI _OWN_SET is clear, if not skip updating. This causes corruption.

    Adding a check in cppi_rx_scan to wait for CPPI_OWN_SET is cleared, fixes this issue.
  • Hi Dwarakesh,

    Would you please show the changes you made to the driver cppi_dma.c?

    Thanks,
    Pete

  • Hi Pete,
    Sorry I don't have access to the code right now. Will check if I can get that code to share. What issue are u facing ?
  • Hi Dwarakesh,

    The problem we're facing is copying a file from one USB stick to another, resulting in this error and USB transfers stop working:

    musb_host_rx 1613: RX1 dma busy, csr 2220
    usb 1-1.1: reset high speed USB device using musb-hdrc and address 5

    I want to try your suggested change to see if it fixes the problem, but I'm not sure what code to change. Here is the code I see in the function cppi_rx_scan:

    	/* run through all completed BDs */
    	for (i = 0, safe2ack = musb_readl(&state->rx_complete, 0);
    			(safe2ack || completed) && bd && i < NUM_RXCHAN_BD;
    			i++, bd = bd->next) {
    		u16	len;
    
    		/* catch latest BD writes from CPPI */
    		rmb();
    		if (!completed && (bd->hw_options & CPPI_OWN_SET))
    			break;
    

    Should the change be:

    		if (!completed)
    			break;
    
    		while (bd->hw_options & CPPI_OWN_SET) {
    			cpu_relax();
    		}
    

    Is that correct?  (I have not tested it)

  • Hi Pete,

    That change seems to be fine. Please do try this and let me know.

  • Hi Pete,

    One change required. You need to check the  CPPI_OWN_SET bit before you manipulate the BDs. So it would be something like this :

    for(bd_check = bd; bd_check; bd_check = bd_check->next) {

    while (bd_check->hw_options & CPPI_OWN_SET) {

       cpu_relax();

    }

    }

    /* run through all completed BDs */

    for (i = 0, safe2ack = musb_readl(&state->rx_complete, 0);

           (safe2ack || completed) && bd && i < NUM_RXCHAN_BD;

           i++, bd = bd->next) {

       u16 len;

       /* catch latest BD writes from CPPI */

       rmb();

       if (!completed)

           break;

  • Thank you Dwarakesh, I have tried the code you posted, unfortunately I cannot get it to work.  The while loop checking the CPPI_OWN_SET bit loops indefinitely, and my system is hung.  That would indicate the DMA never clears the ownership bit.  In a multi-packet transfer, does the DMA require ack'ing current packets through rx_complete before it will clear ownership of the next packets on the queue?


    Is there any chance you can get the original changes you made to the code?

  • Hi Pete,

    Yeah, you can check for Ownership bit, after the completion is checked. Which means the first code you posted above can be tried.

    I still couldn't trace it, since i recently changed my machine. 

  • Thank you Dwarakesh, I think I have it working now.  I put in an extra "tries" option in case the DMA really does get stuck so that my system doesn't hang.  Here is the code I am using:

    		/* catch latest BD writes from CPPI */
    		rmb();
    		if (!completed) {
    			int tries = 0;
    			while (bd->hw_options & CPPI_OWN_SET) {
    				if (++tries >= 1000) break;
    				cpu_relax();
    				rmb();
    			}
    			if (bd->hw_options & CPPI_OWN_SET) {
    				DBG(0, "CPPI_OWN_SET timeout - DMA stuck?\n");
    				break;
    			}
    		}
    

    I was able to successfully copy a 4GB file several times from one USB stick to another, so that is a definite improvement!

  • Hi Pete,

    Glad to know. Congrats.