diff options
| author | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-07-17 21:10:25 +0200 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-07-17 21:10:25 +0200 |
| commit | 40dc39bf7d8d17a84d6a2a427ca7facd8b2cb66b (patch) | |
| tree | 97f6dac4f9fcd5b38b695d99b1a88370310a6659 | |
| parent | eee7357c2778a65a3ecf552ac44b9a419e6e92d9 (diff) | |
| download | plan9front-40dc39bf7d8d17a84d6a2a427ca7facd8b2cb66b.tar.xz | |
usbxhci: better approach to unstalling endpoint and fixup td ring
instead of guessing where the controllers dequeue pointer went,
stop the endpoint and then explicitely set te dequeue pointer to
the next write td position. that way we do not need to fix the cycle
bit in the td's and dont need to rely on if the controller
advanced the dequeue pointer after a stall or not.
add ctx and slot back pointers to ring.
| -rw-r--r-- | sys/src/9/pc/usbxhci.c | 115 |
1 files changed, 43 insertions, 72 deletions
diff --git a/sys/src/9/pc/usbxhci.c b/sys/src/9/pc/usbxhci.c index 8b7983f34..45e502c91 100644 --- a/sys/src/9/pc/usbxhci.c +++ b/sys/src/9/pc/usbxhci.c @@ -159,6 +159,10 @@ struct Wait struct Ring { + int id; + + Slot *slot; + u32int *base; u32int size; @@ -168,10 +172,8 @@ struct Ring u32int rp; u32int wp; - struct { - u32int *r; - u32int v; - } doorbell; + u32int *ctx; + u32int *doorbell; Wait *pending; Lock; @@ -264,8 +266,10 @@ freering(Ring *r) static void initring(Ring *r, int shift) { - r->doorbell.v = 0; - r->doorbell.r = nil; + r->id = 0; + r->ctx = nil; + r->slot = nil; + r->doorbell = nil; r->pending = nil; r->shift = shift; r->size = 1<<shift; @@ -337,8 +341,8 @@ init(Hci *hp) ctlr->setrptr(&ctlr->opr[DCBAAP], PADDR(ctlr->dcba)); initring(ctlr->cr, 8); /* 256 entries */ - ctlr->cr->doorbell.r = &ctlr->dba[0]; - ctlr->cr->doorbell.v = 0; + ctlr->cr->doorbell = &ctlr->dba[0]; + ctlr->cr->id = 0; coherence(); ctlr->setrptr(&ctlr->opr[CRCR], PADDR(ctlr->cr[0].base) | 1); @@ -464,7 +468,7 @@ static void kickring(Ring *r) { coherence(); - *r->doorbell.r = r->doorbell.v; + *r->doorbell = r->id; } static char* @@ -742,8 +746,10 @@ initep(Ep *ep) } if(ep->mode != OREAD){ initring(io->ring[OWRITE] = &slot->epr[ep->nb*2-1], 8); - io->ring[OWRITE]->doorbell.r = &ctlr->dba[slot->id]; - io->ring[OWRITE]->doorbell.v = ep->nb*2; + io->ring[OWRITE]->doorbell = &ctlr->dba[slot->id]; + io->ring[OWRITE]->slot = slot; + io->ring[OWRITE]->ctx = &slot->obase[(ep->nb*2+0)*8<<ctlr->csz]; + io->ring[OWRITE]->id = ep->nb*2; w[1] |= 1 << ep->nb*2; if(ep->nb*2 > slot->nep) @@ -751,8 +757,10 @@ initep(Ep *ep) } if(ep->mode != OWRITE){ initring(io->ring[OREAD] = &slot->epr[ep->nb*2], 8); - io->ring[OREAD]->doorbell.r = &ctlr->dba[slot->id]; - io->ring[OREAD]->doorbell.v = ep->nb*2+1; + io->ring[OREAD]->doorbell = &ctlr->dba[slot->id]; + io->ring[OREAD]->slot = slot; + io->ring[OREAD]->ctx = &slot->obase[(ep->nb*2+1)*8<<ctlr->csz]; + io->ring[OREAD]->id = ep->nb*2+1; w[1] |= 2 << ep->nb*2; if(ep->nb*2+1 > slot->nep) @@ -849,8 +857,10 @@ epopen(Ep *ep) /* allocate control ep 0 ring */ initring(io->ring[OWRITE] = &slot->epr[0], 8); - io->ring[OWRITE]->doorbell.r = &ctlr->dba[slot->id]; - io->ring[OWRITE]->doorbell.v = 1; + io->ring[OWRITE]->doorbell = &ctlr->dba[slot->id]; + io->ring[OWRITE]->slot = slot; + io->ring[OWRITE]->ctx = &slot->obase[8]; + io->ring[OWRITE]->id = 1; slot->nep = 1; /* (input) control context */ @@ -905,60 +915,21 @@ epopen(Ep *ep) } static void -resetring(Ring *r) +unstall(Ring *r) { - ilock(r); - r->rp--; /* assume previous td halted */ - while((int)(r->wp - r->rp) > 0){ - u32int *td = &r->base[4*(--r->wp & r->mask)]; - td[0] = td[1] = td[2] = 0; - td[3] = (r->wp>>r->shift)&1; + u64int qp; + + switch(r->ctx[0]&7){ + case 2: + case 4: + ilock(r); + r->rp = r->wp; + qp = PADDR(&r->base[4*(r->wp & r->mask)]) | ((~r->wp>>r->shift) & 1); + iunlock(r); + + ctlrcmd(r->slot->ctlr, CR_RESETEP | (r->id<<16) | (r->slot->id<<24), 0, 0, nil); + ctlrcmd(r->slot->ctlr, CR_SETTRDQP | (r->id<<16) | (r->slot->id<<24), 0, qp, nil); } - iunlock(r); -} - -static int -epunstall(Ep *ep, int mode) -{ - Ctlr *ctlr; - Slot *slot; - Epio *io; - u32int *w; - int dci, ret; - - ret = 0; - io = ep->aux; - slot = ep->dev->aux; - ctlr = slot->ctlr; - - if(ep->nb == 0) - dci = 1; - else - dci = ep->nb*2; - - /* (output) ep context */ - w = slot->obase; - w += dci*8<<ctlr->csz; - if(mode != OREAD && io->ring[OWRITE] != nil){ - switch(w[0]&7){ - case 2: - case 4: - resetring(io->ring[OWRITE]); - ctlrcmd(ctlr, CR_RESETEP | (dci<<16) | (slot->id<<24), 0, 0, nil); - ret++; - } - } - w += 8<<ctlr->csz, dci++; - if(mode != OWRITE && io->ring[OREAD] != nil){ - switch(w[0]&7){ - case 2: - case 4: - resetring(io->ring[OREAD]); - ctlrcmd(ctlr, CR_RESETEP | (dci<<16) | (slot->id<<24), 0, 0, nil); - ret++; - } - } - return ret; } static long @@ -972,6 +943,7 @@ epread(Ep *ep, void *va, long n) p = va; io = ep->aux; + if(ep->ttype == Tctl){ qlock(io); if(io->cb == nil || BLEN(io->cb) == 0){ @@ -1001,8 +973,8 @@ epread(Ep *ep, void *va, long n) return n; } - epunstall(ep, OREAD); ring = io->ring[OREAD]; + unstall(ring); ilock(ring); queuetd(ring, TR_NORMAL | 1<<16 | 1<<5, n, PADDR(p), ws); iunlock(ring); @@ -1028,6 +1000,7 @@ epwrite(Ep *ep, void *va, long n) p = va; io = ep->aux; + if(ep->ttype == Tctl){ int dir, len; @@ -1059,8 +1032,8 @@ epwrite(Ep *ep, void *va, long n) } } - epunstall(ep, OWRITE); ring = io->ring[OWRITE]; + unstall(ring); ilock(ring); queuetd(ring, TR_SETUPSTAGE | (len > 0 ? 2+dir : 0)<<16 | 1<<6 | 1<<5, 8, p[0] | p[1]<<8 | GET2(&p[2])<<16 | @@ -1104,8 +1077,8 @@ epwrite(Ep *ep, void *va, long n) return n; } - epunstall(ep, OWRITE); ring = io->ring[OWRITE]; + unstall(ring); ilock(ring); queuetd(ring, TR_NORMAL | 1<<16 | 1<<5, n, PADDR(p), ws); iunlock(ring); @@ -1238,8 +1211,6 @@ reset(Hci *hp) if(getconf("*nousbxhci")) return -1; - fmtinstall(L'H', encodefmt); - scanpci(); /* |
