diff options
author | dim <dim@FreeBSD.org> | 2010-11-25 18:36:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2010-11-25 18:36:44 +0000 |
commit | ce4ad7ab6156be02b01fdf19735a19a9c4d5a8ad (patch) | |
tree | 7fb434479af2e2b02b32b54ca0e7312065b0f6ed | |
parent | 71b42433f68a7680bcd07cef6c81b5a9bbe4e948 (diff) | |
parent | 835f186e056004cd67b3e5a1ee17f3ae1202646c (diff) | |
download | FreeBSD-src-ce4ad7ab6156be02b01fdf19735a19a9c4d5a8ad.zip FreeBSD-src-ce4ad7ab6156be02b01fdf19735a19a9c4d5a8ad.tar.gz |
Sync: merge r215709 through r215824 from ^/head.
93 files changed, 1412 insertions, 2829 deletions
diff --git a/bin/sh/arith_lex.l b/bin/sh/arith_lex.l index 1113d29..b4a04d3 100644 --- a/bin/sh/arith_lex.l +++ b/bin/sh/arith_lex.l @@ -53,7 +53,15 @@ int yylex(void); #undef YY_INPUT #define YY_INPUT(buf,result,max) \ - result = (*buf = *arith_buf++) ? 1 : YY_NULL; + do { \ + result = strnlen(arith_buf, max); \ + if (result == 0) \ + result = YY_NULL; \ + else { \ + memcpy(buf, arith_buf, result); \ + arith_buf += result; \ + } \ + } while (0); #define YY_NO_UNPUT #define YY_NO_INPUT %} diff --git a/bin/sh/cd.c b/bin/sh/cd.c index cec7496..068dfb7 100644 --- a/bin/sh/cd.c +++ b/bin/sh/cd.c @@ -192,8 +192,7 @@ cdlogical(char *dest) STPUTC('/', p); first = 0; component = q; - while (*q) - STPUTC(*q++, p); + STPUTS(q, p); if (equal(component, "..")) continue; STACKSTRNUL(p); @@ -219,10 +218,13 @@ cdphysical(char *dest) char *p; INTOFF; - if (chdir(dest) < 0 || (p = findcwd(NULL)) == NULL) { + if (chdir(dest) < 0) { INTON; return (-1); } + p = findcwd(NULL); + if (p == NULL) + out2fmt_flush("cd: warning: failed to get name of current directory\n"); updatepwd(p); INTON; return (0); @@ -270,10 +272,8 @@ findcwd(char *dir) scopy(dir, cdcomppath); STARTSTACKSTR(new); if (*dir != '/') { - p = curdir; - while (*p) - STPUTC(*p++, new); - if (p[-1] == '/') + STPUTS(curdir, new); + if (STTOPC(new) == '/') STUNPUTC(new); } while ((p = getcomponent()) != NULL) { @@ -281,8 +281,7 @@ findcwd(char *dir) while (new > stackblock() && (STUNPUTC(new), *new) != '/'); } else if (*p != '\0' && ! equal(p, ".")) { STPUTC('/', new); - while (*p) - STPUTC(*p++, new); + STPUTS(p, new); } } if (new == stackblock()) @@ -304,7 +303,7 @@ updatepwd(char *dir) if (prevdir) ckfree(prevdir); prevdir = curdir; - curdir = savestr(dir); + curdir = dir ? savestr(dir) : NULL; setvar("PWD", curdir, VEXPORT); setvar("OLDPWD", prevdir, VEXPORT); } diff --git a/bin/sh/eval.c b/bin/sh/eval.c index c306e73..5bae2f2 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -135,8 +135,7 @@ evalcmd(int argc, char **argv) STARTSTACKSTR(concat); ap = argv + 2; for (;;) { - while (*p) - STPUTC(*p++, concat); + STPUTS(p, concat); if ((p = *ap++) == NULL) break; STPUTC(' ', concat); diff --git a/bin/sh/expand.c b/bin/sh/expand.c index d251ed0..7a3b9d9 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -225,6 +225,7 @@ argstr(char *p, int flag) if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) p = exptilde(p, flag); for (;;) { + CHECKSTRSPACE(2, expdest); switch (c = *p++) { case '\0': case CTLENDVAR: @@ -235,16 +236,16 @@ argstr(char *p, int flag) if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=') break; if ((flag & EXP_FULL) != 0) - STPUTC(c, expdest); + USTPUTC(c, expdest); break; case CTLQUOTEEND: lit_quoted = 0; break; case CTLESC: if (quotes) - STPUTC(c, expdest); + USTPUTC(c, expdest); c = *p++; - STPUTC(c, expdest); + USTPUTC(c, expdest); if (split_lit && !lit_quoted) recordregion(expdest - stackblock() - (quotes ? 2 : 1), @@ -267,7 +268,7 @@ argstr(char *p, int flag) * sort of a hack - expand tildes in variable * assignments (after the first '=' and after ':'s). */ - STPUTC(c, expdest); + USTPUTC(c, expdest); if (split_lit && !lit_quoted) recordregion(expdest - stackblock() - 1, expdest - stackblock(), 0); @@ -279,7 +280,7 @@ argstr(char *p, int flag) } break; default: - STPUTC(c, expdest); + USTPUTC(c, expdest); if (split_lit && !lit_quoted) recordregion(expdest - stackblock() - 1, expdest - stackblock(), 0); @@ -902,8 +903,7 @@ varvalue(char *name, int quoted, int subtype, int flag) STPUTC(*p++, expdest); \ } \ } else \ - while (*p) \ - STPUTC(*p++, expdest); \ + STPUTS(p, expdest); \ } while (0) @@ -1573,8 +1573,7 @@ cvtnum(int num, char *buf) if (neg) *--p = '-'; - while (*p) - STPUTC(*p++, buf); + STPUTS(p, buf); return buf; } diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c index 3fc1782..26d46a8 100644 --- a/bin/sh/histedit.c +++ b/bin/sh/histedit.c @@ -411,8 +411,7 @@ fc_replace(const char *s, char *p, char *r) STARTSTACKSTR(dest); while (*s) { if (*s == *p && strncmp(s, p, plen) == 0) { - while (*r) - STPUTC(*r++, dest); + STPUTS(r, dest); s += plen; *p = '\0'; /* so no more matches */ } else diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c index 9158719..d00b4d9 100644 --- a/bin/sh/memalloc.c +++ b/bin/sh/memalloc.c @@ -340,3 +340,20 @@ ungrabstackstr(char *s, char *p) stacknxt = s; sstrnleft = stacknleft - (p - s); } + + +char * +stputbin(const char *data, int len, char *p) +{ + int i; + + for (i = 0; i < len; i++) + STPUTC(data[i], p); + return (p); +} + +char * +stputs(const char *data, char *p) +{ + return (stputbin(data, strlen(data), p)); +} diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h index 563927a..88848dd 100644 --- a/bin/sh/memalloc.h +++ b/bin/sh/memalloc.h @@ -61,6 +61,8 @@ void grabstackblock(int); char *growstackstr(void); char *makestrspace(void); void ungrabstackstr(char *, char *); +char *stputbin(const char *data, int len, char *p); +char *stputs(const char *data, char *p); @@ -82,3 +84,5 @@ void ungrabstackstr(char *, char *); #define STTOPC(p) p[-1] #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount)) #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) +#define STPUTBIN(s, len, p) p = stputbin((s), (len), p) +#define STPUTS(s, p) p = stputs((s), p) diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c index d9ac8a3..dc200b6 100644 --- a/bin/sh/miscbltin.c +++ b/bin/sh/miscbltin.c @@ -172,11 +172,12 @@ readcmd(int argc __unused, char **argv __unused) } if (c == '\0') continue; + CHECKSTRSPACE(1, p); if (backslash) { backslash = 0; startword = 0; if (c != '\n') - STPUTC(c, p); + USTPUTC(c, p); continue; } if (!rflag && c == '\\') { @@ -194,14 +195,14 @@ readcmd(int argc __unused, char **argv __unused) if (is_ifs == 1) { /* Ignore leading IFS whitespace */ if (saveall) - STPUTC(c, p); + USTPUTC(c, p); continue; } if (is_ifs == 2 && startword == 1) { /* Only one non-whitespace IFS per word */ startword = 2; if (saveall) - STPUTC(c, p); + USTPUTC(c, p); continue; } } @@ -212,7 +213,7 @@ readcmd(int argc __unused, char **argv __unused) if (saveall) /* Not just a spare terminator */ saveall++; - STPUTC(c, p); + USTPUTC(c, p); continue; } @@ -222,7 +223,7 @@ readcmd(int argc __unused, char **argv __unused) if (ap[1] == NULL) { /* Last variable needs all IFS chars */ saveall++; - STPUTC(c, p); + USTPUTC(c, p); continue; } diff --git a/bin/sh/parser.c b/bin/sh/parser.c index 01907e8..2687003 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -1017,6 +1017,7 @@ parsebackq(char *out, struct nodelist **pbqlist, setprompt(2); needprompt = 0; } + CHECKSTRSPACE(2, oout); switch (c = pgetc()) { case '`': goto done; @@ -1031,14 +1032,14 @@ parsebackq(char *out, struct nodelist **pbqlist, /* * If eating a newline, avoid putting * the newline into the new character - * stream (via the STPUTC after the + * stream (via the USTPUTC after the * switch). */ continue; } if (c != '\\' && c != '`' && c != '$' && (!dblquote || c != '"')) - STPUTC('\\', oout); + USTPUTC('\\', oout); break; case '\n': @@ -1054,10 +1055,10 @@ parsebackq(char *out, struct nodelist **pbqlist, default: break; } - STPUTC(c, oout); + USTPUTC(c, oout); } done: - STPUTC('\0', oout); + USTPUTC('\0', oout); olen = oout - stackblock(); INTOFF; ostr = ckmalloc(olen); @@ -1444,7 +1445,6 @@ parsesub: { char *p; static const char types[] = "}-+?="; int bracketed_name = 0; /* used to handle ${[0-9]*} variables */ - int i; int linno; int length; @@ -1498,8 +1498,7 @@ parsesub: { linno -= funclinno - 1; snprintf(buf, sizeof(buf), "%d", linno); STADJUST(-6, out); - for (i = 0; buf[i] != '\0'; i++) - STPUTC(buf[i], out); + STPUTS(buf, out); flags |= VSLINENO; } } else if (is_digit(c)) { diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 7109086..e542f9b 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -58,6 +58,8 @@ rc_conf_files="/etc/rc.conf /etc/rc.conf.local" # ZFS support zfs_enable="NO" # Set to YES to automatically mount ZFS file systems +gptboot_enable="YES" # GPT boot success/failure reporting. + # Experimental - test before enabling gbde_autoattach_all="NO" # YES automatically mounts gbde devices from fstab gbde_devices="NO" # Devices to automatically attach (list, or AUTO) diff --git a/etc/rc.d/gptboot b/etc/rc.d/gptboot index ace94b8..abfcaa1 100755 --- a/etc/rc.d/gptboot +++ b/etc/rc.d/gptboot @@ -34,6 +34,7 @@ . /etc/rc.subr name="gptboot" +rcvar=`set_rcvar` start_cmd="gptboot_report" gptboot_report() diff --git a/etc/rc.d/mountcritlocal b/etc/rc.d/mountcritlocal index acd269e..06bf464 100755 --- a/etc/rc.d/mountcritlocal +++ b/etc/rc.d/mountcritlocal @@ -5,13 +5,13 @@ # PROVIDE: mountcritlocal # REQUIRE: root hostid_save mdconfig -# KEYWORD: nojail +# KEYWORD: nojail shutdown . /etc/rc.subr name="mountcritlocal" start_cmd="mountcritlocal_start" -stop_cmd=":" +stop_cmd=sync mountcritlocal_start() { diff --git a/share/man/man4/bge.4 b/share/man/man4/bge.4 index 086045f..cf0d84a 100644 --- a/share/man/man4/bge.4 +++ b/share/man/man4/bge.4 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 7, 2010 +.Dd November 23, 2010 .Dt BGE 4 .Os .Sh NAME @@ -144,27 +144,6 @@ Force full duplex operation. Force half duplex operation. .El .Pp -The -.Nm -driver also supports one special link option for 1000baseTX cards: -.Bl -tag -width ".Cm link0" -.It Cm link0 -With 1000baseTX cards, establishing a link between two ports requires -that one port be configured as a master and the other a slave. -With autonegotiation, -the master/slave settings will be chosen automatically. -However when manually selecting the link state, it is necessary to -force one side of the link to be a master and the other a slave. -The -.Nm -driver configures the ports as slaves by default. -Setting the -.Cm link0 -flag with -.Xr ifconfig 8 -will set a port as a master instead. -.El -.Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE diff --git a/share/man/man4/msk.4 b/share/man/man4/msk.4 index 7ea12dd..fe32a68 100644 --- a/share/man/man4/msk.4 +++ b/share/man/man4/msk.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 30, 2010 +.Dd November 23, 2010 .Dt MSK 4 .Os .Sh NAME @@ -125,27 +125,6 @@ Force full duplex operation. Force half duplex operation. .El .Pp -The -.Nm -driver also supports one special link option for 1000baseTX cards: -.Bl -tag -width ".Cm link0" -.It Cm link0 -With 1000baseTX cards, establishing a link between two ports requires -that one port is configured as master and the other one as slave. -With autonegotiation, -the master/slave settings will be chosen automatically. -However when manually selecting the link state, it is necessary to -force one side of the link to be a master and the other a slave. -The -.Nm -driver configures the ports as slaves by default. -Setting the -.Cm link0 -flag with -.Xr ifconfig 8 -will set a port as a master instead. -.El -.Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE diff --git a/share/man/man4/nge.4 b/share/man/man4/nge.4 index 7c69247..ec02052 100644 --- a/share/man/man4/nge.4 +++ b/share/man/man4/nge.4 @@ -31,7 +31,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 21, 2009 +.Dd November 23, 2010 .Dt NGE 4 .Os .Sh NAME @@ -131,27 +131,6 @@ Force full duplex operation. Force half duplex operation. .El .Pp -The -.Nm -driver also supports one special link option for 1000baseTX cards: -.Bl -tag -width link0 -.It Cm link0 -With 1000baseTX cards, establishing a link between two ports requires -that one port be configured as a master and the other a slave. -With autonegotiation, -the master/slave settings will be chosen automatically. -However when manually selecting the link state, it is necessary to -force one side of the link to be a master and the other a slave. -The -.Nm -driver configures the ports as slaves by default. -Setting the -.Cm link0 -flag with -.Xr ifconfig 8 -will set a port as a master instead. -.El -.Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE diff --git a/share/man/man4/sk.4 b/share/man/man4/sk.4 index 88a4286..71e30c9 100644 --- a/share/man/man4/sk.4 +++ b/share/man/man4/sk.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 23, 2009 +.Dd November 23, 2010 .Dt SK 4 .Os .Sh NAME @@ -132,27 +132,6 @@ Force full duplex operation Force half duplex operation. .El .Pp -The -.Nm -driver also supports one special link option for 1000baseTX cards: -.Bl -tag -width xxxxxxxxxxxxxxxxxxxx -.It link0 -With 1000baseTX cards, establishing a link between two ports requires -that one port is configured as master and the other one as slave. -With autonegotiation, -the master/slave settings will be chosen automatically. -However when manually selecting the link state, it is necessary to -force one side of the link to be a master and the other a slave. -The -.Nm -driver configures the ports as slaves by default. -Setting the -.Ar link0 -flag with -.Xr ifconfig 8 -will set a port as a master instead. -.El -.Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE diff --git a/share/man/man4/stge.4 b/share/man/man4/stge.4 index d9c75ef..bfcaab0 100644 --- a/share/man/man4/stge.4 +++ b/share/man/man4/stge.4 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 25, 2006 +.Dd November 23, 2010 .Dt STGE 4 .Os .Sh NAME @@ -129,27 +129,6 @@ Force full duplex operation. Force half duplex operation. .El .Pp -The -.Nm -driver also supports one special link option for 1000baseTX cards: -.Bl -tag -width ".Cm link0" -.It Cm link0 -With 1000baseTX cards, establishing a link between two ports requires -that one port is configured as master and the other one as slave. -With autonegotiation, -the master/slave settings will be chosen automatically. -However when manually selecting the link state, it is necessary to -force one side of the link to be a master and the other a slave. -The -.Nm -driver configures the ports as slaves by default. -Setting the -.Cm link0 -flag with -.Xr ifconfig 8 -will set a port as a master instead. -.El -.Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE diff --git a/share/man/man4/vge.4 b/share/man/man4/vge.4 index f6ce47c..ae0206a 100644 --- a/share/man/man4/vge.4 +++ b/share/man/man4/vge.4 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 18, 2009 +.Dd November 23, 2010 .Dt VGE 4 .Os .Sh NAME @@ -137,27 +137,6 @@ Force full duplex operation. Force half duplex operation. .El .Pp -The -.Nm -driver also supports one special link option for 1000baseTX cards: -.Bl -tag -width ".Cm link0" -.It Cm link0 -With 1000baseTX cards, establishing a link between two ports requires -that one port be configured as a master and the other a slave. -With autonegotiation, -the master/slave settings will be chosen automatically. -However when manually selecting the link state, it is necessary to -force one side of the link to be a master and the other a slave. -The -.Nm -driver configures the ports as slaves by default. -Setting the -.Cm link0 -flag with -.Xr ifconfig 8 -will set a port as a master instead. -.El -.Pp For more information on configuring this device, see .Xr ifconfig 8 . .Sh HARDWARE diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 2a4ff49..990222f 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 13, 2010 +.Dd November 24, 2010 .Dt RC.CONF 5 .Os .Sh NAME @@ -1575,6 +1575,17 @@ If set to .Pa /etc/rc.d/zfs will attempt to automatically mount ZFS file systems and initialize ZFS volumes (ZVOLs). +.It Va gptboot_enable +.Pq Vt bool +If set to +.Dq Li YES , +.Pa /etc/rc.d/gptboot +will log if the system successfully (or not) booted from a GPT partition, +which had the +.Ar bootonce +attribute set using +.Xr gpart 8 +utility. .It Va gbde_autoattach_all .Pq Vt bool If set to diff --git a/share/man/man9/vrele.9 b/share/man/man9/vrele.9 index 0b9b736..d29ca5b 100644 --- a/share/man/man9/vrele.9 +++ b/share/man/man9/vrele.9 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 17, 2010 +.Dd November 20, 2010 .Dt VRELE 9 .Os .Sh NAME @@ -74,10 +74,6 @@ with less overhead. The .Fn vunref function takes a locked vnode as argument, and returns with the vnode locked. -Nonetheless, the -.Fn vunref -might drop the vnode lock during the operation, so caller should not expect -that non-doomed vnode is still non-doomed after the function returned. .Pp Any code in the system which signified its use of a vnode by usecount should call one of the listed function to decrement use counter. diff --git a/share/misc/bsd-family-tree b/share/misc/bsd-family-tree index edbd689..9e20ad2 100644 --- a/share/misc/bsd-family-tree +++ b/share/misc/bsd-family-tree @@ -228,20 +228,20 @@ FreeBSD 5.2 | | | | | FreeBSD 7.1 | | | | | | | | | DragonFly 2.2.0 | FreeBSD 7.2 | NetBSD 5.0 OpenBSD 4.5 | - | \ | | | | - | | | | | DragonFly 2.4.0 - | | | | OpenBSD 4.6 | - | | | | | | - *--FreeBSD | | | | | - | 8.0 | | | | | - | | FreeBSD | | | | - | | 7.3 | | | DragonFly 2.6.0 - | | | | OpenBSD 4.7 | - | FreeBSD | | | | - | 8.1 | | | | - | | | | | DragonFly 2.8.0 - | | | | OpenBSD 4.8 | - | V | | | | + | \ | | | | | + | | | | | | DragonFly 2.4.0 + | | | | | OpenBSD 4.6 | + | | | | | | | + *--FreeBSD | | | | | | + | 8.0 | | | | | | + | | FreeBSD | | | | | + | | 7.3 | | | | DragonFly 2.6.0 + | | | | | OpenBSD 4.7 | + | FreeBSD | | | | | + | 8.1 | | | | | + | | | | | | DragonFly 2.8.0 + | | | | | OpenBSD 4.8 | + | V | | NetBSD 5.1 | | | | | | | FreeBSD 9 -current | NetBSD -current OpenBSD -current | | | | | | @@ -523,6 +523,7 @@ OpenBSD 4.7 2010-05-19 [OBD] FreeBSD 8.1 2010-07-24 [FBD] DragonFly 2.8.0 2010-10-30 [DFB] OpenBSD 4.8 2010-11-01 [OBD] +NetBSD 5.1 2010-11-19 [NBD] Bibliography ------------------------ diff --git a/sys/amd64/acpica/acpi_switch.S b/sys/amd64/acpica/acpi_switch.S index fbe4097..45bad1f 100644 --- a/sys/amd64/acpica/acpi_switch.S +++ b/sys/amd64/acpica/acpi_switch.S @@ -76,12 +76,6 @@ ENTRY(acpi_restorecpu) movl WAKEUP_CTX(efer), %eax wrmsr - /* Restore PAT. */ - movl $MSR_PAT, %ecx - movl WAKEUP_CTX(pat), %eax - movl 4 + WAKEUP_CTX(pat), %edx - wrmsr - /* Restore fast syscall stuff. */ movl $MSR_STAR, %ecx movl WAKEUP_CTX(star), %eax diff --git a/sys/amd64/acpica/acpi_wakecode.S b/sys/amd64/acpica/acpi_wakecode.S index e131c97..49d14f5 100644 --- a/sys/amd64/acpica/acpi_wakecode.S +++ b/sys/amd64/acpica/acpi_wakecode.S @@ -274,8 +274,6 @@ wakeup_gdt: ALIGN_DATA wakeup_efer: .quad 0 -wakeup_pat: - .quad 0 wakeup_star: .quad 0 wakeup_lstar: diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c index c25d802..57341c9 100644 --- a/sys/amd64/acpica/acpi_wakeup.c +++ b/sys/amd64/acpica/acpi_wakeup.c @@ -278,6 +278,7 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) for (;;) ia32_pause(); } else { + pmap_init_pat(); PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); #ifdef SMP @@ -372,7 +373,6 @@ acpi_install_wakeup_handler(struct acpi_softc *sc) WAKECODE_FIXUP(wakeup_ctx, vm_offset_t, WAKECODE_VADDR(sc) + wakeup_ctx); WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER)); - WAKECODE_FIXUP(wakeup_pat, uint64_t, rdmsr(MSR_PAT)); WAKECODE_FIXUP(wakeup_star, uint64_t, rdmsr(MSR_STAR)); WAKECODE_FIXUP(wakeup_lstar, uint64_t, rdmsr(MSR_LSTAR)); WAKECODE_FIXUP(wakeup_cstar, uint64_t, rdmsr(MSR_CSTAR)); diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index 952a70b..3ad0ef7 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -276,7 +276,7 @@ load_dr: do_tss: movq %rdx,PCPU(TSSP) movq %rdx,%rcx movq PCPU(TSS),%rax - movw %rcx,2(%rax) + movw %cx,2(%rax) shrq $16,%rcx movb %cl,4(%rax) shrq $8,%rcx diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 07380ff..2e85d5f 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -1410,6 +1410,7 @@ cpususpend_handler(void) wbinvd(); atomic_set_int(&stopped_cpus, cpumask); } else { + pmap_init_pat(); PCPU_SET(switchtime, 0); PCPU_SET(switchticks, ticks); } diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index c89affd..3794967 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -183,8 +183,7 @@ pt_entry_t pg_nx; SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); static int pat_works = 1; -TUNABLE_INT("vm.pmap.pat_works", &pat_works); -SYSCTL_INT(_vm_pmap, OID_AUTO, pat_works, CTLFLAG_RDTUN, &pat_works, 1, +SYSCTL_INT(_vm_pmap, OID_AUTO, pat_works, CTLFLAG_RD, &pat_works, 1, "Is page attribute table fully functional?"); static int pg_ps_enabled = 1; diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h index 23d1149..49513d9 100644 --- a/sys/amd64/include/specialreg.h +++ b/sys/amd64/include/specialreg.h @@ -136,6 +136,15 @@ #define CPUID2_AESNI 0x02000000 /* + * Important bits in the Thermal and Power Management flags + * CPUID.6 EAX and ECX. + */ +#define CPUTPM1_SENSOR 0x00000001 +#define CPUTPM1_TURBO 0x00000002 +#define CPUTPM1_ARAT 0x00000004 +#define CPUTPM2_EFFREQ 0x00000001 + +/* * Important bits in the AMD extended cpuid flags */ #define AMDID_SYSCALL 0x00000800 diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index 35b3f0b..f0880b1 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -453,7 +453,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) } result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size); if (result < 0 || (size_t)result != shdr[i].sh_size) { - printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped!"); + printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! (%ju != %ju)", (uintmax_t)result, + (uintmax_t)shdr[i].sh_size); lastaddr = ssym; ssym = 0; goto nosyms; diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 8da3833..326cf03 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -2365,7 +2365,8 @@ freebsd32_nmount(struct thread *td, * Filter out MNT_ROOTFS. We do not want clients of nmount() in * userspace to set this flag, but we must filter it out if we want * MNT_UPDATE on the root file system to work. - * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try(). + * MNT_ROOTFS should only be set by the kernel when mounting its + * root file system. */ uap->flags &= ~MNT_ROOTFS; diff --git a/sys/compat/ia32/ia32_signal.h b/sys/compat/ia32/ia32_signal.h index 717ae74..757e384 100644 --- a/sys/compat/ia32/ia32_signal.h +++ b/sys/compat/ia32/ia32_signal.h @@ -29,6 +29,9 @@ * $FreeBSD$ */ +#ifndef _COMPAT_IA32_IA32_SIGNAL_H +#define _COMPAT_IA32_IA32_SIGNAL_H + struct ia32_mcontext { u_int32_t mc_onstack; /* XXX - sigcontext compat. */ u_int32_t mc_gs; /* machine state (struct trapframe) */ @@ -188,3 +191,5 @@ extern int sz_freebsd4_ia32_sigcode; extern void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *); extern void ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack); + +#endif diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h index d91bfde..f1cc6ed 100644 --- a/sys/compat/ia32/ia32_util.h +++ b/sys/compat/ia32/ia32_util.h @@ -28,6 +28,9 @@ * $FreeBSD$ */ +#ifndef _COMPAT_IA32_IA32_UTIL_H +#define _COMPAT_IA32_IA32_UTIL_H + #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> @@ -51,3 +54,5 @@ struct syscall_args; int ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa); void ia32_set_syscall_retval(struct thread *, int); + +#endif diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h index 769f93c..84c2a7f 100644 --- a/sys/compat/ndis/ntoskrnl_var.h +++ b/sys/compat/ndis/ntoskrnl_var.h @@ -1282,6 +1282,7 @@ typedef struct driver_object driver_object; #define STATUS_PENDING 0x00000103 #define STATUS_FAILURE 0xC0000001 #define STATUS_NOT_IMPLEMENTED 0xC0000002 +#define STATUS_ACCESS_VIOLATION 0xC0000005 #define STATUS_INVALID_PARAMETER 0xC000000D #define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 #define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index a2905c2..a5caa88 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -254,6 +254,7 @@ static uint8_t void *, void *); static void NdisGetCurrentSystemTime(uint64_t *); static void NdisGetSystemUpTime(uint32_t *); +static uint32_t NdisGetVersion(void); static void NdisInitializeString(unicode_string *, char *); static void NdisInitAnsiString(ansi_string *, char *); static void NdisInitUnicodeString(unicode_string *, uint16_t *); @@ -274,6 +275,7 @@ static void NdisMapFile(ndis_status *, void **, ndis_handle); static void NdisUnmapFile(ndis_handle); static void NdisCloseFile(ndis_handle); static uint8_t NdisSystemProcessorCount(void); +static void NdisGetCurrentProcessorCounts(uint32_t *, uint32_t *, uint32_t *); static void NdisMIndicateStatusComplete(ndis_handle); static void NdisMIndicateStatus(ndis_handle, ndis_status, void *, uint32_t); @@ -2067,6 +2069,12 @@ NdisInterlockedDecrement(addend) return (*addend); } +static uint32_t +NdisGetVersion(void) +{ + return (0x00050001); +} + static void NdisInitializeEvent(event) ndis_event *event; @@ -2950,6 +2958,20 @@ NdisSystemProcessorCount() return (mp_ncpus); } +static void +NdisGetCurrentProcessorCounts(idle_count, kernel_and_user, index) + uint32_t *idle_count; + uint32_t *kernel_and_user; + uint32_t *index; +{ + struct pcpu *pcpu; + + pcpu = pcpu_find(curthread->td_oncpu); + *index = pcpu->pc_cpuid; + *idle_count = pcpu->pc_cp_time[CP_IDLE]; + *kernel_and_user = pcpu->pc_cp_time[CP_INTR]; +} + typedef void (*ndis_statusdone_handler)(ndis_handle); typedef void (*ndis_status_handler)(ndis_handle, ndis_status, void *, uint32_t); @@ -3207,6 +3229,7 @@ image_patch_table ndis_functbl[] = { IMPORT_SFUNC(NdisMIndicateStatusComplete, 1), IMPORT_SFUNC(NdisMIndicateStatus, 4), IMPORT_SFUNC(NdisSystemProcessorCount, 0), + IMPORT_SFUNC(NdisGetCurrentProcessorCounts, 3), IMPORT_SFUNC(NdisUnchainBufferAtBack, 2), IMPORT_SFUNC(NdisGetFirstBufferFromPacket, 5), IMPORT_SFUNC(NdisGetFirstBufferFromPacketSafe, 6), @@ -3224,6 +3247,7 @@ image_patch_table ndis_functbl[] = { IMPORT_SFUNC(NdisFreeString, 1), IMPORT_SFUNC(NdisGetCurrentSystemTime, 1), IMPORT_SFUNC(NdisGetSystemUpTime, 1), + IMPORT_SFUNC(NdisGetVersion, 0), IMPORT_SFUNC(NdisMSynchronizeWithInterrupt, 3), IMPORT_SFUNC(NdisMAllocateSharedMemoryAsync, 4), IMPORT_SFUNC(NdisInterlockedInsertHeadList, 3), diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index 80b1d98..c575eb9 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -128,6 +128,7 @@ static kspin_lock ntoskrnl_intlock; static uint8_t RtlEqualUnicodeString(unicode_string *, unicode_string *, uint8_t); +static void RtlCopyString(ansi_string *, const ansi_string *); static void RtlCopyUnicodeString(unicode_string *, unicode_string *); static irp *IoBuildSynchronousFsdRequest(uint32_t, device_object *, @@ -180,7 +181,9 @@ static uint64_t _aullrem(uint64_t, uint64_t); static uint64_t _aullshr(uint64_t, uint8_t); static uint64_t _aullshl(uint64_t, uint8_t); static slist_entry *ntoskrnl_pushsl(slist_header *, slist_entry *); +static void InitializeSListHead(slist_header *); static slist_entry *ntoskrnl_popsl(slist_header *); +static void ExFreePoolWithTag(void *, uint32_t); static void ExInitializePagedLookasideList(paged_lookaside_list *, lookaside_alloc_func *, lookaside_free_func *, uint32_t, size_t, uint32_t, uint16_t); @@ -210,6 +213,10 @@ static void *MmMapLockedPagesSpecifyCache(mdl *, static void MmUnmapLockedPages(void *, mdl *); static device_t ntoskrnl_finddev(device_t, uint64_t, struct resource **); static void RtlZeroMemory(void *, size_t); +static void RtlSecureZeroMemory(void *, size_t); +static void RtlFillMemory(void *, size_t, uint8_t); +static void RtlMoveMemory(void *, const void *, size_t); +static ndis_status RtlCharToInteger(const char *, uint32_t, uint32_t *); static void RtlCopyMemory(void *, const void *, size_t); static size_t RtlCompareMemory(const void *, const void *, size_t); static ndis_status RtlUnicodeStringToInteger(unicode_string *, @@ -538,6 +545,20 @@ RtlEqualUnicodeString(unicode_string *str1, unicode_string *str2, } static void +RtlCopyString(dst, src) + ansi_string *dst; + const ansi_string *src; +{ + if (src != NULL && src->as_buf != NULL && dst->as_buf != NULL) { + dst->as_len = min(src->as_len, dst->as_maxlen); + memcpy(dst->as_buf, src->as_buf, dst->as_len); + if (dst->as_len < dst->as_maxlen) + dst->as_buf[dst->as_len] = 0; + } else + dst->as_len = 0; +} + +static void RtlCopyUnicodeString(dest, src) unicode_string *dest; unicode_string *src; @@ -650,6 +671,14 @@ ExAllocatePoolWithTag(pooltype, len, tag) return (buf); } +static void +ExFreePoolWithTag(buf, tag) + void *buf; + uint32_t tag; +{ + ExFreePool(buf); +} + void ExFreePool(buf) void *buf; @@ -2056,6 +2085,13 @@ ntoskrnl_pushsl(head, entry) return (oldhead); } +static void +InitializeSListHead(head) + slist_header *head; +{ + memset(head, 0, sizeof(*head)); +} + static slist_entry * ntoskrnl_popsl(head) slist_header *head; @@ -2725,6 +2761,59 @@ ntoskrnl_workitem_thread(arg) return; /* notreached */ } +static ndis_status +RtlCharToInteger(src, base, val) + const char *src; + uint32_t base; + uint32_t *val; +{ + int negative = 0; + uint32_t res; + + if (!src || !val) + return (STATUS_ACCESS_VIOLATION); + while (*src != '\0' && *src <= ' ') + src++; + if (*src == '+') + src++; + else if (*src == '-') { + src++; + negative = 1; + } + if (base == 0) { + base = 10; + if (*src == '0') { + src++; + if (*src == 'b') { + base = 2; + src++; + } else if (*src == 'o') { + base = 8; + src++; + } else if (*src == 'x') { + base = 16; + src++; + } + } + } else if (!(base == 2 || base == 8 || base == 10 || base == 16)) + return (STATUS_INVALID_PARAMETER); + + for (res = 0; *src; src++) { + int v; + if (isdigit(*src)) + v = *src - '0'; + else if (isxdigit(*src)) + v = tolower(*src) - 'a' + 10; + else + v = base; + if (v >= base) + return (STATUS_INVALID_PARAMETER); + res = res * base + v; + } + *val = negative ? -res : res; + return (STATUS_SUCCESS); +} + static void ntoskrnl_destroy_workitem_threads(void) { @@ -2905,6 +2994,32 @@ RtlZeroMemory(dst, len) } static void +RtlSecureZeroMemory(dst, len) + void *dst; + size_t len; +{ + memset(dst, 0, len); +} + +static void +RtlFillMemory(dst, len, c) + void *dst; + size_t len; + uint8_t c; +{ + memset(dst, c, len); +} + +static void +RtlMoveMemory(dst, src, len) + void *dst; + const void *src; + size_t len; +{ + memmove(dst, src, len); +} + +static void RtlCopyMemory(dst, src, len) void *dst; const void *src; @@ -2919,17 +3034,14 @@ RtlCompareMemory(s1, s2, len) const void *s2; size_t len; { - size_t i, total = 0; + size_t i; uint8_t *m1, *m2; m1 = __DECONST(char *, s1); m2 = __DECONST(char *, s2); - for (i = 0; i < len; i++) { - if (m1[i] == m2[i]) - total++; - } - return (total); + for (i = 0; i < len && m1[i] == m2[i]; i++); + return (i); } void @@ -4124,7 +4236,12 @@ dummy() image_patch_table ntoskrnl_functbl[] = { IMPORT_SFUNC(RtlZeroMemory, 2), + IMPORT_SFUNC(RtlSecureZeroMemory, 2), + IMPORT_SFUNC(RtlFillMemory, 3), + IMPORT_SFUNC(RtlMoveMemory, 3), + IMPORT_SFUNC(RtlCharToInteger, 3), IMPORT_SFUNC(RtlCopyMemory, 3), + IMPORT_SFUNC(RtlCopyString, 2), IMPORT_SFUNC(RtlCompareMemory, 3), IMPORT_SFUNC(RtlEqualUnicodeString, 3), IMPORT_SFUNC(RtlCopyUnicodeString, 2), @@ -4211,6 +4328,7 @@ image_patch_table ntoskrnl_functbl[] = { IMPORT_SFUNC(ExInitializeNPagedLookasideList, 7), IMPORT_SFUNC(ExDeleteNPagedLookasideList, 1), IMPORT_FFUNC(InterlockedPopEntrySList, 1), + IMPORT_FFUNC(InitializeSListHead, 1), IMPORT_FFUNC(InterlockedPushEntrySList, 2), IMPORT_SFUNC(ExQueryDepthSList, 1), IMPORT_FFUNC_MAP(ExpInterlockedPopEntrySList, @@ -4220,6 +4338,7 @@ image_patch_table ntoskrnl_functbl[] = { IMPORT_FFUNC(ExInterlockedPopEntrySList, 2), IMPORT_FFUNC(ExInterlockedPushEntrySList, 3), IMPORT_SFUNC(ExAllocatePoolWithTag, 3), + IMPORT_SFUNC(ExFreePoolWithTag, 2), IMPORT_SFUNC(ExFreePool, 1), #ifdef __i386__ IMPORT_FFUNC(KefAcquireSpinLockAtDpcLevel, 1), diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 6794f45..4b93d9b 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -858,7 +858,7 @@ ahci_ch_attach(device_t dev) ch->caps = ctlr->caps; ch->caps2 = ctlr->caps2; ch->quirks = ctlr->quirks; - ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1, + ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1; mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF); resource_int_value(device_get_name(dev), device_get_unit(dev), "pm_level", &ch->pm_level); diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c index e454fa1..0fe4fc5 100644 --- a/sys/dev/cas/if_cas.c +++ b/sys/dev/cas/if_cas.c @@ -346,7 +346,7 @@ cas_attach(struct cas_softc *sc) } error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK, - MII_PHY_ANY, MII_OFFSET_ANY, 0); + MII_PHY_ANY, MII_OFFSET_ANY, MIIF_DOPAUSE); } /* * Fall back on an internal PHY if no external PHY was found. @@ -366,7 +366,7 @@ cas_attach(struct cas_softc *sc) } error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK, - MII_PHY_ANY, MII_OFFSET_ANY, 0); + MII_PHY_ANY, MII_OFFSET_ANY, MIIF_DOPAUSE); } } else { /* @@ -388,7 +388,7 @@ cas_attach(struct cas_softc *sc) BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, cas_mediachange, cas_mediastatus, BMSR_DEFCAPMASK, - CAS_PHYAD_EXTERNAL, MII_OFFSET_ANY, 0); + CAS_PHYAD_EXTERNAL, MII_OFFSET_ANY, MIIF_DOPAUSE); } if (error != 0) { device_printf(sc->sc_dev, "attaching PHYs failed\n"); @@ -1093,8 +1093,7 @@ cas_init_locked(struct cas_softc *sc) /* Set the PAUSE thresholds. We use the maximum OFF threshold. */ CAS_WRITE_4(sc, CAS_RX_PTHRS, - ((111 * 64) << CAS_RX_PTHRS_XOFF_SHFT) | - ((15 * 64) << CAS_RX_PTHRS_XON_SHFT)); + (111 << CAS_RX_PTHRS_XOFF_SHFT) | (15 << CAS_RX_PTHRS_XON_SHFT)); /* RX blanking */ CAS_WRITE_4(sc, CAS_RX_BLANK, @@ -1339,7 +1338,7 @@ cas_init_regs(struct cas_softc *sc) CAS_WRITE_4(sc, CAS_MAC_PREAMBLE_LEN, 0x7); CAS_WRITE_4(sc, CAS_MAC_JAM_SIZE, 0x4); CAS_WRITE_4(sc, CAS_MAC_ATTEMPT_LIMIT, 0x10); - CAS_WRITE_4(sc, CAS_MAC_CTRL_TYPE, 0x8088); + CAS_WRITE_4(sc, CAS_MAC_CTRL_TYPE, 0x8808); /* random number seed */ CAS_WRITE_4(sc, CAS_MAC_RANDOM_SEED, @@ -1572,11 +1571,11 @@ cas_tint(struct cas_softc *sc) } #ifdef CAS_DEBUG - CTR4(KTR_CAS, "%s: CAS_TX_STATE_MACHINE %x CAS_TX_DESC_BASE %llx " + CTR5(KTR_CAS, "%s: CAS_TX_SM1 %x CAS_TX_SM2 %x CAS_TX_DESC_BASE %llx " "CAS_TX_COMP3 %x", - __func__, CAS_READ_4(sc, CAS_TX_STATE_MACHINE), - ((long long)CAS_READ_4(sc, CAS_TX_DESC_BASE_HI3) << 32) | - CAS_READ_4(sc, CAS_TX_DESC_BASE_LO3), + __func__, CAS_READ_4(sc, CAS_TX_SM1), CAS_READ_4(sc, CAS_TX_SM2), + ((long long)CAS_READ_4(sc, CAS_TX_DESC3_BASE_HI) << 32) | + CAS_READ_4(sc, CAS_TX_DESC3_BASE_LO), CAS_READ_4(sc, CAS_TX_COMP3)); #endif @@ -1638,7 +1637,7 @@ cas_rint(struct cas_softc *sc) rxhead = CAS_READ_4(sc, CAS_RX_COMP_HEAD); #ifdef CAS_DEBUG CTR4(KTR_CAS, "%s: sc->sc_rxcptr %d, sc->sc_rxdptr %d, head %d", - __func__, sc->rxcptr, sc->sc_rxdptr, rxhead); + __func__, sc->sc_rxcptr, sc->sc_rxdptr, rxhead); #endif skip = 0; CAS_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); @@ -1865,7 +1864,7 @@ cas_rint(struct cas_softc *sc) #ifdef CAS_DEBUG CTR4(KTR_CAS, "%s: done sc->sc_rxcptr %d, sc->sc_rxdptr %d, head %d", - __func__, sc->rxcptr, sc->sc_rxdptr, + __func__, sc->sc_rxcptr, sc->sc_rxdptr, CAS_READ_4(sc, CAS_RX_COMP_HEAD)); #endif } @@ -1988,7 +1987,7 @@ cas_intr_task(void *arg, int pending __unused) #ifdef CAS_DEBUG CTR4(KTR_CAS, "%s: %s: cplt %x, status %x", device_get_name(sc->sc_dev), __func__, - (status >> CAS_STATUS_TX_COMP3_SHIFT), (u_int)status); + (status >> CAS_STATUS_TX_COMP3_SHFT), (u_int)status); /* * PCS interrupts must be cleared, otherwise no traffic is passed! @@ -2100,15 +2099,15 @@ cas_watchdog(struct cas_softc *sc) #ifdef CAS_DEBUG CTR4(KTR_CAS, - "%s: CAS_RX_CONFIG %x CAS_MAC_RX_STATUS %x CAS_MAC_RX_CONFIG %x", - __func__, CAS_READ_4(sc, CAS_RX_CONFIG), + "%s: CAS_RX_CONF %x CAS_MAC_RX_STATUS %x CAS_MAC_RX_CONF %x", + __func__, CAS_READ_4(sc, CAS_RX_CONF), CAS_READ_4(sc, CAS_MAC_RX_STATUS), - CAS_READ_4(sc, CAS_MAC_RX_CONFIG)); + CAS_READ_4(sc, CAS_MAC_RX_CONF)); CTR4(KTR_CAS, - "%s: CAS_TX_CONFIG %x CAS_MAC_TX_STATUS %x CAS_MAC_TX_CONFIG %x", - __func__, CAS_READ_4(sc, CAS_TX_CONFIG), + "%s: CAS_TX_CONF %x CAS_MAC_TX_STATUS %x CAS_MAC_TX_CONF %x", + __func__, CAS_READ_4(sc, CAS_TX_CONF), CAS_READ_4(sc, CAS_MAC_TX_STATUS), - CAS_READ_4(sc, CAS_MAC_TX_CONFIG)); + CAS_READ_4(sc, CAS_MAC_TX_CONF)); #endif if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) @@ -2356,14 +2355,12 @@ cas_mii_statchg(device_t dev) v = CAS_READ_4(sc, CAS_MAC_CTRL_CONF) & ~(CAS_MAC_CTRL_CONF_TXP | CAS_MAC_CTRL_CONF_RXP); -#ifdef notyet if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) v |= CAS_MAC_CTRL_CONF_RXP; if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) v |= CAS_MAC_CTRL_CONF_TXP; -#endif CAS_WRITE_4(sc, CAS_MAC_CTRL_CONF, v); /* diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c index 3ae023c..b3a7ef9 100644 --- a/sys/dev/e1000/e1000_api.c +++ b/sys/dev/e1000/e1000_api.c @@ -312,6 +312,8 @@ s32 e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82580_SGMII: case E1000_DEV_ID_82580_COPPER_DUAL: case E1000_DEV_ID_82580_QUAD_FIBER: + case E1000_DEV_ID_DH89XXCC_SGMII: + case E1000_DEV_ID_DH89XXCC_SERDES: mac->type = e1000_82580; break; case E1000_DEV_ID_82576_VF: diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h index ca9c97d..e80e870 100644 --- a/sys/dev/e1000/e1000_hw.h +++ b/sys/dev/e1000/e1000_hw.h @@ -150,6 +150,8 @@ struct e1000_hw; #define E1000_DEV_ID_82580_SGMII 0x1511 #define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 #define E1000_DEV_ID_82580_QUAD_FIBER 0x1527 +#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436 +#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438 #define E1000_REVISION_0 0 #define E1000_REVISION_1 1 #define E1000_REVISION_2 2 diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index c41e144..6728a98 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -93,7 +93,7 @@ int em_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char em_driver_version[] = "7.1.7"; +char em_driver_version[] = "7.1.8"; /********************************************************************* * PCI Device ID Table @@ -272,6 +272,7 @@ static void em_get_wakeup(device_t); static void em_enable_wakeup(device_t); static int em_enable_phy_wakeup(struct adapter *); static void em_led_func(void *, int); +static void em_disable_aspm(struct adapter *); static int em_irq_fast(void *); @@ -1229,9 +1230,9 @@ em_init_locked(struct adapter *adapter) break; case e1000_ich9lan: case e1000_ich10lan: - case e1000_pchlan: pba = E1000_PBA_10K; break; + case e1000_pchlan: case e1000_pch2lan: pba = E1000_PBA_26K; break; @@ -2762,6 +2763,7 @@ em_reset(struct adapter *adapter) /* Issue a global reset */ e1000_reset_hw(hw); E1000_WRITE_REG(hw, E1000_WUC, 0); + em_disable_aspm(adapter); if (e1000_init_hw(hw) < 0) { device_printf(dev, "Hardware Initialization Failed\n"); @@ -4205,68 +4207,66 @@ em_rxeof(struct rx_ring *rxr, int count, int *done) len = le16toh(cur->length); eop = (status & E1000_RXD_STAT_EOP) != 0; - count--; - if (((cur->errors & E1000_RXD_ERR_FRAME_ERR_MASK) == 0) && - (rxr->discard == FALSE)) { + if ((rxr->discard == TRUE) || (cur->errors & + E1000_RXD_ERR_FRAME_ERR_MASK)) { + ifp->if_ierrors++; + ++rxr->rx_discarded; + if (!eop) /* Catch subsequent segs */ + rxr->discard = TRUE; + else + rxr->discard = FALSE; + em_rx_discard(rxr, i); + goto next_desc; + } - /* Assign correct length to the current fragment */ - mp = rxr->rx_buffers[i].m_head; - mp->m_len = len; + /* Assign correct length to the current fragment */ + mp = rxr->rx_buffers[i].m_head; + mp->m_len = len; - /* Trigger for refresh */ - rxr->rx_buffers[i].m_head = NULL; + /* Trigger for refresh */ + rxr->rx_buffers[i].m_head = NULL; - if (rxr->fmp == NULL) { - mp->m_pkthdr.len = len; - rxr->fmp = mp; /* Store the first mbuf */ - rxr->lmp = mp; - } else { - /* Chain mbuf's together */ - mp->m_flags &= ~M_PKTHDR; - rxr->lmp->m_next = mp; - rxr->lmp = rxr->lmp->m_next; - rxr->fmp->m_pkthdr.len += len; - } + /* First segment? */ + if (rxr->fmp == NULL) { + mp->m_pkthdr.len = len; + rxr->fmp = rxr->lmp = mp; + } else { + /* Chain mbuf's together */ + mp->m_flags &= ~M_PKTHDR; + rxr->lmp->m_next = mp; + rxr->lmp = mp; + rxr->fmp->m_pkthdr.len += len; + } - if (eop) { - rxr->fmp->m_pkthdr.rcvif = ifp; - ifp->if_ipackets++; - em_receive_checksum(cur, rxr->fmp); + if (eop) { + --count; + sendmp = rxr->fmp; + sendmp->m_pkthdr.rcvif = ifp; + ifp->if_ipackets++; + em_receive_checksum(cur, sendmp); #ifndef __NO_STRICT_ALIGNMENT - if (adapter->max_frame_size > - (MCLBYTES - ETHER_ALIGN) && - em_fixup_rx(rxr) != 0) - goto skip; + if (adapter->max_frame_size > + (MCLBYTES - ETHER_ALIGN) && + em_fixup_rx(rxr) != 0) + goto skip; #endif - if (status & E1000_RXD_STAT_VP) { - rxr->fmp->m_pkthdr.ether_vtag = - (le16toh(cur->special) & - E1000_RXD_SPC_VLAN_MASK); - rxr->fmp->m_flags |= M_VLANTAG; - } + if (status & E1000_RXD_STAT_VP) { + sendmp->m_pkthdr.ether_vtag = + (le16toh(cur->special) & + E1000_RXD_SPC_VLAN_MASK); + sendmp->m_flags |= M_VLANTAG; + } #ifdef EM_MULTIQUEUE - rxr->fmp->m_pkthdr.flowid = rxr->msix; - rxr->fmp->m_flags |= M_FLOWID; + sendmp->m_pkthdr.flowid = rxr->msix; + sendmp->m_flags |= M_FLOWID; #endif #ifndef __NO_STRICT_ALIGNMENT skip: #endif - sendmp = rxr->fmp; - rxr->fmp = NULL; - rxr->lmp = NULL; - } - } else { - ifp->if_ierrors++; - ++rxr->rx_discarded; - if (!eop) /* Catch subsequent segs */ - rxr->discard = TRUE; - else - rxr->discard = FALSE; - em_rx_discard(rxr, i); - sendmp = NULL; + rxr->fmp = rxr->lmp = NULL; } - +next_desc: /* Zero out the receive descriptors status. */ cur->status = 0; ++rxdone; /* cumulative for POLL */ @@ -4293,10 +4293,7 @@ skip: } /* Catch any remaining refresh work */ - if (processed != 0) { - em_refresh_mbufs(rxr, i); - processed = 0; - } + em_refresh_mbufs(rxr, i); rxr->next_to_check = i; if (done != NULL) @@ -4878,6 +4875,37 @@ em_led_func(void *arg, int onoff) EM_CORE_UNLOCK(adapter); } +/* +** Disable the L0S and L1 LINK states +*/ +static void +em_disable_aspm(struct adapter *adapter) +{ + int base, reg; + u16 link_cap,link_ctrl; + device_t dev = adapter->dev; + + switch (adapter->hw.mac.type) { + case e1000_82573: + case e1000_82574: + case e1000_82583: + break; + default: + return; + } + if (pci_find_extcap(dev, PCIY_EXPRESS, &base) != 0) + return; + reg = base + PCIR_EXPRESS_LINK_CAP; + link_cap = pci_read_config(dev, reg, 2); + if ((link_cap & PCIM_LINK_CAP_ASPM) == 0) + return; + reg = base + PCIR_EXPRESS_LINK_CTL; + link_ctrl = pci_read_config(dev, reg, 2); + link_ctrl &= 0xFFFC; /* turn off bit 1 and 2 */ + pci_write_config(dev, reg, link_ctrl, 2); + return; +} + /********************************************************************** * * Update the board statistics counters. diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index ee7ba71..14ccede 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -99,7 +99,7 @@ int igb_display_debug_stats = 0; /********************************************************************* * Driver version: *********************************************************************/ -char igb_driver_version[] = "version - 2.0.4"; +char igb_driver_version[] = "version - 2.0.7"; /********************************************************************* @@ -137,6 +137,10 @@ static igb_vendor_info_t igb_vendor_info_array[] = { 0x8086, E1000_DEV_ID_82580_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_82580_COPPER_DUAL, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_82580_QUAD_FIBER, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_DH89XXCC_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_DH89XXCC_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; @@ -307,11 +311,19 @@ static int igb_enable_msix = 1; TUNABLE_INT("hw.igb.enable_msix", &igb_enable_msix); /* - * Header split has seemed to be beneficial in - * many circumstances tested, however there have - * been some stability issues, so the default is - * off. - */ +** Tuneable Interrupt rate +*/ +static int igb_max_interrupt_rate = 8000; +TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate); + +/* +** Header split causes the packet header to +** be dma'd to a seperate mbuf from the payload. +** this can have memory alignment benefits. But +** another plus is that small packets often fit +** into the header and thus use no cluster. Its +** a very workload dependent type feature. +*/ static bool igb_header_split = FALSE; TUNABLE_INT("hw.igb.hdr_split", &igb_header_split); @@ -330,15 +342,6 @@ TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit); static int igb_fc_setting = e1000_fc_full; TUNABLE_INT("hw.igb.fc_setting", &igb_fc_setting); -/* -** Shadow VFTA table, this is needed because -** the real filter table gets cleared during -** a soft reset and the driver needs to be able -** to repopulate it. -*/ -static u32 igb_shadow_vfta[IGB_VFTA_SIZE]; - - /********************************************************************* * Device identification routine * @@ -818,7 +821,7 @@ igb_start_locked(struct tx_ring *txr, struct ifnet *ifp) /* Set watchdog on */ txr->watchdog_time = ticks; - txr->watchdog_check = TRUE; + txr->queue_status = IGB_QUEUE_WORKING; } } @@ -922,7 +925,7 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m) } if (enq > 0) { /* Set the watchdog */ - txr->watchdog_check = TRUE; + txr->queue_status = IGB_QUEUE_WORKING; txr->watchdog_time = ticks; } return (err); @@ -1049,6 +1052,11 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data) } break; case SIOCSIFMEDIA: + /* + ** As the speed/duplex settings are being + ** changed, we need toreset the PHY. + */ + adapter->hw.phy.reset_disable = FALSE; /* Check SOL/IDER usage */ IGB_CORE_LOCK(adapter); if (e1000_check_reset_block(&adapter->hw)) { @@ -1161,19 +1169,6 @@ igb_init_locked(struct adapter *adapter) E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN); - /* Use real VLAN Filter support? */ - if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { - if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) - /* Use real VLAN Filter support */ - igb_setup_vlan_hw_support(adapter); - else { - u32 ctrl; - ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); - ctrl |= E1000_CTRL_VME; - E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); - } - } - /* Set hardware offload abilities */ ifp->if_hwassist = 0; if (ifp->if_capenable & IFCAP_TXCSUM) { @@ -1201,10 +1196,12 @@ igb_init_locked(struct adapter *adapter) ** Figure out the desired mbuf pool ** for doing jumbo/packetsplit */ - if (ifp->if_mtu > ETHERMTU) + if (adapter->max_frame_size <= 2048) + adapter->rx_mbuf_sz = MCLBYTES; + else if (adapter->max_frame_size <= 4096) adapter->rx_mbuf_sz = MJUMPAGESIZE; else - adapter->rx_mbuf_sz = MCLBYTES; + adapter->rx_mbuf_sz = MJUM9BYTES; /* Prepare receive descriptors and buffers */ if (igb_setup_receive_structures(adapter)) { @@ -1213,6 +1210,19 @@ igb_init_locked(struct adapter *adapter) } igb_initialize_receive_units(adapter); + /* Use real VLAN Filter support? */ + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) { + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + /* Use real VLAN Filter support */ + igb_setup_vlan_hw_support(adapter); + else { + u32 ctrl; + ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL); + ctrl |= E1000_CTRL_VME; + E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl); + } + } + /* Don't lose promiscuous settings */ igb_set_promisc(adapter); @@ -1225,9 +1235,6 @@ igb_init_locked(struct adapter *adapter) if (adapter->msix > 1) /* Set up queue routing */ igb_configure_queues(adapter); - /* Set up VLAN tag offload and filter */ - igb_setup_vlan_hw_support(adapter); - /* this clears any pending interrupts */ E1000_READ_REG(&adapter->hw, E1000_ICR); #ifdef DEVICE_POLLING @@ -1627,11 +1634,6 @@ igb_media_change(struct ifnet *ifp) device_printf(adapter->dev, "Unsupported media type\n"); } - /* As the speed/duplex settings my have changed we need to - * reset the PHY. - */ - adapter->hw.phy.reset_disable = FALSE; - igb_init_locked(adapter); IGB_CORE_UNLOCK(adapter); @@ -1947,18 +1949,9 @@ igb_local_timer(void *arg) /* ** Watchdog: check for time since any descriptor was cleaned */ - for (int i = 0; i < adapter->num_queues; i++, txr++) { - IGB_TX_LOCK(txr); - if ((txr->watchdog_check == FALSE) || - (txr->tx_avail == adapter->num_tx_desc)) { - IGB_TX_UNLOCK(txr); - continue; - } - if ((ticks - txr->watchdog_time) > IGB_WATCHDOG) + for (int i = 0; i < adapter->num_queues; i++, txr++) + if (txr->queue_status == IGB_QUEUE_HUNG) goto timeout; - IGB_TX_UNLOCK(txr); - } - out: callout_reset(&adapter->timer, hz, igb_local_timer, adapter); return; @@ -1973,7 +1966,6 @@ timeout: txr->me, txr->tx_avail, txr->next_to_clean); adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; adapter->watchdog_events++; - IGB_TX_UNLOCK(txr); igb_init_locked(adapter); } @@ -2037,7 +2029,7 @@ igb_update_link_status(struct adapter *adapter) if_link_state_change(ifp, LINK_STATE_DOWN); /* Turn off watchdogs */ for (int i = 0; i < adapter->num_queues; i++, txr++) - txr->watchdog_check = FALSE; + txr->queue_status = IGB_QUEUE_IDLE; } } @@ -2069,7 +2061,7 @@ igb_stop(void *arg) /* Unarm watchdog timer. */ for (int i = 0; i < adapter->num_queues; i++, txr++) { IGB_TX_LOCK(txr); - txr->watchdog_check = FALSE; + txr->queue_status = IGB_QUEUE_IDLE; IGB_TX_UNLOCK(txr); } @@ -2280,8 +2272,7 @@ igb_configure_queues(struct adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct igb_queue *que; - u32 tmp, ivar = 0; - u32 newitr = IGB_DEFAULT_ITR; + u32 tmp, ivar = 0, newitr = 0; /* First turn on RSS capability */ if (adapter->hw.mac.type > e1000_82575) @@ -2398,6 +2389,9 @@ igb_configure_queues(struct adapter *adapter) } /* Set the starting interrupt rate */ + if (igb_max_interrupt_rate > 0) + newitr = (4000000 / igb_max_interrupt_rate) & 0x7FFC; + if (hw->mac.type == e1000_82575) newitr |= newitr << 16; else @@ -2509,6 +2503,8 @@ igb_setup_msix(struct adapter *adapter) /* Manual override */ if (igb_num_queues != 0) queues = igb_num_queues; + if (queues > 8) /* max queues */ + queues = 8; /* Can have max of 4 queues on 82575 */ if ((adapter->hw.mac.type == e1000_82575) && (queues > 4)) @@ -2636,7 +2632,7 @@ igb_reset(struct adapter *adapter) fc->send_xon = TRUE; /* Set Flow control, use the tunable location if sane */ - if ((igb_fc_setting >= 0) || (igb_fc_setting < 4)) + if ((igb_fc_setting >= 0) && (igb_fc_setting < 4)) fc->requested_mode = igb_fc_setting; else fc->requested_mode = e1000_fc_none; @@ -2728,10 +2724,11 @@ igb_setup_interface(device_t dev, struct adapter *adapter) ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM; ifp->if_capabilities |= IFCAP_TSO4; ifp->if_capabilities |= IFCAP_JUMBO_MTU; - if (igb_header_split) - ifp->if_capabilities |= IFCAP_LRO; - ifp->if_capenable = ifp->if_capabilities; + + /* Don't enable LRO by default */ + ifp->if_capabilities |= IFCAP_LRO; + #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif @@ -3172,7 +3169,7 @@ igb_initialize_transmit_units(struct adapter *adapter) E1000_READ_REG(hw, E1000_TDBAL(i)), E1000_READ_REG(hw, E1000_TDLEN(i))); - txr->watchdog_check = FALSE; + txr->queue_status = IGB_QUEUE_IDLE; txdctl |= IGB_TX_PTHRESH; txdctl |= IGB_TX_HTHRESH << 8; @@ -3184,14 +3181,14 @@ igb_initialize_transmit_units(struct adapter *adapter) if (adapter->hw.mac.type == e1000_vfadapt) return; + e1000_config_collision_dist(hw); + /* Program the Transmit Control Register */ tctl = E1000_READ_REG(hw, E1000_TCTL); tctl &= ~E1000_TCTL_CT; tctl |= (E1000_TCTL_PSP | E1000_TCTL_RTLC | E1000_TCTL_EN | (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT)); - e1000_config_collision_dist(hw); - /* This write will effectively turn on the transmit unit. */ E1000_WRITE_REG(hw, E1000_TCTL, tctl); } @@ -3500,16 +3497,19 @@ static bool igb_txeof(struct tx_ring *txr) { struct adapter *adapter = txr->adapter; - int first, last, done; + int first, last, done, processed; struct igb_tx_buffer *tx_buffer; struct e1000_tx_desc *tx_desc, *eop_desc; struct ifnet *ifp = adapter->ifp; IGB_TX_LOCK_ASSERT(txr); - if (txr->tx_avail == adapter->num_tx_desc) + if (txr->tx_avail == adapter->num_tx_desc) { + txr->queue_status = IGB_QUEUE_IDLE; return FALSE; + } + processed = 0; first = txr->next_to_clean; tx_desc = &txr->tx_base[first]; tx_buffer = &txr->tx_buffers[first]; @@ -3536,6 +3536,7 @@ igb_txeof(struct tx_ring *txr) tx_desc->lower.data = 0; tx_desc->buffer_addr = 0; ++txr->tx_avail; + ++processed; if (tx_buffer->m_head) { txr->bytes += @@ -3575,6 +3576,15 @@ igb_txeof(struct tx_ring *txr) txr->next_to_clean = first; + /* + ** Watchdog calculation, we know there's + ** work outstanding or the first return + ** would have been taken, so none processed + ** for too long indicates a hang. + */ + if ((!processed) && ((ticks - txr->watchdog_time) > IGB_WATCHDOG)) + txr->queue_status = IGB_QUEUE_HUNG; + /* * If we have enough room, clear IFF_DRV_OACTIVE * to tell the stack that it is OK to send packets. @@ -3583,7 +3593,7 @@ igb_txeof(struct tx_ring *txr) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* All clean, turn off the watchdog */ if (txr->tx_avail == adapter->num_tx_desc) { - txr->watchdog_check = FALSE; + txr->queue_status = IGB_QUEUE_IDLE; return (FALSE); } } @@ -3615,51 +3625,59 @@ igb_refresh_mbufs(struct rx_ring *rxr, int limit) cleaned = -1; /* Signify no completions */ while (i != limit) { rxbuf = &rxr->rx_buffers[i]; - if ((rxbuf->m_head == NULL) && (rxr->hdr_split)) { + /* No hdr mbuf used with header split off */ + if (rxr->hdr_split == FALSE) + goto no_split; + if (rxbuf->m_head == NULL) { mh = m_gethdr(M_DONTWAIT, MT_DATA); if (mh == NULL) goto update; - mh->m_pkthdr.len = mh->m_len = MHLEN; - mh->m_len = MHLEN; - mh->m_flags |= M_PKTHDR; - m_adj(mh, ETHER_ALIGN); - /* Get the memory mapping */ - error = bus_dmamap_load_mbuf_sg(rxr->htag, - rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - printf("GET BUF: dmamap load" - " failure - %d\n", error); - m_free(mh); - goto update; - } - rxbuf->m_head = mh; - bus_dmamap_sync(rxr->htag, rxbuf->hmap, - BUS_DMASYNC_PREREAD); - rxr->rx_base[i].read.hdr_addr = - htole64(hseg[0].ds_addr); - } + } else + mh = rxbuf->m_head; + mh->m_pkthdr.len = mh->m_len = MHLEN; + mh->m_len = MHLEN; + mh->m_flags |= M_PKTHDR; + /* Get the memory mapping */ + error = bus_dmamap_load_mbuf_sg(rxr->htag, + rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + printf("Refresh mbufs: hdr dmamap load" + " failure - %d\n", error); + m_free(mh); + rxbuf->m_head = NULL; + goto update; + } + rxbuf->m_head = mh; + bus_dmamap_sync(rxr->htag, rxbuf->hmap, + BUS_DMASYNC_PREREAD); + rxr->rx_base[i].read.hdr_addr = + htole64(hseg[0].ds_addr); +no_split: if (rxbuf->m_pack == NULL) { mp = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, adapter->rx_mbuf_sz); if (mp == NULL) goto update; - mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz; - /* Get the memory mapping */ - error = bus_dmamap_load_mbuf_sg(rxr->ptag, - rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - printf("GET BUF: dmamap load" - " failure - %d\n", error); - m_free(mp); - goto update; - } - rxbuf->m_pack = mp; - bus_dmamap_sync(rxr->ptag, rxbuf->pmap, - BUS_DMASYNC_PREREAD); - rxr->rx_base[i].read.pkt_addr = - htole64(pseg[0].ds_addr); + } else + mp = rxbuf->m_pack; + + mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz; + /* Get the memory mapping */ + error = bus_dmamap_load_mbuf_sg(rxr->ptag, + rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + printf("Refresh mbufs: payload dmamap load" + " failure - %d\n", error); + m_free(mp); + rxbuf->m_pack = NULL; + goto update; } + rxbuf->m_pack = mp; + bus_dmamap_sync(rxr->ptag, rxbuf->pmap, + BUS_DMASYNC_PREREAD); + rxr->rx_base[i].read.pkt_addr = + htole64(pseg[0].ds_addr); cleaned = i; /* Calculate next index */ @@ -3722,9 +3740,9 @@ igb_allocate_receive_buffers(struct rx_ring *rxr) BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - MJUMPAGESIZE, /* maxsize */ + MJUM9BYTES, /* maxsize */ 1, /* nsegments */ - MJUMPAGESIZE, /* maxsegsize */ + MJUM9BYTES, /* maxsegsize */ 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockfuncarg */ @@ -3826,7 +3844,7 @@ igb_setup_receive_ring(struct rx_ring *rxr) rxr->hdr_split = TRUE; /* Now replenish the ring mbufs */ - for (int j = 0; j != adapter->num_rx_desc; ++j) { + for (int j = 0; j < adapter->num_rx_desc; ++j) { struct mbuf *mh, *mp; rxbuf = &rxr->rx_buffers[j]; @@ -3897,8 +3915,8 @@ skip_head: ** are undesireable in similar setups. */ if (ifp->if_capenable & IFCAP_LRO) { - int err = tcp_lro_init(lro); - if (err) { + error = tcp_lro_init(lro); + if (error) { device_printf(dev, "LRO Initialization failed!\n"); goto fail; } @@ -3940,7 +3958,9 @@ fail: */ for (int j = 0; j > i; ++j) { rxr = &adapter->rx_rings[i]; + IGB_RX_LOCK(rxr); igb_free_receive_ring(rxr); + IGB_RX_UNLOCK(rxr); } return (ENOBUFS); @@ -3983,9 +4003,13 @@ igb_initialize_receive_units(struct adapter *adapter) */ if (ifp->if_mtu > ETHERMTU) { rctl |= E1000_RCTL_LPE; - srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT; - rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; - + if (adapter->rx_mbuf_sz == MJUMPAGESIZE) { + srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX; + } else if (adapter->rx_mbuf_sz > MJUMPAGESIZE) { + srrctl |= 8192 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX; + } /* Set maximum packet len */ psize = adapter->max_frame_size; /* are we on a vlan? */ @@ -4194,11 +4218,11 @@ igb_free_receive_buffers(struct rx_ring *rxr) static __inline void igb_rx_discard(struct rx_ring *rxr, int i) { - struct adapter *adapter = rxr->adapter; struct igb_rx_buf *rbuf; - struct mbuf *mh, *mp; rbuf = &rxr->rx_buffers[i]; + + /* Partially received? Free the chain */ if (rxr->fmp != NULL) { rxr->fmp->m_flags |= M_PKTHDR; m_freem(rxr->fmp); @@ -4206,19 +4230,23 @@ igb_rx_discard(struct rx_ring *rxr, int i) rxr->lmp = NULL; } - mh = rbuf->m_head; - mp = rbuf->m_pack; + /* + ** With advanced descriptors the writeback + ** clobbers the buffer addrs, so its easier + ** to just free the existing mbufs and take + ** the normal refresh path to get new buffers + ** and mapping. + */ + if (rbuf->m_head) { + m_free(rbuf->m_head); + rbuf->m_head = NULL; + } - /* Reuse loaded DMA map and just update mbuf chain */ - if (mh) { /* with no hdr split would be null */ - mh->m_len = MHLEN; - mh->m_flags |= M_PKTHDR; - mh->m_next = NULL; + if (rbuf->m_pack) { + m_free(rbuf->m_pack); + rbuf->m_pack = NULL; } - mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz; - mp->m_data = mp->m_ext.ext_buf; - mp->m_next = NULL; return; } @@ -4333,10 +4361,9 @@ igb_rxeof(struct igb_queue *que, int count, int *done) E1000_RXDADV_HDRBUFLEN_SHIFT; if (hlen > IGB_HDR_BUF) hlen = IGB_HDR_BUF; - /* Handle the header mbuf */ mh = rxr->rx_buffers[i].m_head; mh->m_len = hlen; - /* clear buf info for refresh */ + /* clear buf pointer for refresh */ rxbuf->m_head = NULL; /* ** Get the payload length, this @@ -4347,7 +4374,7 @@ igb_rxeof(struct igb_queue *que, int count, int *done) mp = rxr->rx_buffers[i].m_pack; mp->m_len = plen; mh->m_next = mp; - /* clear buf info for refresh */ + /* clear buf pointer */ rxbuf->m_pack = NULL; rxr->rx_split_packets++; } @@ -4368,7 +4395,7 @@ igb_rxeof(struct igb_queue *que, int count, int *done) /* Initial frame - setup */ if (rxr->fmp == NULL) { mh->m_pkthdr.len = mh->m_len; - /* Store the first mbuf */ + /* Save the head of the chain */ rxr->fmp = mh; rxr->lmp = mh; if (mp != NULL) { @@ -4533,12 +4560,15 @@ igb_register_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + IGB_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - igb_shadow_vfta[index] |= (1 << bit); + adapter->shadow_vfta[index] |= (1 << bit); ++adapter->num_vlans; /* Re-init to load the changes */ - igb_init(adapter); + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + igb_init_locked(adapter); + IGB_CORE_UNLOCK(adapter); } /* @@ -4557,12 +4587,15 @@ igb_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag) if ((vtag == 0) || (vtag > 4095)) /* Invalid */ return; + IGB_CORE_LOCK(adapter); index = (vtag >> 5) & 0x7F; bit = vtag & 0x1F; - igb_shadow_vfta[index] &= ~(1 << bit); + adapter->shadow_vfta[index] &= ~(1 << bit); --adapter->num_vlans; /* Re-init to load the changes */ - igb_init(adapter); + if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) + igb_init_locked(adapter); + IGB_CORE_UNLOCK(adapter); } static void @@ -4585,12 +4618,13 @@ igb_setup_vlan_hw_support(struct adapter *adapter) ** we need to repopulate it now. */ for (int i = 0; i < IGB_VFTA_SIZE; i++) - if (igb_shadow_vfta[i] != 0) { + if (adapter->shadow_vfta[i] != 0) { if (hw->mac.type == e1000_vfadapt) - e1000_vfta_set_vf(hw, igb_shadow_vfta[i], TRUE); + e1000_vfta_set_vf(hw, + adapter->shadow_vfta[i], TRUE); else E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, - i, igb_shadow_vfta[i]); + i, adapter->shadow_vfta[i]); } if (hw->mac.type == e1000_vfadapt) @@ -4994,6 +5028,28 @@ igb_sysctl_reg_handler(SYSCTL_HANDLER_ARGS) } /* +** Tuneable interrupt rate handler +*/ +static int +igb_sysctl_interrupt_rate_handler(SYSCTL_HANDLER_ARGS) +{ + struct igb_queue *que = ((struct igb_queue *)oidp->oid_arg1); + int error; + u32 reg, usec, rate; + + reg = E1000_READ_REG(&que->adapter->hw, E1000_EITR(que->msix)); + usec = ((reg & 0x7FFC) >> 2); + if (usec > 0) + rate = 1000000 / usec; + else + rate = 0; + error = sysctl_handle_int(oidp, &rate, 0, req); + if (error || !req->newptr) + return error; + return 0; +} + +/* * Add sysctl variables, one per statistic, to the system. */ static void @@ -5065,6 +5121,12 @@ igb_add_hw_stats(struct adapter *adapter) CTLFLAG_RD, NULL, "Queue Name"); queue_list = SYSCTL_CHILDREN(queue_node); + SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "interrupt_rate", + CTLFLAG_RD, &adapter->queues[i], + sizeof(&adapter->queues[i]), + igb_sysctl_interrupt_rate_handler, + "IU", "Interrupt Rate"); + SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "txd_head", CTLFLAG_RD, adapter, E1000_TDH(txr->me), igb_sysctl_reg_handler, "IU", diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h index 059a8b9..15fdceb 100644 --- a/sys/dev/e1000/if_igb.h +++ b/sys/dev/e1000/if_igb.h @@ -190,6 +190,9 @@ #define IGB_TX_BUFFER_SIZE ((uint32_t) 1514) #define IGB_FC_PAUSE_TIME 0x0680 #define IGB_EEPROM_APME 0x400; +#define IGB_QUEUE_IDLE 0 +#define IGB_QUEUE_WORKING 1 +#define IGB_QUEUE_HUNG 2 /* * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be @@ -237,7 +240,7 @@ /* Define the starting Interrupt rate per Queue */ #define IGB_INTS_PER_SEC 8000 -#define IGB_DEFAULT_ITR 1000000000/(IGB_INTS_PER_SEC * 256) +#define IGB_DEFAULT_ITR ((1000000/IGB_INTS_PER_SEC) << 2) #define IGB_LINK_ITR 2000 @@ -300,7 +303,7 @@ struct tx_ring { u32 bytes; u32 packets; - bool watchdog_check; + int queue_status; int watchdog_time; int tdt; int tdh; @@ -384,7 +387,15 @@ struct adapter { int wol; int has_manage; - /* Info about the board itself */ + /* + ** Shadow VFTA table, this is needed because + ** the real vlan filter table gets cleared during + ** a soft reset and the driver needs to be able + ** to repopulate it. + */ + u32 shadow_vfta[IGB_VFTA_SIZE]; + + /* Info about the interface */ u8 link_active; u16 link_speed; u16 link_duplex; diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index 5710ca7..2d522c3 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -107,11 +107,11 @@ static int tx_threshold = 64; /* * The configuration byte map has several undefined fields which * must be one or must be zero. Set up a template for these bits. - * The actual configuration is performed in fxp_init. + * The actual configuration is performed in fxp_init_body. * * See struct fxp_cb_config for the bit definitions. */ -static u_char fxp_cb_config_template[] = { +static const u_char const fxp_cb_config_template[] = { 0x0, 0x0, /* cb_status */ 0x0, 0x0, /* cb_command */ 0x0, 0x0, 0x0, 0x0, /* link_addr */ @@ -155,7 +155,7 @@ static u_char fxp_cb_config_template[] = { * particular variants, but we don't currently differentiate between * them. */ -static struct fxp_ident fxp_ident_table[] = { +static const struct fxp_ident const fxp_ident_table[] = { { 0x1029, -1, 0, "Intel 82559 PCI/CardBus Pro/100" }, { 0x1030, -1, 0, "Intel 82559 Pro/100 Ethernet" }, { 0x1031, -1, 3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" }, @@ -217,7 +217,7 @@ static int fxp_shutdown(device_t dev); static int fxp_suspend(device_t dev); static int fxp_resume(device_t dev); -static struct fxp_ident *fxp_find_ident(device_t dev); +static const struct fxp_ident *fxp_find_ident(device_t dev); static void fxp_intr(void *xsc); static void fxp_rxcsum(struct fxp_softc *sc, struct ifnet *ifp, struct mbuf *m, uint16_t status, int pos); @@ -366,12 +366,12 @@ fxp_dma_wait(struct fxp_softc *sc, volatile uint16_t *status, device_printf(sc->dev, "DMA timeout\n"); } -static struct fxp_ident * +static const struct fxp_ident * fxp_find_ident(device_t dev) { uint16_t devid; uint8_t revid; - struct fxp_ident *ident; + const struct fxp_ident *ident; if (pci_get_vendor(dev) == FXP_VENDORID_INTEL) { devid = pci_get_device(dev); @@ -392,7 +392,7 @@ fxp_find_ident(device_t dev) static int fxp_probe(device_t dev) { - struct fxp_ident *ident; + const struct fxp_ident *ident; ident = fxp_find_ident(dev); if (ident != NULL) { @@ -1614,21 +1614,7 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) /* * Advance the end of list forward. */ - -#ifdef __alpha__ - /* - * On platforms which can't access memory in 16-bit - * granularities, we must prevent the card from DMA'ing - * up the status while we update the command field. - * This could cause us to overwrite the completion status. - * XXX This is probably bogus and we're _not_ looking - * for atomicity here. - */ - atomic_clear_16(&sc->fxp_desc.tx_last->tx_cb->cb_command, - htole16(FXP_CB_COMMAND_S)); -#else sc->fxp_desc.tx_last->tx_cb->cb_command &= htole16(~FXP_CB_COMMAND_S); -#endif /*__alpha__*/ sc->fxp_desc.tx_last = txp; /* @@ -2985,13 +2971,13 @@ static uint32_t fxp_ucode_d102e[] = D102_E_RCVBUNDLE_UCODE; #define UCODE(x) x, sizeof(x)/sizeof(uint32_t) -struct ucode { +static const struct ucode { uint32_t revision; uint32_t *ucode; int length; u_short int_delay_offset; u_short bundle_max_offset; -} ucode_table[] = { +} const ucode_table[] = { { FXP_REV_82558_A4, UCODE(fxp_ucode_d101a), D101_CPUSAVER_DWORD, 0 }, { FXP_REV_82558_B0, UCODE(fxp_ucode_d101b0), D101_CPUSAVER_DWORD, 0 }, { FXP_REV_82559_A0, UCODE(fxp_ucode_d101ma), @@ -3010,7 +2996,7 @@ struct ucode { static void fxp_load_ucode(struct fxp_softc *sc) { - struct ucode *uc; + const struct ucode *uc; struct fxp_cb_ucode *cbp; int i; @@ -3177,11 +3163,13 @@ sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high) static int sysctl_hw_fxp_int_delay(SYSCTL_HANDLER_ARGS) { + return (sysctl_int_range(oidp, arg1, arg2, req, 300, 3000)); } static int sysctl_hw_fxp_bundle_max(SYSCTL_HANDLER_ARGS) { + return (sysctl_int_range(oidp, arg1, arg2, req, 1, 0xffff)); } diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h index de44636..ca7f7f5 100644 --- a/sys/dev/fxp/if_fxpvar.h +++ b/sys/dev/fxp/if_fxpvar.h @@ -146,7 +146,7 @@ struct fxp_ident { uint16_t devid; int16_t revid; /* -1 matches anything */ uint8_t ich; - char *name; + const char *name; }; struct fxp_hwstats { @@ -182,7 +182,7 @@ struct fxp_softc { struct resource *fxp_res[2]; /* I/O and IRQ resources */ struct resource_spec *fxp_spec; /* the resource spec we used */ void *ih; /* interrupt handler cookie */ - struct fxp_ident *ident; + const struct fxp_ident *ident; struct mtx sc_mtx; bus_dma_tag_t fxp_txmtag; /* bus DMA tag for Tx mbufs */ bus_dma_tag_t fxp_rxmtag; /* bus DMA tag for Rx mbufs */ diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c index 5c5750e..e8d9400 100644 --- a/sys/dev/gem/if_gem.c +++ b/sys/dev/gem/if_gem.c @@ -302,7 +302,7 @@ gem_attach(struct gem_softc *sc) } error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy, - MII_OFFSET_ANY, 0); + MII_OFFSET_ANY, MIIF_DOPAUSE); } /* @@ -330,7 +330,7 @@ gem_attach(struct gem_softc *sc) } error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy, - MII_OFFSET_ANY, 0); + MII_OFFSET_ANY, MIIF_DOPAUSE); } /* @@ -352,7 +352,7 @@ gem_attach(struct gem_softc *sc) sc->sc_flags |= GEM_SERDES; error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, - GEM_PHYAD_EXTERNAL, MII_OFFSET_ANY, 0); + GEM_PHYAD_EXTERNAL, MII_OFFSET_ANY, MIIF_DOPAUSE); } if (error != 0) { device_printf(sc->sc_dev, "attaching PHYs failed\n"); @@ -712,6 +712,9 @@ gem_reset_rx(struct gem_softc *sc) if (!GEM_BANK1_BITWAIT(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0)) device_printf(sc->sc_dev, "cannot disable RX DMA\n"); + /* Wait 5ms extra. */ + DELAY(5000); + /* Finally, reset the ERX. */ GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX); GEM_BANK2_BARRIER(sc, GEM_RESET, 4, @@ -784,6 +787,9 @@ gem_reset_tx(struct gem_softc *sc) if (!GEM_BANK1_BITWAIT(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0)) device_printf(sc->sc_dev, "cannot disable TX DMA\n"); + /* Wait 5ms extra. */ + DELAY(5000); + /* Finally, reset the ETX. */ GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_TX); GEM_BANK2_BARRIER(sc, GEM_RESET, 4, @@ -1239,7 +1245,7 @@ gem_init_regs(struct gem_softc *sc) GEM_BANK1_WRITE_4(sc, GEM_MAC_PREAMBLE_LEN, 0x7); GEM_BANK1_WRITE_4(sc, GEM_MAC_JAM_SIZE, 0x4); GEM_BANK1_WRITE_4(sc, GEM_MAC_ATTEMPT_LIMIT, 0x10); - GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8088); + GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8808); /* random number seed */ GEM_BANK1_WRITE_4(sc, GEM_MAC_RANDOM_SEED, @@ -2039,14 +2045,12 @@ gem_mii_statchg(device_t dev) v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG) & ~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE); -#ifdef notyet if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) v |= GEM_MAC_CC_RX_PAUSE; if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) v |= GEM_MAC_CC_TX_PAUSE; -#endif GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_CONFIG, v); if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 && diff --git a/sys/dev/mii/bmtphy.c b/sys/dev/mii/bmtphy.c index 63d1df1..6f53349 100644 --- a/sys/dev/mii/bmtphy.c +++ b/sys/dev/mii/bmtphy.c @@ -85,6 +85,11 @@ __FBSDID("$FreeBSD$"); static int bmtphy_probe(device_t); static int bmtphy_attach(device_t); +struct bmtphy_softc { + struct mii_softc mii_sc; + int mii_model; +}; + static device_method_t bmtphy_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bmtphy_probe), @@ -100,18 +105,21 @@ static devclass_t bmtphy_devclass; static driver_t bmtphy_driver = { "bmtphy", bmtphy_methods, - sizeof(struct mii_softc) + sizeof(struct bmtphy_softc) }; DRIVER_MODULE(bmtphy, miibus, bmtphy_driver, bmtphy_devclass, 0, 0); static int bmtphy_service(struct mii_softc *, struct mii_data *, int); static void bmtphy_status(struct mii_softc *); +static void bmtphy_reset(struct mii_softc *); static const struct mii_phydesc bmtphys_dp[] = { MII_PHY_DESC(BROADCOM, BCM4401), MII_PHY_DESC(BROADCOM, BCM5201), + MII_PHY_DESC(BROADCOM, BCM5214), MII_PHY_DESC(BROADCOM, BCM5221), + MII_PHY_DESC(BROADCOM, BCM5222), MII_PHY_END }; @@ -137,11 +145,13 @@ bmtphy_probe(device_t dev) static int bmtphy_attach(device_t dev) { - struct mii_softc *sc; - struct mii_attach_args *ma; - struct mii_data *mii; + struct bmtphy_softc *bsc; + struct mii_softc *sc; + struct mii_attach_args *ma; + struct mii_data *mii; - sc = device_get_softc(dev); + bsc = device_get_softc(dev); + sc = &bsc->mii_sc; ma = device_get_ivars(dev); sc->mii_dev = device_get_parent(dev); mii = ma->mii_data; @@ -153,7 +163,11 @@ bmtphy_attach(device_t dev) sc->mii_service = bmtphy_service; sc->mii_pdata = mii; - mii_phy_reset(sc); + sc->mii_flags |= MIIF_NOMANPAUSE; + + bsc->mii_model = MII_MODEL(ma->mii_id2); + + bmtphy_reset(sc); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; device_printf(dev, " "); @@ -194,16 +208,15 @@ bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) /* Callback if something changed. */ mii_phy_update(sc, cmd); - return (0); } static void bmtphy_status(struct mii_softc *sc) { - struct mii_data *mii; - struct ifmedia_entry *ife; - int bmsr, bmcr, aux_csr; + struct mii_data *mii; + struct ifmedia_entry *ife; + int bmsr, bmcr, aux_csr; mii = sc->mii_pdata; ife = mii->mii_media.ifm_cur; @@ -212,7 +225,6 @@ bmtphy_status(struct mii_softc *sc) mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); - aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; @@ -238,14 +250,45 @@ bmtphy_status(struct mii_softc *sc) return; } + aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR); if (aux_csr & AUX_CSR_SPEED) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (aux_csr & AUX_CSR_FDX) - mii->mii_media_active |= IFM_FDX; + mii->mii_media_active |= + IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else mii->mii_media_active = ife->ifm_media; } + +static void +bmtphy_reset(struct mii_softc *sc) +{ + struct bmtphy_softc *bsc; + u_int16_t data; + + bsc = (struct bmtphy_softc *)sc; + + mii_phy_reset(sc); + + if (bsc->mii_model == MII_MODEL_BROADCOM_BCM5221) { + /* Enable shadow register mode. */ + data = PHY_READ(sc, 0x1f); + PHY_WRITE(sc, 0x1f, data | 0x0080); + + /* Enable APD (Auto PowerDetect). */ + data = PHY_READ(sc, MII_BMTPHY_AUX2); + PHY_WRITE(sc, MII_BMTPHY_AUX2, data | 0x0020); + + /* Enable clocks across APD for Auto-MDIX functionality. */ + data = PHY_READ(sc, MII_BMTPHY_INTR); + PHY_WRITE(sc, MII_BMTPHY_INTR, data | 0x0004); + + /* Disable shadow register mode. */ + data = PHY_READ(sc, 0x1f); + PHY_WRITE(sc, 0x1f, data & ~0x0080); + } +} diff --git a/sys/dev/mii/gentbi.c b/sys/dev/mii/gentbi.c index f5d3a8b..a36f16a 100644 --- a/sys/dev/mii/gentbi.c +++ b/sys/dev/mii/gentbi.c @@ -172,6 +172,8 @@ gentbi_attach(device_t dev) sc->mii_service = gentbi_service; sc->mii_pdata = mii; + sc->mii_flags |= MIIF_NOMANPAUSE; + mii_phy_reset(sc); /* diff --git a/sys/dev/mii/inphy.c b/sys/dev/mii/inphy.c index 6830b5a..1293641 100644 --- a/sys/dev/mii/inphy.c +++ b/sys/dev/mii/inphy.c @@ -113,6 +113,8 @@ inphy_attach(device_t dev) sc->mii_service = inphy_service; sc->mii_pdata = mii; + sc->mii_flags |= MIIF_NOMANPAUSE; + ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), MII_MEDIA_100_TX, NULL); @@ -197,7 +199,8 @@ inphy_status(struct mii_softc *sc) else mii->mii_media_active |= IFM_10_T; if (scr & SCR_FDX) - mii->mii_media_active |= IFM_FDX; + mii->mii_media_active |= + IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c index 3df5dfa..8485691 100644 --- a/sys/dev/mii/mii.c +++ b/sys/dev/mii/mii.c @@ -137,7 +137,7 @@ miibus_attach(device_t dev) free(children, M_TEMP); } if (nchildren == 0) { - device_printf(dev, "cannot get children"); + device_printf(dev, "cannot get children\n"); return (ENXIO); } ivars = device_get_ivars(dev); @@ -311,12 +311,12 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, int bmsr, first, i, nchildren, offset, phymax, phymin, rv; if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY) { - printf("%s: phyloc and offloc specified", __func__); + printf("%s: phyloc and offloc specified\n", __func__); return (EINVAL); } if (offloc != MII_OFFSET_ANY && (offloc < 0 || offloc >= MII_NPHY)) { - printf("%s: ivalid offloc %d", __func__, offloc); + printf("%s: ivalid offloc %d\n", __func__, offloc); return (EINVAL); } @@ -325,7 +325,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, phymax = MII_NPHY - 1; } else { if (phyloc < 0 || phyloc >= MII_NPHY) { - printf("%s: ivalid phyloc %d", __func__, phyloc); + printf("%s: ivalid phyloc %d\n", __func__, phyloc); return (EINVAL); } phymin = phymax = phyloc; @@ -352,7 +352,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp, if (ivars->ifp != ifp || ivars->ifmedia_upd != ifmedia_upd || ivars->ifmedia_sts != ifmedia_sts || ivars->mii_flags != flags) { - printf("%s: non-matching invariant", __func__); + printf("%s: non-matching invariant\n", __func__); return (EINVAL); } /* diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs index ec0b846..24cd551 100644 --- a/sys/dev/mii/miidevs +++ b/sys/dev/mii/miidevs @@ -128,7 +128,9 @@ model ATHEROS F1_7 0x0007 Atheros F1 10/100/1000 PHY model BROADCOM 3C905B 0x0012 3c905B 10/100 internal PHY model BROADCOM 3C905C 0x0017 3c905C 10/100 internal PHY model BROADCOM BCM5201 0x0021 BCM5201 10/100baseTX PHY +model BROADCOM BCM5214 0x0028 BCM5214 Quad 10/100 PHY model BROADCOM BCM5221 0x001e BCM5221 10/100baseTX PHY +model BROADCOM BCM5222 0x0032 BCM5222 Dual 10/100 PHY model BROADCOM BCM4401 0x0036 BCM4401 10/100baseTX PHY model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY diff --git a/sys/dev/mii/nsgphy.c b/sys/dev/mii/nsgphy.c index 7cdee42..4177912 100644 --- a/sys/dev/mii/nsgphy.c +++ b/sys/dev/mii/nsgphy.c @@ -135,6 +135,8 @@ nsgphy_attach(device_t dev) sc->mii_service = nsgphy_service; sc->mii_pdata = mii; + sc->mii_flags |= MIIF_NOMANPAUSE; + mii_phy_reset(sc); /* diff --git a/sys/dev/mii/nsphyter.c b/sys/dev/mii/nsphyter.c index 5489504..c302181 100644 --- a/sys/dev/mii/nsphyter.c +++ b/sys/dev/mii/nsphyter.c @@ -143,6 +143,8 @@ nsphyter_attach(device_t dev) sc->mii_service = nsphyter_service; sc->mii_pdata = mii; + sc->mii_flags |= MIIF_NOMANPAUSE; + #if 1 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) @@ -242,12 +244,8 @@ nsphyter_status(struct mii_softc *sc) else mii->mii_media_active |= IFM_100_TX; if ((physts & PHYSTS_DUPLEX) != 0) -#ifdef notyet mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); -#else - mii->mii_media_active |= IFM_FDX; -#endif else mii->mii_media_active |= IFM_HDX; } else diff --git a/sys/dev/mii/ukphy.c b/sys/dev/mii/ukphy.c index 05b1b45..10842b7 100644 --- a/sys/dev/mii/ukphy.c +++ b/sys/dev/mii/ukphy.c @@ -136,6 +136,8 @@ ukphy_attach(device_t dev) sc->mii_service = ukphy_service; sc->mii_pdata = mii; + sc->mii_flags |= MIIF_NOMANPAUSE; + mii_phy_reset(sc); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 6069b6d..e3b6159 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -3022,8 +3022,35 @@ pci_resume(device_t dev) if (!device_is_attached(child)) pci_cfg_save(child, dinfo, 1); } + + /* + * Resume critical devices first, then everything else later. + */ + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + switch (pci_get_class(child)) { + case PCIC_DISPLAY: + case PCIC_MEMORY: + case PCIC_BRIDGE: + case PCIC_BASEPERIPH: + DEVICE_RESUME(child); + break; + } + } + for (i = 0; i < numdevs; i++) { + child = devlist[i]; + switch (pci_get_class(child)) { + case PCIC_DISPLAY: + case PCIC_MEMORY: + case PCIC_BRIDGE: + case PCIC_BASEPERIPH: + break; + default: + DEVICE_RESUME(child); + } + } free(devlist, M_TEMP); - return (bus_generic_resume(dev)); + return (0); } static void diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c index 7915818..199c132 100644 --- a/sys/dev/pci/pci_pci.c +++ b/sys/dev/pci/pci_pci.c @@ -860,7 +860,9 @@ host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, case 0x00171166: case 0x01011166: case 0x010f1014: + case 0x01101166: case 0x02011166: + case 0x02251166: case 0x03021014: *busnum = read_config(bus, slot, func, 0x44, 1); break; diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c index afc2118..d774d34 100644 --- a/sys/dev/usb/controller/usb_controller.c +++ b/sys/dev/usb/controller/usb_controller.c @@ -207,6 +207,8 @@ usb_detach(device_t dev) usb_proc_free(&bus->control_xfer_proc); + usbpf_detach(bus); + return (0); } @@ -435,6 +437,8 @@ usb_attach_sub(device_t dev, struct usb_bus *bus) usb_devclass_ptr = devclass_find("usbus"); mtx_unlock(&Giant); + usbpf_attach(bus); + /* Initialise USB process messages */ bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore; bus->explore_msg[0].bus = bus; @@ -548,8 +552,6 @@ usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, TAILQ_INIT(&bus->intr_q.head); - usbpf_attach(bus, &bus->uif); - #if USB_HAVE_BUSDMA usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags, dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX); @@ -597,8 +599,6 @@ usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb) usb_dma_tag_unsetup(bus->dma_parent_tag); #endif - usbpf_detach(bus); - mtx_destroy(&bus->bus_mtx); } diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c index 646063a..c19f1fd 100644 --- a/sys/dev/usb/serial/u3g.c +++ b/sys/dev/usb/serial/u3g.c @@ -281,12 +281,12 @@ static const struct usb_device_id u3g_devs[] = { U3G_DEV(HUAWEI, E143D, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E143E, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E143F, U3GINIT_HUAWEI), - U3G_DEV(HUAWEI, E14AC, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E180V, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E220, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E220BIS, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, MOBILE, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, E1752, U3GINIT_HUAWEISCSI), + U3G_DEV(HUAWEI, E1820, U3GINIT_HUAWEISCSI), U3G_DEV(HUAWEI, K3765, U3GINIT_HUAWEI), U3G_DEV(HUAWEI, K3765_INIT, U3GINIT_HUAWEISCSI), U3G_DEV(KYOCERA2, CDMA_MSM_K, 0), diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h index c5dfeff..1dd9d6a 100644 --- a/sys/dev/usb/usb_bus.h +++ b/sys/dev/usb/usb_bus.h @@ -86,7 +86,7 @@ struct usb_bus { struct usb_bus_methods *methods; /* filled by HC driver */ struct usb_device **devices; - struct usbpf_if *uif; /* USB Packet Filter */ + struct ifnet *ifp; /* only for USB Packet Filter */ usb_power_mask_t hw_power_state; /* see USB_HW_POWER_XXX */ usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX]; diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c index 3f5f204..c2925c2 100644 --- a/sys/dev/usb/usb_pf.c +++ b/sys/dev/usb/usb_pf.c @@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <sys/sockio.h> #include <net/if.h> +#include <net/if_types.h> +#include <net/bpf.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -55,1623 +57,39 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/usb_pf.h> #include <dev/usb/usb_transfer.h> -/* - * All usbpf implementations are extracted from bpf(9) APIs and it's - * specialized for USB packet filtering between the driver and the host - * controller. - */ - -MALLOC_DEFINE(M_USBPF, "USBPktFilter", "USB Packet Filter"); - -/* - * Rotate the packet buffers in descriptor ud. Move the store buffer into the - * hold slot, and the free buffer ino the store slot. Zero the length of the - * new store buffer. Descriptor lock should be held. - */ -#define USBPF_ROTATE_BUFFERS(ud) do { \ - (ud)->ud_hbuf = (ud)->ud_sbuf; \ - (ud)->ud_hlen = (ud)->ud_slen; \ - (ud)->ud_sbuf = (ud)->ud_fbuf; \ - (ud)->ud_slen = 0; \ - (ud)->ud_fbuf = NULL; \ - usbpf_bufheld(ud); \ -} while (0) - -#ifndef __i386__ -#define USBPF_ALIGN -#endif - -#ifndef USBPF_ALIGN -#define USBPF_EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p)) -#define USBPF_EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p)) -#else -#define USBPF_EXTRACT_SHORT(p) \ - ((u_int16_t) \ - ((u_int16_t)*((u_char *)p+0)<<8| \ - (u_int16_t)*((u_char *)p+1)<<0)) -#define USBPF_EXTRACT_LONG(p) \ - ((u_int32_t)*((u_char *)p+0)<<24| \ - (u_int32_t)*((u_char *)p+1)<<16| \ - (u_int32_t)*((u_char *)p+2)<<8| \ - (u_int32_t)*((u_char *)p+3)<<0) -#endif - -/* - * Number of scratch memory words (for USBPF_LD|USBPF_MEM and USBPF_ST). - */ -#define USBPF_MEMWORDS 16 - -/* Values for ud_state */ -#define USBPF_IDLE 0 /* no select in progress */ -#define USBPF_WAITING 1 /* waiting for read timeout in select */ -#define USBPF_TIMED_OUT 2 /* read timeout has expired in select */ - -#define PRIUSB 26 /* interruptible */ - -/* Frame directions */ -enum usbpf_direction { - USBPF_D_IN, /* See incoming frames */ - USBPF_D_INOUT, /* See incoming and outgoing frames */ - USBPF_D_OUT /* See outgoing frames */ -}; - -static void usbpf_append_bytes(struct usbpf_d *, caddr_t, u_int, void *, - u_int); -static void usbpf_attachd(struct usbpf_d *, struct usbpf_if *); -static void usbpf_detachd(struct usbpf_d *); -static int usbpf_canfreebuf(struct usbpf_d *); -static void usbpf_buf_reclaimed(struct usbpf_d *); -static int usbpf_canwritebuf(struct usbpf_d *); - -static d_open_t usbpf_open; -static d_read_t usbpf_read; -static d_write_t usbpf_write; -static d_ioctl_t usbpf_ioctl; -static d_poll_t usbpf_poll; -static d_kqfilter_t usbpf_kqfilter; - -static struct cdevsw usbpf_cdevsw = { - .d_version = D_VERSION, - .d_open = usbpf_open, - .d_read = usbpf_read, - .d_write = usbpf_write, - .d_ioctl = usbpf_ioctl, - .d_poll = usbpf_poll, - .d_name = "usbpf", - .d_kqfilter = usbpf_kqfilter, -}; - -static LIST_HEAD(, usbpf_if) usbpf_iflist; -static struct mtx usbpf_mtx; /* global lock */ -static int usbpf_uifd_cnt; - -static int usbpf_bufsize = 4096; -#define USBPF_MINBUFSIZE 32 -#define USBPF_MAXBUFSIZE 0x80000 -static int usbpf_maxbufsize = USBPF_MAXBUFSIZE; -#define USBPF_MAXINSNS 512 -static int usbpf_maxinsns = USBPF_MAXINSNS; - -static void -usbpf_buffer_init(struct usbpf_d *ud) -{ - - ud->ud_bufsize = usbpf_bufsize; -} - -/* - * Free USBPF kernel buffers on device close. - */ -static void -usbpf_buffer_free(struct usbpf_d *ud) -{ - - if (ud->ud_sbuf != NULL) - free(ud->ud_sbuf, M_USBPF); - if (ud->ud_hbuf != NULL) - free(ud->ud_hbuf, M_USBPF); - if (ud->ud_fbuf != NULL) - free(ud->ud_fbuf, M_USBPF); - -#ifdef INVARIANTS - ud->ud_sbuf = ud->ud_hbuf = ud->ud_fbuf = (caddr_t)~0; -#endif -} - -static void -usbpf_buffer_alloc(struct usbpf_d *ud) -{ - - KASSERT(ud->ud_fbuf == NULL, ("%s: ud_fbuf != NULL", __func__)); - KASSERT(ud->ud_sbuf == NULL, ("%s: ud_sbuf != NULL", __func__)); - KASSERT(ud->ud_hbuf == NULL, ("%s: ud_hbuf != NULL", __func__)); - - ud->ud_fbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK); - ud->ud_sbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK); - ud->ud_hbuf = NULL; - ud->ud_slen = 0; - ud->ud_hlen = 0; -} - -/* - * Copy buffer storage to user space in read(). - */ -static int -usbpf_buffer_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len, - struct uio *uio) -{ - - return (uiomove(buf, len, uio)); -} - -/* - * Simple data copy to the current kernel buffer. - */ -static void -usbpf_buffer_append_bytes(struct usbpf_d *ud, caddr_t buf, u_int offset, - void *src, u_int len) -{ - u_char *src_bytes; - - src_bytes = (u_char *)src; - bcopy(src_bytes, buf + offset, len); -} - -/* - * Allocate or resize buffers. - */ -static int -usbpf_buffer_ioctl_sblen(struct usbpf_d *ud, u_int *i) -{ - u_int size; - - USBPFD_LOCK(ud); - if (ud->ud_bif != NULL) { - USBPFD_UNLOCK(ud); - return (EINVAL); - } - size = *i; - if (size > usbpf_maxbufsize) - *i = size = usbpf_maxbufsize; - else if (size < USBPF_MINBUFSIZE) - *i = size = USBPF_MINBUFSIZE; - ud->ud_bufsize = size; - USBPFD_UNLOCK(ud); - return (0); -} - -static const u_short usbpf_code_map[] = { - 0x10ff, /* 0x00-0x0f: 1111111100001000 */ - 0x3070, /* 0x10-0x1f: 0000111000001100 */ - 0x3131, /* 0x20-0x2f: 1000110010001100 */ - 0x3031, /* 0x30-0x3f: 1000110000001100 */ - 0x3131, /* 0x40-0x4f: 1000110010001100 */ - 0x1011, /* 0x50-0x5f: 1000100000001000 */ - 0x1013, /* 0x60-0x6f: 1100100000001000 */ - 0x1010, /* 0x70-0x7f: 0000100000001000 */ - 0x0093, /* 0x80-0x8f: 1100100100000000 */ - 0x0000, /* 0x90-0x9f: 0000000000000000 */ - 0x0000, /* 0xa0-0xaf: 0000000000000000 */ - 0x0002, /* 0xb0-0xbf: 0100000000000000 */ - 0x0000, /* 0xc0-0xcf: 0000000000000000 */ - 0x0000, /* 0xd0-0xdf: 0000000000000000 */ - 0x0000, /* 0xe0-0xef: 0000000000000000 */ - 0x0000 /* 0xf0-0xff: 0000000000000000 */ -}; - -#define USBPF_VALIDATE_CODE(c) \ - ((c) <= 0xff && (usbpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0) - -/* - * Return true if the 'fcode' is a valid filter program. - * The constraints are that each jump be forward and to a valid - * code. The code must terminate with either an accept or reject. - * - * The kernel needs to be able to verify an application's filter code. - * Otherwise, a bogus program could easily crash the system. - */ -static int -usbpf_validate(const struct usbpf_insn *f, int len) -{ - register int i; - register const struct usbpf_insn *p; - - /* Do not accept negative length filter. */ - if (len < 0) - return (0); - - /* An empty filter means accept all. */ - if (len == 0) - return (1); - - for (i = 0; i < len; ++i) { - p = &f[i]; - /* - * Check that the code is valid. - */ - if (!USBPF_VALIDATE_CODE(p->code)) - return (0); - /* - * Check that that jumps are forward, and within - * the code block. - */ - if (USBPF_CLASS(p->code) == USBPF_JMP) { - register u_int offset; - - if (p->code == (USBPF_JMP|USBPF_JA)) - offset = p->k; - else - offset = p->jt > p->jf ? p->jt : p->jf; - if (offset >= (u_int)(len - i) - 1) - return (0); - continue; - } - /* - * Check that memory operations use valid addresses. - */ - if (p->code == USBPF_ST || p->code == USBPF_STX || - p->code == (USBPF_LD|USBPF_MEM) || - p->code == (USBPF_LDX|USBPF_MEM)) { - if (p->k >= USBPF_MEMWORDS) - return (0); - continue; - } - /* - * Check for constant division by 0. - */ - if (p->code == (USBPF_ALU|USBPF_DIV|USBPF_K) && p->k == 0) - return (0); - } - return (USBPF_CLASS(f[len - 1].code) == USBPF_RET); -} - -#ifdef _KERNEL -#define MINDEX(m, k) \ -{ \ - register int len = m->m_len; \ - \ - while (k >= len) { \ - k -= len; \ - m = m->m_next; \ - if (m == 0) \ - return (0); \ - len = m->m_len; \ - } \ -} - -static u_int16_t m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err); -static u_int32_t m_xword(struct mbuf *m, usbpf_u_int32 k, int *err); - -static u_int32_t -m_xword(struct mbuf *m, usbpf_u_int32 k, int *err) -{ - size_t len; - u_char *cp, *np; - struct mbuf *m0; - - len = m->m_len; - while (k >= len) { - k -= len; - m = m->m_next; - if (m == 0) - goto bad; - len = m->m_len; - } - cp = mtod(m, u_char *) + k; - if (len - k >= 4) { - *err = 0; - return (USBPF_EXTRACT_LONG(cp)); - } - m0 = m->m_next; - if (m0 == 0 || m0->m_len + len - k < 4) - goto bad; - *err = 0; - np = mtod(m0, u_char *); - switch (len - k) { - case 1: - return (((u_int32_t)cp[0] << 24) | - ((u_int32_t)np[0] << 16) | - ((u_int32_t)np[1] << 8) | - (u_int32_t)np[2]); - - case 2: - return (((u_int32_t)cp[0] << 24) | - ((u_int32_t)cp[1] << 16) | - ((u_int32_t)np[0] << 8) | - (u_int32_t)np[1]); - - default: - return (((u_int32_t)cp[0] << 24) | - ((u_int32_t)cp[1] << 16) | - ((u_int32_t)cp[2] << 8) | - (u_int32_t)np[0]); - } - bad: - *err = 1; - return (0); -} - -static u_int16_t -m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err) -{ - size_t len; - u_char *cp; - struct mbuf *m0; - - len = m->m_len; - while (k >= len) { - k -= len; - m = m->m_next; - if (m == 0) - goto bad; - len = m->m_len; - } - cp = mtod(m, u_char *) + k; - if (len - k >= 2) { - *err = 0; - return (USBPF_EXTRACT_SHORT(cp)); - } - m0 = m->m_next; - if (m0 == 0) - goto bad; - *err = 0; - return ((cp[0] << 8) | mtod(m0, u_char *)[0]); - bad: - *err = 1; - return (0); -} -#endif - -/* - * Execute the filter program starting at pc on the packet p - * wirelen is the length of the original packet - * buflen is the amount of data present - */ -static u_int -usbpf_filter(const struct usbpf_insn *pc, u_char *p, u_int wirelen, - u_int buflen) -{ - u_int32_t A = 0, X = 0; - usbpf_u_int32 k; - u_int32_t mem[USBPF_MEMWORDS]; - - /* - * XXX temporarily the filter system is disabled because currently it - * could not handle the some machine code properly that leads to - * kernel crash by invalid usage. - */ - return ((u_int)-1); - - if (pc == NULL) - /* - * No filter means accept all. - */ - return ((u_int)-1); - - --pc; - while (1) { - ++pc; - switch (pc->code) { - default: -#ifdef _KERNEL - return (0); -#else - abort(); -#endif - - case USBPF_RET|USBPF_K: - return ((u_int)pc->k); - - case USBPF_RET|USBPF_A: - return ((u_int)A); - - case USBPF_LD|USBPF_W|USBPF_ABS: - k = pc->k; - if (k > buflen || sizeof(int32_t) > buflen - k) { -#ifdef _KERNEL - int merr; - - if (buflen != 0) - return (0); - A = m_xword((struct mbuf *)p, k, &merr); - if (merr != 0) - return (0); - continue; -#else - return (0); -#endif - } -#ifdef USBPF_ALIGN - if (((intptr_t)(p + k) & 3) != 0) - A = USBPF_EXTRACT_LONG(&p[k]); - else -#endif - A = ntohl(*(int32_t *)(p + k)); - continue; - - case USBPF_LD|USBPF_H|USBPF_ABS: - k = pc->k; - if (k > buflen || sizeof(int16_t) > buflen - k) { -#ifdef _KERNEL - int merr; - - if (buflen != 0) - return (0); - A = m_xhalf((struct mbuf *)p, k, &merr); - continue; -#else - return (0); -#endif - } - A = USBPF_EXTRACT_SHORT(&p[k]); - continue; - - case USBPF_LD|USBPF_B|USBPF_ABS: - k = pc->k; - if (k >= buflen) { -#ifdef _KERNEL - struct mbuf *m; - - if (buflen != 0) - return (0); - m = (struct mbuf *)p; - MINDEX(m, k); - A = mtod(m, u_char *)[k]; - continue; -#else - return (0); -#endif - } - A = p[k]; - continue; - - case USBPF_LD|USBPF_W|USBPF_LEN: - A = wirelen; - continue; - - case USBPF_LDX|USBPF_W|USBPF_LEN: - X = wirelen; - continue; - - case USBPF_LD|USBPF_W|USBPF_IND: - k = X + pc->k; - if (pc->k > buflen || X > buflen - pc->k || - sizeof(int32_t) > buflen - k) { -#ifdef _KERNEL - int merr; - - if (buflen != 0) - return (0); - A = m_xword((struct mbuf *)p, k, &merr); - if (merr != 0) - return (0); - continue; -#else - return (0); -#endif - } -#ifdef USBPF_ALIGN - if (((intptr_t)(p + k) & 3) != 0) - A = USBPF_EXTRACT_LONG(&p[k]); - else -#endif - A = ntohl(*(int32_t *)(p + k)); - continue; - - case USBPF_LD|USBPF_H|USBPF_IND: - k = X + pc->k; - if (X > buflen || pc->k > buflen - X || - sizeof(int16_t) > buflen - k) { -#ifdef _KERNEL - int merr; - - if (buflen != 0) - return (0); - A = m_xhalf((struct mbuf *)p, k, &merr); - if (merr != 0) - return (0); - continue; -#else - return (0); -#endif - } - A = USBPF_EXTRACT_SHORT(&p[k]); - continue; - - case USBPF_LD|USBPF_B|USBPF_IND: - k = X + pc->k; - if (pc->k >= buflen || X >= buflen - pc->k) { -#ifdef _KERNEL - struct mbuf *m; - - if (buflen != 0) - return (0); - m = (struct mbuf *)p; - MINDEX(m, k); - A = mtod(m, u_char *)[k]; - continue; -#else - return (0); -#endif - } - A = p[k]; - continue; - - case USBPF_LDX|USBPF_MSH|USBPF_B: - k = pc->k; - if (k >= buflen) { -#ifdef _KERNEL - register struct mbuf *m; - - if (buflen != 0) - return (0); - m = (struct mbuf *)p; - MINDEX(m, k); - X = (mtod(m, u_char *)[k] & 0xf) << 2; - continue; -#else - return (0); -#endif - } - X = (p[pc->k] & 0xf) << 2; - continue; - - case USBPF_LD|USBPF_IMM: - A = pc->k; - continue; - - case USBPF_LDX|USBPF_IMM: - X = pc->k; - continue; - - case USBPF_LD|USBPF_MEM: - A = mem[pc->k]; - continue; - - case USBPF_LDX|USBPF_MEM: - X = mem[pc->k]; - continue; - - case USBPF_ST: - mem[pc->k] = A; - continue; - - case USBPF_STX: - mem[pc->k] = X; - continue; - - case USBPF_JMP|USBPF_JA: - pc += pc->k; - continue; - - case USBPF_JMP|USBPF_JGT|USBPF_K: - pc += (A > pc->k) ? pc->jt : pc->jf; - continue; - - case USBPF_JMP|USBPF_JGE|USBPF_K: - pc += (A >= pc->k) ? pc->jt : pc->jf; - continue; - - case USBPF_JMP|USBPF_JEQ|USBPF_K: - pc += (A == pc->k) ? pc->jt : pc->jf; - continue; - - case USBPF_JMP|USBPF_JSET|USBPF_K: - pc += (A & pc->k) ? pc->jt : pc->jf; - continue; - - case USBPF_JMP|USBPF_JGT|USBPF_X: - pc += (A > X) ? pc->jt : pc->jf; - continue; - - case USBPF_JMP|USBPF_JGE|USBPF_X: - pc += (A >= X) ? pc->jt : pc->jf; - continue; - - case USBPF_JMP|USBPF_JEQ|USBPF_X: - pc += (A == X) ? pc->jt : pc->jf; - continue; - - case USBPF_JMP|USBPF_JSET|USBPF_X: - pc += (A & X) ? pc->jt : pc->jf; - continue; - - case USBPF_ALU|USBPF_ADD|USBPF_X: - A += X; - continue; - - case USBPF_ALU|USBPF_SUB|USBPF_X: - A -= X; - continue; - - case USBPF_ALU|USBPF_MUL|USBPF_X: - A *= X; - continue; - - case USBPF_ALU|USBPF_DIV|USBPF_X: - if (X == 0) - return (0); - A /= X; - continue; - - case USBPF_ALU|USBPF_AND|USBPF_X: - A &= X; - continue; - - case USBPF_ALU|USBPF_OR|USBPF_X: - A |= X; - continue; - - case USBPF_ALU|USBPF_LSH|USBPF_X: - A <<= X; - continue; - - case USBPF_ALU|USBPF_RSH|USBPF_X: - A >>= X; - continue; - - case USBPF_ALU|USBPF_ADD|USBPF_K: - A += pc->k; - continue; - - case USBPF_ALU|USBPF_SUB|USBPF_K: - A -= pc->k; - continue; - - case USBPF_ALU|USBPF_MUL|USBPF_K: - A *= pc->k; - continue; - - case USBPF_ALU|USBPF_DIV|USBPF_K: - A /= pc->k; - continue; - - case USBPF_ALU|USBPF_AND|USBPF_K: - A &= pc->k; - continue; - - case USBPF_ALU|USBPF_OR|USBPF_K: - A |= pc->k; - continue; - - case USBPF_ALU|USBPF_LSH|USBPF_K: - A <<= pc->k; - continue; - - case USBPF_ALU|USBPF_RSH|USBPF_K: - A >>= pc->k; - continue; - - case USBPF_ALU|USBPF_NEG: - A = -A; - continue; - - case USBPF_MISC|USBPF_TAX: - X = A; - continue; - - case USBPF_MISC|USBPF_TXA: - A = X; - continue; - } - } -} - -static void -usbpf_free(struct usbpf_d *ud) -{ - - switch (ud->ud_bufmode) { - case USBPF_BUFMODE_BUFFER: - return (usbpf_buffer_free(ud)); - default: - panic("usbpf_buf_free"); - } -} - -/* - * Notify the buffer model that a buffer has moved into the hold position. - */ -static void -usbpf_bufheld(struct usbpf_d *ud) -{ - - USBPFD_LOCK_ASSERT(ud); -} - -/* - * Free buffers currently in use by a descriptor. - * Called on close. - */ -static void -usbpf_freed(struct usbpf_d *ud) -{ - - /* - * We don't need to lock out interrupts since this descriptor has - * been detached from its interface and it yet hasn't been marked - * free. - */ - usbpf_free(ud); - if (ud->ud_rfilter != NULL) - free((caddr_t)ud->ud_rfilter, M_USBPF); - if (ud->ud_wfilter != NULL) - free((caddr_t)ud->ud_wfilter, M_USBPF); - mtx_destroy(&ud->ud_mtx); -} - -/* - * Close the descriptor by detaching it from its interface, - * deallocating its buffers, and marking it free. - */ -static void -usbpf_dtor(void *data) -{ - struct usbpf_d *ud = data; - - USBPFD_LOCK(ud); - if (ud->ud_state == USBPF_WAITING) - callout_stop(&ud->ud_callout); - ud->ud_state = USBPF_IDLE; - USBPFD_UNLOCK(ud); - funsetown(&ud->ud_sigio); - mtx_lock(&usbpf_mtx); - if (ud->ud_bif) - usbpf_detachd(ud); - mtx_unlock(&usbpf_mtx); - selwakeuppri(&ud->ud_sel, PRIUSB); - knlist_destroy(&ud->ud_sel.si_note); - callout_drain(&ud->ud_callout); - usbpf_freed(ud); - free(ud, M_USBPF); -} - -/* - * Open device. Returns ENXIO for illegal minor device number, - * EBUSY if file is open by another process. - */ -/* ARGSUSED */ -static int -usbpf_open(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct usbpf_d *ud; - int error; - - ud = malloc(sizeof(*ud), M_USBPF, M_WAITOK | M_ZERO); - error = devfs_set_cdevpriv(ud, usbpf_dtor); - if (error != 0) { - free(ud, M_USBPF); - return (error); - } - - usbpf_buffer_init(ud); - ud->ud_bufmode = USBPF_BUFMODE_BUFFER; - ud->ud_sig = SIGIO; - ud->ud_direction = USBPF_D_INOUT; - ud->ud_pid = td->td_proc->p_pid; - mtx_init(&ud->ud_mtx, devtoname(dev), "usbpf cdev lock", MTX_DEF); - callout_init_mtx(&ud->ud_callout, &ud->ud_mtx, 0); - knlist_init_mtx(&ud->ud_sel.si_note, &ud->ud_mtx); - - return (0); -} - -static int -usbpf_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len, struct uio *uio) -{ - - if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER) - return (EOPNOTSUPP); - return (usbpf_buffer_uiomove(ud, buf, len, uio)); -} - -/* - * usbpf_read - read next chunk of packets from buffers - */ -static int -usbpf_read(struct cdev *dev, struct uio *uio, int ioflag) -{ - struct usbpf_d *ud; - int error; - int non_block; - int timed_out; - - error = devfs_get_cdevpriv((void **)&ud); - if (error != 0) - return (error); - - /* - * Restrict application to use a buffer the same size as - * as kernel buffers. - */ - if (uio->uio_resid != ud->ud_bufsize) - return (EINVAL); - - non_block = ((ioflag & O_NONBLOCK) != 0); - - USBPFD_LOCK(ud); - ud->ud_pid = curthread->td_proc->p_pid; - if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER) { - USBPFD_UNLOCK(ud); - return (EOPNOTSUPP); - } - if (ud->ud_state == USBPF_WAITING) - callout_stop(&ud->ud_callout); - timed_out = (ud->ud_state == USBPF_TIMED_OUT); - ud->ud_state = USBPF_IDLE; - /* - * If the hold buffer is empty, then do a timed sleep, which - * ends when the timeout expires or when enough packets - * have arrived to fill the store buffer. - */ - while (ud->ud_hbuf == NULL) { - if (ud->ud_slen != 0) { - /* - * A packet(s) either arrived since the previous - * read or arrived while we were asleep. - */ - if (ud->ud_immediate || non_block || timed_out) { - /* - * Rotate the buffers and return what's here - * if we are in immediate mode, non-blocking - * flag is set, or this descriptor timed out. - */ - USBPF_ROTATE_BUFFERS(ud); - break; - } - } - - /* - * No data is available, check to see if the usbpf device - * is still pointed at a real interface. If not, return - * ENXIO so that the userland process knows to rebind - * it before using it again. - */ - if (ud->ud_bif == NULL) { - USBPFD_UNLOCK(ud); - return (ENXIO); - } - - if (non_block) { - USBPFD_UNLOCK(ud); - return (EWOULDBLOCK); - } - error = msleep(ud, &ud->ud_mtx, PRIUSB|PCATCH, - "uff", ud->ud_rtout); - if (error == EINTR || error == ERESTART) { - USBPFD_UNLOCK(ud); - return (error); - } - if (error == EWOULDBLOCK) { - /* - * On a timeout, return what's in the buffer, - * which may be nothing. If there is something - * in the store buffer, we can rotate the buffers. - */ - if (ud->ud_hbuf) - /* - * We filled up the buffer in between - * getting the timeout and arriving - * here, so we don't need to rotate. - */ - break; - - if (ud->ud_slen == 0) { - USBPFD_UNLOCK(ud); - return (0); - } - USBPF_ROTATE_BUFFERS(ud); - break; - } - } - /* - * At this point, we know we have something in the hold slot. - */ - USBPFD_UNLOCK(ud); - - /* - * Move data from hold buffer into user space. - * We know the entire buffer is transferred since - * we checked above that the read buffer is usbpf_bufsize bytes. - * - * XXXRW: More synchronization needed here: what if a second thread - * issues a read on the same fd at the same time? Don't want this - * getting invalidated. - */ - error = usbpf_uiomove(ud, ud->ud_hbuf, ud->ud_hlen, uio); - - USBPFD_LOCK(ud); - ud->ud_fbuf = ud->ud_hbuf; - ud->ud_hbuf = NULL; - ud->ud_hlen = 0; - usbpf_buf_reclaimed(ud); - USBPFD_UNLOCK(ud); - - return (error); -} - -static int -usbpf_write(struct cdev *dev, struct uio *uio, int ioflag) -{ - - /* NOT IMPLEMENTED */ - return (ENOSYS); -} - -static int -usbpf_ioctl_sblen(struct usbpf_d *ud, u_int *i) -{ - - if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER) - return (EOPNOTSUPP); - return (usbpf_buffer_ioctl_sblen(ud, i)); -} - -/* - * Reset a descriptor by flushing its packet buffer and clearing the receive - * and drop counts. This is doable for kernel-only buffers, but with - * zero-copy buffers, we can't write to (or rotate) buffers that are - * currently owned by userspace. It would be nice if we could encapsulate - * this logic in the buffer code rather than here. - */ -static void -usbpf_reset_d(struct usbpf_d *ud) -{ - - USBPFD_LOCK_ASSERT(ud); - - if ((ud->ud_hbuf != NULL) && - (ud->ud_bufmode != USBPF_BUFMODE_ZBUF || usbpf_canfreebuf(ud))) { - /* Free the hold buffer. */ - ud->ud_fbuf = ud->ud_hbuf; - ud->ud_hbuf = NULL; - ud->ud_hlen = 0; - usbpf_buf_reclaimed(ud); - } - if (usbpf_canwritebuf(ud)) - ud->ud_slen = 0; - ud->ud_rcount = 0; - ud->ud_dcount = 0; - ud->ud_fcount = 0; - ud->ud_wcount = 0; - ud->ud_wfcount = 0; - ud->ud_wdcount = 0; - ud->ud_zcopy = 0; -} - -static int -usbpf_setif(struct usbpf_d *ud, struct usbpf_ifreq *ufr) -{ - struct usbpf_if *uif; - struct usb_bus *theywant; - - theywant = usb_bus_find(ufr->ufr_name); - if (theywant == NULL || theywant->uif == NULL) - return (ENXIO); - - uif = theywant->uif; - - switch (ud->ud_bufmode) { - case USBPF_BUFMODE_BUFFER: - if (ud->ud_sbuf == NULL) - usbpf_buffer_alloc(ud); - KASSERT(ud->ud_sbuf != NULL, ("%s: ud_sbuf == NULL", __func__)); - break; - - default: - panic("usbpf_setif: bufmode %d", ud->ud_bufmode); - } - if (uif != ud->ud_bif) { - if (ud->ud_bif) - /* - * Detach if attached to something else. - */ - usbpf_detachd(ud); - - usbpf_attachd(ud, uif); - } - USBPFD_LOCK(ud); - usbpf_reset_d(ud); - USBPFD_UNLOCK(ud); - return (0); -} - -/* - * Set d's packet filter program to fp. If this file already has a filter, - * free it and replace it. Returns EINVAL for bogus requests. - */ -static int -usbpf_setf(struct usbpf_d *ud, struct usbpf_program *fp, u_long cmd) -{ - struct usbpf_insn *fcode, *old; - u_int wfilter, flen, size; - - if (cmd == UIOCSETWF) { - old = ud->ud_wfilter; - wfilter = 1; - } else { - wfilter = 0; - old = ud->ud_rfilter; - } - if (fp->uf_insns == NULL) { - if (fp->uf_len != 0) - return (EINVAL); - USBPFD_LOCK(ud); - if (wfilter) - ud->ud_wfilter = NULL; - else { - ud->ud_rfilter = NULL; - if (cmd == UIOCSETF) - usbpf_reset_d(ud); - } - USBPFD_UNLOCK(ud); - if (old != NULL) - free((caddr_t)old, M_USBPF); - return (0); - } - flen = fp->uf_len; - if (flen > usbpf_maxinsns) - return (EINVAL); - - size = flen * sizeof(*fp->uf_insns); - fcode = (struct usbpf_insn *)malloc(size, M_USBPF, M_WAITOK); - if (copyin((caddr_t)fp->uf_insns, (caddr_t)fcode, size) == 0 && - usbpf_validate(fcode, (int)flen)) { - USBPFD_LOCK(ud); - if (wfilter) - ud->ud_wfilter = fcode; - else { - ud->ud_rfilter = fcode; - if (cmd == UIOCSETF) - usbpf_reset_d(ud); - } - USBPFD_UNLOCK(ud); - if (old != NULL) - free((caddr_t)old, M_USBPF); - - return (0); - } - free((caddr_t)fcode, M_USBPF); - return (EINVAL); -} - -static int -usbpf_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, - struct thread *td) -{ - struct usbpf_d *ud; - int error; - - error = devfs_get_cdevpriv((void **)&ud); - if (error != 0) - return (error); - - /* - * Refresh PID associated with this descriptor. - */ - USBPFD_LOCK(ud); - ud->ud_pid = td->td_proc->p_pid; - if (ud->ud_state == USBPF_WAITING) - callout_stop(&ud->ud_callout); - ud->ud_state = USBPF_IDLE; - USBPFD_UNLOCK(ud); - - if (ud->ud_locked == 1) { - switch (cmd) { - case UIOCGBLEN: - case UIOCSBLEN: - case UIOCVERSION: - break; - default: - return (EPERM); - } - } - - switch (cmd) { - - default: - error = EINVAL; - break; - - /* - * Get buffer len [for read()]. - */ - case UIOCGBLEN: - *(u_int *)addr = ud->ud_bufsize; - break; - - /* - * Set buffer length. - */ - case UIOCSBLEN: - error = usbpf_ioctl_sblen(ud, (u_int *)addr); - break; - - /* - * Set read filter. - */ - case UIOCSETF: - error = usbpf_setf(ud, (struct usbpf_program *)addr, cmd); - break; - - /* - * Set read timeout. - */ - case UIOCSRTIMEOUT: - { - struct timeval *tv = (struct timeval *)addr; - - /* - * Subtract 1 tick from tvtohz() since this isn't - * a one-shot timer. - */ - if ((error = itimerfix(tv)) == 0) - ud->ud_rtout = tvtohz(tv) - 1; - break; - } - - /* - * Get read timeout. - */ - case UIOCGRTIMEOUT: - { - struct timeval *tv = (struct timeval *)addr; - - tv->tv_sec = ud->ud_rtout / hz; - tv->tv_usec = (ud->ud_rtout % hz) * tick; - break; - } - - /* - * Get packet stats. - */ - case UIOCGSTATS: - { - struct usbpf_stat *us = (struct usbpf_stat *)addr; - - /* XXXCSJP overflow */ - us->us_recv = ud->ud_rcount; - us->us_drop = ud->ud_dcount; - break; - } - - case UIOCVERSION: - { - struct usbpf_version *uv = (struct usbpf_version *)addr; - - uv->uv_major = USBPF_MAJOR_VERSION; - uv->uv_minor = USBPF_MINOR_VERSION; - break; - } - - /* - * Set interface. - */ - case UIOCSETIF: - error = usbpf_setif(ud, (struct usbpf_ifreq *)addr); - break; - - } - return (error); -} - -/* - * Support for select() and poll() system calls - * - * Return true iff the specific operation will not block indefinitely. - * Otherwise, return false but make a note that a selwakeup() must be done. - */ -static int -usbpf_poll(struct cdev *dev, int events, struct thread *td) -{ - - /* NOT IMPLEMENTED */ - return (ENOSYS); -} - -/* - * Support for kevent() system call. Register EVFILT_READ filters and - * reject all others. - */ -int -usbpf_kqfilter(struct cdev *dev, struct knote *kn) -{ - - /* NOT IMPLEMENTED */ - return (ENOSYS); -} - -/* - * Attach file to the usbpf interface, i.e. make d listen on bp. - */ -static void -usbpf_attachd(struct usbpf_d *ud, struct usbpf_if *uif) +void +usbpf_attach(struct usb_bus *ubus) { + struct ifnet *ifp; - USBPFIF_LOCK(uif); - ud->ud_bif = uif; - LIST_INSERT_HEAD(&uif->uif_dlist, ud, ud_next); + ifp = ubus->ifp = if_alloc(IFT_USB); + if_initname(ifp, "usbus", device_get_unit(ubus->bdev)); + if_attach(ifp); - usbpf_uifd_cnt++; - USBPFIF_UNLOCK(uif); -} - -/* - * Detach a file from its interface. - */ -static void -usbpf_detachd(struct usbpf_d *ud) -{ - struct usbpf_if *uif; - struct usb_bus *ubus; - - uif = ud->ud_bif; - USBPFIF_LOCK(uif); - USBPFD_LOCK(ud); - ubus = ud->ud_bif->uif_ubus; + KASSERT(sizeof(struct usbpf_pkthdr) == USBPF_HDR_LEN, + ("wrong USB pf header length (%zd)", sizeof(struct usbpf_pkthdr))); /* - * Remove d from the interface's descriptor list. + * XXX According to the specification of DLT_USB, it indicates packets + * beginning with USB setup header. But not sure all packets would be. */ - LIST_REMOVE(ud, ud_next); - - usbpf_uifd_cnt--; - ud->ud_bif = NULL; - USBPFD_UNLOCK(ud); - USBPFIF_UNLOCK(uif); -} - -void -usbpf_attach(struct usb_bus *ubus, struct usbpf_if **driverp) -{ - struct usbpf_if *uif; - - uif = malloc(sizeof(*uif), M_USBPF, M_WAITOK | M_ZERO); - LIST_INIT(&uif->uif_dlist); - uif->uif_ubus = ubus; - mtx_init(&uif->uif_mtx, "usbpf interface lock", NULL, MTX_DEF); - KASSERT(*driverp == NULL, - ("usbpf_attach: driverp already initialized")); - *driverp = uif; - - mtx_lock(&usbpf_mtx); - LIST_INSERT_HEAD(&usbpf_iflist, uif, uif_next); - mtx_unlock(&usbpf_mtx); + bpfattach(ifp, DLT_USB, USBPF_HDR_LEN); if (bootverbose) device_printf(ubus->parent, "usbpf attached\n"); } -/* - * If there are processes sleeping on this descriptor, wake them up. - */ -static __inline void -usbpf_wakeup(struct usbpf_d *ud) -{ - - USBPFD_LOCK_ASSERT(ud); - if (ud->ud_state == USBPF_WAITING) { - callout_stop(&ud->ud_callout); - ud->ud_state = USBPF_IDLE; - } - wakeup(ud); - if (ud->ud_async && ud->ud_sig && ud->ud_sigio) - pgsigio(&ud->ud_sigio, ud->ud_sig, 0); - - selwakeuppri(&ud->ud_sel, PRIUSB); - KNOTE_LOCKED(&ud->ud_sel.si_note, 0); -} - void usbpf_detach(struct usb_bus *ubus) { - struct usbpf_if *uif; - struct usbpf_d *ud; - - /* Locate USBPF interface information */ - mtx_lock(&usbpf_mtx); - LIST_FOREACH(uif, &usbpf_iflist, uif_next) { - if (ubus == uif->uif_ubus) - break; - } - - /* Interface wasn't attached */ - if ((uif == NULL) || (uif->uif_ubus == NULL)) { - mtx_unlock(&usbpf_mtx); - printf("usbpf_detach: not attached\n"); /* XXX */ - return; - } - - LIST_REMOVE(uif, uif_next); - mtx_unlock(&usbpf_mtx); - - while ((ud = LIST_FIRST(&uif->uif_dlist)) != NULL) { - usbpf_detachd(ud); - USBPFD_LOCK(ud); - usbpf_wakeup(ud); - USBPFD_UNLOCK(ud); - } - - mtx_destroy(&uif->uif_mtx); - free(uif, M_USBPF); -} - -/* Time stamping functions */ -#define USBPF_T_MICROTIME 0x0000 -#define USBPF_T_NANOTIME 0x0001 -#define USBPF_T_BINTIME 0x0002 -#define USBPF_T_NONE 0x0003 -#define USBPF_T_FORMAT_MASK 0x0003 -#define USBPF_T_NORMAL 0x0000 -#define USBPF_T_FAST 0x0100 -#define USBPF_T_MONOTONIC 0x0200 -#define USBPF_T_FORMAT(t) ((t) & USBPF_T_FORMAT_MASK) - -#define USBPF_TSTAMP_NONE 0 -#define USBPF_TSTAMP_FAST 1 -#define USBPF_TSTAMP_NORMAL 2 - -static int -usbpf_ts_quality(int tstype) -{ - - if (tstype == USBPF_T_NONE) - return (USBPF_TSTAMP_NONE); - if ((tstype & USBPF_T_FAST) != 0) - return (USBPF_TSTAMP_FAST); - - return (USBPF_TSTAMP_NORMAL); -} - -static int -usbpf_gettime(struct bintime *bt, int tstype) -{ - int quality; - - quality = usbpf_ts_quality(tstype); - if (quality == USBPF_TSTAMP_NONE) - return (quality); - if (quality == USBPF_TSTAMP_NORMAL) - binuptime(bt); - else - getbinuptime(bt); - - return (quality); -} - -/* - * If the buffer mechanism has a way to decide that a held buffer can be made - * free, then it is exposed via the usbpf_canfreebuf() interface. (1) is - * returned if the buffer can be discarded, (0) is returned if it cannot. - */ -static int -usbpf_canfreebuf(struct usbpf_d *ud) -{ - - USBPFD_LOCK_ASSERT(ud); - - return (0); -} - -/* - * Allow the buffer model to indicate that the current store buffer is - * immutable, regardless of the appearance of space. Return (1) if the - * buffer is writable, and (0) if not. - */ -static int -usbpf_canwritebuf(struct usbpf_d *ud) -{ - - USBPFD_LOCK_ASSERT(ud); - return (1); -} + struct ifnet *ifp = ubus->ifp; -/* - * Notify buffer model that an attempt to write to the store buffer has - * resulted in a dropped packet, in which case the buffer may be considered - * full. - */ -static void -usbpf_buffull(struct usbpf_d *ud) -{ - - USBPFD_LOCK_ASSERT(ud); -} - -/* - * This function gets called when the free buffer is re-assigned. - */ -static void -usbpf_buf_reclaimed(struct usbpf_d *ud) -{ - - USBPFD_LOCK_ASSERT(ud); - - switch (ud->ud_bufmode) { - case USBPF_BUFMODE_BUFFER: - return; - - default: - panic("usbpf_buf_reclaimed"); + if (ifp != NULL) { + bpfdetach(ifp); + if_detach(ifp); + if_free(ifp); } -} - -#define SIZEOF_USBPF_HDR(type) \ - (offsetof(type, uh_hdrlen) + sizeof(((type *)0)->uh_hdrlen)) - -static int -usbpf_hdrlen(struct usbpf_d *ud) -{ - int hdrlen; - - hdrlen = ud->ud_bif->uif_hdrlen; - hdrlen += SIZEOF_USBPF_HDR(struct usbpf_xhdr); - hdrlen = USBPF_WORDALIGN(hdrlen); - - return (hdrlen - ud->ud_bif->uif_hdrlen); -} - -static void -usbpf_bintime2ts(struct bintime *bt, struct usbpf_ts *ts, int tstype) -{ - struct bintime bt2; - struct timeval tsm; - struct timespec tsn; - - if ((tstype & USBPF_T_MONOTONIC) == 0) { - bt2 = *bt; - bintime_add(&bt2, &boottimebin); - bt = &bt2; - } - switch (USBPF_T_FORMAT(tstype)) { - case USBPF_T_MICROTIME: - bintime2timeval(bt, &tsm); - ts->ut_sec = tsm.tv_sec; - ts->ut_frac = tsm.tv_usec; - break; - case USBPF_T_NANOTIME: - bintime2timespec(bt, &tsn); - ts->ut_sec = tsn.tv_sec; - ts->ut_frac = tsn.tv_nsec; - break; - case USBPF_T_BINTIME: - ts->ut_sec = bt->sec; - ts->ut_frac = bt->frac; - break; - } -} - -/* - * Move the packet data from interface memory (pkt) into the - * store buffer. "cpfn" is the routine called to do the actual data - * transfer. bcopy is passed in to copy contiguous chunks, while - * usbpf_append_mbuf is passed in to copy mbuf chains. In the latter case, - * pkt is really an mbuf. - */ -static void -catchpacket(struct usbpf_d *ud, u_char *pkt, u_int pktlen, u_int snaplen, - void (*cpfn)(struct usbpf_d *, caddr_t, u_int, void *, u_int), - struct bintime *bt) -{ - struct usbpf_xhdr hdr; - int caplen, curlen, hdrlen, totlen; - int do_wakeup = 0; - int do_timestamp; - int tstype; - - USBPFD_LOCK_ASSERT(ud); - - /* - * Detect whether user space has released a buffer back to us, and if - * so, move it from being a hold buffer to a free buffer. This may - * not be the best place to do it (for example, we might only want to - * run this check if we need the space), but for now it's a reliable - * spot to do it. - */ - if (ud->ud_fbuf == NULL && usbpf_canfreebuf(ud)) { - ud->ud_fbuf = ud->ud_hbuf; - ud->ud_hbuf = NULL; - ud->ud_hlen = 0; - usbpf_buf_reclaimed(ud); - } - - /* - * Figure out how many bytes to move. If the packet is - * greater or equal to the snapshot length, transfer that - * much. Otherwise, transfer the whole packet (unless - * we hit the buffer size limit). - */ - hdrlen = usbpf_hdrlen(ud); - totlen = hdrlen + min(snaplen, pktlen); - if (totlen > ud->ud_bufsize) - totlen = ud->ud_bufsize; - - /* - * Round up the end of the previous packet to the next longword. - * - * Drop the packet if there's no room and no hope of room - * If the packet would overflow the storage buffer or the storage - * buffer is considered immutable by the buffer model, try to rotate - * the buffer and wakeup pending processes. - */ - curlen = USBPF_WORDALIGN(ud->ud_slen); - if (curlen + totlen > ud->ud_bufsize || !usbpf_canwritebuf(ud)) { - if (ud->ud_fbuf == NULL) { - /* - * There's no room in the store buffer, and no - * prospect of room, so drop the packet. Notify the - * buffer model. - */ - usbpf_buffull(ud); - ++ud->ud_dcount; - return; - } - USBPF_ROTATE_BUFFERS(ud); - do_wakeup = 1; - curlen = 0; - } else if (ud->ud_immediate || ud->ud_state == USBPF_TIMED_OUT) - /* - * Immediate mode is set, or the read timeout has already - * expired during a select call. A packet arrived, so the - * reader should be woken up. - */ - do_wakeup = 1; - caplen = totlen - hdrlen; - tstype = ud->ud_tstamp; - do_timestamp = tstype != USBPF_T_NONE; - - /* - * Append the usbpf header. Note we append the actual header size, but - * move forward the length of the header plus padding. - */ - bzero(&hdr, sizeof(hdr)); - if (do_timestamp) - usbpf_bintime2ts(bt, &hdr.uh_tstamp, tstype); - hdr.uh_datalen = pktlen; - hdr.uh_hdrlen = hdrlen; - hdr.uh_caplen = caplen; - usbpf_append_bytes(ud, ud->ud_sbuf, curlen, &hdr, sizeof(hdr)); - - /* - * Copy the packet data into the store buffer and update its length. - */ - (*cpfn)(ud, ud->ud_sbuf, curlen + hdrlen, pkt, caplen); - ud->ud_slen = curlen + totlen; - - if (do_wakeup) - usbpf_wakeup(ud); -} - -/* - * Incoming linkage from device drivers. Process the packet pkt, of length - * pktlen, which is stored in a contiguous buffer. The packet is parsed - * by each process' filter, and if accepted, stashed into the corresponding - * buffer. - */ -static void -usbpf_tap(struct usbpf_if *uif, u_char *pkt, u_int pktlen) -{ - struct bintime bt; - struct usbpf_d *ud; - u_int slen; - int gottime; - - gottime = USBPF_TSTAMP_NONE; - USBPFIF_LOCK(uif); - LIST_FOREACH(ud, &uif->uif_dlist, ud_next) { - USBPFD_LOCK(ud); - ++ud->ud_rcount; - slen = usbpf_filter(ud->ud_rfilter, pkt, pktlen, pktlen); - if (slen != 0) { - ud->ud_fcount++; - if (gottime < usbpf_ts_quality(ud->ud_tstamp)) - gottime = usbpf_gettime(&bt, ud->ud_tstamp); - catchpacket(ud, pkt, pktlen, slen, - usbpf_append_bytes, &bt); - } - USBPFD_UNLOCK(ud); - } - USBPFIF_UNLOCK(uif); + ubus->ifp = NULL; } static uint32_t @@ -1763,11 +181,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type) int i; char *buf, *ptr, *end; - /* - * NB: usbpf_uifd_cnt isn't protected by USBPFIF_LOCK() because it's - * not harmful. - */ - if (usbpf_uifd_cnt == 0) + if (!bpf_peers_present(bus->ifp->if_bpf)) return; /* @@ -1777,7 +191,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type) * read filter to pass a virtually linear buffer. */ buf = ptr = malloc(sizeof(struct usbpf_pkthdr) + (USB_PAGE_SIZE * 5), - M_USBPF, M_NOWAIT); + M_TEMP, M_NOWAIT); if (buf == NULL) { printf("usbpf_xfertap: out of memory\n"); /* XXX */ return; @@ -1827,36 +241,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type) ptr += xfer->frlengths[i]; } - usbpf_tap(bus->uif, buf, ptr - buf); + bpf_tap(bus->ifp->if_bpf, buf, ptr - buf); done: - free(buf, M_USBPF); + free(buf, M_TEMP); } - -static void -usbpf_append_bytes(struct usbpf_d *ud, caddr_t buf, u_int offset, void *src, - u_int len) -{ - - USBPFD_LOCK_ASSERT(ud); - - switch (ud->ud_bufmode) { - case USBPF_BUFMODE_BUFFER: - return (usbpf_buffer_append_bytes(ud, buf, offset, src, len)); - default: - panic("usbpf_buf_append_bytes"); - } -} - -static void -usbpf_drvinit(void *unused) -{ - struct cdev *dev; - - mtx_init(&usbpf_mtx, "USB packet filter global lock", NULL, - MTX_DEF); - LIST_INIT(&usbpf_iflist); - - dev = make_dev(&usbpf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "usbpf"); -} - -SYSINIT(usbpf_dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, usbpf_drvinit, NULL); diff --git a/sys/dev/usb/usb_pf.h b/sys/dev/usb/usb_pf.h index f5ed9a0..58b9ce9 100644 --- a/sys/dev/usb/usb_pf.h +++ b/sys/dev/usb/usb_pf.h @@ -37,190 +37,6 @@ #ifndef _DEV_USB_PF_H #define _DEV_USB_PF_H -#ifdef _KERNEL -#include <sys/callout.h> -#include <sys/selinfo.h> -#include <sys/queue.h> -#include <sys/conf.h> -#endif - -typedef int32_t usbpf_int32; -typedef u_int32_t usbpf_u_int32; -typedef int64_t usbpf_int64; -typedef u_int64_t usbpf_u_int64; - -struct usbpf_if; - -/* - * Alignment macros. USBPF_WORDALIGN rounds up to the next - * even multiple of USBPF_ALIGNMENT. - */ -#define USBPF_ALIGNMENT sizeof(long) -#define USBPF_WORDALIGN(x) (((x)+(USBPF_ALIGNMENT-1))&~(USBPF_ALIGNMENT-1)) - -/* - * The instruction encodings. - */ - -/* instruction classes */ -#define USBPF_CLASS(code) ((code) & 0x07) -#define USBPF_LD 0x00 -#define USBPF_LDX 0x01 -#define USBPF_ST 0x02 -#define USBPF_STX 0x03 -#define USBPF_ALU 0x04 -#define USBPF_JMP 0x05 -#define USBPF_RET 0x06 -#define USBPF_MISC 0x07 - -/* ld/ldx fields */ -#define USBPF_SIZE(code) ((code) & 0x18) -#define USBPF_W 0x00 -#define USBPF_H 0x08 -#define USBPF_B 0x10 -#define USBPF_MODE(code) ((code) & 0xe0) -#define USBPF_IMM 0x00 -#define USBPF_ABS 0x20 -#define USBPF_IND 0x40 -#define USBPF_MEM 0x60 -#define USBPF_LEN 0x80 -#define USBPF_MSH 0xa0 - -/* alu/jmp fields */ -#define USBPF_OP(code) ((code) & 0xf0) -#define USBPF_ADD 0x00 -#define USBPF_SUB 0x10 -#define USBPF_MUL 0x20 -#define USBPF_DIV 0x30 -#define USBPF_OR 0x40 -#define USBPF_AND 0x50 -#define USBPF_LSH 0x60 -#define USBPF_RSH 0x70 -#define USBPF_NEG 0x80 -#define USBPF_JA 0x00 -#define USBPF_JEQ 0x10 -#define USBPF_JGT 0x20 -#define USBPF_JGE 0x30 -#define USBPF_JSET 0x40 -#define USBPF_SRC(code) ((code) & 0x08) -#define USBPF_K 0x00 -#define USBPF_X 0x08 - -/* ret - USBPF_K and USBPF_X also apply */ -#define USBPF_RVAL(code) ((code) & 0x18) -#define USBPF_A 0x10 - -/* misc */ -#define USBPF_MISCOP(code) ((code) & 0xf8) -#define USBPF_TAX 0x00 -#define USBPF_TXA 0x80 - -/* - * The instruction data structure. - */ -struct usbpf_insn { - u_short code; - u_char jt; - u_char jf; - usbpf_u_int32 k; -}; - -#ifdef _KERNEL - -/* - * Descriptor associated with each open uff file. - */ - -struct usbpf_d { - LIST_ENTRY(usbpf_d) ud_next; /* Linked list of descriptors */ - /* - * Buffer slots: two memory buffers store the incoming packets. - * The model has three slots. Sbuf is always occupied. - * sbuf (store) - Receive interrupt puts packets here. - * hbuf (hold) - When sbuf is full, put buffer here and - * wakeup read (replace sbuf with fbuf). - * fbuf (free) - When read is done, put buffer here. - * On receiving, if sbuf is full and fbuf is 0, packet is dropped. - */ - caddr_t ud_sbuf; /* store slot */ - caddr_t ud_hbuf; /* hold slot */ - caddr_t ud_fbuf; /* free slot */ - int ud_slen; /* current length of store buffer */ - int ud_hlen; /* current length of hold buffer */ - - int ud_bufsize; /* absolute length of buffers */ - - struct usbpf_if *ud_bif; /* interface descriptor */ - u_long ud_rtout; /* Read timeout in 'ticks' */ - struct usbpf_insn *ud_rfilter; /* read filter code */ - struct usbpf_insn *ud_wfilter; /* write filter code */ - void *ud_bfilter; /* binary filter code */ - u_int64_t ud_rcount; /* number of packets received */ - u_int64_t ud_dcount; /* number of packets dropped */ - - u_char ud_promisc; /* true if listening promiscuously */ - u_char ud_state; /* idle, waiting, or timed out */ - u_char ud_immediate; /* true to return on packet arrival */ - int ud_hdrcmplt; /* false to fill in src lladdr automatically */ - int ud_direction; /* select packet direction */ - int ud_tstamp; /* select time stamping function */ - int ud_feedback; /* true to feed back sent packets */ - int ud_async; /* non-zero if packet reception should generate signal */ - int ud_sig; /* signal to send upon packet reception */ - struct sigio * ud_sigio; /* information for async I/O */ - struct selinfo ud_sel; /* bsd select info */ - struct mtx ud_mtx; /* mutex for this descriptor */ - struct callout ud_callout; /* for USBPF timeouts with select */ - struct label *ud_label; /* MAC label for descriptor */ - u_int64_t ud_fcount; /* number of packets which matched filter */ - pid_t ud_pid; /* PID which created descriptor */ - int ud_locked; /* true if descriptor is locked */ - u_int ud_bufmode; /* Current buffer mode. */ - u_int64_t ud_wcount; /* number of packets written */ - u_int64_t ud_wfcount; /* number of packets that matched write filter */ - u_int64_t ud_wdcount; /* number of packets dropped during a write */ - u_int64_t ud_zcopy; /* number of zero copy operations */ - u_char ud_compat32; /* 32-bit stream on LP64 system */ -}; - -#define USBPFD_LOCK(ud) mtx_lock(&(ud)->ud_mtx) -#define USBPFD_UNLOCK(ud) mtx_unlock(&(ud)->ud_mtx) -#define USBPFD_LOCK_ASSERT(ud) mtx_assert(&(ud)->ud_mtx, MA_OWNED) - -/* - * Descriptor associated with each attached hardware interface. - */ -struct usbpf_if { - LIST_ENTRY(usbpf_if) uif_next; /* list of all interfaces */ - LIST_HEAD(, usbpf_d) uif_dlist; /* descriptor list */ - u_int uif_hdrlen; /* length of link header */ - struct usb_bus *uif_ubus; /* corresponding interface */ - struct mtx uif_mtx; /* mutex for interface */ -}; - -#define USBPFIF_LOCK(uif) mtx_lock(&(uif)->uif_mtx) -#define USBPFIF_UNLOCK(uif) mtx_unlock(&(uif)->uif_mtx) - -#endif - -/* - * Structure prepended to each packet. - */ -struct usbpf_ts { - usbpf_int64 ut_sec; /* seconds */ - usbpf_u_int64 ut_frac; /* fraction */ -}; -struct usbpf_xhdr { - struct usbpf_ts uh_tstamp; /* time stamp */ - usbpf_u_int32 uh_caplen; /* length of captured portion */ - usbpf_u_int32 uh_datalen; /* original length of packet */ - u_short uh_hdrlen; /* length of uff header (this struct - plus alignment padding) */ -}; - -#define USBPF_BUFMODE_BUFFER 1 /* Kernel buffers with read(). */ -#define USBPF_BUFMODE_ZBUF 2 /* Zero-copy buffers. */ - struct usbpf_pkthdr { int up_busunit; /* Host controller unit number */ u_char up_address; /* USB device address */ @@ -268,50 +84,13 @@ struct usbpf_pkthdr { u_char up_reserved[96]; }; -struct usbpf_version { - u_short uv_major; - u_short uv_minor; -}; -#define USBPF_MAJOR_VERSION 1 -#define USBPF_MINOR_VERSION 1 - -#define USBPF_IFNAMSIZ 32 -struct usbpf_ifreq { - /* bus name, e.g. "usbus0" */ - char ufr_name[USBPF_IFNAMSIZ]; -}; - -/* - * Structure for UIOCSETF. - */ -struct usbpf_program { - u_int uf_len; - struct usbpf_insn *uf_insns; -}; - -/* - * Struct returned by UIOCGSTATS. - */ -struct usbpf_stat { - u_int us_recv; /* number of packets received */ - u_int us_drop; /* number of packets dropped */ -}; - -#define UIOCGBLEN _IOR('U', 102, u_int) -#define UIOCSBLEN _IOWR('U', 102, u_int) -#define UIOCSETF _IOW('U', 103, struct usbpf_program) -#define UIOCSETIF _IOW('U', 108, struct usbpf_ifreq) -#define UIOCSRTIMEOUT _IOW('U', 109, struct timeval) -#define UIOCGRTIMEOUT _IOR('U', 110, struct timeval) -#define UIOCGSTATS _IOR('U', 111, struct usbpf_stat) -#define UIOCVERSION _IOR('U', 113, struct usbpf_version) -#define UIOCSETWF _IOW('U', 123, struct usbpf_program) +#define USBPF_HDR_LEN 128 #define USBPF_XFERTAP_SUBMIT 0 #define USBPF_XFERTAP_DONE 1 #ifdef _KERNEL -void usbpf_attach(struct usb_bus *, struct usbpf_if **); +void usbpf_attach(struct usb_bus *); void usbpf_detach(struct usb_bus *); void usbpf_xfertap(struct usb_xfer *, int); #endif diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index 91fe9f4..a34ec3c 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -1789,8 +1789,8 @@ product HTC LEGENDINTERNET 0x0ffe HTC Legend Internet Sharing /* HUAWEI products */ product HUAWEI MOBILE 0x1001 Huawei Mobile -product HUAWEI E220 0x1003 Huawei HSDPA modem -product HUAWEI E220BIS 0x1004 Huawei HSDPA modem +product HUAWEI E220 0x1003 HSDPA modem +product HUAWEI E220BIS 0x1004 HSDPA modem product HUAWEI E1401 0x1401 3G modem product HUAWEI E1402 0x1402 3G modem product HUAWEI E1403 0x1403 3G modem @@ -1802,7 +1802,7 @@ product HUAWEI E1408 0x1408 3G modem product HUAWEI E1409 0x1409 3G modem product HUAWEI E140A 0x140a 3G modem product HUAWEI E140B 0x140b 3G modem -product HUAWEI E180V 0x140c Huawei Mobile E180V +product HUAWEI E180V 0x140c E180V product HUAWEI E140D 0x140d 3G modem product HUAWEI E140E 0x140e 3G modem product HUAWEI E140F 0x140f 3G modem @@ -1856,8 +1856,8 @@ product HUAWEI E143E 0x143e 3G modem product HUAWEI E143F 0x143f 3G modem product HUAWEI E1752 0x1446 3G modem product HUAWEI K3765 0x1465 3G modem -product HUAWEI E14AC 0x14ac 3G modem -product HUAWEI K3765_INIT 0x1520 HUAWEI Mobile K3765 Initial +product HUAWEI E1820 0x14ac E1820 HSPA+ USB Slider +product HUAWEI K3765_INIT 0x1520 K3765 Initial /* HUAWEI 3com products */ product HUAWEI3COM WUB320G 0x0009 Aolynk WUB320g diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index b15e9b7..7efa29c 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -220,8 +220,7 @@ static uma_zone_t pdptzone; SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); static int pat_works = 1; -TUNABLE_INT("vm.pmap.pat_works", &pat_works); -SYSCTL_INT(_vm_pmap, OID_AUTO, pat_works, CTLFLAG_RDTUN, &pat_works, 1, +SYSCTL_INT(_vm_pmap, OID_AUTO, pat_works, CTLFLAG_RD, &pat_works, 1, "Is page attribute table fully functional?"); static int pg_ps_enabled = 1; diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h index dd0d4ee..73e7a84 100644 --- a/sys/i386/include/specialreg.h +++ b/sys/i386/include/specialreg.h @@ -133,6 +133,15 @@ #define CPUID2_AESNI 0x02000000 /* + * Important bits in the Thermal and Power Management flags + * CPUID.6 EAX and ECX. + */ +#define CPUTPM1_SENSOR 0x00000001 +#define CPUTPM1_TURBO 0x00000002 +#define CPUTPM1_ARAT 0x00000004 +#define CPUTPM2_EFFREQ 0x00000001 + +/* * Important bits in the AMD extended cpuid flags */ #define AMDID_SYSCALL 0x00000800 diff --git a/sys/i386/include/xen/hypercall.h b/sys/i386/include/xen/hypercall.h index b33626f..2631a9b 100644 --- a/sys/i386/include/xen/hypercall.h +++ b/sys/i386/include/xen/hypercall.h @@ -234,8 +234,9 @@ HYPERVISOR_memory_op( return _hypercall2(int, memory_op, cmd, arg); } +int HYPERVISOR_multicall(multicall_entry_t *, int); static inline int -HYPERVISOR_multicall( +_HYPERVISOR_multicall( void *call_list, int nr_calls) { return _hypercall2(int, multicall, call_list, nr_calls); diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index f8dc11c..8d37562 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -938,7 +938,7 @@ fpu_clean_state(void) * the x87 stack, but we don't care since we're about to call * fxrstor() anyway. */ - __asm __volatile("ffree %%st(7); fld %0" : : "m" (dummy_variable)); + __asm __volatile("ffree %%st(7); flds %0" : : "m" (dummy_variable)); } #endif /* CPU_ENABLE_SSE */ diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index ae4d520..b7fa7d1 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -204,6 +204,9 @@ legacy_pcib_is_host_bridge(int bus, int slot, int func, break; } break; + case 0x1A308086: + s = "Intel 82845 Host to PCI bridge"; + break; /* AMD -- vendor 0x1022 */ case 0x30001022: @@ -304,6 +307,8 @@ legacy_pcib_is_host_bridge(int bus, int slot, int func, case 0x00171166: /* FALLTHROUGH */ case 0x01011166: + case 0x01101166: + case 0x02251166: s = "ServerWorks host to PCI bridge(unknown chipset)"; *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); break; diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index c44bf18..7671dd9 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -1292,7 +1292,19 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) mclp->args[0] = va; mclp->args[1] = (uint32_t)(pa & 0xffffffff); mclp->args[2] = (uint32_t)(pa >> 32); +#if 0 mclp->args[3] = (*pte & PG_V) ? UVMF_INVLPG|UVMF_ALL : 0; +#else + /* + * Somehow we seem to be ending up with pages which are in + * the TLB in spite of not having PG_V set, resulting in + * pages newly loaded into the bufcache not showing up + * immediately (i.e., accessing them provides the old data). + * As a workaround, always perform a TLB flush, even if the + * old page didn't have PG_V. + */ + mclp->args[3] = UVMF_INVLPG|UVMF_ALL; +#endif va += PAGE_SIZE; pte++; diff --git a/sys/i386/xen/xen_machdep.c b/sys/i386/xen/xen_machdep.c index aaad5d4..a9180fc 100644 --- a/sys/i386/xen/xen_machdep.c +++ b/sys/i386/xen/xen_machdep.c @@ -482,7 +482,6 @@ xen_pt_pin(vm_paddr_t ma) struct mmuext_op op; op.cmd = MMUEXT_PIN_L1_TABLE; op.arg1.mfn = ma >> PAGE_SHIFT; - printk("xen_pt_pin(): mfn=%x\n", op.arg1.mfn); xen_flush_queue(); PANIC_IF(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } @@ -1178,6 +1177,27 @@ trap_info_t trap_table[] = { { 0, 0, 0, 0 } }; +/* Perform a multicall and check that individual calls succeeded. */ +int +HYPERVISOR_multicall(struct multicall_entry * call_list, int nr_calls) +{ + int ret = 0; + int i; + + /* Perform the multicall. */ + PANIC_IF(_HYPERVISOR_multicall(call_list, nr_calls)); + + /* Check the results of individual hypercalls. */ + for (i = 0; i < nr_calls; i++) + if (unlikely(call_list[i].result < 0)) + ret++; + if (unlikely(ret > 0)) + panic("%d multicall(s) failed: cpu %d\n", + ret, smp_processor_id()); + + /* If we didn't panic already, everything succeeded. */ + return (0); +} /********** CODE WORTH KEEPING ABOVE HERE *****************/ diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 2487b6b..bfa39f7 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -448,7 +448,7 @@ tc_windup(void) th->th_offset.sec++; } if ((delta > th->th_counter->tc_frequency / 2) && - (th->th_scale * delta < (uint64_t)1 << 63)) { + (th->th_scale * delta < ((uint64_t)1 << 63))) { /* The product th_scale * delta just barely overflows. */ th->th_offset.sec++; } diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index 49ddce2..20b6a0b 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -53,7 +53,6 @@ struct taskqueue_busy { struct taskqueue { STAILQ_HEAD(, task) tq_queue; - const char *tq_name; taskqueue_enqueue_fn tq_enqueue; void *tq_context; TAILQ_HEAD(, taskqueue_busy) tq_active; @@ -94,7 +93,7 @@ TQ_SLEEP(struct taskqueue *tq, void *p, struct mtx *m, int pri, const char *wm, } static struct taskqueue * -_taskqueue_create(const char *name, int mflags, +_taskqueue_create(const char *name __unused, int mflags, taskqueue_enqueue_fn enqueue, void *context, int mtxflags, const char *mtxname) { @@ -106,7 +105,6 @@ _taskqueue_create(const char *name, int mflags, STAILQ_INIT(&queue->tq_queue); TAILQ_INIT(&queue->tq_active); - queue->tq_name = name; queue->tq_enqueue = enqueue; queue->tq_context = context; queue->tq_spin = (mtxflags & MTX_SPIN) != 0; diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 83cbc60..4971a25 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -383,7 +383,8 @@ nmount(td, uap) * Filter out MNT_ROOTFS. We do not want clients of nmount() in * userspace to set this flag, but we must filter it out if we want * MNT_UPDATE on the root file system to work. - * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try(). + * MNT_ROOTFS should only be set by the kernel when mounting its + * root file system. */ uap->flags &= ~MNT_ROOTFS; @@ -720,7 +721,8 @@ mount(td, uap) * Filter out MNT_ROOTFS. We do not want clients of mount() in * userspace to set this flag, but we must filter it out if we want * MNT_UPDATE on the root file system to work. - * MNT_ROOTFS should only be set in the kernel in vfs_mountroot_try(). + * MNT_ROOTFS should only be set by the kernel when mounting its + * root file system. */ uap->flags &= ~MNT_ROOTFS; diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index b032513..8cff685 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -2186,7 +2186,7 @@ vputx(struct vnode *vp, int func) KASSERT(vp != NULL, ("vputx: null vp")); if (func == VPUTX_VUNREF) - ASSERT_VOP_ELOCKED(vp, "vunref"); + ASSERT_VOP_LOCKED(vp, "vunref"); else if (func == VPUTX_VPUT) ASSERT_VOP_LOCKED(vp, "vput"); else @@ -2224,12 +2224,22 @@ vputx(struct vnode *vp, int func) * as VI_DOINGINACT to avoid recursion. */ vp->v_iflag |= VI_OWEINACT; - if (func == VPUTX_VRELE) { + switch (func) { + case VPUTX_VRELE: error = vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK); VI_LOCK(vp); - } else if (func == VPUTX_VPUT && VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { - error = VOP_LOCK(vp, LK_UPGRADE | LK_INTERLOCK | LK_NOWAIT); - VI_LOCK(vp); + break; + case VPUTX_VPUT: + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { + error = VOP_LOCK(vp, LK_UPGRADE | LK_INTERLOCK | + LK_NOWAIT); + VI_LOCK(vp); + } + break; + case VPUTX_VUNREF: + if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) + error = EBUSY; + break; } if (vp->v_usecount > 0) vp->v_iflag &= ~VI_OWEINACT; diff --git a/sys/net/bpf_buffer.c b/sys/net/bpf_buffer.c index 8924c88..6920c70 100644 --- a/sys/net/bpf_buffer.c +++ b/sys/net/bpf_buffer.c @@ -88,10 +88,10 @@ __FBSDID("$FreeBSD$"); static int bpf_bufsize = 4096; SYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW, - &bpf_bufsize, 0, "Maximum capture buffer size in bytes"); + &bpf_bufsize, 0, "Default capture buffer size in bytes"); static int bpf_maxbufsize = BPF_MAXBUFSIZE; SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW, - &bpf_maxbufsize, 0, "Default capture buffer in bytes"); + &bpf_maxbufsize, 0, "Maximum capture buffer in bytes"); void bpf_buffer_alloc(struct bpf_d *d) diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 63fc026..4e24a5f 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -206,6 +206,11 @@ static void vlan_iflladdr(void *arg, struct ifnet *ifp); static struct if_clone vlan_cloner = IFC_CLONE_INITIALIZER(VLANNAME, NULL, IF_MAXUNIT, NULL, vlan_clone_match, vlan_clone_create, vlan_clone_destroy); +#ifdef VIMAGE +static VNET_DEFINE(struct if_clone, vlan_cloner); +#define V_vlan_cloner VNET(vlan_cloner) +#endif + #ifndef VLAN_ARRAY #define HASH(n, m) ((((n) >> 8) ^ ((n) >> 4) ^ (n)) & (m)) @@ -588,7 +593,9 @@ vlan_modevent(module_t mod, int type, void *data) vlan_input_p = vlan_input; vlan_link_state_p = vlan_link_state; vlan_trunk_cap_p = vlan_trunk_capabilities; +#ifndef VIMAGE if_clone_attach(&vlan_cloner); +#endif if (bootverbose) printf("vlan: initialized, using " #ifdef VLAN_ARRAY @@ -600,7 +607,9 @@ vlan_modevent(module_t mod, int type, void *data) "\n"); break; case MOD_UNLOAD: +#ifndef VIMAGE if_clone_detach(&vlan_cloner); +#endif EVENTHANDLER_DEREGISTER(ifnet_departure_event, ifdetach_tag); EVENTHANDLER_DEREGISTER(iflladdr_event, iflladdr_tag); vlan_input_p = NULL; @@ -625,6 +634,27 @@ static moduledata_t vlan_mod = { DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); MODULE_VERSION(if_vlan, 3); +#ifdef VIMAGE +static void +vnet_vlan_init(const void *unused __unused) +{ + + V_vlan_cloner = vlan_cloner; + if_clone_attach(&V_vlan_cloner); +} +VNET_SYSINIT(vnet_vlan_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, + vnet_vlan_init, NULL); + +static void +vnet_vlan_uninit(const void *unused __unused) +{ + + if_clone_detach(&V_vlan_cloner); +} +VNET_SYSUNINIT(vnet_vlan_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, + vnet_vlan_uninit, NULL); +#endif + static struct ifnet * vlan_clone_match_ethertag(struct if_clone *ifc, const char *name, int *tag) { @@ -1432,6 +1462,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSETVLAN: +#ifdef VIMAGE + if (ifp->if_vnet != ifp->if_home_vnet) { + error = EPERM; + break; + } +#endif error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); if (error) break; @@ -1461,6 +1497,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCGETVLAN: +#ifdef VIMAGE + if (ifp->if_vnet != ifp->if_home_vnet) { + error = EPERM; + break; + } +#endif bzero(&vlr, sizeof(vlr)); VLAN_LOCK(); if (TRUNK(ifv) != NULL) { diff --git a/sys/netgraph/ng_pipe.c b/sys/netgraph/ng_pipe.c index 77009bf..3efd6d9 100644 --- a/sys/netgraph/ng_pipe.c +++ b/sys/netgraph/ng_pipe.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004-2008 University of Zagreb + * Copyright (c) 2004-2010 University of Zagreb * Copyright (c) 2007-2008 FreeBSD Foundation * * This software was developed by the University of Zagreb and the @@ -62,8 +62,6 @@ static MALLOC_DEFINE(M_NG_PIPE, "ng_pipe", "ng_pipe"); -struct mtx ng_pipe_giant; - /* Packet header struct */ struct ngp_hdr { TAILQ_ENTRY(ngp_hdr) ngp_link; /* next pkt in queue */ @@ -88,7 +86,6 @@ struct hookinfo { int noqueue; /* bypass any processing */ TAILQ_HEAD(, ngp_fifo) fifo_head; /* FIFO queues */ TAILQ_HEAD(, ngp_hdr) qout_head; /* delay queue head */ - LIST_ENTRY(hookinfo) active_le; /* active hooks */ struct timeval qin_utime; struct ng_pipe_hookcfg cfg; struct ng_pipe_hookrun run; @@ -103,6 +100,8 @@ struct node_priv { u_int32_t header_offset; struct hookinfo lower; struct hookinfo upper; + struct callout timer; + int timer_scheduled; }; typedef struct node_priv *priv_p; @@ -131,17 +130,9 @@ typedef struct node_priv *priv_p; static void parse_cfg(struct ng_pipe_hookcfg *, struct ng_pipe_hookcfg *, struct hookinfo *, priv_p); static void pipe_dequeue(struct hookinfo *, struct timeval *); -static void pipe_scheduler(void *); -static void pipe_poll(void); +static void ngp_callout(node_p, hook_p, void *, int); static int ngp_modevent(module_t, int, void *); -/* linked list of active "pipe" hooks */ -static LIST_HEAD(, hookinfo) active_head; -static int active_gen_id = 0; - -/* timeout handle for pipe_scheduler */ -static struct callout polling_timer; - /* zone for storing ngp_hdr-s */ static uma_zone_t ngp_zone; @@ -267,6 +258,11 @@ ngp_constructor(node_p node) return (ENOMEM); NG_NODE_SET_PRIVATE(node, priv); + /* Mark node as single-threaded */ + NG_NODE_FORCE_WRITER(node); + + ng_callout_init(&priv->timer); + return (0); } @@ -310,8 +306,6 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) struct ng_pipe_cfg *cfg; int error = 0; - mtx_lock(&ng_pipe_giant); - NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_PIPE_COOKIE: @@ -326,7 +320,7 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) error = ENOMEM; break; } - stats = (struct ng_pipe_stats *)resp->data; + stats = (struct ng_pipe_stats *) resp->data; bcopy(&priv->upper.stats, &stats->downstream, sizeof(stats->downstream)); bcopy(&priv->lower.stats, &stats->upstream, @@ -345,7 +339,7 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) error = ENOMEM; break; } - run = (struct ng_pipe_run *)resp->data; + run = (struct ng_pipe_run *) resp->data; bcopy(&priv->upper.run, &run->downstream, sizeof(run->downstream)); bcopy(&priv->lower.run, &run->upstream, @@ -357,7 +351,7 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) error = ENOMEM; break; } - cfg = (struct ng_pipe_cfg *)resp->data; + cfg = (struct ng_pipe_cfg *) resp->data; bcopy(&priv->upper.cfg, &cfg->downstream, sizeof(cfg->downstream)); bcopy(&priv->lower.cfg, &cfg->upstream, @@ -374,7 +368,7 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) cfg->bandwidth = 0; break; case NGM_PIPE_SET_CFG: - cfg = (struct ng_pipe_cfg *)msg->data; + cfg = (struct ng_pipe_cfg *) msg->data; if (msg->header.arglen != sizeof(*cfg)) { error = EINVAL; break; @@ -401,7 +395,8 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) if (cfg->overhead == -1) priv->overhead = 0; - else if (cfg->overhead > 0 && cfg->overhead < 256) + else if (cfg->overhead > 0 && + cfg->overhead < MAX_OHSIZE) priv->overhead = cfg->overhead; if (cfg->header_offset == -1) @@ -411,9 +406,9 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) priv->header_offset = cfg->header_offset; parse_cfg(&priv->upper.cfg, &cfg->downstream, - &priv->upper, priv); + &priv->upper, priv); parse_cfg(&priv->lower.cfg, &cfg->upstream, - &priv->lower, priv); + &priv->lower, priv); break; default: error = EINVAL; @@ -427,8 +422,6 @@ ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) NG_RESPOND_MSG(error, node, item, resp); NG_FREE_MSG(msg); - mtx_unlock(&ng_pipe_giant); - return (error); } @@ -449,9 +442,9 @@ parse_cfg(struct ng_pipe_hookcfg *current, struct ng_pipe_hookcfg *new, uint32_t fsize, i; if (hinfo->ber_p == NULL) - hinfo->ber_p = malloc(\ - (MAX_FSIZE + MAX_OHSIZE)*sizeof(uint64_t), \ - M_NG_PIPE, M_NOWAIT); + hinfo->ber_p = + malloc((MAX_FSIZE + MAX_OHSIZE) * sizeof(uint64_t), + M_NG_PIPE, M_NOWAIT); current->ber = new->ber; /* @@ -467,10 +460,10 @@ parse_cfg(struct ng_pipe_hookcfg *current, struct ng_pipe_hookcfg *new, p = one; for (fsize = 0; fsize < MAX_FSIZE + MAX_OHSIZE; fsize++) { hinfo->ber_p[fsize] = p; - for (i=0; i<8; i++) - p = (p*(p0&0xffff)>>48) + \ - (p*((p0>>16)&0xffff)>>32) + \ - (p*(p0>>32)>>16); + for (i = 0; i < 8; i++) + p = (p * (p0 & 0xffff) >> 48) + + (p * ((p0 >> 16) & 0xffff) >> 32) + + (p * (p0 >> 32) >> 16); } } @@ -575,25 +568,42 @@ ngp_rcvdata(hook_p hook, item_p item) struct ngp_fifo *ngp_f = NULL, *ngp_f1; struct ngp_hdr *ngp_h = NULL; struct mbuf *m; - int hash; + int hash, plen; int error = 0; - if (hinfo->noqueue) { + /* + * Shortcut from inbound to outbound hook when neither of + * bandwidth, delay, BER or duplication probability is + * configured, nor we have queued frames to drain. + */ + if (hinfo->run.qin_frames == 0 && hinfo->run.qout_frames == 0 && + hinfo->noqueue) { struct hookinfo *dest; if (hinfo == &priv->lower) dest = &priv->upper; else dest = &priv->lower; + + /* Send the frame. */ + plen = NGI_M(item)->m_pkthdr.len; NG_FWD_ITEM_HOOK(error, item, dest->hook); - return error; + + /* Update stats. */ + if (error) { + hinfo->stats.out_disc_frames++; + hinfo->stats.out_disc_octets += plen; + } else { + hinfo->stats.fwd_frames++; + hinfo->stats.fwd_octets += plen; + } + + return (error); } - mtx_lock(&ng_pipe_giant); microuptime(now); /* - * Attach us to the list of active ng_pipes if this was an empty - * one before, and also update the queue service deadline time. + * If this was an empty queue, update service deadline time. */ if (hinfo->run.qin_frames == 0) { struct timeval *when = &hinfo->qin_utime; @@ -602,8 +612,6 @@ ngp_rcvdata(hook_p hook, item_p item) when->tv_sec = now->tv_sec; when->tv_usec = now->tv_usec; } - if (hinfo->run.qout_frames == 0) - LIST_INSERT_HEAD(&active_head, hinfo, active_le); } /* Populate the packet header */ @@ -702,9 +710,7 @@ ngp_rcvdata(hook_p hook, item_p item) } /* - * Try to start the dequeuing process immediately. We must - * hold the ng_pipe_giant lock here and pipe_dequeue() will - * release it + * Try to start the dequeuing process immediately. */ pipe_dequeue(hinfo, now); @@ -720,27 +726,21 @@ ngp_rcvdata(hook_p hook, item_p item) * to outbound (delay) queue; * 4) Loop to 2) until bandwidth quota for this timeslice is reached, or * inbound queue is flushed completely; - * 5) Extract the first frame from the outbound queue, if it's time has - * come. Queue the frame for transmission on the outbound hook; - * 6) Loop to 5) until outbound queue is flushed completely, or the next - * frame in the queue is not scheduled to be dequeued yet; - * 7) Transimit all frames queued in 5) - * - * Note: the caller must hold the ng_pipe_giant lock; this function - * returns with the lock released. + * 5) Dequeue frames from the outbound queue and send them downstream until + * outbound queue is flushed completely, or the next frame in the queue + * is not due to be dequeued yet */ static void pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { static uint64_t rand, oldrand; - const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hinfo->hook)); + const node_p node = NG_HOOK_NODE(hinfo->hook); + const priv_p priv = NG_NODE_PRIVATE(node); struct hookinfo *dest; struct ngp_fifo *ngp_f, *ngp_f1; struct ngp_hdr *ngp_h; struct timeval *when; - struct mbuf *q_head = NULL; - struct mbuf *q_tail = NULL; struct mbuf *m; - int error = 0; + int plen, error = 0; /* Which one is the destination hook? */ if (hinfo == &priv->lower) @@ -791,13 +791,13 @@ pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { /* Calculate the serialization delay */ if (hinfo->cfg.bandwidth) { - hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len - + priv->overhead ) * - 8000000 / hinfo->cfg.bandwidth; + hinfo->qin_utime.tv_usec += + ((uint64_t) m->m_pkthdr.len + priv->overhead ) * + 8000000 / hinfo->cfg.bandwidth; hinfo->qin_utime.tv_sec += - hinfo->qin_utime.tv_usec / 1000000; + hinfo->qin_utime.tv_usec / 1000000; hinfo->qin_utime.tv_usec = - hinfo->qin_utime.tv_usec % 1000000; + hinfo->qin_utime.tv_usec % 1000000; } when = &ngp_h->when; when->tv_sec = hinfo->qin_utime.tv_sec; @@ -853,95 +853,57 @@ pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { /* Delay queue processing */ while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { - struct mbuf *m = ngp_h->m; - when = &ngp_h->when; + m = ngp_h->m; if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec && when->tv_usec > now->tv_usec)) break; /* Update outbound queue stats */ - hinfo->stats.fwd_frames++; - hinfo->stats.fwd_octets += m->m_pkthdr.len; + plen = m->m_pkthdr.len; hinfo->run.qout_frames--; - hinfo->run.qout_octets -= m->m_pkthdr.len; + hinfo->run.qout_octets -= plen; /* Dequeue the packet from qout */ TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); uma_zfree(ngp_zone, ngp_h); - /* Enqueue locally for sending downstream */ - if (q_head == NULL) - q_head = m; - if (q_tail) - q_tail->m_nextpkt = m; - q_tail = m; - m->m_nextpkt = NULL; - } - - /* If both queues are empty detach us from the list of active queues */ - if (hinfo->run.qin_frames + hinfo->run.qout_frames == 0) { - LIST_REMOVE(hinfo, active_le); - active_gen_id++; + NG_SEND_DATA(error, dest->hook, m, meta); + if (error) { + hinfo->stats.out_disc_frames++; + hinfo->stats.out_disc_octets += plen; + } else { + hinfo->stats.fwd_frames++; + hinfo->stats.fwd_octets += plen; + } } - mtx_unlock(&ng_pipe_giant); - - while ((m = q_head) != NULL) { - q_head = m->m_nextpkt; - m->m_nextpkt = NULL; - NG_SEND_DATA(error, dest->hook, m, meta); + if ((hinfo->run.qin_frames != 0 || hinfo->run.qout_frames != 0) && + !priv->timer_scheduled) { + ng_callout(&priv->timer, node, NULL, 1, ngp_callout, NULL, 0); + priv->timer_scheduled = 1; } } - /* - * This routine is called on every clock tick. We poll all nodes/hooks + * This routine is called on every clock tick. We poll connected hooks * for queued frames by calling pipe_dequeue(). */ static void -pipe_scheduler(void *arg) +ngp_callout(node_p node, hook_p hook, void *arg1, int arg2) { - pipe_poll(); - - /* Reschedule */ - callout_reset(&polling_timer, 1, &pipe_scheduler, NULL); -} - - -/* - * Traverse the list of all active hooks and attempt to dequeue - * some packets. Hooks with empty queues are not traversed since - * they are not linked into this list. - */ -static void -pipe_poll(void) -{ - struct hookinfo *hinfo; + const priv_p priv = NG_NODE_PRIVATE(node); struct timeval now; - int old_gen_id = active_gen_id; - - mtx_lock(&ng_pipe_giant); + + priv->timer_scheduled = 0; microuptime(&now); - LIST_FOREACH(hinfo, &active_head, active_le) { - CURVNET_SET(NG_HOOK_NODE(hinfo->hook)->nd_vnet); - pipe_dequeue(hinfo, &now); - CURVNET_RESTORE(); - mtx_lock(&ng_pipe_giant); - if (old_gen_id != active_gen_id) { - /* the list was updated; restart traversing */ - hinfo = LIST_FIRST(&active_head); - if (hinfo == NULL) - break; - old_gen_id = active_gen_id; - continue; - } - } - mtx_unlock(&ng_pipe_giant); + if (priv->upper.hook != NULL) + pipe_dequeue(&priv->upper, &now); + if (priv->lower.hook != NULL) + pipe_dequeue(&priv->lower, &now); } - /* * Shutdown processing * @@ -955,6 +917,8 @@ ngp_shutdown(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); + if (priv->timer_scheduled) + ng_uncallout(&priv->timer, node); if (priv->lower.hook && priv->upper.hook) ng_bypass(priv->lower.hook, priv->upper.hook); else { @@ -978,9 +942,6 @@ ngp_disconnect(hook_p hook) struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook); struct ngp_fifo *ngp_f; struct ngp_hdr *ngp_h; - int removed = 0; - - mtx_lock(&ng_pipe_giant); KASSERT(hinfo != NULL, ("%s: null info", __FUNCTION__)); hinfo->hook = NULL; @@ -991,7 +952,6 @@ ngp_disconnect(hook_p hook) TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); m_freem(ngp_h->m); uma_zfree(ngp_zone, ngp_h); - removed++; } TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); uma_zfree(ngp_zone, ngp_f); @@ -1002,27 +962,12 @@ ngp_disconnect(hook_p hook) TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); m_freem(ngp_h->m); uma_zfree(ngp_zone, ngp_h); - removed++; } - /* - * Both queues should be empty by now, so detach us from - * the list of active queues - */ - if (removed) { - LIST_REMOVE(hinfo, active_le); - active_gen_id++; - } - if (hinfo->run.qin_frames + hinfo->run.qout_frames != removed) - printf("Mismatch: queued=%d but removed=%d !?!", - hinfo->run.qin_frames + hinfo->run.qout_frames, removed); - /* Release the packet loss probability table (BER) */ if (hinfo->ber_p) free(hinfo->ber_p, M_NG_PIPE); - mtx_unlock(&ng_pipe_giant); - return (0); } @@ -1038,16 +983,9 @@ ngp_modevent(module_t mod, int type, void *unused) UMA_ALIGN_PTR, 0); if (ngp_zone == NULL) panic("ng_pipe: couldn't allocate descriptor zone"); - - mtx_init(&ng_pipe_giant, "ng_pipe_giant", NULL, MTX_DEF); - LIST_INIT(&active_head); - callout_init(&polling_timer, CALLOUT_MPSAFE); - callout_reset(&polling_timer, 1, &pipe_scheduler, NULL); break; case MOD_UNLOAD: - callout_drain(&polling_timer); uma_zdestroy(ngp_zone); - mtx_destroy(&ng_pipe_giant); break; default: error = EOPNOTSUPP; diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index d2d99b9..1354d5e 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -218,7 +218,7 @@ static void carp_set_state(struct carp_softc *, int); static int carp_addrcount(struct carp_if *, struct in_ifaddr *, int); enum { CARP_COUNT_MASTER, CARP_COUNT_RUNNING }; -static void carp_multicast_cleanup(struct carp_softc *); +static void carp_multicast_cleanup(struct carp_softc *, int dofree); static int carp_set_addr(struct carp_softc *, struct sockaddr_in *); static int carp_del_addr(struct carp_softc *, struct sockaddr_in *); static void carp_carpdev_state_locked(struct carp_if *); @@ -227,7 +227,7 @@ static void carp_sc_state_locked(struct carp_softc *); static void carp_send_na(struct carp_softc *); static int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); static int carp_del_addr6(struct carp_softc *, struct sockaddr_in6 *); -static void carp_multicast6_cleanup(struct carp_softc *); +static void carp_multicast6_cleanup(struct carp_softc *, int dofree); #endif static LIST_HEAD(, carp_softc) carpif_list; @@ -466,9 +466,11 @@ carp_clone_destroy(struct ifnet *ifp) /* * This function can be called on CARP interface destroy path, * and in case of the removal of the underlying interface as - * well. We differentiate these two cases. In the latter case - * we do not cleanup our multicast memberships, since they - * are already freed. Also, in the latter case we do not + * well. We differentiate these two cases: in case of destruction + * of the underlying interface, we do not cleanup our multicast + * memberships, since they are already freed. But we purge pointers + * to multicast structures, since they are no longer valid, to + * avoid panic in future calls to carpdetach(). Also, we do not * release the lock on return, because the function will be * called once more, for another CARP instance on the same * interface. @@ -493,10 +495,9 @@ carpdetach(struct carp_softc *sc, int unlock) carp_set_state(sc, INIT); SC2IFP(sc)->if_flags &= ~IFF_UP; carp_setrun(sc, 0); - if (unlock) - carp_multicast_cleanup(sc); + carp_multicast_cleanup(sc, unlock); #ifdef INET6 - carp_multicast6_cleanup(sc); + carp_multicast6_cleanup(sc, unlock); #endif if (sc->sc_carpdev != NULL) { @@ -1444,7 +1445,7 @@ carp_setrun(struct carp_softc *sc, sa_family_t af) } static void -carp_multicast_cleanup(struct carp_softc *sc) +carp_multicast_cleanup(struct carp_softc *sc, int dofree) { struct ip_moptions *imo = &sc->sc_imo; u_int16_t n = imo->imo_num_memberships; @@ -1452,7 +1453,8 @@ carp_multicast_cleanup(struct carp_softc *sc) /* Clean up our own multicast memberships */ while (n-- > 0) { if (imo->imo_membership[n] != NULL) { - in_delmulti(imo->imo_membership[n]); + if (dofree) + in_delmulti(imo->imo_membership[n]); imo->imo_membership[n] = NULL; } } @@ -1464,14 +1466,15 @@ carp_multicast_cleanup(struct carp_softc *sc) #ifdef INET6 static void -carp_multicast6_cleanup(struct carp_softc *sc) +carp_multicast6_cleanup(struct carp_softc *sc, int dofree) { struct ip6_moptions *im6o = &sc->sc_im6o; u_int16_t n = im6o->im6o_num_memberships; while (n-- > 0) { if (im6o->im6o_membership[n] != NULL) { - in6_mc_leave(im6o->im6o_membership[n], NULL); + if (dofree) + in6_mc_leave(im6o->im6o_membership[n], NULL); im6o->im6o_membership[n] = NULL; } } @@ -1831,7 +1834,7 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) cleanup: if (!sc->sc_naddrs6) - carp_multicast6_cleanup(sc); + carp_multicast6_cleanup(sc, 1); ifa_free(&ia->ia_ifa); return (error); } @@ -1849,7 +1852,7 @@ carp_del_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) SC2IFP(sc)->if_flags &= ~IFF_UP; SC2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING; sc->sc_vhid = -1; - carp_multicast6_cleanup(sc); + carp_multicast6_cleanup(sc, 1); TAILQ_REMOVE(&cif->vhif_vrs, sc, sc_list); if (!--cif->vhif_nvrs) { CARP_LOCK_DESTROY(cif); diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c index e40639b..b7b4118 100644 --- a/sys/netinet/sctp_cc_functions.c +++ b/sys/netinet/sctp_cc_functions.c @@ -42,6 +42,7 @@ #include <netinet/sctp_auth.h> #include <netinet/sctp_asconf.h> #include <netinet/sctp_cc_functions.h> +#include <netinet/sctp_dtrace_declare.h> #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -63,6 +64,9 @@ sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net) net->cwnd = (net->mtu - sizeof(struct sctphdr)) * cwnd_in_mtu; net->ssthresh = assoc->peers_rwnd; + SDT_PROBE(sctp, cwnd, net, init, + stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, + 0, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) { sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION); @@ -98,6 +102,9 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, net->ssthresh = 2 * net->mtu; } net->cwnd = net->ssthresh; + SDT_PROBE(sctp, cwnd, net, fr, + stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_FR); @@ -155,6 +162,7 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb, int accum_moved, int reneged_all, int will_exit) { struct sctp_nets *net; + int old_cwnd; /******************************/ /* update cwnd and Early FR */ @@ -246,7 +254,11 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb, (asoc->sctp_cmt_pf > 0) && ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) { net->dest_state &= ~SCTP_ADDR_PF; + old_cwnd = net->cwnd; net->cwnd = net->mtu * asoc->sctp_cmt_pf; + SDT_PROBE(sctp, cwnd, net, ack, + stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, + old_cwnd, net->cwnd); SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n", net, net->cwnd); /* @@ -290,13 +302,26 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb, /* We are in slow start */ if (net->flight_size + net->net_ack >= net->cwnd) { if (net->net_ack > (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable))) { + old_cwnd = net->cwnd; net->cwnd += (net->mtu * SCTP_BASE_SYSCTL(sctp_L2_abc_variable)); + SDT_PROBE(sctp, cwnd, net, ack, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, net->mtu, SCTP_CWND_LOG_FROM_SS); } } else { + old_cwnd = net->cwnd; net->cwnd += net->net_ack; + SDT_PROBE(sctp, cwnd, net, ack, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, net->net_ack, SCTP_CWND_LOG_FROM_SS); @@ -318,7 +343,13 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb, if ((net->flight_size + net->net_ack >= net->cwnd) && (net->partial_bytes_acked >= net->cwnd)) { net->partial_bytes_acked -= net->cwnd; + old_cwnd = net->cwnd; net->cwnd += net->mtu; + SDT_PROBE(sctp, cwnd, net, ack, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, net->mtu, SCTP_CWND_LOG_FROM_CA); @@ -364,7 +395,11 @@ sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net) net->ssthresh = max(net->cwnd / 2, 4 * net->mtu); net->cwnd = net->mtu; net->partial_bytes_acked = 0; - + SDT_PROBE(sctp, cwnd, net, to, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, net->cwnd - old_cwnd, SCTP_CWND_LOG_FROM_RTX); } @@ -383,6 +418,11 @@ sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net) net->RTO <<= 1; } net->cwnd = net->ssthresh; + SDT_PROBE(sctp, cwnd, net, ecn, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT); } @@ -492,6 +532,11 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb, } if (net->cwnd - old_cwnd != 0) { /* log only changes */ + SDT_PROBE(sctp, cwnd, net, pd, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_SAT); @@ -508,7 +553,11 @@ sctp_cwnd_update_after_output(struct sctp_tcb *stcb, if (net->ssthresh < net->cwnd) net->ssthresh = net->cwnd; net->cwnd = (net->flight_size + (burst_limit * net->mtu)); - + SDT_PROBE(sctp, cwnd, net, bl, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, (net->cwnd - old_cwnd), SCTP_CWND_LOG_FROM_BRST); } @@ -530,6 +579,11 @@ sctp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp, if (net->cwnd < net->ssthresh) /* still in SS move to CA */ net->ssthresh = net->cwnd - 1; + SDT_PROBE(sctp, cwnd, net, fr, + stcb->asoc.my_vtag, + ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), + net, + old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { sctp_log_cwnd(stcb, net, (old_cwnd - net->cwnd), SCTP_CWND_LOG_FROM_FR); } diff --git a/sys/netinet/sctp_dtrace_declare.h b/sys/netinet/sctp_dtrace_declare.h new file mode 100644 index 0000000..76e63d5 --- /dev/null +++ b/sys/netinet/sctp_dtrace_declare.h @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2010, by Randall Stewart & Michael Tuexen, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * a) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * b) Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * c) Neither the name of Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#ifndef __sctp_dtrace_declare_h__ +#include "opt_kdtrace.h" +#include <sys/kernel.h> +#include <sys/sdt.h> + +/* Declare the SCTP provider */ +SDT_PROVIDER_DECLARE(sctp); + +/* The probes we have so far: */ + +/* One to track a net's cwnd */ +/* initial */ +SDT_PROBE_DECLARE(sctp, cwnd, net, init); +/* update at a ack -- increase */ +SDT_PROBE_DECLARE(sctp, cwnd, net, ack); +/* update at a fast retransmit -- decrease */ +SDT_PROBE_DECLARE(sctp, cwnd, net, fr); +/* update at a time-out -- decrease */ +SDT_PROBE_DECLARE(sctp, cwnd, net, to); +/* update at a burst-limit -- decrease */ +SDT_PROBE_DECLARE(sctp, cwnd, net, bl); +/* update at a ECN -- decrease */ +SDT_PROBE_DECLARE(sctp, cwnd, net, ecn); +/* update at a Packet-Drop -- decrease */ +SDT_PROBE_DECLARE(sctp, cwnd, net, pd); + +/* One to track an associations rwnd */ +SDT_PROBE_DECLARE(sctp, rwnd, assoc, val); + +/* One to track a net's flight size */ +SDT_PROBE_DECLARE(sctp, flightsize, net, val); + +/* One to track an associations flight size */ +SDT_PROBE_DECLARE(sctp, flightsize, assoc, val); + + + + + + +#endif diff --git a/sys/netinet/sctp_dtrace_define.h b/sys/netinet/sctp_dtrace_define.h new file mode 100644 index 0000000..3c74fc5 --- /dev/null +++ b/sys/netinet/sctp_dtrace_define.h @@ -0,0 +1,201 @@ +/*- + * Copyright (c) 2010, by Randall Stewart & Michael Tuexen, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * a) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * b) Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + * + * c) Neither the name of Cisco Systems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#ifndef __sctp_dtrace_define_h__ +#include "opt_kdtrace.h" +#include <sys/kernel.h> +#include <sys/sdt.h> + +SDT_PROVIDER_DEFINE(sctp); + +/********************************************************/ +/* Cwnd probe - tracks changes in the congestion window on a netp */ +/********************************************************/ +/* Initial */ +SDT_PROBE_DEFINE(sctp, cwnd, net, init, init); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 2, "uintptr_t"); +/* The old value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 4, "int"); + + +/* ACK-INCREASE */ +SDT_PROBE_DEFINE(sctp, cwnd, net, ack, ack); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 2, "uintptr_t"); +/* The old value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 4, "int"); + +/* FastRetransmit-DECREASE */ +SDT_PROBE_DEFINE(sctp, cwnd, net, fr, fr); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 2, "uintptr_t"); +/* The old value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 4, "int"); + + +/* TimeOut-DECREASE */ +SDT_PROBE_DEFINE(sctp, cwnd, net, to, to); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 2, "uintptr_t"); +/* The old value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 4, "int"); + + +/* BurstLimit-DECREASE */ +SDT_PROBE_DEFINE(sctp, cwnd, net, bl, bl); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 2, "uintptr_t"); +/* The old value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 4, "int"); + + +/* ECN-DECREASE */ +SDT_PROBE_DEFINE(sctp, cwnd, net, ecn, ecn); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 2, "uintptr_t"); +/* The old value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 4, "int"); + + +/* PacketDrop-DECREASE */ +SDT_PROBE_DEFINE(sctp, cwnd, net, pd, pd); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 2, "uintptr_t"); +/* The old value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 4, "int"); + + + +/********************************************************/ +/* Rwnd probe - tracks changes in the receiver window for an assoc */ +/********************************************************/ +SDT_PROBE_DEFINE(sctp, rwnd, assoc, val, val); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 1, "uint32_t"); +/* The up/down amount */ +SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 2, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 3, "int"); + +/********************************************************/ +/* flight probe - tracks changes in the flight size on a net or assoc */ +/********************************************************/ +SDT_PROBE_DEFINE(sctp, flightsize, net, val, val); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 1, "uint32_t"); +/* The pointer to the struct sctp_nets * changing */ +SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 2, "uintptr_t"); +/* The up/down amount */ +SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 3, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 4, "int"); +/********************************************************/ +/* The total flight version */ +/********************************************************/ +SDT_PROBE_DEFINE(sctp, flightsize, assoc, val, val); +/* The Vtag for this end */ +SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 0, "uint32_t"); +/* The port number of the local side << 16 | port number of remote + * in network byte order. + */ +SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 1, "uint32_t"); +/* The up/down amount */ +SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 2, "int"); +/* The new value of the cwnd */ +SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 3, "int"); + +#endif diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index aaa0500..949121e 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_output.h> #include <netinet/sctp_timer.h> #include <netinet/sctp_bsd_addr.h> +#include <netinet/sctp_dtrace_define.h> #include <netinet/udp.h> diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index 1cb62f3..8109f0f 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -942,7 +942,7 @@ struct sctpstat { uint32_t sctps_wu_sacks_sent; /* Window Update only sacks sent */ uint32_t sctps_sends_with_flags; /* number of sends with * sinfo_flags !=0 */ - uint32_t sctps_sends_with_unord; /* number of unordered sends */ + uint32_t sctps_sends_with_unord; /* number of unordered sends */ uint32_t sctps_sends_with_eof; /* number of sends with EOF flag set */ uint32_t sctps_sends_with_abort; /* number of sends with ABORT * flag set */ diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index afb7f76..568d15f 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -325,6 +325,7 @@ typedef struct { #define PT_LOOS 0x60000000 /* First OS-specific. */ #define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ #define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 #define PT_LOSUNW 0x6ffffffa #define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ #define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index fbfd6e8..10256c5 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -452,6 +452,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); { "logsigexit", CTLTYPE_INT }, \ { "iov_max", CTLTYPE_INT }, \ { "hostuuid", CTLTYPE_STRING }, \ + { "arc4rand", CTLTYPE_OPAQUE }, \ } /* diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index ecbef05..94a96bd 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -821,9 +821,11 @@ rescan: np = TAILQ_NEXT(p, listq); if (p->valid == 0) continue; - while (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) { + if (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) { if (object->generation != curgeneration) goto rescan; + np = vm_page_find_least(object, pi); + continue; } vm_page_test_dirty(p); if (p->dirty == 0) diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c index 7f8e583..d6da578 100644 --- a/sys/x86/x86/local_apic.c +++ b/sys/x86/x86/local_apic.c @@ -251,7 +251,7 @@ lapic_init(vm_paddr_t addr) /* Intel CPUID 0x06 EAX[2] set if APIC timer runs in C3. */ if (cpu_vendor_id == CPU_VENDOR_INTEL && cpu_high >= 6) { do_cpuid(0x06, regs); - if (regs[0] & 0x4) + if ((regs[0] & CPUTPM1_ARAT) != 0) arat = 1; } bzero(&lapic_et, sizeof(lapic_et)); diff --git a/tools/tools/sysbuild/sysbuild.sh b/tools/tools/sysbuild/sysbuild.sh index 07a26f2..b269da1 100644 --- a/tools/tools/sysbuild/sysbuild.sh +++ b/tools/tools/sysbuild/sysbuild.sh @@ -163,29 +163,47 @@ log_it() ( ports_recurse() ( set +x + t=$1 + shift + if [ "x$t" = "x." ] ; then + true > /tmp/_.plist + true > /tmp/_.plist.tdone + echo 'digraph {' > /tmp/_.plist.dot + fi + if grep -q "^$t\$" /tmp/_.plist.tdone ; then + return + fi + echo "$t" >> /tmp/_.plist.tdone for d do if [ ! -d $d ] ; then echo "Missing port $d" 1>&2 exit 2 fi + if [ "x$t" != "x." ] ; then + echo "\"$t\" -> \"$d\"" >> /tmp/_.plist.dot + fi if grep -q "^$d\$" /tmp/_.plist ; then true + elif grep -q "^$d\$" /tmp/_.plist.tdone ; then + true else ( cd $d - ports_recurse `make -V _DEPEND_DIRS ${PORTS_OPTS}` + ports_recurse $d `make -V _DEPEND_DIRS ${PORTS_OPTS}` ) - echo $d >> /tmp/_.plist + echo "$d" >> /tmp/_.plist fi done + if [ "x$t" = "x." ] ; then + echo '}' >> /tmp/_.plist.dot + fi ) ports_build() ( set +x - true > /tmp/_.plist - ports_recurse $PORTS_WE_WANT + ports_recurse . $PORTS_WE_WANT # Now build & install them for p in `cat /tmp/_.plist` @@ -226,22 +244,31 @@ ports_build() ( ports_prefetch() ( ( set +x - true > /tmp/_.plist - ports_recurse $PORTS_WE_WANT - true > /mnt/_.prefetch + echo "Building /tmp/_.plist" >> /mnt/_.prefetch + + ports_recurse . $PORTS_WE_WANT + + echo "Completed /tmp/_.plist" >> /mnt/_.prefetch # Now checksump/fetch them for p in `cat /tmp/_.plist` do - echo "Prefetching $p" >> /mnt/_.prefetch b=`echo $p | tr / _` ( cd $p if make checksum $PORTS_OPTS ; then - true + rm -f /mnt/_.prefetch.$b + echo "OK $p" >> /mnt/_.prefetch + exit 0 + fi + make distclean + make checksum $PORTS_OPTS || true + + if make checksum $PORTS_OPTS > /dev/null 2>&1 ; then + rm -f /mnt/_.prefetch.$b + echo "OK $p" >> /mnt/_.prefetch else - make distclean - make checksum $PORTS_OPTS || true + echo "BAD $p" >> /mnt/_.prefetch fi ) > /mnt/_.prefetch.$b 2>&1 done @@ -411,7 +438,7 @@ if [ "x${REMOTEDISTFILES}" != "x" ] ; then fi log_it copy ports config files -(cd / ; find var/db/ports -print | cpio -dumpv /mnt ) +(cd / ; find var/db/ports -print | cpio -dumpv /mnt > /dev/null 2>&1) log_it "Start prefetch of ports distfiles" ports_prefetch & diff --git a/usr.bin/locate/locate/locate.h b/usr.bin/locate/locate/locate.h index 24df8d4..c2f27fb 100644 --- a/usr.bin/locate/locate/locate.h +++ b/usr.bin/locate/locate/locate.h @@ -48,15 +48,15 @@ #define LDC_MAX 28 /* 128-255 bigram codes (128 most common, as determined by 'updatedb') */ -#define BIGRAM_MIN (UCHAR_MAX - CHAR_MAX) +#define BIGRAM_MIN (UCHAR_MAX - SCHAR_MAX) #define BIGRAM_MAX UCHAR_MAX /* 32-127 single character (printable) ascii residue (ie, literal) */ #define ASCII_MIN 32 -#define ASCII_MAX CHAR_MAX +#define ASCII_MAX SCHAR_MAX -/* #define TO7BIT(x) (x = ( ((u_char)x) & CHAR_MAX )) */ -#define TO7BIT(x) (x = x & CHAR_MAX ) +/* #define TO7BIT(x) (x = ( ((u_char)x) & SCHAR_MAX )) */ +#define TO7BIT(x) (x = x & SCHAR_MAX ) #if UCHAR_MAX >= 4096 diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c index 01a0242..07be206 100644 --- a/usr.bin/netstat/inet.c +++ b/usr.bin/netstat/inet.c @@ -428,13 +428,14 @@ protopr(u_long off, const char *name, int af1, int proto) "2msl", "delack", "rcvtime", "(state)"); } - if (!xflag && !Tflag) + if (!xflag && !Tflag) { printf((Aflag && !Wflag) ? "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s" : "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s", "Proto", "Recv-Q", "Send-Q", "Local Address", "Foreign Address"); - + printf("(state)\n"); + } first = 0; } if (Lflag && so->so_qlimit == 0) diff --git a/usr.sbin/iostat/iostat.8 b/usr.sbin/iostat/iostat.8 index 69fadcf..aab668a 100644 --- a/usr.sbin/iostat/iostat.8 +++ b/usr.sbin/iostat/iostat.8 @@ -60,7 +60,7 @@ .\" .\" @(#)iostat.8 8.1 (Berkeley) 6/6/93 .\" -.Dd April 17, 2006 +.Dd November 24, 2010 .Dt IOSTAT 8 .Os .Sh NAME @@ -102,11 +102,18 @@ Repeat the display times. If no repeat .Ar count -is specified, the default is infinity. +is specified, the default depends on whether +.Fl w +is specified. +With +.Fl w +the default repeat count is infinity, otherwise it is 1. .It Fl C Display CPU statistics. This is on by default, unless .Fl d +or +.Fl x is specified. .It Fl d Display only device statistics. @@ -231,6 +238,8 @@ output, up to the number of devices that can be displayed in Display TTY statistics. This is on by default, unless .Fl d +or +.Fl x is specified. .It Fl w Pause @@ -255,6 +264,11 @@ so your mileage may vary. .It Fl x Show extended disk statistics. Each disk is displayed on a line of its own with all available statistics. +If this flag is turned on, only disk statistics will be displayed, unless +.Fl C +or +.Fl T +is also specified to enable the display of CPU or TTY statistics. .It Fl z If .Fl x diff --git a/usr.sbin/kernbb/Makefile b/usr.sbin/kernbb/Makefile deleted file mode 100644 index f3bf37c..0000000 --- a/usr.sbin/kernbb/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $FreeBSD$ - -PROG= kernbb -MAN= kernbb.8 - -DPADD= ${LIBKVM} -LDADD= -lkvm - -CFLAGS+= -I${.CURDIR}/../../contrib/gcc - -.include <bsd.prog.mk> - diff --git a/usr.sbin/kernbb/kernbb.8 b/usr.sbin/kernbb/kernbb.8 deleted file mode 100644 index 3d6fe02..0000000 --- a/usr.sbin/kernbb/kernbb.8 +++ /dev/null @@ -1,82 +0,0 @@ -.\" Copyright (c) 1983, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd May 22, 1995 -.Dt KERNBB 8 -.Os -.Sh NAME -.Nm kernbb -.Nd generate a dump of the kernels basic-block profile buffers -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -The -.Nm -utility is used to extract the basic-block profiling buffers of the running -kernel into the files needed for the -.Xr gcov 1 -tool. -.Pp -At least one source file in the running kernel must have been compiled -with the -.Fl Fl test-coverage -and -.Fl Fl profile-arcs -options. -.Pp -The output is stored in the filenames compiled into the kernel by -.Xr gcc 1 . -If the absolute pathname cannot be written to, the directory part -of the filename is discarded and the file stored in the current -directory under its basename. -.Pp -The output files are named -.Pa *.da , -and the -.Xr gcov 1 -program will extract the counts and merge them with the source -file to show actual execution counts. -.Sh FILES -.Bl -tag -width /boot/kernel/kernel -compact -.It Pa /boot/kernel/kernel -the default system -.It Pa /dev/kmem -the default memory -.El -.Sh SEE ALSO -.Xr cc 1 , -.Xr gcov 1 -.Sh AUTHORS -The -.Nm -utility was written by -.An Poul-Henning Kamp , -along with the kernel-support. -.Sh BUGS -There are far too much magic and internal knowledge from GCC in this. diff --git a/usr.sbin/kernbb/kernbb.c b/usr.sbin/kernbb/kernbb.c deleted file mode 100644 index 1ecd5ad..0000000 --- a/usr.sbin/kernbb/kernbb.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <err.h> -#include <fcntl.h> -#include <kvm.h> -#include <nlist.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/endian.h> - -typedef long long gcov_type; - -#define PARAMS(foo) foo -#define ATTRIBUTE_UNUSED __unused -#include "gcov-io.h" - -struct bbf { - long checksum; - int arc_count; - u_long name; -}; - -struct bb { - u_long zero_one; - u_long filename; - u_long counts; - u_long ncounts; - u_long next; - u_long sizeof_bb; - u_long funcs; -}; - -struct nlist namelist[] = { - { "bbhead", 0, 0, 0, 0 }, - { NULL, 0, 0, 0, 0 } -}; - -kvm_t *kv; - -int -main(int argc __unused, char **argv __unused) -{ - int i, funcs; - u_long l1,l2,l4; - struct bb bb; - struct bbf bbf; - char buf[BUFSIZ], *p; - gcov_type *q, *qr; - - FILE *f; - - kv = kvm_open(NULL,NULL,NULL,O_RDWR,"dnc"); - if (!kv) - err(1,"kvm_open"); - i = kvm_nlist(kv,namelist); - if (i) - err(1,"kvm_nlist"); - - l1 = namelist[0].n_value; - kvm_read(kv,l1,&l2,sizeof l2); - while(l2) { - l1 += sizeof l1; - kvm_read(kv,l2,&bb,sizeof bb); -#if 0 -printf("%lx\n%lx\n%lx\n%lx\n%lx\n%lx\n%lx\n", - bb.zero_one, bb.filename, bb.counts, bb.ncounts, bb.next, - bb.sizeof_bb, bb.funcs); -#endif - - funcs = 0; - for (l4 = bb.funcs; ; l4 += sizeof (bbf)) { - kvm_read(kv, l4, &bbf, sizeof(bbf)); - if (bbf.arc_count == -1) - break; - funcs++; - } - - l2 = bb.next; - - kvm_read(kv, bb.filename, buf, sizeof(buf)); - p = buf; - f = fopen(p, "w"); - if (f != NULL) { - printf("Writing \"%s\"\n", p); - } else { - p = strrchr(buf, '/'); - if (p == NULL) - p = buf; - else - p++; - printf("Writing \"%s\" (spec \"%s\")\n", p, buf); - f = fopen(p, "w"); - } - if (f == NULL) - err(1,"%s", p); - __write_long(-123, f, 4); - - __write_long(funcs, f, 4); - - __write_long(4 + 8 + 8 + 4 + 8 + 8, f, 4); - - __write_long(bb.ncounts, f, 4); - __write_long(0, f, 8); - __write_long(0, f, 8); - - __write_long(bb.ncounts, f, 4); - __write_long(0, f, 8); - __write_long(0, f, 8); - - qr = malloc(bb.ncounts * 8); - kvm_read(kv, bb.counts, qr, bb.ncounts * 8); - q = qr; - for (l4 = bb.funcs; ; l4 += sizeof (bbf)) { - kvm_read(kv, l4, &bbf, sizeof(bbf)); - if (bbf.arc_count == -1) - break; - kvm_read(kv, bbf.name, buf, sizeof(buf)); - - __write_gcov_string(buf, strlen(buf), f, -1); - - __write_long(bbf.checksum, f, 4); - __write_long(bbf.arc_count, f, 4); - for (i = 0; i < bbf.arc_count; i++) { - __write_gcov_type(*q, f, 8); - q++; - } - } - fclose(f); - free(qr); - } - return 0; -} diff --git a/usr.sbin/usbdump/usbdump.c b/usr.sbin/usbdump/usbdump.c index 6545f1c..93e9f21 100644 --- a/usr.sbin/usbdump/usbdump.c +++ b/usr.sbin/usbdump/usbdump.c @@ -32,8 +32,11 @@ #include <sys/param.h> #include <sys/endian.h> #include <sys/ioctl.h> +#include <sys/socket.h> #include <sys/stat.h> #include <sys/utsname.h> +#include <net/if.h> +#include <net/bpf.h> #include <dev/usb/usb.h> #include <dev/usb/usb_pf.h> #include <dev/usb/usbdi.h> @@ -216,7 +219,7 @@ hexdump(const char *region, size_t len) } static void -print_apacket(const struct usbpf_xhdr *hdr, struct usbpf_pkthdr *up, +print_apacket(const struct bpf_xhdr *hdr, struct usbpf_pkthdr *up, const char *payload) { struct tm *tm; @@ -235,8 +238,8 @@ print_apacket(const struct usbpf_xhdr *hdr, struct usbpf_pkthdr *up, up->up_error = le32toh(up->up_error); up->up_interval = le32toh(up->up_interval); - tv.tv_sec = hdr->uh_tstamp.ut_sec; - tv.tv_usec = hdr->uh_tstamp.ut_frac; + tv.tv_sec = hdr->bh_tstamp.bt_sec; + tv.tv_usec = hdr->bh_tstamp.bt_frac; tm = localtime(&tv.tv_sec); len = strftime(buf, sizeof(buf), "%H:%M:%S", tm); @@ -267,20 +270,19 @@ print_apacket(const struct usbpf_xhdr *hdr, struct usbpf_pkthdr *up, print_status(up->up_status); } } - static void print_packets(char *data, const int datalen) { struct usbpf_pkthdr *up; - const struct usbpf_xhdr *hdr; + const struct bpf_xhdr *hdr; u_int32_t framelen, x; char *ptr, *next; for (ptr = data; ptr < (data + datalen); ptr = next) { - hdr = (const struct usbpf_xhdr *)ptr; - up = (struct usbpf_pkthdr *)(ptr + hdr->uh_hdrlen); - next = ptr + USBPF_WORDALIGN(hdr->uh_hdrlen + hdr->uh_caplen); + hdr = (const struct bpf_xhdr *)ptr; + up = (struct usbpf_pkthdr *)(ptr + hdr->bh_hdrlen); + next = ptr + BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen); ptr = ((char *)up) + sizeof(struct usbpf_pkthdr); if (w_arg == NULL) @@ -404,12 +406,12 @@ int main(int argc, char *argv[]) { struct timeval tv; - struct usbpf_insn total_insn; - struct usbpf_program total_prog; - struct usbpf_stat us; - struct usbpf_version uv; + struct bpf_insn total_insn; + struct bpf_program total_prog; + struct bpf_stat us; + struct bpf_version bv; struct usbcap uc, *p = &uc; - struct usbpf_ifreq ufr; + struct ifreq ifr; long snapshot = 192; u_int v; int fd, o; @@ -454,37 +456,37 @@ main(int argc, char *argv[]) exit(EXIT_SUCCESS); } - p->fd = fd = open("/dev/usbpf", O_RDONLY); + p->fd = fd = open("/dev/bpf", O_RDONLY); if (p->fd < 0) { fprintf(stderr, "(no devices found)\n"); return (EXIT_FAILURE); } - if (ioctl(fd, UIOCVERSION, (caddr_t)&uv) < 0) { - fprintf(stderr, "UIOCVERSION: %s\n", strerror(errno)); + if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { + fprintf(stderr, "BIOCVERSION: %s\n", strerror(errno)); return (EXIT_FAILURE); } - if (uv.uv_major != USBPF_MAJOR_VERSION || - uv.uv_minor < USBPF_MINOR_VERSION) { + if (bv.bv_major != BPF_MAJOR_VERSION || + bv.bv_minor < BPF_MINOR_VERSION) { fprintf(stderr, "kernel bpf filter out of date"); return (EXIT_FAILURE); } - if ((ioctl(fd, UIOCGBLEN, (caddr_t)&v) < 0) || v < 65536) - v = 65536; + if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || v < 4096) + v = 4096; for ( ; v != 0; v >>= 1) { - (void)ioctl(fd, UIOCSBLEN, (caddr_t)&v); - (void)strncpy(ufr.ufr_name, i_arg, sizeof(ufr.ufr_name)); - if (ioctl(fd, UIOCSETIF, (caddr_t)&ufr) >= 0) + (void)ioctl(fd, BIOCSBLEN, (caddr_t)&v); + (void)strncpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name)); + if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0) break; } if (v == 0) { - fprintf(stderr, "UIOCSBLEN: %s: No buffer size worked", i_arg); + fprintf(stderr, "BIOCSBLEN: %s: No buffer size worked", i_arg); return (EXIT_FAILURE); } - if (ioctl(fd, UIOCGBLEN, (caddr_t)&v) < 0) { - fprintf(stderr, "UIOCGBLEN: %s", strerror(errno)); + if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { + fprintf(stderr, "BIOCGBLEN: %s", strerror(errno)); return (EXIT_FAILURE); } @@ -496,23 +498,23 @@ main(int argc, char *argv[]) } /* XXX no read filter rules yet so at this moment accept everything */ - total_insn.code = (u_short)(USBPF_RET | USBPF_K); + total_insn.code = (u_short)(BPF_RET | BPF_K); total_insn.jt = 0; total_insn.jf = 0; total_insn.k = snapshot; - total_prog.uf_len = 1; - total_prog.uf_insns = &total_insn; - if (ioctl(p->fd, UIOCSETF, (caddr_t)&total_prog) < 0) { - fprintf(stderr, "UIOCSETF: %s", strerror(errno)); + total_prog.bf_len = 1; + total_prog.bf_insns = &total_insn; + if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) { + fprintf(stderr, "BIOCSETF: %s", strerror(errno)); return (EXIT_FAILURE); } /* 1 second read timeout */ tv.tv_sec = 1; tv.tv_usec = 0; - if (ioctl(p->fd, UIOCSRTIMEOUT, (caddr_t)&tv) < 0) { - fprintf(stderr, "UIOCSRTIMEOUT: %s", strerror(errno)); + if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&tv) < 0) { + fprintf(stderr, "BIOCSRTIMEOUT: %s", strerror(errno)); return (EXIT_FAILURE); } @@ -520,16 +522,16 @@ main(int argc, char *argv[]) do_loop(p); - if (ioctl(fd, UIOCGSTATS, (caddr_t)&us) < 0) { - fprintf(stderr, "UIOCGSTATS: %s", strerror(errno)); + if (ioctl(fd, BIOCGSTATS, (caddr_t)&us) < 0) { + fprintf(stderr, "BIOCGSTATS: %s", strerror(errno)); return (EXIT_FAILURE); } /* XXX what's difference between pkt_captured and us.us_recv? */ printf("\n"); printf("%d packets captured\n", pkt_captured); - printf("%d packets received by filter\n", us.us_recv); - printf("%d packets dropped by kernel\n", us.us_drop); + printf("%d packets received by filter\n", us.bs_recv); + printf("%d packets dropped by kernel\n", us.bs_drop); if (p->fd > 0) close(p->fd); |