From owner-svn-src-all@FreeBSD.ORG Sat Jul 16 12:50:31 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5F543106564A; Sat, 16 Jul 2011 12:50:31 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3515B8FC0C; Sat, 16 Jul 2011 12:50:31 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p6GCoVV7028494; Sat, 16 Jul 2011 12:50:31 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p6GCoVBU028492; Sat, 16 Jul 2011 12:50:31 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201107161250.p6GCoVBU028492@svn.freebsd.org> From: Hans Petter Selasky Date: Sat, 16 Jul 2011 12:50:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r224095 - head/sys/dev/usb X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 16 Jul 2011 12:50:31 -0000 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;