Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 May 2013 06:32:07 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251023 - head/sys/dev/usb/controller
Message-ID:  <201305270632.r4R6W7EP063999@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305270632.r4R6W7EP063999>