--- /sys/src/9/boot/boot.c Thu Dec 5 22:50:15 2013 +++ /sys/src/9/boot/boot.c Wed Mar 12 00:46:27 2014 @@ -19,6 +19,7 @@ int fflag; int kflag; int debugboot; +int nousbboot; char *bargv[Nbarg]; int bargc; @@ -62,6 +63,8 @@ if(getenv("debugboot")) debugboot = 1; + if(getenv("nousbboot")) + nousbboot = 1; #ifdef DEBUG print("argc=%d\n", argc); for(fd = 0; fd < argc; fd++) @@ -111,8 +114,7 @@ static void doauth(int cpuflag) { - if(debugboot) - fprint(2, "auth..."); + dprint("auth..."); authentication(cpuflag); } @@ -255,8 +257,10 @@ * set up usb keyboard & mouse, if any. * starts partfs on first disk, if any, to permit nvram on usb. */ - usbinit(Dontpost); + if (!nousbboot) + usbinit(Dontpost); + dprint("pickmethod..."); mp = pickmethod(argc, argv); islocal = strcmp(mp->name, "local") == 0; ishybrid = strcmp(mp->name, "hybrid") == 0; @@ -264,13 +268,17 @@ kbmap(); /* load keymap if it's there. */ /* don't trigger aoe until the network has been configured */ + dprint("bind #æ..."); bind("#æ", "/dev", MAFTER); /* nvram could be here */ + dprint("bind #S..."); bind("#S", "/dev", MAFTER); /* nvram could be here */ + dprint("partinit..."); partinit(); doauth(cpuflag); /* authentication usually changes hostowner */ rfork(RFNAMEG); /* leave existing subprocs in own namespace */ - usbinit(Post); /* restart partfs under the new hostowner id */ + if (!nousbboot) + usbinit(Post); /* restart partfs under the new hostowner id */ fd = connectroot(mp, islocal, ishybrid); afd = nsinit(fd, &rsp); close(fd); @@ -319,6 +327,7 @@ int n; /* look for required reply */ + dprint("read #e/nobootprompt..."); readfile("#e/nobootprompt", reply, sizeof(reply)); if(reply[0]){ mp = findmethod(reply); @@ -336,6 +345,7 @@ sprint(prompt+n, ")"); /* create default reply */ + dprint("read #e/bootargs..."); readfile("#e/bootargs", reply, sizeof(reply)); if(reply[0] == 0 && arg != 0) strcpy(reply, arg); @@ -349,6 +359,7 @@ /* parse replies */ do{ + dprint("outin..."); outin(prompt, reply, sizeof(reply)); mp = findmethod(reply); }while(mp == nil); @@ -359,6 +370,7 @@ cp = strchr(reply, '!'); if(cp) strcpy(sys, cp+1); + dprint("pickmethod done\n"); return mp; } --- /sys/src/9/boot/boot.h Wed Aug 15 23:26:08 2012 +++ /sys/src/9/boot/boot.h Wed Mar 12 00:40:38 2014 @@ -12,6 +12,8 @@ Nbarg= 16, }; +#define dprint(...) if(debugboot) fprint(2, __VA_ARGS__); else USED(debugboot) + extern char* bootdisk; /* defined in ../$arch/boot$CONF.c */ extern char* rootdir; extern int (*cfs)(int); --- /sys/src/9/boot/bootip.c Thu Jun 27 23:49:32 2013 +++ /sys/src/9/boot/bootip.c Wed Mar 12 00:45:31 2014 @@ -5,20 +5,18 @@ #include "boot.h" static uchar fsip[IPaddrlen]; - uchar auip[IPaddrlen]; +static uchar auip[IPaddrlen]; static char mpoint[32]; static int isvalidip(uchar*); -static void netndb(char*, uchar*); -static void netenv(char*, uchar*); - +static void getndbvar(char *name, uchar *var, char *prompt); void configip(int bargc, char **bargv, int needfs) { Waitmsg *w; int argc, pid; - char **arg, **argv, buf[32], *p; + char **arg, **argv, *p; fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); @@ -48,24 +46,30 @@ break; } ARGEND; - /* bind in an ip interface */ + /* bind in an ip interface or two */ + dprint("bind #I..."); if(bind("#I", mpoint, MAFTER) < 0) fatal("bind #I"); + dprint("bind #l0..."); if(access("#l0", 0) == 0 && bind("#l0", mpoint, MAFTER) < 0) warning("bind #l0"); + dprint("bind #l1..."); if(access("#l1", 0) == 0 && bind("#l1", mpoint, MAFTER) < 0) warning("bind #l1"); + dprint("bind #l2..."); if(access("#l2", 0) == 0 && bind("#l2", mpoint, MAFTER) < 0) warning("bind #l2"); + dprint("bind #l3..."); if(access("#l3", 0) == 0 && bind("#l3", mpoint, MAFTER) < 0) warning("bind #l3"); werrstr(""); - /* let ipconfig configure the ip interface */ + /* let ipconfig configure the first ip interface */ switch(pid = fork()){ case -1: fatal("fork configuring ip: %r"); case 0: + dprint("starting ipconfig..."); exec("/boot/ipconfig", arg); fatal("execing /boot/ipconfig: %r"); default: @@ -73,8 +77,7 @@ } /* wait for ipconfig to finish */ - if(debugboot) - fprint(2, "waiting for dhcp..."); + dprint("waiting for dhcp..."); for(;;){ w = wait(); if(w != nil && w->pid == pid){ @@ -86,31 +89,11 @@ fatal("configuring ip"); free(w); } - if(debugboot) - fprint(2, "\n"); - - if(!needfs) - return; - - /* if we didn't get a file and auth server, query user */ - netndb("fs", fsip); - if(!isvalidip(fsip)) - netenv("fs", fsip); - while(!isvalidip(fsip)){ - buf[0] = 0; - outin("filesystem IP address", buf, sizeof(buf)); - if (parseip(fsip, buf) == -1) - fprint(2, "configip: can't parse fs ip %s\n", buf); - } + dprint("\n"); - netndb("auth", auip); - if(!isvalidip(auip)) - netenv("auth", auip); - while(!isvalidip(auip)){ - buf[0] = 0; - outin("authentication server IP address", buf, sizeof(buf)); - if (parseip(auip, buf) == -1) - fprint(2, "configip: can't parse auth ip %s\n", buf); + if(needfs) { /* if we didn't get a file and auth server, query user */ + getndbvar("fs", fsip, "filesystem IP address"); + getndbvar("auth", auip, "authentication server IP address"); } } @@ -126,7 +109,9 @@ void configtcp(Method*) { + dprint("configip..."); configip(bargc, bargv, 1); + dprint("setauthaddr..."); setauthaddr("tcp", 567); } @@ -137,6 +122,7 @@ char buf[64]; snprint(buf, sizeof buf, "tcp!%I!564", fsip); + dprint("dial %s...", buf); fd = dial(buf, 0, 0, 0); if (fd < 0) werrstr("dial %s: %r", buf); @@ -166,6 +152,7 @@ return; n = read(fd, buf, sizeof(buf)-1); + close(fd); if(n <= 0) return; buf[n] = 0; @@ -203,5 +190,20 @@ return; } } - return; +} + +static void +getndbvar(char *name, uchar *var, char *prompt) +{ + char buf[64]; + + netndb(name, var); + if(!isvalidip(var)) + netenv(name, var); + while(!isvalidip(var)){ + buf[0] = 0; + outin(prompt, buf, sizeof buf); + if (parseip(var, buf) == -1) + fprint(2, "configip: can't parse %s ip %s\n", name, buf); + } } --- /sys/src/9/boot/parts.c Sat Mar 24 00:49:50 2012 +++ /sys/src/9/boot/parts.c Wed Mar 12 00:41:53 2014 @@ -113,8 +113,7 @@ if (fprint(unit->ctl, "part %s %lld %lld\n", name, start, end) < 0) fprint(2, "can't update %s's devsd partition table for %s: %r\n", unit->name, name); - if (debugboot) - print("part %s %lld %lld\n", name, start, end); + dprint("part %s %lld %lld\n", name, start, end); } static long @@ -193,8 +192,7 @@ pp->start = unit->sectors - 2; pp->end = unit->sectors - 1; - if(debugboot) - print("oldp9part %s\n", unit->name); + dprint("oldp9part %s\n", unit->name); if(sdreadblk(unit, pp, partbuf, 0, 0) < 0) return; @@ -265,8 +263,7 @@ uvlong start, end; int i, n; - if(debugboot) - print("p9part %s %s\n", unit->name, name); + dprint("p9part %s %s\n", unit->name, name); p = sdfindpart(unit, name); if(p == nil) return; --- /sys/src/9/boot/usb.c Thu Feb 6 18:45:17 2014 +++ /sys/src/9/boot/usb.c Wed Mar 12 00:41:27 2014 @@ -13,8 +13,6 @@ Post, }; -int debugboot; - static char usbdisk0[] = "/dev/sdU0.0"; static char sdxxctl[] = "/dev/sdXX/ctl"; @@ -34,14 +32,12 @@ return -1; } - if(debugboot) - fprint(2, "%s...", name); + dprint("%s...", name); runv(argv); for(cnt = 10; cnt > 0 && access(file, AEXIST) < 0; cnt--) sleep(100); if (cnt <= 0) { - if(debugboot) - fprint(2, "no %s...", file); + dprint("no %s...", file); return -1; } return 0; @@ -54,8 +50,7 @@ dir = dirstat(file); if (dir == nil) { - if(debugboot) - fprint(2, "can't stat %s: %r\n", file); + dprint("can't stat %s: %r\n", file); return -1; } dir->mode &= ~0777; @@ -108,8 +103,7 @@ { int fd; - if(debugboot) - fprint(2, "mount usbd..."); + dprint("mount usbd..."); fd = open("/srv/usb", ORDWR); if(fd < 0) warning("can't open /srv/usb"); @@ -140,8 +134,7 @@ if(access("#u/usb/ctl", AEXIST) < 0 || bind("#u", "/dev", MAFTER) < 0) return; - if(debugboot) - fprint(2, "usbinit..."); + dprint("usbinit..."); start("usbd", usbdv, "/srv/usb"); /* allow a little time for usbd's device discovery */ @@ -149,6 +142,6 @@ sleep(100); if(cnt > 0) startpartfs(post); - else if(debugboot) - fprint(2, "no usb disk..."); + else + dprint("no usb disk..."); } --- /sys/src/9/pc/ether8169.c Tue Oct 22 00:01:45 2013 +++ /sys/src/9/pc/ether8169.c Wed Mar 12 00:26:22 2014 @@ -297,6 +297,10 @@ int rcr; /* receive configuration register */ int imr; + Watermark wmrb; + Watermark wmrd; + Watermark wmtd; + QLock slock; /* statistics */ Dtcc* dtcc; uint txdu; @@ -494,7 +498,7 @@ static long rtl8169ifstat(Ether* edev, void* a, long n, ulong offset) { - char *p; + char *p, *s, *e; Ctlr *ctlr; Dtcc *dtcc; int i, l, r, timeo; @@ -535,6 +539,7 @@ if((p = malloc(READSTR)) == nil) error(Enomem); + e = p + READSTR; l = snprint(p, READSTR, "TxOk: %llud\n", dtcc->txok); l += snprint(p+l, READSTR-l, "RxOk: %llud\n", dtcc->rxok); @@ -575,6 +580,11 @@ } snprint(p+l, READSTR-l, "\n"); } + s = p + l + 1; +// s = seprintmark(s, e, &ctlr->wmrb); + s = seprintmark(s, e, &ctlr->wmrd); + s = seprintmark(s, e, &ctlr->wmtd); + USED(s); n = readstr(offset, a, n, p); @@ -851,6 +861,9 @@ } memset(ctlr->dtcc, 0, sizeof(Dtcc)); /* paranoia */ rtl8169init(edev); + initmark(&ctlr->wmrb, Nrd, "rcv bufs unprocessed"); + initmark(&ctlr->wmrd, Nrd-1, "rcv descrs processed at once"); + initmark(&ctlr->wmtd, Ntd-1, "xmit descr queue len"); ctlr->init = 1; } qunlock(&ctlr->alock); @@ -942,6 +955,8 @@ coherence(); d->control |= Own | Fs | Ls | BLEN(bp); + /* note size of queue of tds awaiting transmission */ + notemark(&ctlr->wmtd, (x + Ntd - ctlr->tdh) % Ntd); x = NEXT(x, ctlr->ntd); ctlr->ntq++; } @@ -959,7 +974,7 @@ rtl8169receive(Ether* edev) { D *d; - int rdh; + int rdh, passed; Block *bp; Ctlr *ctlr; u32int control; @@ -967,6 +982,7 @@ ctlr = edev->ctlr; rdh = ctlr->rdh; + passed = 0; for(;;){ d = &ctlr->rd[rdh]; @@ -1009,6 +1025,7 @@ break; } etheriq(edev, bp, 1); + passed++; }else{ if(!(control & Res)) ctlr->frag++; @@ -1023,6 +1040,8 @@ if(ctlr->nrdfree < ctlr->nrd/2) rtl8169replenish(ctlr); } + /* note how many rds had full buffers */ + notemark(&ctlr->wmrd, passed); ctlr->rdh = rdh; } --- /sys/src/9/pc/ether82563.c Wed Feb 5 22:22:04 2014 +++ /sys/src/9/pc/ether82563.c Tue Mar 11 20:47:37 2014 @@ -488,6 +488,10 @@ Rendez lrendez; int lim; + Watermark wmrb; + Watermark wmrd; + Watermark wmtd; + QLock slock; uint statistics[Nstatistics]; uint lsleep; @@ -688,6 +692,10 @@ // } // p = seprint(p, e, "\n"); + p = seprintmark(p, e, &ctlr->wmrb); + p = seprintmark(p, e, &ctlr->wmrd); + p = seprintmark(p, e, &ctlr->wmtd); + USED(p); n = readstr(offset, a, n, s); free(s); @@ -871,24 +879,24 @@ #define Next(x, m) (((x)+1) & (m)) static int -i82563cleanup(Ctlr *c) +i82563cleanup(Ctlr *ctlr) { Block *b; int tdh, m, n; - tdh = c->tdh; - m = c->ntd-1; - while(c->tdba[n = Next(tdh, m)].status & Tdd){ + tdh = ctlr->tdh; + m = ctlr->ntd-1; + while(ctlr->tdba[n = Next(tdh, m)].status & Tdd){ tdh = n; - if((b = c->tb[tdh]) != nil){ - c->tb[tdh] = nil; + if((b = ctlr->tb[tdh]) != nil){ + ctlr->tb[tdh] = nil; freeb(b); }else iprint("82563 tx underrun!\n"); - c->tdba[tdh].status = 0; + ctlr->tdba[tdh].status = 0; } - return c->tdh = tdh; + return ctlr->tdh = tdh; } static void @@ -925,6 +933,8 @@ td->addr[0] = PCIWADDR(bp->rp); td->control = Ide|Rs|Ifcs|Teop|BLEN(bp); ctlr->tb[tdt] = bp; + /* note size of queue of tds awaiting transmission */ + notemark(&ctlr->wmtd, (tdt + Ntd - tdh) % Ntd); tdt = Next(tdt, m); } if(ctlr->tdt != tdt){ @@ -1059,7 +1069,7 @@ Rd *rd; Block *bp; Ctlr *ctlr; - int r, m, rdh, rim; + int r, m, rdh, rim, passed; Ether *edev; edev = arg; @@ -1078,6 +1088,7 @@ sleep(&ctlr->rrendez, i82563rim, ctlr); rdh = ctlr->rdh; + passed = 0; for(;;){ rim = ctlr->rim; ctlr->rim = 0; @@ -1120,7 +1131,9 @@ ilock(&i82563rblock); nrbfull++; iunlock(&i82563rblock); + notemark(&ctlr->wmrb, nrbfull); etheriq(edev, bp, 1); + passed++; } else { if (rd->status & Reop && rd->errors) print("%s: input packet error %#ux\n", @@ -1140,13 +1153,15 @@ if(ctlr->rdfree <= ctlr->nrd - 32 || (rim & Rxdmt0)) i82563replenish(ctlr); } + /* note how many rds had full buffers */ + notemark(&ctlr->wmrd, passed); } } static int -i82563lim(void* c) +i82563lim(void* ctlr) { - return ((Ctlr*)c)->lim != 0; + return ((Ctlr*)ctlr)->lim != 0; } static int speedtab[] = { @@ -1154,14 +1169,14 @@ }; static uint -phyread(Ctlr *c, int reg) +phyread(Ctlr *ctlr, int reg) { uint phy, i; - csr32w(c, Mdic, MDIrop | 1<ctlr; + ctlr = e->ctlr; - if(c->type == i82573 && (phy = phyread(c, Phyier)) != ~0) - phywrite(c, Phyier, phy | Lscie | Ancie | Spdie | Panie); + if(ctlr->type == i82573 && (phy = phyread(ctlr, Phyier)) != ~0) + phywrite(ctlr, Phyier, phy | Lscie | Ancie | Spdie | Panie); for(;;){ - phy = phyread(c, Physsr); + phy = phyread(ctlr, Physsr); if(phy == ~0) goto next; i = (phy>>14) & 3; - switch(c->type){ + switch(ctlr->type){ case i82563: - a = phyread(c, Phyisr) & Ane; + a = phyread(ctlr, Phyisr) & Ane; break; case i82571: case i82572: case i82575: case i82576: - a = phyread(c, Phylhr) & Anf; + a = phyread(ctlr, Phylhr) & Anf; i = (i-1) & 3; break; default: @@ -1226,18 +1241,18 @@ break; } if(a) - phywrite(c, Phyctl, phyread(c, Phyctl) | Ran | Ean); + phywrite(ctlr, Phyctl, phyread(ctlr, Phyctl) | Ran | Ean); e->link = (phy & Rtlink) != 0; if(e->link){ - c->speeds[i]++; + ctlr->speeds[i]++; if (speedtab[i]) e->mbps = speedtab[i]; } next: - c->lim = 0; - i82563im(c, Lsc); - c->lsleep++; - sleep(&c->lrendez, i82563lim, c); + ctlr->lim = 0; + i82563im(ctlr, Lsc); + ctlr->lsleep++; + sleep(&ctlr->lrendez, i82563lim, ctlr); } } @@ -1245,12 +1260,12 @@ i82563tproc(void *v) { Ether *e; - Ctlr *c; + Ctlr *ctlr; e = v; - c = e->ctlr; + ctlr = e->ctlr; for(;;){ - sleep(&c->trendez, return0, 0); + sleep(&ctlr->trendez, return0, 0); i82563transmit(e); } } @@ -1307,6 +1322,9 @@ ctlr->edev = edev; /* point back to Ether* */ ctlr->attached = 1; + initmark(&ctlr->wmrb, Nrb, "rcv bufs unprocessed"); + initmark(&ctlr->wmrd, Nrd-1, "rcv descrs processed at once"); + initmark(&ctlr->wmtd, Ntd-1, "xmit descr queue len"); snprint(name, sizeof name, "#l%dl", edev->ctlrno); kproc(name, i82563lproc, edev); @@ -1511,13 +1529,13 @@ } static int -fread(Ctlr *c, Flash *f, int ladr) +fread(Ctlr *ctlr, Flash *f, int ladr) { ushort s; ulong n; delay(1); - if(fcycle(c, f) == -1) + if(fcycle(ctlr, f) == -1) return -1; f->reg[Fsts] |= Fdone; f->reg32[Faddr] = ladr; @@ -1539,32 +1557,32 @@ } static int -fload(Ctlr *c) +fload(Ctlr *ctlr) { ulong data, io, r, adr; ushort sum; Flash f; - io = c->pcidev->mem[1].bar & ~0x0f; - f.reg = vmap(io, c->pcidev->mem[1].size); + io = ctlr->pcidev->mem[1].bar & ~0x0f; + f.reg = vmap(io, ctlr->pcidev->mem[1].size); if(f.reg == nil) return -1; f.reg32 = (void*)f.reg; f.base = f.reg32[Bfpr] & FMASK(0, 13); f.lim = (f.reg32[Bfpr]>>16) & FMASK(0, 13); - if(csr32r(c, Eec) & (1<<22)) + if(csr32r(ctlr, Eec) & (1<<22)) f.base += (f.lim + 1 - f.base) >> 1; r = f.base << 12; sum = 0; for (adr = 0; adr < 0x40; adr++) { - data = fread(c, &f, r + adr*2); + data = fread(ctlr, &f, r + adr*2); if(data == -1) break; - c->eeprom[adr] = data; + ctlr->eeprom[adr] = data; sum += data; } - vunmap(f.reg, c->pcidev->mem[1].size); + vunmap(f.reg, ctlr->pcidev->mem[1].size); return sum; } --- /sys/src/9/pc/ether82598.c Wed Feb 5 22:30:51 2014 +++ /sys/src/9/pc/ether82598.c Tue Mar 11 23:18:12 2014 @@ -24,7 +24,7 @@ /* tunable parameters */ Nrd = 256, /* multiple of 8, power of 2 for NEXTPOW2 */ Nrb = 1024, - Ntd = 128, /* multiple of 8, power of 2 for NEXTPOW2 */ + Ntd = 64, /* multiple of 8, power of 2 for NEXTPOW2 */ Goslow = 0, /* flag: go slow by throttling intrs, etc. */ }; @@ -312,8 +312,12 @@ int procsrunning; int attached; - Lock slock; - Lock alock; /* attach lock */ + Watermark wmrb; + Watermark wmrd; + Watermark wmtd; + + QLock slock; + QLock alock; /* attach lock */ QLock tlock; Rendez lrendez; Rendez trendez; @@ -350,16 +354,17 @@ static int nctlr; static Lock rblock; static Block *rbpool; +static int nrbfull; /* # of rcv Blocks with data awaiting processing */ static void -readstats(Ctlr *c) +readstats(Ctlr *ctlr) { int i; - lock(&c->slock); - for(i = 0; i < nelem(c->stats); i++) - c->stats[i] += c->reg[stattab[i].reg >> 2]; - unlock(&c->slock); + qlock(&ctlr->slock); + for(i = 0; i < nelem(ctlr->stats); i++) + ctlr->stats[i] += ctlr->reg[stattab[i].reg >> 2]; + qunlock(&ctlr->slock); } static int speedtab[] = { @@ -369,28 +374,32 @@ }; static long -ifstat(Ether *e, void *a, long n, ulong offset) +ifstat(Ether *edev, void *a, long n, ulong offset) { uint i, *t; - char *s, *p, *q; - Ctlr *c; + char *s, *p, *e; + Ctlr *ctlr; - c = e->ctlr; + ctlr = edev->ctlr; p = s = malloc(READSTR); if(p == nil) error(Enomem); - q = p + READSTR; + e = p + READSTR; - readstats(c); + readstats(ctlr); for(i = 0; i < nelem(stattab); i++) - if(c->stats[i] > 0) - p = seprint(p, q, "%.10s %uld\n", stattab[i].name, - c->stats[i]); - t = c->speeds; - p = seprint(p, q, "speeds: 0:%d 1000:%d 10000:%d\n", t[0], t[1], t[2]); - p = seprint(p, q, "mtu: min:%d max:%d\n", e->minmtu, e->maxmtu); - seprint(p, q, "rdfree %d rdh %d rdt %d\n", c->rdfree, c->reg[Rdt], - c->reg[Rdh]); + if(ctlr->stats[i] > 0) + p = seprint(p, e, "%.10s %uld\n", stattab[i].name, + ctlr->stats[i]); + t = ctlr->speeds; + p = seprint(p, e, "speeds: 0:%d 1000:%d 10000:%d\n", t[0], t[1], t[2]); + p = seprint(p, e, "mtu: min:%d max:%d\n", edev->minmtu, edev->maxmtu); + p = seprint(p, e, "rdfree %d rdh %d rdt %d\n", ctlr->rdfree, ctlr->reg[Rdt], + ctlr->reg[Rdh]); + p = seprintmark(p, e, &ctlr->wmrb); + p = seprintmark(p, e, &ctlr->wmrd); + p = seprintmark(p, e, &ctlr->wmtd); + USED(p); n = readstr(offset, a, n, s); free(s); @@ -398,12 +407,12 @@ } static void -ienable(Ctlr *c, int i) +ienable(Ctlr *ctlr, int i) { - ilock(&c->imlock); - c->im |= i; - c->reg[Ims] = c->im; - iunlock(&c->imlock); + ilock(&ctlr->imlock); + ctlr->im |= i; + ctlr->reg[Ims] = ctlr->im; + iunlock(&ctlr->imlock); } static int @@ -416,23 +425,23 @@ lproc(void *v) { int r, i; - Ctlr *c; + Ctlr *ctlr; Ether *e; e = v; - c = e->ctlr; + ctlr = e->ctlr; for (;;) { - r = c->reg[Links]; + r = ctlr->reg[Links]; e->link = (r & Lnkup) != 0; i = 0; if(e->link) i = 1 + ((r & Lnkspd) != 0); - c->speeds[i]++; + ctlr->speeds[i]++; e->mbps = speedtab[i]; - c->lim = 0; - ienable(c, Lsc); - sleep(&c->lrendez, lim, c); - c->lim = 0; + ctlr->lim = 0; + ienable(ctlr, Lsc); + sleep(&ctlr->lrendez, lim, ctlr); + ctlr->lim = 0; } } @@ -466,23 +475,24 @@ ilock(&rblock); b->next = rbpool; rbpool = b; + nrbfull--; iunlock(&rblock); } static int -cleanup(Ctlr *c, int tdh) +cleanup(Ctlr *ctlr, int tdh) { Block *b; uint m, n; - m = c->ntd - 1; - while(c->tdba[n = NEXTPOW2(tdh, m)].status & Tdd){ + m = ctlr->ntd - 1; + while(ctlr->tdba[n = NEXTPOW2(tdh, m)].status & Tdd){ tdh = n; - b = c->tb[tdh]; - c->tb[tdh] = 0; + b = ctlr->tb[tdh]; + ctlr->tb[tdh] = 0; if (b) freeb(b); - c->tdba[tdh].status = 0; + ctlr->tdba[tdh].status = 0; } return tdh; } @@ -491,42 +501,44 @@ transmit(Ether *e) { uint i, m, tdt, tdh; - Ctlr *c; + Ctlr *ctlr; Block *b; Td *t; - c = e->ctlr; - if(!canqlock(&c->tlock)){ - ienable(c, Itx0); + ctlr = e->ctlr; + if(!canqlock(&ctlr->tlock)){ + ienable(ctlr, Itx0); return; } - tdh = c->tdh = cleanup(c, c->tdh); - tdt = c->tdt; - m = c->ntd - 1; + tdh = ctlr->tdh = cleanup(ctlr, ctlr->tdh); + tdt = ctlr->tdt; + m = ctlr->ntd - 1; for(i = 0; ; i++){ if(NEXTPOW2(tdt, m) == tdh){ /* ring full? */ - ienable(c, Itx0); + ienable(ctlr, Itx0); break; } if((b = qget(e->oq)) == nil) break; - assert(c->tdba != nil); - t = c->tdba + tdt; + assert(ctlr->tdba != nil); + t = ctlr->tdba + tdt; t->addr[0] = PCIWADDR(b->rp); t->length = BLEN(b); t->cmd = Ifcs | Teop; if (!Goslow) t->cmd |= Rs; - c->tb[tdt] = b; + ctlr->tb[tdt] = b; + /* note size of queue of tds awaiting transmission */ + notemark(&ctlr->wmtd, (tdt + Ntd - tdh) % Ntd); tdt = NEXTPOW2(tdt, m); } if(i) { coherence(); - c->reg[Tdt] = c->tdt = tdt; /* make new Tds active */ + ctlr->reg[Tdt] = ctlr->tdt = tdt; /* make new Tds active */ coherence(); - ienable(c, Itx0); + ienable(ctlr, Itx0); } - qunlock(&c->tlock); + qunlock(&ctlr->tlock); } static int @@ -538,101 +550,114 @@ static void tproc(void *v) { - Ctlr *c; + Ctlr *ctlr; Ether *e; e = v; - c = e->ctlr; + ctlr = e->ctlr; for (;;) { - sleep(&c->trendez, tim, c); /* transmit interrupt kicks us */ - c->tim = 0; + sleep(&ctlr->trendez, tim, ctlr); /* xmit interrupt kicks us */ + ctlr->tim = 0; transmit(e); } } static void -rxinit(Ctlr *c) +rxinit(Ctlr *ctlr) { - int i, is598; + int i, is598, autoc; + ulong until; Block *b; - c->reg[Rxctl] &= ~Rxen; - c->reg[Rxdctl] = 0; - for(i = 0; i < c->nrd; i++){ - b = c->rb[i]; - c->rb[i] = 0; + ctlr->reg[Rxctl] &= ~Rxen; + ctlr->reg[Rxdctl] = 0; + for(i = 0; i < ctlr->nrd; i++){ + b = ctlr->rb[i]; + ctlr->rb[i] = 0; if(b) freeb(b); } - c->rdfree = 0; + ctlr->rdfree = 0; coherence(); - c->reg[Fctrl] |= Bam; - c->reg[Fctrl] &= ~(Upe | Mpe); + ctlr->reg[Fctrl] |= Bam; + ctlr->reg[Fctrl] &= ~(Upe | Mpe); /* intel gets some csums wrong (e.g., errata 44) */ - c->reg[Rxcsum] &= ~Ippcse; - c->reg[Hlreg0] &= ~Jumboen; /* jumbos are a bad idea */ - c->reg[Hlreg0] |= Txcrcen | Rxcrcstrip | Txpaden; - c->reg[Srrctl] = (c->rbsz + 1024 - 1) / 1024; - c->reg[Mhadd] = c->rbsz << 16; - - c->reg[Rbal] = PCIWADDR(c->rdba); - c->reg[Rbah] = 0; - c->reg[Rdlen] = c->nrd*sizeof(Rd); /* must be multiple of 128 */ - c->reg[Rdh] = 0; - c->reg[Rdt] = c->rdt = 0; + ctlr->reg[Rxcsum] &= ~Ippcse; + ctlr->reg[Hlreg0] &= ~Jumboen; /* jumbos are a bad idea */ + ctlr->reg[Hlreg0] |= Txcrcen | Rxcrcstrip | Txpaden; + ctlr->reg[Srrctl] = (ctlr->rbsz + 1024 - 1) / 1024; + ctlr->reg[Mhadd] = ctlr->rbsz << 16; + + ctlr->reg[Rbal] = PCIWADDR(ctlr->rdba); + ctlr->reg[Rbah] = 0; + ctlr->reg[Rdlen] = ctlr->nrd*sizeof(Rd); /* must be multiple of 128 */ + ctlr->reg[Rdh] = 0; + ctlr->reg[Rdt] = ctlr->rdt = 0; coherence(); - is598 = (c->type == I82598); + is598 = (ctlr->type == I82598); if (is598) - c->reg[Rdrxctl] = Rdmt¼; + ctlr->reg[Rdrxctl] = Rdmt¼; else { - c->reg[Rdrxctl] |= Crcstrip; - c->reg[Rdrxctl] &= ~Rscfrstsize; + ctlr->reg[Rdrxctl] |= Crcstrip; + ctlr->reg[Rdrxctl] &= ~Rscfrstsize; } if (Goslow && is598) - c->reg[Rxdctl] = 8<reg[Rxdctl] = 8<reg[Rxdctl] = Renable; + ctlr->reg[Rxdctl] = Renable; coherence(); - while (!(c->reg[Rxdctl] & Renable)) + + /* + * don't wait forever like an idiot (and hang the system), + * maybe it's disconnected. + */ + until = TK2MS(MACHP(0)->ticks) + 250; + while (!(ctlr->reg[Rxdctl] & Renable) && TK2MS(MACHP(0)->ticks) < until) ; - c->reg[Rxctl] |= Rxen | (is598? Dmbyps: 0); + if(!(ctlr->reg[Rxdctl] & Renable)) + print("#l%d: Renable didn't come on, might be disconnected\n", + ctlr->edev->ctlrno); + + ctlr->reg[Rxctl] |= Rxen | (is598? Dmbyps: 0); if (is598){ - print("82598: autoc %#ux; lms %d (3 is 10g sfp)\n", - c->reg[Autoc], ((c->reg[Autoc]>>Lmsshift) & Lmsmask)); - c->reg[Autoc] |= Flu; + autoc = ctlr->reg[Autoc]; + /* what is this rubbish and why do we care? */ + print("#l%d: autoc %#ux; lms %d (3 is 10g sfp)\n", + ctlr->edev->ctlrno, autoc, (autoc>>Lmsshift) & Lmsmask); + ctlr->reg[Autoc] |= Flu; coherence(); delay(50); } } static void -replenish(Ctlr *c, uint rdh) +replenish(Ctlr *ctlr, uint rdh) { int rdt, m, i; Block *b; Rd *r; - m = c->nrd - 1; + m = ctlr->nrd - 1; i = 0; - for(rdt = c->rdt; NEXTPOW2(rdt, m) != rdh; rdt = NEXTPOW2(rdt, m)){ - r = c->rdba + rdt; + for(rdt = ctlr->rdt; NEXTPOW2(rdt, m) != rdh; rdt = NEXTPOW2(rdt, m)){ + r = ctlr->rdba + rdt; if((b = rballoc()) == nil){ - print("82598: no buffers\n"); + print("#l%d: no buffers\n", ctlr->edev->ctlrno); break; } - c->rb[rdt] = b; + ctlr->rb[rdt] = b; r->addr[0] = PCIWADDR(b->rp); r->status = 0; - c->rdfree++; + ctlr->rdfree++; i++; } if(i) { coherence(); - c->reg[Rdt] = c->rdt = rdt; /* hand back recycled rdescs */ + ctlr->reg[Rdt] = ctlr->rdt = rdt; /* hand back recycled rdescs */ coherence(); } } @@ -646,63 +671,75 @@ void rproc(void *v) { + int passed; uint m, rdh; - Block *b; - Ctlr *c; + Block *bp; + Ctlr *ctlr; Ether *e; Rd *r; e = v; - c = e->ctlr; - m = c->nrd - 1; + ctlr = e->ctlr; + m = ctlr->nrd - 1; for (rdh = 0; ; ) { - replenish(c, rdh); - ienable(c, Irx0); - sleep(&c->rrendez, rim, c); + replenish(ctlr, rdh); + ienable(ctlr, Irx0); + sleep(&ctlr->rrendez, rim, ctlr); + passed = 0; for (;;) { - c->rim = 0; - r = c->rdba + rdh; + ctlr->rim = 0; + r = ctlr->rdba + rdh; if(!(r->status & Rdd)) break; /* wait for pkts to arrive */ - b = c->rb[rdh]; - c->rb[rdh] = 0; + bp = ctlr->rb[rdh]; + ctlr->rb[rdh] = 0; if (r->length > ETHERMAXTU) - print("82598: got jumbo of %d bytes\n", r->length); - b->wp += r->length; - b->lim = b->wp; /* lie like a dog */ + print("#l%d: got jumbo of %d bytes\n", + e->ctlrno, r->length); + bp->wp += r->length; + bp->lim = bp->wp; /* lie like a dog */ // r->status = 0; - etheriq(e, b, 1); - c->rdfree--; + + ilock(&rblock); + nrbfull++; + iunlock(&rblock); + notemark(&ctlr->wmrb, nrbfull); + etheriq(e, bp, 1); + + passed++; + ctlr->rdfree--; rdh = NEXTPOW2(rdh, m); - if (c->rdfree <= c->nrd - 16) - replenish(c, rdh); + if (ctlr->rdfree <= ctlr->nrd - 16) + replenish(ctlr, rdh); } + /* note how many rds had full buffers */ + notemark(&ctlr->wmrd, passed); } } static void promiscuous(void *a, int on) { - Ctlr *c; + Ctlr *ctlr; Ether *e; e = a; - c = e->ctlr; + ctlr = e->ctlr; if(on) - c->reg[Fctrl] |= Upe | Mpe; + ctlr->reg[Fctrl] |= Upe | Mpe; else - c->reg[Fctrl] &= ~(Upe | Mpe); + ctlr->reg[Fctrl] &= ~(Upe | Mpe); } static void multicast(void *a, uchar *ea, int on) { int b, i; - Ctlr *c; + Ctlr *ctlr; Ether *e; e = a; - c = e->ctlr; + ctlr = e->ctlr; /* * multiple ether addresses can hash to the same filter bit, @@ -715,14 +752,14 @@ b = (ea[5]&1)<<4 | ea[4]>>4; b = 1 << b; if(on) - c->mta[i] |= b; + ctlr->mta[i] |= b; // else -// c->mta[i] &= ~b; - c->reg[Mta+i] = c->mta[i]; +// ctlr->mta[i] &= ~b; + ctlr->reg[Mta+i] = ctlr->mta[i]; } static void -freemem(Ctlr *c) +freemem(Ctlr *ctlr) { Block *b; @@ -730,46 +767,46 @@ b->free = 0; freeb(b); } - free(c->rdba); - c->rdba = nil; - free(c->tdba); - c->tdba = nil; - free(c->rb); - c->rb = nil; - free(c->tb); - c->tb = nil; + free(ctlr->rdba); + ctlr->rdba = nil; + free(ctlr->tdba); + ctlr->tdba = nil; + free(ctlr->rb); + ctlr->rb = nil; + free(ctlr->tb); + ctlr->tb = nil; } static int -detach(Ctlr *c) +detach(Ctlr *ctlr) { int i, is598; - c->reg[Imc] = ~0; - c->reg[Ctrl] |= Rst; + ctlr->reg[Imc] = ~0; + ctlr->reg[Ctrl] |= Rst; for(i = 0; i < 100; i++){ delay(1); - if((c->reg[Ctrl] & Rst) == 0) + if((ctlr->reg[Ctrl] & Rst) == 0) break; } if (i >= 100) return -1; - is598 = (c->type == I82598); + is598 = (ctlr->type == I82598); if (is598) { /* errata */ delay(50); - c->reg[Ecc] &= ~(1<<21 | 1<<18 | 1<<9 | 1<<6); + ctlr->reg[Ecc] &= ~(1<<21 | 1<<18 | 1<<9 | 1<<6); } /* not cleared by reset; kill it manually. */ for(i = 1; i < 16; i++) - c->reg[is598? Rah98: Rah99] &= ~Enable; + ctlr->reg[is598? Rah98: Rah99] &= ~Enable; for(i = 0; i < 128; i++) - c->reg[Mta + i] = 0; + ctlr->reg[Mta + i] = 0; for(i = 1; i < (is598? 640: 128); i++) - c->reg[Vfta + i] = 0; + ctlr->reg[Vfta + i] = 0; -// freemem(c); // TODO - c->attached = 0; +// freemem(ctlr); // TODO + ctlr->attached = 0; return 0; } @@ -782,133 +819,133 @@ /* ≤ 20ms */ static ushort -eeread(Ctlr *c, int i) +eeread(Ctlr *ctlr, int i) { - c->reg[Eerd] = EEstart | i<<2; - while((c->reg[Eerd] & EEdone) == 0) + ctlr->reg[Eerd] = EEstart | i<<2; + while((ctlr->reg[Eerd] & EEdone) == 0) ; - return c->reg[Eerd] >> 16; + return ctlr->reg[Eerd] >> 16; } static int -eeload(Ctlr *c) +eeload(Ctlr *ctlr) { ushort u, v, p, l, i, j; - if((eeread(c, 0) & 0xc0) != 0x40) + if((eeread(ctlr, 0) & 0xc0) != 0x40) return -1; u = 0; for(i = 0; i < 0x40; i++) - u += eeread(c, i); + u += eeread(ctlr, i); for(i = 3; i < 0xf; i++){ - p = eeread(c, i); - l = eeread(c, p++); + p = eeread(ctlr, i); + l = eeread(ctlr, p++); if((int)p + l + 1 > 0xffff) continue; for(j = p; j < p + l; j++) - u += eeread(c, j); + u += eeread(ctlr, j); } if(u != 0xbaba) return -1; - if(c->reg[Status] & (1<<3)) - u = eeread(c, 10); + if(ctlr->reg[Status] & (1<<3)) + u = eeread(ctlr, 10); else - u = eeread(c, 9); + u = eeread(ctlr, 9); u++; for(i = 0; i < Eaddrlen;){ - v = eeread(c, u + i/2); - c->ra[i++] = v; - c->ra[i++] = v>>8; + v = eeread(ctlr, u + i/2); + ctlr->ra[i++] = v; + ctlr->ra[i++] = v>>8; } - c->ra[5] += (c->reg[Status] & 0xc) >> 2; + ctlr->ra[5] += (ctlr->reg[Status] & 0xc) >> 2; return 0; } static int -reset(Ctlr *c) +reset(Ctlr *ctlr) { int i, is598; uchar *p; - if(detach(c)){ + if(detach(ctlr)){ print("82598: reset timeout\n"); return -1; } - if(eeload(c)){ + if(eeload(ctlr)){ print("82598: eeprom failure\n"); return -1; } - p = c->ra; - is598 = (c->type == I82598); - c->reg[is598? Ral98: Ral99] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]; - c->reg[is598? Rah98: Rah99] = p[5]<<8 | p[4] | Enable; - - readstats(c); - for(i = 0; istats); i++) - c->stats[i] = 0; + p = ctlr->ra; + is598 = (ctlr->type == I82598); + ctlr->reg[is598? Ral98: Ral99] = p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0]; + ctlr->reg[is598? Rah98: Rah99] = p[5]<<8 | p[4] | Enable; + + readstats(ctlr); + for(i = 0; istats); i++) + ctlr->stats[i] = 0; - c->reg[Ctrlext] |= 1 << 16; /* required by errata (spec change 4) */ + ctlr->reg[Ctrlext] |= 1 << 16; /* required by errata (spec change 4) */ if (Goslow) { /* make some guesses for flow control */ - c->reg[Fcrtl] = 0x10000 | Enable; - c->reg[Fcrth] = 0x40000 | Enable; - c->reg[Rcrtv] = 0x6000; + ctlr->reg[Fcrtl] = 0x10000 | Enable; + ctlr->reg[Fcrth] = 0x40000 | Enable; + ctlr->reg[Rcrtv] = 0x6000; } else - c->reg[Fcrtl] = c->reg[Fcrth] = c->reg[Rcrtv] = 0; + ctlr->reg[Fcrtl] = ctlr->reg[Fcrth] = ctlr->reg[Rcrtv] = 0; /* configure interrupt mapping (don't ask) */ - c->reg[Ivar+0] = 0 | 1<<7; - c->reg[Ivar+64/4] = 1 | 1<<7; -// c->reg[Ivar+97/4] = (2 | 1<<7) << (8*(97%4)); + ctlr->reg[Ivar+0] = 0 | 1<<7; + ctlr->reg[Ivar+64/4] = 1 | 1<<7; +// ctlr->reg[Ivar+97/4] = (2 | 1<<7) << (8*(97%4)); if (Goslow) { /* interrupt throttling goes here. */ for(i = Itr; i < Itr + 20; i++) - c->reg[i] = 128; /* ¼µs intervals */ - c->reg[Itr + Itx0] = 256; + ctlr->reg[i] = 128; /* ¼µs intervals */ + ctlr->reg[Itr + Itx0] = 256; } else { /* don't throttle */ for(i = Itr; i < Itr + 20; i++) - c->reg[i] = 0; /* ¼µs intervals */ - c->reg[Itr + Itx0] = 0; + ctlr->reg[i] = 0; /* ¼µs intervals */ + ctlr->reg[Itr + Itx0] = 0; } return 0; } static void -txinit(Ctlr *c) +txinit(Ctlr *ctlr) { Block *b; int i; if (Goslow) - c->reg[Txdctl] = 16<reg[Txdctl] = 16<reg[Txdctl] = 0; - if (c->type == I82599) - c->reg[Dtxctl99] = 0; + ctlr->reg[Txdctl] = 0; + if (ctlr->type == I82599) + ctlr->reg[Dtxctl99] = 0; coherence(); - for(i = 0; i < c->ntd; i++){ - b = c->tb[i]; - c->tb[i] = 0; + for(i = 0; i < ctlr->ntd; i++){ + b = ctlr->tb[i]; + ctlr->tb[i] = 0; if(b) freeb(b); } - assert(c->tdba != nil); - memset(c->tdba, 0, c->ntd * sizeof(Td)); - c->reg[Tdbal] = PCIWADDR(c->tdba); - c->reg[Tdbah] = 0; - c->reg[Tdlen] = c->ntd*sizeof(Td); /* must be multiple of 128 */ - c->reg[Tdh] = 0; - c->tdh = c->ntd - 1; - c->reg[Tdt] = c->tdt = 0; + assert(ctlr->tdba != nil); + memset(ctlr->tdba, 0, ctlr->ntd * sizeof(Td)); + ctlr->reg[Tdbal] = PCIWADDR(ctlr->tdba); + ctlr->reg[Tdbah] = 0; + ctlr->reg[Tdlen] = ctlr->ntd*sizeof(Td); /* must be multiple of 128 */ + ctlr->reg[Tdh] = 0; + ctlr->tdh = ctlr->ntd - 1; + ctlr->reg[Tdt] = ctlr->tdt = 0; coherence(); - if (c->type == I82599) - c->reg[Dtxctl99] |= Te; + if (ctlr->type == I82599) + ctlr->reg[Dtxctl99] |= Te; coherence(); - c->reg[Txdctl] |= Ten; + ctlr->reg[Txdctl] |= Ten; coherence(); - while (!(c->reg[Txdctl] & Ten)) + while (!(ctlr->reg[Txdctl] & Ten)) ; } @@ -916,51 +953,58 @@ attach(Ether *e) { Block *b; - Ctlr *c; + Ctlr *ctlr; char buf[KNAMELEN]; - c = e->ctlr; - c->edev = e; /* point back to Ether* */ - lock(&c->alock); + ctlr = e->ctlr; + ctlr->edev = e; /* point back to Ether* */ + qlock(&ctlr->alock); if(waserror()){ - unlock(&c->alock); - freemem(c); + reset(ctlr); + freemem(ctlr); + qunlock(&ctlr->alock); nexterror(); } - if(c->rdba == nil) { - c->nrd = Nrd; - c->ntd = Ntd; - c->rdba = mallocalign(c->nrd * sizeof *c->rdba, Descalign, 0, 0); - c->tdba = mallocalign(c->ntd * sizeof *c->tdba, Descalign, 0, 0); - c->rb = malloc(c->nrd * sizeof(Block *)); - c->tb = malloc(c->ntd * sizeof(Block *)); - if (c->rdba == nil || c->tdba == nil || - c->rb == nil || c->tb == nil) + if(ctlr->rdba == nil) { + ctlr->nrd = Nrd; + ctlr->ntd = Ntd; + ctlr->rdba = mallocalign(ctlr->nrd * sizeof *ctlr->rdba, + Descalign, 0, 0); + ctlr->tdba = mallocalign(ctlr->ntd * sizeof *ctlr->tdba, + Descalign, 0, 0); + ctlr->rb = malloc(ctlr->nrd * sizeof(Block *)); + ctlr->tb = malloc(ctlr->ntd * sizeof(Block *)); + if (ctlr->rdba == nil || ctlr->tdba == nil || + ctlr->rb == nil || ctlr->tb == nil) error(Enomem); - for(c->nrb = 0; c->nrb < 2*Nrb; c->nrb++){ - b = allocb(c->rbsz + BY2PG); /* see rbfree() */ + for(ctlr->nrb = 0; ctlr->nrb < 2*Nrb; ctlr->nrb++){ + b = allocb(ctlr->rbsz + BY2PG); /* see rbfree() */ if(b == nil) error(Enomem); b->free = rbfree; freeb(b); } } - if (!c->attached) { - rxinit(c); - txinit(c); - if (!c->procsrunning) { + if (!ctlr->attached) { + rxinit(ctlr); + txinit(ctlr); + nrbfull = 0; + if (!ctlr->procsrunning) { snprint(buf, sizeof buf, "#l%dl", e->ctlrno); kproc(buf, lproc, 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); - c->procsrunning = 1; + ctlr->procsrunning = 1; } - c->attached = 1; + initmark(&ctlr->wmrb, Nrb, "rcv bufs unprocessed"); + initmark(&ctlr->wmrd, Nrd-1, "rcv descrs processed at once"); + initmark(&ctlr->wmtd, Ntd-1, "xmit descr queue len"); + ctlr->attached = 1; } - unlock(&c->alock); + qunlock(&ctlr->alock); poperror(); } @@ -968,33 +1012,33 @@ interrupt(Ureg*, void *v) { int icr, im; - Ctlr *c; + Ctlr *ctlr; Ether *e; e = v; - c = e->ctlr; - ilock(&c->imlock); - c->reg[Imc] = ~0; /* disable all intrs */ - im = c->im; - while((icr = c->reg[Icr] & c->im) != 0){ + ctlr = e->ctlr; + ilock(&ctlr->imlock); + ctlr->reg[Imc] = ~0; /* disable all intrs */ + im = ctlr->im; + while((icr = ctlr->reg[Icr] & ctlr->im) != 0){ if(icr & Irx0){ im &= ~Irx0; - c->rim = Irx0; - wakeup(&c->rrendez); + ctlr->rim = Irx0; + wakeup(&ctlr->rrendez); } if(icr & Itx0){ im &= ~Itx0; - c->tim = Itx0; - wakeup(&c->trendez); + ctlr->tim = Itx0; + wakeup(&ctlr->trendez); } if(icr & Lsc){ im &= ~Lsc; - c->lim = Lsc; - wakeup(&c->lrendez); + ctlr->lim = Lsc; + wakeup(&ctlr->lrendez); } } - c->reg[Ims] = c->im = im; /* enable only intrs we didn't service */ - iunlock(&c->imlock); + ctlr->reg[Ims] = ctlr->im = im; /* enable only intrs we didn't service */ + iunlock(&ctlr->imlock); } static void @@ -1003,7 +1047,7 @@ int pciregs, pcimsix, type; ulong io, iomsi; void *mem, *memmsi; - Ctlr *c; + Ctlr *ctlr; Pcidev *p; p = 0; @@ -1030,7 +1074,7 @@ continue; } pciregs = 0; - if(nctlr == nelem(ctlrtab)){ + if(nctlr >= nelem(ctlrtab)){ print("i82598: too many controllers\n"); return; } @@ -1052,28 +1096,28 @@ continue; } - c = malloc(sizeof *c); - if(c == nil) { + ctlr = malloc(sizeof *ctlr); + if(ctlr == nil) { vunmap(mem, p->mem[pciregs].size); vunmap(memmsi, p->mem[pcimsix].size); error(Enomem); } - c->p = p; - c->type = type; - c->physreg = (u32int*)io; - c->physmsix = (u32int*)iomsi; - c->reg = (u32int*)mem; - c->msix = (u32int*)memmsi; /* unused */ - c->rbsz = Rbsz; - if(reset(c)){ + ctlr->p = p; + ctlr->type = type; + ctlr->physreg = (u32int*)io; + ctlr->physmsix = (u32int*)iomsi; + ctlr->reg = (u32int*)mem; + ctlr->msix = (u32int*)memmsi; /* unused */ + ctlr->rbsz = Rbsz; + if(reset(ctlr)){ print("i82598: can't reset\n"); - free(c); + free(ctlr); vunmap(mem, p->mem[pciregs].size); vunmap(memmsi, p->mem[pcimsix].size); continue; } pcisetbme(p); - ctlrtab[nctlr++] = c; + ctlrtab[nctlr++] = ctlr; } } @@ -1081,27 +1125,28 @@ pnp(Ether *e) { int i; - Ctlr *c = nil; + Ctlr *ctlr; if(nctlr == 0) scan(); + ctlr = nil; for(i = 0; i < nctlr; i++){ - c = ctlrtab[i]; - if(c == nil || c->flag & Factive) + ctlr = ctlrtab[i]; + if(ctlr == nil || ctlr->flag & Factive) continue; - if(e->port == 0 || e->port == (ulong)c->reg) + if(e->port == 0 || e->port == (ulong)ctlr->reg) break; } if (i >= nctlr) return -1; - c->flag |= Factive; - e->ctlr = c; - e->port = (uintptr)c->physreg; - e->irq = c->p->intl; - e->tbdf = c->p->tbdf; + ctlr->flag |= Factive; + e->ctlr = ctlr; + e->port = (uintptr)ctlr->physreg; + e->irq = ctlr->p->intl; + e->tbdf = ctlr->p->tbdf; e->mbps = 10000; e->maxmtu = ETHERMAXTU; - memmove(e->ea, c->ra, Eaddrlen); + memmove(e->ea, ctlr->ra, Eaddrlen); e->arg = e; e->attach = attach; @@ -1121,4 +1166,5 @@ ether82598link(void) { addethercard("i82598", pnp); + addethercard("i10gbe", pnp); } --- /sys/src/9/pc/etherigbe.c Sat Mar 1 21:28:12 2014 +++ /sys/src/9/pc/etherigbe.c Tue Mar 11 20:47:04 2014 @@ -477,6 +477,10 @@ int link; + Watermark wmrb; + Watermark wmrd; + Watermark wmtd; + QLock slock; uint statistics[Nstatistics]; uint lsleep; @@ -521,6 +525,7 @@ static Lock igberblock; /* free receive Blocks */ static Block* igberbpool; /* receive Blocks for all igbe controllers */ +static int nrbfull; /* # of rcv Blocks with data awaiting processing */ static char* statistics[Nstatistics] = { "CRC Error", @@ -593,7 +598,7 @@ igbeifstat(Ether* edev, void* a, long n, ulong offset) { Ctlr *ctlr; - char *p, *s; + char *p, *s, *e; int i, l, r; uvlong tuvl, ruvl; @@ -667,6 +672,13 @@ } snprint(p+l, READSTR-l, "\n"); } + e = p + READSTR; + s = p + l + 1; + s = seprintmark(s, e, &ctlr->wmrb); + s = seprintmark(s, e, &ctlr->wmrd); + s = seprintmark(s, e, &ctlr->wmtd); + USED(s); + n = readstr(offset, a, n, p); free(p); qunlock(&ctlr->slock); @@ -789,6 +801,7 @@ ilock(&igberblock); bp->next = igberbpool; igberbpool = bp; + nrbfull--; iunlock(&igberblock); } @@ -1013,6 +1026,8 @@ td->control = ((BLEN(bp) & LenMASK)<control |= Dext|Ifcs|Teop|DtypeDD; ctlr->tb[tdt] = bp; + /* note size of queue of tds awaiting transmission */ + notemark(&ctlr->wmtd, (tdt + Ntd - tdh) % Ntd); tdt = NEXT(tdt, ctlr->ntd); if(NEXT(tdt, ctlr->ntd) == tdh){ td->control |= Rs; @@ -1085,6 +1100,7 @@ } } igbereplenish(ctlr); + nrbfull = 0; switch(ctlr->id){ case i82540em: @@ -1120,7 +1136,7 @@ Rd *rd; Block *bp; Ctlr *ctlr; - int r, rdh; + int r, rdh, passed; Ether *edev; edev = arg; @@ -1130,7 +1146,6 @@ r = csr32r(ctlr, Rctl); r |= Ren; csr32w(ctlr, Rctl, r); - for(;;){ ctlr->rim = 0; igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq); @@ -1138,6 +1153,7 @@ sleep(&ctlr->rrendez, igberim, ctlr); rdh = ctlr->rdh; + passed = 0; for(;;){ rd = &ctlr->rdba[rdh]; @@ -1180,7 +1196,12 @@ bp->checksum = rd->checksum; bp->flag |= Bpktck; } + ilock(&igberblock); + nrbfull++; + iunlock(&igberblock); + notemark(&ctlr->wmrb, nrbfull); etheriq(edev, bp, 1); + passed++; } else if(ctlr->rb[rdh] != nil){ freeb(ctlr->rb[rdh]); @@ -1196,6 +1217,8 @@ if(ctlr->rdfree < ctlr->nrd/2 || (ctlr->rim & Rxdmt0)) igbereplenish(ctlr); + /* note how many rds had full buffers */ + notemark(&ctlr->wmrd, passed); } } @@ -1258,6 +1281,9 @@ bp->free = igberbfree; freeb(bp); } + initmark(&ctlr->wmrb, Nrb, "rcv bufs unprocessed"); + initmark(&ctlr->wmrd, Nrd-1, "rcv descrs processed at once"); + initmark(&ctlr->wmtd, Ntd-1, "xmit descr queue len"); snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno); kproc(name, igbelproc, edev); --- /sys/src/9/pc/etherm10g.c Wed Feb 5 22:29:26 2014 +++ /sys/src/9/pc/etherm10g.c Wed Mar 12 00:05:20 2014 @@ -5,6 +5,8 @@ * the card is big endian. * we use uvlong rather than uintptr to hold addresses so that * we don't get "warning: stupid shift" on 32-bit architectures. + * + * appears to have massively-bloated buffers. */ #include "u.h" #include "../port/lib.h" @@ -34,9 +36,9 @@ enum { Epromsz = 256, - Maxslots= 1024, + Maxslots= 1024, /* rcv descriptors; wasteful: only 9 needed */ Align = 4096, - Maxmtu = 9000, + Maxmtu = 9000, /* jumbos; bad idea */ Noconf = 0xffffffff, Fwoffset= 1*MiB, --- /sys/src/9/pc/main.c Wed Feb 5 22:30:09 2014 +++ /sys/src/9/pc/main.c Tue Mar 11 20:49:31 2014 @@ -89,6 +89,27 @@ panic("cpu%d: can't allocate fpsavalign", m->machno); } +static int +isa20on(void) +{ + int r; + ulong o; + ulong *zp, *mb1p; + + zp = (ulong *)KZERO; + mb1p = (ulong *)(KZERO|MB); + o = *zp; + + *zp = 0x1234; + *mb1p = 0x8765; + coherence(); + wbinvd(); + r = *zp != *mb1p; + + *zp = o; + return r; +} + void main(void) { @@ -111,6 +132,8 @@ meminit(); confinit(); archinit(); + if(!isa20on()) + panic("bootstrap didn't leave a20 address line enabled"); xinit(); if(i8237alloc != nil) i8237alloc(); @@ -387,7 +410,8 @@ { char *p; int i, userpcnt; - ulong kpages; + unsigned mb; + ulong kpages, ksize; if(p = getconf("*kernelpercent")) userpcnt = 100 - strtol(p, 0, 0); @@ -420,10 +444,13 @@ * The patch of nimage is a band-aid, scanning the whole * page list in imagereclaim just takes too long. */ - if(kpages > (200*MB + conf.npage*sizeof(Page))/BY2PG){ - kpages = (200*MB + conf.npage*sizeof(Page))/BY2PG; - conf.nimage = 2000; - kpages += (conf.nproc*KSTACK)/BY2PG; + for (mb = 400; mb >= 100; mb /= 2) { + ksize = mb*MB + conf.npage*sizeof(Page); + if(kpages > ksize/BY2PG && cankaddr(ksize)) { + kpages = ksize/BY2PG + (conf.nproc*KSTACK)/BY2PG; + conf.nimage = 2000; + break; + } } } else { if(userpcnt < 10) { --- /sys/src/9/pc/mkfile Sat Mar 1 21:57:50 2014 +++ /sys/src/9/pc/mkfile Wed Mar 12 04:07:49 2014 @@ -45,6 +45,7 @@ sysproc.$O\ taslock.$O\ tod.$O\ + watermarks.$O\ xalloc.$O\ OBJ=\ --- /sys/src/9/port/portdat.h Wed Feb 5 22:33:16 2014 +++ /sys/src/9/port/portdat.h Tue Mar 11 20:44:26 2014 @@ -48,6 +48,7 @@ typedef struct Waitq Waitq; typedef struct Walkqid Walkqid; typedef struct Watchdog Watchdog; +typedef struct Watermark Watermark; typedef int Devgen(Chan*, char*, Dirtab*, int, int, Dir*); #pragma incomplete DevConf @@ -991,6 +992,15 @@ void (*disable)(void); /* watchdog disable */ void (*restart)(void); /* watchdog restart */ void (*stat)(char*, char*); /* watchdog statistics */ +}; + +struct Watermark +{ + int highwater; + int curr; + int max; + int hitmax; /* count: how many times hit max? */ + char *name; }; --- /sys/src/9/port/portfns.h Wed Feb 5 22:33:16 2014 +++ /sys/src/9/port/portfns.h Tue Mar 11 20:44:26 2014 @@ -134,6 +134,7 @@ void ilock(Lock*); void iunlock(Lock*); long incref(Ref*); +void initmark(Watermark *, int, char *); void initseg(void); int iprint(char*, ...); void isdir(Chan*); @@ -202,6 +203,7 @@ Rgrp* newrgrp(void); Proc* newproc(void); void nexterror(void); +void notemark(Watermark *, int); int notify(Ureg*); int nrand(int); uvlong ns2fastticks(uvlong); @@ -312,6 +314,7 @@ ulong segattach(Proc*, ulong, char *, ulong, ulong); void segclock(ulong); void segpage(Segment*, Page*); +char* seprintmark(char *, char *, Watermark *); int setcolor(ulong, ulong, ulong, ulong); void setkernur(Ureg*, Proc*); int setlabel(Label*); --- /sys/src/9/port/watermarks.c Thu Jan 1 01:00:00 1970 +++ /sys/src/9/port/watermarks.c Tue Mar 11 20:44:26 2014 @@ -0,0 +1,37 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +void +initmark(Watermark *wp, int max, char *name) +{ + memset(wp, 0, sizeof *wp); + wp->max = max; + wp->name = name; +} + +void +notemark(Watermark *wp, int val) +{ + /* enforce obvious limits */ + if (val < 0) + val = 0; + else if (val > wp->max) + val = wp->max; + + if (val > wp->highwater) { + wp->highwater = val; + if (val == wp->max && wp->curr < val) + wp->hitmax++; + } + wp->curr = val; +} + +char * +seprintmark(char *buf, char *ebuf, Watermark *wp) +{ + return seprint(buf, ebuf, "%s:\thighwater %d/%d curr %d hitmax %d\n", + wp->name, wp->highwater, wp->max, wp->curr, wp->hitmax); +}