diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2009-11-18 11:37:15 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-11-30 19:43:15 -0500 |
commit | c2f6595fbdb408d3d6850cfae590c8fa93e27399 (patch) | |
tree | 028249fb4eb0878154230b013d59e1bf674d09ca /drivers/usb | |
parent | a8a84540eb3fd0493f250dc1c513bef6810a50fd (diff) |
USB: EHCI: don't send Clear-TT-Buffer following a STALL
This patch (as1304) fixes a regression in ehci-hcd. Evidently some
hubs don't handle Clear-TT-Buffer requests correctly, so we should
avoid sending them when they don't appear to be absolutely necessary.
The reported symptom is that output on a downstream audio device cuts
out because the hub stops relaying isochronous packets.
The patch prevents Clear-TT-Buffer requests from being sent following
a STALL handshake. In theory a STALL indicates either that the
downstream device sent a STALL or that no matching TT buffer could be
found. In either case, the transfer is completed and the TT buffer
does not remain busy, so it doesn't need to be cleared.
Also, the patch fixes a minor flaw in the code that actually sends the
Clear-TT-Buffer requests. Although the pipe direction isn't really
used for control transfers, it should be a Send rather than a Receive.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: Javier Kohen <jkohen@users.sourceforge.net>
CC: David Brownell <david-b@pacbell.net>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 16 |
2 files changed, 15 insertions, 3 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 5ce839137ad6..0f857e645058 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -444,7 +444,7 @@ resubmit: | |||
444 | static inline int | 444 | static inline int |
445 | hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) | 445 | hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) |
446 | { | 446 | { |
447 | return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), | 447 | return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), |
448 | HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, | 448 | HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, |
449 | tt, NULL, 0, 1000); | 449 | tt, NULL, 0, 1000); |
450 | } | 450 | } |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 00ad9ce392ed..139a2cc3f641 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -487,8 +487,20 @@ halt: | |||
487 | * we must clear the TT buffer (11.17.5). | 487 | * we must clear the TT buffer (11.17.5). |
488 | */ | 488 | */ |
489 | if (unlikely(last_status != -EINPROGRESS && | 489 | if (unlikely(last_status != -EINPROGRESS && |
490 | last_status != -EREMOTEIO)) | 490 | last_status != -EREMOTEIO)) { |
491 | ehci_clear_tt_buffer(ehci, qh, urb, token); | 491 | /* The TT's in some hubs malfunction when they |
492 | * receive this request following a STALL (they | ||
493 | * stop sending isochronous packets). Since a | ||
494 | * STALL can't leave the TT buffer in a busy | ||
495 | * state (if you believe Figures 11-48 - 11-51 | ||
496 | * in the USB 2.0 spec), we won't clear the TT | ||
497 | * buffer in this case. Strictly speaking this | ||
498 | * is a violation of the spec. | ||
499 | */ | ||
500 | if (last_status != -EPIPE) | ||
501 | ehci_clear_tt_buffer(ehci, qh, urb, | ||
502 | token); | ||
503 | } | ||
492 | } | 504 | } |
493 | 505 | ||
494 | /* if we're removing something not at the queue head, | 506 | /* if we're removing something not at the queue head, |