dwc2 does not detect host disconnect in device mode with rpi cm4
Describe the bug
The dwc2 driver does not detect that the rpi cm4 otg port was disconnected from host. This port is in peripheral mode.
I only see that we get an early suspend interrupt in dwc2_hsotg_irq: dwc2 fe980000.usb: GINTSTS_ErlySusp, otherwise we don't get any interrupts that indicate that usb was disconnected.
This cause issue because when we plug one of our product based on the cm4 into another similar or identical product based on the cm4, it complains about the fact some endpoints are not disabled. Note we use a renesas usb to pcie bridge in our board and maybe it is more picky about that for some reason. Jul 06 17:26:56 inogeni-cam230 kernel: usb 1-1: ERROR: Endpoint drop flag = 0, add flag = 1, and endpoint is not disabled. Jul 06 17:26:56 inogeni-cam230 kernel: xhci_hcd 0000:01:00.0: xhci_fixup_endpoint: Configure endpoint failed: -22
The end result is that our uvc gadget does not work and we can't get video frames.
dwc2 driver should detect straight away that usb was disconnected.
There is a piece of code that look for some interupts flags in dwc2_hsotg_irq():
if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET))
We should either get inside that if condition, or detect the usb disconnect through other means.
What does the documentation for the otg of the rpi cm4 says about detecting disconnect in peripheral mode?
Steps to reproduce the behaviour
Create a uvc gadget on a rpi cm4 and notice that the uvc disconnect event is not raised until a new host is connected. This is because the disable function (uvc_function_disable) of the uvc gadget is not called at disconnection time, but when reconfiguring because we reconnected to the host. @disable: (REQUIRED) Indicates the function should be disabled. Reasons
- include host resetting or reconfiguring the gadget, and disconnection
It would also help to enable debug logs from dwc2 driver, especially the file gadget.c which would report if it detected a disconnect/suspend etc.
Device (s)
Raspberry Pi CM4
System
Yocto Kirkstone with linux 5.15.
Logs
No response
Additional context
No response
Possible explanation: https://github.com/raspberrypi/linux/pull/3151#issuecomment-1146570510
Reply from Synopsys about the problem: Re: usb: dwc2: Detecting cable disconnection in OTG mode?
FWIW, one trick to check connection status is to check /sys/class/udc/*/current_speed for relevant port: it reports UNKNOWN when disconnected.
FWIW, one trick to check connection status is to check
/sys/class/udc/*/current_speedfor relevant port: it reportsUNKNOWNwhen disconnected.
hmm for me on a Pi Zero W it seems to still just show high-speed regardless or connect or disconnect (similarly is_selfpowered remains 1 and state remains configured.
Seeing the same problem with RPi4. /sys/class/udc/*/current_speed is expected UNKNOWN on startup with no host connected. Once the host is connected, switches to high-speed as expected. Then, if the device is removed, it remains high-speed.
As a workaround, I found that I can look at /sys/bus/gadget/devices/gadget.0/suspended, and only pay attention to current_speed, etc if the device is not suspended.
Oooh @JeremyBCD that's a very interesting little nugget you've found there! That looks like a usable workaround - the switch of current_speed from UNKNOWN to high-speed indicates initial connection and then thereafter use suspended=1 to identify USB disconnection and 0 to determine reconnection!
@EDIflyer Yes. Good catch there checking against UNKNOWN, because suspended will be false on startup when there is no connection.
@JeremyBCD just to confirm now up and running using those two folders and able to detect connection/disconnection and trigger appropriate action as a result. Annoyingly watchdog can't monitor /sys folders so just having to poll instead but at least it does the trick!