diff --git a/sys/src/9/bcm64/ethergenet.c b/sys/src/9/bcm64/ethergenet.c index be1543d29..4ca06805b 100644 --- a/sys/src/9/bcm64/ethergenet.c +++ b/sys/src/9/bcm64/ethergenet.c @@ -768,7 +768,7 @@ linkproc(void *arg) REG(ctlr->regs[ExtRgmiiOobCtrl]) = (REG(ctlr->regs[ExtRgmiiOobCtrl]) & ~OobDisable) | RgmiiLink; umaccmd(ctlr, cmd, CmdSpeedMask|CmdHdEn|CmdRxPauseIgn|CmdTxPauseIgn); - edev->mbps = phy->speed; + ethersetspeed(edev, phy->speed); } edev->link = link; // print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps); diff --git a/sys/src/9/cycv/ethercycv.c b/sys/src/9/cycv/ethercycv.c index d20d91a39..2ee344ac3 100644 --- a/sys/src/9/cycv/ethercycv.c +++ b/sys/src/9/cycv/ethercycv.c @@ -127,20 +127,19 @@ ethproc(void *ved) } v = mdread(c, MDPHYCTRL); if((v & 0x40) != 0){ - sp = "1000BASE-T"; while((mdread(c, MDGSTATUS) & RECVOK) != RECVOK) ; - edev->mbps = 1000; c->r[MAC_CONFIG] &= ~(1<<15); - + ethersetspeed(edev, 1000); + sp = "1000BASE-T"; }else if((v & 0x20) != 0){ - sp = "100BASE-TX"; - edev->mbps = 100; c->r[MAC_CONFIG] = c->r[MAC_CONFIG] | (1<<15|1<<14); + ethersetspeed(edev, 100); + sp = "100BASE-TX"; }else if((v & 0x10) != 0){ - sp = "10BASE-T"; - edev->mbps = 10; c->r[MAC_CONFIG] = c->r[MAC_CONFIG] & ~(1<<14) | 1<<15; + ethersetspeed(edev, 10); + sp = "10BASE-T"; }else sp = "???"; if((v & 0x08) != 0){ diff --git a/sys/src/9/imx8/etherimx.c b/sys/src/9/imx8/etherimx.c index c6277ea9d..397dbc43e 100644 --- a/sys/src/9/imx8/etherimx.c +++ b/sys/src/9/imx8/etherimx.c @@ -515,7 +515,7 @@ linkproc(void *arg) wr(ctlr, ENET_RCR, rcr); wr(ctlr, ENET_TCR, tcr); - edev->mbps = phy->speed; + ethersetspeed(edev, phy->speed); wr(ctlr, ENET_RDAR, RDAR_ACTIVE); } diff --git a/sys/src/9/kw/ether1116.c b/sys/src/9/kw/ether1116.c index a856615c9..4751fbeda 100644 --- a/sys/src/9/kw/ether1116.c +++ b/sys/src/9/kw/ether1116.c @@ -1281,7 +1281,7 @@ kirkwoodmii(Ether *ether) } } - ether->mbps = phy->speed; + ethersetspeed(ether, phy->speed); MIIDBG("#l%d: kirkwoodmii: fd %d speed %d tfc %d rfc %d\n", ctlr->port, phy->fd, phy->speed, phy->tfc, phy->rfc); MIIDBG("mii done\n"); diff --git a/sys/src/9/pc/ether8139.c b/sys/src/9/pc/ether8139.c index 8a953c340..65d7c6cfe 100644 --- a/sys/src/9/pc/ether8139.c +++ b/sys/src/9/pc/ether8139.c @@ -646,14 +646,10 @@ rtl8139interrupt(Ureg*, void* arg) */ msr = csr8r(ctlr, Msr); if(!(msr & Linkb)){ - if(!(msr & Speed10) && edev->mbps != 100){ - edev->mbps = 100; - qsetlimit(edev->oq, 256*1024); - } - else if((msr & Speed10) && edev->mbps != 10){ - edev->mbps = 10; - qsetlimit(edev->oq, 65*1024); - } + if(msr & Speed10) + ethersetspeed(edev, 10); + else + ethersetspeed(edev, 100); } isr &= ~(Clc|PunLc); } diff --git a/sys/src/9/pc/ether8169.c b/sys/src/9/pc/ether8169.c index 1511d7d1a..bcc901906 100644 --- a/sys/src/9/pc/ether8169.c +++ b/sys/src/9/pc/ether8169.c @@ -876,7 +876,6 @@ static void rtl8169link(Ether* edev) { uint r; - int limit; Ctlr *ctlr; ctlr = edev->ctlr; @@ -887,18 +886,14 @@ rtl8169link(Ether* edev) * Could stall transmits if no link, maybe? */ edev->link = (r & Linksts) != 0; - - limit = 256*1024; - if(r & Speed10){ - edev->mbps = 10; - limit = 65*1024; - } else if(r & Speed100) - edev->mbps = 100; - else if(r & Speed1000) - edev->mbps = 1000; - - if(edev->oq != nil) - qsetlimit(edev->oq, limit); + if(edev->link){ + if(r & Speed10) + ethersetspeed(edev, 10); + else if(r & Speed100) + ethersetspeed(edev, 100); + else if(r & Speed1000) + ethersetspeed(edev, 1000); + } } static void diff --git a/sys/src/9/pc/ether82563.c b/sys/src/9/pc/ether82563.c index 4b47f6a77..544bc882b 100644 --- a/sys/src/9/pc/ether82563.c +++ b/sys/src/9/pc/ether82563.c @@ -1222,10 +1222,11 @@ phyl79proc(void *v) } i = (phy>>8) & 3; e->link = i != 3 && (phy & Link) != 0; - if(e->link == 0) + if(e->link) + ethersetspeed(e, speedtab[i]); + else i = 3; c->speeds[i]++; - e->mbps = speedtab[i]; lsleep(c, Lsc); } } @@ -1278,10 +1279,11 @@ phylproc(void *v) phywrite(c, phyno, Phyctl, phyread(c, phyno, Phyctl) | Ran | Ean); next: e->link = (phy & Rtlink) != 0; - if(e->link == 0) + if(e->link) + ethersetspeed(e, speedtab[i]); + else i = 3; c->speeds[i]++; - e->mbps = speedtab[i]; if(c->type == i82563) phyerrata(e, c, phyno); lsleep(c, Lsc); @@ -1306,12 +1308,12 @@ pcslproc(void *v) phy = csr32r(c, Pcsstat); e->link = phy & Linkok; i = 3; - if(e->link) + if(e->link){ i = (phy & 6) >> 1; - else if(phy & Anbad) + ethersetspeed(e, speedtab[i]); + }else if(phy & Anbad) csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart); c->speeds[i]++; - e->mbps = speedtab[i]; lsleep(c, Lsc | Omed); } } @@ -1334,10 +1336,11 @@ serdeslproc(void *v) e->link = (rx & 1<<31) != 0; // e->link = (csr32r(c, Status) & Lu) != 0; i = 3; - if(e->link) + if(e->link){ i = 2; + ethersetspeed(e, speedtab[i]); + } c->speeds[i]++; - e->mbps = speedtab[i]; lsleep(c, Lsc); } } diff --git a/sys/src/9/pc/ether82598.c b/sys/src/9/pc/ether82598.c index e03698343..b41e943b6 100644 --- a/sys/src/9/pc/ether82598.c +++ b/sys/src/9/pc/ether82598.c @@ -386,10 +386,11 @@ lproc(void *v) r = c->reg[Links]; e->link = (r & Lnkup) != 0; i = 0; - if(e->link) + if(e->link){ i = 1 + ((r & Lnkspd) != 0); + ethersetspeed(e, speedtab[i]); + } c->speeds[i]++; - e->mbps = speedtab[i]; c->lim = 0; im(c, Lsc); sleep(&c->lrendez, lim, c); diff --git a/sys/src/9/pc/etherbcm.c b/sys/src/9/pc/etherbcm.c index a6700ede2..1fd08d0af 100644 --- a/sys/src/9/pc/etherbcm.c +++ b/sys/src/9/pc/etherbcm.c @@ -331,12 +331,12 @@ checklink(Ether *edev) { Ctlr *ctlr; ulong i; + int mbps; ctlr = edev->ctlr; miir(ctlr, PhyStatus); /* dummy read necessary */ if(!(miir(ctlr, PhyStatus) & PhyLinkStatus)) { edev->link = 0; - edev->mbps = 1000; ctlr->duplex = 1; print("bcm: no link\n"); goto out; @@ -345,26 +345,26 @@ checklink(Ether *edev) while((miir(ctlr, PhyStatus) & PhyAutoNegComplete) == 0); i = miir(ctlr, PhyGbitStatus); if(i & (Phy1000FD | Phy1000HD)) { - edev->mbps = 1000; + mbps = 1000; ctlr->duplex = (i & Phy1000FD) != 0; } else if(i = miir(ctlr, PhyPartnerStatus), i & (Phy100FD | Phy100HD)) { - edev->mbps = 100; + mbps = 100; ctlr->duplex = (i & Phy100FD) != 0; } else if(i & (Phy10FD | Phy10HD)) { - edev->mbps = 10; + mbps = 10; ctlr->duplex = (i & Phy10FD) != 0; } else { edev->link = 0; - edev->mbps = 1000; ctlr->duplex = 1; print("bcm: link partner supports neither 10/100/1000 Mbps\n"); goto out; } - print("bcm: %d Mbps link, %s duplex\n", edev->mbps, ctlr->duplex ? "full" : "half"); + print("bcm: %d Mbps link, %s duplex\n", mbps, ctlr->duplex ? "full" : "half"); + ethersetspeed(edev, mbps); out: if(ctlr->duplex) csr32(ctlr, MACMode) &= ~MACHalfDuplex; else csr32(ctlr, MACMode) |= MACHalfDuplex; - if(edev->mbps >= 1000) + if(mbps >= 1000) csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortGMII; else csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortMII; diff --git a/sys/src/9/pc/etherelnk3.c b/sys/src/9/pc/etherelnk3.c index 37a76a61f..d39cab622 100644 --- a/sys/src/9/pc/etherelnk3.c +++ b/sys/src/9/pc/etherelnk3.c @@ -1972,14 +1972,14 @@ etherelnk3reset(Ether* ether) } XCVRDEBUG("mii anar: %uX\n", anar); if(anar & 0x0100){ /* 100BASE-TXFD */ - ether->mbps = 100; + ethersetspeed(ether, 100); setfullduplex(port); } else if(anar & 0x0200){ /* 100BASE-T4 */ /* nothing to do */ } else if(anar & 0x0080) /* 100BASE-TX */ - ether->mbps = 100; + ethersetspeed(ether, 100); else if(anar & 0x0040) /* 10BASE-TFD */ setfullduplex(port); else{ /* 10BASE-T */ @@ -1998,7 +1998,7 @@ etherelnk3reset(Ether* ether) outs(port+MediaStatus, x); if(x & dataRate100) - ether->mbps = 100; + ethersetspeed(ether, 100); break; case xcvr10BaseT: /* diff --git a/sys/src/9/pc/etherga620.c b/sys/src/9/pc/etherga620.c index 282c115fc..65e4a6bf0 100644 --- a/sys/src/9/pc/etherga620.c +++ b/sys/src/9/pc/etherga620.c @@ -581,13 +581,14 @@ ga620event(Ether *edev, int eci, int epi) case 0x06: /* link state changed */ switch (code) { case 1: - edev->mbps = 1000; + ethersetspeed(edev, 1000); break; case 2: print("#l%d: link down\n", edev->ctlrno); break; case 3: - edev->mbps = 100; /* it's 10 or 100 */ + /* it's 10 or 100 */ + ethersetspeed(edev, 100); break; } if (code != 2) diff --git a/sys/src/9/pc/etherwpi.c b/sys/src/9/pc/etherwpi.c index 999790509..dac236bf0 100644 --- a/sys/src/9/pc/etherwpi.c +++ b/sys/src/9/pc/etherwpi.c @@ -1586,8 +1586,6 @@ wpiattach(Ether *edev) error("wifi disabled by switch"); if(ctlr->wifi == nil){ - qsetlimit(edev->oq, MaxQueue); - ctlr->wifi = wifiattach(edev, transmit); ctlr->wifi->rates = wpirates; } diff --git a/sys/src/9/pc/etherx550.c b/sys/src/9/pc/etherx550.c index 46495939e..c35830afe 100644 --- a/sys/src/9/pc/etherx550.c +++ b/sys/src/9/pc/etherx550.c @@ -348,10 +348,11 @@ lproc(void *v) r = c->reg[Links]; e->link = (r & Lnkup) != 0; i = 0; - if(e->link) + if(e->link){ i = 1 + ((r & Lnkspd) != 0); + ethersetspeed(e, speedtab[i]); + } c->speeds[i]++; - e->mbps = speedtab[i]; c->lim = 0; im(c, Lsc); sleep(&c->lrendez, lim, c); diff --git a/sys/src/9/pc/etheryuk.c b/sys/src/9/pc/etheryuk.c index 29586d632..b03b632f1 100644 --- a/sys/src/9/pc/etheryuk.c +++ b/sys/src/9/pc/etheryuk.c @@ -1358,23 +1358,16 @@ static int spdtab[4] = { static void link(Ether *e) { - uint i, s, spd; + uint i, s; Ctlr *c; c = e->ctlr; i = phyread(c, Phyint); s = phyread(c, Phylstat); dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s); - spd = 0; e->link = (s & Plink) != 0; - if(e->link && c->feat&Ffiber) - spd = 1000; - else if(e->link){ - spd = s & Physpd; - spd >>= 14; - spd = spdtab[spd]; - } - e->mbps = spd; + if(e->link) + ethersetspeed(e, (c->feat&Ffiber)? 1000: spdtab[(s & Physpd) >> 14]); dprint("#l%d: yuk: link %d spd %d\n", e->ctlrno, e->link, e->mbps); } diff --git a/sys/src/9/port/devether.c b/sys/src/9/port/devether.c index 09fd9daa1..e870af198 100644 --- a/sys/src/9/port/devether.c +++ b/sys/src/9/port/devether.c @@ -373,11 +373,31 @@ addethercard(char* t, int (*r)(Ether*)) ncard++; } +static int +etherqueuesize(Ether *ether) +{ + int lg, mb; + ulong bsz; + + /* compute log10(mbps) into lg */ + for(lg = 0, mb = ether->mbps; mb >= 10; lg++) + mb /= 10; + if (lg > 0) + lg--; + if (lg > 14) /* 2^(14+17) = 2³¹ */ + lg = 14; + /* allocate larger output queues for higher-speed interfaces */ + bsz = 1UL << (lg + 17); /* 2¹⁷ = 128K, bsz = 2ⁿ × 128K */ + while (bsz > mainmem->maxsize / 8 && bsz > 128*1024) + bsz /= 2; +if(0) print("#l%d: %d Mbps -> queue size %lud\n", ether->ctlrno, ether->mbps, bsz); + return (int)bsz; +} + static Ether* etherprobe(int cardno, int ctlrno, char *conf) { - int i, lg; - ulong mb, bsz; + int i; Ether *ether; ether = malloc(sizeof(Ether)); @@ -430,26 +450,14 @@ Nope: print("#l%d: %s: %dMbps port 0x%lluX irq %d ea %E\n", ctlrno, ether->type, ether->mbps, (uvlong)ether->port, ether->irq, ether->ea); - /* compute log10(ether->mbps) into lg */ - for(lg = 0, mb = ether->mbps; mb >= 10; lg++) - mb /= 10; - if (lg > 0) - lg--; - if (lg > 14) /* 2^(14+17) = 2³¹ */ - lg = 14; - /* allocate larger output queues for higher-speed interfaces */ - bsz = 1UL << (lg + 17); /* 2¹⁷ = 128K, bsz = 2ⁿ × 128K */ - while (bsz > mainmem->maxsize / 8 && bsz > 128*1024) - bsz /= 2; - - netifinit(ether, ether->name, Ntypes, bsz); - if(ether->oq == nil) { - ether->oq = qopen(bsz, Qmsg, 0, 0); - ether->limit = bsz; + netifinit(ether, ether->name, Ntypes, etherqueuesize(ether)); + if(ether->oq == nil){ + ether->oq = qopen(ether->limit, Qmsg, 0, 0); + if(ether->oq == nil) + panic("etherreset %s: can't allocate output queue", ether->name); + } else { + qsetlimit(ether->oq, ether->limit); } - if(ether->oq == nil) - panic("etherreset %s: can't allocate output queue of %ld bytes", ether->name, bsz); - ether->alen = Eaddrlen; memmove(ether->addr, ether->ea, Eaddrlen); memset(ether->bcast, 0xFF, Eaddrlen); @@ -457,6 +465,18 @@ Nope: return ether; } +void +ethersetspeed(Ether *ether, int mbps) +{ + if(ether->mbps == mbps) + return; + ether->mbps = mbps; + if(mbps <= 0 || ether->oq == nil) + return; + netifsetlimit(ether, etherqueuesize(ether)); + qsetlimit(ether->oq, ether->limit); +} + static void netconsole(int); static void diff --git a/sys/src/9/port/etherif.h b/sys/src/9/port/etherif.h index c5f7f8c67..35e00f34e 100644 --- a/sys/src/9/port/etherif.h +++ b/sys/src/9/port/etherif.h @@ -51,6 +51,7 @@ struct Ether { DMAT* dmat; }; +extern void ethersetspeed(Ether*, int); extern void etheriq(Ether*, Block*); extern void addethercard(char*, int(*)(Ether*)); extern ulong ethercrc(uchar*, int); diff --git a/sys/src/9/port/etheriwl.c b/sys/src/9/port/etheriwl.c index 06ae80747..8a9663112 100644 --- a/sys/src/9/port/etheriwl.c +++ b/sys/src/9/port/etheriwl.c @@ -4103,8 +4103,6 @@ iwlattach(Ether *edev) error(err); if(ctlr->wifi == nil){ - qsetlimit(edev->oq, MaxQueue); - ctlr->wifi = wifiattach(edev, transmit); /* tested with 2230, it has transmit issues using higher bit rates */ if(ctlr->family >= 7000 || ctlr->type != Type2030) diff --git a/sys/src/9/port/netif.c b/sys/src/9/port/netif.c index b63051a3b..42a3b3ccc 100644 --- a/sys/src/9/port/netif.c +++ b/sys/src/9/port/netif.c @@ -16,7 +16,7 @@ static int parseaddr(uchar*, char*, int); * set up a new network interface */ void -netifinit(Netif *nif, char *name, int nfile, ulong limit) +netifinit(Netif *nif, char *name, int nfile, int limit) { if(strlen(name) >= sizeof nif->name) panic("netifinit: name too long: %s", name); @@ -29,6 +29,28 @@ netifinit(Netif *nif, char *name, int nfile, ulong limit) nif->limit = limit; } +/* + * adjust input queue sizes for all files + */ +void +netifsetlimit(Netif *nif, int limit) +{ + Netfile *f; + int i; + + qlock(nif); + nif->limit = limit; + for(i = 0; i < nif->nfile; i++){ + f = nif->f[i]; + if(f == nil) + continue; + qlock(f); + qsetlimit(f->in, nif->limit); + qunlock(f); + } + qunlock(nif); +} + /* * generate a 3 level directory */ diff --git a/sys/src/9/port/netif.h b/sys/src/9/port/netif.h index c5a11b7b5..90dc48330 100644 --- a/sys/src/9/port/netif.h +++ b/sys/src/9/port/netif.h @@ -108,7 +108,8 @@ struct Netif char* (*ifstat)(void*, char*, char*); }; -void netifinit(Netif*, char*, int, ulong); +void netifinit(Netif*, char*, int, int); +void netifsetlimit(Netif *, int); Walkqid* netifwalk(Netif*, Chan*, Chan*, char **, int); Chan* netifopen(Netif*, Chan*, int); void netifclose(Netif*, Chan*); diff --git a/sys/src/9/port/wifi.c b/sys/src/9/port/wifi.c index 06dfaf468..9bb6cf258 100644 --- a/sys/src/9/port/wifi.c +++ b/sys/src/9/port/wifi.c @@ -817,7 +817,7 @@ Scan: while((wn = wifi->bss) != nil){ ether->link = (wn->status == Sassoc) || (wn->status == Sblocked); if(ether->link && (rate = wn->actrate) != nil) - ether->mbps = ((*rate & 0x7f)+3)/4; + ethersetspeed(ether, ((*rate & 0x7f)+3)/4); now = MACHP(0)->ticks; if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 20 || goodbss(wifi, wn) == 0){ wifideauth(wifi, wn); diff --git a/sys/src/9/ppc/etherfcc.c b/sys/src/9/ppc/etherfcc.c index 2e4e31a5f..3796aa0e6 100644 --- a/sys/src/9/ppc/etherfcc.c +++ b/sys/src/9/ppc/etherfcc.c @@ -870,7 +870,7 @@ fccltimer(Ureg*, Timer *t) print("link lost\n"); return; } - ether->mbps = phy->speed; + ethersetspeed(ether, phy->speed); if(phy->fd != ctlr->duplex) print("set duplex\n"); diff --git a/sys/src/9/teg2/ether8169.c b/sys/src/9/teg2/ether8169.c index edd97f17d..72063e78c 100644 --- a/sys/src/9/teg2/ether8169.c +++ b/sys/src/9/teg2/ether8169.c @@ -1275,7 +1275,6 @@ static void rtl8169link(Ether* edev) { uint r; - int limit; Ctlr *ctlr; ctlr = edev->ctlr; @@ -1288,22 +1287,17 @@ rtl8169link(Ether* edev) } return; } - if (edev->link == 0) { + if(edev->link == 0) { edev->link = 1; csr8w(ctlr, Cr, Te|Re); iprint("#l%d: link up\n", edev->ctlrno); } - limit = 256*1024; - if(r & Speed10){ - edev->mbps = 10; - limit = 65*1024; - } else if(r & Speed100) - edev->mbps = 100; + if(r & Speed10) + ethersetspeed(edev, 10); + else if(r & Speed100) + ethersetspeed(edev, 100); else if(r & Speed1000) - edev->mbps = 1000; - - if(edev->oq != nil) - qsetlimit(edev->oq, limit); + ethersetspeed(edev, 1000); } static void diff --git a/sys/src/9/zynq/etherzynq.c b/sys/src/9/zynq/etherzynq.c index 709dad0b7..cfd784f9c 100644 --- a/sys/src/9/zynq/etherzynq.c +++ b/sys/src/9/zynq/etherzynq.c @@ -159,19 +159,19 @@ ethproc(void *ved) sp = "1000BASE-T"; while((mdread(c, MDGSTATUS) & RECVOK) != RECVOK) ; - edev->mbps = 1000; c->r[NET_CFG] |= GIGE_EN; slcr[GEM0_CLK_CTRL] = 1 << 20 | 8 << 8 | 1; + ethersetspeed(edev, 1000); }else if((v & 0x20) != 0){ sp = "100BASE-TX"; - edev->mbps = 100; c->r[NET_CFG] = c->r[NET_CFG] & ~GIGE_EN | SPEED; slcr[GEM0_CLK_CTRL] = 5 << 20 | 8 << 8 | 1; + ethersetspeed(edev, 100); }else if((v & 0x10) != 0){ sp = "10BASE-T"; - edev->mbps = 10; c->r[NET_CFG] = c->r[NET_CFG] & ~(GIGE_EN | SPEED); slcr[GEM0_CLK_CTRL] = 20 << 20 | 20 << 8 | 1; + ethersetspeed(edev, 10); }else sp = "???"; if((v & 0x08) != 0){