git: 9front

Download patch

ref: a035fa013e92d436806dac855c4dd772292e4c20
parent: 74db0f96a8251c01d2b5138f9224b7daab6cc9b6
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Jul 2 01:34:13 EDT 2019

usbxhci: fix mysterious ENABLESLOT failures (update to XHCI spec revision 1.2 (2019))

Ori Bernstein had Sunrise Point-H USB 3.0 xHCI Controller that would mysteriously
crash on the 5th ENABLESLOT command. This was reproducable by even just allocating
slots in a loop right after init.

It turns out, the 1.2 spec extended the Max Scratchpad Buffers in HCSPARAMS2 so our
driver would not allocate enougth scratchpad buffers and controller firmware would
crash once it went beyond our allocated scratchpad buffer array.

This change also fixes:

- ignore bits 16:31 in PAGESIZE register
- preserve bits 10:31 in the CONFIG register
- handle ADDESSDEV command failure (so it can be retried)

--- a/sys/src/9/pc/usbxhci.c
+++ b/sys/src/9/pc/usbxhci.c
@@ -483,9 +483,9 @@
 		ctlr->setrptr = setrptr64;
 	else
 		ctlr->setrptr = setrptr32;
-	ctlr->pagesize = ctlr->opr[PAGESIZE]<<12;
+	ctlr->pagesize = (ctlr->opr[PAGESIZE] & 0xFFFF) << 12;
 
-	ctlr->nscratch = (ctlr->mmio[HCSPARAMS2] >> 27) & 0x1F;
+	ctlr->nscratch = (ctlr->mmio[HCSPARAMS2] >> 27) & 0x1F | (ctlr->mmio[HCSPARAMS2] >> 16) & 0x3E0;
 	ctlr->nintrs = (ctlr->mmio[HCSPARAMS1] >> 8) & 0x7FF;
 	ctlr->nslots = (ctlr->mmio[HCSPARAMS1] >> 0) & 0xFF;
 
@@ -533,7 +533,7 @@
 	}
 	for(i=1; i<=ctlr->nslots; i++)
 		ctlr->dcba[i] = 0;
-	ctlr->opr[CONFIG] = ctlr->nslots;	/* MaxSlotsEn */
+	ctlr->opr[CONFIG] = (ctlr->opr[CONFIG] & 0xFFFFFC00) | ctlr->nslots;	/* MaxSlotsEn */
 	ctlr->setrptr(&ctlr->opr[DCBAAP], PADDR(ctlr->dcba));
 
 	initring(ctlr->cr, 8);		/* 256 entries */
@@ -970,9 +970,6 @@
 	ctlr->slot[slot->id] = slot;
 	qunlock(&ctlr->slotlock);
 
-	dev->aux = slot;
-	dev->free = freeslot;
-
 	return slot;
 }
 
@@ -1198,6 +1195,10 @@
 		error(Egreg);
 
 	slot = allocslot(ctlr, dev);
+	if(waserror()){
+		freeslot(slot);
+		nexterror();
+	}
 
 	/* allocate control ep 0 ring */
 	ring = initring(io[OWRITE].ring = &slot->epr[0], 4);
@@ -1253,7 +1254,13 @@
 
 	/* (output) slot context */
 	w = slot->obase;
-	ep->dev->addr = w[3] & 0xFF;
+
+	dev->addr = w[3] & 0xFF;
+
+	dev->aux = slot;
+	dev->free = freeslot;
+
+	poperror();
 	poperror();
 }
 
--