diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-04-19 23:39:47 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-04-19 23:39:47 +0200 |
commit | a0da5b973ffa098e428c574104e270b600770f9a (patch) | |
tree | 39875c3b77317bee52d5edf0f2babbeb9d75cf9b | |
parent | 6bceabbc79b9c60a18dae90b1618eddbf7737275 (diff) |
usbxhci: make stuck usb transactions interruptable.
some control transactions can confuse the xhci controller so
much that it even fails to respond to command abort or STOPEP
control command. with no way for us to abort the transaction
but a full controller reset.
we give the controller 5 seconds to abort our initial
transaction and if that fails we wake the recover process
to reset the controller.
thanks mischief for testing.
-rw-r--r-- | sys/src/9/pc/usbxhci.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/sys/src/9/pc/usbxhci.c b/sys/src/9/pc/usbxhci.c index 653fdb0ca..9c9ad60eb 100644 --- a/sys/src/9/pc/usbxhci.c +++ b/sys/src/9/pc/usbxhci.c @@ -753,14 +753,23 @@ waittd(Ctlr *ctlr, Wait *w, int tmout) *r->doorbell = r->id; while(waserror()){ - if(!r->stopped) { - if(r == ctlr->cr) - ctlr->opr[CRCR] |= CA; - else - ctlrcmd(ctlr, CR_STOPEP | (r->id<<16) | (r->slot->id<<24), 0, 0, nil); - r->stopped = 1; + if(r->stopped) { + ctlr->er->stopped = 1; + wakeup(&ctlr->recover); + + /* wait for rescue */ + tmout = 0; + continue; } - tmout = 0; + + if(r == ctlr->cr) + ctlr->opr[CRCR] |= CA; + else + ctlrcmd(ctlr, CR_STOPEP | (r->id<<16) | (r->slot->id<<24), 0, 0, nil); + r->stopped = 1; + + /* time to abort the transaction */ + tmout = 5000; } if(tmout > 0){ tsleep(&up->sleep, waitdone, w, tmout); |