ref: d46099e3afa9681a4f98e0d2574c2ad65820ed7e
parent: adfb0e9371752ffb8d9995d4678e6bfa24c75f60
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jul 30 23:07:14 EDT 2017
usbehci: fix crash in cancelisoio() for highspeed device due to wrong pollival
--- a/sys/src/9/port/usbehci.c
+++ b/sys/src/9/port/usbehci.c
@@ -2000,7 +2000,7 @@
iunlock(ctlr);
qunlock(iso);
poperror();
- diprint("uhci: episoread: %#p %uld bytes err '%s'\n", iso, tot, iso->err);
+ diprint("ehci: episoread: %#p %uld bytes err '%s'\n", iso, tot, iso->err);
if(iso->err != nil)
error(iso->err);
return tot;
@@ -2691,6 +2691,7 @@
ulong frno;
Ctlr *ctlr;
+ iso->hs = 0;
ctlr = ep->hp->aux;
left = 0;
ltd = nil;
@@ -2742,9 +2743,7 @@
Ctlr *ctlr;
iso->hs = 1;
- ival = 1;
- if(ep->pollival > 8)
- ival = ep->pollival/8;
+ ival = (ep->pollival+7)/8;
ctlr = ep->hp->aux;
left = 0;
ltd = nil;
@@ -2807,19 +2806,17 @@
iso->state = Qidle;
coherence();
iso->debug = ep->debug;
- ival = ep->pollival;
tpf = 1;
+ ival = ep->pollival;
if(ep->dev->speed == Highspeed){
tpf = 8;
- if(ival <= 8)
- ival = 1;
- else
- ival /= 8;
+ ival = (ival+7)/8;
}
- assert(ival != 0);
+ if(ival < 1)
+ error("bad pollival");
iso->nframes = Nisoframes / ival;
if(iso->nframes < 3)
- error("uhci isoopen bug"); /* we need at least 3 tds */
+ error("ehci isoopen bug"); /* we need at least 3 tds */
iso->maxsize = ep->ntds * ep->maxpkt;
if(ctlr->load + ep->load > 800)
print("usb: ehci: bandwidth may be exceeded\n");
@@ -2871,7 +2868,7 @@
for(w = 0; w < n; w++){
frno = iso->td0frno;
woff = w * Nisoframes;
- for(i = 0; i < iso->nframes ; i++){
+ for(i = 0; i < iso->nframes; i++){
assert(woff+frno < ctlr->nframes);
assert(iso->tdps[frno] != nil);
if(ep->dev->speed == Highspeed)
@@ -2881,7 +2878,7 @@
ctlr->frames[woff+frno] = PADDR(iso->tdps[frno])
|Lsitd;
coherence();
- frno = TRUNC(frno+ep->pollival, Nisoframes);
+ frno = TRUNC(frno+ival, Nisoframes);
}
}
coherence();
@@ -3002,7 +2999,7 @@
}
static void
-cancelisoio(Ctlr *ctlr, Isoio *iso, int pollival, ulong load)
+cancelisoio(Ctlr *ctlr, Isoio *iso, int ival, ulong load)
{
int frno, i, n, t, w, woff;
ulong *lp, *tp;
@@ -3031,6 +3028,8 @@
panic("cancleiso: not found");
*il = iso->next;
+ if(iso->hs)
+ ival = (ival+7)/8;
frno = iso->td0frno;
for(i = 0; i < iso->nframes; i++){
tp = iso->tdps[frno];
@@ -3062,7 +3061,7 @@
}
}
coherence();
- frno = TRUNC(frno+pollival, Nisoframes);
+ frno = TRUNC(frno+ival, Nisoframes);
}
iunlock(ctlr);
@@ -3085,7 +3084,7 @@
else
sitdfree(ctlr, iso->sitdps[frno]);
iso->tdps[frno] = nil;
- frno = TRUNC(frno+pollival, Nisoframes);
+ frno = TRUNC(frno+ival, Nisoframes);
}
free(iso->tdps);
iso->tdps = nil;