shithub: riscv

Download patch

ref: a0da5b973ffa098e428c574104e270b600770f9a
parent: 6bceabbc79b9c60a18dae90b1618eddbf7737275
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Apr 19 19:39:47 EDT 2019

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.

--- a/sys/src/9/pc/usbxhci.c
+++ b/sys/src/9/pc/usbxhci.c
@@ -753,14 +753,23 @@
 	*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);