handle multiple interrupts of sleeps. use iprint in interrupts clean up reset protocol (thanks to cinap for this) Reference: /n/atom/patch/applied2013/ehciintr Date: Sat Sep 21 22:15:23 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/port/usbehci.c Sat Sep 21 22:13:42 2013 +++ /sys/src/9/port/usbehci.c Sat Sep 21 22:13:45 2013 @@ -395,7 +395,7 @@ if(i == 100) print("ehci %#p %s cmd timed out\n", ctlr->capio, on ? "run" : "halt"); - ddprint("ehci %#p cmd %#lux sts %#lux\n", + ddprint("ehci %#p cmd %#ux sts %#ux\n", ctlr->capio, opio->cmd, opio->sts); } @@ -407,7 +407,7 @@ lock(&edpool); if(edpool.free == nil){ - pool = xspanalloc(Incr*sizeof(Ed), Align, 0); + pool = mallocalign(Incr*sizeof(Ed), Align, 0, 0); if(pool == nil) panic("edalloc"); for(i=Incr; --i>=0;){ @@ -524,9 +524,9 @@ } static void -qhsetaddr(Qh *qh, ulong addr) +qhsetaddr(Qh *qh, u32int addr) { - ulong eps0; + u32int eps0; eps0 = qh->eps0 & ~((Epmax<<8)|Devmax); qh->eps0 = eps0 | addr & Devmax | ((addr >> 7) & Epmax) << 8; @@ -645,7 +645,7 @@ static void qhsetmaxpkt(Qh *qh, int maxpkt) { - ulong eps0; + u32int eps0; eps0 = qh->eps0 & ~(Qhmplmask << Qhmplshift); qh->eps0 = eps0 | (maxpkt & Qhmplmask) << Qhmplshift; @@ -740,11 +740,12 @@ qlock(&ctlr->portlck); ctlr->opio->cmd |= Ciasync; /* ask for intr. on async advance */ coherence(); - for(i = 0; i < 3 && qhadvanced(ctlr) == 0; i++) - if(!waserror()){ - tsleep(ctlr, qhadvanced, ctlr, Abortdelay); - poperror(); - } + for(i = 0; i < 3 && qhadvanced(ctlr) == 0; i++){ + while(waserror()) + ; + tsleep(ctlr, qhadvanced, ctlr, Abortdelay); + poperror(); + } dprint("ehci: qhcoherency: doorbell %d\n", qhadvanced(ctlr)); if(i == 3) print("ehci: async advance doorbell did not ring\n"); @@ -772,6 +773,7 @@ coherence(); }else unschedq(ctlr, qh); + qh->state = Qfree; /* paranoia */ iunlock(ctlr); qhcoherency(ctlr); @@ -787,7 +789,7 @@ static void qhlinktd(Qh *qh, Td *td) { - ulong csw; + u32int csw; int i; csw = qh->csw; @@ -810,9 +812,9 @@ } static char* -seprintlink(char *s, char *se, char *name, ulong l, int typed) +seprintlink(char *s, char *se, char *name, u32int l, int typed) { - s = seprint(s, se, "%s %ulx", name, l); + s = seprint(s, se, "%s %ux", name, l); if((l & Lterm) != 0) return seprint(s, se, "T"); if(typed == 0) @@ -1125,14 +1127,14 @@ ctlr->capio, ctlr->frames, ctlr->nframes, ctlr->nintr, ctlr->ntdintr); print(" nqhintr %d nisointr %d\n", ctlr->nqhintr, ctlr->nisointr); - print("\tcmd %#lux sts %#lux intr %#lux frno %uld", + print("\tcmd %#ux sts %#ux intr %#ux frno %ud", opio->cmd, opio->sts, opio->intr, opio->frno); - print(" base %#lux link %#lux fr0 %#lux\n", + print(" base %#ux link %#ux fr0 %#lux\n", opio->frbase, opio->link, ctlr->frames[0]); se = buf+sizeof(buf); s = seprint(buf, se, "\t"); for(i = 0; i < hp->nports; i++){ - s = seprint(s, se, "p%d %#lux ", i, opio->portsc[i]); + s = seprint(s, se, "p%d %#ux ", i, opio->portsc[i]); if(hp->nports > 4 && i == hp->nports/2 - 1) s = seprint(s, se, "\n\t"); } @@ -1519,7 +1521,7 @@ Ctlr *ctlr; Eopio *opio; Isoio *iso; - ulong sts; + u32int sts; Qh *qh; int i, some; @@ -1532,7 +1534,6 @@ * This is Intel's doing. */ ilock(ctlr); - ctlr->nintr++; sts = opio->sts & Sintrs; if(sts == 0){ /* not ours; shared intr. */ iunlock(ctlr); @@ -1540,10 +1541,11 @@ } opio->sts = sts; coherence(); + ctlr->nintr++; if((sts & Sherr) != 0) - print("ehci: port %#p fatal host system error\n", ctlr->capio); + iprint("ehci: port %#p fatal host system error\n", ctlr->capio); if((sts & Shalted) != 0) - print("ehci: port %#p: halted\n", ctlr->capio); + iprint("ehci: port %#p: halted\n", ctlr->capio); if((sts & Sasync) != 0){ dprint("ehci: doorbell\n"); wakeup(ctlr); @@ -1557,12 +1559,12 @@ if((sts & (Serrintr|Sintr)) != 0){ ctlr->ntdintr++; if(ehcidebug > 1){ - print("ehci port %#p frames %#p nintr %d ntdintr %d", + iprint("ehci port %#p frames %#p nintr %d ntdintr %d", ctlr->capio, ctlr->frames, ctlr->nintr, ctlr->ntdintr); - print(" nqhintr %d nisointr %d\n", + iprint(" nqhintr %d nisointr %d\n", ctlr->nqhintr, ctlr->nisointr); - print("\tcmd %#lux sts %#lux intr %#lux frno %uld", + iprint("\tcmd %#ux sts %#ux intr %#ux frno %ud", opio->cmd, opio->sts, opio->intr, opio->frno); } @@ -1590,7 +1592,7 @@ qh = qh->next; }while(qh != ctlr->qhs && i++ < 100); if(i > 100) - print("echi: interrupt: qh loop?\n"); + iprint("echi: interrupt: qh loop?\n"); } // if (some == 0) // panic("ehciintr: no work"); @@ -1632,7 +1634,7 @@ microdelay(64); iunlock(ctlr); tsleep(&up->sleep, return0, 0, Enabledelay); - dprint("ehci %#p port %d enable=%d: sts %#lux\n", + dprint("ehci %#p port %d enable=%d: sts %#ux\n", ctlr->capio, port, on, opio->portsc[port-1]); qunlock(&ctlr->portlck); poperror(); @@ -1651,7 +1653,7 @@ portlend(Ctlr *ctlr, int port, char *ss) { Eopio *opio; - ulong s; + u32int s; opio = ctlr->opio; @@ -1665,7 +1667,7 @@ static int portreset(Hci *hp, int port, int on) { - ulong *portscp; + u32int *portscp; Eopio *opio; Ctlr *ctlr; int i; @@ -1682,33 +1684,35 @@ nexterror(); } portscp = &opio->portsc[port-1]; - dprint("ehci %#p port %d reset; sts %#lux\n", ctlr->capio, port, *portscp); + dprint("ehci %#p port %d reset; sts %#ux\n", ctlr->capio, port, *portscp); ilock(ctlr); /* Shalted must be zero, else Psreset will stay set */ if (opio->sts & Shalted) iprint("ehci %#p: halted yet trying to reset port\n", ctlr->capio); - *portscp = (*portscp & ~Psenable) | Psreset; /* initiate reset */ - coherence(); + *portscp = (*portscp & ~Psenable) | Psreset; /* initiate reset */ /* * usb 2 spec: reset must finish within 20 ms. * linux says spec says it can take 50 ms. for hubs. */ - for(i = 0; *portscp & Psreset && i < 50; i++) + delay(50); + *portscp &= ~Psreset; /* terminate reset */ + + delay(10); + for(i = 0; *portscp & Psreset && i < 10; i++) delay(10); + if (*portscp & Psreset) - iprint("ehci %#p: port %d didn't reset within %d ms; sts %#lux\n", - ctlr->capio, port, i * 10, *portscp); - *portscp &= ~Psreset; /* force appearance of reset done */ - coherence(); - delay(10); /* ehci spec: enable within 2 ms. */ + iprint("ehci %#p: port %d didn't reset; sts %#ux\n", + ctlr->capio, port, *portscp); + delay(10); /* ehci spec: enable within 2 ms. */ if((*portscp & Psenable) == 0) portlend(ctlr, port, "full"); iunlock(ctlr); - dprint("ehci %#p after port %d reset; sts %#lux\n", + dprint("ehci %#p after port %d reset; sts %#ux\n", ctlr->capio, port, *portscp); qunlock(&ctlr->portlck); poperror(); @@ -1848,15 +1852,15 @@ xdump(char* pref, void *qh) { int i; - ulong *u; + u32int *u; u = qh; print("%s %#p:", pref, u); for(i = 0; i < 16; i++) if((i%4) == 0) - print("\n %#8.8ulx", u[i]); + print("\n %#.8ux", u[i]); else - print(" %#8.8ulx", u[i]); + print(" %#.8ux", u[i]); print("\n"); } @@ -2181,7 +2185,6 @@ Td *td; qh->state = Qdone; - coherence(); if(qh->sched >= 0 && (qh->eps0 & Qhspeedmask) != Qhhigh) qh->eps0 |= Qhint; /* inactivate on next pass */ coherence(); @@ -2189,8 +2192,8 @@ if(td->csw & Tdactive) td->ndata = 0; td->csw |= Tdhalt; - coherence(); } + coherence(); } /* @@ -2310,10 +2313,10 @@ aborttds(io->qh); io->err = "request timed out"; iunlock(ctlr); - if(!waserror()){ - tsleep(&up->sleep, return0, 0, Abortdelay); - poperror(); - } + while(waserror()) + ; + tsleep(&up->sleep, return0, 0, Abortdelay); + poperror(); ilock(ctlr); } if(qh->state != Qclose) @@ -2955,7 +2958,7 @@ ilock(ctlr); qh = io->qh; - if(io == nil || io->qh == nil || io->qh->state == Qclose){ + if(qh == nil || qh->state == Qclose){ iunlock(ctlr); return; } @@ -2964,10 +2967,10 @@ aborttds(qh); qh->state = Qclose; iunlock(ctlr); - if(!waserror()){ - tsleep(&up->sleep, return0, 0, Abortdelay); - poperror(); - } + while(waserror()) + ; + tsleep(&up->sleep, return0, 0, Abortdelay); + poperror(); wakeup(io); qlock(io); /* wait for epio if running */ @@ -3201,7 +3204,7 @@ opio = ctlr->opio; frsize = ctlr->nframes * sizeof(ulong); assert((frsize & 0xFFF) == 0); /* must be 4k aligned */ - ctlr->frames = xspanalloc(frsize, frsize, 0); + ctlr->frames = mallocalign(frsize, frsize, 0, 0); if(ctlr->frames == nil) panic("ehci reset: no memory"); @@ -3215,7 +3218,7 @@ mkqhtree(ctlr); /* init sync list */ edfree(edalloc()); /* try to get some ones pre-allocated */ - dprint("ehci %#p flb %#lux frno %#lux\n", + dprint("ehci %#p flb %#ux frno %#ux\n", ctlr->capio, opio->frbase, opio->frno); } --- /sys/src/nix/port/usbehci.c Sat Sep 21 22:13:49 2013 +++ /sys/src/nix/port/usbehci.c Sat Sep 21 22:13:52 2013 @@ -740,11 +740,12 @@ qlock(&ctlr->portlck); ctlr->opio->cmd |= Ciasync; /* ask for intr. on async advance */ coherence(); - for(i = 0; i < 3 && qhadvanced(ctlr) == 0; i++) - if(!waserror()){ - tsleep(ctlr, qhadvanced, ctlr, Abortdelay); - poperror(); - } + for(i = 0; i < 3 && qhadvanced(ctlr) == 0; i++){ + while(waserror()) + ; + tsleep(ctlr, qhadvanced, ctlr, Abortdelay); + poperror(); + } dprint("ehci: qhcoherency: doorbell %d\n", qhadvanced(ctlr)); if(i == 3) print("ehci: async advance doorbell did not ring\n"); @@ -772,6 +773,7 @@ coherence(); }else unschedq(ctlr, qh); + qh->state = Qfree; /* paranoia */ iunlock(ctlr); qhcoherency(ctlr); @@ -1532,7 +1534,6 @@ * This is Intel's doing. */ ilock(ctlr); - ctlr->nintr++; sts = opio->sts & Sintrs; if(sts == 0){ /* not ours; shared intr. */ iunlock(ctlr); @@ -1540,10 +1541,11 @@ } opio->sts = sts; coherence(); + ctlr->nintr++; if((sts & Sherr) != 0) - print("ehci: port %#p fatal host system error\n", ctlr->capio); + iprint("ehci: port %#p fatal host system error\n", ctlr->capio); if((sts & Shalted) != 0) - print("ehci: port %#p: halted\n", ctlr->capio); + iprint("ehci: port %#p: halted\n", ctlr->capio); if((sts & Sasync) != 0){ dprint("ehci: doorbell\n"); wakeup(ctlr); @@ -1557,12 +1559,12 @@ if((sts & (Serrintr|Sintr)) != 0){ ctlr->ntdintr++; if(ehcidebug > 1){ - print("ehci port %#p frames %#p nintr %d ntdintr %d", + iprint("ehci port %#p frames %#p nintr %d ntdintr %d", ctlr->capio, ctlr->frames, ctlr->nintr, ctlr->ntdintr); - print(" nqhintr %d nisointr %d\n", + iprint(" nqhintr %d nisointr %d\n", ctlr->nqhintr, ctlr->nisointr); - print("\tcmd %#ux sts %#ux intr %#ux frno %ud", + iprint("\tcmd %#ux sts %#ux intr %#ux frno %ud", opio->cmd, opio->sts, opio->intr, opio->frno); } @@ -1590,7 +1592,7 @@ qh = qh->next; }while(qh != ctlr->qhs && i++ < 100); if(i > 100) - print("echi: interrupt: qh loop?\n"); + iprint("echi: interrupt: qh loop?\n"); } // if (some == 0) // panic("ehciintr: no work"); @@ -1688,9 +1690,8 @@ if (opio->sts & Shalted) iprint("ehci %#p: halted yet trying to reset port\n", ctlr->capio); - *portscp = (*portscp & ~Psenable) | Psreset; /* initiate reset */ - coherence(); + *portscp = (*portscp & ~Psenable) | Psreset; /* initiate reset */ /* * usb 2 spec: reset must finish within 20 ms. * linux says spec says it can take 50 ms. for hubs. @@ -1703,10 +1704,10 @@ delay(10); if (*portscp & Psreset) - iprint("ehci %#p: port %d didn't reset sts %#ux\n", + iprint("ehci %#p: port %d didn't reset; sts %#ux\n", ctlr->capio, port, *portscp); - delay(10); /* ehci spec: enable within 2 ms. */ + delay(10); /* ehci spec: enable within 2 ms. */ if((*portscp & Psenable) == 0) portlend(ctlr, port, "full"); @@ -2184,7 +2185,6 @@ Td *td; qh->state = Qdone; - coherence(); if(qh->sched >= 0 && (qh->eps0 & Qhspeedmask) != Qhhigh) qh->eps0 |= Qhint; /* inactivate on next pass */ coherence(); @@ -2192,8 +2192,8 @@ if(td->csw & Tdactive) td->ndata = 0; td->csw |= Tdhalt; - coherence(); } + coherence(); } /* @@ -2313,10 +2313,10 @@ aborttds(io->qh); io->err = "request timed out"; iunlock(ctlr); - if(!waserror()){ - tsleep(&up->sleep, return0, 0, Abortdelay); - poperror(); - } + while(waserror()) + ; + tsleep(&up->sleep, return0, 0, Abortdelay); + poperror(); ilock(ctlr); } if(qh->state != Qclose) @@ -2958,7 +2958,7 @@ ilock(ctlr); qh = io->qh; - if(io == nil || io->qh == nil || io->qh->state == Qclose){ + if(qh == nil || qh->state == Qclose){ iunlock(ctlr); return; } @@ -2967,10 +2967,10 @@ aborttds(qh); qh->state = Qclose; iunlock(ctlr); - if(!waserror()){ - tsleep(&up->sleep, return0, 0, Abortdelay); - poperror(); - } + while(waserror()) + ; + tsleep(&up->sleep, return0, 0, Abortdelay); + poperror(); wakeup(io); qlock(io); /* wait for epio if running */ --- /sys/src/nix/k10/usbehcipc.c Sat Sep 21 22:13:53 2013 +++ /sys/src/nix/k10/usbehcipc.c Sat Sep 21 22:13:54 2013 @@ -113,7 +113,7 @@ ctlr->nframes = 256; break; default: - panic("ehci: unknown fls %ld", opio->cmd & Cflsmask); + panic("ehci: unknown fls %d", opio->cmd & Cflsmask); } dprint("ehci: %d frames\n", ctlr->nframes); iunlock(ctlr);