Author: hselasky
Date: Sat Jul 16 12:50:30 2011
New Revision: 224095
URL: http://svn.freebsd.org/changeset/base/224095

Log:
  Fix for VirtualBox 4.x and other virtual machines that fail
  to generate a port reset change event.
  
  MFC after:    1 weeks

Modified:
  head/sys/dev/usb/usb_request.c

Modified: head/sys/dev/usb/usb_request.c
==============================================================================
--- head/sys/dev/usb/usb_request.c      Sat Jul 16 11:34:38 2011        
(r224094)
+++ head/sys/dev/usb/usb_request.c      Sat Jul 16 12:50:30 2011        
(r224095)
@@ -779,10 +779,17 @@ usbd_req_reset_port(struct usb_device *u
        uint16_t pr_recovery_delay;
 
 #endif
-       err = usbd_req_set_port_feature(udev, mtx, port, UHF_PORT_RESET);
-       if (err) {
+       /* clear any leftover port reset changes first */
+       usbd_req_clear_port_feature(
+           udev, mtx, port, UHF_C_PORT_RESET);
+
+       /* assert port reset on the given port */
+       err = usbd_req_set_port_feature(
+           udev, mtx, port, UHF_PORT_RESET);
+
+       /* check for errors */
+       if (err)
                goto done;
-       }
 #ifdef USB_DEBUG
        /* range check input parameters */
        pr_poll_delay = usb_pr_poll_delay;
@@ -798,6 +805,9 @@ usbd_req_reset_port(struct usb_device *u
 #endif
        n = 0;
        while (1) {
+               uint16_t status;
+               uint16_t change;
+
 #ifdef USB_DEBUG
                /* wait for the device to recover from reset */
                usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_poll_delay));
@@ -811,14 +821,25 @@ usbd_req_reset_port(struct usb_device *u
                if (err) {
                        goto done;
                }
+               status = UGETW(ps.wPortStatus);
+               change = UGETW(ps.wPortChange);
+
                /* if the device disappeared, just give up */
-               if (!(UGETW(ps.wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) {
+               if (!(status & UPS_CURRENT_CONNECT_STATUS))
                        goto done;
-               }
+
                /* check if reset is complete */
-               if (UGETW(ps.wPortChange) & UPS_C_PORT_RESET) {
+               if (change & UPS_C_PORT_RESET)
                        break;
-               }
+
+               /*
+                * Some Virtual Machines like VirtualBox 4.x fail to
+                * generate a port reset change event. Check if reset
+                * is no longer asserted.
+                */
+               if (!(status & UPS_RESET))
+                       break;
+
                /* check for timeout */
                if (n > 1000) {
                        n = 0;
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to