dwc3 Disable Compliance Mode
Subsystems (2)
Hi Felipe,
I hope you are doing well. My team and I are frequently experiencing an issue with the dwc3 in our CherryTrail SoC where we encounter an LFPS Polling timeout while our device is being enumerated.
We configured the dwc3 as an ethernet gadget using configfs and the ecm and RNDIS functions. The dwc3 transitions to U3 after configuration as expected. Only once we connect our device to a USB host do we see the link state transition to Polling. We are assuming LFPS Polling times out because the link_state file in debugfs shows the link has transitioned to compliance mode only after entering LFPS.Polling, and we recently learned that compliance mode is triggered by a timeout during LFPS.Polling.
This issue is not 100% reproducible, but is occuring rather frequently at the moment. We're unsure of the root cause of the issue as well. One culprit might be the USB SuperSpeed Redriver we use in our design.
We would like to disable compliance mode in the meantime to allow other team members to continue developing and testing USB device mode features while we dig into the root cause of the issue. Is there a proper way to disable compliance mode entirely?
If not, is there some mechanism we could implement to reset the dwc3 when we enter compliance mode? I attempted some sort of mechanism to reset the link state, but it does not seem to help the issue. I've attached my patch and the trace events for my attempted workaround to this email. My initial approach was to transition the link from Compliance -> SS.Disabled -> Rx.Detect when we detect we've entered compliance mode. The traces show that the dwc3 just enters LFPS.Polling and subsequently enters compliance mode, despite the link being reset.
Do you have any ideas on how we might work around compliance mode in the meantime?
Thanks in advance for your input!
Cheers,
Rob Weber
drivers/usb/dwc3/core.c +90 -0
@@ -48,6 +48,91 @@#include "debug.h" #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000/* ms */ +#define COMP_MODE_RECOVERY_MSECS 2000 + +static void compliance_mode_recovery (unsigned long arg) +{ +struct dwc3 *dwc3; +int state; +unsigned long flags; + + dwc3 = (struct dwc3 *) arg; + +dwc3_trace (trace_dwc3_core,"Tick! Checking for compliance mode\n" ); + +// Read link state + +spin_lock_irqsave (&dwc3->lock, flags); + state =dwc3_gadget_get_link_state (dwc3); + +// if in compliance mode or loopback mode, we need to revert the link to normal operation +// Couple options for resetting link state +// * setting link state to RESET - NOT WORKING +// * setting linsk state to SS disabled or RX detect +// * try a hard reset (we're afraid we will have to reconfigure the gadget with this method) +if (state ==DWC3_LINK_STATE_CMPLY || state ==DWC3_LINK_STATE_LPBK ) { +dwc3_trace (trace_dwc3_core,"Compliance Mode detected. Attempting recovery routine\n" ); +printk ("dwc3 compliance mode detected. Attempting recovery\n" ); + + state =dwc3_gadget_set_link_state (dwc3,DWC3_LINK_STATE_SS_DIS ); +if (state <0 ) { +dwc3_trace (trace_dwc3_core,"Compliance -> SS.Disabled transition failed: %d (Timed out?)\n" , state); +printk ("Compliance -> SS.Disabled transition failed: %d (Timed out?)\n" , state); + + } + +udelay (1000 ); + state =dwc3_gadget_set_link_state (dwc3,DWC3_LINK_STATE_RX_DET ); +if (state <0 ) { +dwc3_trace (trace_dwc3_core,"SS.Disabled -> Rx.Detect transition failed: %d (Timed out?)\n" , state); +printk ("SS.Disabled -> Rx.Detect transition failed: %d (Timed out?)\n" , state); + } + } + +spin_unlock_irqrestore (&dwc3->lock, flags); +/* +struct *xhci; +struct usb_hcd *hcd; +u32 temp; +int i; + +xhci = (struct xhci_hcd *)arg; + +for (i = 0; i < xhci->num_usb3_ports; i++) { +temp = xhci_readl(xhci, xhci->usb3_ports[i]); +if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { +xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", +i + 1); +xhci_dbg(xhci, "Attempting Recovery routine!\n"); +hcd = xhci->shared_hcd; + +if (hcd->state == HC_STATE_SUSPENDED) +usb_hcd_resume_root_hub(hcd); + +usb_hcd_poll_rh_status(hcd); +} +} + +if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) +mod_timer(&xhci->comp_mode_recovery_timer, +jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +*/ +/* TODO: figure out when we don't need to keep re-enabling this timer anymore */ +mod_timer (&dwc3->comp_mode_recovery_timer, + jiffies +msecs_to_jiffies (COMP_MODE_RECOVERY_MSECS )); +} + +static void compliance_mode_recovery_timer_init (struct dwc3 *dwc3) +{ +setup_timer (&dwc3->comp_mode_recovery_timer, + compliance_mode_recovery, (unsigned long )dwc3); + + dwc3->comp_mode_recovery_timer.expires = jiffies + +msecs_to_jiffies (COMP_MODE_RECOVERY_MSECS ); + +add_timer (&dwc3->comp_mode_recovery_timer); +dwc3_trace (trace_dwc3_core,"Compliance Mode Recovery Timer Initialized.\n" ); +}/** * dwc3_get_dr_mode - Validates and sets dr_mode
@@ -612,6 +697,8 @@ static void dwc3_core_exit(struct dwc3 *dwc)usb_phy_set_suspend (dwc->usb3_phy,1 );phy_power_off (dwc->usb2_generic_phy);phy_power_off (dwc->usb3_generic_phy); + +del_timer_sync (&dwc->comp_mode_recovery_timer); }/**
@@ -786,6 +873,9 @@ static int dwc3_core_init(struct dwc3 *dwc)dwc3_writel (dwc->regs,DWC3_GUCTL2 , reg); } +/* Enable timer to check for and recover from entering compliance mode */ +compliance_mode_recovery_timer_init (dwc); +return 0 ; err4:
drivers/usb/dwc3/core.h +2 -0
@@ -979,6 +979,8 @@ struct dwc3 { unsigned tx_de_emphasis_quirk:1; unsigned tx_de_emphasis:2; + +struct timer_list comp_mode_recovery_timer; };/* -------------------------------------------------------------------------- */
# tracer: nop
#
# entries-in-buffer/entries-written: 220/220 #P:4
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
<idle>-0 [003] ..s1 178.444339: dwc3_core: Tick! Checking for compliance mode
<idle>-0 [003] d.s2 178.444352: dwc3_core: Compliance Mode detected. Attempting recovery routine
irq/23-dwc3-1115 [002] d..1 178.445380: dwc3_event: event (00140301): Link Change [SS.Disabled]
irq/23-dwc3-1115 [002] d..1 178.445826: dwc3_event: event (00150301): Link Change [RX.Detect]
irq/23-dwc3-1115 [002] d..1 178.445832: dwc3_event: event (00170301): Link Change [Polling]
<idle>-0 [003] ..s1 180.492293: dwc3_core: Tick! Checking for compliance mode
<idle>-0 [003] d.s2 180.492306: dwc3_core: Compliance Mode detected. Attempting recovery routine
irq/23-dwc3-1115 [002] d..1 180.493333: dwc3_event: event (00140301): Link Change [SS.Disabled]
irq/23-dwc3-1115 [002] d..1 180.493636: dwc3_event: event (00150301): Link Change [RX.Detect]
irq/23-dwc3-1115 [002] d..1 180.493641: dwc3_event: event (00170301): Link Change [Polling]
<idle>-0 [003] ..s1 182.540350: dwc3_core: Tick! Checking for compliance mode
<idle>-0 [003] d.s2 182.540362: dwc3_core: Compliance Mode detected. Attempting recovery routine
irq/23-dwc3-1115 [002] d..1 182.541392: dwc3_event: event (00140301): Link Change [SS.Disabled]
irq/23-dwc3-1115 [002] d..1 182.541976: dwc3_event: event (00150301): Link Change [RX.Detect]
irq/23-dwc3-1115 [002] d..1 182.541982: dwc3_event: event (00170301): Link Change [Polling]
<idle>-0 [003] .Ns1 184.588211: dwc3_core: Tick! Checking for compliance mode
<idle>-0 [003] dNs2 184.588232: dwc3_core: Compliance Mode detected. Attempting recovery routineHi Rob,
Quoted 15 lines · Rob Weber
Hi Felipe,
I hope you are doing well. My team and I are frequently experiencing an issue with the dwc3 in our CherryTrail SoC where we encounter an LFPS Polling timeout while our device is being enumerated.
We configured the dwc3 as an ethernet gadget using configfs and the ecm and RNDIS functions. The dwc3 transitions to U3 after configuration as expected. Only once we connect our device to a USB host do we see the link state transition to Polling. We are assuming LFPS Polling times out because the
link_statefile in debugfs shows the link has transitioned to compliance mode only after entering LFPS.Polling, and we recently learned that compliance mode is triggered by a timeout during LFPS.Polling.
Quoted 8 lines
This issue is not 100% reproducible, but is occuring rather frequently at the moment. We're unsure of the root cause of the issue as well. One culprit might be the USB SuperSpeed Redriver we use in our design.
We would like to disable compliance mode in the meantime to allow other team members to continue developing and testing USB device mode features while we dig into the root cause of the issue. Is there a proper way to disable compliance mode entirely?
That's not something that can be done, unfortunately.
Quoted 8 lines
If not, is there some mechanism we could implement to reset the dwc3 when we enter compliance mode? I attempted some sort of mechanism to reset the link state, but it does not seem to help the issue. I've attached my patch and the trace events for my attempted workaround to this email. My initial approach was to transition the link from Compliance -> SS.Disabled -> Rx.Detect when we detect we've entered compliance mode. The traces show that the dwc3 just enters LFPS.Polling and subsequently enters compliance mode, despite the link being reset.
I think you would have to go through the entire Power On Reset sequence, but that's likely to be flakey.
Quoted 2 lines
Do you have any ideas on how we might work around compliance mode in the meantime?
We have a few quirk flags that may help. snps,u2exit_lfps_quirk comes to mind, but I suggest trying a few of them and see if any helps.
All flags are described inDocumentation/devicetree/bindings/usb/dwc3.txt
Quoted 28 lines
/* -------------------------------------------------------------------------- */
# tracer: nop
#
# entries-in-buffer/entries-written: 220/220 #P:4
#
# _-----=> irqs-off
# / _----=> need-resched# | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | <idle>-0 [003] ..s1 178.444339: dwc3_core: Tick! Checking for compliance mode <idle>-0 [003] d.s2 178.444352: dwc3_core: Compliance Mode detected. Attempting recovery routine irq/23-dwc3-1115 [002] d..1 178.445380: dwc3_event: event (00140301): Link Change [SS.Disabled] irq/23-dwc3-1115 [002] d..1 178.445826: dwc3_event: event (00150301): Link Change [RX.Detect] irq/23-dwc3-1115 [002] d..1 178.445832: dwc3_event: event (00170301): Link Change [Polling] <idle>-0 [003] ..s1 180.492293: dwc3_core: Tick! Checking for compliance mode <idle>-0 [003] d.s2 180.492306: dwc3_core: Compliance Mode detected. Attempting recovery routine irq/23-dwc3-1115 [002] d..1 180.493333: dwc3_event: event (00140301): Link Change [SS.Disabled] irq/23-dwc3-1115 [002] d..1 180.493636: dwc3_event: event (00150301): Link Change [RX.Detect] irq/23-dwc3-1115 [002] d..1 180.493641: dwc3_event: event (00170301): Link Change [Polling] <idle>-0 [003] ..s1 182.540350: dwc3_core: Tick! Checking for compliance mode
Quoted 8 lines
<idle>-0 [003] d.s2 182.540362: dwc3_core: Compliance Mode detected. Attempting recovery routine
irq/23-dwc3-1115 [002] d..1 182.541392: dwc3_event: event (00140301): Link Change [SS.Disabled]
irq/23-dwc3-1115 [002] d..1 182.541976: dwc3_event: event (00150301): Link Change [RX.Detect]
irq/23-dwc3-1115 [002] d..1 182.541982: dwc3_event: event (00170301): Link Change [Polling]
<idle>-0 [003] .Ns1 184.588211: dwc3_core: Tick! Checking for compliance mode
<idle>-0 [003] dNs2 184.588232: dwc3_core: Compliance Mode detected. Attempting recovery routineDon't we get an interrupt for Compliance mode entry?
cheers
Signature · 1 line
balbi
Hello Felipe,
Quoted 18 lines · Felipe Balbi
Quoted 17 lines · Rob Weber
I hope you are doing well. My team and I are frequently experiencing an issue with the dwc3 in our CherryTrail SoC where we encounter an LFPS Polling timeout while our device is being enumerated.
We configured the dwc3 as an ethernet gadget using configfs and the ecm and RNDIS functions. The dwc3 transitions to U3 after configuration as expected. Only once we connect our device to a USB host do we see the link state transition to Polling. We are assuming LFPS Polling times out because the
link_statefile in debugfs shows the link has transitioned to compliance mode only after entering LFPS.Polling, and we recently learned that compliance mode is triggered by a timeout during LFPS.Polling.This issue is not 100% reproducible, but is occuring rather frequently at the moment. We're unsure of the root cause of the issue as well. One culprit might be the USB SuperSpeed Redriver we use in our design.
Quoted 6 lines
Quoted 4 lines
We would like to disable compliance mode in the meantime to allow other team members to continue developing and testing USB device mode features while we dig into the root cause of the issue. Is there a proper way to disable compliance mode entirely?
That's not something that can be done, unfortunately.
Okay, understood.
Quoted 10 lines
Quoted 9 lines
If not, is there some mechanism we could implement to reset the dwc3 when we enter compliance mode? I attempted some sort of mechanism to reset the link state, but it does not seem to help the issue. I've attached my patch and the trace events for my attempted workaround to this email. My initial approach was to transition the link from Compliance -> SS.Disabled -> Rx.Detect when we detect we've entered compliance mode. The traces show that the dwc3 just enters LFPS.Polling and subsequently enters compliance mode, despite the link being reset.
Quoted 2 lines
I think you would have to go through the entire Power On Reset sequence, but that's likely to be flakey.
Okay, good to know. I am not confident in this approach as well because of the state management / recovery we might have to perform.
I wanted to explain our goal a little bit more in depth in case some other apprach might come to mind. Our product supports 3 ways in which the user can work with the USB port: Host mode, Mass Storage Mode, and Ethernet Mode. Host mode is pretty straightforward. Users will generally work with USB mass storage devices and USB-Ethernet adapters in host mode. Mass storage mode exposes an internal user data partition using f_mass_storage and configfs so the user can connect our product to their host computer for backing up data. Ethernet uses the f_ecm and f_rndis functions creating an ethernet connection with USB hosts, particularly mobile devices, to interact with our mobile applications and servers through a wired connection.
We control this functionality through a userspace application written in Go that creates the gadget/function configuration in configfs. Given this background information, are there any approaches that come to mind, such as reconfiguring the gadget? Thanks in advance for your input.
Quoted 8 lines
Quoted 2 lines
Do you have any ideas on how we might work around compliance mode in the meantime?
We have a few quirk flags that may help. snps,u2exit_lfps_quirk comes to mind, but I suggest trying a few of them and see if any helps.
All flags are described in
Documentation/devicetree/bindings/usb/dwc3.txt
Great, thank you. I will give these a shot and let you know if I have further questions.
Quoted 30 lines
Quoted 30 lines
/* -------------------------------------------------------------------------- */
# tracer: nop
#
# entries-in-buffer/entries-written: 220/220 #P:4
#
# _-----=> irqs-off
# / _----=> need-resched# | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | <idle>-0 [003] ..s1 178.444339: dwc3_core: Tick! Checking for compliance mode <idle>-0 [003] d.s2 178.444352: dwc3_core: Compliance Mode detected. Attempting recovery routine irq/23-dwc3-1115 [002] d..1 178.445380: dwc3_event: event (00140301): Link Change [SS.Disabled] irq/23-dwc3-1115 [002] d..1 178.445826: dwc3_event: event (00150301): Link Change [RX.Detect] irq/23-dwc3-1115 [002] d..1 178.445832: dwc3_event: event (00170301): Link Change [Polling] <idle>-0 [003] ..s1 180.492293: dwc3_core: Tick! Checking for compliance mode <idle>-0 [003] d.s2 180.492306: dwc3_core: Compliance Mode detected. Attempting recovery routine irq/23-dwc3-1115 [002] d..1 180.493333: dwc3_event: event (00140301): Link Change [SS.Disabled] irq/23-dwc3-1115 [002] d..1 180.493636: dwc3_event: event (00150301): Link Change [RX.Detect] irq/23-dwc3-1115 [002] d..1 180.493641: dwc3_event: event (00170301): Link Change [Polling] <idle>-0 [003] ..s1 182.540350: dwc3_core: Tick! Checking for compliance mode <idle>-0 [003] d.s2 182.540362: dwc3_core: Compliance Mode detected. Attempting recovery routine
Quoted 8 lines
Quoted 6 lines
irq/23-dwc3-1115 [002] d..1 182.541392: dwc3_event: event (00140301): Link Change [SS.Disabled] irq/23-dwc3-1115 [002] d..1 182.541976: dwc3_event: event (00150301): Link Change [RX.Detect] irq/23-dwc3-1115 [002] d..1 182.541982: dwc3_event: event (00170301): Link Change [Polling] <idle>-0 [003] .Ns1 184.588211: dwc3_core: Tick! Checking for compliance mode<idle>-0 [003] dNs2 184.588232:
dwc3_core: Compliance Mode detected. Attempting recovery routineDon't we get an interrupt for Compliance mode entry?
Not that I've seen, surprisingly. My compliance mode recovery mechanism looks for both compliance mode and loopback mode, neither of which I have ever seen in the link state change events.
Cheers,
Rob Weber
Hi,
Quoted 27 lines · Rob Weber
Quoted 11 lines
Quoted 8 lines
If not, is there some mechanism we could implement to reset the dwc3 when we enter compliance mode? I attempted some sort of mechanism to reset the link state, but it does not seem to help the issue. I've attached my patch and the trace events for my attempted workaround to this email. My initial approach was to transition the link from Compliance -> SS.Disabled -> Rx.Detect when we detect we've entered compliance mode. The traces show that the dwc3 just enters LFPS.Polling and subsequently enters compliance mode, despite the link being reset.
I think you would have to go through the entire Power On Reset sequence, but that's likely to be flakey.
Okay, good to know. I am not confident in this approach as well because of the state management / recovery we might have to perform.
I wanted to explain our goal a little bit more in depth in case some other apprach might come to mind. Our product supports 3 ways in which the user can work with the USB port: Host mode, Mass Storage Mode, and Ethernet Mode. Host mode is pretty straightforward. Users will generally work with USB mass storage devices and USB-Ethernet adapters in host mode. Mass storage mode exposes an internal user data partition using
f_mass_storageand configfs so the user can connect our product to their host computer for backing up data. Ethernet uses thef_ecmandf_rndisfunctions creating an ethernet connection with USB hosts, particularly mobile devices, to interact with our mobile applications and servers through a wired connection.
Quoted 4 lines
We control this functionality through a userspace application written in Go that creates the gadget/function configuration in configfs. Given this background information, are there any approaches that come to mind, such as reconfiguring the gadget? Thanks in advance for your input.
Not really, if it goes into compliance mode, the only way to get it out of there is with a power-on reset. You can't even change link state back to U0 as that will just tell dwc3 to walk through the compliance patterns :-p
I think our best bet is understanding why we're transitioning to compliance and preventing that.
One question comes to mind: Does this happen *only* with the ethernet gadget? Does it happen with *all* hosts or just a particular host?
Any chance you can capture a full session with both CATC or Beagle 5000 analyzer and dwc3 tracepoints and send it to me?
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
<idle>-0 [003] dNs2 184.588232:
dwc3_core: Compliance Mode detected. Attempting recovery routineDon't we get an interrupt for Compliance mode entry?
Not that I've seen, surprisingly. My compliance mode recovery mechanism looks for both compliance mode and loopback mode, neither of which I have ever seen in the link state change events.
That's odd, I would expect it to still give the event. Oh well, moving on :-)
Signature · 1 line
balbi
Hi,
Quoted 24 lines · Rob Weber
Quoted 5 lines
I think our best bet is understanding why we're transitioning to compliance and preventing that.
One question comes to mind: Does this happen *only* with the ethernet gadget? Does it happen with *all* hosts or just a particular host?
This issue does not just occur with the ethernet gadget, it also occurs with the mass storage mode gadget. I'm guessing that this issue is not gadget-specific. This seem to happen with all hosts as well. I tested with my Dell laptop, an iPad Pro, a Macbook Pro, and a Lenovo laptop running windows.
This issue was 100% reproducible on 2 units I was testing last week when I sent you the initial email. These two boards are not particularly trustworthy data points: one board was from the first lot of units in mass production, and there are known issues with that manufacturing process that might be interfering with my testing. The other unit has gone through several rounds of modifications while tuning the de-emphasis and voltage swing of the SS Redriver on our design. We were frequently swapping 0201 resistors around this component, so I'm wondering if it was damaged? We also replaced the SoC's crystal oscillator during debugging at one point. This is connected to the CherryTrail's
ICLK_OSCINandICLK_OSCOUTpins.
Quoted 8 lines
I have since completed the userspace library for controlling our USB role and I started testing on newer boards that were recently manufactured. So far these issues are not reproducible. Mass storage mdoe and ethernet mode are both working well with no compliance mode issues. My current objective is to gather more data with several more units to see if this is a problem we're experiencing across all units, or if I just happened to be testing on two faulty units. I will keep you updated on the status of this issue after collecting more data.
Please do, if it happens again, let's start looking at known errata for the redriver. We need to understand what's causing LFPS timeout.
Quoted 8 lines
Quoted 2 lines
Any chance you can capture a full session with both CATC or Beagle 5000 analyzer and dwc3 tracepoints and send it to me?
Sure thing! Please find the beagle 5000 analyzer data and dwc3 tracepoints attached. I'm still learning how to read the protocol analyzer captures, so I'm not sure if my interpretation is correct, but it looked like a bunch of unknown packets were being transmitted by the device during LFPS Polling. I'm curious to know your interpretation.
Yeah, it just times out polling because of these unknown packets. I wonder if we can get away from it by disabling scrambling. There's a bit in dwc3 for that:
#define DWC3_GCTL_DISSCRAMBLE BIT(3)
Can you apply this hack below and see if it makes any difference?
drivers/usb/dwc3/core.c +1 -0
@@ -771,6 +771,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) reg |=DWC3_GCTL_DISSCRAMBLE ; else reg &= ~DWC3_GCTL_DISSCRAMBLE; + reg |=DWC3_GCTL_DISSCRAMBLE ;if (dwc->u2exit_lfps_quirk) reg |=DWC3_GCTL_U2EXIT_LFPS ;
Note that you should NOT run your product with this bit set (meaning, without scrambling disabled) as that will have an effect in EMI. Still, it may help understand if the redriver is getting confused with the scrambling or not.
Best
Signature · 1 line
balbi