From owner-svn-src-all@FreeBSD.ORG Mon Mar 21 21:16:25 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 9B77E1065845; Mon, 21 Mar 2011 21:16:25 +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 8AAE18FC1B; Mon, 21 Mar 2011 21:16:25 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p2LLGP0s021035; Mon, 21 Mar 2011 21:16:25 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2LLGPGF021033; Mon, 21 Mar 2011 21:16:25 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201103212116.p2LLGPGF021033@svn.freebsd.org> From: Hans Petter Selasky Date: Mon, 21 Mar 2011 21:16:25 +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: r219845 - head/sys/dev/usb/controller 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: Mon, 21 Mar 2011 21:16:25 -0000 Author: hselasky Date: Mon Mar 21 21:16:25 2011 New Revision: 219845 URL: http://svn.freebsd.org/changeset/base/219845 Log: - Bugfix: Fix a EHCI hardware race, where the hardware computed data toggle value is updated after that we read it in the queue-head. This patch can fix problems with BULK timeouts. The issue was found on a Nvidia chipset. MFC after: 14 days Approved by: thompsa (mentor) Modified: head/sys/dev/usb/controller/ehci.c Modified: head/sys/dev/usb/controller/ehci.c ============================================================================== --- head/sys/dev/usb/controller/ehci.c Mon Mar 21 21:16:12 2011 (r219844) +++ head/sys/dev/usb/controller/ehci.c Mon Mar 21 21:16:25 2011 (r219845) @@ -1180,6 +1180,26 @@ _ehci_remove_qh(ehci_qh_t *sqh, ehci_qh_ return (last); } +static void +ehci_data_toggle_update(struct usb_xfer *xfer, uint16_t actlen, uint16_t xlen) +{ + uint8_t full = (actlen == xlen); + uint8_t dt; + + /* count number of full packets */ + dt = (actlen / xfer->max_packet_size) & 1; + + /* cumpute remainder */ + actlen = actlen % xfer->max_packet_size; + + if (actlen > 0) + dt ^= 1; /* short packet at the end */ + else if (!full) + dt ^= 1; /* zero length packet at the end */ + + xfer->endpoint->toggle_next ^= dt; +} + static usb_error_t ehci_non_isoc_done_sub(struct usb_xfer *xfer) { @@ -1213,7 +1233,10 @@ ehci_non_isoc_done_sub(struct usb_xfer * status |= EHCI_QTD_HALTED; } else if (xfer->aframes != xfer->nframes) { xfer->frlengths[xfer->aframes] += td->len - len; + /* manually update data toggle */ + ehci_data_toggle_update(xfer, td->len - len, td->len); } + /* Check for last transfer */ if (((void *)td) == xfer->td_transfer_last) { td = NULL; @@ -1295,9 +1318,6 @@ ehci_non_isoc_done(struct usb_xfer *xfer status = hc32toh(sc, qh->qh_qtd.qtd_status); - xfer->endpoint->toggle_next = - (status & EHCI_QTD_TOGGLE_MASK) ? 1 : 0; - /* reset scanner */ xfer->td_transfer_cache = xfer->td_transfer_first; @@ -1876,6 +1896,8 @@ ehci_setup_standard_chain(struct usb_xfe if (xfer->flags_int.control_xfr) { if (xfer->flags_int.control_hdr) { + xfer->endpoint->toggle_next = 0; + temp.qtd_status &= htohc32(temp.sc, EHCI_QTD_SET_CERR(3)); temp.qtd_status |= htohc32(temp.sc,