From owner-svn-src-all@FreeBSD.ORG Mon May 27 06:32:07 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id C59F1B4E; Mon, 27 May 2013 06:32:07 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id B89E664A; Mon, 27 May 2013 06:32:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r4R6W77I064002; Mon, 27 May 2013 06:32:07 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r4R6W7EP063999; Mon, 27 May 2013 06:32:07 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201305270632.r4R6W7EP063999@svn.freebsd.org> From: Hans Petter Selasky Date: Mon, 27 May 2013 06:32:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r251023 - head/sys/dev/usb/controller X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 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, 27 May 2013 06:32:07 -0000 Author: hselasky Date: Mon May 27 06:32:07 2013 New Revision: 251023 URL: http://svnweb.freebsd.org/changeset/base/251023 Log: Workaround for for a problem seen with ATI Technologies EHCI controller hardware most likely present on UHCI chipsets aswell. The bug manifests itself when issuing isochronous transfers and bulk transfers towards the same device simultaneously. From time to time it happens that either the completion IRQ was missing or that the completion IRQ was happening before the ITD/SITD was completely written back to memory. The workaround assumes that double buffered isochronous transfers are used, and that a second interrupt is generated at the beginning of the next isochronous transfer to complete the previous one. Possibly skipping the interrupt at the last isochronous frame is possible, but will then break single buffered isochronous transfers. For now we can live with some extra interrupts. MFC after: 1 week Modified: head/sys/dev/usb/controller/ehci.c head/sys/dev/usb/controller/uhci.c Modified: head/sys/dev/usb/controller/ehci.c ============================================================================== --- head/sys/dev/usb/controller/ehci.c Mon May 27 06:24:31 2013 (r251022) +++ head/sys/dev/usb/controller/ehci.c Mon May 27 06:32:07 2013 (r251023) @@ -2454,6 +2454,7 @@ ehci_device_isoc_fs_enter(struct usb_xfe uint16_t tlen; uint8_t sa; uint8_t sb; + uint8_t first = 1; #ifdef USB_DEBUG uint8_t once = 1; @@ -2618,6 +2619,16 @@ ehci_device_isoc_fs_enter(struct usb_xfe EHCI_SITD_IOC | EHCI_SITD_ACTIVE | EHCI_SITD_SET_LEN(*plen)); + } else if (first != 0) { + /* + * Workaround for lost or too early + * completion interrupt: + */ + first = 0; + td->sitd_status = htohc32(sc, + EHCI_SITD_IOC | + EHCI_SITD_ACTIVE | + EHCI_SITD_SET_LEN(*plen)); } else { td->sitd_status = htohc32(sc, EHCI_SITD_ACTIVE | @@ -2759,6 +2770,7 @@ ehci_device_isoc_hs_enter(struct usb_xfe uint8_t td_no; uint8_t page_no; uint8_t shift = usbd_xfer_get_fps_shift(xfer); + uint8_t first = 1; #ifdef USB_DEBUG uint8_t once = 1; @@ -2920,6 +2932,13 @@ ehci_device_isoc_hs_enter(struct usb_xfe /* set IOC bit if we are complete */ if (nframes == 0) { td->itd_status[td_no - 1] |= htohc32(sc, EHCI_ITD_IOC); + } else if (first != 0) { + /* + * Workaround for lost or too early + * completion interrupt: + */ + first = 0; + td->itd_status[0] |= htohc32(sc, EHCI_ITD_IOC); } usb_pc_cpu_flush(td->page_cache); #ifdef USB_DEBUG Modified: head/sys/dev/usb/controller/uhci.c ============================================================================== --- head/sys/dev/usb/controller/uhci.c Mon May 27 06:24:31 2013 (r251022) +++ head/sys/dev/usb/controller/uhci.c Mon May 27 06:32:07 2013 (r251023) @@ -2138,6 +2138,7 @@ uhci_device_isoc_enter(struct usb_xfer * uint32_t nframes; uint32_t temp; uint32_t *plen; + uint8_t first = 1; #ifdef USB_DEBUG uint8_t once = 1; @@ -2253,6 +2254,18 @@ uhci_device_isoc_enter(struct usb_xfer * UHCI_TD_ACTIVE | UHCI_TD_IOS | UHCI_TD_IOC)); + } else if (first != 0) { + /* + * Workaround for lost or too early completion + * interrupt: + */ + first = 0; + td->td_status = htole32 + (UHCI_TD_ZERO_ACTLEN + (UHCI_TD_SET_ERRCNT(0) | + UHCI_TD_ACTIVE | + UHCI_TD_IOS | + UHCI_TD_IOC)); } else { td->td_status = htole32 (UHCI_TD_ZERO_ACTLEN