summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/usb_hub.c
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2011-06-06 21:45:09 +0000
committerhselasky <hselasky@FreeBSD.org>2011-06-06 21:45:09 +0000
commit5f55faed0601b0486b09dd7ec3727f5312e33d5d (patch)
tree0b32799a28515b5c61e32d9d9a2ae9fedbba5065 /sys/dev/usb/usb_hub.c
parentc8e197a2037e17686f997232419f8b02d1e61ffc (diff)
downloadFreeBSD-src-5f55faed0601b0486b09dd7ec3727f5312e33d5d.zip
FreeBSD-src-5f55faed0601b0486b09dd7ec3727f5312e33d5d.tar.gz
Improve enumeration of Low- and Full-speed devices connected through a
High-speed USB HUB by resetting the transaction translator (TT) before trying re-enumeration. Also when clear-stall fails multiple times try a re-enumeration. Suggested by: Trevor Blackwell MFC after: 14 days
Diffstat (limited to 'sys/dev/usb/usb_hub.c')
-rw-r--r--sys/dev/usb/usb_hub.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index ce8a4a5..351b134 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -242,9 +242,14 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up)
if (child->flags.usb_mode == USB_MODE_HOST) {
usbd_enum_lock(child);
if (child->re_enumerate_wait) {
- err = usbd_set_config_index(child, USB_UNCONFIG_INDEX);
- if (err == 0)
- err = usbd_req_re_enumerate(child, NULL);
+ err = usbd_set_config_index(child,
+ USB_UNCONFIG_INDEX);
+ if (err != 0) {
+ DPRINTF("Unconfigure failed: "
+ "%s: Ignored.\n",
+ usbd_errstr(err));
+ }
+ err = usbd_req_re_enumerate(child, NULL);
if (err == 0)
err = usbd_set_config_index(child, 0);
if (err == 0) {
@@ -2471,3 +2476,19 @@ usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode)
/* use fixed power mode given by hardware driver */
return (temp);
}
+
+/*------------------------------------------------------------------------*
+ * usbd_start_re_enumerate
+ *
+ * This function starts re-enumeration of the given USB device. This
+ * function does not need to be called BUS-locked. This function does
+ * not wait until the re-enumeration is completed.
+ *------------------------------------------------------------------------*/
+void
+usbd_start_re_enumerate(struct usb_device *udev)
+{
+ if (udev->re_enumerate_wait == 0) {
+ udev->re_enumerate_wait = 1;
+ usb_needs_explore(udev->bus, 0);
+ }
+}
OpenPOWER on IntegriCloud