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.
This commit is contained in:
cinap_lenrek 2019-09-22 18:51:41 +02:00
parent 71a1d11a81
commit 490c3d87cb

View file

@ -1368,20 +1368,26 @@ isowrite(Ep *ep, uchar *p, long n)
} }
static char* static char*
unstall(Ring *r) unstall(Ep *ep, Ring *r)
{ {
char *err; char *err;
switch(r->ctx[0]&7){ switch(r->ctx[0]&7){
case 2: /* halted */ case 2: /* halted */
case 4: /* error */ 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); 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) if(err != nil)
return err; return err;
r->stopped = 1;
} }
if(r->stopped){ if(r->stopped){
err = ctlrcmd(r->slot->ctlr, CR_SETTRDQP | (r->id<<16) | (r->slot->id<<24), 0, resetring(r), nil); 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) if(err != nil)
return err; return err;
r->stopped = 0; r->stopped = 0;
@ -1444,7 +1450,7 @@ epread(Ep *ep, void *va, long n)
nexterror(); nexterror();
} }
if((err = unstall(io->ring)) != nil) if((err = unstall(ep, io->ring)) != nil)
error(err); error(err);
dmaflush(1, p, n); dmaflush(1, p, n);
@ -1517,7 +1523,7 @@ epwrite(Ep *ep, void *va, long n)
io->b->wp += len; io->b->wp += len;
} }
} }
if((err = unstall(ring)) != nil) if((err = unstall(ep, ring)) != nil)
error(err); error(err);
if((ring->ctx[1]>>16) != ep->maxpkt){ if((ring->ctx[1]>>16) != ep->maxpkt){
@ -1596,7 +1602,7 @@ epwrite(Ep *ep, void *va, long n)
nexterror(); nexterror();
} }
if((err = unstall(io->ring)) != nil) if((err = unstall(ep, io->ring)) != nil)
error(err); error(err);
dmaflush(1, p, n); dmaflush(1, p, n);