summaryrefslogtreecommitdiff
path: root/sys/dev/usb/usb_request.c
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2014-01-13 15:21:11 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2014-01-13 15:21:11 +0000
commita0d53e0b384c1f7d63d0f7277a8adb594eec7230 (patch)
tree2ed1bd7186b681c28c7635d5d7e144cf1152435e /sys/dev/usb/usb_request.c
parenta148d44fb57982c384ac3b81c3745786e95c3a12 (diff)
downloadsrc-test2-a0d53e0b384c1f7d63d0f7277a8adb594eec7230.tar.gz
src-test2-a0d53e0b384c1f7d63d0f7277a8adb594eec7230.zip
Notes
Diffstat (limited to 'sys/dev/usb/usb_request.c')
-rw-r--r--sys/dev/usb/usb_request.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index cecc16724c5c..8c9271574e2b 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -721,6 +721,17 @@ done:
if ((mtx != NULL) && (mtx != &Giant))
mtx_lock(mtx);
+ switch (err) {
+ case USB_ERR_NORMAL_COMPLETION:
+ case USB_ERR_SHORT_XFER:
+ case USB_ERR_STALLED:
+ case USB_ERR_CANCELLED:
+ break;
+ default:
+ DPRINTF("I/O error - waiting a bit for TT cleanup\n");
+ usb_pause_mtx(mtx, hz / 16);
+ break;
+ }
return ((usb_error_t)err);
}
@@ -2010,6 +2021,7 @@ usbd_req_re_enumerate(struct usb_device *udev, struct mtx *mtx)
return (USB_ERR_INVAL);
}
retry:
+#if USB_HAVE_TT_SUPPORT
/*
* Try to reset the High Speed parent HUB of a LOW- or FULL-
* speed device, if any.
@@ -2017,15 +2029,24 @@ retry:
if (udev->parent_hs_hub != NULL &&
udev->speed != USB_SPEED_HIGH) {
DPRINTF("Trying to reset parent High Speed TT.\n");
- err = usbd_req_reset_tt(udev->parent_hs_hub, NULL,
- udev->hs_port_no);
+ if (udev->parent_hs_hub == parent_hub &&
+ (uhub_count_active_host_ports(parent_hub, USB_SPEED_LOW) +
+ uhub_count_active_host_ports(parent_hub, USB_SPEED_FULL)) == 1) {
+ /* we can reset the whole TT */
+ err = usbd_req_reset_tt(parent_hub, NULL,
+ udev->hs_port_no);
+ } else {
+ /* only reset a particular device and endpoint */
+ err = usbd_req_clear_tt_buffer(udev->parent_hs_hub, NULL,
+ udev->hs_port_no, old_addr, UE_CONTROL, 0);
+ }
if (err) {
DPRINTF("Resetting parent High "
"Speed TT failed (%s).\n",
usbd_errstr(err));
}
}
-
+#endif
/* Try to warm reset first */
if (parent_hub->speed == USB_SPEED_SUPER)
usbd_req_warm_reset_port(parent_hub, mtx, udev->port_no);