Subject: YO: Need OHCI patch tested
To: None <current-users@netbsd.org>
From: Charles M. Hannum <abuse@spamalicious.com>
List: current-users
Date: 03/04/2005 08:42:08
--Boundary-00=_g9BKCXdJEIEJydh
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Could people with OHCI devices please test the following patch and let me know 
if they experience any new problems?  It would be especially useful to get 
results from non-PC platforms -- e.g. embedded OHCI controllers on some ARM 
systems, Macs, etc.

Also, if you can compare performance (e.g. bulk read/write of a USB flash 
device) before/after, that would be useful.  In theory, you shouldn't notice 
any difference.

If I don't get results back, I'm going to go ahead and commit it.  You've been 
warned.

--Boundary-00=_g9BKCXdJEIEJydh
Content-Type: text/x-diff;
  charset="us-ascii";
  name="ohci.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="ohci.diff"

Index: ohci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ohci.c,v
retrieving revision 1.156
diff -u -r1.156 ohci.c
--- ohci.c	2 Mar 2005 11:37:27 -0000	1.156
+++ ohci.c	4 Mar 2005 07:05:53 -0000
@@ -143,7 +143,6 @@
 Static void		ohci_poll(struct usbd_bus *);
 Static void		ohci_softintr(void *);
 Static void		ohci_waitintr(ohci_softc_t *, usbd_xfer_handle);
-Static void		ohci_add_done(ohci_softc_t *, ohci_physaddr_t);
 Static void		ohci_rhsc(ohci_softc_t *, usbd_xfer_handle);
 
 Static usbd_status	ohci_device_request(usbd_xfer_handle xfer);
@@ -208,7 +207,6 @@
 
 Static void		ohci_timeout(void *);
 Static void		ohci_timeout_task(void *);
-Static void		ohci_rhsc_able(ohci_softc_t *, int);
 Static void		ohci_rhsc_enable(void *);
 
 Static void		ohci_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *);
@@ -1124,7 +1122,6 @@
 ohci_intr1(ohci_softc_t *sc)
 {
 	u_int32_t intrs, eintrs;
-	ohci_physaddr_t done;
 
 	DPRINTFN(14,("ohci_intr1: enter\n"));
 
@@ -1136,22 +1133,11 @@
 		return (0);
 	}
 
-        intrs = 0;
-	done = le32toh(sc->sc_hcca->hcca_done_head);
-	if (done != 0) {
-		if (done & ~OHCI_DONE_INTRS)
-			intrs = OHCI_WDH;
-		if (done & OHCI_DONE_INTRS)
-			intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS);
-		sc->sc_hcca->hcca_done_head = 0;
-	} else
-		intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & ~OHCI_WDH;
-
+	intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS);
 	if (!intrs)
 		return (0);
 
-	intrs &= ~OHCI_MIE;
-	OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs); /* Acknowledge */
+	OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs & ~(OHCI_MIE|OHCI_WDH)); /* Acknowledge */
 	eintrs = intrs & sc->sc_eintrs;
 	if (!eintrs)
 		return (0);
@@ -1173,9 +1159,11 @@
 		eintrs &= ~OHCI_SO;
 	}
 	if (eintrs & OHCI_WDH) {
-		ohci_add_done(sc, done &~ OHCI_DONE_INTRS);
+		/*
+		 * We block the interrupt below, and reenable it later from
+		 * ohci_softintr().
+		 */
 		usb_schedsoftintr(&sc->sc_bus);
-		eintrs &= ~OHCI_WDH;
 	}
 	if (eintrs & OHCI_RD) {
 		printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev));
@@ -1188,51 +1176,37 @@
 		/* XXX what else */
 	}
 	if (eintrs & OHCI_RHSC) {
-		ohci_rhsc(sc, sc->sc_intrxfer);
 		/*
-		 * Disable RHSC interrupt for now, because it will be
-		 * on until the port has been reset.
+		 * We block the interrupt below, and reenable it later from
+		 * a timeout.
 		 */
-		ohci_rhsc_able(sc, 0);
+		ohci_rhsc(sc, sc->sc_intrxfer);
 		/* Do not allow RHSC interrupts > 1 per second */
                 usb_callout(sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc);
-		eintrs &= ~OHCI_RHSC;
 	}
 
 	sc->sc_bus.intr_context--;
 
 	if (eintrs != 0) {
-		/* Block unprocessed interrupts. XXX */
+		/* Block unprocessed interrupts. */
 		OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs);
 		sc->sc_eintrs &= ~eintrs;
-		printf("%s: blocking intrs 0x%x\n",
-		       USBDEVNAME(sc->sc_bus.bdev), eintrs);
+		DPRINTFN(1, ("%s: blocking intrs 0x%x\n",
+		    USBDEVNAME(sc->sc_bus.bdev), eintrs));
 	}
 
 	return (1);
 }
 
 void
-ohci_rhsc_able(ohci_softc_t *sc, int on)
-{
-	DPRINTFN(4, ("ohci_rhsc_able: on=%d\n", on));
-	if (on) {
-		sc->sc_eintrs |= OHCI_RHSC;
-		OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC);
-	} else {
-		sc->sc_eintrs &= ~OHCI_RHSC;
-		OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC);
-	}
-}
-
-void
 ohci_rhsc_enable(void *v_sc)
 {
 	ohci_softc_t *sc = v_sc;
 	int s;
 
 	s = splhardusb();
-	ohci_rhsc_able(sc, 1);
+	sc->sc_eintrs |= OHCI_RHSC;
+	OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC);
 	splx(s);
 }
 
@@ -1258,10 +1232,28 @@
 #endif
 
 void
-ohci_add_done(ohci_softc_t *sc, ohci_physaddr_t done)
+ohci_softintr(void *v)
 {
-	ohci_soft_itd_t *sitd, *sidone, **ip;
-	ohci_soft_td_t  *std,  *sdone,  **p;
+	ohci_softc_t *sc = v;
+	ohci_soft_itd_t *sitd, *sidone, *sitdnext;
+	ohci_soft_td_t  *std,  *sdone,  *stdnext;
+	usbd_xfer_handle xfer;
+	struct ohci_pipe *opipe;
+	int len, cc, s;
+	int i, j, actlen, iframes, uedir;
+	ohci_physaddr_t done;
+
+	DPRINTFN(10,("ohci_softintr: enter\n"));
+
+	sc->sc_bus.intr_context++;
+
+	s = splhardusb();
+	done = le32toh(sc->sc_hcca->hcca_done_head) & ~OHCI_DONE_INTRS;
+	sc->sc_hcca->hcca_done_head = 0;
+	OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_WDH);
+	sc->sc_eintrs |= OHCI_WDH;
+	OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_WDH);
+	splx(s);
 
 	/* Reverse the done list. */
 	for (sdone = NULL, sidone = NULL; done != 0; ) {
@@ -1281,41 +1273,9 @@
 			DPRINTFN(5,("add ITD %p\n", sitd));
 			continue;
 		}
-		panic("ohci_add_done: addr 0x%08lx not found", (u_long)done);
+		panic("ohci_softintr: addr 0x%08lx not found", (u_long)done);
 	}
 
-	/* sdone & sidone now hold the done lists. */
-	/* Put them on the already processed lists. */
-	for (p = &sc->sc_sdone; *p != NULL; p = &(*p)->dnext)
-		;
-	*p = sdone;
-	for (ip = &sc->sc_sidone; *ip != NULL; ip = &(*ip)->dnext)
-		;
-	*ip = sidone;
-}
-
-void
-ohci_softintr(void *v)
-{
-	ohci_softc_t *sc = v;
-	ohci_soft_itd_t *sitd, *sidone, *sitdnext;
-	ohci_soft_td_t  *std,  *sdone,  *stdnext;
-	usbd_xfer_handle xfer;
-	struct ohci_pipe *opipe;
-	int len, cc, s;
-	int i, j, actlen, iframes, uedir;
-
-	DPRINTFN(10,("ohci_softintr: enter\n"));
-
-	sc->sc_bus.intr_context++;
-
-	s = splhardusb();
-	sdone = sc->sc_sdone;
-	sc->sc_sdone = NULL;
-	sidone = sc->sc_sidone;
-	sc->sc_sidone = NULL;
-	splx(s);
-
 	DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone));
 
 #ifdef OHCI_DEBUG
@@ -2564,7 +2524,7 @@
 		case UHF_C_PORT_RESET:
 			/* Enable RHSC interrupt if condition is cleared. */
 			if ((OREAD4(sc, port) >> 16) == 0)
-				ohci_rhsc_able(sc, 1);
+				ohci_rhsc_enable(sc);
 			break;
 		default:
 			break;
Index: ohcivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ohcivar.h,v
retrieving revision 1.35
diff -u -r1.35 ohcivar.h
--- ohcivar.h	11 Jan 2005 07:45:34 -0000	1.35
+++ ohcivar.h	4 Mar 2005 07:05:53 -0000
@@ -118,9 +118,6 @@
 
 	usbd_xfer_handle sc_intrxfer;
 
-	ohci_soft_itd_t *sc_sidone;
-	ohci_soft_td_t  *sc_sdone;
-
 	char sc_vendor[16];
 	int sc_id_vendor;
 

--Boundary-00=_g9BKCXdJEIEJydh--