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--