summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-04-19 23:39:47 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-04-19 23:39:47 +0200
commita0da5b973ffa098e428c574104e270b600770f9a (patch)
tree39875c3b77317bee52d5edf0f2babbeb9d75cf9b
parent6bceabbc79b9c60a18dae90b1618eddbf7737275 (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.c23
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);