summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2017-07-17 21:10:25 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2017-07-17 21:10:25 +0200
commit40dc39bf7d8d17a84d6a2a427ca7facd8b2cb66b (patch)
tree97f6dac4f9fcd5b38b695d99b1a88370310a6659
parenteee7357c2778a65a3ecf552ac44b9a419e6e92d9 (diff)
downloadplan9front-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.c115
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();
/*