Re: Low & full speed devices stop working after testusb run

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 14 Jul 2011, Sebastian Andrzej Siewior wrote:

> * Arvid Brodin | 2011-07-13 03:54:39 [+0200]:
> 
> >Hi,
> Hi,
> 
> >The problem is that low- and full-speed devices stop working while running the
> >testusb suite. It looks like this:
> >
> ># ./testusb -a
> >...
> >After this, plugging in a full speed device yields this (on any port):
> >/var/log/messages:
> >usb 1-1.2: new full speed USB device using isp1760 and address 23
> >usb 1-1.2: device descriptor read/64, error -110
> >hub 1-1:1.0: unable to enumerate USB device on port 2
> >
> >High speed devices however works just fine (on any port).
> 
> You have only one port which you access via isp1760's hub code. The
> three external ports are behind the external hub. From this it seems
> that the hub wants to remain in HighSpeed.
> 
> >The usbmon dump ends with one line of -ENOENT (-2) for every line of "error 110"
> >in the output above:
> >
> >...
> >93e26a80 2856118575 C Bo:1:003:2 0 512 >
> >93e26a80 2856119258 C Bo:1:003:2 0 512 >
> >93e26a80 2861121006 C Co:1:003:0 -2 0
> There is no submit to this? Could it be that the pipe is "down" and you
> never subit the URB in the first place?
> 
> >93e26a80 2861129835 S Co:1:003:0 s 01 0b 0000 0000 0000 0
> >93e26a80 2866200342 C Co:1:003:0 -2 0
> >
> >Any idea what could be causing this? (The driver itself never sets urb->status
> >to -ENOENT, but I can see that this is done in the usb core code for numerous
> >reasons.)
> I guess another prinkt would help :)
> 
> >Another clue may be that with the addition of this printk to core/urb.c, the
> >error does not occur, so it would have to be a timing dependent issue:
> >
> > void usb_kill_urb(struct urb *urb)
> > {
> >	might_sleep();
> >	if (!(urb && urb->dev && urb->ep))
> >		return;
> >	atomic_inc(&urb->reject);
> >
> >+	printk(KERN_ERR "E\n");
> >	usb_hcd_unlink_urb(urb, -ENOENT);
> >	wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
> >
> >	atomic_dec(&urb->reject);
> > }
> > EXPORT_SYMBOL_GPL(usb_kill_urb);
> 
> Is it possible that since you defer the unlinking you don't interrupt
> the internal HUB in the middle of whatever it is doing? Maybe the way
> the transfers are unlinked is something that confuses the internal hub.

Ah -- that was the clue I didn't notice before.

When an URB is unlinked, and it is for a full-speed/low-speed device
attached via a high-speed hub, it is necessary to send a
Clear-TT-Buffer request to the hub.  The usbmon log did not show any
such requests being sent.  Without them, the TT buffers in the hub
never drain and it becomes impossible to send any more control or bulk
messages to that device (or to any other device sharing the same TT).

Any high-speed host controller driver has to call
usb_hub_clear_tt_buffer() when a bulk or control URB going through a TT
is unlinked or fails for any reason other than -EPIPE or -EREMOTEIO.  
Also, the driver must define a .clear_tt_buffer_complete callback in
its hc_driver structure, and it must not send any transactions to the
URB's endpoint until the callback tells it the TT buffer has been
cleared.

This is all explained in section 11.17 of the USB-2 spec.  See 
especially 11.17.5 for a discussion of Clear-TT-Buffer.

Alan Stern

--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux