usbehci: fix crash in cancelisoio() for highspeed device due to wrong pollival

This commit is contained in:
cinap_lenrek 2017-07-31 03:07:14 +02:00
parent adfb0e9371
commit d46099e3af

View file

@ -2000,7 +2000,7 @@ episoread(Ep *ep, Isoio *iso, void *a, long count)
iunlock(ctlr); iunlock(ctlr);
qunlock(iso); qunlock(iso);
poperror(); 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) if(iso->err != nil)
error(iso->err); error(iso->err);
return tot; return tot;
@ -2691,6 +2691,7 @@ isofsinit(Ep *ep, Isoio *iso)
ulong frno; ulong frno;
Ctlr *ctlr; Ctlr *ctlr;
iso->hs = 0;
ctlr = ep->hp->aux; ctlr = ep->hp->aux;
left = 0; left = 0;
ltd = nil; ltd = nil;
@ -2742,9 +2743,7 @@ isohsinit(Ep *ep, Isoio *iso)
Ctlr *ctlr; Ctlr *ctlr;
iso->hs = 1; iso->hs = 1;
ival = 1; ival = (ep->pollival+7)/8;
if(ep->pollival > 8)
ival = ep->pollival/8;
ctlr = ep->hp->aux; ctlr = ep->hp->aux;
left = 0; left = 0;
ltd = nil; ltd = nil;
@ -2807,19 +2806,17 @@ isoopen(Ctlr *ctlr, Ep *ep)
iso->state = Qidle; iso->state = Qidle;
coherence(); coherence();
iso->debug = ep->debug; iso->debug = ep->debug;
ival = ep->pollival;
tpf = 1; tpf = 1;
ival = ep->pollival;
if(ep->dev->speed == Highspeed){ if(ep->dev->speed == Highspeed){
tpf = 8; tpf = 8;
if(ival <= 8) ival = (ival+7)/8;
ival = 1;
else
ival /= 8;
} }
assert(ival != 0); if(ival < 1)
error("bad pollival");
iso->nframes = Nisoframes / ival; iso->nframes = Nisoframes / ival;
if(iso->nframes < 3) 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; iso->maxsize = ep->ntds * ep->maxpkt;
if(ctlr->load + ep->load > 800) if(ctlr->load + ep->load > 800)
print("usb: ehci: bandwidth may be exceeded\n"); print("usb: ehci: bandwidth may be exceeded\n");
@ -2881,7 +2878,7 @@ isoopen(Ctlr *ctlr, Ep *ep)
ctlr->frames[woff+frno] = PADDR(iso->tdps[frno]) ctlr->frames[woff+frno] = PADDR(iso->tdps[frno])
|Lsitd; |Lsitd;
coherence(); coherence();
frno = TRUNC(frno+ep->pollival, Nisoframes); frno = TRUNC(frno+ival, Nisoframes);
} }
} }
coherence(); coherence();
@ -3002,7 +2999,7 @@ cancelio(Ctlr *ctlr, Qio *io)
} }
static void 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; int frno, i, n, t, w, woff;
ulong *lp, *tp; ulong *lp, *tp;
@ -3031,6 +3028,8 @@ cancelisoio(Ctlr *ctlr, Isoio *iso, int pollival, ulong load)
panic("cancleiso: not found"); panic("cancleiso: not found");
*il = iso->next; *il = iso->next;
if(iso->hs)
ival = (ival+7)/8;
frno = iso->td0frno; frno = iso->td0frno;
for(i = 0; i < iso->nframes; i++){ for(i = 0; i < iso->nframes; i++){
tp = iso->tdps[frno]; tp = iso->tdps[frno];
@ -3062,7 +3061,7 @@ cancelisoio(Ctlr *ctlr, Isoio *iso, int pollival, ulong load)
} }
} }
coherence(); coherence();
frno = TRUNC(frno+pollival, Nisoframes); frno = TRUNC(frno+ival, Nisoframes);
} }
iunlock(ctlr); iunlock(ctlr);
@ -3085,7 +3084,7 @@ cancelisoio(Ctlr *ctlr, Isoio *iso, int pollival, ulong load)
else else
sitdfree(ctlr, iso->sitdps[frno]); sitdfree(ctlr, iso->sitdps[frno]);
iso->tdps[frno] = nil; iso->tdps[frno] = nil;
frno = TRUNC(frno+pollival, Nisoframes); frno = TRUNC(frno+ival, Nisoframes);
} }
free(iso->tdps); free(iso->tdps);
iso->tdps = nil; iso->tdps = nil;