summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-09-22 18:51:41 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-09-22 18:51:41 +0200
commit490c3d87cb558a8cfe8ad4db9f39c9cb3df91d17 (patch)
treedcc54936a4b2f2aa8fa15d6686ea475ce2e5d59c /sys/src
parent71a1d11a81faba020649408e8c9eaeb10095a341 (diff)
usbxhci: fix endpoint stall recovery, handle Ep.clrhalt flag
after issuing CR_RESETEP command, we have to invalidate the endpoints output context buffer so that the halted/error status reflects the new state. not doing so resulted in the halted state to be stuck and we continued issuing endpoint reset commands when we where already recovered. handle the devusb Ep.clrhalt flag from devusb that userspace uses to force a endpoint reset on the next transaction.
Diffstat (limited to 'sys/src')
-rw-r--r--sys/src/9/port/usbxhci.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/sys/src/9/port/usbxhci.c b/sys/src/9/port/usbxhci.c
index f1ce6d8ab..ab30aa040 100644
--- a/sys/src/9/port/usbxhci.c
+++ b/sys/src/9/port/usbxhci.c
@@ -1368,20 +1368,26 @@ isowrite(Ep *ep, uchar *p, long n)
}
static char*
-unstall(Ring *r)
+unstall(Ep *ep, Ring *r)
{
char *err;
switch(r->ctx[0]&7){
case 2: /* halted */
case 4: /* error */
- r->stopped = 1;
+ ep->clrhalt = 1;
+ }
+ if(ep->clrhalt){
+ ep->clrhalt = 0;
err = ctlrcmd(r->slot->ctlr, CR_RESETEP | (r->id<<16) | (r->slot->id<<24), 0, 0, nil);
+ dmaflush(0, r->ctx, 8*4 << r->slot->ctlr->csz);
if(err != nil)
return err;
+ r->stopped = 1;
}
if(r->stopped){
err = ctlrcmd(r->slot->ctlr, CR_SETTRDQP | (r->id<<16) | (r->slot->id<<24), 0, resetring(r), nil);
+ dmaflush(0, r->ctx, 8*4 << r->slot->ctlr->csz);
if(err != nil)
return err;
r->stopped = 0;
@@ -1444,7 +1450,7 @@ epread(Ep *ep, void *va, long n)
nexterror();
}
- if((err = unstall(io->ring)) != nil)
+ if((err = unstall(ep, io->ring)) != nil)
error(err);
dmaflush(1, p, n);
@@ -1517,7 +1523,7 @@ epwrite(Ep *ep, void *va, long n)
io->b->wp += len;
}
}
- if((err = unstall(ring)) != nil)
+ if((err = unstall(ep, ring)) != nil)
error(err);
if((ring->ctx[1]>>16) != ep->maxpkt){
@@ -1596,7 +1602,7 @@ epwrite(Ep *ep, void *va, long n)
nexterror();
}
- if((err = unstall(io->ring)) != nil)
+ if((err = unstall(ep, io->ring)) != nil)
error(err);
dmaflush(1, p, n);