Re: USB hot-plug not working (ASUS TP301UA-C4028T)
Hi! I've managed to build the patched kernel on OBS, install the package and boot! \o/ And I can confirm that the patch indeed fix the issue! The kernel was booted without the usb.autosuspend=-1 option, of course. Thank you guys! Cheers, Pierre. Le jeudi 13 octobre 2016, 17:11:46 NZDT Alan Stern a écrit : > On Fri, 14 Oct 2016, Pierre de Villemereuil wrote: > > Hi! > > > > I've branched the kernel package on the OpenSUSE Build Server, I'll > > try to apply the patch there (this ought to be cleanest method). > > > > Starting from the root of the kernel tarball, the patch should be > > applied to drivers/pci/pci.c, am I right? > > You just cd to the top directory of the kernel source, and do > > patch -p1 > where "filename" is the contents of the email message containing the > patch. Or if you want, since the patch is so small, you can simply > edit the file by hand to add in the new lines. > > Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Problem with OHCI controller dying in 4.8
Alan, I apologize, but git itself is still over my head, and I don't know how to get bisect. I download the kernel tar.xz files and tell Debian's make-kpkg utility to compile them for me. But for what it's worth, the patch from Bryan Paluch that changes IO_WATCHDOG_DELAY in drivers/usb/host/ohci-hcd.c from 250 to 275 msecs either fixed or masked the problem (no problem scanning with the patch applied). This would perhaps lend support to his theory about timing changes having an unintended effect on the ohci drivers. Quoting Mr. Paluch: >> I suspect that the new timer wheel based timers in 4.8 have exposed a bug >> in the ohci driver. Before the io watchdog timer was set to 250 with 20 msecs >> of slack time. This is more than likely just a hacky work around [...] Sure enough, I hacked, and it worked around. Thanks, Joe On Fri, Oct 14, 2016 at 5:11 PM, Alan Stern wrote: > On Fri, 14 Oct 2016, Benjamin Staton wrote: > >> The Issue: Scanning (with xsane 0.999) while using kernel 4.8 (I >> tested 4.8 rc1, rc5, rc7, rc8, and 4.8.1) fails when the scanner >> becomes disconnected from the USB bus. Every time. >> >> Scanning (with xsane 0.999) while using kernel 4.7.0 or earlier 4's >> works without fail. >> >> My scanner is known to lsusb as "Bus 006 Device 002: ID 04a9:2206 >> Canon, Inc. CanoScan N650U/N656U" and to Xsane as "Canon CanoScan >> N650U/N flatbed scanner [plustek:libusb:006:002]". >> >> Relevant lines from /var/log/kern.log at the time of the disconnect: >> Oct 14 13:30:00 quiz kernel: [ 167.746817] ohci-pci :00:12.0: >> HcDoneHead not written back; disabled >> Oct 14 13:30:00 quiz kernel: [ 167.746829] ohci-pci :00:12.0: HC >> died; cleaning up >> Oct 14 13:30:00 quiz kernel: [ 167.746916] usb 6-1: USB disconnect, >> device number 2 >> Oct 14 13:30:00 quiz kernel: [ 167.747618] usb 6-3: USB disconnect, >> device number 3 >> Oct 14 13:30:00 quiz kernel: [ 167.747624] usb 6-3.2: USB disconnect, >> device number 4 >> Oct 14 13:30:00 quiz kernel: [ 167.803283] usb 6-3.3: USB disconnect, >> device number 5 >> >> This is on an asrock 970M Pro3 motherboard w/AMD FX-8300 CPU and 32GB >> RAM running debian testing/9. Kernels built from kernel.org without >> further patching. >> >> Apologies for posting to wrong place (bugzilla) and happy to provide more >> info. > > Can you run git bisect between 4.7 and 4.8-rc1 to find the particular > commit that introduced this problem? There haven't been any > significant changes to the ohci-hcd driver during that period. > > Alan Stern > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re:
Brian, Working - I appreciate this. I applied this mini-patch to kernel 4.8.1 and confirm that after a few test scans, I now have no problem with the USB Canon scanner. Also seems to have cleared up a puzzling no-input problem I was having with a cheap no-brand USB keyboard/video/mouse switch under 4.8.1. Thanks, Joe On Fri, Oct 14, 2016 at 3:52 PM, Bryan Paluch wrote: > I've been experiencing similar issues with usb audio headsets. There is an > issue for ubuntu 16.10 here > https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1630063 . > > I was able to fix the issue by changing the IO_WATCHDOG_DELAY in ohci-hcd.c > from 250 msec to 275 msec. I suspect that the new timer wheel based timers > in 4.8 have exposed a bug in the ohci driver. Before the io watchdog timer > was set to 250 with 20 msecs of slack time. This is more than likely just a > hacky work around but I'm able to use my usb headphones now. Here's my diff > > diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c > index 1700908..86612ac 100644 > --- a/drivers/usb/host/ohci-hcd.c > +++ b/drivers/usb/host/ohci-hcd.c > @@ -72,7 +72,7 @@ > static const char hcd_name [] = "ohci_hcd"; > > #define STATECHANGE_DELAY msecs_to_jiffies(300) > -#define IO_WATCHDOG_DELAY msecs_to_jiffies(250) > +#define IO_WATCHDOG_DELAY msecs_to_jiffies(275) > > #include "ohci.h" > #include "pci-quirks.h" -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Problem with OHCI controller dying in 4.8
On Fri, 14 Oct 2016, Benjamin Staton wrote: > The Issue: Scanning (with xsane 0.999) while using kernel 4.8 (I > tested 4.8 rc1, rc5, rc7, rc8, and 4.8.1) fails when the scanner > becomes disconnected from the USB bus. Every time. > > Scanning (with xsane 0.999) while using kernel 4.7.0 or earlier 4's > works without fail. > > My scanner is known to lsusb as "Bus 006 Device 002: ID 04a9:2206 > Canon, Inc. CanoScan N650U/N656U" and to Xsane as "Canon CanoScan > N650U/N flatbed scanner [plustek:libusb:006:002]". > > Relevant lines from /var/log/kern.log at the time of the disconnect: > Oct 14 13:30:00 quiz kernel: [ 167.746817] ohci-pci :00:12.0: > HcDoneHead not written back; disabled > Oct 14 13:30:00 quiz kernel: [ 167.746829] ohci-pci :00:12.0: HC > died; cleaning up > Oct 14 13:30:00 quiz kernel: [ 167.746916] usb 6-1: USB disconnect, > device number 2 > Oct 14 13:30:00 quiz kernel: [ 167.747618] usb 6-3: USB disconnect, > device number 3 > Oct 14 13:30:00 quiz kernel: [ 167.747624] usb 6-3.2: USB disconnect, > device number 4 > Oct 14 13:30:00 quiz kernel: [ 167.803283] usb 6-3.3: USB disconnect, > device number 5 > > This is on an asrock 970M Pro3 motherboard w/AMD FX-8300 CPU and 32GB > RAM running debian testing/9. Kernels built from kernel.org without > further patching. > > Apologies for posting to wrong place (bugzilla) and happy to provide more > info. Can you run git bisect between 4.7 and 4.8-rc1 to find the particular commit that introduced this problem? There haven't been any significant changes to the ohci-hcd driver during that period. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 50/57] [media] zr364xx: don't break long lines
Due to the 80-cols checkpatch warnings, several strings were broken into multiple lines. This is not considered a good practice anymore, as it makes harder to grep for strings at the source code. So, join those continuation lines. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/zr364xx/zr364xx.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index cc128db85723..3950708cbb32 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -633,8 +633,7 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, } else { if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) { dev_info(&cam->udev->dev, -"%s: buffer (%d bytes) too small to hold " -"frame data. Discarding frame data.\n", +"%s: buffer (%d bytes) too small to hold frame data. Discarding frame data.\n", __func__, MAX_FRAME_SIZE); } else { pdest += frm->cur_size; @@ -1373,8 +1372,7 @@ static int zr364xx_board_init(struct zr364xx_camera *cam) &cam->buffer.frame[i], i, cam->buffer.frame[i].lpvbits); if (cam->buffer.frame[i].lpvbits == NULL) { - printk(KERN_INFO KBUILD_MODNAME ": out of memory. " - "Using less frames\n"); + printk(KERN_INFO KBUILD_MODNAME ": out of memory. Using less frames\n"); break; } } -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] net: asix: Avoid looping when the device does not respond
From: Guenter Roeck Date: Thu, 13 Oct 2016 16:43:16 -0700 > Check answers from USB stack and avoid re-sending the request > multiple times if the device does not respond. > > This fixes the following problem, observed with a probably flaky adapter. ... > Since the USB timeout is 5 seconds, and the operation is retried 30 times, > this results in ... > Signed-off-by: Guenter Roeck Applied, thanks. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Problem with musb dma packet
Hi, On Thu, Oct 06, 2016 at 02:45:30PM +, Andrew Goodbody wrote: > I am trying to investigate an issue on a TI Sitara CPU, AM3352 with > the musb USB controller. > > The scenario is that a device has been in use and working correctly. > The device is an Android device and is presenting as an MTP device. AM3352 musb is the host or device? Sounds like it is the host. > That first session of use is finished and the port is reset but the > device is not unplugged, so enumeration and configuration starts again How this happened? How do you control the host reset the device but not re-enumerate it? > the next time it is needed. The transfers over EP0 using PIO all > proceed as expected. The problem is the first bulk packet sent to EP1, > which also happens to be the first dma packet. USBMON shows this > packet as being sent. However a hardware analyser does not show this > packet on the wire and of course there is no ACK either. Looking at > the debug info from the musb driver I can see the dma being started > and then the callback being called. MUSB_TXCSR_TXPKTRDY remains set as > does MUSB_TXCSR_TXFIFONOTEMPTY so nothing else happens. The TXCSR > register is 0x3403. The code is waiting for MUSB_TXCSR_TXPKTRDY to be > cleared but that will not happen until an ACK is received. It just > seems that the controller is not putting the packet onto the wire for > some reason. Sounds to me that the cppi teamdown before/during bus reset was not complete, so the channels are not in the ready state for next transfers. I don't have a better way to debug it, but you have to ensure the teardown sequence does follow that in the normal device detach. If the issue still happens, you would have to dump the cppi registers to see why the channels are in the wrong state. > > This is on 4.5.1. > > I would welcome some pointers on how to proceed to debug this or else > any information on possible applicable errata and workarounds for > this. It is more like software problem to me. Good luck. Regards, -Bin. > > Thanks, > Andrew -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC][PATCH 2/2] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220
On 10/13/2016 4:36 PM, John Stultz wrote: > From: Chen Yu > > The Hi6220's usb controller is limited in that it does not > automatically autonegotiate the usb speed. Thus it requires a > quirk so that we can manually negotiate the best usb speed for > the attached device. Hi, Could you expand more on this by explaining what exactly is the limitation and the workaround? [snip] > +/* > + * HPRT0_SPD_HIGH_SPEED: high speed > + * HPRT0_SPD_FULL_SPEED: full speed > + */ > +static void dwc2_change_bus_speed(struct usb_hcd *hcd, int speed) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (hsotg->core_params->speed == speed) > + return; > + > + hsotg->core_params->speed = speed; > + queue_work(hsotg->wq_otg, &hsotg->wf_otg); > +} > + > +static int dwc2_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (!hsotg->change_speed_quirk) > + return 1; > + > + hsotg->device_count++; Why do you need to track the device count? > + dev_info(hsotg->dev, "Device count is %u after alloc dev\n", > + hsotg->device_count); > + > + return 1; > +} > + > +static void dwc2_free_dev(struct usb_hcd *hcd, struct usb_device *udev) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (!hsotg->change_speed_quirk) > + return; > + > + if (hsotg->device_count) > + hsotg->device_count--; > + > + dev_info(hsotg->dev, "Device count is %u after free dev\n", > + hsotg->device_count); > + > + if (hsotg->device_count == 1 && udev->parent && > + udev->parent->speed > USB_SPEED_UNKNOWN && > + udev->parent->speed < USB_SPEED_HIGH) { > + dev_info(hsotg->dev, "Set speed to default high-speed\n"); > + dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED); > + } > +} > + > +static int dwc2_reset_device(struct usb_hcd *hcd, struct usb_device *udev) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (!hsotg->change_speed_quirk) > + return 0; > + > + if (udev->speed == USB_SPEED_HIGH) { > + dev_info(hsotg->dev, "Set speed to high-speed\n"); > + dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED); > + } else if (udev->speed == USB_SPEED_FULL > + || udev->speed == USB_SPEED_LOW) { > + dev_info(hsotg->dev, "Set speed to full-speed\n"); > + dwc2_change_bus_speed(hcd, HPRT0_SPD_FULL_SPEED); > + } It seems you are reinitializing the core every time a device is reset and the udev->speed does not match the core_param speed. But how is the udev->speed being set correctly if the hw cannot negotiate the speed in the first place? Also should it be for every device? What about if a device gets plugged in behind a hub? I don't think you want to execute this code in that case. This should only affect devices plugged into the root hub, correct? And the hsotg controller only has one root hub port. It seems things could be simplified a bit. Regards, John -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[no subject]
The Issue: Scanning (with xsane 0.999) while using kernel 4.8 (I tested 4.8 rc1, rc5, rc7, rc8, and 4.8.1) fails when the scanner becomes disconnected from the USB bus. Every time. Scanning (with xsane 0.999) while using kernel 4.7.0 or earlier 4's works without fail. My scanner is known to lsusb as "Bus 006 Device 002: ID 04a9:2206 Canon, Inc. CanoScan N650U/N656U" and to Xsane as "Canon CanoScan N650U/N flatbed scanner [plustek:libusb:006:002]". Relevant lines from /var/log/kern.log at the time of the disconnect: Oct 14 13:30:00 quiz kernel: [ 167.746817] ohci-pci :00:12.0: HcDoneHead not written back; disabled Oct 14 13:30:00 quiz kernel: [ 167.746829] ohci-pci :00:12.0: HC died; cleaning up Oct 14 13:30:00 quiz kernel: [ 167.746916] usb 6-1: USB disconnect, device number 2 Oct 14 13:30:00 quiz kernel: [ 167.747618] usb 6-3: USB disconnect, device number 3 Oct 14 13:30:00 quiz kernel: [ 167.747624] usb 6-3.2: USB disconnect, device number 4 Oct 14 13:30:00 quiz kernel: [ 167.803283] usb 6-3.3: USB disconnect, device number 5 This is on an asrock 970M Pro3 motherboard w/AMD FX-8300 CPU and 32GB RAM running debian testing/9. Kernels built from kernel.org without further patching. Apologies for posting to wrong place (bugzilla) and happy to provide more info. Thanks, Joe -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/2] Fixes for two more musb regressions
Hi, On Fri, Sep 30, 2016 at 11:10:08AM -0700, Tony Lindgren wrote: > Hi all, > > Looks like we have two more regressions caused by my attempts > to make musb PM simpler. As it's very close to the merge window > opening, these are against current Linux next. > > Once reviewed, tested and merged to the mainline kernel we can > request these to be included also into v4.8.y kernel. Maybe Bin > can tag these as cc stable v4.8 already when applying. > > Regards, > > Tony > > Tony Lindgren (2): > usb: musb: Fix hardirq-safe hardirq-unsafe lock order error > usb: musb: Call pm_runtime from musb_gadget_queue Applied. Regards, -Bin. > > drivers/usb/musb/musb_gadget.c | 4 > drivers/usb/musb/omap2430.c| 7 ++- > 2 files changed, 6 insertions(+), 5 deletions(-) > > -- > 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC][PATCH 2/2] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220
On Fri, Oct 14, 2016 at 8:00 AM, Rob Herring wrote: > On Thu, Oct 13, 2016 at 6:29 PM, John Stultz wrote: >> From: Chen Yu >> >> The Hi6220's usb controller is limited in that it does not >> automatically autonegotiate the usb speed. Thus it requires a >> quirk so that we can manually negotiate the best usb speed for >> the attached device. >> >> Cc: Wei Xu >> Cc: Guodong Xu >> Cc: Amit Pundir >> Cc: Rob Herring >> Cc: Mark Rutland >> Cc: John Youn >> Cc: Douglas Anderson >> Cc: Greg Kroah-Hartman >> Cc: linux-usb@vger.kernel.org >> Signed-off-by: Chen Yu >> Signed-off-by: John Stultz >> --- >> arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 1 + >> drivers/usb/dwc2/core.h | 7 +++ >> drivers/usb/dwc2/hcd.c| 75 >> +++ >> drivers/usb/dwc2/platform.c | 3 ++ >> 4 files changed, 86 insertions(+) >> [snip] >> diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c >> index 8e1728b..21c328b 100644 >> --- a/drivers/usb/dwc2/platform.c >> +++ b/drivers/usb/dwc2/platform.c >> @@ -585,6 +585,9 @@ static int dwc2_driver_probe(struct platform_device *dev) >> dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n", >> (unsigned long)res->start, hsotg->regs); >> >> + hsotg->change_speed_quirk = device_property_read_bool(&dev->dev, >> + "hi6220,change_speed_quirk"); > > Can't this be determined from the hi6220's compatible string? Ah. Good suggestion! I'm moving the quirk field to the core_params. Should avoid any dts or binding changes. thanks -john -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RESEND PATCH] usb: dwc2: Add msleep for host-only
From: Heiko Stuebner Although a host-only controller should not have any associated delay, some rockchip SOC platforms will not show the correct host-values of registers until after a delay. So add a 50 ms sleep when in host-only mode. Signed-off-by: John Youn Signed-off-by: Heiko Stuebner --- Resend as the original did not seem to make it to the list. Hi Felipe, Can you queue this in your fixes tree when you get a chance. It fixes a regression that got into 4.9-rc1. Thanks, John drivers/usb/dwc2/core.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index fa9b26b..4c0fa0b 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -463,9 +463,18 @@ static void dwc2_clear_force_mode(struct dwc2_hsotg *hsotg) */ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg) { + bool ret; + switch (hsotg->dr_mode) { case USB_DR_MODE_HOST: - dwc2_force_mode(hsotg, true); + ret = dwc2_force_mode(hsotg, true); + /* +* NOTE: This is required for some rockchip soc based +* platforms on their host-only dwc2. +*/ + if (!ret) + msleep(50); + break; case USB_DR_MODE_PERIPHERAL: dwc2_force_mode(hsotg, false); -- 2.10.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC][PATCH 2/2] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220
On Thu, Oct 13, 2016 at 6:29 PM, John Stultz wrote: > From: Chen Yu > > The Hi6220's usb controller is limited in that it does not > automatically autonegotiate the usb speed. Thus it requires a > quirk so that we can manually negotiate the best usb speed for > the attached device. > > Cc: Wei Xu > Cc: Guodong Xu > Cc: Amit Pundir > Cc: Rob Herring > Cc: Mark Rutland > Cc: John Youn > Cc: Douglas Anderson > Cc: Greg Kroah-Hartman > Cc: linux-usb@vger.kernel.org > Signed-off-by: Chen Yu > Signed-off-by: John Stultz > --- > arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 1 + > drivers/usb/dwc2/core.h | 7 +++ > drivers/usb/dwc2/hcd.c| 75 > +++ > drivers/usb/dwc2/platform.c | 3 ++ > 4 files changed, 86 insertions(+) > > diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi > b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi > index 17839db..2c8f435 100644 > --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi > +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi > @@ -752,6 +752,7 @@ > g-np-tx-fifo-size = <128>; > g-tx-fifo-size = <128 128 128 128 128 128>; > interrupts = <0 77 0x4>; > + hi6220,change_speed_quirk; > }; > > mailbox: mailbox@f751 { > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h > index 2a21a04..24fea73 100644 > --- a/drivers/usb/dwc2/core.h > +++ b/drivers/usb/dwc2/core.h > @@ -823,6 +823,10 @@ struct dwc2_hregs_backup { > * @frame_list_sz: Frame list size > * @desc_gen_cache: Kmem cache for generic descriptors > * @desc_hsisoc_cache: Kmem cache for hs isochronous descriptors > + * @change_speed_quirk: Change speed configuration to DWC2_SPEED_PARAM_FULL > + * while full&low speed device connect. And change speed > + * back to DWC2_SPEED_PARAM_HIGH while device is gone. > + * @device_count: Number of devices connect to root hub > * > * These are for peripheral mode: > * > @@ -951,6 +955,9 @@ struct dwc2_hsotg { > struct kmem_cache *desc_gen_cache; > struct kmem_cache *desc_hsisoc_cache; > > + int change_speed_quirk; > + unsigned int device_count; > + > #ifdef DEBUG > u32 frrem_samples; > u64 frrem_accum; > diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c > index b374e60..663033e 100644 > --- a/drivers/usb/dwc2/hcd.c > +++ b/drivers/usb/dwc2/hcd.c > @@ -4868,6 +4868,75 @@ static void _dwc2_hcd_clear_tt_buffer_complete(struct > usb_hcd *hcd, > spin_unlock_irqrestore(&hsotg->lock, flags); > } > > +/* > + * HPRT0_SPD_HIGH_SPEED: high speed > + * HPRT0_SPD_FULL_SPEED: full speed > + */ > +static void dwc2_change_bus_speed(struct usb_hcd *hcd, int speed) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (hsotg->core_params->speed == speed) > + return; > + > + hsotg->core_params->speed = speed; > + queue_work(hsotg->wq_otg, &hsotg->wf_otg); > +} > + > +static int dwc2_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (!hsotg->change_speed_quirk) > + return 1; > + > + hsotg->device_count++; > + dev_info(hsotg->dev, "Device count is %u after alloc dev\n", > + hsotg->device_count); > + > + return 1; > +} > + > +static void dwc2_free_dev(struct usb_hcd *hcd, struct usb_device *udev) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (!hsotg->change_speed_quirk) > + return; > + > + if (hsotg->device_count) > + hsotg->device_count--; > + > + dev_info(hsotg->dev, "Device count is %u after free dev\n", > + hsotg->device_count); > + > + if (hsotg->device_count == 1 && udev->parent && > + udev->parent->speed > USB_SPEED_UNKNOWN && > + udev->parent->speed < USB_SPEED_HIGH) { > + dev_info(hsotg->dev, "Set speed to default high-speed\n"); > + dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED); > + } > +} > + > +static int dwc2_reset_device(struct usb_hcd *hcd, struct usb_device *udev) > +{ > + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); > + > + if (!hsotg->change_speed_quirk) > + return 0; > + > + if (udev->speed == USB_SPEED_HIGH) { > + dev_info(hsotg->dev, "Set speed to high-speed\n"); > + dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED); > + } else if (udev->speed == USB_SPEED_FULL > + || udev->speed == USB_SPEED_LOW) { > + dev_info(hsotg->dev, "Set speed to full-speed\n"); > + dwc2_change_bus_speed(hcd, HPRT0_SPD_FULL_SPEED); > + } > + > + return
Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq
On Fri, 14 Oct 2016, Felipe Balbi wrote: > argh, we have nested spinlocks :-( Well, we shouldn't call > usb_ep_disable() with locks held AFAICR. So the following should be > enough: > > diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c > index 919d7d1b611c..2e9359c58eb9 100644 > --- a/drivers/usb/gadget/composite.c > +++ b/drivers/usb/gadget/composite.c > @@ -732,8 +732,10 @@ static void reset_config(struct usb_composite_dev *cdev) > DBG(cdev, "reset config\n"); > > list_for_each_entry(f, &cdev->config->functions, list) { > + spin_unlock_irq(&cdev->lock); > if (f->disable) > f->disable(f); > + spin_lock_irq(&cdev->lock); > > bitmap_zero(f->endpoints, 32); > } > > Alan, do you remember if we have a requirement for not holding locks > when calling usb_ep_disable()? I can't find Documentation about it, but > history shows me that usb_ep_disable() was called without locks and IRQs > enabled. Do you think we should update documentation about this? I don't think there is any requirement for interrupts to be enabled when usb_ep_disable() runs. At least, a quick check shows that both net2280 and dummy-hcd use spin_lock_irqsave() rather than spin_lock() in their disable routines. Holding locks is a different story. It should be okay for a gadget driver to hold one of its own locks when disabling an endpoint (which means that the gadget's disable routine shouldn't wait for a concurrent giveback to finish), but we might want to avoid holding a lock in the composite core. Although even that might be okay -- I can't think of any reason why a udc driver would need to call back into the composite core while disabling an endpoint. It should be a pretty self-contained operation. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: All USB devices stop working. Their reconnect not helps
On Fri, Oct 14, 2016 at 06:53:29PM +0500, Михаил Гаврилов wrote: > [ 16.685607] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 16.893766] usb 2-5.4: Device not responding to setup address. > [ 17.098457] usb 2-5.4: device not accepting address 6, error -71 > [ 17.162458] usb 1-9.1.6: new full-speed USB device number 8 using xhci_hcd > [ 17.242470] usb 1-9.1.6: New USB device found, idVendor=046d, > idProduct=c52b > [ 17.242476] usb 1-9.1.6: New USB device strings: Mfr=1, Product=2, > SerialNumber=0 > [ 17.242479] usb 1-9.1.6: Product: USB Receiver > [ 17.242482] usb 1-9.1.6: Manufacturer: Logitech Hm, not good. > [ 30.678097] usb 2-5.4: Device not responding to setup address. > [ 30.882771] usb 2-5.4: device not accepting address 7, error -71 > [ 30.950961] usb 1-9.1.2: reset high-speed USB device number 5 using > xhci_hcd > [ 31.096011] option 1-9.1.2:1.0: GSM modem (1-port) converter detected > [ 31.096269] usb 1-9.1.2: GSM modem (1-port) converter now attached to > ttyUSB0 > [ 31.096304] option 1-9.1.2:1.1: GSM modem (1-port) converter detected > [ 31.096474] usb 1-9.1.2: GSM modem (1-port) converter now attached to > ttyUSB1 Also odd... > [ 86.385506] usb 2-5.4: Device not responding to setup address. > [ 86.590238] usb 2-5.4: device not accepting address 12, error -71 > [ 86.590798] usb 2-5-port4: unable to enumerate USB device > [ 101.516693] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 101.722125] usb 2-5.4: Device not responding to setup address. > [ 101.926702] usb 2-5.4: device not accepting address 16, error -71 > [ 115.338361] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 115.546467] usb 2-5.4: Device not responding to setup address. > [ 115.751170] usb 2-5.4: device not accepting address 17, error -71 > [ 129.185004] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 129.397080] usb 2-5.4: Device not responding to setup address. > [ 129.601697] usb 2-5.4: device not accepting address 18, error -71 > [ 143.024578] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 143.231669] usb 2-5.4: Device not responding to setup address. > [ 143.436203] usb 2-5.4: device not accepting address 19, error -71 > [ 143.436814] usb 2-5-port4: unable to enumerate USB device > [ 157.882154] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 158.090299] usb 2-5.4: Device not responding to setup address. > [ 158.294896] usb 2-5.4: device not accepting address 22, error -71 > [ 171.710696] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 171.916643] usb 2-5.4: Device not responding to setup address. > [ 172.121397] usb 2-5.4: device not accepting address 23, error -71 > [ 185.542558] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 185.751236] usb 2-5.4: Device not responding to setup address. > [ 185.955910] usb 2-5.4: device not accepting address 24, error -71 > [ 199.376149] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 199.585824] usb 2-5.4: Device not responding to setup address. > [ 199.790405] usb 2-5.4: device not accepting address 25, error -71 > [ 199.790982] usb 2-5-port4: unable to enumerate USB device > [ 215.279864] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 215.484730] usb 2-5.4: Device not responding to setup address. > [ 215.689305] usb 2-5.4: device not accepting address 30, error -71 > [ 229.092273] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 229.303070] usb 2-5.4: Device not responding to setup address. > [ 229.507787] usb 2-5.4: device not accepting address 31, error -71 > [ 243.006432] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 243.217684] usb 2-5.4: Device not responding to setup address. > [ 243.422307] usb 2-5.4: device not accepting address 32, error -71 > [ 256.887746] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 257.100277] usb 2-5.4: Device not responding to setup address. > [ 257.304830] usb 2-5.4: device not accepting address 33, error -71 > [ 257.305437] usb 2-5-port4: unable to enumerate USB device > [ 272.222579] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 272.430894] usb 2-5.4: Device not responding to setup address. > [ 272.635589] usb 2-5.4: device not accepting address 37, error -71 > [ 286.017843] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 286.225508] usb 2-5.4: Device not responding to setup address. > [ 286.430078] usb 2-5.4: device not accepting address 38, error -71 > [ 299.838156] xhci_hcd :00:14.0: Timeout while waiting for setup device > command > [ 300.044133] usb 2-5.4: Device not responding to setup address. > [ 300.2486
Re: [PATCH v8 0/8] power: add power sequence library
On Friday, October 14, 2016 10:59:47 AM Peter Chen wrote: > Hi all, > > This is a follow-up for my last power sequence framework patch set [1]. > According to Rob Herring and Ulf Hansson's comments[2]. The kinds of > power sequence instances will be added at postcore_initcall, the match > criteria is compatible string first, if the compatible string is not > matched between dts and library, it will try to use generic power sequence. > > The host driver just needs to call of_pwrseq_on/of_pwrseq_off > if only one power sequence instance is needed, for more power sequences > are used, using of_pwrseq_on_list/of_pwrseq_off_list instead (eg, USB hub > driver). > > In future, if there are special power sequence requirements, the special > power sequence library can be created. > > This patch set is tested on i.mx6 sabresx evk using a dts change, I use > two hot-plug devices to simulate this use case, the related binding > change is updated at patch [1/6], The udoo board changes were tested > using my last power sequence patch set.[3] > > Except for hard-wired MMC and USB devices, I find the USB ULPI PHY also > need to power on itself before it can be found by ULPI bus. > > [1] http://www.spinics.net/lists/linux-usb/msg142755.html > [2] http://www.spinics.net/lists/linux-usb/msg143106.html > [3] http://www.spinics.net/lists/linux-usb/msg142815.html > > Changes for v8: > - Allocate one extra pwrseq instance if pwrseq_get has succeed, it can avoid > preallocate instances problem which the number of instance is decided at > compile time, thanks for Heiko Stuebner's suggestion [Patch 2/8] > - Delete pwrseq_compatible_sample.c which is the demo purpose to show > compatible > match method. [Patch 2/8] > - Add Maciej S. Szmigiero's tested-by. [Patch 7/8] > > Changes for v7: > - Create kinds of power sequence instance at postcore_initcall, and match > the instance with node using compatible string, the beneit of this is > the host driver doesn't need to consider which pwrseq instance needs > to be used, and pwrseq core will match it, however, it eats some memories > if less power sequence instances are used. [Patch 2/8] > - Add pwrseq_compatible_sample.c to test match pwrseq using device_id. [Patch > 2/8] > - Fix the comments Vaibhav Hiremath adds for error path for clock and do not > use device_node for parameters at pwrseq_on. [Patch 2/8] > - Simplify the caller to use power sequence, follows Alan's commnets [Patch > 4/8] > - Tested three pwrseq instances together using both specific compatible > string and > generic libraries. > > Changes for v6: > - Add Matthias Kaehlcke's Reviewed-by and Tested-by. (patch [2/6]) > - Change chipidea core of_node assignment for coming user. (patch [5/6]) > - Applies Joshua Clayton's three dts changes for two boards, > the USB device's reg has only #address-cells, but without #size-cells. > > Changes for v5: > - Delete pwrseq_register/pwrseq_unregister, which is useless currently > - Fix the linker error when the pwrseq user is compiled as module > > Changes for v4: > - Create the patch on next-20160722 > - Fix the of_node is not NULL after chipidea driver is unbinded [Patch 5/6] > - Using more friendly wait method for reset gpio [Patch 2/6] > - Support multiple input clocks [Patch 2/6] > - Add Rob Herring's ack for DT changes > - Add Joshua Clayton's Tested-by > > Changes for v3: > - Delete "power-sequence" property at binding-doc, and change related code > at both library and user code. > - Change binding-doc example node name with Rob's comments > - of_get_named_gpio_flags only gets the gpio, but without setting gpio flags, > add additional code request gpio with proper gpio flags > - Add Philipp Zabel's Ack and MAINTAINER's entry > > Changes for v2: > - Delete "pwrseq" prefix and clock-names for properties at dt binding > - Should use structure not but its pointer for kzalloc > - Since chipidea core has no of_node, let core's of_node equals glue > layer's at core's probe > > Joshua Clayton (2): > ARM: dts: imx6qdl: Enable usb node children with > ARM: dts: imx6q-evi: Fix onboard hub reset line > > Peter Chen (6): > binding-doc: power: pwrseq-generic: add binding doc for generic power > sequence library > power: add power sequence library > binding-doc: usb: usb-device: add optional properties for power > sequence > usb: core: add power sequence handling for USB devices > usb: chipidea: let chipidea core device of_node equal's glue layer > device of_node > ARM: dts: imx6qdl-udoo.dtsi: fix onboard USB HUB property > > .../bindings/power/pwrseq/pwrseq-generic.txt | 48 ++ > .../devicetree/bindings/usb/usb-device.txt | 10 +- > MAINTAINERS| 9 + > arch/arm/boot/dts/imx6q-evi.dts| 25 +-- > arch/arm/boot/dts/imx6qdl-udoo.dtsi| 26 ++- > arch/arm/boot/dts/imx6qdl.dtsi | 6 + > drivers
Re: [PATCH 2/3] usb: dwc3: gadget: wait for End Transfer to complete
Hi, Felipe Balbi writes: > Instead of just delaying for 100us, we should > actually wait for End Transfer Command Complete > interrupt before moving on. Note that this should > only be done if we're dealing with one of the core > revisions that actually require the interrupt before > moving on. > > Reported-by: Baolin Wang > Signed-off-by: Felipe Balbi I've updated this one in order to fix the comment we had about delaying 100us. No further changes were made, only the comment. Here it is: 8< From f3fa94f3171709f787a30e3c5ce69a668960b66e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 13 Oct 2016 14:09:47 +0300 Subject: [PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete Instead of just delaying for 100us, we should actually wait for End Transfer Command Complete interrupt before moving on. Note that this should only be done if we're dealing with one of the core revisions that actually require the interrupt before moving on. Reported-by: Baolin Wang Signed-off-by: Felipe Balbi --- . Changes since v1: - Fix comment drivers/usb/dwc3/core.h | 10 ++- drivers/usb/dwc3/gadget.c | 71 +++ 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e878366ead00..2f6f7c4bc8d4 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -504,6 +505,7 @@ struct dwc3_event_buffer { * @endpoint: usb endpoint * @pending_list: list of pending requests for this endpoint * @started_list: list of started requests on this endpoint + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete * @lock: spinlock for endpoint request queue traversal * @regs: pointer to first endpoint register * @trb_pool: array of transaction buffers @@ -529,6 +531,8 @@ struct dwc3_ep { struct list_headpending_list; struct list_headstarted_list; + wait_queue_head_t wait_end_transfer; + spinlock_t lock; void __iomem*regs; @@ -545,7 +549,8 @@ struct dwc3_ep { #define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_PENDING_REQUEST(1 << 5) #define DWC3_EP_MISSED_ISOC(1 << 6) - +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) +#define DWC3_EP_KICK_POST_END_TRANSFER (1 << 8) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN(1 << 31) @@ -1047,6 +1052,9 @@ struct dwc3_event_depevt { #define DEPEVT_TRANSFER_BUS_EXPIRY 2 u32 parameters:16; + +/* For Command Complete Events */ +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 8)) >> 8) } __packed; /** diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3ba05b12e49a..05a5b54a001b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -598,6 +598,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + init_waitqueue_head(&dep->wait_end_transfer); + if (usb_endpoint_xfer_control(desc)) return 0; @@ -1151,6 +1153,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (!dwc3_calc_trbs_left(dep)) return 0; + if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) { + dep->flags |= DWC3_EP_KICK_POST_END_TRANSFER; + return 0; + } + ret = __dwc3_gadget_kick_transfer(dep, 0); if (ret && ret != -EBUSY) dwc3_trace(trace_dwc3_gadget, @@ -2156,6 +2163,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, { struct dwc3_ep *dep; u8 epnum = event->endpoint_number; + u8 cmd; dep = dwc->eps[epnum]; @@ -2200,8 +2208,15 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, return; } break; - case DWC3_DEPEVT_RXTXFIFOEVT: case DWC3_DEPEVT_EPCMDCMPLT: + cmd = DEPEVT_PARAMETER_CMD(event->parameters); + + if (cmd == DWC3_DEPCMD_ENDTRANSFER) { + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; + wake_up(&dep->wait_end_transfer); + } + break; + case DWC3_DEPEVT_RXTXFIFOEVT: break; } } @@ -2246,6 +2261,7 @@ static void dwc3_reset_gadget(struct dwc3 *dwc) } static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) +__releases(&dwc->lock) __acquires(&dwc->lock) { struct dwc3_ep *dep; struct dwc3_gadget_ep_cmd_params params; @@ -2254,36 +2270,20 @@ static void dwc3_stop
[PATCH 2/3] usb: dwc3: gadget: wait for End Transfer to complete
Instead of just delaying for 100us, we should actually wait for End Transfer Command Complete interrupt before moving on. Note that this should only be done if we're dealing with one of the core revisions that actually require the interrupt before moving on. Reported-by: Baolin Wang Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 10 +- drivers/usb/dwc3/gadget.c | 36 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e878366ead00..2f6f7c4bc8d4 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -504,6 +505,7 @@ struct dwc3_event_buffer { * @endpoint: usb endpoint * @pending_list: list of pending requests for this endpoint * @started_list: list of started requests on this endpoint + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete * @lock: spinlock for endpoint request queue traversal * @regs: pointer to first endpoint register * @trb_pool: array of transaction buffers @@ -529,6 +531,8 @@ struct dwc3_ep { struct list_headpending_list; struct list_headstarted_list; + wait_queue_head_t wait_end_transfer; + spinlock_t lock; void __iomem*regs; @@ -545,7 +549,8 @@ struct dwc3_ep { #define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_PENDING_REQUEST(1 << 5) #define DWC3_EP_MISSED_ISOC(1 << 6) - +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) +#define DWC3_EP_KICK_POST_END_TRANSFER (1 << 8) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN(1 << 31) @@ -1047,6 +1052,9 @@ struct dwc3_event_depevt { #define DEPEVT_TRANSFER_BUS_EXPIRY 2 u32 parameters:16; + +/* For Command Complete Events */ +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 8)) >> 8) } __packed; /** diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3ba05b12e49a..8e3f9062a7d9 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -598,6 +598,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + init_waitqueue_head(&dep->wait_end_transfer); + if (usb_endpoint_xfer_control(desc)) return 0; @@ -1151,6 +1153,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) if (!dwc3_calc_trbs_left(dep)) return 0; + if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) { + dep->flags |= DWC3_EP_KICK_POST_END_TRANSFER; + return 0; + } + ret = __dwc3_gadget_kick_transfer(dep, 0); if (ret && ret != -EBUSY) dwc3_trace(trace_dwc3_gadget, @@ -2156,6 +2163,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, { struct dwc3_ep *dep; u8 epnum = event->endpoint_number; + u8 cmd; dep = dwc->eps[epnum]; @@ -2200,8 +2208,15 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, return; } break; - case DWC3_DEPEVT_RXTXFIFOEVT: case DWC3_DEPEVT_EPCMDCMPLT: + cmd = DEPEVT_PARAMETER_CMD(event->parameters); + + if (cmd == DWC3_DEPCMD_ENDTRANSFER) { + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; + wake_up(&dep->wait_end_transfer); + } + break; + case DWC3_DEPEVT_RXTXFIFOEVT: break; } } @@ -2246,6 +2261,7 @@ static void dwc3_reset_gadget(struct dwc3 *dwc) } static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) +__releases(&dwc->lock) __acquires(&dwc->lock) { struct dwc3_ep *dep; struct dwc3_gadget_ep_cmd_params params; @@ -2254,7 +2270,8 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) dep = dwc->eps[epnum]; - if (!dep->resource_index) + if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || + !dep->resource_index) return; /* @@ -2295,11 +2312,22 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force) memset(¶ms, 0, sizeof(params)); ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); WARN_ON_ONCE(ret); + + if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A) { + dep->flags |= DWC3_EP_END_TRANSFER_PENDING; + wait_event_lock_irq(dep->wait_end_transfer, + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), + dwc->lock); + } + dep
[PATCH 3/3] usb: dwc3: gadget: purge dwc3_stop_active_transfers()
That function is unnecessarily called from dwc3_gadget_reset_interrupt(). Gadget drivers (and thus, functions) are required to dequeue all pending requests when they get notified about a USB Bus Reset. Trying to make sure there are no pending requests only serves the purpose of working around possibly bad gadgets. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 20 1 file changed, 20 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8e3f9062a7d9..bcbb456e1129 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2330,24 +2330,6 @@ __releases(&dwc->lock) __acquires(&dwc->lock) } } -static void dwc3_stop_active_transfers(struct dwc3 *dwc) -{ - u32 epnum; - - for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { - struct dwc3_ep *dep; - - dep = dwc->eps[epnum]; - if (!dep) - continue; - - if (!(dep->flags & DWC3_EP_ENABLED)) - continue; - - dwc3_remove_requests(dwc, dep); - } -} - static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) { u32 epnum; @@ -2433,8 +2415,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) reg &= ~DWC3_DCTL_TSTCTRL_MASK; dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc->test_mode = false; - - dwc3_stop_active_transfers(dwc); dwc3_clear_stall_all_ep(dwc); /* Reset device address to zero */ -- 2.10.0.440.g21f862b -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] usb: gadget: composite: unlock before calling f->disable()
f->disable() will call usb_ep_disable() which should be called with IRQs enabled and locks released. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 919d7d1b611c..2e9359c58eb9 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -732,8 +732,10 @@ static void reset_config(struct usb_composite_dev *cdev) DBG(cdev, "reset config\n"); list_for_each_entry(f, &cdev->config->functions, list) { + spin_unlock_irq(&cdev->lock); if (f->disable) f->disable(f); + spin_lock_irq(&cdev->lock); bitmap_zero(f->endpoints, 32); } -- 2.10.0.440.g21f862b -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq
Hi, Baolin Wang writes: >> Baolin Wang writes: >>> I see what the problem is. Databook tells us we *must* set CMDIOC >>> when >>> issuing EndTransfer command and we should always wait for Command >>> Complete IRQ. However, we took a shortcut and just delayed for 100us >>> after issuing End Transfer. >> >> Yes, but 100us delay is not enough in some scenarios, like changing >> function with configfs frequently, we will met problems. > > heh, 100us *is* enough. However we still get an IRQ because we > requested > for it. If you want to fix this, then you need to find a way to get > rid > of that 100us udelay() and add a proper wait_for_completion() to delay > execution until command complete IRQ fires up. I haven't tested this yet, but it shows the idea (I think we might still have a race with ep_queue if we're still waiting for End Transfer, but >>> >>> Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when >>> queuing one request. >> >> Yeah, I'll add that check later. I still need to make sure we would >> still try to kick any transfers that might have been queued while >> waiting for End Transfer Command Complete IRQ. > > OK. But I still worried if there are other races in some places which There are no other places where this needs to be sorted out. > is not easy to find out by testing. No introducing race condition > would be one better solution, anyway I would like to test the patch > you send out firstly. Right, but your patch was working around another problem, rather then fixing it. Here's another version which should make sure everything remains working as it should. 8< From 1f922a902a21d5cee32082be18bbfbf1d46137e4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 13 Oct 2016 14:09:47 +0300 Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete Instead of just delaying for 100us, we should actually wait for End Transfer Command Complete interrupt before moving on. Note that this should only be done if we're dealing with one of the core revisions that actually require the interrupt before moving on. Reported-by: Baolin Wang Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 10 +- drivers/usb/dwc3/gadget.c | 31 --- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e878366ead00..cf495d932252 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -504,6 +505,7 @@ struct dwc3_event_buffer { * @endpoint: usb endpoint * @pending_list: list of pending requests for this endpoint * @started_list: list of started requests on this endpoint + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete * @lock: spinlock for endpoint request queue traversal * @regs: pointer to first endpoint register * @trb_pool: array of transaction buffers @@ -529,6 +531,8 @@ struct dwc3_ep { struct list_headpending_list; struct list_headstarted_list; + wait_queue_head_t wait_end_transfer; + spinlock_t lock; void __iomem*regs; @@ -545,7 +549,8 @@ struct dwc3_ep { #define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_PENDING_REQUEST(1 << 5) #define DWC3_EP_MISSED_ISOC(1 << 6) - +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) +#define DWC3_EP_KICK_POST_END_TRANSFER (1 << 8) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN(1 << 31) @@ -1047,6 +1052,9 @@ struct dwc3_event_depevt { #define DEPEVT_TRANSFER_BUS_EXPIRY 2 u32 parameters:16; + +/* For Command Complete Events */ +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 24)) >> 24) } __packed; /** diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3ba05b12e49a..a3f81b5ba901 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -598,6 +598,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + init_waitqueue_head(&dep->wait_end_transfer); +
[PATCH v4] usb: dwc3: Wait for control tranfer completed when stopping gadget
When we change the USB function with configfs dynamically, we possibly met this situation: one core is doing the control transfer, another core is trying to unregister the USB gadget from userspace, we must wait for completing this control tranfer, or it will hang the controller to set the DEVCTRLHLT flag. Signed-off-by: Baolin Wang --- Changes since v3: - Remove the patch 1 which will cause start gadget failed. - Remove try_again and refactor the code. Changes since v2: - Move disconnect checking into dwc3_send_gadget_ep_cmd(). - Rename completion name and issue complete() at one place. - Move completion initialization into dwc3_gadget_init(). Changes since v1: - Split into 2 separate ptaches. - Choose complete mechanism instead of polling. --- drivers/usb/dwc3/core.h |2 ++ drivers/usb/dwc3/ep0.c|2 ++ drivers/usb/dwc3/gadget.c | 28 +++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index b2317e7..23765a1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -745,6 +745,7 @@ struct dwc3_scratchpad_array { * @ep0_usb_req: dummy req used while handling STD USB requests * @ep0_bounce_addr: dma address of ep0_bounce * @scratch_addr: dma address of scratchbuf + * @ep0_in_setup: one control transfer is completed and enter setup phase * @lock: for synchronizing * @dev: pointer to our struct device * @xhci: pointer to our xHCI child @@ -843,6 +844,7 @@ struct dwc3 { dma_addr_t ep0_bounce_addr; dma_addr_t scratch_addr; struct dwc3_request ep0_usb_req; + struct completion ep0_in_setup; /* device lock */ spinlock_t lock; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index fe79d77..06c167a 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -311,6 +311,8 @@ void dwc3_ep0_out_start(struct dwc3 *dwc) ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8, DWC3_TRBCTL_CONTROL_SETUP, false); WARN_ON(ret < 0); + + complete(&dwc->ep0_in_setup); } static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1783406..3722c90 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1434,6 +1434,13 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) if (pm_runtime_suspended(dwc->dev)) return 0; + /* +* Per databook, when we want to stop the gadget, if a control transfer +* is still in process, complete it and get the core into setup phase. +*/ + if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) + return -EBUSY; + reg = dwc3_readl(dwc->regs, DWC3_DCTL); if (is_on) { if (dwc->revision <= DWC3_REVISION_187A) { @@ -1480,11 +1487,28 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) { struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; - int ret; + int ret = 0; is_on = !!is_on; spin_lock_irqsave(&dwc->lock, flags); + if (!is_on && !pm_runtime_suspended(dwc->dev) && + dwc->ep0state != EP0_SETUP_PHASE) { + reinit_completion(&dwc->ep0_in_setup); + ret = -EBUSY; + } + spin_unlock_irqrestore(&dwc->lock, flags); + + if (ret == -EBUSY) { + ret = wait_for_completion_timeout(&dwc->ep0_in_setup, + msecs_to_jiffies(500)); + if (ret == 0) { + dev_err(dwc->dev, "timeout to wait for setup phase.\n"); + return -ETIMEDOUT; + } + } + + spin_lock_irqsave(&dwc->lock, flags); ret = dwc3_gadget_run_stop(dwc, is_on, false); spin_unlock_irqrestore(&dwc->lock, flags); @@ -2911,6 +2935,8 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err4; } + init_completion(&dwc->ep0_in_setup); + dwc->gadget.ops = &dwc3_gadget_ops; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.sg_supported= true; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq
Hi Felipe, On 14 October 2016 at 15:46, Felipe Balbi wrote: > > Hi, > > Baolin Wang writes: >> I see what the problem is. Databook tells us we *must* set CMDIOC >> when >> issuing EndTransfer command and we should always wait for Command >> Complete IRQ. However, we took a shortcut and just delayed for 100us >> after issuing End Transfer. > > Yes, but 100us delay is not enough in some scenarios, like changing > function with configfs frequently, we will met problems. heh, 100us *is* enough. However we still get an IRQ because we requested for it. If you want to fix this, then you need to find a way to get rid of that 100us udelay() and add a proper wait_for_completion() to delay execution until command complete IRQ fires up. >>> >>> I haven't tested this yet, but it shows the idea (I think we might still >>> have a race with ep_queue if we're still waiting for End Transfer, but >> >> Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when >> queuing one request. > > Yeah, I'll add that check later. I still need to make sure we would > still try to kick any transfers that might have been queued while > waiting for End Transfer Command Complete IRQ. OK. But I still worried if there are other races in some places which >>> >>> There are no other places where this needs to be sorted out. >>> is not easy to find out by testing. No introducing race condition would be one better solution, anyway I would like to test the patch you send out firstly. >>> >>> Right, but your patch was working around another problem, rather then >>> fixing it. >>> >>> Here's another version which should make sure everything remains working >>> as it should. >>> >>> 8< >>> From 1f922a902a21d5cee32082be18bbfbf1d46137e4 Mon Sep 17 00:00:00 2001 >>> From: Felipe Balbi >>> Date: Thu, 13 Oct 2016 14:09:47 +0300 >>> Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete >>> >>> Instead of just delaying for 100us, we should >>> actually wait for End Transfer Command Complete >>> interrupt before moving on. Note that this should >>> only be done if we're dealing with one of the core >>> revisions that actually require the interrupt before >>> moving on. >>> >>> Reported-by: Baolin Wang >>> Signed-off-by: Felipe Balbi >>> --- >>> drivers/usb/dwc3/core.h | 10 +- >>> drivers/usb/dwc3/gadget.c | 31 --- >>> 2 files changed, 37 insertions(+), 4 deletions(-) >>> >>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h >>> index e878366ead00..cf495d932252 100644 >>> --- a/drivers/usb/dwc3/core.h >>> +++ b/drivers/usb/dwc3/core.h >>> @@ -26,6 +26,7 @@ >>> #include >>> #include >>> #include >>> +#include >>> >>> #include >>> #include >>> @@ -504,6 +505,7 @@ struct dwc3_event_buffer { >>> * @endpoint: usb endpoint >>> * @pending_list: list of pending requests for this endpoint >>> * @started_list: list of started requests on this endpoint >>> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer >>> complete >>> * @lock: spinlock for endpoint request queue traversal >>> * @regs: pointer to first endpoint register >>> * @trb_pool: array of transaction buffers >>> @@ -529,6 +531,8 @@ struct dwc3_ep { >>> struct list_headpending_list; >>> struct list_headstarted_list; >>> >>> + wait_queue_head_t wait_end_transfer; >>> + >>> spinlock_t lock; >>> void __iomem*regs; >>> >>> @@ -545,7 +549,8 @@ struct dwc3_ep { >>> #define DWC3_EP_BUSY (1 << 4) >>> #define DWC3_EP_PENDING_REQUEST(1 << 5) >>> #define DWC3_EP_MISSED_ISOC(1 << 6) >>> - >>> +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) >>> +#define DWC3_EP_KICK_POST_END_TRANSFER (1 << 8) >>> /* This last one is specific to EP0 */ >>> #define DWC3_EP0_DIR_IN(1 << 31) >>> >>> @@ -1047,6 +1052,9 @@ struct dwc3_event_depevt { >>> #define DEPEVT_TRANSFER_BUS_EXPIRY 2 >>> >>> u32 parameters:16; >>> + >>> +/* For Command Complete Events */ >>> +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 24)) >> 24) >>> } __packed; >>> >>> /** >>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c >>> index 3ba05b12e49a..a3f81b5ba901 100644 >>> --- a/drivers/usb/dwc3/gadget.c >>> +++ b/drivers/usb/dwc3/gadget.c >>> @@ -598,6 +598,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, >>> reg |= DWC3_DALEPENA_EP(dep->number); >>> dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); >>> >>> + init_waitqueue_head(&dep->wait_end_transfer); >>> + >>> if (usb_endpoint_xfer_control(desc)) >>> return 0; >>> >>> @@ -1151,6 +
[PATCH V11 1/1] usb:serial: Add Fintek F81532/534 driver
This driver is for Fintek F81532/F81534 USB to Serial Ports IC. F81532 spec: https://drive.google.com/file/d/0B8vRwwYO7aMFOTRRMmhWQVNvajQ/view?usp= sharing F81534 spec: https://drive.google.com/file/d/0B8vRwwYO7aMFV29pQWJqbVBNc00/view?usp= sharing Features: 1. F81532 is 1-to-2 & F81534 is 1-to-4 serial ports IC 2. Support Baudrate from B50 to B115200. Reviewed-by: Johan Hovold Signed-off-by: Ji-Ze Hong (Peter Hong) --- Changelog: V11 1. Reduce F81534_MAX_BUS_RETRY from 2000 to 20. We are only using internal SPI bus to read flash when attach() & calc_num_ports() and never read flash when the F81532/534 in full loading, so we can reduce retry count. 2. Modify attach() & calc_num_ports() read default value only when can't find the custom setting. 3. Change tx_empty protect method from spinlock to set_bit()/ clear_bit()/test_and_clear_bit(). 4. Move calculate tty_idx[i] from port_probe() to attach(). 5. Add f81534_tx_empty() V10 1. Change the submit/kill timming for read URBs, submit when first serial port open and kill when final port close. 2. Remove all source code about controlling GPIOs. 3. Change the f81534_tiocmget() from reading shadow MSR with delay 20ms to read MSR register directly. 4. Using tty_port_initialized() to check port opened/closed. 5. Add sanity check for variables. v9 1. Remove lots of code to make more generic for F81532/534. e.g., high baud rate support, RS485/422 mode switch, most of GPIO control and internal storage write functional. 2. Change f81534_tiocmget() MSR delay from schedule_timeout_killable() to wait_for_completion_killable_timeout(). This IC will delayed receiving MSR change when doing loop-back test e.g., BurnInTest. We'll reset completion "msr_done" in f81534_update_mctrl(). If we changed MCR, the next f81534_tiocmget() will delay for 20ms or continue with new MSR arrived. 3. Fix for non-zero buffer allocated in f81534_setup_ports(). It'll make device malfunctional with incorrect tx length for other ports. v8 1. Remove driver mode GPIOLIB & RS485 control support, the driver will only load GPIO/UART Mode when driver attach() & port_probe(). 2. Add more documents for 3 generation IC with f81534_calc_num_ports(). 3. Simplify the GPIO register structure "f81534_pin_control". 4. Change all counter type from int to size_t. 5. Change some failed message with failed: "status code" and remove all exclamation mark in messages. 6. Change all save blocks to block0 due to the driver is only used 1 block (block0) to save data. 7. Change read MSR in open() instead of port_probe(). 8. use GFP_ATOMIC kmalloc mode in write(). 9. Maintain old style with 1 read URBs and 4 write URBs like mxuports.c I had tested with submit 4 read URBs, but it'll make some port freeze when doing BurnInTest Port test. v7 1. Make all gpiolib function with #ifdef CONFIG_GPIOLIB marco block. Due to F81532/534 could run without gpiolib, we implements f81534_prepare_gpio()/f81534_release_gpio() always success without CONFIG_GPIOLIB. 2. Fix crash when receiving MSR change on driver load/unload. It's cause by f81534_process_read_urb() get read URB callback data, but port private data is not init complete or released. We solve with 2 modifications. 1. add null pointer check with f81534_process_read_urb(). We'll skip this report when port_priv = NULL. 2. when "one" port f81534_port_remove() is called, kill the port-0 read URB before kfree port_priv. v6 1. Re-implement the write()/resume() function. Due to this device cant be suitable with generic write(), we'll do the submit write URB when write()/received tx empty/set_termios()/resume() 2. Logic/Phy Port mapping rewrite in f81534_port_probe() & f81534_phy_to_logic_port(). 3. Introduced "Port Hide" function. Some customer use F81532 reference design for HW layout, but really use F81534 IC. We'll check F81534_PORT_CONF_DISABLE_PORT flag with in uart mode field to do port hide with port not used. It can be avoid end-user to use not layouted port. 4. The 4x3 output-only open-drain pins for F81532/534 is designed for control outer devices (with our EVB for examples, the 4 sets of pins are designed to control transceiver mode). So we decide to implement with gpiolib interface. 5. Add device vendor id with 0x2c42 v5 1. Change f81534_port_disable/enable() from H/W mode to S/W mode It'll skip all rx data when port is not opened. 2. Some function modifier add with static (Thanks for Paul Bolle) 3. It's will direct return when count=0 in f81534_write() to reduce spin_lock usage. v4 1. clearify f81534_process_read_urb() with f81534_p
Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq
Hi, Baolin Wang writes: > I see what the problem is. Databook tells us we *must* set CMDIOC when > issuing EndTransfer command and we should always wait for Command > Complete IRQ. However, we took a shortcut and just delayed for 100us > after issuing End Transfer. Yes, but 100us delay is not enough in some scenarios, like changing function with configfs frequently, we will met problems. >>> >>> heh, 100us *is* enough. However we still get an IRQ because we requested >>> for it. If you want to fix this, then you need to find a way to get rid >>> of that 100us udelay() and add a proper wait_for_completion() to delay >>> execution until command complete IRQ fires up. >> >> I haven't tested this yet, but it shows the idea (I think we might still >> have a race with ep_queue if we're still waiting for End Transfer, but > > Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when > queuing one request. Yeah, I'll add that check later. I still need to make sure we would still try to kick any transfers that might have been queued while waiting for End Transfer Command Complete IRQ. >>> >>> OK. But I still worried if there are other races in some places which >> >> There are no other places where this needs to be sorted out. >> >>> is not easy to find out by testing. No introducing race condition >>> would be one better solution, anyway I would like to test the patch >>> you send out firstly. >> >> Right, but your patch was working around another problem, rather then >> fixing it. >> >> Here's another version which should make sure everything remains working >> as it should. >> >> 8< >> From 1f922a902a21d5cee32082be18bbfbf1d46137e4 Mon Sep 17 00:00:00 2001 >> From: Felipe Balbi >> Date: Thu, 13 Oct 2016 14:09:47 +0300 >> Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete >> >> Instead of just delaying for 100us, we should >> actually wait for End Transfer Command Complete >> interrupt before moving on. Note that this should >> only be done if we're dealing with one of the core >> revisions that actually require the interrupt before >> moving on. >> >> Reported-by: Baolin Wang >> Signed-off-by: Felipe Balbi >> --- >> drivers/usb/dwc3/core.h | 10 +- >> drivers/usb/dwc3/gadget.c | 31 --- >> 2 files changed, 37 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h >> index e878366ead00..cf495d932252 100644 >> --- a/drivers/usb/dwc3/core.h >> +++ b/drivers/usb/dwc3/core.h >> @@ -26,6 +26,7 @@ >> #include >> #include >> #include >> +#include >> >> #include >> #include >> @@ -504,6 +505,7 @@ struct dwc3_event_buffer { >> * @endpoint: usb endpoint >> * @pending_list: list of pending requests for this endpoint >> * @started_list: list of started requests on this endpoint >> + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer >> complete >> * @lock: spinlock for endpoint request queue traversal >> * @regs: pointer to first endpoint register >> * @trb_pool: array of transaction buffers >> @@ -529,6 +531,8 @@ struct dwc3_ep { >> struct list_headpending_list; >> struct list_headstarted_list; >> >> + wait_queue_head_t wait_end_transfer; >> + >> spinlock_t lock; >> void __iomem*regs; >> >> @@ -545,7 +549,8 @@ struct dwc3_ep { >> #define DWC3_EP_BUSY (1 << 4) >> #define DWC3_EP_PENDING_REQUEST(1 << 5) >> #define DWC3_EP_MISSED_ISOC(1 << 6) >> - >> +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) >> +#define DWC3_EP_KICK_POST_END_TRANSFER (1 << 8) >> /* This last one is specific to EP0 */ >> #define DWC3_EP0_DIR_IN(1 << 31) >> >> @@ -1047,6 +1052,9 @@ struct dwc3_event_depevt { >> #define DEPEVT_TRANSFER_BUS_EXPIRY 2 >> >> u32 parameters:16; >> + >> +/* For Command Complete Events */ >> +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 24)) >> 24) >> } __packed; >> >> /** >> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c >> index 3ba05b12e49a..a3f81b5ba901 100644 >> --- a/drivers/usb/dwc3/gadget.c >> +++ b/drivers/usb/dwc3/gadget.c >> @@ -598,6 +598,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, >> reg |= DWC3_DALEPENA_EP(dep->number); >> dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); >> >> + init_waitqueue_head(&dep->wait_end_transfer); >> + >> if (usb_endpoint_xfer_control(desc)) >> return 0; >> >> @@ -1151,6 +1153,11 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep >> *dep, struct dwc3_request *req) >> if (!dwc3_calc_trbs_left(dep)) >> return 0; >> >> + if (dep->flags & DWC3_EP_END_T
Re: [PATCH v2] usb: dwc3: gadget: Wait for end transfer complete before free irq
Hi Felipe, On 13 October 2016 at 21:34, Felipe Balbi wrote: > > > Hi, > > Baolin Wang writes: >>> Baolin Wang writes: >> Baolin Wang writes: >> I'm thinking this is a bug in configfs interface of Gadget API, not >> dwc3. The only reason for this to happen would be if we get to >> ->udc_stop() with endpoints still enabled. >> >> Can you check if that's the case? i.e. can you check if any endpoints >> are still enabled when we get here? > > No, it is not any endpoints are still enabled. Like I said in commit > message, we will start end transfer command when disable the endpoint, > if the end transfer command complete event comes after we have freed > the gadget irq, it will trigger the interrupt line all the time to > crash the system. I see what the problem is. Databook tells us we *must* set CMDIOC when issuing EndTransfer command and we should always wait for Command Complete IRQ. However, we took a shortcut and just delayed for 100us after issuing End Transfer. >>> >>> Yes, but 100us delay is not enough in some scenarios, like changing >>> function with configfs frequently, we will met problems. >> >> heh, 100us *is* enough. However we still get an IRQ because we requested >> for it. If you want to fix this, then you need to find a way to get rid >> of that 100us udelay() and add a proper wait_for_completion() to delay >> execution until command complete IRQ fires up. > > I haven't tested this yet, but it shows the idea (I think we might still > have a race with ep_queue if we're still waiting for End Transfer, but Yes, maybe we need check DWC3_EP_END_TRANSFER_PENDING flag when queuing one request. >>> >>> Yeah, I'll add that check later. I still need to make sure we would >>> still try to kick any transfers that might have been queued while >>> waiting for End Transfer Command Complete IRQ. >> >> OK. But I still worried if there are other races in some places which > > There are no other places where this needs to be sorted out. > >> is not easy to find out by testing. No introducing race condition >> would be one better solution, anyway I would like to test the patch >> you send out firstly. > > Right, but your patch was working around another problem, rather then > fixing it. > > Here's another version which should make sure everything remains working > as it should. > > 8< > From 1f922a902a21d5cee32082be18bbfbf1d46137e4 Mon Sep 17 00:00:00 2001 > From: Felipe Balbi > Date: Thu, 13 Oct 2016 14:09:47 +0300 > Subject: [PATCH] usb: dwc3: gadget: wait for End Transfer to complete > > Instead of just delaying for 100us, we should > actually wait for End Transfer Command Complete > interrupt before moving on. Note that this should > only be done if we're dealing with one of the core > revisions that actually require the interrupt before > moving on. > > Reported-by: Baolin Wang > Signed-off-by: Felipe Balbi > --- > drivers/usb/dwc3/core.h | 10 +- > drivers/usb/dwc3/gadget.c | 31 --- > 2 files changed, 37 insertions(+), 4 deletions(-) > > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index e878366ead00..cf495d932252 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -26,6 +26,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -504,6 +505,7 @@ struct dwc3_event_buffer { > * @endpoint: usb endpoint > * @pending_list: list of pending requests for this endpoint > * @started_list: list of started requests on this endpoint > + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete > * @lock: spinlock for endpoint request queue traversal > * @regs: pointer to first endpoint register > * @trb_pool: array of transaction buffers > @@ -529,6 +531,8 @@ struct dwc3_ep { > struct list_headpending_list; > struct list_headstarted_list; > > + wait_queue_head_t wait_end_transfer; > + > spinlock_t lock; > void __iomem*regs; > > @@ -545,7 +549,8 @@ struct dwc3_ep { > #define DWC3_EP_BUSY (1 << 4) > #define DWC3_EP_PENDING_REQUEST(1 << 5) > #define DWC3_EP_MISSED_ISOC(1 << 6) > - > +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) > +#define DWC3_EP_KICK_POST_END_TRANSFER (1 << 8) > /* This last one is specific to EP0 */ > #define DWC3_EP0_DIR_IN(1 << 31) > > @@ -1047,6 +1052,9 @@ struct dwc3_event_depevt { > #define DEPEVT_TRANSFER_BUS_EXPIRY 2 > > u32 parameters:16; > + > +/* For Command Complete Events */ > +#define DEPEVT_PARAMETER_CMD(n) (((n) & (0xf << 24)) >> 24) > } __packed; > > /** > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/