On Fri, 15 May 2009, Karl Hiramoto wrote: > Dave Higton wrote: > > On Thursday May 14, Ethan wrote: > > > > > >> I'm having trouble with a 7-port, powered USB hub made by D-Link > >> (model DUB-7). The devices plugged into the hub seem to work fine for > >> small transfers, but large transfers (such as to/from a scanner or > >> usb-storage device) break something. Once things are "broken" I see > >> from the syslog that the bus is reset every few seconds. It is not > >> clear to me if any data moves at all between bus resets but it is very > >> little if anything. When the bus is in this state, all devices on the > >> bus become inaccessible not just the one that was engaged in the > >> transfer. Removing and reinstalling the ehci_hcd and ohci_hcd modules > >> seems to reset the bus and correct the problem until the next large > >> transfer is initiated. > >> > >> I suspect the problem lies with the hub because all of the devices > >> work fine when plugged directly into the computer or when plugged into > >> a different brand hub. > >> > > > > I also have a DUB-7 that I use on RISC OS. I noticed a long time ago > > that most mass storage devices won't work through it, though they > > work fine when connected directly to the computer. I would be > > interested in any insight that this thread might give me. > > > > Dave > > > I thik this hub has the philips ISP1521 chip in it.. It has only one > TT per port. I've notitced if you have all high speed devices, it > seems to work. If it stops working you have to unplug/plug it to reset it. > > > I think windows has the same issue: > http://www.techtalkz.com/microsoft-device-drivers/243707-usb-problem-when-using-philips-isp1521-based-hub.html The problem described in that thread appears to be a genuine bug. In short, ehci-hcd doesn't do a clear-TT-buffer when a low/full-speed async URB is unlinked. When that happens the buffer remains busy indefinitely, and when all the buffers are busy the hub won't work right. This patch may fix the problem. I haven't tested it, so you guys will have to be the guinea pigs. :-) Dave B.: The patch makes a few significant changes. Most notably, the code for clearing the TT buffer no longer depends on QTD_STS_HALT, and unlinked URBs no longer cause an early return. It also doesn't depend on status != -EPIPE; that seemed like an unnecessary optimization. It's more careful to run only for async endpoints (the old code only checked for !Interrupt). Last but not least, the test for QTD_STS_MMF is changed to QTD_STS_STS -- the MMF value must have been a typo since it applies only to periodic endpoints. Alan Stern Index: usb-2.6/drivers/usb/host/ehci-q.c =================================================================== --- usb-2.6.orig/drivers/usb/host/ehci-q.c +++ usb-2.6/drivers/usb/host/ehci-q.c @@ -152,10 +152,6 @@ static int qtd_copy_status ( if (likely (QTD_PID (token) != 2)) urb->actual_length += length - QTD_LENGTH (token); - /* don't modify error codes */ - if (unlikely(urb->unlinked)) - return status; - /* force cleanup after short read; not always an error */ if (unlikely (IS_SHORT_READ (token))) status = -EREMOTEIO; @@ -195,30 +191,35 @@ static int qtd_copy_status ( usb_pipeendpoint (urb->pipe), usb_pipein (urb->pipe) ? "in" : "out", token, status); + } - /* if async CSPLIT failed, try cleaning out the TT buffer */ - if (status != -EPIPE - && urb->dev->tt - && !usb_pipeint(urb->pipe) - && ((token & QTD_STS_MMF) != 0 - || QTD_CERR(token) == 0) - && (!ehci_is_TDI(ehci) - || urb->dev->tt->hub != - ehci_to_hcd(ehci)->self.root_hub)) { + /* if async CSPLIT failed or an async URB was unlinked, + * try cleaning out the TT buffer + */ + if (urb->dev->tt && (usb_pipecontrol(urb->pipe) + || usb_pipebulk(urb->pipe)) + && ((token & QTD_STS_STS) != 0 + || QTD_CERR(token) == 0) + && (!ehci_is_TDI(ehci) + || urb->dev->tt->hub != + ehci_to_hcd(ehci)->self.root_hub)) { #ifdef DEBUG - struct usb_device *tt = urb->dev->tt->hub; - dev_dbg (&tt->dev, - "clear tt buffer port %d, a%d ep%d t%08x\n", - urb->dev->ttport, urb->dev->devnum, - usb_pipeendpoint (urb->pipe), token); + struct usb_device *tt = urb->dev->tt->hub; + dev_dbg(&tt->dev, + "clear tt buffer port %d, a%d ep%d t%08x\n", + urb->dev->ttport, urb->dev->devnum, + usb_pipeendpoint(urb->pipe), token); #endif /* DEBUG */ - /* REVISIT ARC-derived cores don't clear the root - * hub TT buffer in this way... - */ - usb_hub_tt_clear_buffer (urb->dev, urb->pipe); - } + /* REVISIT ARC-derived cores don't clear the root + * hub TT buffer in this way... + */ + usb_hub_tt_clear_buffer(urb->dev, urb->pipe); } + /* For unlinked URBs, don't change the unlink error code */ + if (unlikely(urb->unlinked)) + status = -EINPROGRESS; + return status; } -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html