]> git.lizzy.rs Git - plan9front.git/commitdiff
usbxhci: fix mysterious ENABLESLOT failures (update to XHCI spec revision 1.2 (2019))
authorcinap_lenrek <cinap_lenrek@felloff.net>
Tue, 2 Jul 2019 03:34:13 +0000 (05:34 +0200)
committercinap_lenrek <cinap_lenrek@felloff.net>
Tue, 2 Jul 2019 03:34:13 +0000 (05:34 +0200)
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)

sys/src/9/pc/usbxhci.c

index 9c9ad60eb4b0ecc089264ef028a46d48ba3a83f8..2a73e31096549997a80b5a8d0699b9de0868ffad 100644 (file)
@@ -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();
 }