Hi Peter, On Wednesday 03 May 2017 11:10:55 Peter Chen wrote: > 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. By the way, do you have access to a Xilinx Zynq-based board for testing ? If you do, what board is that ? And if you don't, what board would you use ? -- Regards, Laurent Pinchart -- 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