Compare commits

...

8 commits

Author SHA1 Message Date
Ori Bernstein
8b7a03c5e9 gefs: remove daed mkfile bits
when we imported gefs, we put the manpages in the right
place, and moved the paper to /sys/doc; we don't need
the rules to build and install them any more
2025-01-09 05:20:08 +00:00
Arne
b0e7312a62 gefs(8): fix indent of empty snapshot paragraph 2025-01-08 19:36:17 +00:00
cinap_lenrek
c6a91038b1 stats: add etherovf value (hw and software overflows on input queue) 2025-01-07 11:54:07 +00:00
cinap_lenrek
22d3ade384 devether: don't print link-status until netif is initialized 2025-01-07 11:52:48 +00:00
cinap_lenrek
705a2c3c28 netif: fix potential memory leak in netifwstat()
convM2D() might fault and raise error, leaking
sizeof(Dir)+n allocation.
2025-01-07 06:49:40 +00:00
cinap_lenrek
00c25292d7 devether: print mbps only on link-up
To avoid frequent prints of the current link speed,
which in case of wifi is adjusted based link quality,
print the link speed only on link up events.
2025-01-07 03:50:45 +00:00
cinap_lenrek
5dde462f96 devether: make link status prints consistent
Provide ethersetlink() function for norifying about
link status changes, which will do the printing
that includes the controller number.
2025-01-07 03:10:35 +00:00
cinap_lenrek
682e47137a ether2114x: fix automatic media detection
We used to reject media info if FD was not specified
in plan9.ini. Instead, initialize fd override to -1
which makes us use it if the infoblock tells us to
and provide a "HD" option to force half-duplex mode.

This makes the media detection work on hyper-v.
2025-01-07 00:45:41 +00:00
28 changed files with 162 additions and 140 deletions

View file

@ -148,7 +148,7 @@ snapshot are required for the file system to work correctly, and may not be remo
.I dump: .I dump:
This is the name used to mount a list of all snapshots. This is the name used to mount a list of all snapshots.
Each snapshot in the file system will be listed in a directory. Each snapshot in the file system will be listed in a directory.
.IP .TP
.I empty: .I empty:
This is a read-only empty snapshot. This is a read-only empty snapshot.
It contains no files or directories. It contains no files or directories.

View file

@ -1400,7 +1400,7 @@ linkdown(Ctlr *ctl)
if(edev == nil || ctl->status == Disconnected) if(edev == nil || ctl->status == Disconnected)
return; return;
ctl->status = Disconnected; ctl->status = Disconnected;
edev->link = 0; ethersetlink(edev, 0);
/* send eof to aux/wpa */ /* send eof to aux/wpa */
for(i = 0; i < edev->nfile; i++){ for(i = 0; i < edev->nfile; i++){
f = edev->f[i]; f = edev->f[i];
@ -1550,7 +1550,7 @@ bcmevent(Ctlr *ctl, uchar *p, int len)
break; break;
case 16: /* E_LINK */ case 16: /* E_LINK */
if(flags&1){ /* link up */ if(flags&1){ /* link up */
ctl->edev->link = 1; ethersetlink(ctl->edev, 1);
break; break;
} }
/* fall through */ /* fall through */
@ -1812,8 +1812,8 @@ wljoin(Ctlr *ctl, char *ssid, int chan)
ctl->status = Connecting; ctl->status = Connecting;
switch(waitjoin(ctl)){ switch(waitjoin(ctl)){
case 0: case 0:
ctl->edev->link = 1;
ctl->status = Connected; ctl->status = Connected;
ethersetlink(ctl->edev, 1);
break; break;
case 3: case 3:
ctl->status = Disconnected; ctl->status = Disconnected;

View file

@ -770,8 +770,7 @@ linkproc(void *arg)
ethersetspeed(edev, phy->speed); ethersetspeed(edev, phy->speed);
} }
edev->link = link; ethersetlink(edev, link);
// print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps);
} }
} }

View file

@ -111,7 +111,6 @@ ethproc(void *ved)
{ {
Ether *edev; Ether *edev;
Ctlr *c; Ctlr *c;
char *sp, *dpl;
u16int v; u16int v;
edev = ved; edev = ved;
@ -120,8 +119,7 @@ ethproc(void *ved)
mdwrite(c, MDCTRL, AUTONEG); mdwrite(c, MDCTRL, AUTONEG);
for(;;){ for(;;){
if((mdread(c, MDSTATUS) & LINK) == 0){ if((mdread(c, MDSTATUS) & LINK) == 0){
edev->link = 0; ethersetlink(edev, 0);
print("eth: no link\n");
while((mdread(c, MDSTATUS) & LINK) == 0) while((mdread(c, MDSTATUS) & LINK) == 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);
} }
@ -131,26 +129,19 @@ ethproc(void *ved)
; ;
c->r[MAC_CONFIG] &= ~(1<<15); c->r[MAC_CONFIG] &= ~(1<<15);
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
sp = "1000BASE-T";
}else if((v & 0x20) != 0){ }else if((v & 0x20) != 0){
c->r[MAC_CONFIG] = c->r[MAC_CONFIG] | (1<<15|1<<14); c->r[MAC_CONFIG] = c->r[MAC_CONFIG] | (1<<15|1<<14);
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
sp = "100BASE-TX";
}else if((v & 0x10) != 0){ }else if((v & 0x10) != 0){
c->r[MAC_CONFIG] = c->r[MAC_CONFIG] & ~(1<<14) | 1<<15; c->r[MAC_CONFIG] = c->r[MAC_CONFIG] & ~(1<<14) | 1<<15;
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
sp = "10BASE-T"; }
}else
sp = "???";
if((v & 0x08) != 0){ if((v & 0x08) != 0){
dpl = "full";
c->r[MAC_CONFIG] |= 1<<11; c->r[MAC_CONFIG] |= 1<<11;
}else{ }else{
dpl = "half";
c->r[MAC_CONFIG] &= ~(1<<11); c->r[MAC_CONFIG] &= ~(1<<11);
} }
edev->link = 1; ethersetlink(edev, 1);
print("eth: %s %s duplex link\n", sp, dpl);
c->r[MAC_CONFIG] |= 1<<3 | 1<<2; c->r[MAC_CONFIG] |= 1<<3 | 1<<2;
while((mdread(c, MDSTATUS) & LINK) != 0) while((mdread(c, MDSTATUS) & LINK) != 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);

View file

@ -519,8 +519,7 @@ linkproc(void *arg)
wr(ctlr, ENET_RDAR, RDAR_ACTIVE); wr(ctlr, ENET_RDAR, RDAR_ACTIVE);
} }
edev->link = link; ethersetlink(edev, link);
print("#l%d: link %d speed %d\n", edev->ctlrno, edev->link, edev->mbps);
} }
} }

View file

@ -866,9 +866,9 @@ interrupt(Ureg*, void *arg)
* thus we note the link change here, and check for * thus we note the link change here, and check for
* that and autonegotiation done below. * that and autonegotiation done below.
*/ */
if(irqe & IEphystschg) { if(irqe & IEphystschg){
ether->link = (reg->ps0 & PS0linkup) != 0;
ctlr->linkchg = 1; ctlr->linkchg = 1;
ethersetlink(ether, reg->ps0 & PS0linkup);
} }
if(irqe & IEtxerrq(Qno)) if(irqe & IEtxerrq(Qno))
ether->oerrs++; ether->oerrs++;
@ -895,8 +895,8 @@ interrupt(Ureg*, void *arg)
if(ctlr->linkchg && (reg->ps1 & PS1an_done)) { if(ctlr->linkchg && (reg->ps1 & PS1an_done)) {
handled++; handled++;
ether->link = (reg->ps0 & PS0linkup) != 0;
ctlr->linkchg = 0; ctlr->linkchg = 0;
ethersetlink(ether, reg->ps0 & PS0linkup);
} }
ctlr->newintrs++; ctlr->newintrs++;

View file

@ -1623,7 +1623,7 @@ srom(Ctlr* ctlr)
} }
} }
ctlr->fd = 0; ctlr->fd = -1;
ctlr->medium = -1; ctlr->medium = -1;
return 0; return 0;
@ -1776,13 +1776,15 @@ reset(Ether* ether)
* (no MII) or the autonegotiation fails. * (no MII) or the autonegotiation fails.
*/ */
for(i = 0; i < ether->nopt; i++){ for(i = 0; i < ether->nopt; i++){
if(cistrcmp(ether->opt[i], "HD") == 0){
ctlr->fd = 0;
continue;
}
if(cistrcmp(ether->opt[i], "FD") == 0){ if(cistrcmp(ether->opt[i], "FD") == 0){
ctlr->fd = 1; ctlr->fd = 1;
continue; continue;
} }
for(x = 0; x < nelem(mediatable); x++){ for(x = 0; x < nelem(mediatable); x++){
debug("compare <%s> <%s>\n", mediatable[x],
ether->opt[i]);
if(cistrcmp(mediatable[x], ether->opt[i])) if(cistrcmp(mediatable[x], ether->opt[i]))
continue; continue;
ctlr->medium = x; ctlr->medium = x;
@ -1803,6 +1805,7 @@ reset(Ether* ether)
} }
ether->mbps = media(ether, 1); ether->mbps = media(ether, 1);
ether->link = ether->mbps != 0;
/* /*
* Initialise descriptor rings, ethernet address. * Initialise descriptor rings, ethernet address.

View file

@ -880,19 +880,21 @@ rtl8169link(Ether* edev)
ctlr = edev->ctlr; ctlr = edev->ctlr;
r = csr8r(ctlr, Phystatus);
/* /*
* Maybe the link changed - do we care very much? * Maybe the link changed - do we care very much?
* Could stall transmits if no link, maybe? * Could stall transmits if no link, maybe?
*/ */
edev->link = (r & Linksts) != 0; r = csr8r(ctlr, Phystatus);
if(edev->link){ if(r & Linksts){
if(r & Speed10) if(r & Speed10)
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
else if(r & Speed100) else if(r & Speed100)
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
else if(r & Speed1000) else if(r & Speed1000)
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
ethersetlink(edev, 1);
} else {
ethersetlink(edev, 0);
} }
} }

View file

@ -508,7 +508,7 @@ struct Ctlr {
uvlong port; uvlong port;
Pcidev *pcidev; Pcidev *pcidev;
Ctlr *next; Ctlr *next;
int active; Ether *edev;
int type; int type;
u16int eeprom[0x40]; u16int eeprom[0x40];
@ -851,7 +851,7 @@ i82563cleanup(Ctlr *c)
c->tb[tdh] = nil; c->tb[tdh] = nil;
freeb(b); freeb(b);
}else }else
iprint("82563 tx underrun!\n"); iprint("#l%d: %s: tx underrun!\n", c->edev->ctlrno, cname(c));
c->tdba[tdh].status = 0; c->tdba[tdh].status = 0;
} }
@ -914,7 +914,7 @@ i82563replenish(Ctlr *ctlr)
for(rdt = ctlr->rdt; NEXT(rdt, ctlr->nrd) != ctlr->rdh; rdt = NEXT(rdt, ctlr->nrd)){ for(rdt = ctlr->rdt; NEXT(rdt, ctlr->nrd) != ctlr->rdh; rdt = NEXT(rdt, ctlr->nrd)){
rd = &ctlr->rdba[rdt]; rd = &ctlr->rdba[rdt];
if(ctlr->rb[rdt] != nil){ if(ctlr->rb[rdt] != nil){
iprint("82563: tx overrun\n"); iprint("#l%d: %s: tx overrun\n", ctlr->edev->ctlrno, cname(ctlr));
break; break;
} }
i++; i++;
@ -1097,7 +1097,7 @@ phyread(Ctlr *c, int phyno, int reg)
microdelay(1); microdelay(1);
} }
if((phy & (MDIe|MDIready)) != MDIready){ if((phy & (MDIe|MDIready)) != MDIready){
print("%s: phy %d wedged %.8ux\n", cname(c), phyno, phy); print("#l%d: %s: phy %d wedged %.8ux\n", c->edev->ctlrno, cname(c), phyno, phy);
return ~0; return ~0;
} }
return phy & 0xffff; return phy & 0xffff;
@ -1143,18 +1143,18 @@ static uint
phywrite(Ctlr *c, uint phyno, uint reg, ushort v) phywrite(Ctlr *c, uint phyno, uint reg, ushort v)
{ {
if(setpage(c, phyno, reg>>8, reg & 0xff) == ~0) if(setpage(c, phyno, reg>>8, reg & 0xff) == ~0)
panic("%s: bad phy reg %.4ux", cname(c), reg); panic("#l%d: %s: bad phy reg %.4ux", c->edev->ctlrno, cname(c), reg);
return phywrite0(c, phyno, reg & 0xff, v); return phywrite0(c, phyno, reg & 0xff, v);
} }
static void static void
phyerrata(Ether *e, Ctlr *c, uint phyno) phyerrata(Ctlr *c, uint phyno)
{ {
if(e->mbps == 0){ if(c->edev->mbps == 0){
if(c->phyerrata == 0){ if(c->phyerrata == 0){
c->phyerrata++; c->phyerrata++;
phywrite(c, phyno, Phyprst, Prst); /* try a port reset */ phywrite(c, phyno, Phyprst, Prst); /* try a port reset */
print("%s: phy port reset\n", cname(c)); print("#l%d: %s: phy port reset\n", c->edev->ctlrno, cname(c));
} }
}else }else
c->phyerrata = 0; c->phyerrata = 0;
@ -1174,10 +1174,11 @@ phyprobe(Ctlr *c, uint mask)
phy |= phyread(c, phyno, Phyid2) >> 10; phy |= phyread(c, phyno, Phyid2) >> 10;
if(phy == 0xFFFFF || phy == 0) if(phy == 0xFFFFF || phy == 0)
continue; continue;
print("%s: phy%d oui %#ux\n", cname(c), phyno, phy); print("#l%d: %s: phy%d oui %#ux\n", c->edev->ctlrno, cname(c),
phyno, phy);
return phyno; return phyno;
} }
print("%s: no phy\n", cname(c)); print("#l%d: %s: no phy\n", c->edev->ctlrno, cname(c));
return ~0; return ~0;
} }
@ -1221,11 +1222,13 @@ phyl79proc(void *v)
break; break;
} }
i = (phy>>8) & 3; i = (phy>>8) & 3;
e->link = i != 3 && (phy & Link) != 0; if(i != 3 && (phy & Link) != 0){
if(e->link)
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
else ethersetlink(e, 1);
}else{
ethersetlink(e, 0);
i = 3; i = 3;
}
c->speeds[i]++; c->speeds[i]++;
lsleep(c, Lsc); lsleep(c, Lsc);
} }
@ -1278,14 +1281,16 @@ phylproc(void *v)
if(a) if(a)
phywrite(c, phyno, Phyctl, phyread(c, phyno, Phyctl) | Ran | Ean); phywrite(c, phyno, Phyctl, phyread(c, phyno, Phyctl) | Ran | Ean);
next: next:
e->link = (phy & Rtlink) != 0; if(phy & Rtlink){
if(e->link)
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
else ethersetlink(e, 1);
}else{
ethersetlink(e, 0);
i = 3; i = 3;
}
c->speeds[i]++; c->speeds[i]++;
if(c->type == i82563) if(c->type == i82563)
phyerrata(e, c, phyno); phyerrata(c, phyno);
lsleep(c, Lsc); lsleep(c, Lsc);
} }
} }
@ -1306,13 +1311,16 @@ pcslproc(void *v)
csr32w(c, Connsw, Enrgirq); csr32w(c, Connsw, Enrgirq);
for(;;){ for(;;){
phy = csr32r(c, Pcsstat); phy = csr32r(c, Pcsstat);
e->link = phy & Linkok; if(phy & Linkok){
i = 3;
if(e->link){
i = (phy & 6) >> 1; i = (phy & 6) >> 1;
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
}else if(phy & Anbad) ethersetlink(e, 1);
csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart); }else {
ethersetlink(e, 0);
if(phy & Anbad)
csr32w(c, Pcsctl, csr32r(c, Pcsctl) | Pan | Prestart);
i = 3;
}
c->speeds[i]++; c->speeds[i]++;
lsleep(c, Lsc | Omed); lsleep(c, Lsc | Omed);
} }
@ -1333,12 +1341,13 @@ serdeslproc(void *v)
rx = csr32r(c, Rxcw); rx = csr32r(c, Rxcw);
tx = csr32r(c, Txcw); tx = csr32r(c, Txcw);
USED(tx); USED(tx);
e->link = (rx & 1<<31) != 0; if(rx & 1<<31){ /*(csr32r(c, Status) & Lu*/
// e->link = (csr32r(c, Status) & Lu) != 0;
i = 3;
if(e->link){
i = 2; i = 2;
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
i = 3;
} }
c->speeds[i]++; c->speeds[i]++;
lsleep(c, Lsc); lsleep(c, Lsc);
@ -1538,7 +1547,7 @@ eeread(Ctlr *ctlr, int adr)
while ((csr32r(ctlr, Eerd) & EEdone) == 0 && timeout--) while ((csr32r(ctlr, Eerd) & EEdone) == 0 && timeout--)
microdelay(5); microdelay(5);
if (timeout < 0) { if (timeout < 0) {
print("%s: eeread timeout\n", cname(ctlr)); print("#l%d: %s: eeread timeout\n", ctlr->edev->ctlrno, cname(ctlr));
return -1; return -1;
} }
return (csr32r(ctlr, Eerd) >> 16) & 0xffff; return (csr32r(ctlr, Eerd) >> 16) & 0xffff;
@ -1589,7 +1598,7 @@ done:
while((f->reg[Fsts] & Fdone) == 0 && timeout--) while((f->reg[Fsts] & Fdone) == 0 && timeout--)
microdelay(5); microdelay(5);
if(timeout < 0){ if(timeout < 0){
print("%s: fread timeout\n", cname(c)); print("#l%d: %s: fread timeout\n", c->edev->ctlrno, cname(c));
return -1; return -1;
} }
if(f->reg[Fsts] & (Fcerr|Ael)) if(f->reg[Fsts] & (Fcerr|Ael))
@ -1626,7 +1635,7 @@ done:
while((f->reg32[Fsts/2] & Fdone) == 0 && timeout--) while((f->reg32[Fsts/2] & Fdone) == 0 && timeout--)
microdelay(5); microdelay(5);
if(timeout < 0){ if(timeout < 0){
print("%s: fread timeout\n", cname(c)); print("#l%d: %s: fread timeout\n", c->edev->ctlrno, cname(c));
return -1; return -1;
} }
if(f->reg32[Fsts/2] & (Fcerr|Ael)) if(f->reg32[Fsts/2] & (Fcerr|Ael))
@ -1777,7 +1786,7 @@ i82563reset(Ctlr *ctlr)
r = eeload(ctlr); r = eeload(ctlr);
if(r != 0 && r != 0xbaba){ if(r != 0 && r != 0xbaba){
print("%s: bad eeprom checksum - %#.4ux", cname(ctlr), r); print("#l%d: %s: bad eeprom checksum - %#.4ux", ctlr->edev->ctlrno, cname(ctlr), r);
if(flag & Fbadcsum) if(flag & Fbadcsum)
print("; ignored\n"); print("; ignored\n");
else { else {
@ -2101,12 +2110,12 @@ pnp(Ether *edev, int type)
for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){ for(ctlr = i82563ctlrhead; ; ctlr = ctlr->next){
if(ctlr == nil) if(ctlr == nil)
return -1; return -1;
if(ctlr->active) if(ctlr->edev != nil)
continue; continue;
if(type != -1 && ctlr->type != type) if(type != -1 && ctlr->type != type)
continue; continue;
if(edev->port == 0 || edev->port == ctlr->port){ if(edev->port == 0 || edev->port == ctlr->port){
ctlr->active = 1; ctlr->edev = edev;
memmove(ctlr->ra, edev->ea, Eaddrlen); memmove(ctlr->ra, edev->ea, Eaddrlen);
if(setup(ctlr) == 0) if(setup(ctlr) == 0)
break; break;

View file

@ -384,11 +384,13 @@ lproc(void *v)
; ;
for (;;) { for (;;) {
r = c->reg[Links]; r = c->reg[Links];
e->link = (r & Lnkup) != 0; if(r & Lnkup){
i = 0;
if(e->link){
i = 1 + ((r & Lnkspd) != 0); i = 1 + ((r & Lnkspd) != 0);
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
i = 0;
} }
c->speeds[i]++; c->speeds[i]++;
c->lim = 0; c->lim = 0;

View file

@ -333,15 +333,14 @@ checklink(Ether *edev)
ulong i; ulong i;
int mbps; int mbps;
mbps = 0;
ctlr = edev->ctlr; ctlr = edev->ctlr;
miir(ctlr, PhyStatus); /* dummy read necessary */ miir(ctlr, PhyStatus); /* dummy read necessary */
if(!(miir(ctlr, PhyStatus) & PhyLinkStatus)) { if(!(miir(ctlr, PhyStatus) & PhyLinkStatus)) {
edev->link = 0;
ctlr->duplex = 1; ctlr->duplex = 1;
print("bcm: no link\n"); ethersetlink(edev, 0);
goto out; goto out;
} }
edev->link = 1;
while((miir(ctlr, PhyStatus) & PhyAutoNegComplete) == 0); while((miir(ctlr, PhyStatus) & PhyAutoNegComplete) == 0);
i = miir(ctlr, PhyGbitStatus); i = miir(ctlr, PhyGbitStatus);
if(i & (Phy1000FD | Phy1000HD)) { if(i & (Phy1000FD | Phy1000HD)) {
@ -354,13 +353,12 @@ checklink(Ether *edev)
mbps = 10; mbps = 10;
ctlr->duplex = (i & Phy10FD) != 0; ctlr->duplex = (i & Phy10FD) != 0;
} else { } else {
edev->link = 0;
ctlr->duplex = 1; ctlr->duplex = 1;
print("bcm: link partner supports neither 10/100/1000 Mbps\n"); ethersetlink(edev, 0);
goto out; goto out;
} }
print("bcm: %d Mbps link, %s duplex\n", mbps, ctlr->duplex ? "full" : "half");
ethersetspeed(edev, mbps); ethersetspeed(edev, mbps);
ethersetlink(edev, 1);
out: out:
if(ctlr->duplex) csr32(ctlr, MACMode) &= ~MACHalfDuplex; if(ctlr->duplex) csr32(ctlr, MACMode) &= ~MACHalfDuplex;
else csr32(ctlr, MACMode) |= MACHalfDuplex; else csr32(ctlr, MACMode) |= MACHalfDuplex;

View file

@ -2118,6 +2118,8 @@ etherelnk3reset(Ether* ether)
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name); intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
ether->link = ether->mbps != 0;
return 0; return 0;
} }

View file

@ -583,17 +583,12 @@ ga620event(Ether *edev, int eci, int epi)
case 1: case 1:
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
break; break;
case 2:
print("#l%d: link down\n", edev->ctlrno);
break;
case 3: case 3:
/* it's 10 or 100 */ /* it's 10 or 100 */
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
break; break;
} }
if (code != 2) ethersetlink(edev, code != 2);
print("#l%d: %dMbps link up\n",
edev->ctlrno, edev->mbps);
break; break;
case 0x07: /* event error */ case 0x07: /* event error */
default: default:

View file

@ -1242,13 +1242,8 @@ checkstats(Ether *e, Ctlr *c, Stats *s)
return; return;
i = gbit32(s->linkstat); i = gbit32(s->linkstat);
if(c->linkstat != i){ if(c->linkstat != i)
e->link = i; ethersetlink(e, c->linkstat = i);
if(c->linkstat = i)
dprint("m10g: link up\n");
else
dprint("m10g: link down\n");
}
i = gbit32(s->nrdma); i = gbit32(s->nrdma);
if(i != c->nrdma){ if(i != c->nrdma){
dprint("m10g: rdma timeout %ld\n", i); dprint("m10g: rdma timeout %ld\n", i);

View file

@ -713,9 +713,8 @@ vgbeinterrupt(Ureg *, void* arg)
print("vgbe: irq: PHY interrupt\n"); print("vgbe: irq: PHY interrupt\n");
if(status & Isr_LinkStatus){ if(status & Isr_LinkStatus){
edev->link = (riob(ctlr, PhySts0) & PhySts_Link) ? 1 : 0; ethersetlink(edev, riob(ctlr, PhySts0) & PhySts_Link);
vgbemiip(ctlr, 1); vgbemiip(ctlr, 1);
print("vgbe: irq: link status change\n");
} }
if(status & Isr_RxNoDesc) if(status & Isr_RxNoDesc)
print("vgbe: irq: ran out of Rx descriptors\n"); print("vgbe: irq: ran out of Rx descriptors\n");

View file

@ -346,11 +346,13 @@ lproc(void *v)
; ;
for (;;) { for (;;) {
r = c->reg[Links]; r = c->reg[Links];
e->link = (r & Lnkup) != 0; if(r & Lnkup){
i = 0;
if(e->link){
i = 1 + ((r & Lnkspd) != 0); i = 1 + ((r & Lnkspd) != 0);
ethersetspeed(e, speedtab[i]); ethersetspeed(e, speedtab[i]);
ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
i = 0;
} }
c->speeds[i]++; c->speeds[i]++;
c->lim = 0; c->lim = 0;

View file

@ -1365,10 +1365,12 @@ link(Ether *e)
i = phyread(c, Phyint); i = phyread(c, Phyint);
s = phyread(c, Phylstat); s = phyread(c, Phylstat);
dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s); dprint("#l%d: yuk: link %.8ux %.8ux\n", e->ctlrno, i, s);
e->link = (s & Plink) != 0; if(s & Plink){
if(e->link)
ethersetspeed(e, (c->feat&Ffiber)? 1000: spdtab[(s & Physpd) >> 14]); 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); ethersetlink(e, 1);
} else {
ethersetlink(e, 0);
}
} }
static void static void

View file

@ -410,6 +410,7 @@ etherprobe(int cardno, int ctlrno, char *conf)
ether->irq = -1; ether->irq = -1;
ether->ctlrno = ctlrno; ether->ctlrno = ctlrno;
ether->mbps = 10; ether->mbps = 10;
ether->link = 0;
ether->minmtu = ETHERMINTU; ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU; ether->maxmtu = ETHERMAXTU;
@ -422,19 +423,15 @@ etherprobe(int cardno, int ctlrno, char *conf)
memmove(&ether->opt[0], &ether->opt[1], --ether->nopt*sizeof(ether->opt[0])); memmove(&ether->opt[0], &ether->opt[1], --ether->nopt*sizeof(ether->opt[0]));
} else if(isaconfig("ether", ctlrno, ether) == 0) } else if(isaconfig("ether", ctlrno, ether) == 0)
goto Nope; goto Nope;
for(cardno = 0; cards[cardno].type != nil; cardno++)
if(cistrcmp(cards[cardno].type, ether->type) == 0)
break;
if(cards[cardno].type == nil)
goto Nope;
for(i = 0; i < ether->nopt; i++){ for(i = 0; i < ether->nopt; i++){
if(strncmp(ether->opt[i], "ea=", 3) == 0){ if(strncmp(ether->opt[i], "ea=", 3) == 0){
if(parseether(ether->ea, &ether->opt[i][3])) if(parseether(ether->ea, &ether->opt[i][3]))
memset(ether->ea, 0, Eaddrlen); memset(ether->ea, 0, Eaddrlen);
} }
} }
for(cardno = 0; cards[cardno].type != nil; cardno++)
if(cistrcmp(cards[cardno].type, ether->type) == 0)
break;
} }
if(cardno >= MaxEther || cards[cardno].type == nil) if(cardno >= MaxEther || cards[cardno].type == nil)
goto Nope; goto Nope;
@ -471,12 +468,33 @@ ethersetspeed(Ether *ether, int mbps)
if(ether->mbps == mbps) if(ether->mbps == mbps)
return; return;
ether->mbps = mbps; ether->mbps = mbps;
if(mbps <= 0 || ether->oq == nil)
if(mbps <= 0 || ether->f == nil || ether->oq == nil)
return; return;
netifsetlimit(ether, etherqueuesize(ether)); netifsetlimit(ether, etherqueuesize(ether));
qsetlimit(ether->oq, ether->limit); qsetlimit(ether->oq, ether->limit);
} }
void
ethersetlink(Ether *ether, int link)
{
link = !!link;
if(!!ether->link == link)
return;
ether->link = link;
if(ether->f == nil)
return;
if(link)
print("#l%d: %s: link up: %dMbps\n",
ether->ctlrno, ether->type, ether->mbps);
else
print("#l%d: %s: link down\n",
ether->ctlrno, ether->type);
}
static void netconsole(int); static void netconsole(int);
static void static void

View file

@ -52,6 +52,7 @@ struct Ether {
}; };
extern void ethersetspeed(Ether*, int); extern void ethersetspeed(Ether*, int);
extern void ethersetlink(Ether*, int);
extern void etheriq(Ether*, Block*); extern void etheriq(Ether*, Block*);
extern void addethercard(char*, int(*)(Ether*)); extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int); extern ulong ethercrc(uchar*, int);

View file

@ -54,6 +54,7 @@ reset(Ether* ether)
{ {
if(ether->type==nil) if(ether->type==nil)
return -1; return -1;
ether->link = 0;
ether->mbps = 1000; ether->mbps = 1000;
ether->attach = attach; ether->attach = attach;
ether->multicast = multicast; ether->multicast = multicast;

View file

@ -780,7 +780,6 @@ reset(Ether* edev)
edev->multicast = multicast; edev->multicast = multicast;
edev->promiscuous = promiscuous; edev->promiscuous = promiscuous;
pcisetbme(ctlr->pcidev); pcisetbme(ctlr->pcidev);
intrenable(edev->irq, interrupt, edev, edev->tbdf, edev->name); intrenable(edev->irq, interrupt, edev, edev->tbdf, edev->name);

View file

@ -418,11 +418,13 @@ netifwstat(Netif *nif, Chan *c, uchar *db, int n)
error(Eperm); error(Eperm);
dir = smalloc(sizeof(Dir)+n); dir = smalloc(sizeof(Dir)+n);
m = convM2D(db, n, &dir[0], (char*)&dir[1]); if(waserror()){
if(m == 0){
free(dir); free(dir);
error(Eshortstat); nexterror();
} }
m = convM2D(db, n, &dir[0], (char*)&dir[1]);
if(m == 0)
error(Eshortstat);
if(!emptystr(dir[0].uid)){ if(!emptystr(dir[0].uid)){
strncpy(f->owner, dir[0].uid, KNAMELEN-1); strncpy(f->owner, dir[0].uid, KNAMELEN-1);
f->owner[KNAMELEN-1] = 0; f->owner[KNAMELEN-1] = 0;
@ -430,6 +432,7 @@ netifwstat(Netif *nif, Chan *c, uchar *db, int n)
if(dir[0].mode != ~0UL) if(dir[0].mode != ~0UL)
f->mode = dir[0].mode; f->mode = dir[0].mode;
free(dir); free(dir);
poperror();
return m; return m;
} }

View file

@ -815,9 +815,13 @@ Scan:
/* maintain access point */ /* maintain access point */
tmout = 0; tmout = 0;
while((wn = wifi->bss) != nil){ while((wn = wifi->bss) != nil){
ether->link = (wn->status == Sassoc) || (wn->status == Sblocked); if(wn->status == Sassoc || wn->status == Sblocked){
if(ether->link && (rate = wn->actrate) != nil) if((rate = wn->actrate) != nil)
ethersetspeed(ether, ((*rate & 0x7f)+3)/4); ethersetspeed(ether, ((*rate & 0x7f)+3)/4);
ethersetlink(ether, 1);
} else {
ethersetlink(ether, 0);
}
now = MACHP(0)->ticks; now = MACHP(0)->ticks;
if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 20 || goodbss(wifi, wn) == 0){ if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 20 || goodbss(wifi, wn) == 0){
wifideauth(wifi, wn); wifideauth(wifi, wn);

View file

@ -867,10 +867,11 @@ fccltimer(Ureg*, Timer *t)
return; return;
} }
if(phy->link == 0){ if(phy->link == 0){
print("link lost\n"); ethersetlink(ether, 0);
return; return;
} }
ethersetspeed(ether, phy->speed); ethersetspeed(ether, phy->speed);
ethersetlink(ether, 1);
if(phy->fd != ctlr->duplex) if(phy->fd != ctlr->duplex)
print("set duplex\n"); print("set duplex\n");

View file

@ -1280,24 +1280,22 @@ rtl8169link(Ether* edev)
ctlr = edev->ctlr; ctlr = edev->ctlr;
if(!((r = csr8r(ctlr, Phystatus)) & Linksts)){ if(!((r = csr8r(ctlr, Phystatus)) & Linksts)){
if (edev->link) { if(edev->link) {
edev->link = 0;
csr8w(ctlr, Cr, Re); csr8w(ctlr, Cr, Re);
iprint("#l%d: link down\n", edev->ctlrno); ethersetlink(edev, 0);
} }
return; return;
} }
if(edev->link == 0) {
edev->link = 1;
csr8w(ctlr, Cr, Te|Re);
iprint("#l%d: link up\n", edev->ctlrno);
}
if(r & Speed10) if(r & Speed10)
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
else if(r & Speed100) else if(r & Speed100)
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
else if(r & Speed1000) else if(r & Speed1000)
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
if(edev->link == 0) {
csr8w(ctlr, Cr, Te|Re);
ethersetlink(edev, 1);
}
} }
static void static void

View file

@ -141,7 +141,6 @@ ethproc(void *ved)
{ {
Ether *edev; Ether *edev;
Ctlr *c; Ctlr *c;
char *sp, *dpl;
u16int v; u16int v;
edev = ved; edev = ved;
@ -149,40 +148,32 @@ ethproc(void *ved)
mdwrite(c, MDCTRL, AUTONEG); mdwrite(c, MDCTRL, AUTONEG);
for(;;){ for(;;){
if((mdread(c, MDSTATUS) & LINK) == 0){ if((mdread(c, MDSTATUS) & LINK) == 0){
edev->link = 0; ethersetlink(edev, 0);
print("eth: no link\n");
while((mdread(c, MDSTATUS) & LINK) == 0) while((mdread(c, MDSTATUS) & LINK) == 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);
} }
v = mdread(c, MDPHYCTRL); v = mdread(c, MDPHYCTRL);
if((v & 0x40) != 0){ if((v & 0x40) != 0){
sp = "1000BASE-T";
while((mdread(c, MDGSTATUS) & RECVOK) != RECVOK) while((mdread(c, MDGSTATUS) & RECVOK) != RECVOK)
; ;
c->r[NET_CFG] |= GIGE_EN; c->r[NET_CFG] |= GIGE_EN;
slcr[GEM0_CLK_CTRL] = 1 << 20 | 8 << 8 | 1; slcr[GEM0_CLK_CTRL] = 1 << 20 | 8 << 8 | 1;
ethersetspeed(edev, 1000); ethersetspeed(edev, 1000);
}else if((v & 0x20) != 0){ }else if((v & 0x20) != 0){
sp = "100BASE-TX";
c->r[NET_CFG] = c->r[NET_CFG] & ~GIGE_EN | SPEED; c->r[NET_CFG] = c->r[NET_CFG] & ~GIGE_EN | SPEED;
slcr[GEM0_CLK_CTRL] = 5 << 20 | 8 << 8 | 1; slcr[GEM0_CLK_CTRL] = 5 << 20 | 8 << 8 | 1;
ethersetspeed(edev, 100); ethersetspeed(edev, 100);
}else if((v & 0x10) != 0){ }else if((v & 0x10) != 0){
sp = "10BASE-T";
c->r[NET_CFG] = c->r[NET_CFG] & ~(GIGE_EN | SPEED); c->r[NET_CFG] = c->r[NET_CFG] & ~(GIGE_EN | SPEED);
slcr[GEM0_CLK_CTRL] = 20 << 20 | 20 << 8 | 1; slcr[GEM0_CLK_CTRL] = 20 << 20 | 20 << 8 | 1;
ethersetspeed(edev, 10); ethersetspeed(edev, 10);
}else }
sp = "???";
if((v & 0x08) != 0){ if((v & 0x08) != 0){
dpl = "full";
c->r[NET_CFG] |= FDEN; c->r[NET_CFG] |= FDEN;
}else{ }else{
dpl = "half";
c->r[NET_CFG] &= ~FDEN; c->r[NET_CFG] &= ~FDEN;
} }
edev->link = 1; ethersetlink(edev, 1);
print("eth: %s %s duplex link\n", sp, dpl);
while((mdread(c, MDSTATUS) & LINK) != 0) while((mdread(c, MDSTATUS) & LINK) != 0)
tsleep(&up->sleep, return0, nil, Linkdelay); tsleep(&up->sleep, return0, nil, Linkdelay);
} }

View file

@ -27,13 +27,3 @@ HFILES=\
atomic.h atomic.h
</sys/src/cmd/mkone </sys/src/cmd/mkone
</sys/doc/fonts
%.ps: %.ms
{ echo $FONTS; cat $stem.ms } | pic | tbl | eqn | troff -ms | lp -dstdout > $target
%.pdf: %.ps
ps2pdf $stem.ps $stem.pdf
man.install: gefs.4.man gefs.8.man
cp gefs.4.man /sys/man/4/gefs
cp gefs.8.man /sys/man/8/gefs

View file

@ -56,6 +56,8 @@ enum
Link, Link,
Out, Out,
Err0, Err0,
Overflows,
Soverflows,
}; };
struct Machine struct Machine
@ -76,8 +78,8 @@ struct Machine
uvlong prevsysstat[10]; uvlong prevsysstat[10];
int nproc; int nproc;
int lgproc; int lgproc;
uvlong netetherstats[8]; uvlong netetherstats[9];
uvlong prevetherstats[8]; uvlong prevetherstats[9];
uvlong batterystats[2]; uvlong batterystats[2];
uvlong temp[10]; uvlong temp[10];
@ -114,6 +116,7 @@ enum Menu2
Methererr, Methererr,
Metherin, Metherin,
Metherout, Metherout,
Metherovf,
Mfault, Mfault,
Midle, Midle,
Minintr, Minintr,
@ -138,6 +141,7 @@ char *menu2str[Nmenu2+1] = {
"add ethererr", "add ethererr",
"add etherin ", "add etherin ",
"add etherout", "add etherout",
"add etherovf",
"add fault ", "add fault ",
"add idle ", "add idle ",
"add inintr ", "add inintr ",
@ -159,6 +163,7 @@ char *menu2str[Nmenu2+1] = {
void contextval(Machine*, uvlong*, uvlong*, int), void contextval(Machine*, uvlong*, uvlong*, int),
etherval(Machine*, uvlong*, uvlong*, int), etherval(Machine*, uvlong*, uvlong*, int),
ethererrval(Machine*, uvlong*, uvlong*, int), ethererrval(Machine*, uvlong*, uvlong*, int),
etherovfval(Machine*, uvlong*, uvlong*, int),
etherinval(Machine*, uvlong*, uvlong*, int), etherinval(Machine*, uvlong*, uvlong*, int),
etheroutval(Machine*, uvlong*, uvlong*, int), etheroutval(Machine*, uvlong*, uvlong*, int),
faultval(Machine*, uvlong*, uvlong*, int), faultval(Machine*, uvlong*, uvlong*, int),
@ -186,6 +191,7 @@ void (*newvaluefn[Nmenu2])(Machine*, uvlong*, uvlong*, int init) = {
ethererrval, ethererrval,
etherinval, etherinval,
etheroutval, etheroutval,
etherovfval,
faultval, faultval,
idleval, idleval,
inintrval, inintrval,
@ -796,7 +802,7 @@ needstat(int init)
int int
needether(int init) needether(int init)
{ {
return init | present[Mether] | present[Metherin] | present[Metherout] | present[Methererr]; return init | present[Mether] | present[Metherin] | present[Metherout] | present[Methererr] | present[Metherovf];
} }
int int
@ -1049,6 +1055,17 @@ ethererrval(Machine *m, uvlong *v, uvlong *vmax, int)
*vmax = (sleeptime/1000)*10; *vmax = (sleeptime/1000)*10;
} }
void
etherovfval(Machine *m, uvlong *v, uvlong *vmax, int)
{
int i;
*v = 0;
for(i=Overflows; i<=Soverflows; i++)
*v += m->netetherstats[i]-m->prevetherstats[i];
*vmax = (sleeptime/1000)*10;
}
void void
batteryval(Machine *m, uvlong *v, uvlong *vmax, int) batteryval(Machine *m, uvlong *v, uvlong *vmax, int)
{ {
@ -1413,6 +1430,7 @@ main(int argc, char *argv[])
addgraph(Metherin); addgraph(Metherin);
addgraph(Metherout); addgraph(Metherout);
addgraph(Methererr); addgraph(Methererr);
addgraph(Metherovf);
break; break;
case 'p': case 'p':
addgraph(Mtlbpurge); addgraph(Mtlbpurge);