summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-07-02 05:34:13 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-07-02 05:34:13 +0200
commit54f9b36720ee3201dfd5a2524cdbf836edf5914f (patch)
treeee5ce8a34bf336475c86a1189d20ee7b00e56940
parentb2c7a8d84a0075fea104009115d0c34bffc39e06 (diff)
downloadplan9front-54f9b36720ee3201dfd5a2524cdbf836edf5914f.tar.xz
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)
-rw-r--r--sys/src/9/pc/usbxhci.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/sys/src/9/pc/usbxhci.c b/sys/src/9/pc/usbxhci.c
index 9c9ad60eb..2a73e3109 100644
--- a/sys/src/9/pc/usbxhci.c
+++ b/sys/src/9/pc/usbxhci.c
@@ -483,9 +483,9 @@ init(Hci *hp)
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 @@ init(Hci *hp)
}
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 @@ allocslot(Ctlr *ctlr, Udev *dev)
ctlr->slot[slot->id] = slot;
qunlock(&ctlr->slotlock);
- dev->aux = slot;
- dev->free = freeslot;
-
return slot;
}
@@ -1198,6 +1195,10 @@ epopen(Ep *ep)
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 @@ epopen(Ep *ep)
/* (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();
}