From: Dongwoo Lee Date: Wed, 26 Feb 2020 10:39:04 +0000 (+0900) Subject: usb: dwc2: Defer forcing peripheral mode X-Git-Tag: accepted/tizen/unified/20240422.153132~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F47%2F308447%2F2;p=platform%2Fkernel%2Flinux-rpi.git usb: dwc2: Defer forcing peripheral mode dwc2 forces the mode as following dr_mode when it is finally determined. In the case of peripheral mode, however, this causes the notification to host without any preparation about gadget driver. In host, hcd requests device descriptor for enumeration, but it does never get response. See log below: usb 2-2: new high-speed USB device number 6 using xhci_hcd usb 2-2: device descriptor read/64, error -110 usb 2-2: device descriptor read/64, error -110 usb 2-2: new high-speed USB device number 7 using xhci_hcd usb 2-2: device descriptor read/64, error -110 usb 2-2: device descriptor read/64, error -110 usb usb2-port2: attempt power cycle usb 2-2: new high-speed USB device number 8 using xhci_hcd xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command usb 2-2: device not accepting address 8, error -62 usb 2-2: new high-speed USB device number 9 using xhci_hcd xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command xhci_hcd 0000:00:14.0: Timeout while waiting for setup device command usb 2-2: device not accepting address 9, error -62 usb usb2-port2: unable to enumerate USB device Even worse, all ports on host can get disabled at least xhci case in this situation. To prevent this, forcing peripheral mode will be defered until the gadget driver is prepared. Signed-off-by: Dongwoo Lee (cherry picked from commit 9507385cb797a12f278e73b9cb298ba73f120fd5) Signed-off-by: Jaehoon Chung Change-Id: Ic24f1a36c9ccfd9b571cd4d6eff5cbc3da9082b1 --- diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 81f6843..f755d73 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -581,7 +581,12 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) break; case USB_DR_MODE_PERIPHERAL: - dwc2_force_mode(hsotg, false); + /* + * To prevent early notification to host without any + * preparation about device descriptor, forcing mode + * is defered until gadget driver is ready. + */ + /* dwc2_force_mode(hsotg, false); */ break; case USB_DR_MODE_OTG: dwc2_clear_force_mode(hsotg); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 68292c2..dc999fd 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -4550,6 +4550,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, hsotg->gadget.speed = USB_SPEED_UNKNOWN; if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) { + dwc2_force_mode(hsotg, false); ret = dwc2_lowlevel_hw_enable(hsotg); if (ret) goto err; diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index d0508a0..5e0f85c 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -864,7 +864,8 @@ static void dwc2_get_dev_hwparams(struct dwc2_hsotg *hsotg) if (hsotg->dr_mode == USB_DR_MODE_HOST) return; - dwc2_force_mode(hsotg, false); + if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) + dwc2_force_mode(hsotg, false); gnptxfsiz = dwc2_readl(hsotg, GNPTXFSIZ);