some support for the second interface. it doesn't work, but at least we see it. Reference: /n/atom/patch/applied/duali40 Date: Thu Jun 12 04:53:08 CES 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/k10/etheri40.c Thu Jun 12 04:52:06 2014 +++ /sys/src/nix/k10/etheri40.c Thu Jun 12 04:52:09 2014 @@ -487,6 +487,8 @@ Mb1 = 1<<6, /* must be 1 */ Rs = 1<<5, Teop = 1<<4, + Txdesc = 0<<0, + Nopdesc = 1<<0, /* Td status */ Tdd = 0xf<<0, @@ -512,7 +514,7 @@ Hmcpgsz = 4096, Hmcalign = 4096, Fpdeperpage = Hmcpgsz/sizeof(FPDE), - Fpgshift = 9, + Fpgshift = 12, Fpdevalid = 1<<0, }; @@ -548,7 +550,7 @@ Block **rb; uint rdt, rdfree; Td *tdba; - uint tdh, tdt; + uint tdh, tdt, tdfree; Block **tb; uchar ra[Eaddrlen]; uvlong zstats[nelem(stattab)]; @@ -556,8 +558,10 @@ uchar *rxbuf; int type; uint speeds[5]; - uint nobufs; -/**/ uvlong irqcnt[4]; + uint phy; + uint nobufs, txfull; + uvlong irqcnt[4]; + char ename[16]; }; struct Rbpool { @@ -575,6 +579,8 @@ union { struct { Block *x; + uvlong fasttick; + uvlong slowtick; uint nfast; uint nslow; }; @@ -585,7 +591,7 @@ /* tweakable parameters */ enum{ Nrd = 256, /* 2ⁿ */ - Ntd = 256, /* 2ⁿ */ + Ntd = 2*256, /* 2ⁿ */ Nrb = 2048, Nctlr = 8, Rbalign = 8, @@ -642,7 +648,24 @@ return cttab[c->type].name; } -int +static char* +ename(Ether *e) +{ + Ctlr *c; + + c = e->ctlr; + if(c->ename[0] == 0) + snprint(c->ename, sizeof c->ename, "#l%d: %s:pf %d", + e->ctlrno, cname(c), c->pf); + return c->ename; +} + +static void +readclear(u32int) +{ +} + +static int seidtovsiid(int i) { return i-512; @@ -675,6 +698,7 @@ uint i; uvlong v, *stats; Ctlr *c; + Rbpool *r; c = e->ctlr; p = s = malloc(READSTR + nelem(stattab)*sizeof(uvlong)); @@ -692,12 +716,20 @@ if((v = stats[i] - c->zvstats[i])>0) p = seprint(p, q, "%.10s %llud\n", vstattab[i].name, v); p = seprint(p, q, "type: %s\n", cttab[c->type].name); + r = c->pool; + p = seprint(p, q, "pool: fast %d %llud slow %d %lld starve %d wake %d on %d\n", + r->nfast, r->fasttick, + r->nslow, r->slowtick, + r->nstarve, r->nwakey, r->starve); p = seprint(p, q, "speeds:"); for(i = 0; i < nelem(c->speeds); i++) p = seprint(p, q, " %d:%d", speeds[i], c->speeds[i]); p = seprint(p, q, "\n"); - p = seprint(p, q, "irqcnt: a %lld r %lld t %lld s %lld\n", c->irqcnt[Cnta], c->irqcnt[Cntr], c->irqcnt[Cntt], c->irqcnt[Cnts]); + p = seprint(p, q, "phy: %.2ux\n", c->phy); + p = seprint(p, q, "irqcnt: a %lld r %lld t %lld s %lld\n", + c->irqcnt[Cnta], c->irqcnt[Cntr], c->irqcnt[Cntt], c->irqcnt[Cnts]); seprint(p, q, "nobufs: %ud\n", c->nobufs); + seprint(p, q, "txfull: %ud\n", c->txfull); n = readstr(offset, a, n, s); free(s); @@ -764,8 +796,9 @@ e->link = link; e->mbps = speeds[i]; c->speeds[i]++; + c->phy = b[0]; - print("link %d; mbps %d; an %d; phy %.2ux\n", e->link, e->mbps, b[3] & 1<<0, b[0]); +// print("link %d; mbps %d; an %d; phy %.2ux\n", e->link, e->mbps, b[3] & 1<<0, b[0]); return 0; } @@ -779,6 +812,18 @@ } static void +txim(Ctlr *c, int on) +{ + c->reg[Itxqctl + 0] = Itxidx*Iqirqidx | Iqend | on*Iqenable; /* tx: ics=0x02 */ +} + +static void +rxim(Ctlr *c, int on) +{ + c->reg[Irxqctl + 0] = Irxidx*Iqirqidx | 0*Iqnxtqidx | Iqnxtt | on*Iqenable; /* tx: ics=0x04 */ +} + +static void qrx(Ether *e, Ctlr *c, Ad *a) { switch(a->op){ @@ -815,10 +860,28 @@ c->aim = 0; if(oldaim & (Eccerr | Malice | Grst | Pcierr)){ - print("%s: err %.8ux; we're doomed\n", cname(c), oldaim & Errint); + print("%s: err %.8ux; we're doomed\n", ename(e), oldaim & Errint); } if(oldaim & Errint){ - print("hmerr %.8ux %.8ux\n", c->reg[Hmerr+c->pf], c->reg[Hmerrd+c->pf]); + /* + * 0:4 pf + * 8:11 error + * 0 private memory fn invalid + * 1 invalid lan queue idx + * 2 object index larger than glhmc_*cnt + * 3 address beyond pf's segment limits + * 4 invalid segment descriptor + * 5 sd too small + * 6 page descriptor invalid + * 7 unsupported pcie read + * 8 pflan_qalloc_pmat or pf_vt_pfalloc_pmat unset + * 9 invalid object type + * 10 invalid fcoe idx + * 16:20 object type (tx=0, rx=1) + * 31 error detected + */ + print("%s: hmcerr %.8ux %.8ux\n", ename(e), + c->reg[Hmerr+c->pf], c->reg[Hmerrd+c->pf]); } /* * fixme: it's not necessary to process link status changes both @@ -830,7 +893,7 @@ end = c->reg[Arqh+ pf]; for(h = c->arh; h != end; h = NEXT(h, Narq)){ a = c->arq + h; - print("%s: cmd slot %d op %#ux\n", cname(c), h, a->op); + print("%s: cmd slot %d op %#ux\n", ename(e), h, a->op); qrx(e, c, a); adinitrx(c, h); c->reg[Arqt + pf] = h; @@ -876,12 +939,15 @@ rballoc(Rbpool *p) { Block *b; + uvlong t; + t = -rdtsc(); for(;;){ if((b = p->x) != nil){ p->nfast++; p->x = b->next; b->next = nil; + p->fasttick += t+rdtsc(); return b; } @@ -895,6 +961,7 @@ return nil; } p->nslow++; + p->slowtick += t+rdtsc(); iunlock(p); p->x = b; } @@ -1046,19 +1113,66 @@ return ((Ctlr*)c)->tim != 0; } +static int +·cleanup(Ctlr *c, int tdh) +{ + Block *b; + uint m, n; + + m = c->ntd-1; + while(c->nrd - c->tdfree > 16 && (c->tdba[n = Next(tdh, m)].cmd&Tdd) == Tdd){ + tdh = n; + b = c->tb[tdh]; + c->tb[tdh] = nil; + freeb(b); + // c->tdba[tdh].cmd = 0; + c->tdfree++; + } + return tdh; +} + static void tproc(void *v) { - Ether *e; + uint m, w; + Block *b; Ctlr *c; + Ether *e; + Td *t; e = v; c = e->ctlr; -loop: - sleep(&c->trendez, tim, c); /* transmit kicks us */ - c->tim = 0; - transmit(e); - goto loop; + m = c->ntd-1; + w = 0; + for(;;){ + c->tdh = ·cleanup(c, c->tdh); + if(Next(c->tdt, m) == c->tdh){ + c->txfull++; +/**/ print("%s: tproc full\n", ename(e)); + txim(c, 1); + sleep(&c->trendez, tim, c); + txim(c, 0); +/**/ print("%s: tproc tim %.8ux\n", ename(e), c->tim); + c->tim = 0; + continue; + } + if(w > 8 || qlen(e->oq) == 0){ + c->reg[Txtail + c->tqno] = c->tdt; + w = 0; + } + b = qbread(e->oq, 100000); + t = c->tdba+c->tdt; + t->addr = Pciwaddr(b->rp); + t->length = BLEN(b)<<2; + t->offset = (6+6+2)/2; // cksum offload # header words up to etype + t->cmd = Rs|Mb1|Teop|Txdesc; + sfence(); + c->tb[c->tdt] = b; + c->tdt = Next(c->tdt, m); + c->reg[Txtail + c->tqno] = c->tdt; + c->tdfree--; + w++; + } } static int @@ -1072,7 +1186,7 @@ m = c->nrd-1; i = 0; p = c->pool; - for(rdt = c->rdt; Next(rdt, m) != rdh; rdt = Next(rdt, m)){ + for(rdt = c->rdt; c->nrd-c->rdfree >= 16 && Next(rdt, m) != rdh; rdt = Next(rdt, m)){ r = c->rdba+rdt; while((b = rballoc(c->pool)) == nil){ c->nobufs++; @@ -1117,26 +1231,28 @@ c = e->ctlr; m = c->nrd-1; rdh = 0; + im(c, Irx); loop: replenish(c, rdh, 1); - im(c, Irx); + rxim(c, 1); +im(c, Irx); /* this isn't right; still big delays. */ sleep(&c->rrendez, rim, c); +// rxim(c, 0); loop1: c->rim = 0; - if(c->nrd-c->rdfree >= 16) + if(c->nrd-c->rdfree >= 24) if(replenish(c, rdh, 0) == -1) goto loop; r = c->rdba+rdh; if(!(r->status&Rdd)) goto loop; b = c->rb[rdh]; - c->rb[rdh] = 0; + c->rb[rdh] = nil; b->wp += r->length>>6; b->lim = b->wp; /* lie like a dog */ - b->flag |= Bipck; /* always */ if(r->status&l3l4p) b->flag |= Bipck|Btcpck|Budpck; - r->status = 0; +// r->status = 0; etheriq(e, b, 1); c->rdfree--; rdh = Next(rdh, m); @@ -1208,9 +1324,9 @@ c = e->ctlr; rv = setmc(c, on, c->vsiseid, ea); if(rv != 0){ - snprint(buf, sizeof buf, "%s: multicast: error %d", cname(c), rv); + snprint(buf, sizeof buf, "%s: multicast: error %d", ename(e), rv); if(rv < nelem(errtab)) - snprint(buf, sizeof buf, "%s: multicast: %s", cname(c), errtab[rv]); + snprint(buf, sizeof buf, "%s: multicast: %s", ename(e), errtab[rv]); error(buf); } } @@ -1218,24 +1334,23 @@ static int detach(Ctlr *c) { - int i, pf, wait; + int i, wait; - pf = c->pf; - wait = (c->reg[Rstctl + pf] & 0x3f)*100; + wait = (c->reg[Rstctl] & 0x3f)*100; for(i = 0;; i++){ if(i == wait) return -1; - if((c->reg[Rststat + pf] & Devstate) == 0) + if((c->reg[Rststat] & Devstate) == 0) break; delay(1); } if(i == 0){ /* need to use pf here not the port# */ - c->reg[Ctl + pf] |= Sreset; + c->reg[Ctl] |= Sreset; for (i = 0; i < 10; i++) { if(i == 10) return -1; - if((c->reg[Ctl + pf] & Sreset) == 0) + if((c->reg[Ctl] & Sreset) == 0) break; delay(1); } @@ -1390,39 +1505,42 @@ /* disable pause here */ } +#define Pageno(fpa) ((fpa)>>Fpgshift) +#define Pfpageidx(pf, fpa) (Pageno(fpa) - Pageno(2*MiB*(pf))) +#define Hmcblock(fpa) ((fpa)>>9) + static void hmcmap(Ctlr *c, u64int fpa) { - uint pgno; + uint pfpg; if(fpa > Fpdeperpage * Hmcpgsz) panic("%s: hmcmap: %#llux\n", cname(c), fpa); if(fpa & (1<>Fpgshift; - if(pgno >= nelem(c->pagetab)) - panic("%s: hmcmap: pgno %d > %d", cname(c), pgno, nelem(c->pagetab)); - if(c->pagetab[pgno] != nil) + pfpg = Pfpageidx(c->pf, fpa); + if(pfpg >= nelem(c->pagetab)) + panic("%s: hmcmap", cname(c)); +if(c->pf==1)print("PFPG %d\n", pfpg); + if(c->pagetab[pfpg] != nil) return; - c->pagetab[pgno] = mallocalign(Hmcpgsz, Hmcalign, 0, 0); + c->pagetab[pfpg] = mallocalign(Hmcpgsz, Hmcalign, 0, 0); } static void hmcfault(Ctlr *c, u64int fpa) { - uint pgno; + uint pfpg; hmcmap(c, fpa); - pgno = fpa>>Fpgshift; - c->pdpage[pgno] = Pciwaddr(c->pagetab[pgno]) | Fpdevalid; + pfpg = Pfpageidx(c->pf, fpa); + c->pdpage[pfpg] = Pciwaddr(c->pagetab[pfpg]) | Fpdevalid; } -#define Pageno(x) ((x)>>Fpgshift) - static void hmcinit(Ctlr *c) { - int pf; + uint pf; pf = c->pf; c->pdpage = mallocalign(Hmcpgsz, Hmcalign, 0, 0); @@ -1432,15 +1550,15 @@ * to each pf. populate each card's addres space with * 1 FPDE at [2M*pf, 2M*pf+(1<reg[Hmsdpart + pf] = pf*(2*MiB>>Fpgshift) | 1*Segentries; + c->reg[Hmsdpart + pf] = Pageno(pf*2*MiB) | 1*Segentries; /* * allocate 4 rx and 4 tx queues. allocation is in 512b blocks. * divide our single allocated page in half between tx/rx. */ - c->reg[Hmtxbase + pf] = 0/512; + c->reg[Hmtxbase + pf] = (0+2*MiB*pf)/512; c->reg[Hmtxcnt + pf] = 4; - c->reg[Hmrxbase + pf] = (Hmcpgsz/2)/512; + c->reg[Hmrxbase + pf] = (0+2*MiB*pf + Hmcpgsz/2)/512; c->reg[Hmrxcnt + pf] = 4; /* @@ -1451,9 +1569,9 @@ /* * program SD with our pdpage. */ - c->reg[Hmsdaddrhi] = Pciwaddrh(c->pdpage); - c->reg[Hmsdaddrlo] = Pciwaddrl(c->pdpage) | 1*Sdcount | Sdvalid | Sdpaged; - c->reg[Hmsdcmd] = Hmcmdwrite | Pageno(0); + c->reg[Hmsdaddrhi + pf] = Pciwaddrh(c->pdpage); + c->reg[Hmsdaddrlo + pf] = Pciwaddrl(c->pdpage) | 1*Sdcount | Sdvalid | Sdpaged; + c->reg[Hmsdcmd + pf] = Hmcmdwrite | Pageno(pf*2*MiB); } static void @@ -1629,11 +1747,6 @@ // print("tc0 on qset %#.4ux\n", c->qsh); } -void -readclear(u32int) -{ -} - static void irqenable(Ctlr *c) { @@ -1641,12 +1754,11 @@ readclear(c->reg[Icr + c->pf]); for(pf = 0; pf < c->npf; pf++){ - c->reg[Irxqctl + 0] = Irxidx*Iqirqidx | 0*Iqnxtqidx | Iqnxtt | Iqenable; /* rx: ics=0x04 */ - c->reg[Itxqctl + 0] = Itxidx*Iqirqidx | Iqend | Iqenable; /* tx: ics=0x02 */ + rxim(c, 0); + txim(c, 0); c->reg[Ilnklst + pf] = 0*Firstqidx | Firstrx; /* 1st: rxq idx 0 */ - c->reg[Icren + pf] = c->im; - c->reg[Idynctl + pf] = Intena | Clearpba; + c->reg[Idynctl + pf] = 0<<5 | 0<<3 | Intena | Clearpba; /* 0*4µs coalescing */ } im(c, Errint); } @@ -1723,18 +1835,19 @@ u[25] |= p>>8; } +// c->reg[Vsiqbase + seidtovsiid(c->vsiseid)] = Vsicontig | 0; + static void txrxinit(Ctlr *c) { uchar *t, *r; -// c->reg[Vsiqbase + seidtovsiid(c->vsiseid)] = Vsicontig | 0; - c->tqno = c->pf*4 + 0; c->rqno = c->pf*4 + 0; /* skip 1 to ignore flow director (doesn't work) */ t = (uchar*)c->pagetab[0] + 0 + c->tqno*128; r = (uchar*)c->pagetab[0] + Hmcpgsz/2 + c->rqno*32; + txcontext(c, t); rxcontext(c, r); sfence(); @@ -1760,9 +1873,17 @@ } static void -attach(Ether *e) +vkproc(char c, Ether *e, void(*f)(void*)) { char buf[KNAMELEN]; + + snprint(buf, sizeof buf, "#l%d%c", e->ctlrno, c); + kproc(buf, f, e); +} + +static void +attach(Ether *e) +{ int t; Ctlr *c; @@ -1773,7 +1894,6 @@ unlock(&c->alock); if(t & Fstarted) return; - hmcinit(c); linkinit(c); @@ -1785,12 +1905,9 @@ allocblocks(c); /* wrong place? move to rproc */ txrxinit(c); - snprint(buf, sizeof buf, "#l%da", e->ctlrno); - kproc(buf, aproc, e); - snprint(buf, sizeof buf, "#l%dr", e->ctlrno); - kproc(buf, rproc, e); - snprint(buf, sizeof buf, "#l%dt", e->ctlrno); - kproc(buf, tproc, e); + vkproc('a', e, aproc); + vkproc('r', e, rproc); + vkproc('t', e, tproc); } static void @@ -1806,32 +1923,33 @@ ilock(&c->imlock); im = c->im; pf = c->pf; +int debug = pf==1; - icr = c->reg[Icr + pf] & c->im; - c->reg[Idynctl + pf] = Intena | Clearpba; + icr = c->reg[Icr + pf] & im; +// c->reg[Idynctl + pf] = Clearpba; -// iprint("%s: irq %.8ux im %.8ux\n", cname(c), icr, c->im); -/**/ if((icr & (Aprocint|Irx|Itx)) == 0) -/**/ c->irqcnt[Cnts]++; +if(debug)iprint("icr %.8ux %.8ux %.8ux\n", icr, c->reg[Hmerr+c->pf], c->reg[Hmerrd+c->pf]); + if((icr & (Aprocint|Irx|Itx)) == 0) + c->irqcnt[Cnts]++; if(icr&Aprocint){ -/**/ c->irqcnt[Cnta]++; + c->irqcnt[Cnta]++; im &= ~Aprocint; c->aim = icr&Aprocint; wakeup(&c->arendez); } if(icr&Irx){ -/**/ c->irqcnt[Cntr]++; - im &= ~Irx; + c->irqcnt[Cntr]++; c->rim = icr&Irx; wakeup(&c->rrendez); } if(icr&Itx){ -/**/ c->irqcnt[Cntt]++; - im &= ~Itx; + c->irqcnt[Cntt]++; c->tim = icr&Itx; wakeup(&c->trendez); } c->reg[Icren + pf] = im; + c->reg[Idynctl + pf] = 3<<3 | Intena; /* no change to coalescing; enable */ + c->im = im; iunlock(&c->imlock); } @@ -1874,8 +1992,7 @@ Ctlr *c; Pcidev *p; - p = 0; - while(p = pcimatch(p, 0x8086, 0)){ + for(p = nil; p = pcimatch(p, 0x8086, 0);){ hbafixup(p); if((type = didmatch(p->did)) == -1) continue; @@ -1891,11 +2008,11 @@ continue; } c = malloc(sizeof *c); + c->type = type; c->p = p; c->port = io; c->reg = (u32int*)mem; c->rbsz = cttab[type].mtu; - c->type = type; pcisetbme(p); c->pf = c->reg[Portnum]&3; c->npf = 1; /* wrong */ @@ -1916,9 +2033,12 @@ { int i; Ctlr *c; + static int once; - if(nctlr == 0) + if(once == 0){ scan(); + once++; + } for(i = 0; iflag&Factive) @@ -1944,7 +2064,7 @@ e->multicast = multicast; e->promiscuous = promiscuous; e->shutdown = shutdown; - e->transmit = transmit; +// e->transmit = transmit; return 0; }