Re: Chipidea USB controller hangs in peripheral mode under high memory bus pressure

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, May 02, 2017 at 03:07:03PM +0300, Laurent Pinchart wrote:
> Hello,
> 
> I ran into an issue with a Xilinx Zynq XC7Z010 system. The system acts as a 
> USB peripheral, using the UVC gadget driver.
> 
> When transferring high bandwidth data over USB in isochronous mode, complete 
> system freezes are occasionally noticed. The problem was traced to the 
> following code from _hardware_enqueue() in drivers/usb/chipidea/udc.c.
> 
> 		wmb();
> 		if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
> 			goto done;
> 		do {
> 			hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
> 			tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
> 		} while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
> 		hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
> 		if (tmp_stat)
> 			goto done;
> 
> 
> The do ... while loop loops forever, and as the function is called under a 
> spin_lock_irqsave(), the system doesn't appreciate. Adding a maximum number of 
> iterations to exit the loop is easy (I'll try to submit a patch after finding 
> the root cause of the problem). That fixes the system hang, but USB transfers 
> are still broken.
> 
> I've checked the code and unfortunately it seems to match the procedure 
> documented in the datasheet :-/
> 
> The MTBF is several hours, but running 'memtester -M100' 
> (http://pyropus.ca/software/memtester/) in parallel to UVC video transfer over 
> USB brings the MTBF to a few minutes. The problem thus seems to be related to 
> memory bus pressure.
> 
> Has anyone run into this problem before ? Is this a known issue ? I don't mind 
> getting my hands dirty debugging, but as I'm not familiar with the chipidea 
> USB controller pointers to what I should check in priority would be 
> appreciated.
> 

There was no one reported this problem before, but from the description,
it seems an IC issue which is triggered at high loading memory bus,
controller may not get time to visit memory at limited time. At 
Xilinx Zynq, its tx buffer is small, and less than 512 bytes (84bc70f94d81,
"usb: chipidea: add xilinx zynq platform data"), and your throughput
may be > (512 * 3) bytes/SoF, you can't use non-stream mode by reducing
max packet size. I think you may observe many under-run at bus analyzer
during the test.

As a workaround, you may try to do below things:

1. Link more TDs before the UVC run
2. Comment out the code, you are stuck in, it is only useful for protect 
last td status which is handling or will be handled soon by hardware.
		/*
		do {
			hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
			tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
		} while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
		hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
		if (tmp_stat)
			goto done;
		*/
3. If it can let your test run more time, try change code like below:

if (remaining_td_num > 2)
	don't do hardware check;
else
	do hardware check.


Besides, I can try your test if you could show me the detail test steps.

-- 

Best Regards,
Peter Chen
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux