Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Jun 2005 17:42:44 +0100
From:      Ian Dowse <iedowse@iedowse.com>
To:        Stefan Walter <sw@gegenunendlich.de>
Cc:        freebsd-stable@freebsd.org
Subject:   Re: EHCI: mtools stuck in state 'physrd' or panic 
Message-ID:  <200506261742.aa93128@nowhere.iedowse.com>
In-Reply-To: Your message of "Sun, 26 Jun 2005 11:26:20 %2B0200." <20050626092620.GA1565@kyuzo.dunkelkammer.void> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <20050626092620.GA1565@kyuzo.dunkelkammer.void>, Stefan Walter write
s:
>FYI: I have just sent a PR for this problem.
>
>http://www.freebsd.org/cgi/query-pr.cgi?pr=82660

OpenBSD have a workaround for problems with VIA EHCI controllers
that can cause the hanging symptoms you describe. Below is a patch
that implements their change in FreeBSD's driver. Could you try it
to see if it helps?

Thanks,

Ian

Index: sys/dev/usb/ehci.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/ehci.c,v
retrieving revision 1.14.2.9
diff -u -r1.14.2.9 ehci.c
--- sys/dev/usb/ehci.c	31 Mar 2005 19:47:11 -0000	1.14.2.9
+++ sys/dev/usb/ehci.c	26 Jun 2005 16:21:11 -0000
@@ -155,6 +155,7 @@
 Static void		ehci_idone(struct ehci_xfer *);
 Static void		ehci_timeout(void *);
 Static void		ehci_timeout_task(void *);
+Static void		ehci_intrlist_timeout(void *);
 
 Static usbd_status	ehci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
 Static void		ehci_freem(struct usbd_bus *, usb_dma_t *);
@@ -491,6 +492,7 @@
 	EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH);
 
 	usb_callout_init(sc->sc_tmo_pcd);
+	usb_callout_init(sc->sc_tmo_intrlist);
 
 	lockinit(&sc->sc_doorbell_lock, PZERO, "ehcidb", 0, 0);
 
@@ -694,6 +696,11 @@
 		ehci_check_intr(sc, ex);
 	}
 
+	/* Schedule a callout to catch any dropped transactions. */
+	if ((sc->sc_flags & EHCI_SCFLG_LOSTINTRBUG) &&
+	    !LIST_EMPTY(&sc->sc_intrhead))
+		usb_callout(sc->sc_tmo_intrlist, hz, ehci_intrlist_timeout, sc);
+
 #ifdef USB_USE_SOFTINTR
 	if (sc->sc_softwake) {
 		sc->sc_softwake = 0;
@@ -942,6 +949,7 @@
 	EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
 	EOWRITE4(sc, EHCI_USBCMD, 0);
 	EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
+	usb_uncallout(sc->sc_tmo_intrlist, ehci_intrlist_timeout, sc);
 	usb_uncallout(sc->sc_tmo_pcd, ehci_pcd_enable, sc);
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
@@ -2701,6 +2708,30 @@
 	splx(s);
 }
 
+
+/*
+ * Some EHCI chips from VIA seem to trigger interrupts before writing back the
+ * qTD status, or miss signalling occasionally under heavy load.  If the host
+ * machine is too fast, we we can miss transaction completion - when we scan
+ * the active list the transaction still seems to be active.  This generally
+ * exhibits itself as a umass stall that never recovers.
+ *
+ * We work around this behaviour by setting up this callback after any softintr
+ * that completes with transactions still pending, giving us another chance to
+ * check for completion after the writeback has taken place.
+ */
+void
+ehci_intrlist_timeout(void *arg)
+{
+	ehci_softc_t *sc = arg;
+	int s = splusb();
+
+	DPRINTFN(3, ("ehci_intrlist_timeout\n"));
+	usb_schedsoftintr(&sc->sc_bus);
+
+	splx(s);
+}
+
 /************************/
 
 Static usbd_status
Index: sys/dev/usb/ehci_pci.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/ehci_pci.c,v
retrieving revision 1.14.2.2
diff -u -r1.14.2.2 ehci_pci.c
--- sys/dev/usb/ehci_pci.c	13 Jun 2005 09:00:19 -0000	1.14.2.2
+++ sys/dev/usb/ehci_pci.c	26 Jun 2005 16:21:11 -0000
@@ -303,6 +303,10 @@
 		return ENXIO;
 	}
 
+	/* Enable workaround for dropped interrupts as required */
+	if (pci_get_vendor(self) == PCI_EHCI_VENDORID_VIA)
+		sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG;
+
 	/*
 	 * Find companion controllers.  According to the spec they always
 	 * have lower function numbers so they should be enumerated already.
Index: sys/dev/usb/ehcivar.h
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/ehcivar.h,v
retrieving revision 1.4.2.4
diff -u -r1.4.2.4 ehcivar.h
--- sys/dev/usb/ehcivar.h	22 Mar 2005 00:56:54 -0000	1.4.2.4
+++ sys/dev/usb/ehcivar.h	26 Jun 2005 16:21:11 -0000
@@ -93,6 +93,7 @@
 #define EHCI_COMPANION_MAX 8
 
 #define EHCI_SCFLG_DONEINIT	0x0001	/* ehci_init() has been called. */
+#define EHCI_SCFLG_LOSTINTRBUG	0x0002	/* workaround for VIA chipsets */
 
 typedef struct ehci_softc {
 	struct usbd_bus sc_bus;		/* base device */
@@ -149,6 +150,7 @@
 	struct lock sc_doorbell_lock;
 
 	usb_callout_t sc_tmo_pcd;
+	usb_callout_t sc_tmo_intrlist;
 
 	device_ptr_t sc_child;		/* /dev/usb# device */

 



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